我看到了下面的例子中丰富的视频序列 http://blip.tv/file/734409 约33-36分钟到其中:在Clojure的`first`功能的性能
(first "abcd") => \a
现在,他说,这扩展到(排序):
(first "abcd") => (first (seq "abcd")) => (first '(\a \b \c \d))
因此,它看起来像一个O(N)
操作,因为字符串的完整副本正在制作。首先,如果String
是不可变的,那么它为什么被复制? (编辑:根据答案,它可能不是;只是在打印时以这种方式看)。其次,假设first
在Java中可变的其他东西上操作,比如说一个整数链表。 first
是否应该以懒惰的方式行动(例如,首先创建一个持久序列)?马上评估并保存它是否有意义?这可能会破坏很好的抽象,但我认为完成这项工作很快。当您拨打(seq "abcd")
时,您不知道如何使用它。当您拨打seq
上的first
时,您知道该怎么做。但是,当您拨打 "abcd"
时,我认为执行一个快速“抓取并保存”的方法比抓取一个序列更好,然后致电first
。
我错过了什么吗? Rich Hickey是否跳过了一些步骤?
让我知道如果我有问题。谢谢!
谢谢,关于使用可变成Java序列的可变Java对象的任何进一步输入? – 2010-10-04 16:41:44
IIRC调用seq返回一个由Java迭代器支持的惰性Clojure序列。所以随着懒惰序列的实现,它需要遵循与迭代器有关的所有规则(只要对基础对象进行变异)一旦实现,它就是一个不可变的Clojure序列。 – levand 2010-10-04 18:06:14
@Hamish - 如果你想把一个可变的Java对象变成一个序列,那么你需要做一个O(n)成本的防御副本,否则就有可能改变底层数据的风险(这会违反seq的正常期望行为并可能导致微妙的错误)。前一种方法(复制)可能是可取的,后者是非常危险的,除非你绝对确定在错误的时刻什么都不会改变。 – mikera 2011-09-29 08:15:18