为什么追加函数调用时函数执行顺序看起来相反?

时间:2019-02-08 04:16:46

标签: function go

我正在阅读以下问题:Decorator functions in Go,并且想知道为什么在接受的答案中示例的执行顺序似乎与我相反。

我已将其分解为以下最小示例,并且想知道其效果是否是由于函数链接引起的。

// Interesting Part
some_string := "Some_String"
var fn3 StringManipulator = ident
fn3 = AppendDecorator(" GOLANG", ToLower(PrependDecorator("DECORATED ", fn3)))
fmt.Println(fn3(some_string))
// Prints "DECORATED some_string golang"

// Function Definitions
func ToLower(m StringManipulator) StringManipulator {
    return func(s string) string {
        lower := strings.ToLower(s)
        return m(lower)
    }
}

func AppendDecorator(x string, m StringManipulator) StringManipulator {
        return func(s string) string {
            return m(s + x)
        }
}

func PrependDecorator(x string, m StringManipulator) StringManipulator {
    return func(s string) string {
        return m(x + s)
    }
}

如代码中所述,这将产生“ DECORATED some_string golang”,表明函数是从左到右执行的,而正常函数是从最内到最外(即从右到左)求值的。 [这让我想起了转换矩阵的后乘法-顺序也被“颠倒了”,即M_1 * M_2 * M_3]这是由于函数链接还是原因?有人可以帮我了解它如何详细执行吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

我重写了您的示例进行说明。

嵌套函数调用从内部到外部执行。每个函数调用都返回一个函数。最终,为变量m分配了AppendDecorator的结果,该结果本身是一个由所有装饰器组成的函数,看起来像这样:

m := func(s string) string {
    return ("DECORATED " + strings.ToLower(s + " GOLANG"))
}

当我们执行m(s)(在fmt.Println(m(s)内部)时,我们正在执行AppendDecorator返回的函数。该函数调用m(s + x),其中mToLower返回的函数。执行此函数时,它将调用m(lower),其中mPrependDecorator返回的函数。执行此函数时,它将调用m(x + s),其中m是我们传入的Identity函数。

package main

import (
    "fmt"
    "strings"
)

// StringManipulator manipulate a string
type StringManipulator func(str string) string

// Identity a string manipulator that leaves the string unchanged
func Identity(s string) string {
    fmt.Println("Executing Identity manipulator")
    return s
}

// ToLower a lower case string manipulator
func ToLower(m StringManipulator) StringManipulator {
    fmt.Println("Returning ToLower manipulator")
    return func(s string) string {
        fmt.Println("Executing ToLower manipulator")
        lower := strings.ToLower(s)
        return m(lower)
    }
}

// AppendDecorator append a string manipulator
func AppendDecorator(x string, m StringManipulator) StringManipulator {
    fmt.Println("Returning Append manipulator")
    return func(s string) string {
        fmt.Println("Executing Append manipulator")
        return m(s + x)
    }
}

// PrependDecorator prepend a string manipulator
func PrependDecorator(x string, m StringManipulator) StringManipulator {
    fmt.Println("Returning Prepend manipulator")
    return func(s string) string {
        fmt.Println("Executing Prepend manipulator")
        return m(x + s)
    }
}

func main() {
    s := "Some_String"

    m := AppendDecorator(" GOLANG", ToLower(PrependDecorator("DECORATED ", Identity)))
    fmt.Println(m(s))
}

m := AppendDecorator(" GOLANG", ToLower(PrependDecorator("DECORATED ", Identity)))的输出是:

Returning Prepend manipulator
Returning ToLower manipulator
Returning Append manipulator

,来自fmt.Println(m(s))的输出为:

Executing Append manipulator
Executing ToLower manipulator
Executing Prepend manipulator
Executing Identity manipulator
DECORATED some_string golang