コンテンツにスキップ

フレッシュ変数

マクロがコードを生成した後、それらは通常の Crystal パーサーで解析されます。そこで、マクロ呼び出しのコンテキストにおけるローカル変数は定義済みであるとみなされます。

これは例で理解しやすいでしょう。

macro update_x
  x = 1
end

x = 0
update_x
x # => 1

これは、意図的にローカル変数を読み書きすることでコードの繰り返しを避けるのに役立つことがありますが、誤ってローカル変数を上書きしてしまう可能性もあります。これを避けるために、フレッシュ変数を `%name` で宣言できます。

macro dont_update_x
  %x = 1
  puts %x
end

x = 0
dont_update_x # outputs 1
x             # => 0

上記の例で `%x` を使用することにより、現在のスコープ内のローカル変数と競合しないことが保証された名前の変数を宣言しています。

さらに、他の AST ノードに関するフレッシュ変数は、`%var{key1, key2, ..., keyN}` で宣言できます。例えば、

macro fresh_vars_sample(*names)
  # First declare vars
  {% for name, index in names %}
    print "Declaring: ", stringify(%name{index}), '\n'
    %name{index} = {{index}}
  {% end %}

  # Then print them
  {% for name, index in names %}
    print stringify(%name{index}), ": ", %name{index}, '\n'
  {% end %}
end

macro stringify(var)
  {{ var.stringify }}
end

fresh_vars_sample a, b, c

# Sample output:
# Declaring: __temp_255
# Declaring: __temp_256
# Declaring: __temp_257
# __temp_255: 0
# __temp_256: 1
# __temp_257: 2

上記の例では、3つのインデックス付き変数が宣言され、値が代入され、そして出力されます。それぞれの対応するインデックスが表示されます。