テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(nim report) templateによるメタプログラミング

nim-fuseを美しく設計するにあたって, コードの重複を省くことを求められている. そこで簡単な実験をしてみる.

Nimを始めとして, 最近の言語は, メタプログラミングへのサポートを重視している. Rustもメタプログラミングが楽しい言語だ.
Go?なんですかそれは. グーグルが作ったからDockerが使ってるからみんなが使ってるから簡単だから流行るからという理由で使ったら, 骨がなくなる. Rain(ピ)なんて歌手もいたから, Go(ミ)というのもありだろう.

Anyway, 以下のコードは, templateを使って, コード生成をしている. 内包したオブジェクトに処理を転送するだけのラッパーを生成しているだけだが, 有益なものだ. typeを作る時には, injectが必要らしい. これなしではコンパイル出来ない.

ちなみにもう一つのmacroではASTをいじくり回すことが出来る. 基本的にはpycparserによるAST書き換えと同じようなものなので, 私のmacro-of-inline実装を追いかけていた読者ならば容易に理解出来る.

type T = ref object
proc exec(t: T, x: int, y: string): char =
  y[x]

template defWrapper(typ: typedesc) =
  type `Wrap typ` {. inject .} = ref object
    t: `typ`
  proc `exec`(self: `Wrap typ`, x: int, y: string): char =
    self.t.exec(x, y)

defWrapper(T)

if isMainModule:
  let t = T()
  echo t.exec(0, "akira") # 'a'
  echo t.exec(1, "akira") # 'k'

  let w = WrapT (t: T())
  echo w.exec(0, "akira") # 'a'
  echo w.exec(1, "akira") # 'k'