Issue #5454 has been updated by Yusuke E…
File keyword-argument-patch-20111023.zip added
Assignee changed from Yukihiro M. to Koichi Sasada
Hello,
I’ve updated the patch (keyword-argument-patch-20111023.zip).
It modifies the core much.
So I’d like to commit it after koichi’s review.
The rough strategy of the implementation is to interpret:
def foo(str: “foo”, num: 424242, **h)
…
end
as:
def foo(*r)
h = r.last.respond_to?(:to_hash) ? r.last.to_hash.dup : {}
str = h.key?(:str) ? h.delete(:str) : “foo”
num = h.key?(:num) ? h.delete(:num) : 424242
…
end
| - Do we need a way to receive all the keyword arguments?
|
| def foo(str: “foo”, num: 424242, **h)
| p h
| end
| foo(str: “bar”, check: true) #=> { :check => true }It would be necessary for delegating arguments to another method.
Done.
$ ./ruby -e ’
def foo(str: “foo”, num: 4242, **h)
p h
end
foo(str: “bar”, check: true)
’
{:check=>true}
| - When nil is passed explicitly, should the value be nil?
|
| def foo(str: “foo”)
| p str
| end
| foo(str: nil) #=> nil ? (not implemented yet, “foo” is assigned now)It should be nil.
Done.
$ ./ruby -e ’
def foo(str: “foo”, num: 4242)
p str
end
foo(str: nil)
’
nil
| - When unknown keyword is specified and there is no **rest,
| should we raise exception or warning?
|
| def foo(str: “foo”, num: 424242)
| end
| foo(check: true) #=> ArgumentError?There is a room for discussion. Currently I think it should raise an exception
unless receiving with **rest, but I may change my opinion after using it in
several situations in actual scripts.
Done.
$ ./ruby -e ’
def foo(str: “foo”, num: 4242)
end
foo(str: “bar”, check: true)
’
-e:5:in `': unknown keyword (TypeError)
| - Should we accept an object behaves like Hash as keyword arguments?
| (Current implementation only checks T_HASH for speed)Please use to_hash for now. Maybe we should define new method, something like
to_kw.
Done.
$ ./ruby -e ’
def foo(str: “foo”, num: 4242)
p str
end
h = Object.new
def h.to_hash; { str: “bar” }; end
foo(h)
’
“bar”
| )
I think this order is OK.
Thanks!
–
Yusuke E. [email protected]
Feature #5454: keyword arguments
Author: Yusuke E.
Status: Assigned
Priority: Normal
Assignee: Koichi Sasada
Category:
Target version: 2.0.0
遠藤です。
キーワード引数を実装してみました。
$ cat t.rb
def foo(str: “foo”, num: 424242)
p [str, num]
end
foo(str: “bar”)
$ ./ruby t.rb
[“bar”, 424242]
細かいことはまだ気にしていませんが、キーワード引数が 2.0 に入る
ことはかなり確定的なので、とりあえず trunk に入れて考えるという
のはどうでしょうか。
一応私の環境では make check は通ります (キーワード引数のテスト
は書いてないですが) 。パーサに conflict はないです。
既存のベンチマークを見ると、一部気になる項目もありますが (vm1_
rescue とか) 、全体的には特に速度劣化しないようです。
以下は未検討・未実装の細かいことです。
-
残りのキーワード引数を受け取る方法が必要?
def foo(str: “foo”, num: 424242, **h)
p h
end
foo(str: “bar”, check: true) #=> { :check => true } -
nil が渡されたらやはり nil になるべき?
def foo(str: “foo”)
p str
end
foo(str: nil) #=> nil ? (今は手抜きで “foo”) -
rest なしで知らないキーワードが来たら例外・警告を発して
欲しい?def foo(str: “foo”, num: 424242)
end
foo(check: true) #=> ArgumentError? -
Hash のように振る舞うオブジェクトもキーワード引数として
解釈すべき? (現在は速度重視で T_HASH だけ見ている) -
引数の順番はこれでよいか?
def foo(
a, b, c, # mandatory arguments
opt = 1, # optional arguments
*rest, # rest argument
x, y, z, # post mandatory arguments
k1: 1, k2:2, # keyword arguments
**kh, # keyword rest argument
&blk # block argument
) -
他いろいろ
benchmark results:
name ruby 1.9.4dev (2011-10-16 trunk 33471) [i686-linux] ruby
1.9.4dev (2011-10-16 trunk 33471) [i686-linux] average difference
app_answer 0.259 0.131 -0.127
app_erb 2.699 2.681 -0.018
app_factorial 5.236 5.320 0.084
app_fib 1.576 1.731 0.154
app_mandelbrot 4.324 3.911 -0.413
app_pentomino 40.882 40.768 -0.114
app_raise 0.966 0.982 0.017
app_strconcat 3.143 3.102 -0.041
app_tak 2.192 2.140 -0.052
app_tarai 1.682 1.748 0.066
app_uri 1.870 1.767 -0.103
io_file_create 2.589 2.570 -0.019
io_file_read 6.169 5.838 -0.330
io_file_write 1.966 1.976 0.010
io_select 3.066 3.111 0.044
io_select2 3.647 3.623 -0.025
io_select3 0.051 0.051 0.000
loop_for 3.302 3.219 -0.082
loop_generator 1.111 1.102 -0.009
loop_times 2.959 2.960 0.001
loop_whileloop 1.437 1.422 -0.016
loop_whileloop2 0.298 0.297 -0.001
so_ackermann 1.862 1.816 -0.046
so_array 3.317 3.473 0.155
so_binary_trees 0.891 0.900 0.009
so_concatenate 9.538 8.696 -0.842
so_count_words 0.412 0.407 -0.005
so_exception 2.185 2.177 -0.008
so_fannkuch 3.338 3.334 -0.004
so_fasta 5.182 5.061 -0.121
so_k_nucleotide 3.425 3.324 -0.101
so_lists 2.239 2.312 0.073
so_mandelbrot 11.479 10.660 -0.820
so_matrix 2.206 2.177 -0.030
so_meteor_contest 11.479 11.634 0.155
so_nbody 8.006 7.925 -0.081
so_nested_loop 2.768 2.614 -0.154
so_nsieve 6.163 6.184 0.021
so_nsieve_bits 6.618 6.850 0.231
so_object 1.807 1.899 0.091
so_partial_sums 11.057 10.537 -0.520
so_pidigits 2.944 3.011 0.066
so_random 1.962 1.992 0.031
so_reverse_complement 3.136 3.036 -0.099
so_sieve 2.224 2.203 -0.021
so_spectralnorm 7.981 7.591 -0.390
vm1_block* 3.790 5.112 1.306
vm1_const* 0.756 0.757 -0.015
vm1_ensure* 0.487 0.601 0.099
vm1_ivar* 1.634 1.863 0.213
vm1_ivar_set* 1.625 1.661 0.021
vm1_length* 1.312 1.366 0.038
vm1_neq* 1.152 0.979 -0.189
vm1_not* 0.589 0.589 -0.015
vm1_rescue* 0.133 0.750 0.601
vm1_simplereturn* 2.467 3.601 1.119
vm1_swap* 1.199 1.716 0.502
vm2_array* 1.644 1.643 -0.001
vm2_case* 0.324 0.348 0.023
vm2_defined_method* 8.829 9.003 0.173
vm2_eval* 39.557 37.726 -1.832
vm2_method* 5.255 4.113 -1.142
vm2_mutex* 3.043 3.175 0.131
vm2_poly_method* 6.044 5.340 -0.705
vm2_poly_method_ov* 0.493 0.675 0.181
vm2_proc* 1.297 1.391 0.093
vm2_regexp* 2.419 2.557 0.137
vm2_send* 0.662 0.903 0.241
vm2_super* 1.107 1.016 -0.093
vm2_unif1* 0.688 0.816 0.127
vm2_zsuper* 1.210 1.068 -0.143
vm3_clearmethodcache 0.785 0.770 -0.014
vm3_gc 2.487 2.453 -0.033
vm_thread_alive_check1 0.389 0.422 0.033
vm_thread_create_join 6.064 6.181 0.118
vm_thread_mutex1 2.349 2.546 0.197
vm_thread_mutex2 10.123 7.755 -2.368
vm_thread_mutex3 4.428 5.390 0.962
vm_thread_pass 0.692 0.754 0.063
vm_thread_pass_flood 0.167 0.170 0.003
vm_thread_pipe 2.437 2.540 0.103