defn vs. let в отношении разложения - PullRequest
5 голосов
/ 17 октября 2011

Я определяю функцию, которая принимает два параметра - карту и ключ. На ключ ссылаются из разложения параметра карты

(defn myfunc [{v k} k]
   v)

когда я звоню:

  (myfunc {:a 10} :a)

Это неожиданно дает ожидаемый результат: 10

Подобная вещь в лете:

(let [{v k} {:a 10} k :a] v)

терпит неудачу, потому что k не определен в тот момент, когда оценивается первая часть.

Мой вопрос: почему декомпозиция внутри параметров функции ведет себя иначе, чем декомпозиция в let выражениях?

Ответы [ 2 ]

3 голосов
/ 17 октября 2011

Макрорасширение формы defn Я получаю эквивалент этого (удалил .withMeta материал и переформатировал):

(def myfunc
  (fn* myfunc
       ([p__11393 k]
          (let* [map__11394 p__11393
                 map__11394 (if (seq? map__11394)
                              (apply hash-map map__11394)
                              map__11394)
                 v          (get map__11394 k)]
                v))))

Итак, здесь мы можем видеть, что карта {v k} фактически сначала присваивается локальной переменной p__11393. Затем оператор if проверяет, является ли эта переменная на самом деле последовательностью, и превращает ее в хэш-карту, если это так, в противном случае оставляет ее как есть. Важно отметить, что значение, присвоенное k, ищется на карте после того, как все это происходит, таким образом, это работает без ошибок (а также, если бы :a не было на карте, get возвращает nil в этом случае).

С другой стороны, макрос, расширяющий форму let, которую я получаю

(let*
    [map__11431
  {:a 10}
  map__11431
  (if (seq? map__11431) (apply hash-map map__11431) map__11431)
  v
  (get map__11431 k)
  k
  :a]
  v)

и здесь мы можем видеть, что v получает результат (get map__11431 k), но k пока не определено, следовательно, ошибка.

0 голосов
/ 17 октября 2011

Это не полный ответ, но работает следующее:

user=> (defn myfunc [{v k} k] v)
#'user/myfunc
user=> (myfunc {:a 10} :a)
10
user=> (let [k :a {v k} {:a 10}] v)
10
user=>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...