这是"Clojure中最具惯用性"的问题.
我正在使用Cassandra作为我的DB,Alia作为我的Clojure司机(Cassandra和Alia工作非常好 - 不能更快乐).
问题是这样的:Cassandra在列名中使用下划线(而不是破折号),而Clojure更喜欢使用破折号来强调下划线.所以Clojure中的"user-key"在Cassandra中是"user_key".如何最好地处理Cassandra列名称到Clojure变量的映射?
因为我正在为我的CQL查询使用预准备语句,所以我认为列名称包含下划线而不是破折号这一事实不仅仅是要抽象出来的实现细节 - 我经常将CQL查询作为字符串放入我的Clojure代码中,而且我认为代表CQL实际上很重要.我已经考虑了在查询字符串中自动将短划线转换为下划线的方法,因此有一个Clo的Clojure版本被映射到CQL的Cassandra版本,但这似乎是一个不合适的抽象级别.此外,当你直接在Cassandra中运行CQL查询进行故障排除时,你仍然需要使用下划线,因此你需要在脑中保留两个不同的列名表示.似乎是错误的方法.
我最终采用的方法是在Clojure解构映射中执行映射,如下所示:
(let [{user-key :user_key, user-name :user_name}
(conn/exec-1-row-ps "select user_key,user_name from users limit 1")] )
Run Code Online (Sandbox Code Playgroud)
("conn/exec-1-row-ps"是我的便捷函数,只是在地图中查找CQL字符串,并使用先前准备的语句(如果存在),或者准备语句并将其存储在地图中,并且然后执行预准备语句并返回结果集的第一行,如果返回多行,则抛出异常).
如果我使用更简洁的{:keys []}解构方法,那么我会在我的Clojure变量名中使用下划线:
(let [{:keys [user_key user_name]} ...
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的第一种方法,但它变得非常快,因为带有下划线的变量名称会渗透到代码中,并与带有破折号的变量名称进行正面交锋.混乱.
在很长一段时间内遇到这个问题,在解构图中进行转换,其中Clojure"变量名"和Cassandra"column_name"并排感觉就像是最好的解决方案.它还允许我在需要时将short_col_nms扩展为更具描述性的变量名称.
这与Clojure在文件名中强调命名空间中的破折号的映射有一些相似之处,所以感觉就像这样进行映射有一些先例.在文件名/命名空间的情况下,Clojure自动执行映射,因此直接模拟可能是{:keys []}解构的版本,将破折号映射到下划线.
我是Clojure的新手,所以我意识到可能有更好的方法来做到这一点.因此我的问题.
我考虑过的一个改进是编写一个在编译时动态构建解构映射的宏.但我不知道如何编写一个在编译过程早期运行的宏.
我经常交换!使用匿名函数的原子值,该匿名函数在计算新值时使用一个或多个外部值。有两种方法可以执行此操作,一种是我了解的是闭合,而另一种则不是,我的问题是哪种方法更好/更有效?
这是一个简单的示例-向原子添加变量数值-显示两种方法:
(def my-atom (atom 0))
(defn add-val-with-closure [n]
(swap! my-atom
(fn [curr-val]
;; we pull 'n' from outside the scope of the function
;; asking the compiler to do some magic to make this work
(+ curr-val n)) ))
(defn add-val-no-closure [n]
(swap! my-atom
(fn [curr-val val-to-add]
;; we bring 'n' into the scope of the function as the second function parameter
;; so no closure is needed
(+ curr-val val-to-add))
n))
Run Code Online (Sandbox Code Playgroud)
这是一个虚构的示例,当然,您实际上不会编写此代码来解决此特定问题,因为:
(swap! my-atom + n)
Run Code Online (Sandbox Code Playgroud)
无需额外功能即可完成相同的操作。
但是在更复杂的情况下,您确实需要一个函数,然后问题就出现了。对我来说,从编码的角度来看,解决问题的两种方法的复杂度大致相同。如果是这样,我应该选择哪个?我的工作假设是,非封闭方法是更好的方法(因为编译器更容易实现)。 …