削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
→‎eval()がない: Crystal には eval() はありません。 Crystalはコンパイル型言語ですので、無理もないことです。 もし、Crystal で eval() を実装しようとすると、Common Lisp の様にインタープリターを丸ごとランタイムに含む必要があります。これはリーズナブルな選択ではありません。 Crystal では、eval() が必要なケースに(限定的ですが)マクロを使うことが出来る可能性があります。
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎マクロ p!: メソッド p は、与えられた「式」の inspaect() の返す値を puts しますが、マクロ p! は、それに先んじて(評価前の)「式」を表示します<ref>[https://crystal-lang.org/api/1.5.0/Crystal/Macros.html#p%21%28%2Aexpressions%29%3ANop-instance-method def p!(*expressions) : Nop]</ref>。
タグ: 2017年版ソースエディター
181 行
 
=== マクロ ===
Crystalには、Rubyにはないマクロがあります<ref>[https://crystal-lang.org/reference/1.5/syntax_and_semantics/macros/ Macros - Crystal]</ref>。Rubyは実行時にすべてのオブジェクトにアクセス出来て、メソッド生やし放題なのでマクロは必要ありませんが、Crystalはコンパイル時に型やメソッドを確定する必要があり、特にメソッドジェネレターとしてのマクロにニーズがあります。また、テンプレート言語的なマクロなので、環境変数による条件分岐や、コンテナを渡し繰返し処理する構文もあります(面白いことにマクロには for 文があり、反対にマクロの中では、eachメソッドは使えません)。マクロには <code><nowiki>{{</nowiki>attr.id}}</code> の様にASTへのアクセスする構文手順が用意されており、半ば言語を拡張するようなアプローチを取ることも出来ます。
 
[TODO:ASTについての解説;コラム向き?]
189 行
def initialize(@x : Int32, @y : Int32)
end
 
# macro定義
macro attr_accessor(*attrs)
197 行
{% end %}
end
 
# macro呼出し
attr_accessor :x, :y
end
 
pt = Point.new(20, 30)
p [pt.x, pt.y]
210 行
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
[20, 30]
[30, 20]
</syntaxhighlight>
220 行
</syntaxhighlight>相当のコードが生成されます。
[TODO:マクロの機能と構文の説明 *の付いた引数、 <nowiki>{{</nowiki>引数}}、{% … %} 構文]
 
==== マクロ p! ====
メソッド p は、与えられた「式」の inspaect() の返す値を puts しますが、マクロ p! は、それに先んじて(評価前の)「式」を表示します<ref>[https://crystal-lang.org/api/1.5.0/Crystal/Macros.html#p%21%28%2Aexpressions%29%3ANop-instance-method def p!(*expressions) : Nop]</ref>。
;p!の例:<syntaxhighlight lang=crystal>
x, y = true, false
 
p! x,y,x && y, x || y, x ^ y, !x, x != y, x == y
 
ary = [ 1, 2, 3 ]
 
p! ary
 
p! ary.map(&. << 1)
 
p! ary.map(&.to_f)
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
x # => true
y # => false
x && y # => false
x || y # => true
x ^ y # => true
!x # => false
x != y # => true
x == y # => false
ary # => [1, 2, 3]
ary.map(&.<<(1)) # => [2, 4, 6]
ary.map(&.to_f) # => [1.0, 2.0, 3.0]
</syntaxhighlight>
 
=== ユーザー定義クラス ===