2024 Clojure现状调查!分享您的想法。

欢迎!请参阅关于页面,了解有关如何使用的更多信息。

0
REPL
编辑

上下文:我从互联网上解析了一些广泛的XML数据。现在我想在REPL中进行探索/过滤/下钻。

我有一个名为xs的未知长度和未知内容的LazySeq。我想在REPL中探索xs的前几个元素。为了方便起见,我想这样def一些变量

(def x1 (nth xs 0 nil))
...
(def x5 (nth xs 4 nil))

这很麻烦,尤其是当需要重复操作以开发我的"下钻"函数时。是否有便捷函数(或宏)可以帮我做这个,可能像这样

(defmany xs "x" 5)
;=> #'my.ns/x1
;=> ...
;=> #'my.ns/x5

我尝试编写了一个函数。它使用了eval,这并不安全(还有其他缺点)。因此,我的问题是

  1. 类似的这项功能在某处已经存在了吗?
  2. 我需要宏来处理这个问题,还是可以用函数解决?(我对编写Clojure宏不熟悉。)
  3. 如何定义这个函数/宏?

作为娱乐,这是我尝试的结果

(defn def-many
  [xs prefix n]
  (map eval
       (for [i (range n)]
            (list 'def
                  (symbol (str prefix (inc i)))
                  (nth xs i nil)))))

(如果(nth xs i nil)是LazySeq或列表,则eval会尝试将其解释为函数调用。这可以检测并转换为向量等,但这并不太理想。)

1 答案

+2
 
最佳答案

对于这个问题,您不需要使用eval(因为您控制所有实际上被eval执行的内容,所以在这个上下文中这也是不安全的)

(let [data (vec (range 10))]
  (dotimes [idx (count data)]
    (intern *ns* (symbol (str "x" idx)) (nth data idx))))

=> x5
5

但是,不要像这样做,我强烈建议使用tap>来处理数据并使用像Portal、Reveal、REBL这样的工具。与在纯文本REPL中浏览复杂的嵌套数据相比,这要方便得多。

`intern`!就是这样!谢谢!还有,对于Portal/Reveal/REBL的建议也非常棒。再次感谢!
...