позвольте внутри конусовидный

Я работаю с clojure и в то время как я плескался с, шепелявит прежде, я испытываю затруднения при нахождении, что очевидный способ для вложения позволил операторам в конусовидных операторах. Например, рассмотрите следующую функцию:

(defn operate-on-list [xs]
  (let [[unpack vector] (first xs)]
    (cond
      [(empty? xs) 'empty
       unpack vector
       :else (operate-on-list (rest xs))])))

Это - довольно стандартная рекурсивная операция в списке, но это должно сделать некоторую работу над первым элементом в списке, прежде чем это будет работать с содержанием. Проблема, конечно, то, что список может быть пустым.

В этом примере не было бы трудно измениться unpack кому: ((first xs) 0) и vector кому: ((first xs) 1), но это быстро становится ужасным, если больше работы должно быть сделано на (первый xs).

Там какой-либо путь состоит в том, чтобы эффективно использовать оператор, которому позволяют, отчасти через конусовидное?

Спасибо.

- Nate

5
задан So8res 14 January 2010 в 21:52
поделиться

2 ответа

В подобных случаях лучше всего использовать if-let :

(defn operate-on-list [xs]
  (if-let [[unpack v] (first xs)]
    (cond
      unpack v
      :else  (operate-on-list (rest xs)))))

Этот код проходит по заданному list seq -able (список, вектор, массив ...) векторов и возвращает второй элемент первого вектора, первый элемент которого истинен (то есть не false или nil ). nil возвращается, если такой вектор не найден.

Обратите внимание, что вектор является встроенной функцией, поэтому я выбрал v в качестве имени переменной на тот случай, если необходимость использования функции в теле возникает в будущее. Что еще более важно, вы используете слишком много скобок в синтаксисе cond; исправлено в этой версии.

ОБНОВЛЕНИЕ : о if-let следует отметить еще две вещи:

  1. Как работает if-let , if (первые xs) оказывается nil ( false будет таким же), деструктурирующее связывание никогда не происходит, поэтому Clojure не будет жаловаться на невозможность привязать nil в [распаковать v] .

  2. Кроме того, if-let принимает предложение else (в котором вы не можете ссылаться на переменные, связанные в векторе привязок if-let , хотя, если вы находитесь в предложение else, вы знаете, где false или nil в любом случае).

11
ответ дан 18 December 2019 в 10:44
поделиться

Вроде этого, с дайте внутри объема COND ?

(defn operate-on-list [list]
  (let [ el_first (first list) ]
    (cond
      (nil? el_first) (println "Finished")
      :else (do 
       (let [ list_rest (rest list) ]
                (println el_first)  
                (operate-on-list list_rest))))))

(operate-on-list '(1 2 3))

Выход:

1
2
3
Finished
2
ответ дан 18 December 2019 в 10:44
поделиться