Macros Clojure宏以常量形式收集字符串
我有一个Clojure文件,里面有很多字符串常量。我想通过将这些字符串包装到宏中,将它们收集到集合中。经过几次尝试,我成功了,但我的解决方案看起来相当可怕Macros Clojure宏以常量形式收集字符串,macros,clojure,Macros,Clojure,我有一个Clojure文件,里面有很多字符串常量。我想通过将这些字符串包装到宏中,将它们收集到集合中。经过几次尝试,我成功了,但我的解决方案看起来相当可怕 (ns Memorable) (def MEMORY (atom [])) (defmacro memorize [s] (swap! MEMORY conj s) s) (prn (str (memorize "hello") " brave new " (memorize "world"))) ; test (defmacro m
(ns Memorable)
(def MEMORY (atom []))
(defmacro memorize [s] (swap! MEMORY conj s) s)
(prn (str (memorize "hello") " brave new " (memorize "world"))) ; test
(defmacro make-memories-constant [] `(def MEMORIES ~(deref MEMORY)))
(make-memories-constant)
对于这个问题有更优雅的解决方案吗?就代码清理而言,我会删除
使内存保持常量
宏——您可以这样做
(def MEMORIES @MEMORY)
甚至
(def MEMORY @MEMORY)
为了避免另一个变量将名称空间弄得杂乱无章。只要您在所有调用MEMORY
之后放置此变量,这将保存内存
的快照,其中包含所有MEMORY
d字符串
我想说这实际上是相当干净的,运行时执行的实际代码与没有任何记忆的情况下没有什么不同
另一种方法是准备一种“记忆框架”,作为一个单独的名称空间,导出一个名为setup memoration
的宏,比如说,它可能看起来像这样(只是一个粗略的草图,如果没有一些润色,它将无法工作…更新为(不是很彻底)经过测试的版本——这确实有效!…不过,请根据您的需要调整它):
然后你要使用记忆框架名称空间,朝名称空间的顶部做(设置记忆)
来设置事情,调用记忆
,就像在示例代码中那样,记忆东西,最后使用结束记忆
定义记忆
将字符串集合存储在变量中的某个位置,并删除用于存储用于构造时存储的原子的临时变量,以及进一步调用从此名称空间中记住
。(当调用集合时,end memory
宏的目的是在没有参数的情况下将集合返回到调用它的位置,或者定义一个新的变量来存储它(如果给定一个参数),该参数必须是用于命名变量的符号。更新:我只测试了defmemtories
版本,因此我将它留在这里并删除。)“就地返回”变量。)
REPL在命名空间foo
中的交互示例(注意我在用户
命名空间中定义了设置记忆
):
这些“评估已中止”。消息表明调用get memory
和memory
会在调用defmemory
后引发异常。如上所述,这是设计的。另外,get memory
主要用于简化测试/调试
如果您只打算使用一次,那么设置记忆方法可能会有点过头,但我想如果您更多地使用它,它会为您删除一些样板文件。就代码清理而言,我会删除使记忆保持不变
宏——您可以这样做
(def MEMORIES @MEMORY)
甚至
(def MEMORY @MEMORY)
为了避免另一个变量将名称空间弄得杂乱无章。只要您在所有调用MEMORY
之后放置此变量,这将保存内存
的快照,其中包含所有MEMORY
d字符串
我想说这实际上是相当干净的,运行时执行的实际代码与没有任何记忆的情况下没有什么不同
另一种方法是准备一种“记忆框架”,作为一个单独的名称空间,导出一个名为setup memoration
的宏,比如说,它可能看起来像这样(只是一个粗略的草图,如果没有一些润色,它将无法工作…更新为(不是很彻底)经过测试的版本——这确实有效!…不过,请根据您的需要调整它):
然后你要使用记忆框架名称空间,朝名称空间的顶部做(设置记忆)
来设置事情,调用记忆
,就像在示例代码中那样,记忆东西,最后使用结束记忆
定义记忆
将字符串集合存储在变量中的某个位置,并删除用于存储用于构造时存储的原子的临时变量,以及进一步调用从此名称空间中记住
。(当调用集合时,end memory
宏的目的是在没有参数的情况下将集合返回到调用它的位置,或者定义一个新的变量来存储它(如果给定一个参数),该参数必须是用于命名变量的符号。更新:我只测试了defmemtories
版本,因此我将它留在这里并删除。)“就地返回”变量。)
REPL在命名空间foo
中的交互示例(注意我在用户
命名空间中定义了设置记忆
):
这些“评估已中止”。消息表明调用get memory
和memory
会在调用defmemory
后引发异常。如上所述,这是设计的。另外,get memory
主要用于简化测试/调试
如果您只打算使用一次所有这些,那么设置记忆
方法可能会有些过火,但我想如果您更多地使用它,它会为您删除一些样板文件。为什么记忆
是一个宏?为什么要在一个向量上映射identity
,然后创建一个新的结果向量?@Mike Douglas:makeMEMORY
宏可以消除运行时的函数调用开销(当宏展开时,conj
到MEMORY
)。同意第二点,这是为了什么?你想收集字符串以进行翻译吗?地图没有必要,我现在已经删除了它。宏是必需的,不是为了性能,而是因为在编译代码时,宏扩展阶段被跳过,内存将为空。@Stuart我有一个clojure文件w