Slide 1

Slide 1 text

Yuichiro Kaneko Crystal × macro

Slide 2

Slide 2 text

ࣗݾ঺հ • @yui-knk (github) / @spikeolaf (twitter) • docrails commiter

Slide 3

Slide 3 text

RailsΨΠυ຋༁νʔϜ

Slide 4

Slide 4 text

Crystal ͷੈքͰ͸

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

0.7.5 release!!

Slide 7

Slide 7 text

ϚΫϩ?? • Macros are methods that receive AST nodes at compile-time and produce code that is pasted into a program. • ίϯύΠϧ࣌ʹɺASTϊʔυΛ͏͚ͱͬͯɺ ίʔυΛฦ͢Α͏ͳϝιουɻ • http://crystal-lang.org/docs/syntax_and_semantics/macros.html

Slide 8

Slide 8 text

Example.1 # ϚΫϩΛఆٛ͢Δ macro define_method(name, content) def {{name.id}} {{content}} end end ! # ϚΫϩΛల։͢Δ define_method :foo, 1 # def foo # 1 # end ! # ϝιουΛݺͼग़͢ foo # => 1

Slide 9

Slide 9 text

Example.2 (for) # ϚΫϩΛఆٛ͢Δ macro define_dummy_methods(names) {% for name, index in names %} def {{name.id}} {{index}} end {% end %} end ! # ϚΫϩΛల։͢Δ define_dummy_methods [foo, bar, baz] # def foo # 0 # end # … ! foo # => 0 bar # => 1 baz # => 2

Slide 10

Slide 10 text

Example.3 (yield) # ϚΫϩΛఆٛ͢Δ macro test_with p "before" {{yield}} p "after" end ! # ϚΫϩΛల։͢Δ test_with do p "in block" end # p "before" # p "in block" # p "after"

Slide 11

Slide 11 text

ϚΫϩ?? • Macros are methods that receive AST nodes at compile-time and produce code that is pasted into a program. • ίϯύΠϧ࣌ʹɺASTϊʔυΛ͏͚ͱͬͯɺ ίʔυΛฦ͢Α͏ͳϝιουɻ • http://crystal-lang.org/docs/syntax_and_semantics/macros.html

Slide 12

Slide 12 text

Example.4 # ϚΫϩΛఆٛ͢Δ macro test_print {{p "before"}} {{yield}} {{p "after"}} end ! # ϚΫϩΛల։͢Δ test_print do p "in block" end # “before" (printed) # “after" (printed) # # p "in block" # ϚΫϩల։࣌ʹQSJOUͯ͠OJMΛฦ͢

Slide 13

Slide 13 text

ϚΫϩ?? • Macros are methods that receive AST nodes at compile-time and produce code that is pasted into a program. • ίϯύΠϧ࣌ʹɺASTϊʔυΛ͏͚ͱͬͯɺ ίʔυΛฦ͢Α͏ͳϝιουɻ • http://crystal-lang.org/docs/syntax_and_semantics/macros.html

Slide 14

Slide 14 text

Example.5 (StringLiteral) # ͜Ε͸ok {{"hoge".upcase}} # "HOGE" ! # ͜Ε͸ok "1".to_i # =>1 ! # ͜Ε͸ng {{"1".to_i}} ! Error in test.cr:1: expanding macro ! {{"1".to_i}} ^ ! in test.cr:1: undefined macro method 'StringLiteral#to_i' ! {{"1".to_i}} ^~~~

Slide 15

Slide 15 text

Example.6 (#class_name) from 0.7.5 macro print_class_names(*nodes) {% for node in nodes %} {{p node.class_name}} {% end %} end ! print_class_names(“1") # “StringLiteral" print_class_names([1]) # “ArrayLiteral" print_class_names({a: 10}) # “HashLiteral" print_class_names(foo) # “Call" print_class_names(true ? 1 : 0) # “If"

Slide 16

Slide 16 text

Example.6 (#class_name) from 0.7.5 print_class_names( if true 1 else 0 end ) # “If" print_class_names( class Foo end ) # “ClassDef" print_class_names( def test_method end ) # “Def"

Slide 17

Slide 17 text

Example.6 (#class_name) from 0.7.5 print_class_names( if true 1 else 0 end, class MyClass end ) # “If" # “ClassDef"

Slide 18

Slide 18 text

http://crystal-lang.org/api/ index.html

Slide 19

Slide 19 text

Example.7 (my_unless) macro my_unless(cond, then_exp, else_exp = nil) if {{ cond }} {{ else_exp }} else {{ then_exp }} end end ! def ten?(a) a == 10 end ! my_unless( ten?(11), p("false case"), p("true case") ) # "false case"

Slide 20

Slide 20 text

Example.8 (visibility) class MyClass def public_method end ! protected def protected_method end ! private def private_method end ! {% for m in @type.methods %} {{p m.name}} {{p m.visibility}} {% end %} end # public_method # :public # protected_method # :protected # private_method # :private

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

·ͱΊ • ruby like syntaxͰcompilerͱ͔ಡΊΔ • macro def ͱ͔ @type ͷ͜ͱௐ΂͍ͨ • ASTNodeͷprinter΄͍͠ • ύʔαδΣωϨʔλʔɾɾɾ