--20cf3071cfae466a6204a23b8ef6 Content-Type: text/plain; charset=ISO-8859-1 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 ; 9: int lim ; 10: VALUE result, tmp; 11: 12: if (rb_scan_args(argc, argv, "02", &spat, &limit) 2) { 13: lim UM2INT(limit); 14: if (lim < ) limit nil; 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 ; 21: } 22: 23: enc TR_ENC_GET(str); 24: if (NIL_P(spat)) { 25: if (!NIL_P(rb_fs)) { 26: spat b_fs; 27: goto fs_set; 28: } 29: split_type wk; 30: } 31: else { 32: fs_set: 33: if (TYPE(spat) T_STRING) { 34: rb_encoding *enc2 TR_ENC_GET(spat); 35: 36: split_type tring; 37: if (RSTRING_LEN(spat) 0) { 38: /* Special case - split into chars */ 39: spat b_reg_regcomp(spat); 40: split_type egexp; 41: } 42: else if (rb_enc_asciicompat(enc2) 1) { 43: if (RSTRING_LEN(spat) 1 && RSTRING_PTR(spat)[0] ' '){ 44: split_type wk; 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 wk; 52: } 53: } 54: } 55: else { 56: spat et_pat(spat, 1); 57: split_type egexp; 58: } 59: } 60: 61: result b_ary_new(); 62: beg ; 63: if (split_type awk) { 64: char *ptr STRING_PTR(str); 65: char *eptr STRING_END(str); 66: char *bptr tr; 67: int skip ; 68: unsigned int c; 69: 70: end eg; 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 tr - bptr; 77: } 78: else { 79: end tr - bptr; 80: skip ; 81: if (!NIL_P(limit) && lim < ) break; 82: } 83: } 84: else if (ascii_isspace(c)) { 85: rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 86: skip ; 87: beg tr - bptr; 88: if (!NIL_P(limit)) ++i; 89: } 90: else { 91: end tr - bptr; 92: } 93: } 94: } 95: else { 96: while (ptr < eptr) { 97: int n; 98: 99: c b_enc_codepoint_len(ptr, eptr, &n, enc); 100: ptr + ; 101: if (skip) { 102: if (rb_isspace(c)) { 103: beg tr - bptr; 104: } 105: else { 106: end tr - bptr; 107: skip ; 108: if (!NIL_P(limit) && lim < ) break; 109: } 110: } 111: else if (rb_isspace(c)) { 112: rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 113: skip ; 114: beg tr - bptr; 115: if (!NIL_P(limit)) ++i; 116: } 117: else { 118: end tr - bptr; 119: } 120: } 121: } 122: } 123: else if (split_type string) { 124: char *ptr STRING_PTR(str); 125: char *temp tr; 126: char *eptr STRING_END(str); 127: char *sptr STRING_PTR(spat); 128: long slen STRING_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 b_enc_check(str, spat); 137: while (ptr < eptr && 138: (end b_memsearch(sptr, slen, ptr, eptr - ptr, enc)) > ) { 139: /* Check we are at the start of a char */ 140: char *t b_enc_right_char_head(ptr, ptr + end, eptr, enc); 141: if (t ! tr + end) { 142: ptr ; 143: continue; 144: } 145: rb_ary_push(result, rb_str_subseq(str, ptr - temp, end)); 146: ptr + nd + slen; 147: if (!NIL_P(limit) && lim < +i) break; 148: } 149: beg tr - temp; 150: } 151: else { 152: char *ptr STRING_PTR(str); 153: long len STRING_LEN(str); 154: long start eg; 155: long idx; 156: int last_null ; 157: struct re_registers *regs; 158: 159: while ((end b_reg_search(spat, str, start, 0)) > ) { 160: regs MATCH_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 tart; 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 ; 179: continue; 180: } 181: } 182: else { 183: rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 184: beg tart ND(0); 185: } 186: last_null ; 187: 188: for (idx idx < regs->num_regs; idx++) { 189: if (BEG(idx) -1) continue; 190: if (BEG(idx) END(idx)) 191: tmp tr_new_empty(str); 192: else 193: tmp b_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 tr_new_empty(str); 202: else 203: tmp b_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 ARRAY_LEN(result)) > 0 && 209: (tmp ARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) 0)) 210: rb_ary_pop(result); 211: } 212: 213: return result; 214: } pry(main)> exit --20cf3071cfae466a6204a23b8ef6--