From: Yusuke ENDOH Date: 2008-01-30T00:13:58+09:00 Subject: [ruby-dev:33509] Re: HashからStructを作る 遠藤と申します。 08/01/29 に rubikitch@ruby-lang.org さんは書きました: > From: Yukihiro Matsumoto > Subject: [ruby-dev:33507] Re: HashからStructを作る > Date: Tue, 29 Jan 2008 23:34:17 +0900 > > > 「Struct.new(:a => 1)」で「Struct.new(:a).new(1)」の意味なん > > ですね。プログラムにちゃんとそう書いてあるのに。 > > > > ま、それは私の間違いなんで置いといて、そうすると、インスタン > > スがひとつしかないStructを毎回作ることになりますね。それって > > どれだけうれしいんですかね。外から見る限り、単なるHashと大差 > > ないような。もちろん多少メモリ効率は違いますが、それ意外に特 > > にうれしいことはなさそうな上に、生成するのにHashひとつ、イン > > スタンスごとに無名クラスひとつ作っちゃうのでそこまでメモリ効 > > 率もよくはないような。 > > やっぱり st.a のようにアクセサでアクセスできることです。 > アクセサの方がオブジェクト指向している感じだし、 > メンバ名の打ち間違いをしようものならエラーを投げてくれるので使う方としては > とても嬉しいです。 とても共感したので実装してみました。 $ ./ruby -e 'p Struct.new(:a => 1, :b => 2, :c => 3)' # 議論のたたき台になれば幸いです。 Index: struct.c =================================================================== --- struct.c (revision 15331) +++ struct.c (working copy) @@ -281,6 +281,13 @@ return make_struct(nm, ary, rb_cStruct); } +static int +keyvalue_i(VALUE key, VALUE value, void *ptr) { + VALUE *arg = (VALUE*) ptr; + rb_ary_push(arg[0], key); + rb_ary_push(arg[1], value); +} + /* * call-seq: * Struct.new( [aString] [, aSym]+> ) => StructClass @@ -318,12 +325,19 @@ static VALUE rb_struct_s_def(int argc, VALUE *argv, VALUE klass) { - VALUE name, rest; + VALUE name, rest, values = Qfalse; long i; VALUE st; ID id; - rb_scan_args(argc, argv, "1*", &name, &rest); + if (rb_scan_args(argc, argv, "1*", &name, &rest) == 1 && TYPE(name) == T_HASH) { + VALUE arg[2]; + rest = arg[0] = rb_ary_new(); + values = arg[1] = rb_ary_new(); + rb_hash_foreach(name, keyvalue_i, (VALUE)&arg); + name = Qnil; + } + for (i=0; i