ruby049源码解读之array.c文件
昨天半夜睡不着,就起床写了一博文,写完后,继续睡觉。感觉还是有些迷糊。晚上还是要好好睡才是。
今天我接着说说array.c文件。我是在linux下读程序,但写文字还是在windows下。那个ubuntu下五笔输入法没弄好。
这个程序中最末尾是
Init_Array()
{
C_Array = rb_define_class("Array", C_Object);
rb_include_module(C_Array, M_Enumerable);
rb_define_single_method(C_Array, "new", Fary_new, 0);
rb_define_method(C_Array, "to_s", Fary_to_s, 0);
rb_define_method(C_Array, "_inspect", Fary_inspect, 0);
rb_define_method(C_Array, "to_a", Fary_to_a, 0);
rb_define_method(C_Array, "[]", Fary_aref, -2);
rb_define_method(C_Array, "[]=", Fary_aset, -2);
rb_define_method(C_Array, "<<", Fary_append, 1);
rb_define_method(C_Array, "push", Fary_push, 1);
rb_define_method(C_Array, "pop", Fary_pop, 0);
rb_define_method(C_Array, "shift", Fary_shift, 0);
rb_define_method(C_Array, "unshift", Fary_unshift, 1);
rb_define_method(C_Array, "each", Fary_each, 0);
rb_define_method(C_Array, "length", Fary_length, 0);
rb_define_method(C_Array, "clone", Fary_clone, 0);
rb_define_method(C_Array, "join", Fary_join, -2);
rb_define_method(C_Array, "reverse", Fary_reverse, 0);
rb_define_method(C_Array, "sort", Fary_sort, 0);
rb_define_method(C_Array, "delete", Fary_delete, 1);
rb_define_method(C_Array, "delete_if", Fary_delete_if, 0);
rb_define_method(C_Array, "clear", Fary_clear, 0);
rb_define_method(C_Array, "fill", Fary_fill, -2);
rb_define_method(C_Array, "assoc", Fary_assoc, 1);
rb_define_method(C_Array, "rassoc", Fary_rassoc, 1);
rb_define_method(C_Array, "+", Fary_plus, 1);
rb_define_method(C_Array, "*", Fary_times, 1);
cmp = rb_intern("<=>");
eq = rb_intern("==");
rb_define_method(C_Kernel, "::", assoc_new, 1);
}
个人理解是,先要把这些数组的方法混个熟悉。因为我比较喜欢用数组,所以这些方法基本熟悉。象push,pop是模仿栈的操作,自栈顶进行插入或删除操作。而shift,unshift是模仿队列操作,在队头可以进行插入删除操作。each是对每个元素进行遍历,这样include M_Enumerable后,就可以使用M_Enumerable中的若干函数了。
length取数组的长度。join把数组中的元素用一个分隔符号串起来。reverse把数组颠倒过来。delete,delete_if用来删除数组中某一个元素。clear用来把数组中元素清除,但数组不释放。fill用一个给定元素去填写数组中的所有元素。
+用于把两个数组拼起来,变成一个大数组。而*用于把一个数组的元素重复。
基本上,把这些数组的方法心里有个谱,再去读源码,就心里大致有数了。千万不要追求100%的读懂。我试过,当我要把一本书中100%读懂,那读得累,而且效率不高,也坚持不下去。后来,我变成,想读就读,读到哪算哪。这样效率高,而且也能坚持下去。象Init_array{}开头的
C_Array = rb_define_class("Array", C_Object);
是什么意思?我知道,他的意思是构建Array类是Object的子类。在Array的super指针指向Object.但具体如何实现,但会麻烦得不得了。
rb_include_module(C_Array, M_Enumerable);
这里是什么意思?估计就是
include Enumerable
因为包含一个模块,也把这个模块当成父类之一。和上面逻辑差不多。深入下去,这个array.c的代码我就看不完了。于是选择性的忽略。
VALUE
ary_new2(len)
{
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, C_Array, T_ARRAY);
GC_LINK;
GC_PRO(ary);
ary->len = 0;
ary->capa = len;
ary->ptr = ALLOC_N(VALUE, len);
GC_UNLINK;
return (VALUE)ary;
}
这个函数中,ary是一个数组,但数组对象