跳至內容

全新變數

一旦巨集產生程式碼,它們會由常規的 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,我們宣告一個保證其名稱不會與目前範圍內的區域變數衝突的變數。

此外,可以使用 %var{key1, key2, ..., keyN} 宣告相對於其他 AST 節點的全新變數。例如

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

在上面的範例中,宣告了三個索引變數,並賦予了值,然後列印出來,顯示它們對應的索引。