On Sun, May 1, 2011 at 1:56 PM, Josh Cheek <josh.cheek / gmail.com> wrote:

> On Sun, May 1, 2011 at 4:29 AM, Konstantin Ka <paranox3 / yahoo.de> wrote:
>
>>
>> Would there be any way that Ruby-Newbie-mme could come along, have a
>> look inside the preprogrammed String class and see written there in Ruby
>> language
>>
>> >  def rand
>> >    self.split('').shuffle.join
>> >  end
>>
>> ... because that would enable me to go "Oh, sure! It splits the string,
>> shuffles it, and joins it back together. Sounds easy!" even if, to find
>> out what some of those "1st tier" methods like .split actually do, I'd
>> have to go look at the C code.
>>
>>
>>
> Check out the gem pry (get it by going to the command line and typing "gem
> install pry pry-doc" -- possibly requiring "sudo" privelages, and possibly
> not working on 1.8.6)
>
> Then you can start a pry session with "pry"
>

Sorry I hit space or something, and it sent the message before I finished.
Here is an example session. Pry is a repl (like irb) but it knows how to do
lots of really useful things. One of these is reflecting upon code. In this
case, I tell it to show me the documentation for String#split, then I tell
it to show me the code for String#split For more cool things you can do with
it, check out
http://rdoc.info/github/banister/pry/master/file/README.markdown


$ pry -f


pry(main)> show-doc String#split

From: string.c in Ruby Core (C Method):
Number of lines: 36

Divides str into substrings based on a delimiter, returning an array
of these substrings.

If pattern is a String, then its contents are used as
the delimiter when splitting str. If pattern is a single
space, str is split on whitespace, with leading whitespace and runs
of contiguous whitespace characters ignored.

If pattern is a Regexp, str is divided where the
pattern matches. Whenever the pattern matches a zero-length string,
str is split into individual characters. If pattern contains
groups, the respective matches will be returned in the array as well.

