2016-09-16 1 views
2

Я озадачен разница в поведении в следующих выражениях:Clojure метаданные потеряли на определенных формах

(pr (meta ^{:a 0} (list 1 2))) ;; prints nil returns nil 

(pr (meta ^{:a 0} '(1 2)));; prints {:line 110, :column 20} returns nil 

(pr (meta ^{:a 0} (range 1 3))) ;; prints nil returns nil 

(pr (meta ^{:a 0} [1 2])) ;; prints {:a 0} returns nil 

Это использование Clojure 1.8.0. Я хотел бы получить объяснение, почему результаты отличаются.

ответ

5

Метаданные для чтения прикреплены к форме, которую читатель возвращает. meta, в каждом случае, вызывается с тем, что эта форма оценивается во время выполнения. Между одним и другим нет никакой необходимой связи.

Если вам нужно прикрепить метаданные к значению во время выполнения, вы можете использовать with-meta для этого.

Давайте посмотрим на то, что происходит в каждом из случаев, перечисленных в вопросе:

  1. (pr (meta ^{:a 0} (list 1 2)))

    метаданных чтения прилагается к структуре списка (list 1 2), но meta применяется не к этому но к значению, которое оно оценивает во время выполнения, которое будет только что выделенным списком из двух элементов без прикрепленных метаданных.

  2. (pr (meta ^{:a 0} '(1 2)))

    метаданных чтения прилагается к структуре списка (quote (1 2)) (одиночная кавычка символ читателя стенография для (quote …)), но meta применяется не к этому списку структуры, а значения, которое он оценивает, чтобы во время выполнения , которая представляет собой структуру списка (1 2), которую читатель создал при чтении в этом выражении. Это переносит метаданные {:line … :column …}, поскольку считыватель Clojure присоединяет это к определенным типам форм для использования в сообщениях об ошибках и тому подобное.

  3. (pr (meta ^{:a 0} (range 1 3)))

    То же, что в первом случае выше.

  4. (pr (meta ^{:a 0} [1 2]))

    Это очень похоже на '(1 2) случае с кардинальным отличием, что в то время как не пустые списки должны быть указаны, если они не должны рассматриваться как функции/макровызовов, векторы нет, и поэтому метаданные читателя фактически привязаны к интересующему буквалю - самому вектору.

    Это выполнимо со списком, а также:

    (pr (meta ' ^{:a 0} (1 2))) 
         ^note the quote comes before the metadata 
    ;; prints {:line 1, :column 14, :a 0} 
    

    NB. явная карта метаданных читателя была объединена с картой {:line … :column …}, которую читатель добавляет сам по себе.