Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在clojure中定义'fori'宏/函数_Clojure - Fatal编程技术网

在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])