# Error calling block in sub class

**URL:** <https://www.ruby-forum.com/t/error-calling-block-in-sub-class/79115>\
**Category:** Ruby\
**Created:** [March 9, 2006, 6:36pm UTC](https://www.ruby-forum.com/t/error-calling-block-in-sub-class/79115 "2006-03-09T18:36:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![apjanes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee59a6/32.png) [@apjanes](https://www.ruby-forum.com/u/apjanes)\
**Post date:** [March 9, 2006, 6:36pm UTC](https://www.ruby-forum.com/t/error-calling-block-in-sub-class/79115/1 "2006-03-09T18:36:32Z")

</div>

I am creating a base collection class that will allow the assignment of  
multiple code blocks which validate the addition of objects to the  
collection. The code looks like this:

\<\< Code Snippet \>\>

class CollectionBase  
public  
def initialize()  
@validators = Array.new() # Contains any validators  
@items = Array.new() # Contains collection’s objects  
end

```
# Adds a code block to the validators array that will be called when 

```

adding  
# items to the collection.  
def add\_validator(&block)  
validators.push(block)  
end

```
# Adds an object to the collection
def add(obj)
  # Check to see if the object is valid for this collection
  if valid?(obj)
    @items.push(obj)
    return @items.length - 1
  end
end

```

… Code omitted to be consise

```
# Loops through all validators and passes the
# object being checked to the code block.
# If any validator returns false the object is
# invalid.
def valid?(obj)
  invalid = false
  @validators.each do |validator|
    if !validator.nil?
      invalid = true if !validator.call(obj)
    end
  end
  !invalid
end

```

end

\<\< End Code Snippet \>\>

This code works fine. I can create a new CollectionBase, pass a code  
block to add\_validators and depending on the result of the code block  
objects are added or not.

The problem comes when I try and subclass this class. I also want to  
create a SetBase class which extends CollectionBase but by default adds  
a validator that prevents duplicate objects from being added:

\<\< Code Snippet \>\>

require ‘Collections’

class SetBase \< CollectionBase  
public  
def initialize()  
super  
# add a validator that returns false if object is already  
# in the set  
add\_validator {return !index(obj) }  
end  
end

\<\< End Code Snippet \>\>

When I try to add an item to SetBase, however, I get the error:  
unexpected return (LocalJumpError)

I have stepped through with a debugger and the error is raised when an  
attempt is made to call the code block (ie. the addition of the  
validator works fine).

Does anyone have any idea why this is happening?

Thanks,  
Aaron

---

<div class="post-metadata">

**Author:** ![apjanes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee59a6/32.png) [@apjanes](https://www.ruby-forum.com/u/apjanes)\
**Post date:** [March 9, 2006, 10:38pm UTC](https://www.ruby-forum.com/t/error-calling-block-in-sub-class/79115/2 "2006-03-09T22:38:39Z")

</div>

> Is that what you’re after?

That’s spot on. Modified my code like you said and it worked perfectly.  
So the |obj| is the way you specify a required parameter for a code  
block? When omitting the |obj| as well as the return I get the error  
“undefined local variable or method `obj’ for…” so that must be the  
case.

Thanks for your help.

Aaron

---

<div class="post-metadata">

**Author:** ![apjanes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee59a6/32.png) [@apjanes](https://www.ruby-forum.com/u/apjanes)\
**Post date:** [March 9, 2006, 9:02pm UTC](https://www.ruby-forum.com/t/error-calling-block-in-sub-class/79115/3 "2006-03-09T21:02:41Z")

</div>

On Fri, 2006-03-10 at 02:36 +0900, Aaron Janes wrote:

> \<\< Code Snippet \>\>  
> end  
> end
> 
> \<\< End Code Snippet \>\>
> 
> When I try to add an item to SetBase, however, I get the error:  
> unexpected return (LocalJumpError)

I think it’s because you’re saving the block for later use, and slightly  
misunderstanding the semantics of ‘return’. The return in the block is  
actually trying to return from the initialize() method, not from the  
block, so Ruby naturally thinks ‘huh? We did that already…’. For  
example:

```
def test
  p [1,2,3,4,5].each { |e| p e; return e }
end
# => nil

test
1	# (output)
# => 1

```

You can see here that the return applies to the test method (in which  
the block is defined) rather than ‘each’. The first time it’s executed,  
the whole method returns, abandoning the iteration. As a closure, the  
block retains the scope it’s created in.

You should be able to fix the problem with something like:

class SetBase \< CollectionBase  
public  
def initialize()  
super  
# add a validator that returns false if object is already  
# in the set  
add\_validator { |obj| !index(obj) }  
end  
end

(i.e. don’t use return in there - generally you can avoid using return  
in most places, since you’ll always get the result of the last  
expression executed as the return of a method or block/lambda).

After adding an ‘index’ method to the base-class, this gave me the  
following results:

c = SetBase.new  
c.add(1)  
c.add(2)  
c.add(3)

c.valid?(1)

# =\> false

p c.valid?(2)

# =\> false

p c.valid?(3)

# =\> false

p c.valid?(4)

# =\> true

Is that what you’re after?
