我可以使用clojure'for'宏来反转字符串吗?

noa*_*hlz 4 clojure

这是我的问题"递归反转Clojure中的序列"的后续内容.

是否可以使用Clojure"for"宏来反转序列?我试图更好地理解这个宏的局限性和用例.

这是我开始的代码:

((defn reverse-with-for [s] 
    (for [c s] c))
Run Code Online (Sandbox Code Playgroud)

可能?

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

Gor*_*vic 7

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

这些序列可能会或可能不会像矢量那样暴露随机访问.因此,在一般情况下,您无法访问Clojure序列的最后一个元素而不会一直遍历它,这将使得以相反的顺序传递它是不可能的.

我假设你有类似的东西(类似Java的伪代码):

for(int i = n-1; i--; i<=0){
   doSomething(array[i]);
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我们n事先知道数组大小,我们可以通过索引访问元素.使用Clojure序列我们不知道.在Java中,使用数组和ArrayLists执行此操作是有意义的.然而,Clojure序列更像链接列表 - 您有一个元素,并且引用了下一个元素.

顺便说一下,即使有一种(可能是非惯用的)方法,它的时间复杂度也会像O(n ^ 2)那样,与链接帖子中更简单的解决方案相比,这是不值得的.列表的O(n ^ 2)和向量的O(n)要好得多(而且非常优雅和惯用.实际上,官方reverse有实现).

编辑:

一般建议:不要尝试在Clojure中进行命令式编程,它不是为它而设计的.虽然很多事情看起来很奇怪或反直觉的(而不是从命令式编程众所周知的成语),一旦你习惯做的事情是很多的功能性的方式,我的意思是很多容易.

专门针对这个问题,尽管Java(和其他C-like)for和Clojure for同名的东西都不一样!首先是实际循环 - 它定义了流量控制.第二个是理解 - 从概念上看它是一个序列的更高函数和一个函数f为它的每个元素完成,它返回另一个f(元素)序列.Java for是一个声明,它不评估任何东西,Clojure for(以及Clojure 中的任何其他东西)是一个表达式 - 它评估f(元素)的序列.

可能最简单的方法是使用序列函数库:http://clojure.org/sequences.另外,您可以在http://www.4clojure.com/上解决一些问题.第一个问题很容易,但随着你的进展,它们会越来越难.

*正如亚历山大的答案所示,问题的解决方案实际上是惯用的,非常聪明.为此感到荣幸!:)


Ale*_*min 5

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

(defn reverse-with-for [s] 
    (apply str
        (for [i (range (dec (count s)) -1 -1)]
            (get s i))))
Run Code Online (Sandbox Code Playgroud)

请注意,此代码是无变异的.它与以下相同:

(defn reverse-with-map [s] 
    (apply str
        (map (partial get s) (range (dec (count s)) -1 -1))))
Run Code Online (Sandbox Code Playgroud)

一个更简单的解决方案是:

(apply str (reverse s))
Run Code Online (Sandbox Code Playgroud)

  • 如果String支持`rseq`会很好,这样你就可以做到这一点而不需要遍历字符串来进行反转. (3认同)