在clojure中定义'fori'宏/函数
我希望能够循环一个集合,但要使用该循环维护一个计数器。我设法创造了在clojure中定义'fori'宏/函数,clojure,Clojure,我希望能够循环一个集合,但要使用该循环维护一个计数器。我设法创造了 (for [[email i] (map vector emails (range))] ...) 要做到这一点,但理想情况下,我更喜欢一个fori宏(除非函数是可能的,但我的直觉告诉我它必须是一个宏),它可以让我做相同的事情 (fori [email i emails] ...) 或 我没有使用宏的经验,查看for宏的源代码看起来非常吓人。有什么帮助吗 Super cool将是一个遵循for语法的宏,并允许 (fo
(for [[email i] (map vector emails (range))]
...)
要做到这一点,但理想情况下,我更喜欢一个fori
宏(除非函数是可能的,但我的直觉告诉我它必须是一个宏),它可以让我做相同的事情
(fori [email i emails]
...)
或
我没有使用宏的经验,查看for
宏的源代码看起来非常吓人。有什么帮助吗
Super cool将是一个遵循for
语法的宏,并允许
(fori [email i emails
line j (lines email)]
...)
这可能是你想要的。e、 g
(fori [:a :b :c :d])
产生
([0 :a] [1 :b] [2 :c] [3 :d])
顺便说一句,for不是一个循环,而是创建一个列表。如果你想在一个循环中做一些有副作用的事情,你应该研究doseq。你可以为编写一个扩展到
的宏,但我并不认为这有多大意义。有许多内置函数正是为了实现这一目的,而fori
语法实际上读起来不是很好。至少看起来应该是这样的
(fori [[email i] emails,
[line j] (lines email)]
...)
但如果你真的想完全按照你说的写,那肯定不是不可能的:
(defmacro fori [bindings body]
(letfn [(clauses [bindings]
(lazy-seq
(cond (empty? bindings) ()
(keyword? (first bindings)) (concat (take 2 bindings)
(clauses (drop 2 bindings)))
:else (let [[name index value] (take 3 bindings)]
(list* [index name] `(map-indexed vector ~value)
(clauses (drop 3 bindings)))))))]
`(for [~@(clauses bindings)]
~body)))
user> (macroexpand-1 '(fori [email i xs,
:when (even? i)
line j (lines email)]
[i line]))
(for [[i email] (map-indexed vector xs)
:when (even? i)
[j line] (map-indexed vector (lines email))]
[i line])
@KobbyPemson好的,这已经是一半了,但还是比我想要的更多的重复,因为我是通过电子邮件、推特、彩信、Facebook、WordPress、tumblrs等进行重复的。这不只是等同于(def fori map indexed)
,或者基本上是告诉我使用地图索引
?在这种情况下,请看我对这个问题的第一个评论。不,它不是等价的。试试看。好的,和(def-fori(部分映射索引向量))
一样。寻找更多。主要目标相当于F#land的Seq.iteri
;这甚至超出了它的伟大之处,尽管最终我同意你提供的格式可能更好;我将仔细研究这个问题并找出如何修改它。对于其他寻找答案顶部建议语法的人来说,结果非常简单:将let
修改为[[name index]值](接受2个绑定)]
,然后(删除2个绑定)
fori
表达式可能比您希望采用的模式更进一步,或者更全面地看待它,一个简单的fori
表达式将在单循环情况下工作,它是:(defmacro fori[[[item i]collection]body]`(for[[i~ item](映射索引向量集合)]~body))@DaxFohl“fori表达式”?由于Clojure没有任何语句,我不确定这是什么意思。@Noises我的注释在F#序列表达式与正则函数的词典中。
(fori [[email i] emails,
[line j] (lines email)]
...)
(defmacro fori [bindings body]
(letfn [(clauses [bindings]
(lazy-seq
(cond (empty? bindings) ()
(keyword? (first bindings)) (concat (take 2 bindings)
(clauses (drop 2 bindings)))
:else (let [[name index value] (take 3 bindings)]
(list* [index name] `(map-indexed vector ~value)
(clauses (drop 3 bindings)))))))]
`(for [~@(clauses bindings)]
~body)))
user> (macroexpand-1 '(fori [email i xs,
:when (even? i)
line j (lines email)]
[i line]))
(for [[i email] (map-indexed vector xs)
:when (even? i)
[j line] (map-indexed vector (lines email))]
[i line])