Méthodes de macro

Les définitions de macro vous permettent de définir une méthode pour une hiérarchie de classe qui est ensuite instantiée pour chaque sous-type concret.

Un def est implicitement considéré comme une macro def s'il contient une expression macro faisant référence à @type. Par exemple:

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"]

Vous pouvez aussi rendre cela explicite en écrivant macro def, bien que cela puisse disparaître dans le futur:

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

Dans les définitions de macro, les arguments sont passés comme leurs noeuds AST, vous y donnant accès dans les expansions de macro ({{some_macro_argument}}). Néanmoins ceci est faux pour les définitions de macro. Ici la liste d'arguments est celle de la méthode générée par la définition de macro. Vous ne pouvez accéder à leur valeur à la compilation.

class Object
  def has_instance_var?(name) : Bool
    # Nous ne pouvons accéder au nom dans l'expansion de la macro ici,
    # à la place nous avons besoin d'utiliser le langage de macro pour construire un array
    # et faire la vérification d'inclusion à l'exécution.
    {{ @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

results matching ""

    No results matching ""