代码之家  ›  专栏  ›  技术社区  ›  David Soroko

Julia迭代错误

  •  2
  • David Soroko  · 技术社区  · 6 年前

    我在看一个迭代器示例 http://lostella.github.io/blog/2018/07/25/iterative-methods-done-right 还有一个问题。以下操作可产生最多13个斐波那契数:

    iterate(f::FibonacciIterable) = f.s0, (f.s0, f.s1)
    iterate(f::FibonacciIterable, state) = state[2], (state[2], state[1] + state[2])
    
    for f in FibonacciIterable(0, 1)
        print("$f ")
        if f > 10 println(); break end
    end
    

    我在试着替换这两个 iterate

    iterate(f::FibonacciIterable, state = (f.s0, (f.s0, f.s1)) ) = (state[2], state[1] + state[2])
    

    运行此代码会产生:

    ERROR: LoadError: MethodError: no method matching +(::Int64, ::Tuple{Int64,Int64})
    Closest candidates are:
      +(::Any, ::Any, !Matched::Any, !Matched::Any...) at operators.jl:502
      +(::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, !Matched::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:53
      +(::Union{Int16, Int32, Int64, Int8}, !Matched::BigInt) at gmp.jl:456        
    

    注意

    在这里评论Bogumi Kamiski关于格式化和额外空间的回答

    谢谢博古米-但我仍然很难建立一个关于这个工作原理的心理模型。首先,以下也是

    iterate(iter::FibonacciIterable, state=(iter.s1, iter.s0)) = state[2], (state[2], sum(state))
    

    文件上说:

    iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}}
    
    Advance the iterator to obtain the next element. If no elements remain, nothing should be returned. 
    Otherwise, a 2-tuple of the next element and the new iteration state should be returned.
    

    我读这篇文章的时候,第一次打电话给 迭代 iter.s1 建立下一个州 成为 iter.s0 1 下一次调用 应该失败 因为没有 state[2] . 显然这不是第一个值 0 计算过程没有任何误差。你能指出我的逻辑哪里出错吗?

    意见2

    对-这有助于:

    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)))
    (2, (2, 3))
    

    我假设 state 迭代

    正如你所指出的,情况并非如此 状态 Tuple{I,I} 但是返回值的类型是 Tuple{I, Tuple{I,I}} Union{Nothing, Tuple{I, Tuple{I,I}}} 但别介意)里面的元组是状态。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Bogumił Kamiński    6 年前

    你必须通过唯一的州,所以 Tuple{I, I} where {I} Tuple{I, Tuple{I, I}} where {I} iter.s0 ).

    因此,您可以定义 iterate 功能是:

    iterate(iter::FibonacciIterable, state=(iter.s1-iter.s0, iter.s0)) =
        state[2], (state[2], sum(state))
    

    julia> for F in FibonacciIterable(BigInt(0), BigInt(1))
               println(F)
               F > 10 && break
           end
    0
    1
    1
    2
    3
    5
    8
    13
    

    编辑 :参考您的附加问题。

    如果将定义更改为:

    iterate(iter::FibonacciIterable, state=(iter.s1, iter.s0)) = state[2],
            (state[2], sum(state))
    

    julia> for F in FibonacciIterable(BigInt(2), BigInt(3))
                      println(F)
                                 F > 10 && break
                                        end
    2
    5
    7
    12
    

    我们清楚地看到出了问题。

    (fibonacci(n), fibonacci(n+1) i、 e.先到元素 n 第二个是元素 n+1 .

    iterate(iter::FibonacciIterable, state=(iter.s1-iter.s0, iter.s0)) =
            state[2], (state[2], sum(state))
    

    让我们看看当我们运行这些行时会发生什么:

    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)))
    (2, (2, 3))
    
    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)), (2, 3))
    (3, (3, 5))
    
    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)), (3, 5))
    (5, (5, 8))
    

    迭代 告诉你第一个元素是 2 (2,3) . 所以在第二行,我们使用这个状态来获得下一个迭代:value 3 下一个州 (3,5) . 我们继续使用这个新状态来获取下一个值 5 (5,8) .

    我想在这个例子中混淆的是状态是一个元组,但是 迭代

    struct FiboState{I}
        a::I
        b::I
    end
    

    以及以下定义 迭代

    iterate(iter::FibonacciIterable, state=FiboState(iter.s1-iter.s0, iter.s0)) =
            state.b, FiboState(state.b, state.a+state.b)
    

    现在我们清楚地看到了发生了什么:

    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)))
    (2, FiboState{BigInt}(2, 3))
    
    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)), FiboState{BigInt}(2, 3))
    (3, FiboState{BigInt}(3, 5))
    
    julia> iterate(FibonacciIterable(BigInt(2), BigInt(3)), FiboState{BigInt}(3, 5))
    (5, FiboState{BigInt}(5, 8))
    

    我希望这能有帮助。