【问题标题】:Is the `:as` binding useful only when the argument to a function is a temporary?`:as` 绑定是否仅在函数的参数是临时参数时才有用?
【发布时间】:2021-12-12 04:56:25
【问题描述】:

Clojure Programming中显示的:as的第一个用法如下

(let [[x _ z :as original-vector] v]
  (conj original-vector (+ x z)))
;= [42 foo 99.2 [5 12] 141.2]

但是,通过对https://rextester.com/l/clojure_online_compiler 进行一些实验,我发现vlet 的主体中可见,因此我可以跳过:as 解构并使用v 而不是original-vector ,结果是一样的

(let [[x _ z] v]
  (conj v (+ x z)))
;= [42 foo 99.2 [5 12] 141.2]

如果我有一个更复杂的表达式而不是 v,这显然是不可行的(在 C++ 中,我会说 temporary/rvalue,而 v将是一个左值)。

所以我的问题是::as 语法是否仅在我们解构临时对象时有用,而在我们解构命名实体时它完全是多余的?我的意思是在上面的示例中,使用:as 的唯一区别似乎是我们通过另一个名称引用v,但我看不出这有什么好处...


示例假设

(def v [42 "foo" 99.2 [5 12]])

【问题讨论】:

    标签: data-binding functional-programming clojure pattern-matching destructuring


    【解决方案1】:

    :as 解构技术可能是多余的,这是正确的。但是,解构形式的:as 几乎总是与函数的参数向量一起使用,而不是与let 形式一起使用:

    (ns tst.demo.core
      (:use tupelo.core tupelo.test))
    
    (defn myfun
      [[x _ z :as original-vector]]
      (conj original-vector (+ x z)))
    
    (dotest
      (is= [1 2 3 4]
        (myfun [1 2 3])))
    
    

    然而,值得注意的是,解构的全部力量 可用于函数参数和let 表单。


    该示例是使用my favorite template project 构建的。

    【讨论】:

    • 我会说它也经常以let 形式使用。它唯一(当然!)很少使用的地方是解构一个命名值,因为你为什么要给一个值一个名称,然后再解构它,而不是同时做这两个。例如,(let [[x y :as coords] (foo)] ...) 而不是 (let [coords (foo) [x y] coords])
    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 2012-09-15
    • 2018-10-17
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    相关资源
    最近更新 更多