def fun(*args)
........
end
args 是一个数组,请问这是怎么实现的?
貌似和楼上的指引没啥关系,指引指的是 Native 方法的处理,参数个数限制在 -2- 15 个。
Ruby 处理很简单,在 c 里面已经将参数整理成 VALUE*argv
了,这个 VALUE 的类型就是 Array,传多少个都没有问题。
和@luikore差不多的意思
C 中的 main 是这样的
int main(int argc, char *argv[]);
argc 是参数个数,argv 指向字符串数组,这里是把调用程序的名称也算进来的 例如 $ls 这个命令的 argc=1,argv[0] = "ls"
C~~是弱类型的语言,所以~~使用指针指向复杂的结构体,用来表达不同的类型。 在 C 语言眼里,万物都是数字,一个指针指向一块内存地址,代表各种可能,好单纯的语言。 结构体类似于面向对象编程语言中的对象。
可以看 ruby 里很多核心类的 C 实现,例如 Fixnum#to_s
static VALUE
fix_to_s(int argc, VALUE *argv, VALUE x)
{
int base;
if (argc == 0) base = 10;
else {
VALUE b;
rb_scan_args(argc, argv, "01", &b);
base = NUM2INT(b);
}
return rb_fix2str(x, base);
}
这里的 VALUE 可以看作代表 ruby 中的各种类型的结构体,argv 可以看作指向 VALUE 的数组,根据 argc 的值不同做处理就可以实现可变参数,默认参数值等功能。
同@ruohanc问,为何这也精华帖了
edit at 2014-03-02 @rasefon 强弱类型的说法的确有很多误解,不如说是可以使用指针来干“坏事”的静态类型语言 http://stackoverflow.com/questions/430182/is-c-strongly-typed
C is a language that is statically typed but that has a lot of loopholes. One loophole is that you can freely cast any pointer type to any other pointer type.
这个应该在 Lexical Analysis 时得到的,看一下 parse.y 这里对于参数的处理
f_arg : f_arg_item
/*%c%*/
/*%c
{
$$ = rb_ary_new3(1, $1);
}
c%*/
| f_arg ',' f_arg_item
{
/*%%%*/
$$ = $1;
$$->nd_plen++;
$$->nd_next = block_append($$->nd_next, $3->nd_next);
rb_gc_force_recycle((VALUE)$3);
/*%
$$ = rb_ary_push($1, $3);
%*/
}
;
不管什么参数都是往 rb_ary 里扔。
C 语言本来就可以实现可变参数,比如 printf、scanf 之类的函数,参考这几个宏:va_arg, va_list, va_start, va_end
这也精华帖,是管理员手抖了么。。
比如 https://github.com/bhuztez/deepthought-ruby/blob/master/lib/deepthought.rb#L180
Ruby 的中间变量打出来完全没法看。数括号数到眼花,果然 Ruby 有 LISP 风范