On Jul 6, 2014, at 7:27 AM, Arup R. [email protected]
wrote:
Now If I write “any string”.scan(/\d+/) { |m| p m } - It is clear I am using
block version.
Now, while I write - “any string”.enum_for(:scan, /\d+/) – I can’t see how
$scan is actually working. So my question came out right there…
Hope it is clear now.
One way I have started to understand how Ruby’s interpreter works is to
look at the source. These days I use pry to look at things in Ruby as I
can use pry’s $ command to see source:
[1]pry(main)> $ String#scan
From: string.c (C Method):
Owner: String
Visibility: public
Number of lines: 30
static VALUE
rb_str_scan(VALUE str, VALUE pat)
{
VALUE result;
long start = 0;
long last = -1, prev = 0;
char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);
pat = get_pat(pat, 1);
if (!rb_block_given_p()) {
VALUE ary = rb_ary_new();
while (!NIL_P(result = scan_once(str, pat, &start))) {
last = prev;
prev = start;
rb_ary_push(ary, result);
}
if (last >= 0) rb_reg_search(pat, str, last, 0);
return ary;
}
while (!NIL_P(result = scan_once(str, pat, &start))) {
last = prev;
prev = start;
rb_yield(result);
str_mod_check(str, p, len);
}
if (last >= 0) rb_reg_search(pat, str, last, 0);
return str;
}
There aren’t two different versions of String#scan, when a String is
sent the scan message the scan method checks to see if it was given a
block. If no block was given then it builds and returns a new array,
populates it and returns it. If there was a block given then it yields
the results as it finds them and eventually returns the original string.
Another fun place to look for implementations of bits of Ruby is in
Rubinius, as most of it is written in Ruby.
Hope this helps,
Mike
–
Mike S. [email protected]
http://www.stok.ca/~mike/
The “`Stok’ disclaimers” apply.