Clojure 有人能解释一下这个代码吗?

Clojure 有人能解释一下这个代码吗?,clojure,types,Clojure,Types,有人能解释一下这个代码吗 为什么在(关联某些帐户:所有者:任何所有者)之后(包含?某些帐户:所有者)返回false 为什么,只有在(def some account(assoc some account:owner:any owner))之后(contains?some account:owner)才会返回true 为什么在(dissoc some account:owner)之后(contains?some account:owner)返回true 出于本能,我试着说(def some acc

有人能解释一下这个代码吗

为什么在
(关联某些帐户:所有者:任何所有者)
之后
(包含?某些帐户:所有者)
返回
false

为什么,只有在
(def some account(assoc some account:owner:any owner))
之后
(contains?some account:owner)
才会返回
true

为什么在
(dissoc some account:owner)
之后
(contains?some account:owner)
返回
true


出于本能,我试着说
(def some account(assoc some account:owner:any owner))
。但是为什么它是这样工作的呢?

Clojure中的映射是不可变的

也就是说,更新函数不是修改原始映射,而是返回一个新的更新映射

请尝试以下操作:

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

在Clojure中,所有数据类型都是不可变的。因此,对
some account
映射执行的
assoc
操作不会将其更改到位(与java中对
java.util.map
执行的
put
操作不同),并生成一个新映射。这就是
countain?
操作返回false的原因。当你这样做的时候

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=>

您正在捕获
assoc
操作的返回值,并将其分配给
some account
变量。从某种意义上说,你正在重新定义它。因此,稍后
contain?
操作返回true。

因为assoc和dissoc返回新对象,并且不更改某些帐户

请注意,当更新函数生成新映射时,他们不复制旧零件,而是生成一个新零件,该零件与旧零件共享所有未更改的零件,并且只替换更改所需的零件

这种结构共享对于所有具有[不可变数据结构][1]的函数式语言都非常重要


[1] :编程--不可变的数据结构

假设您使用的是数字而不是地图:

(def some-account (assoc some-account :owner :any-owner))
在Clojure中,大多数值的行为类似于数字。有些东西是可变的,但它们隐藏在神秘的接口后面。没有它们,很多编程都可以完成

但是我们如何在不改变变量的情况下编程呢?您可能已经看到了阶乘函数

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)
(defn阶乘[n]
(如果((阶乘5)
120
下面是一个类似的函数,它以相同的方式构建地图

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

user> (factorial 5)
120
(defn字符映射[n]
(如果((字符映射10)
{各种控制字符..}
这种风格起初很奇怪,但最终变得自然。现在,当我想到一些要编程的东西时,我经常想到在命令式循环之前的递归解决方案

它们是看待同一事物的两种不同方式

在它们之间进行翻译通常很容易,因此,如果你能想到一种方法,那么你已经想到了另一种方法。但这需要练习,就像学习说拉丁语一样


在思路清晰和线程安全性方面有一些优势,可以让事情在创建之后保持不变。数学家们似乎特别喜欢它。

干净编码的精彩介绍:)
(defn char-map [n]
        (if (< n 0) {}
            (assoc (char-map (dec n)) n (char n))))

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