Project

General

Profile

Actions

Bug #3011

closed

caller for recursive function

Added by marcandre (Marc-Andre Lafortune) over 14 years ago. Updated over 12 years ago.

Status:
Closed
Target version:
ruby -v:
ruby 1.8.8dev (2010-03-25) [i386-darwin10.2.0]
[ruby-core:28963]

Description

=begin
For some reason, Ruby 1.8 will skip multiple copies of the same method. In case of a recursive function call, the behavior is different from Ruby 1.9 and seems wrong.

Here's the rubyspec I just committed:

 it "returns one entry per call, even for recursive methods" do
   def recurse(n)
     return caller if n <= 0
     recurse(n-1)
   end
   (recurse(3).size - recurse(2).size).should == 1
 end

The following patch doesn't seem to yield any new failure with make test, make test-all, nor the caller specs:

diff --git a/eval.c b/eval.c
index 3407548..65fb970 100644
--- a/eval.c
+++ b/eval.c
@@ -6468,9 +6468,6 @@ backtrace(lev)
}
for (; frame && (n = frame->node); frame = frame->prev) {
if (frame->prev && frame->prev->last_func) {

  •       if (frame->prev->node == n) {
    
  •           if (frame->prev->last_func == frame->last_func) continue;
    
  •       }
          snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
                   n->nd_file, nd_line(n),
                   rb_id2name(frame->prev->last_func));
    

Nobu, can you recall what was the reason for these lines ( r10593 ) ?
=end

Actions #1

Updated by nobu (Nobuyoshi Nakada) over 14 years ago

=begin
Hi,

At Thu, 25 Mar 2010 10:38:57 +0900,
Marc-Andre Lafortune wrote in [ruby-core:28963]:

For some reason, Ruby 1.8 will skip multiple copies of the
same method. In case of a recursive function call, the
behavior is different from Ruby 1.9 and seems wrong.

According to the log and ML archive, it was origined from
r8590, and intended to veil implicitly called method names.
e.g.: to make the former to the latter.

$ ruby -e 'p [0].max_by'
-e:1:in max_by': no block given (LocalJumpError) from -e:1:in each'
from -e:1:in `max_by'
from -e:1

$ ruby -e 'p [0].max_by'
-e:1:in `max_by': no block given (LocalJumpError)
from -e:1

But something seems to have changed and it doesn't work
expectedly now.

The following patch doesn't seem to yield any new failure
with make test, make test-all, nor the caller specs:

Seems nice.

Another idea is to reduce same methods like following patch,
but it may cause other issues.


diff --git i/eval.c w/eval.c
index 3407548..159ed0e 100644
--- i/eval.c
+++ w/eval.c
@@ -6437,4 +6437,5 @@ backtrace(lev)
VALUE ary;
NODE *n;

  • int succ = 0;

    ary = rb_ary_new();
    @@ -6467,15 +6468,22 @@ backtrace(lev)
    }
    }

  • for (; frame && (n = frame->node); frame = frame->prev) {
  • for (frame && (n = frame->node); frame = frame->prev) {
  • const char *name = 0;
    if (frame->prev && frame->prev->last_func) {
  •  if (frame->prev->node == n) {
    
  •  if (frame->prev->last_func == frame->last_func) continue;
    
  •  if (frame->prev->node == n && frame->prev->last_func == frame->last_func) {
    
  •  succ++;
    
  •  continue;
     }
    
  •  snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
    
  •       n->nd_file, nd_line(n),
    
  •       rb_id2name(frame->prev->last_func));
    
  •  name = rb_id2name(frame->prev->last_func);
    
    }
  • else {
  •  snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
    
  • snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
  • if (name) {
  •  long len = strlen(buf);
    
  •  snprintf(buf + len, BUFSIZ - len, ":in `%s'", name);
    
  •  len += strlen(buf + len);
    
  •  if (succ > 0) {
    
  •  snprintf(buf + len, BUFSIZ - len, " (%d levels)", succ + 1);
    
  •  succ = 0;
    
  •  }
    
    }
    rb_ary_push(ary, rb_str_new2(buf));

--
Nobu Nakada

=end

Actions #2

Updated by shyouhei (Shyouhei Urabe) over 14 years ago

  • Status changed from Open to Assigned

=begin

=end

Updated by marcandre (Marc-Andre Lafortune) over 12 years ago

  • Description updated (diff)
  • Status changed from Assigned to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0