Кто-нибудь может объяснить этот код? - PullRequest
2 голосов
/ 03 сентября 2010
1: user=> (def some-account {:number :any­-number :balance :any­-balance :bank :any­-bank})
2: #'user/some-account
3: user=> (contains? some-account :bank)
4: true
5: user=> (assoc some-account :owner :any-owner)
6: {:owner :any-owner, :number :any­-number, :balance :any­-balance, :bank :any­-bank}
7: user=> (contains? some-account :owner)
8: false
9: user=> (def some-account (assoc some-account :owner :any-owner))
10: #'user/some-account
11: user=> (contains? some-account :owner)
12: true
13: user=> (dissoc some-account :owner)
14: {:number :any-­number, :balance :any­-balance, :bank :any-­bank}
15: user=> (contains? some-account :owner)
16: true

Может кто-нибудь объяснить этот код?

Почему после (assoc some-account :owner :any-owner) возвращается (contains? some-account :owner) false?

Почему только после (def some-account (assoc some-account :owner :any-owner)) (contains? some-account :owner) return true?

Почему после (dissoc some-account :owner) (contains? some-account :owner) возвращает true?

Я пытался сказать (def some-account (assoc some-account :owner :any-owner)) из инстинкта.Но почему это так работает?

Ответы [ 5 ]

6 голосов
/ 03 сентября 2010

Карты в Clojure неизменны.

То есть функции обновления вместо изменения исходной карты возвращают новую обновленную карту.

Попробуйте следующее:

user=> (def some-account {:number :any­-number :balance :any­-balance :bank :any-bank})
#'user/some-account
user=> (contains? some-account :bank)
true
user=> (def updated-map (assoc some-account :owner :any-owner))
#'user/updated-map
user=> (contains? updated-map :owner)
true
user=>
3 голосов
/ 04 сентября 2010

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

Это структурное совместное использование очень важно для всех функциональных языков с [неизменяемыми структурами данных] [1]

[1]: http://clojure.org/functional_programming#Functional Программирование - неизменяемые структуры данных

2 голосов
/ 03 сентября 2010

В Clojure все типы данных являются неизменяемыми. Следовательно, операция assoc на карте some-account не меняет ее на месте (в отличие от операции put на java.util.Map в Java) и создает новую карту. Вот почему операция countain? возвращает false. Когда вы делаете

(def some-account (assoc some-account :owner :any-owner))

вы перехватываете возвращаемое значение операции assoc и присваиваете его переменной some-account. В некотором смысле вы переопределяете это. Так что позже операция contain? возвращает true.

1 голос
/ 06 сентября 2010

Представьте, что вы использовали номер вместо карты:

user> (def s 3)
#'user/s
user> (= s 3)
true
user> (+ 1 s)
4
user> (= s 4)
false
user> (def s (+ 1 s)) ;;don't do this! changing definitions shouldn't be used in a program, only at the REPL for trying things out!
#'user/s
user> (= s 4)
true
user> (- s 1)
3
user> (= s 4)

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

Но как мы можем программировать без изменения переменных? Возможно, вы видели функцию факториала

(defn factorial [n]
        (if (< n 2) 1
            (* n (factorial (dec n)))))

user> (factorial 5)
120

Вот аналогичная функция, которая создает карту таким же образом

(defn char-map [n]
        (if (< n 0) {}
            (assoc (char-map (dec n)) n (char n))))

user> (char-map 10)
{various control characters..}

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

Это два разных взгляда на одно и то же.

Обычно легко переводить между ними, так что, если вы можете придумать один способ сделать это, вы уже подумали о другом. Но для этого нужно практиковаться, например, научиться говорить по-латыни.

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

1 голос
/ 03 сентября 2010

потому что Assoc и Disoc возвращают новые объекты и не меняют аккаунт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...