通过实现具有3个函数的迭代接口,可以为新定义的类型实现Julia中的迭代: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包中碰到了一些不尊重它的迭代器。
答案 0 :(得分:7)
如果可能,那些函数不应该改变迭代器(这样可以复制和重用迭代器状态)。然而,有一些突出的例子表明这种设计是不可能的,或者只有在显着的性能损失下才有可能。这个例子的主要例子是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
在这些情况下,我们通常对变异很好(尽管当然任何使用迭代协议来缓存状态都不会起作用)。函数末尾的感叹号是一个约定,但不以任何方式强制执行(并不严格限制其输入参数的变异,而是具有一些副作用,您希望确保程序员知道)
答案 1 :(得分:3)
这些方法应该不修改他们的参数,可能是因为您可能想要重复使用迭代器,并且您对感叹号标记是正确的。
你说得对,自定义是在方法名称修改参数时附加!
我还遇到了一个包,ProgressMeter包使用了下一个方法!(),而且确实改变了你拥有的进度表类型
我喜欢感叹号的想法(我不知道它是否起源于朱莉娅或其他地方)但对于开发人员来说,确保其与此一致非常重要
<强> TL;博士强> 你是对的,它在文档中这么说,并且真正强调了这一点,详细描述它的部分称为Essentials
(请注意非英语母语人士,不存在感叹号)