削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
→‎for式がない?!: Crystal には、Ruby にはある for式がありません。
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎マクロ: Crystalには、Rubyにはないマクロがあります。Rubyは実行時にすべてのオブジェクトにアクセス出来て、メソッド生やし放題なのでマクロは必要ありませんが、Crystalはコンパイル時に型やmwソッドを確定する必要があり、特にメソッドジェネレターとしてのマクロにニーズがあります。また、テンプレート的な機能を持ったマクロなので、コンテナを渡し繰返し処理する構文もマクロにあります(面白いことにマクロには for 文があり、反対にマクロの中では、eachメソッドは使えません)。
タグ: 2017年版ソースエディター
147 行
end
</syntaxhighlight>
: の様にコレクションの each メソッドで置換え可能なので、Rubyからの移植でも小規模な書換えで済みます<ref>[https://github.com/crystal-lang/crystal/issues/830 "For" Loop support #830]</ref>(後述のマクロで実装できないかと思いましたが、いまのところ無理のようです)。
また loop 式もありませんが while true; … end で間に合います。Ruby では while 式の条件の次に do が置けますが、Crystal では置けません。
 
=== マクロ ===
Crystalには、Rubyにはないマクロがあります。Rubyは実行時にすべてのオブジェクトにアクセス出来て、メソッド生やし放題なのでマクロは必要ありませんが、Crystalはコンパイル時に型やmwソッドを確定する必要があり、特にメソッドジェネレターとしてのマクロにニーズがあります。また、テンプレート言語的なマクロなので、環境変数による条件分岐や、コンテナを渡し繰返し処理する構文もあります(面白いことにマクロには for 文があり、反対にマクロの中では、eachメソッドは使えません)。
 
;マクロを使ったattr_accessorのイミュレーション:<syntaxhighlight lang=crystal>
class Point
def initialize(@x : Int32, @y : Int32)
end
# macro定義
macro attr_accessor(*attrs)
{% for attr in attrs %}
def {{attr.id}}
@{{attr.id}}
end
def {{attr.id}}=(var)
@{{attr.id}} = var
end
{% end %}
end
# macro呼出し
attr_accessor :x, :y
end
pt = Point.new(20, 30)
p [pt.x, pt.y]
t = pt.x
pt.x = pt.y
pt.y = t
p [pt.x, pt.y]
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
[20, 30]
[30, 20]
</syntaxhighlight>
: Ruby には、attr_accessor と言う「クラスのメンバーのアクセサーを自動生成するメソッド」がありますが、Crystalにはないようなので、マクロで実装しました。
:: attr_accessor :name からは
::<syntaxhighlight lang=ruby>
def name
@name
end
def name=(val)
@name = val
end
</syntaxhighlight>相当のコードが生成されます。
[TODO:マクロの機能と構文の説明 *の付いた引数、 {{引数}}、{% … %} 構文]
 
== 脚註 ==