(def! x1 S)
example:
(def! mynum 111)
=> 111
;; 此时绑定值到了mynum 这个符号上
(let* (p (+ 2 3)
q (+ 2 p)) (+ p q))
=> 12
使用 let* 临时赋值
((lambda [x] (+ 1 x)) 1)
=> 2
定义一个闭包过程。可以和 def!组合起来定义一个函数。
注意参数的语法 如果在参数前使用&符号可以表示多个参数都到一个 list 中。而且只能使用在最后一个参数的前面。
(do (+ 1 2) (+ 3 4) 5)
=> 5
计算列表中的每个元素的值,然后返回最后一个元素的值。
(list 1 2 3)
=> (1 2 3)
生成一个 Lisp 的列表。
(read-string "Nil")
=> Nil
(read-string "(+ 1 1)")
=> (Fn*<xxx00> 1 1)
读一个字符串生成一个 Lisp 对象,注意只生成对象,但是不进行求值。
(eval (read-string "(+ 1 3)"))
=> 4
(eval (list + 1 3))
=> 4
对 Lisp 对象进行求值。使用这个方法后,Lisp 中没有了数据和代码的界限。捅破了数据和代码的那层窗户纸。
打印一个符号如果不存在就报错
(prn abc)
=> not found 'abc'
表示后面的值是这个符号本身 可以和 prn 进行配合使用
(prn (quote abc))
=> abc
=> Nil
解释:打印 abc 是 prn 函数的副作用。prn 函数真正的返回是 Nil。
' 是 quote 的语法糖。 'abc 和 (quote abc)是完全等效的。实际上它在解释器内部也会翻译成 quote 的形式。
quasiquote 建立一个可以临时求值的的符号。如果单独使用和 quote 没有什么区别。
要和 unquote 与 splice-unquote 联合使用。其中有轻微的差别。unquote 表示对下一个符号进行临时取值。
splice-unquote 临时取值后把列表展开。
具体例子如下:
(def! lst '(2 3))
=> (2 3)
(quasiquote (1 (unquote lst)))
=> (1 (2 3))
(quasiquote (1 (splice-unquote lst)))
=> (1 2 3)
quasiquote 、 unquote 和 splice-unquote 的语法糖。
(def! lst '(2 3))
=> (2 3)
`(1 ~lst)
=> (1 (2 3))
`(1 ~@lst)
=> (1 2 3)
这个函数将它的第一个参数连接到它的第二个参数 (一个列表) 前面,返回一个新列表。
(cons [1] [2 3])
=> ([1] 2 3)
(cons 1 [2 3])
=> (1 2 3)
这个函数接受零个或多个列表作为参数,并且返回由这些列表的所有参数组成的一个新列表。
(concat [1 2] (list 3 4) [5 6])
=> (1 2 3 4 5 6)
(concat [1 2])
=> (1 2)
宏定义和宏展开
宏定义 定义一个符号。它的返回值会被继续当做 ast 进行求值。所有这里可以广泛的运用到之前的' ` ~ ~@ d 等语法糖。
宏展开。展开一个宏,只计算出它要求值的 ast 而不进行求值。
(defmacro! unless (lambda (pred a b) `(if ~pred ~b ~a)))
=> ...(此处省略)
(unless false 7 8)
=> 7
(macroexpand (unless false 7 8))
=> (if fasle 7 8)
这个函数接受一个列表(或向量)以及一个数字(序号)作为参数,返回列表中给定序号位置的元素。如果序号超出了返回,函数抛出一个异常。
(nth [1 2 3] 0)
=> 1
(nth '(1 2 3) 1)
=> 2
这个函数接受一个列表(或向量)作为参数,返回它的第一个元素,如果列表(或向量)是空的,或者参数本身是 nil,则返回 nil。
(first '((1 2) 2 3))
=> (1 2)
接受一个列表或者向量返回列表或者向量的长度
(count '(1 2 (2 3)))
=> 3
(count [1 2 3])
=> 3
接受一个列表或者向量判断这个对象是否事空。如果我空的情况下返回 true 否则返回 false
(empty? '())
=> true
(empty? nil)
=> true
try-catch 代码块和其他 语言的 try-catch 并没有什么特别的不同。try 后面跟着一个语句。如果有多条语句可以使用 do 语句进行配合,而 catch 语句中,会有一个异常,并且可以控制代码段的返回。如果使用了 throw 可以主动的抛出一个异常。
(throw "err1")
=> err1
(try* abc (catch* exc (prn "exc is:" exc)))
=> "exc is:" "not found 'abc'"
(try* (throw "my exception") (catch* exc (do (prn "exc:" exc) 7)))
=> "exc:" "my exception"
=> 7
它有两个参数,第一个参数是一个函数。而第二个参数是这个函数需要的入参的列表。这个函数会返回这个求值的结果。
(apply + (list 1 3))
=> 4
(apply + '(2 3))
=> 5
(apply (lambda [x y] (do (prn x "+" y) (+ x y))) '(7 8))
=> 7 "+" 8
=> 15
它有两个参数,第一个参数是一个函数,第二个参数是一个向量或者列表。之后它会对第二个参数中的每个值进行求值,然后结果返回一个新的列表。
注意 map 每个函数只接受一个参数。但是可以配合 apply 达到传多个值的效果。
(map (lambda [x] (apply + x)) (list [1 2] [2 3]))
=> (3 5)
(def! *test-atom* (atom 0))
=> (atom 0)
(reset! *test-atom* 10)
=> 10
(deref *test-atom*) | @*test-atom*
=> 10
(swap! *test-atom* (lambda [x] (+ x 1)))
=> 11
@ 是 deref 的语法糖
在此方言中 hashmap 是一种基本的类型。使用{}大括号表示字面量。其中 key 可以使用两种方式。字符串和关键字。关键字是使用:开头的字符串。
{"a" 1 "b" 2}
{:a 1 :b 2}
上面两种形式都可以表示一个 map.
注意上面的方法都没有产生副作用,也就是没有改变原理的值。如果你要这么做的话建议你使用 atom 或者重新 def!
(gensym)
=> 每次运行不一样!
有偶数个参数一个是条件一个是返回的值
(def! ten-test (lambda [data]
(cond
(> data 10) 1
(= data 10) 0
(< data 10) -1)))
(ten-test 15)
=> 1
列出当前目录下的文件和文件夹
(ls)
=> (. .. mal)
(ls "mal")
=> (. .. hello.mal)
读取文件内容到字符串
(read-file "mal/hello.mal")
=> "(+ 1 1)"
读取 mal 格式的文件,并且加载里面的语句。返回 nil
a.mal
(def! test (lambda [x] (prn x)))
(load-file "a.mal")
=> nil
(test "x")
=> "x"
=> nil
TODO 其他基本函数
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。