Перебираете let-лист в Clojure?

если бы у меня было неизвестное количество аргументов, которые я хочу связать друг с другом с помощью «let», например:

let [a "hello" b 55 ]

Если я привяжу let внутри функции / макроса или чего-то подобного, и я хочу прокрутить список, как мне это сделать?

Обратите внимание, что в let есть 4 элемента, но я хочу пройтись только по «клавишам». Примером использования может быть проверка того, является ли значение, привязанное к ключу, числом вроде b, равным 55.

Изменить: в качестве примера: обратите внимание, что это следующее очень не работает, но оно просто предназначено для объяснения проблемы:

(defn func [& arguments] 
 (let [ ~arguments] ((println "omg no way!") (for [x let-list] (number? x (println "roar") )))

ввод: (func [a "привет" b 55]

Итак, в основном: я хочу иметь функцию, которая:

  • связывает аргументы с некоторой формой списка, например: [a b]
  • выводит "omg no way!") - не должен быть частью цикла, должен печататься только один раз в функции
  • какой-то цикл вроде цикла for, который проходит через «let-list», так что он будет следующим: «a, это число? нет, это число b? да, выведите« roar »

Вывод: omg no way roar

Еще раз: Мне интересно, есть ли способ получить доступ к ключевым словам внутри let внутри функции. Как показывает цикл for, я хочу получить доступ к каждому отдельному элементу и что-то делать с ним. Если бы я использовал (вместо [x arguments], он бы дал: omg no way, roar roar (потому что b привязано к 55, поэтому это число, но 55 также является числом, но нет необходимости использовать 55, потому что 55 уже привязано к b)


person Deragon    schedule 13.01.2013    source источник
comment
Похоже, вам нужны loop и recur: clojure.org/special_forms#Special Forms - ( цикл [привязки *] выражения *)   -  person Diego Basch    schedule 14.01.2013
comment
пример ввода и вывода здесь очень поможет   -  person Arthur Ulfeldt    schedule 14.01.2013
comment
Это похоже на то, что лучше было бы достичь с помощью карты. Но я согласен с @ArthurUlfeldt, что пример с контекстом действительно поможет нам помочь вам.   -  person Dan Midwood    schedule 14.01.2013
comment
Похоже, что вам нужно (map second (partition 2 arguments)).   -  person Leonid Beschastny    schedule 14.01.2013


Ответы (1)


вот пример макроса, который принимает список чередующихся имен и значений, связывает их в let, а затем сохраняет карту только что созданных привязок, вводя символ под названием 'locals', который называет карту локальных имен в локальные значения.

(defmacro anaphoric-let [alternating-symbols-and-values & body]
  `(let [~@alternating-symbols-and-values
         names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
         values#  ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
         ~'locals (zipmap names# values#)]
     ~@body))

любые выражения, вызываемые с anaphoric-let, смогут использовать значения из имени locals.

user> (anaphoric-let [a 1 b 2 c 3 d 4] [a locals])
[1 {d 4, c 3, b 2, a 1}]

сохранение значений в карте после определения их с помощью let и до тела важно для предотвращения многократного выполнения и других грехов антисанитарных макросов.

затем эту карту можно использовать для принятия решений на основе местных жителей:

user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"] 
        (map (fn [[local val]] 
               (str local " is " (if (number? val) val "woof"))) 
              locals))
("e is woof" "d is 4" "c is 3" "b is 2" "a is 1")

or:

user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"] 
        (println "omg no way!") 
        (dorun (for [x (vals locals)] 
                 (if (number? x) (println "roar")))))
omg no way!                                                                                                                                                    
roar                                                                                                                                                           
roar                                                                                                                                                           
roar                                                                                                                                                           
roar                                                                                                                                                           
nil

ps: анафоический макрос - это любой макрос, который вводит имя в создаваемый им код, которого не было в переданном ему коде.

person Arthur Ulfeldt    schedule 13.01.2013