我可以使用clojure';对于';宏来反转字符串?

我可以使用clojure';对于';宏来反转字符串?,clojure,Clojure,这是我问题的后续行动 是否可以使用Clojure“for”宏反转序列?我试图更好地理解这个宏的限制和用例 以下是我开始的代码: ((defn reverse-with-for [s] (for [c s] c)) 可能吗 如果是这样,我假设解决方案可能需要将for宏包装在定义可变变量的某个表达式中,或者for宏的body expr将以某种方式将序列传递到下一次迭代(类似于map)。Clojurefor宏正在与任意Clojure序列一起使用 这些序列可能会也可能不会像向量那样公开随机访

这是我问题的后续行动

是否可以使用Clojure“for”宏反转序列?我试图更好地理解这个宏的限制和用例

以下是我开始的代码:

((defn reverse-with-for [s] 
    (for [c s] c))
可能吗


如果是这样,我假设解决方案可能需要将
for
宏包装在定义可变变量的某个表达式中,或者for宏的body expr将以某种方式将序列传递到下一次迭代(类似于
map
)。

Clojure
for
宏正在与任意Clojure序列一起使用

这些序列可能会也可能不会像向量那样公开随机访问。因此,在一般情况下,如果不遍历Clojure序列的最后一个元素,就无法访问该序列的最后一个元素,这将使以相反顺序遍历它成为不可能

我想你一定有这样的想法(类似Java的伪代码):


首先,正如Goran所说,
for
不是一个语句,它是一个表达式,即序列理解。它通过迭代其他序列来构造序列。因此,在形式上,它是纯函数(没有副作用).for的
可以看作是增强的
映射
注入了
过滤器
。因此,它不能像
reduce
那样用于保持迭代状态

其次,您可以使用
for
和可变状态来表示序列反转,例如使用atom,这大致相当于java变量(不考虑其并发属性)。但这样做会面临几个问题:

  • 您正在打破主语言范式,因此您的代码外观和行为肯定会变得更差
  • 由于所有clojure可变状态单元都设计为线程安全,因此它们都使用某种非法的并发修改保护,并且无法删除它。因此,您将获得较差的性能特征
  • 在这种特殊情况下,正如Goran所说,序列是广泛使用的Clojure抽象之一。例如,有一些惰性序列,它们可能是无限的,所以你无法将它们走到最后。使用命令式技术处理这些序列肯定会有困难
  • 所以不要这样做,至少在Clojure:)


    编辑:我忘了提了
    for
    返回惰性序列,因此您必须以某种方式对其求值,以便应用在其中执行的所有状态变化。不这样做的另一个原因是:)

    以下是使用for反转字符串的方法:

    (defn reverse-with-for [s] 
        (apply str
            (for [i (range (dec (count s)) -1 -1)]
                (get s i))))
    
    请注意,此代码是无变异的。这与:

    (defn reverse-with-map [s] 
        (apply str
            (map (partial get s) (range (dec (count s)) -1 -1))))
    
    更简单的解决办法是:

    (apply str (reverse s))
    

    理解。但是我想你可能会做一些非常棘手的事情,比如变异
    之外为
    定义的var。但是,
    doseq
    可能更合适。@noahz:我想你可以这样做。我的编辑是指那个部分。但接下来,您将在命令式算法中使用可变状态。按照这种思路,您还可以用实际的Java编写一个纯Java代码,并通过互操作调用它。我并不总是反对命令式变异代码。我只是觉得用原始Java更容易实现。特别是因为互操作非常有效。请查看Alexandre的解决方案。性能很差,但这正是我想要的。事实上,原子相当快,在无争用的代码中,它们只是一个比较和设置java调用。在我的测试中,它们比(inc1)慢20倍。map+过滤器实际上仍然没有
    强大
    for
    更像是
    mapcat
    的一个(可能重复)应用程序,实际上它同样强大。考虑编写<代码>(对于[x(范围10)y[:xx] y)< /> >作为<代码> MAP>代码>操作:您不能这样做,因为您希望返回两倍于给定的元素。谢谢您的澄清。我不知道
    for
    的这种拼接功能。我写了关于
    和map+filter的等价性的文章,考虑到Scala中类似的构造,我读到它等价于map+filter。这就是我一直在寻找的东西。无突变的奖金。谢谢。如果字符串支持
    rseq
    ,那就太好了,这样您就可以在不需要遍历字符串进行反转的情况下完成此操作。@amalloy是的。我在写这个答案的时候发现了你的邮件列表,并在谷歌上搜索了clojure字符串rseq。不过,反转字符串并不是必须经常做的事情。
    (apply str (reverse s))