If pattern is omitted, the value of $; is used.  If
$; is nil (which is the default), str is
split on whitespace as if ` ' were specified.

If the limit parameter is omitted, trailing null fields are
suppressed. If limit is a positive number, at most that number of
fields will be returned (if limit is 1, the entire
string is returned as the only entry in an array). If negative, there is no
limit to the number of fields returned, and trailing null fields are not
suppressed.

   " now's  the time".split        #=> ["now's", "the", "time"]
   " now's  the time".split(' ')   #=> ["now's", "the", "time"]
   " now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
   "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
   "hello".split(//)               #=> ["h", "e", "l", "l", "o"]
   "hello".split(//, 3)            #=> ["h", "e", "llo"]
   "hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]

   "mellow yellow".split("ello")   #=> ["m", "w y", "w"]
   "1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]
   "1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
   "1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]


pry(main)> show-method -l -f String#split

From: string.c in Ruby Core (C Method):
Number of lines: 214

1: static VALUE
2: rb_str_split_m(int argc, VALUE *argv, VALUE str)
3: {
4:     rb_encoding *enc;
5:     VALUE spat;
6:     VALUE limit;
7:     enum {awk, string, regexp} split_type;
8:     long beg, end, i = 0;
9:     int lim = 0;
10:     VALUE result, tmp;
11:
12:     if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
13:     lim = NUM2INT(limit);
14:     if (lim <= 0) limit = Qnil;
15:     else if (lim == 1) {
16:         if (RSTRING_LEN(str) == 0)
17:         return rb_ary_new2(0);
18:         return rb_ary_new3(1, str);
19:     }
20:     i = 1;
21:     }
22:
23:     enc = STR_ENC_GET(str);
24:     if (NIL_P(spat)) {
25:     if (!NIL_P(rb_fs)) {
26:         spat = rb_fs;
27:         goto fs_set;
28:     }
29:     split_type = awk;
30:     }
31:     else {
32:       fs_set:
33:     if (TYPE(spat) == T_STRING) {
34:         rb_encoding *enc2 = STR_ENC_GET(spat);
35:
36:         split_type = string;
37:         if (RSTRING_LEN(spat) == 0) {
38:         /* Special case - split into chars */
39:         spat = rb_reg_regcomp(spat);
40:         split_type = regexp;
41:         }
42:         else if (rb_enc_asciicompat(enc2) == 1) {
43:         if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
44:             split_type = awk;
45:         }
46:         }
47:         else {
48:         int l;
49:         if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l,
enc2) == ' ' &&
50:             RSTRING_LEN(spat) == l) {
51:             split_type = awk;
52:         }
53:         }
54:     }
55:     else {
56:         spat = get_pat(spat, 1);
57:         split_type = regexp;
58:     }
59:     }
60:
61:     result = rb_ary_new();
62:     beg = 0;
63:     if (split_type == awk) {
64:     char *ptr = RSTRING_PTR(str);
65:     char *eptr = RSTRING_END(str);
66:     char *bptr = ptr;
67:     int skip = 1;
68:     unsigned int c;
69:
70:     end = beg;
71:     if (is_ascii_string(str)) {
72:         while (ptr < eptr) {
73:         c = (unsigned char)*ptr++;
74:         if (skip) {
75:             if (ascii_isspace(c)) {
76:             beg = ptr - bptr;
77:             }
78:             else {
79:             end = ptr - bptr;
80:             skip = 0;
81:             if (!NIL_P(limit) && lim <= i) break;
82:             }
83:         }
84:         else if (ascii_isspace(c)) {
85:             rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
86:             skip = 1;
87:             beg = ptr - bptr;
88:             if (!NIL_P(limit)) ++i;
89:         }
90:         else {
91:             end = ptr - bptr;
92:         }
93:         }
94:     }
95:     else {
96:         while (ptr < eptr) {
97:         int n;
98:
99:         c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
100:         ptr += n;
101:         if (skip) {
102:             if (rb_isspace(c)) {
103:             beg = ptr - bptr;
104:             }
105:             else {
106:             end = ptr - bptr;
107:             skip = 0;
108:             if (!NIL_P(limit) && lim <= i) break;
109:             }
110:         }
111:         else if (rb_isspace(c)) {
112:             rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
113:             skip = 1;
114:             beg = ptr - bptr;
115:             if (!NIL_P(limit)) ++i;
116:         }
117:         else {
118:             end = ptr - bptr;
119:         }
120:         }
121:     }
122:     }
123:     else if (split_type == string) {
124:     char *ptr = RSTRING_PTR(str);
125:     char *temp = ptr;
126:     char *eptr = RSTRING_END(str);
127:     char *sptr = RSTRING_PTR(spat);
128:     long slen = RSTRING_LEN(spat);
129:
130:     if (is_broken_string(str)) {
131:         rb_raise(rb_eArgError, "invalid byte sequence in %s",
rb_enc_name(STR_ENC_GET(str)));
132:     }
133:     if (is_broken_string(spat)) {
134:         rb_raise(rb_eArgError, "invalid byte sequence in %s",
rb_enc_name(STR_ENC_GET(spat)));
135:     }
136:     enc = rb_enc_check(str, spat);
137:     while (ptr < eptr &&
138:            (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0)
{
139:         /* Check we are at the start of a char */
140:         char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
141:         if (t != ptr + end) {
142:         ptr = t;
143:         continue;
144:         }
145:         rb_ary_push(result, rb_str_subseq(str, ptr - temp, end));
146:         ptr += end + slen;
147:         if (!NIL_P(limit) && lim <= ++i) break;
148:     }
149:     beg = ptr - temp;
150:     }
151:     else {
152:     char *ptr = RSTRING_PTR(str);
153:     long len = RSTRING_LEN(str);
154:     long start = beg;
155:     long idx;
156:     int last_null = 0;
157:     struct re_registers *regs;
158:
159:     while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
160:         regs = RMATCH_REGS(rb_backref_get());
161:         if (start == end && BEG(0) == END(0)) {
162:         if (!ptr) {
163:             rb_ary_push(result, str_new_empty(str));
164:             break;
165:         }
166:         else if (last_null == 1) {
167:             rb_ary_push(result, rb_str_subseq(str, beg,
168:                               rb_enc_fast_mbclen(ptr+beg,
169:                                      ptr+len,
170:                                      enc)));
171:             beg = start;
172:         }
173:         else {
174:                     if (ptr+start == ptr+len)
175:                         start++;
176:                     else
177:                         start +=
rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
178:             last_null = 1;
179:             continue;
180:         }
181:         }
182:         else {
183:         rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
184:         beg = start = END(0);
185:         }
186:         last_null = 0;
187:
188:         for (idx=1; idx < regs->num_regs; idx++) {
189:         if (BEG(idx) == -1) continue;
190:         if (BEG(idx) == END(idx))
191:             tmp = str_new_empty(str);
192:         else
193:             tmp = rb_str_subseq(str, BEG(idx), END(idx)-BEG(idx));
194:         rb_ary_push(result, tmp);
195:         }
196:         if (!NIL_P(limit) && lim <= ++i) break;
197:     }
198:     }
199:     if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) >
beg || lim < 0)) {
200:     if (RSTRING_LEN(str) == beg)
201:         tmp = str_new_empty(str);
202:     else
203:         tmp = rb_str_subseq(str, beg, RSTRING_LEN(str)-beg);
204:     rb_ary_push(result, tmp);
205:     }
206:     if (NIL_P(limit) && lim == 0) {
207:     long len;
208:     while ((len = RARRAY_LEN(result)) > 0 &&
209:            (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
210:         rb_ary_pop(result);
211:     }
212:
213:     return result;
214: }
pry(main)> exit