Julia可以通过实现具有3个函数的迭代接口来实现对新定义类型的迭代:start
, next
, done
我在这些函数的末尾没有看到感叹号,所以根据我对julia命名约定的理解,这3个函数不应该修改它们的参数。特别是这两个循环应该给出相同的输出
state = start(iter)
while !done(iter, state)
(i, state) = next(iter, state)
@show i
end
state = start(iter)
while !done(iter, state)
(other_i, other_state) = next(iter, state)
(i, state) = next(iter, state)
@show i
end
我错了吗?我问这个问题是因为我在外部julia包中碰到了一些不尊重这一点的迭代器。
如果可能的话,这些函数不应该改变迭代器的状态(这样迭代器的状态就可以被复制和重用)。然而,在一些突出的例子中,这样的设计是不可能的,或者只有在显著的性能损失下才可能实现。最典型的例子是Base.Task
,它是可迭代的(每次迭代运行直到下一个produce
语句):
julia> collect(@async for i = 1:10
produce(i)
end)
10-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
10
在这些情况下,我们通常可以很好地处理突变(当然,任何使用缓存状态的迭代协议都不起作用)。函数末尾的感叹号是一种惯例,但不以任何方式强制执行(并且不严格限于其输入参数的突变,而是有一些您希望确保程序员意识到的副作用)。
这些方法应该不应该修改它们的参数,这可能是因为您可能想要重用迭代器,您关于感叹号标记的看法是正确的。
你是对的,习惯上是附加!如果方法修改了参数
我还遇到了一个包,ProgressMeter包,它使用next!()方法,它确实改变了你的进度表类型
我喜欢感叹号的想法(我不知道它是否起源于Julia或其他地方),但对于开发人员来说,与此保持一致是很重要的
tl;博士你说得对,文档里是这么说的,为了强调这一点,详细说明的部分叫做Essentials
(非英语为母语的人注意,没有感叹号这种东西)