2016-06-17 3 views
1

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

(defn my-func [data] 
    (let [right (:right data) 
     left (:left data)] 
    ... body ...)) 

Однако, мне сказали, очень скоро, что соответствующий шаблон является одним из большие возможности Clojure (или действительно Haskell и Scala), так что я был вынужден написать:

(defn my-func [ {:keys [right left] } ] 
    ... body ...) 

так что мой код теперь валялись с этим типом синтаксиса. Как-то мне это не нравится. Я нахожу, что мой код менее привлекателен, чтобы выглядеть, может быть, даже менее читаемым (но это, вероятно, связано с отсутствием опыта идиоматического Clojure, поэтому со временем это будет лучше).

Так что я хотел спросить, есть ли фундаментальная причина использовать один стиль над другим? Например, компилятор генерирует байт-коды, которые намного эффективнее во втором случае. Или есть другие причины, о которых я должен знать?

ответ

4

Destructuring is not pattern matching! Когда вы пишете это:

(defn my-func [{:keys [right left]}] 
    ,,,) 

Это то же самое, что и:

(defn my-func [data] 
    (let [{:keys [right left]} data] 
    ,,,)) 

Что такое же, как это:

(defn my-func [data] 
    (let [right (:right data) 
     left (:left data)] 
    ,,,)) 

As Piotrek pointed out, нет преимущества в производительности для использования более краткой форме. Тем не менее, все еще есть преимущество: а именно, краткий обзор.

As Alan pointed out, основное преимущество :keys деструктуризации заключается в том, что вам нужно писать только каждое имя ключа один раз вместо двух.

As you pointed out, делая деструктурирование непосредственно в векторе аргументов функции, может сделать ваш код менее читаемым, поэтому на самом деле он не очень распространен в Clojure.

Самое замечательное в том, что, так как деструктурирующий не complected с параметром именовании в Clojure, вы можете получить лучшее из обоих миров (вторая форма, которую я дал выше):

(defn my-func [data] 
    (let [{:keys [right left]} data] 
    ,,,)) 

Таким образом, вы получаете (особенно если вы назовете свой параметр чем-то лучше, чем data) и сгладить (используя :keys деструктурирование).

+0

Большое спасибо! Спасибо также за ссылку на деструктурирование v шаблона соответствия –

3

:keys деструктурирование - это всего лишь синтаксический сахар и фактически расширена на ряд вызовов до get и присвоений символам. Например:

(macroexpand-1 
    '(let [{:keys [a b]} {:a 1 :b 2}])) 

получает разложена в:

(let* 
[map__2507 
    {:a 1, :b 2} 
    map__2507 
    (if (clojure.core/seq? map__2507) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__2507)) map__2507) 
    a 
    (clojure.core/get map__2507 :a) 
    b 
    (clojure.core/get map__2507 :b)]) 

Основной целью деструктуризации (обратите внимание, что это только уничтожение того - не полный поиск по шаблону) является лаконичным код и нет оптимизации производительности участие.

Чтобы проиллюстрировать, как код без :keys деструктуризации более многословным посмотрите на пример:

(let [{:keys [id name address age salary]} person] 
    ...) 

против

(let [id (:id person) 
     name (:name person) 
     address (:address person) 
     age (:age person) 
     salary (:salary person)] 
    ...) 
+2

Как отметил Пиотрек, большое преимущество состоит в том, что вам не нужно повторять каждое имя дважды (например, символ «справа» и ключевое слово «: справа»), а символ «данные» удаляется из каждой строки, как а также список arg. –

+0

Я добавил пример, чтобы проиллюстрировать вашу мысль. –

+0

Спасибо большое за Piotrek/Alan –

1

Для полноты, это от Clojure Library Coding Standards:

Идиоматического код использует много уничтожения того. Тем не менее, вы должны только разрушить список arg, если хотите связать субструктуру как часть контракта вызывающего абонента. В противном случае деструкция в первой строке пусть. Пример: my snake code из книги не удается выполнить этот тест, делая слишком много деструктурирования в списках arg.

+0

Большое спасибо Валентину! –

Смежные вопросы