Macros 关于“匿名”的建议/讨论;“自我参照”;数据结构

Macros 关于“匿名”的建议/讨论;“自我参照”;数据结构,macros,clojure,self-reference,Macros,Clojure,Self Reference,对于任何错误的术语,我深表歉意——我对计算机科学相当陌生,而且我几乎只知道Clojure(但我想我会说我非常了解它) 因此,我还没有对此做过大量的研究,但我有时发现在编写Clojure代码时,能够从该数据结构中引用某些“我所处的任何数据结构的中间版本”(很像在let中)。快速示例: =>(self-ish{:a 10 :b(inc(this:a)) :c(计数(VAL此))}) =>{:A10,:B11,:C3} =>(自我约束[“a”和“b”(减少此项)]) =>[“a”“b”“ab”] //

对于任何错误的术语,我深表歉意——我对计算机科学相当陌生,而且我几乎只知道Clojure(但我想我会说我非常了解它)

因此,我还没有对此做过大量的研究,但我有时发现在编写Clojure代码时,能够从该数据结构中引用某些“我所处的任何数据结构的中间版本”(很像在
let
中)。快速示例:

=>(self-ish{:a 10
:b(inc(this:a))
:c(计数(VAL此))})
=>{:A10,:B11,:C3}
=>(自我约束[“a”和“b”(减少此项)])
=>[“a”“b”“ab”]
//也适用于任何嵌套位
=>(self-ish[1 2 3[4 5(第一个本)]6[7[8(第二个本)(第三个本))]]
=> [1 2 3 [4 5 1] 6 [7 [8 (2 4 5 1)]]]
其思想是结构以增量的方式构建自身,并且在任何阶段都能够将当前的中间结构称为
this
。以下是我当前实现的代码:

//随机简单但有用的定义
(定义地图条目?[obj]
(例如:clojure.lang.AMapEntry obj))
(def Map clojure.lang.IPersistentMap)
(def Vector clojure.lang.IPersistentVector)
(def List clojure.lang.IPersistentList)
(def Set clojure.lang.IPersistentSet)
(defn附加
[x coll]
(如果不是coll x
(condp实例?coll
映射(如果(空?x)coll
(助理秘书长(第一个x)(第二个x)))
向量(conj coll x)
集合(conj coll x)
列表(应用列表(concat coll[x]))
(concat coll[x]))
(defn构建这个
[acc堆栈acc]
(->>(cons acc堆栈)
(在列表中删除?)
(中途退出(每个pred空?标识))
(减少追加)
(自我放纵
[acc stack acc表格]
;//取消对以下内容的注释,以查看其打印处理的中间阶段
#_(println“this:(构建此acc堆栈acc)”\n位于:“表单”
(附加)
(coll?form)(减少(部分自放纵(cons acc acc堆栈))
(如有)(地图输入?表格)[]
(空表)
(表格)
(=(引用此)表格)(构建此acc堆栈acc)
:其他表格)
行政协调会)
(自嘲)
[表格]
(自我放纵(零形式))
append
函数将项追加到集合中,并返回相同类型的集合。
self-audency
函数有一个标准的reduce-like累加器,它只构建表单元素。它还有一个累加器堆栈,每当
自我放纵
自身递归时,累加器堆栈就会变长。这一点是为了跟踪其他“更高”的累加器,以便
这将是整个结构,而不仅仅是局部。
self-ish
宏只是很好地包裹了
self-audency
(它使用
partial
调用自己,所以它不能穿宏裤子)

编辑:示例用例 对我来说,这个宏是关于提高代码可读性,而不是真正扩展功能。我发现这很有用的地方是在我有部分冗余数据的手写结构的情况下——或者“依赖”是一个更好的词。阅读代码和查看数据结构的不同部分会更容易,如果我修改结构的一部分中的数据值并希望该更改反映在其他部分中,这也会很有用。例如:

=>(自我介绍:最喜欢的书(列出“犯罪与惩罚”“达洛韦夫人”)
:最喜欢的东西(列出*“冰淇淋”“吊床”(这是:最喜欢的书)})
=>{:最喜欢的东西(“冰淇淋”“吊床”“犯罪与惩罚”“达洛韦夫人”),
:最喜欢的书(“犯罪与惩罚”“达洛韦夫人”)}
当人们可能真的希望在数据中包含烘焙的内容,而不是使用某个函数进行动态派生时,它也可能非常有用。这些情况可能更为罕见,我认为,如果可以使用干净的函数来处理数据,那么不必要地将数据纠结起来是一个坏主意

我的主要问题是:

  • 这真的有用吗,还是会产生太多的歧义/复杂性?我想我不是唯一想要/使用这种类型的宏的人。其他人在这里有什么经验?你使用过类似的东西吗?你找到更好的解决方法了吗?有没有理由在任何Clojure库中都没有类似的东西?或者有什么我喜欢的东西你还没见过吗
  • 是否有更好的命名约定我可以使用-相对于
    self ish
    this
    ?例如,可能
    this
    太过带有OOP含义,我不确定,我基本上只熟悉Clojure
  • 我对计算机科学相当陌生,有没有与这类事情相关的可访问和信息资源——我想我会称之为匿名自指(也许自反是一个更好的词?)数据结构?我还没有发现任何既可接近又可信息的东西
  • 有没有更好的方法来编写
    self-ish
    宏?上面,我已经包括了我当前版本的宏,但我无法动摇可能有更简单的方法的感觉
  • 关于什么可能是“最明智的”实施细节,我有各种各样的问题

    • :应该是广度优先还是深度优先?如果是深度优先、前序、后序还是顺序优先?现在,我认为它是深度优先的前序,这对我来说很有意义,但可能它有一些我没有注意到的缺点
    • 顺序问题:()在
      {}
      (即手工编写的映射)如果不使用
      数组映射
      排序映射
      ,就不可能正确地维护顺序(超过8个映射项)——换句话说,超过8个映射项,
      {/code>的使用是不安全的
      
      (let [this {}
            this (assoc this :a 1)
            this (assoc this :b (+ (this :a) 3))]
        this)
      
      (defmacro self-ish [bindings]
        `(let [~'this {}
               ~@(mapcat 
                 #(do `(~'this (assoc ~'this ~@%)) )    
                 (partition 2 bindings) )]
          ~'this))
      
      (self-ish [:a 1
                 :b (+ (this :a) 3)])
      => {:b 4, :a 1}
      
      (let [meaningful-foo (something)
            meaningful-bar (something-else)]
         {:foo meaningful-foo
          :bar meaningful-bar
          :baz (some-calculation meaningful-foo meaningful-bar)})