Почему пусть требуется вектор? - PullRequest
14 голосов
/ 05 октября 2010

Я никогда не думал об этом, пока не объяснил какой-то код clojure коллеге, который не был знаком с clojure.Я объяснил ему let, когда он спросил, почему вы используете вектор для объявления привязок, а не списка.У меня действительно не было ответа для него.Но язык ограничивает вас от использования списков:

=> (let (x 1) x)
java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:0)

Почему именно это?

Ответы [ 5 ]

25 голосов
/ 05 октября 2010

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

Просто для удовольствия:

user=> (defmacro list-let [bindings & body] `(let ~(vec bindings) ~@body))
#'user/list-let
user=> (macroexpand-1 '(list-let (x 0) (println x)))
(clojure.core/let [x 0] (println x))
user=> (list-let (x 0 y 1) (println x y))
0 1
nil
13 голосов
/ 05 октября 2010

Это идиома из Схемы. Во многих реализациях Схемы квадратные скобки могут использоваться взаимозаменяемо с круглыми скобками в литералах списка. В этих реализациях Схемы квадратные скобки часто используются для различения списков параметров, списков аргументов и привязок от S-выражений или списков данных.

В Clojure скобки и скобки означают разные вещи, но они используются одинаково в связывающих объявлениях.

11 голосов
/ 05 октября 2010

Clojure очень старается быть последовательным. Не существует технической причины, по которой форма списка не могла бы использоваться в let, fn, with-open и т. Д. Фактически, вы можете достаточно легко создать свой собственный my-let, который использует его вместо этого. Тем не менее, помимо заметного выделения, вектор используется последовательно в разных формах для обозначения «вот некоторые привязки». Вы должны стремиться отстаивать этот идеал в своем собственном коде.

1 голос
/ 31 мая 2011

Еще один способ думать об этом состоит в том, что let просто происходит от лямбды. Эти два выражения эквивалентны:

((fn [y] (+ y 42)) 10)
(let [y 10] (+ 42 y))

Таким образом, в качестве академического или учебного пособия, вы могли бы даже написать свою собственную очень элементарную версию let, которая содержала список и вектор:

(defmacro my-let [x body]
  (list (list `fn[(first x)]
              `~body)
        (last x)))

(my-let (z 42) (* z z))

хотя для этого не было бы практической причины.

1 голос
/ 05 октября 2010

я предполагаю, что это соглашение

fn использовало это, defn использовало это, loop использует.

кажется, что это для всего, что напоминает блок кода, который имеет некоторые параметры;более конкретно, квадратные скобки предназначены для обозначения этих параметров

, другие формы для блоков кода не используют его, например if или do.у них нет параметров

...