(小さな) スライスをパラメーターに渡す必要がある場合、goで純粋な関数を記述する最良の方法は何ですか? スライスは配列のように値渡しされません。そのため、関数の実行中に変更されないことを保証することはできません。解決策は、関数を呼び出すたびにスライスをコピーすることです。実際には機能しますが、関数呼び出しの前にコピーが作成されることを保証する方法がないため、より安全なソリューションをお勧めします。
3 に答える
本当の答えではありませんが、それでも議論する価値があると思います。
全体の考えは希望的観測だと思います。あなたの関数が純粋であるという事実を決して使用しない言語で純粋関数を持つように努力することに意味はありません。関数を純粋であると「マーク」できる場合、Goは理論上、このヒントを何らかの形で有利に使用できます(たとえば、一連の呼び出しで一部の関数の実行を並べ替える場合など)。そのようなことを明示的にサポートしていないので、関数の純粋さはあなたの心の中にのみ存在します。たとえば、渡されたスライスを変更しないように関数を強制することができたとします。それでも、その関数で別の副作用を実行することを妨げるものは何もありません(たとえば、I / Oの実行やグローバル変数の変更)。
ライブラリを作成していて、その呼び出し元がコールバックを変更してはならないスライスを取得するコールバックを提供するようにしたい場合は、ドキュメントにこの事実を明確に記載してください。
スライスは参照値であるため、スライス引数を持つ真に純粋な関数は不可能です。
必要に応じて、配列を使用できます。配列には固定数の要素があり、次のように宣言されます。
var myArray [10]int
配列は、値渡し時にコピーされます。
別の可能性は、スライスからの読み取りのみを許可し、スライスへの書き込みを許可しないインターフェイスにスライスをカプセル化することです。
例を次に示します。
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)
}
パッケージを作成している場合は、スライスを取得してコピーし、実際の関数に渡すメソッドをエクスポートできます。
func MyExportedFunc(someSlice []int) {
sliceCopy := make([]int, len(someSlice))
copy(sliceCopy, someSlice)
myUnexportedFunc(sliceCopy)
}
もちろん、これはMyExportedFunc
純粋ではないため、一般的な問題の解決策ではありません。@Tomが提案したように、おそらく最良の方法はスライスをカプセル化することです。