Macros: Macro methods

Macro methods

Macro defs allow you to define a method for a class hierarchy which is then instantiated for each concrete subtype.

A def is implicitly considered a macro def if it contains a macro expression which refers to @type. For example:

class Object
  def instance_vars_names
    {{ @type.instance_vars.map &.name.stringify }}
  end
end

class Person
  def initialize(@name : String, @age : Int32)
  end
end

person = Person.new "John", 30
person.instance_vars_names #=> ["name", "age"]

You can also make this explicit by writing macro def, though this might be removed in the future:

class Object
  macro def instance_vars_names
    {{ @type.instance_vars.map &.name.stringify }}
  end
end

In macro definitions, arguments are passed as their AST nodes, giving you access to them in macro expansions ({{some_macro_argument}}). However that is not true for macro defs. Here the argument list is that of the method generated by the macro def. You cannot access their compile-time value.

class Object
  def has_instance_var?(name) : Bool
    # We cannot access name inside the macro expansion here,
    # instead we need to use the macro language to construct an array
    # and do the inclusion check at runtime.
    {{ @type.instance_vars.map &.name.stringify }}.includes? name
  end
end

person = Person.new "John", 30
person.has_instance_var?("name") #=> true
person.has_instance_var?("birthday") #=> false

To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/docs/syntax_and_semantics/macros/macro_methods.html

在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号

意见反馈
返回顶部