以切片为参数的纯函数

时间:2012-12-10 21:33:24

标签: go

如果我需要在参数中传递(小)切片,那么写入pure function的最佳方法是什么? 切片不像数组那样传递值。因此,不可能保证在执行函数期间不会修改它。 一旦解决方案是每次调用函数时复制切片。它会在实践中起作用,但我更倾向于使用更安全的解决方案,因为无法确保在函数调用之前创建副本。

3 个答案:

答案 0 :(得分:2)

你是对的,因为切片是参考值,所以不可能使用切片参数的真正纯函数。

根据您的需要,您可以使用数组。数组具有固定数量的元素,声明如下:

var myArray [10]int

按值传递时会复制数组。

另一种可能性是将切片封装在只允许从切片读取的接口中,而不是写入切片。

Here's an example

package main

import "fmt"

// The interface
type ReadOnlyStringSlice interface {
    Get(int) string
}

// An implementation of ReadOnlyStringSlice
type MyReadOnlySlice struct {
    slice []string
}

func (m MyReadOnlySlice) Get(i int) string {
    e := m.slice[i]
    return e
}

// Your "pure" function
func MyPureFunction(r ReadOnlyStringSlice) {
    fmt.Println(r.Get(0))
}

func main() {
    m := MyReadOnlySlice{[]string{"foo", "bar"}}
    MyPureFunction(m)
}

答案 1 :(得分:2)

不是一个真正的答案,但我想仍然值得讨论。

我认为整个想法是一厢情愿的想法:努力在一种语言中使用纯函数是没有意义的,这种语言不会以任何方式使用你的函数纯粹的事实。如果你可以将一个函数“标记”为纯函数,那么Go理论上可以以某种方式使用这个提示来获得它的优势(例如,在一系列调用中重新排序某些函数的执行)。由于没有明确的支持这种东西,功能的纯度只存在于你的脑海中。例如,假设您能够以某种方式强制函数不修改传递给它的切片;即使这样,也没有什么能阻止你在该函数中执行另一个副作用(比如,执行I / O或修改全局变量)。

如果你正在编写一个库并希望它的调用者提供一个回调,并且回调一定不能改变,只需在文档中清楚地说明这一事实。

答案 2 :(得分:0)

如果您正在编写程序包,则可以导出一个获取切片但复制的方法 它并将其传递给真正的函数:

func MyExportedFunc(someSlice []int) {
    sliceCopy := make([]int, len(someSlice))
    copy(sliceCopy, someSlice)

    myUnexportedFunc(sliceCopy)
}

当然,这不是解决问题的方法,因为MyExportedFunc不是 纯。最好的方法可能是封装切片,正如@Tom建议的那样。