clojure实战——符号&@#'+-*/

clojure实战——符号&@#’+-*/

本博客继续对clojure语言中一些符号进行讲解:&,@,-‘,#’。

保持“剩下的元素”——&、%&

&:保持”剩下的元素”

在解构中,可以用&符号保持解构剩下来的元素,有点像java中的可变参数

示例:

(comment
  (defn &test
    [a & rest]
    rest)

  (&test 1 2 3 4)
  ;; => '(2 3 4)
  ;; 剩下的元素被放入到rest中,rest是一个列表,而不是vector。

  (let [[a & b] [1 2 3]]
    b)
  ;; => (2 3)

  (defn &test2
    [a & [rest]]
    rest)
  (&test2 1 2 3 4)
  ;; => 2
  ;; 有趣的现象:剩下的元素为'(2 3 4),它被'[rest]解构,并将r绑定到第一个元素2
  ;; 类似于:(let [[r] '(2 3 4)] r) => 2

  (defn &test3
    [a & [r h a]]
    (conj [] r h a))
  (&test3 1 2 3 4)
  ;; => [2 3 4]
  ;; r、h、a 分别为234。
  )

;; 在匿名函数中,可以用 %& 表示剩下的参数
;; %1, %2, ... %n 表示第n个参数
(#(apply + 5 %1 %2 %&) 100 200 300 400) ;; => 305

;; 上面的等价于:
(apply + 5 100 200 '(300 400))

解引用——@

@:解引用

@等同于deref函数
clojure中有很多实体都是可以解引用的,如delay、future、promise以及所有引用类型:atom、ref、agent、var。

示例:

(comment
  (def atom-a (atom 10))
  @atom-a
  ;; => 10

  (def a-var 10)
  @(var a-var)
  ;; => 10
  )

获取符号指向的Var——#’

#’:用于获得一个符号(Sysmbol)所指向的Var。

clojure中,Var有def来创建
等同于var函数,返回值都是Var
clojure中,使用了两层”指针”来绑定”Sysmbol->Var->Function”
也就是说,我们通过一个符号来调用一个函数其实还经历了Var这一层:先找到符号指向的Var,再找到Var指向的函数。
这样做的好处是,我们可以动态地绑定Var指向某个具体的函数(有点多态的感觉)。

示例:

(comment
  #'+
  ;; => #'clojure.core/+
  (var +)
  ;; => #'clojure.core/+
  ;; 表明符号+指向的Var是#'clojure.core/+

  ;;查看#'和var的返回值类型
  (class (var +))
  (class #'+)
  ;; => clojure.lang.Var
  ;; 说明返回值类型是一个Var

  ;; 那#'clojure.core/+指向的函数是什么?可以对Var解引用
  @#'+
  ;; => #object[clojure.core$_PLUS_ 0x77730aa7 "clojure.core$_PLUS_@77730aa7"]
  ;; 说明指向的函数是 #object[clojure.core$_PLUS_ 0x77730aa7 "clojure.core$_PLUS_@77730aa7"]

  ;; Var默认是静态的(static),不可被动态绑定
  (def var-x 1)
  (binding [var-x 1]
    var-x)
  ;; => CompilerException java.lang.IllegalStateException: Can't dynamically bind non-dynamic var: clojure-async.symbols/var-x,

  ;; 在创建一个Var时,可以指定它是可动态绑定的。
  ;; 下面建立了一个可动态绑定的Var,并绑定一个根值为:default-value
  (def ^:dynamic var-y :default-value)
  (binding [var-y 2]
    var-y)
  ;; => 2
  ;; 被动态绑定为2,但是它只作用于binding的作用域内。
  var-y
  ;; => :default-value
  )

减——-‘

-‘:加强版的减。

-‘函数可以接受一个参数,当只有一个参数时,默认被减数为0;当有多个参数时,和普通减号一样。
支持任意精度,不会像普通-那样出现越界异常。

示例:

(comment
  (-' 3)
  ;; => -3 默认被减数为0
  (-' 5 2 1)
  ;; => 2 和普通符号一样

  (- 0 9000000000000000000 1000000000000000000)
  ;; => ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1521)
  (-' 0 9000000000000000000 1000000000000000000)
  ;; => => -10000000000000000000N
  )

加——+’

+’:加强版的+

接受0到N个数值的参数
支持任意精度

示例:

(comment
  (+)
  (+')
  ;; => 0
  (+ 1 Long/MAX_VALUE)
  ;; => ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1521)
  (+' 1 Long/MAX_VALUE)
  ;; => 9223372036854775808N
  )

乘——*’

‘:加强版的

接受0到N个数值的参数
支持任意精度

示例:

(comment
  (*)
  (*')
  ;; => 1
  (* 2 Long/MAX_VALUE)
  ;; => CompilerException java.lang.ArithmeticException: integer overflow, compiling
  (*' 2 Long/MAX_VALUE)
  ;; => 18446744073709551614N
  )
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值