Зачем нужен вектор?
Я никогда не думал об этом, пока не объяснил код clojure сотруднику, который не был знаком с clojure. Я объяснял ему let
, когда он спросил, почему вы используете вектор для объявления привязок, а не списка. У меня на самом деле не было ответа на него. Но язык ограничивает использование списков:
=> (let (x 1) x)
java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:0)
Почему именно это?
Ответы
Ответ 1
В основном читаемость, я думаю. Всякий раз, когда привязки необходимы в Clojure, вектор довольно последовательно используется. Многие люди согласны с тем, что векторы для привязок делают вещи более эффективными и позволяют легче различать, что такое привязки и что работает.
Просто для удовольствия:
user=> (defmacro list-let [bindings & body] `(let ~(vec bindings) [email protected]))
#'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
Ответ 2
Это идиома из Схемы. Во многих реализациях Схемы квадратные скобки могут использоваться взаимозаменяемо с круглыми скобками в списковых литералах. В тех реализациях Схемы квадратные скобки часто используются для выделения списков параметров, списков аргументов и привязок из S-выражений или списков данных.
В Clojure круглые скобки и скобки означают разные вещи, но они используются одинаково в объявлениях привязки.
Ответ 3
Clojure очень сложно быть последовательным. Нет никаких технических причин, чтобы форма списка не могла использоваться в let
, fn
, with-open
и т.д. На самом деле вы можете создать свой собственный my-let
достаточно легко, чтобы использовать его вместо него. Однако, не выделяясь видимо, вектор последовательно используется в разных формах, чтобы обозначить "вот некоторые привязки". Вы должны стремиться поддерживать этот идеал в своем собственном коде.
Ответ 4
Я предполагаю, что это соглашение
fn
использовал его, defn
использовал его, loop
использовал.
кажется, что он для всего, что напоминает блок кода, который имеет некоторые параметры; более конкретно, квадратные скобки предназначены для маркировки этих параметров
другие формы для блоков кода не используют его, например if
или do
. у них нет параметров
Ответ 5
Еще один способ подумать о том, что 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))
хотя практических оснований для этого не было.