😀
Nimのfunc(副作用なし関数)が厳格化できるようになる
概要
- Nimで一番単純なプロシージャ定義方法は
proc
を使用 -
proc
の代わりにfunc
を使用して 副作用なし であることを明確化することができる - しかし、これまでNimにおける 副作用なし の基準が緩く、直感と合わなかった
- v1.4.0以降は 副作用なし の基準を厳格化できる
情報元
Version 1.4.0 released
Write Tracking for Nim (Part 2)
これまでの仕様
- 単純なプロシージャ定義の例
proc add(a,b:int):int =
return a + b
echo add(1,2) # 3
-
{.noSideEffect.}
プラグマを使用して副作用がないことを明確化可能
proc add(a,b:int):int {.noSideEffect.}=
return a + b
echo add(1,2) # 3
-
proc
+{.noSideEffect.}
プラグマのシンタックスシュガーとしてfunc
を使用可
func add(a,b:int):int =
return a + b
echo add(1,2) # 3
- ただしオブジェクトの参照先の値を変えることは 副作用 に含まれていなかった。
# このコードは有効
type
Node = ref object
data: string
func setData(n:Node, newData:string) =
n.data = newData
let n0 = Node(data:"original")
echo n0.data # original
setData(n0,"changed")
echo n0.data # changed
新しい仕様(v1.4.0以降)
次のどちらかにより 副作用なし の仕様を厳格化可能
-
{.experimental: "strictFuncs".}
プラグマを使用 - コンパイル時に
--experimental:strictFuncs
オプションを使用
test.nim
# このコードはコンパイルできない
{.experimental: "strictFuncs".}
type
Node = ref object
data: string
func setData(n:Node, newData:string) =
n.data = newData
var n0 = Node(data:"original")
echo n0.data
setData(n0,"changed")
echo n0.data
- コンパイラエラーとして以下のメッセージが表示される
- これにより、
func
の挙動がより直感に合う形になり、関数に副作用がないことを明確化できる
test.nim(7, 6) Error: 'setData' can have side effects
an object reachable from 'n' is potentially mutated
test.nim(8, 4) the mutation is here
- パラメーターに
var
をつけることで、func
の中で意図した副作用を許容することもできる
# このコードは有効
{.experimental: "strictFuncs".}
type
Node = ref object
data: string
func setData(n:var Node, newData:string) =
n.data = newData
var n0 = Node(data:"original")
echo n0.data # original
setData(n0,"changed")
echo n0.data # changed
まとめ
- v1.4.0以降は 副作用なし の厳格化で
func
をより直感に合う形で使用できるようになった
Discussion