2015-07-22 3 views
0

Разработал функцию в Clojure, чтобы проверить, соответствуют ли входы для: maxlength и: minlength длиной 1-3 символа, а текст в ассоциированном столбце находится в пределах min и max. Есть ли более чистый способ сделать это? Я был бы признателен, если предлагается более эффективный метод, особенно форма if.Выполнение сравнения в Clojure

(defn range-text-length 
"input = {:col val :minlength minlength :maxlength maxlength} 
    Expects 3 parameter key/value combinations: 
    :col The column containing the text value 
    :maxlength integer value greater than zero up to 3 characters long 
Catch any rows where the column contains text that is shorter than the Minimum Length or longer than the Maximum Length" 
[row input] 
(let [{:keys [col minlength maxlength ]} input 
    minlength-count (count (str minlength)) 
    maxlength-count (count (str maxlength)) 
    max (read-string (str maxlength)) 
    min (read-string (str minlength))] 
    (if (and (and (> maxlength-count 0) (<= maxlength-count 3) (number? max) (> max 0)) 
     (and (> minlength-count 0)(<= minlength-count 3)(number? min)(> min 0))) 
    (and (>= (count (get row col)) min) (<= (count (get row col)) max)) 
    (throw (Exception. "length must be a positive integer value with no more than 3 digits."))))) 

И я вызвать функцию таким образом:

(catch-out-of-range-text-length ["weert" "sertt" "qwertyuiopasdfg" "asert"] {:col 2 :minlength 2 :maxlength 15}) 
+0

Вы можете добавить образец данных? Кроме того, в соответствии с исключением, все столбцы являются числовыми? –

+0

Это действительно работает, просто попросив более чистый способ сделать сравнение в форме if @Frank C. – Jyd

+0

Кандидат должен быть перемещен в codereview –

ответ

0

Во-первых: вложенными and избыточна. Поскольку код не может отличить, какая часть условия была ложной, нет эффекта вложенных вызовов на and, а не на то, чтобы положить все предложения в том же and.

Далее <, <=, > и >= все принимают переменное число аргументов, и с немного рефакторинга вы можете объединить вызовы, которые разделяют термин.

Наконец, вместо того, чтобы тестировать, если что-то больше 0, вы можете прямо проверить, положительно ли оно с pos?.

(defn range-text-length 
"input = {:col val :minlength minlength :maxlength maxlength} 
    Expects 3 parameter key/value combinations: 
    :col The column containing the text value 
    :maxlength integer value greater than zero up to 3 characters long 
Catch any rows where the column contains text that is shorter than the Minimum Length or longer than the Maximum Length" 
[row input] 
(let [{:keys [col minlength maxlength ]} input 
     minlength-count (count (str minlength)) 
     maxlength-count (count (str maxlength)) 
     max (read-string (str maxlength)) 
     min (read-string (str minlength))] 
    (if (and (> 4 maxlength-count 0) 
      (number? max) 
      (pos? max) 
      (> 4 minlength-count 0) 
      (number? min) 
      (pos? min)) 
    (>= max (count (get row col)) min) 
    (throw (Exception. "length must be a positive integer value with no more than 3 digits."))))) 
+0

Спасибо @noisesmith ..Я очень новичок в Clojure, не могли бы вы указать мне хорошие ресурсы на Clojure. – Jyd

+0

http://clojure.org действительно имеет действительно хорошую вводную документацию. Также http://conj.io - хорошая рекомендация. –

+0

@noisesmith: Вы доступны для наставничества. Я хочу учиться у вас. Я уверен, что мы сможем что-то выдумать. Пошлите мне свой контактный адрес электронной почты, спасибо – Jyd

-1

if пункта прибран и предпосылки используются, чтобы избежать загрязнять реальную цель функции с предполагаемыми предварительными условиями. Некоторые дополнительные examples

(defn range-text-length 
    "input = {:col val :minlength minlength :maxlength maxlength} 
    Expects 3 parameter key/value combinations: 
    :col The column containing the text value 
    :maxlength integer value greater than zero up to 3 characters long 
    Catch any rows where the column contains text that is shorter than the Minimum Length or longer than the Maximum Length" 
    [row input] 
    {: pre [(let [{:keys [col minlength maxlength ]} input 
        minlength-count (count (str minlength)) 
        maxlength-count (count (str maxlength)) 
        max (read-string (str maxlength)) 
        min (read-string (str minlength)) 
        crc (count (get row col))] 
       (not (and (pos? maxlength-count) 
         (pos? minlength-count) 
         (pos? max) 
         (pos? min) 
         (<= maxlength-count 3) 
         (<= minlength-count 3) 
         (>= crc min) 
         (<= crc max))))]} 
    (do (println "do my stuff with satisfied preconditions"))) 
+0

Мог ли downvoter объяснить, почему вы это сделали? –

+0

Предпосылки не для исключительных условий выполнения, они предназначены для обнаружения ошибок в программной логике. Они могут быть отключены через флаг в jvm, и эта программа была бы неправильной, если бы утверждения были отключены. Кроме того, этот ответ не дублирует логику исходного (рабочего) кода. – noisesmith

+0

Это правда, но спорно. Пользователь, который никогда не слышал о предварительных условиях, редко знает, что он может отключить их флагом JVM. Я ответил за предполагаемую аудиторию, пытающуюся представить новую концепцию не для экспертов. И флаг - это то, что вы должны установить __indeed__, поэтому в 99% случаев это не будет проблемой. –

0

Я вижу, что вы уже отметили @noisesmith как ответ. Несмотря на то, что происходит я играл вокруг и получает следующее:

(defn range-text-length 
    [row {:keys [col minlength maxlength] :as input}] 
    (if-let [x (and (and (pos? minlength) (< minlength 1000)) 
        (and (pos? maxlength) (< maxlength 1000)) 
        (and (>= (count (get row col)) minlength) 
         (<= (count (get row col)) maxlength)))] 
    true 
    (throw (Exception. "length must be a positive integer value with no more than 3 digits.")))) 

Несмотря на VARIADIC способности and я отделенной для удобства чтения.

EDIT: покончил с if-let:

(defn range-text-length 
    [row {:keys [col minlength maxlength] :as input}] 
    (or (and (and (pos? minlength) (< minlength 1000)) 
      (and (pos? maxlength) (< maxlength 1000)) 
      (and (>= (count (get row col)) minlength) 
       (<= (count (get row col)) maxlength))) 
    (throw (Exception. "length must be a positive integer value with no more than 3 digits.")))) 
2

Я думаю, что следующее эквивалентен твое:

(defn range-text-length [row input] 
    (let [in-range? (fn [n] (< 0 n 1000)) 
     {:keys [col minlength maxlength ]} input 
     ] 
    (if (every? in-range? [minlength maxlength]) 
     (<= minlength (count (row col)) maxlength) 
     (throw (Exception. "length must be a positive integer with no more than 3 digits."))))) 
+0

Приятный альтернативный подход! –

Смежные вопросы