åå§çRubyå ¥é2åç®Fizzbuzzã®å
一昨日ã®ã¤ã¥ããã
ããªãã ã®Hello Worldããããã°ã©ãã³ã°è¨èªãå¦ã¶ããã®åå¼ã§ãããªãã°ãæè¿ã®ããã°ã©ãã³ã°è¨èªã®å¦ç¿ã§ããã§ãæ¸ãã¨ãçãªåé¡ã¨ãã¦FizzBuzzåé¡ã¨ããã®ãããã
1ãã100ã¾ã§ã®æ°åã§ã3ã®åæ°ã®ã¨ãã¯ã¢ãã«ãªãFizzã¨ã5ã®åæ°ã®ã¨ãã¯Buzzã¨ã15ã®åæ°ã¯FizzBuzzã¨ããã®ä»ã®æ°åã¯æ°åããã®ã¾ã¾è¡¨ç¤ºããã¨ããåé¡ã
ã¾ããRubyã¨ããã®ã¯Cã®ç®ããã¶ã£ãLispãªã®ã§ãLisp脳ãããã1ãã100ã¾ã§ã®é åãä½ããRubyã§ã¯
[1,2,3,....,99,100]
ã®ããã«ãé åã®ãªãã¸ã§ã¯ããçæããç°¡åãªè¨æ³ãåå¨ããã®ã ãããã¡ãã¡100ã¾ã§æ¸ãã®ã¯é¢åãªã®ã§ãRangeãªãã¸ã§ã¯ãã¨ããã®ã使ããããããé åã¯ã©ã¹ãçæããã
Rangeãªãã¸ã§ã¯ãã¨ããã®ã¯ãæå®ããç¯å²ã表ããªãã¸ã§ã¯ãã§ãããRangeãªãã¸ã§ã¯ããé åã¨åãã§ã
(1..100)
ã®ããã«ç°¡åã«çæã§ããããã®ãªãã¸ã§ã¯ãããã¤to_aã¡ã½ããã使ãã¨ããã®ç¯å²ãè¦ç´ ã¨ãã¤é åãä½ãããããããªããã
VALUE ary = rb_funcall(rb_eval_string("(1..100)"),rb_intern("to_a"),0);
rb_eval_string()ã¨ããã®ã¯ããã¾ããªãã§ã¯ãªããé¬éè¡ã§ãããããããã¨ç価交æã§ä¾¿å©ããå¾ããã¨ãã§ããã
ãã®é åã®ããããã®è¦ç´ ã«å¯¾ãã3,5,15ã®åæ°ãã©ãããå¤æãã¦ãæå®ãããæåã表示ããã°ããã
Javaãªã©ã§ã¯ãé åã®è¦ç´ ããã¹ã¦åãã«ã¯ãforæçã§é åã®é·ããã¿ãªããã¾ããã¦ããããRubyã§ã¯ãã¤ãã¬ã¼ã¿ã¼ã¨ãã便å©ãªç©ããããé åã®æã¤ã¤ãã¬ã¼ã¿ã¼ã¨ãã¦ã代表çãªã®ãeachã¡ã½ããã§ãããeachã¡ã½ããã¯ãé åã®è¦ç´ ãã¹ã¦ã«å¯¾ãããããã¯ã¨å¼ã°ããç©ã«è¦ç´ ããããã¦ãå®è¡ãã¦ããããããã¯ã¨ããã®ã¯ãç°¡åã«è¨ãã¨ãä¸æçãªé¢æ°ã¨æã£ã¦ããã¦ããã
ã¨ããããã§ãæ¦ç¥ã¨ãã¦ãããã¯å ã§ã表示ããæåãå¤å¥ã表示ããã¨ããæ¦ç¥ãã¨ãã
ã§ã¯ãä»å使ç¨ãããããã¯ãè¦ã¦ã¿ããã
VALUE fizzbuzz( VALUE elem, VALUE nil) { int mod = rb_intern("%"); int eql = rb_intern("=="); int puts = rb_intern("puts"); int kuku = rb_intern("<<"); int length = rb_intern("length"); int to_s = rb_intern("to_s"); VALUE str_buff = rb_str_new2(""); if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(3)),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_str_new2("Fizz")); if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(5)),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_str_new2("Buzz")); if (rb_funcall(rb_funcall(elem,length,0),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_funcall(elem,to_s,0)); return rb_funcall($kernel,puts,1,str_buff); }
ãããã¯ã¯ããªãã¸ã§ã¯ããããã£ã¦ããªãã¸ã§ã¯ããè¿ãé¢æ°ã®ãããªãã®ã§ããã
ã¾ãã¯ã復ç¿ãrb_funcallã¨ããã®ã¯ã第ä¸å¼æ°ã®ãªãã¸ã§ã¯ãã«å¯¾ãã第äºå¼æ°ã®ã¡ãã»ã¼ã¸ããã³ã ããã¨ããå½ä»¤ã§ãããRubyã§ã¯ãrb_funcallã§ã¡ã½ããå¼ã³åºããè¡ãã¨ããªãã¸ã§ã¯ããè¿ã£ã¦ããããããã大æµãããè¿ã£ã¦ããã¨ãããããªã¨ãããªãã¸ã§ã¯ããè¿ã£ã¦ãããããããã流れるようなインターフェースã¨ããæèããªãã¦ãã¹ãã¬ã¹ç¡ãæ¸ããã
æå¾ã®returnã®é¨åã§åºã¦ãã$kernelã¨ããã®ã¯ãã°ãã¼ãã«å¤æ°ã§ãããRubyã§ã¯ãã°ãã¼ãã«å¤æ°ã¯ã$ããã¯ãã¾ããã¨ã«ãªããä»åã¯ã$kernelã¨ããã°ãã¼ãã«å¤æ°ã«Objectã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ãçæãã¦ãã(å¥ã®ç®æã ãã©)ã
å¦çã®æµãã説æããã¨ã空ã®æååãç¨æãã渡ãããè¦ç´ (elem)ã3ã®åæ°ãªãããã¡ã½ãã(<<)ã使ããæååã«"Fizz"ã追å ã次ã«5ã®åæ°ãªã"Buzz"ã追å ãæå¾ã«æååã®é·ãã0ãªããè¦ç´ ãæååã«ãªããã(to_sã¡ã½ããã使ã)ãã®ãæååã«è¿½å ã
ãã¦ãããããeachã«ä»ä½ã£ããããã¯(fizzbuzz)ããããã¦å¼ã³åºãã¦ã¿ããã
rb_iterate(rb_each,ary,fizzbuzz,Qnil);
ã¡ã½ããå¼ã³åºãã®æã¯ããªãã¸ã§ã¯ããã¡ã½ããã®é ã§ãã£ãããã¤ãã¬ã¼ã¿ã¼ã¡ã½ããå¼ã³åºãã®æã¯ãã¤ãã¬ã¼ã¿ã¼ã¡ã½ããããªãã¸ã§ã¯ãããããã¯ã®é ã«ãªãã®ã§æ³¨æããªãã¸ã§ã¯ãã«å¯¾ããã¤ãã¬ã¼ã¿ã¼ã¡ã½ãããå¼ã³åºããã¤ãã¬ã¼ã¿ã¼ã¡ã½ããå ã®ç¹å®ã®ã¿ã¤ãã³ã°(ä»ã¯å ¨ç¶ããããªãã¦ãã)ã§ãè¦ç´ ãå¼æ°ã«ãã¦ãããã¯ãå®è¡ããããã¨ã«ãªãã(å®ã¯ã第åå¼æ°ãããããããã ããä»ã¯èããªãã¦ãã)ã
ã§ã¯ãä»åã®ããã°ã©ã å ¨ä½ãä»åãOMAZINAIãã£ã±ãã
#include "ruby.h" VALUE $kernel ; VALUE fizzbuzz( VALUE elem, VALUE nil) { int mod = rb_intern("%"); int eql = rb_intern("=="); int puts = rb_intern("puts"); int kuku = rb_intern("<<"); int length = rb_intern("length"); int to_s = rb_intern("to_s"); VALUE str_buff = rb_str_new2(""); if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(3)),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_str_new2("Fizz")); if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(5)),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_str_new2("Buzz")); if (rb_funcall(rb_funcall(elem,length,0),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_funcall(elem,to_s,0)); return rb_funcall($kernel,puts,1,str_buff); } int main() { VALUE ary; ruby_init(); ruby_init_loadpath(); ruby_script("hello_ruby"); $kernel = rb_class_new_instance(0,0,rb_cObject); ary = rb_funcall(rb_eval_string("(1..100)"),rb_intern("to_a"),0); rb_iterate(rb_each,ary,fizzbuzz,Qnil); ruby_finalize(); return 0; }
ã§ã¯ãå®è¡ã
$ gcc -o fizzbuzz -I./ruby-1.8.6-p114/ -g -L./ruby-1.8.6-p114/ -lruby -ldl fizzbuz.c && ./fizzbuzz (eval): [BUG] Bus Error ruby 1.8.6 (2007-09-24) [universal-darwin9.0] Abort trap
ãã£ã¨ãRubyãã©ãããè½ã¡ãããã ãããã°ã©ã ã«ã¯ãã°ãã¤ããã®ãªã®ã§ãæ°ã¯è½ã¨ããã«ãããã°ãã¦ãããã
Rubyã«ã¯ãã¡ããã¨ãããã¬ã¼ãã¤ãã¦ããã®ã§å®å¿ã ãã·ã§ã«ã§æ¬¡ã®ããã«å ¥åã ã
$ gdb ./fizzbuzz
ãããããã¨ãããã以ä¸ã®ããã«ããã°ã©ã ãå®è¡ãã¦ã¿ããã
(gdb) run Starting program: /Users/taka/prog/c/hello_ruby/fizzbuzz Reading symbols for shared libraries +++. done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000048 0x000d0c98 in rb_iterate ()
ã©ããããã¤ãã¬ã¼ã¿ã¼ãå®è¡ãã¦ãã延é·ã§è½ã¡ã¦ããã£ã½ãããããªã¨ãã¯ã大æµãããã¯å ã®å®è£ ãæªãã®ã§ããããã¯ã«ãã¬ã¼ã¯ãã¤ã³ãããã¦ããã¦ããä¸åº¦å®è¡ã ã
(gdb) b fizzbuzz Breakpoint 1 at 0x1cd1: file fizzbuz.c, line 8. (gdb) run Starting program: /Users/taka/prog/c/hello_ruby/fizzbuzz Breakpoint 1, fizzbuzz (elem=3, nil=4) at fizzbuz.c:8 8 int mod = rb_intern("%"); (gdb) n 9 int eql = rb_intern("=="); (gdb) n 10 int puts = rb_intern("puts"); (gdb) n 11 int kuku = rb_intern("<<"); (gdb) n 12 int length = rb_intern("length"); (gdb) n 13 int to_s = rb_intern("to_s"); (gdb) n 14 VALUE str_buff = rb_str_new2(""); (gdb) n 16 if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(3)),eql,1,INT2NUM(0))) (gdb) n 19 if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(5)),eql,1,INT2NUM(0))) (gdb) n 22 if (rb_funcall(rb_funcall(elem,length,0),eql,1,INT2NUM(0))) (gdb) n 0x000de055 in rb_thread_trap_eval () (gdb)
ã©ããããæååã®é·ããæ¯è¼ãããã¨ããã¨ãããæªããããããã¼ãã
ãã£ã¨ãæååã®lengthã¡ã½ãããå¼ã³åºããã¨ãã¦ããã®ã«ãé åã®è¦ç´ ã®ãªãã¸ã§ã¯ãã«å¯¾ãã¦lengthã¡ã½ãããå¼ã³åºãã¦ãããããªãããã¨ããããã§ããããªæãã§ä¿®æ£ã
: diff -bup bug.fizzbuz.c fizzbuz.c --- bug.fizzbuz.c 2008-04-18 00:25:57.000000000 +0900 +++ fizzbuz.c 2008-04-18 00:31:20.000000000 +0900 @@ -19,7 +19,7 @@ fizzbuzz( VALUE elem, VALUE nil) if (rb_funcall(rb_funcall(elem,mod,1,INT2NUM(5)),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_str_new2("Buzz")); - if (rb_funcall(rb_funcall(elem,length,0),eql,1,INT2NUM(0))) + if (rb_funcall(rb_funcall(str_buff,length,0),eql,1,INT2NUM(0))) rb_funcall(str_buff,kuku,1,rb_funcall(elem,to_s,0)); return rb_funcall($kernel,puts,1,str_buff);
ãããå®è¡ãã¦ã¿ãããé·ãã®ã§æ¹è¡ã¯ãã³ã³ãã«ç½®ãæãã¦ã®ãããã
$ gcc -o fizzbuzz -I./ruby-1.8.6-p114/ -g -L./ruby-1.8.6-p114/ -lruby -ldl fizzbuz.c && ./fizzbuzz 1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz,16,...,97,98,Fizz,Buzz
ä»åã¯é·ããªã£ã¦ãã¾ã£ããã©ãã ããããã ãããã
ã¤ãã¬ã¼ã¿ã¼ããããã¯ã¨ããã®ã¯ãRubyã§ã¯ãã使ããã便å©ãªãã®ãªã®ã§ããã復ç¿ãã¦ãããã
çµããã«ï¼ã©ãèãã¦ãåºãªãã®ãã¿ãå¼ã£å¼µãã®ã¯ããã©ãããã ãJKãä»åã®åç©«ã¨ãã¦ã¯ãèªåãããããã£ã¦ãªãã£ãã¤ãã¬ã¼ã¿ã¼ã®å¼ã³åºãããç°¡åã«ã¨ã¯ããç解ã§ãããã¨ã ããã