Flat Leon Works

アプリやゲームを作ってます。

【Nim】無名プロシージャの書き方まとめ

この記事は「Nim Advent Calendar 2021」の24日目の記事として登録させてもらっています。

無名プロシージャの書き方

無名プロシージャ(Anonymous Procs)は書き方がいくつかあり少し混乱したのでまとめてみました。

基本形

まずは、普通の書き方。

var p = proc( x:int ): int = return x + 1

returnを省略

returnは省略できます。(これは通常のプロシージャでも同じ)

var p2 = proc( x:int ): int = x + 1

仮引数を省略(無い場合)

仮引数が無い場合、省略できます。(これも通常のプロシージャと同じ)

var p2 = proc: int = 1

戻り値型を省略(無い場合)

戻り値が無い場合、戻り値型を省略できます。(これも通常のプロシージャと同じ)

var p2 = proc = echo "aaa"

procと戻り値型を省略(=>記法を使う)

ドキュメント:
`=>`

=>記法を使うことで、procと戻り値型を省略することができます。

=>記法を使うにはstd/sugarをインポートする必要があります。

import std/sugar

var p3 = (x: int) => x + 1

また、=>記法をプロシージャの引数で使う場合は、引数の型名を省略できるようです。

proc echoF( f: proc(x: int): int ) =
  echo f(0)

echoF (x: int) => x * 2 # 引数の型を記述
echoF (x) => x * 2 # 引数の型を省略

do記法を使う(引数でのみ使用可能)

ドキュメント:
Do notation

引数で無名プロシージャを書く場合のみdo記法を使うことができます。

do記法を使うには、{.experimental.}プラグマが必要です。

{.experimental.}

proc echoF( value: int, f: proc(x: int): int ) =
  echo f(value)
  
echoF( 10 ) do ( x: int ) -> int: x * 2

do記法で記述した無名プロシージャは直前のプロシージャ呼び出しの引数として追加されます。

echoF( 10 ) do ( x: int ) -> int: x * 2
echoF( 10, proc( x: int ): int = x * 2 ) # do記法を使わない場合

do記法は連続させることができます。連続させた分、引数として追加されます。

proc echoF2( value: int, f: proc(x: int): int, f2: proc(x: int): int ) =
  echo f(value)
  echo f2(value)
  
echoF2( 10 ) do ( x: int ) -> int:
  x * 2
do ( x: int ) -> int:
  x * 3

まとめ

var f1 = proc(x: int): int = x * 2 # 変数f1に無名プロシージャを格納
var f2 = (x: int) => x * 2 # 変数f2に無名プロシージャを格納
hoge do (x: int) -> int: x * 2 # プロシージャhogeの引数に無名プロシージャを渡す

使い分け

無名プロシージャはproc記法、=>記法、do記法と大きく分けて3つの書き方がありますが、これらの使い分けは以下のような感じでしょうか。*1

  • 無名プロシージャを変数に格納する場合 : =>記法
  • 無名プロシージャを1引数のプロシージャに渡す場合 : =>記法
  • 無名プロシージャを2引数以上のプロシージャに渡す場合 : do記法
  • 無名プロシージャの戻り値型を明示的に記述したい場合 : do記法
  • import std/sugar{.experimental.}を記述するのが面倒な場合 : proc記法

(おまけ)プロシージャ型の書き方

プロシージャ型とは、プロシージャを変数や引数として受け取るときの型のことです。

基本形

var f: proc(x: int): int # int型引数を1つとり、int型を返すプロシージャ

->記法を使う

ドキュメント:
`->`

import std/sugar

var f: (x: int) -> int
var f2: (int) -> int # ->記法では仮引数名を省略可能

->は無名プロシージャを記述するときのdo記法でも使うので混同しないように注意しましょう。

*1:まだ無名プロシージャをあまり使ったことがないので、的はずれなことを書いてるかもしれません。