【问题标题】:golang multiple assignment evaluationgolang 多重赋值评估
【发布时间】:2018-02-16 23:07:45
【问题描述】:

我对多重赋值的概念感到困惑。给定以下代码:

func fibonacci() func() int {
    current, next := 0, 1
    return func() int {
        current, next = next, current+next
        return current
    }
}

鉴于两个变量都出现在赋值的左侧和右侧,如何评估赋值?

【问题讨论】:

    标签: go


    【解决方案1】:

    The Go Programming Language Specification

    Assignments

    任务分两个阶段进行。一、索引​​的操作数 表达式和指针间接(包括隐式指针 选择器中的间接)在左边和表达式在 right 都按照通常的顺序进行评估。二、作业 按从左到右的顺序执行。


    说明多个分配的常用示例是交换。例如,

    package main
    
    import "fmt"
    
    func main() {
        {
            i, j := 7, 42
            fmt.Println(i, j)
            // swap i and j - implicit temporaries
            i, j = j, i
            fmt.Println(i, j)
        }
    
        fmt.Println()
    
        {
            i, j := 7, 42
            fmt.Println(i, j)
            // swap i and j - explicit temporaries
            ti, tj := i, j
            i, j = tj, ti
            fmt.Println(i, j)
        }
    }
    

    游乐场:https://play.golang.org/p/HcD9zq_7tqQ

    输出:

    7 42
    42 7
    
    7 42
    42 7
    

    使用隐式临时变量的一个语句多重赋值相当于(简写)两个使用显式临时变量的多重赋值语句。


    您的斐波那契示例通过显式顺序和临时变量转换为:

    package main
    
    import "fmt"
    
    func fibonacciMultiple() func() int {
        current, next := 0, 1
        return func() int {
            current, next = next, current+next
            return current
        }
    }
    
    func fibonacciSingle() func() int {
        current, next := 0, 1
        return func() int {
    
            // current, next = next, current+next
            // first phase, evaluation, left-to-right
            t1 := next
            t2 := current + next
            // second phase, assignmemt, left-to-right
            current = t1
            next = t2
    
            return current
        }
    }
    
    func main() {
        m := fibonacciMultiple()
        fmt.Println(m(), m(), m(), m(), m(), m())
        s := fibonacciSingle()
        fmt.Println(s(), s(), s(), s(), s(), s())
    }
    

    游乐场:https://play.golang.org/p/XFq-0wyNke9

    输出:

    1 1 2 3 5 8
    1 1 2 3 5 8
    

    【讨论】:

      【解决方案2】:

      顺序在语言规范中的Order of Evaluation 中定义。

      在包级别,初始化依赖关系决定了变量声明中各个初始化表达式的计算顺序。否则,在计算表达式、赋值或返回语句的操作数时,所有函数调用、方法调用和通信操作都按词法从左到右的顺序计算。

      附带一个复杂求值顺序的好例子

      y[f()], ok = g(h(), i()+x[j()], <-c), k()
      

      函数调用和通信按 f()、h()、i()、j()、

      从左到右计算操作数。在计算操作数之后分配next 的事实是无关紧要的。

      然后是Assignments:

      任务分两个阶段进行。首先,左侧的索引表达式和指针间接(包括选择器中的隐式指针间接)的操作数和右侧的表达式都按通常的顺序计算。其次,作业是按从左到右的顺序进行的。

      所以这里的顺序是next 然后是current+nextnext的结果赋值给current,然后current+next的结果赋值给next

      【讨论】:

      • 但是在 current+next 中使用了 'current' 的哪个值?在分配“下一个”之前还是之后?
      • @JeroenJacobs:那里只有一个 current 值可以使用。在计算所有操作数之后进行赋值。
      【解决方案3】:

      来自spec

      任务分两个阶段进行。首先,左侧的索引表达式和指针间接(包括选择器中的隐式指针间接)的操作数和右侧的表达式都按通常的顺序计算。其次,作业是按从左到右的顺序进行的。

      【讨论】:

        猜你喜欢
        • 2012-02-02
        • 2015-10-03
        • 2011-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        • 2011-01-01
        相关资源
        最近更新 更多