# Syntax error when redefining \>\> operator to take a block

**URL:** <https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028>\
**Category:** Ruby\
**Created:** [October 12, 2007, 7:39am UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028 "2007-10-12T07:39:44Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 12, 2007, 7:39am UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/1 "2007-10-12T07:39:44Z")

</div>

I’m trying to redefine the \>\> operator for a particular class such that  
it takes a block as its argument. It works if I invoke the redifined \>\>  
operator using “.” syntax, but causes a syntax error otherwise.

This code illustrates my problem:

class C  
def \>\>(&block)  
block.call(“inside \>\>”)  
end  
end

c = C.new  
c.\>\> { |x| puts x } # outputs “inside \>\>”  
#c \>\> { |x| puts x } # syntax error, if uncommented

This is the syntax error reported:

test.rb:10: syntax error, unexpected ‘|’, expecting ‘}’  
c \>\> { |x| puts x } # syntax error, if uncommented  
^  
test.rb:10: syntax error, unexpected tIDENTIFIER, expecting kDO or ‘{’  
or ‘(’  
c \>\> { |x| puts x } # syntax error, if uncommented  
^

Any pointers? Thanks.

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 12, 2007, 2:04pm UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/2 "2007-10-12T14:04:48Z")

</div>

2007/10/12, John W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> end  
> test.rb:10: syntax error, unexpected tIDENTIFIER, expecting kDO or ‘{’  
> or ‘(’  
> c \>\> { |x| puts x } # syntax error, if uncommented  
> ^
> 
> Any pointers? Thanks.

Redefining operator behavior cannot change Ruby’s syntax. \>\> is with  
a block is just not valid Ruby syntax - as you have seen.

robert

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 12, 2007, 8:22pm UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/3 "2007-10-12T20:22:56Z")

</div>

> > I’m trying to redefine the \>\> operator for a particular class such that  
> > it takes a block as its argument. It works if I invoke the redifined \>\>  
> > operator using “.” syntax, but causes a syntax error otherwise.
> > 
> > […snip…]
> > 
> > Any pointers? Thanks.
> 
> Redefining operator behavior cannot change Ruby’s syntax. \>\> is with  
> a block is just not valid Ruby syntax - as you have seen.

I don’t understand why it’s invalid syntax. I’m new to Ruby and am  
looking to better understand.

Please consider these two different definitions of \>\>

def \>\>(arg) …  
def \>\>(&arg) …

and these two different invocations of \>\>

c \>\> { }  
c.\>\> { }

In the following example, the first invocation works with the first  
definition, and the second with the second. However the first/second  
invocation doesn’t work second/first definition, respectively.

class C  
def \>\>(arg)  
puts arg.class  
end  
end

c = C.new

c \>\> { } # outputs ‘Hash’  
#c.\>\> { } # syntax error: wrong number of args (0 for 1)

class C  
def \>\>(&arg)  
puts arg.class  
end  
end

c.\>\> { } # outputs ‘Proc’  
#c \>\> { } # syntax error: wrong number of args (1 for 0)

It seems that if the operator is invoked with only optional whitespace  
between the receiver “c” and the operator “\>\>” then ruby interprets the  
following { … } to be a hash, and if the operator is invoked with a  
“.” then ruby interprets { … } to be a proc. And this appears to be  
regardless of what’s actually between the braces, or regardless of how  
the argument to \>\> is defined (ie with or without the “&”).

I’m wondering why ruby doesn’t instead interpret { … } to be either a  
hash or a proc based on what’s inside the braces. For example, { 1 =\>  
“one” } is a hash, and { |x| x + x } is a proc. It seems to me this  
distinction should be made by what’s between the braces, and not whether  
there’s a " " or “.” between the receiver and the operator. Then, if  
there’s a mismatch between what’s being passed and the operator  
definition, I would expect an error.

So is this an area where Ruby’s parsing could be improved to enable  
passing a block to an operator (without having to use “.” to invoke the  
operator)? Or, am I misunderstanding something? Any insight would be  
appreciated.

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 1:09am UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/4 "2007-10-13T01:09:38Z")

</div>

Generally, you don’t need to try and create or override operators in  
Ruby.  
It’s just not worth the trouble.  
It’s a lot easier (probably intentionally) to just create a normal  
method or function.  
It’s not C++  
Try to make it readable by humans.

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 12:40am UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/5 "2007-10-13T00:40:55Z")

</div>

On 12.10.2007 20:22, John W. wrote:

> c \>\> { }  
> end  
> end
> 
> c.\>\> { } # outputs ‘Proc’  
> #c \>\> { } # syntax error: wrong number of args (1 for 0)
> 
> It seems that if the operator is invoked with only optional whitespace  
> between the receiver “c” and the operator “\>\>” then ruby interprets the  
> following { … } to be a hash, and if the operator is invoked with a  
> “.” then ruby interprets { … } to be a proc. And this appears to be  
> regardless of what’s actually between the braces, or regardless of how  
> the argument to \>\> is defined (ie with or without the “&”).

I cannot be different because - as I have said before - a method /  
operator (re-)definition cannot change the syntax of the language. For  
syntax it is completely irrelevant how you define a method / operator.

Here are some examples:

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self.\>\> {}’  
[]  
#Proc:0x00000000@-e:1

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self.\>\>({})’  
[{}]  
nil

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self.\>\>(){}’  
[]  
#Proc:0x00000000@-e:1

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self \>\> {}’  
[{}]  
nil

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self.\>\> {|x|}’  
[]  
#Proc:0x00000000@-e:1

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self.\>\>() {|x|}’  
[]  
#Proc:0x00000000@-e:1

robert@fussel ~  
$ ruby -e ‘def self.\>\>(\*a,&b) p a,b end; self \>\> {|x|}’  
-e:1: syntax error, unexpected ‘|’, expecting ‘}’  
def self.\>\>(\*a,&b) p a,b end; self \>\> {|x|}  
^  
When you use the dot notation then the expression is a normal method  
invocation just with an unusual method name. So all the normal method  
invocation syntax applies and in that case {} is interpreted as block -  
no matter what.

When you use the operator syntax (i.e. no dot) Ruby tries to parse the  
right hand side as an expression, which could only be a Hash in this  
case since a block is not an expression. You need an expression on the  
right hand side because \>\> is a binary operator.

> I’m wondering why ruby doesn’t instead interpret { … } to be either a  
> hash or a proc based on what’s inside the braces. For example, { 1 =\>  
> “one” } is a hash, and { |x| x + x } is a proc. It seems to me this  
> distinction should be made by what’s between the braces, and not whether  
> there’s a " " or “.” between the receiver and the operator. Then, if  
> there’s a mismatch between what’s being passed and the operator  
> definition, I would expect an error.

And what is {}? It’s both a valid Hash and block. And actually Ruby  
does parse accordingly:

robert@fussel ~  
$ ruby -ce ‘a \>\> do |x| end’  
-e:1: syntax error, unexpected kDO  
a \>\> do |x| end  
^

robert@fussel ~  
$ ruby -ce ‘a \>\> {|x| }’  
-e:1: syntax error, unexpected ‘|’, expecting ‘}’  
a \>\> {|x| }  
^

robert@fussel ~  
$ ruby -ce ‘a \>\> {}’  
Syntax OK

> So is this an area where Ruby’s parsing could be improved to enable  
> passing a block to an operator (without having to use “.” to invoke the  
> operator)? Or, am I misunderstanding something? Any insight would be  
> appreciated.

I would not consider it an improvement since I don’t see a point in  
passing a block to an operator. I don’t see need for improvement here.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 7:12pm UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/6 "2007-10-13T19:12:16Z")

</div>

Thanks guys, I now understand much better what’s going on with my  
attempt to redefine \>\>. This list is great!

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 4:51am UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/7 "2007-10-13T04:51:50Z")

</div>

Hi,

On Fri, 2007-10-12 at 14:39 +0900, John W. wrote:

> I’m trying to redefine the \>\> operator for a particular class such that  
> it takes a block as its argument. It works if I invoke the redifined \>\>  
> operator using “.” syntax, but causes a syntax error otherwise.

I think the problem is summed up shortly in another reply, but –

> > is a binary operator, meaning it must accept one argument. Block  
> > arguments are treated in a special manner (e.g. the arity of a method  
> > which takes only a block is 0), and thus aren’t valid as the other  
> > operand of a binary operator!

HTH your understanding a bit,  
arlen

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 7:44pm UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/8 "2007-10-13T19:44:28Z")

</div>

On 10/12/07, Arlen Christian Mart C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> arguments are treated in a special manner (e.g. the arity of a method  
> which takes only a block is 0), and thus aren’t valid as the other  
> operand of a binary operator!

Note from the post which started this thread:

c.\>\> { |x| puts x } # outputs “inside \>\>”  
#c \>\> { |x| puts x } # syntax error, if uncommented

It really doesn’t have to do with the arity of the method. It’s the  
way the statement is parsed, the parser doesn’t check arity, in fact I  
don’t think it could if it wanted to, it doesn’t know what method  
would be bound to :\>\> for an arbitrary value of c.

That ‘.’ on the first line makes all the difference, The c \>\> x is  
syntactic sugar for sure which the parser turns into what gets  
evaluated effectively as c.\>\>(x) but since the parser doesn’t see a  
valid x it results in a syntax error.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [October 13, 2007, 8:15pm UTC](https://www.ruby-forum.com/t/syntax-error-when-redefining-operator-to-take-a-block/117028/9 "2007-10-13T20:15:29Z")

</div>

On 13.10.2007 19:43, Rick DeNatale wrote:

> > arguments are treated in a special manner (e.g. the arity of a method  
> > don’t think it could if it wanted to, it doesn’t know what method  
> > would be bound to :\>\> for an arbitrary value of c.
> 
> That ‘.’ on the first line makes all the difference, The c \>\> x is  
> syntactic sugar for sure which the parser turns into what gets  
> evaluated effectively as c.\>\>(x) but since the parser doesn’t see a  
> valid x it results in a syntax error.

Yeah, and that’s why operators are special in a way when it comes to  
arity. Although you can define them with arbitrary arity the normal  
usage of a binary operator enforces exactly one argument (plus self of  
course) and thus practically enforces arity one - even if you can pass  
more arguments when using dot notation.

irb(main):001:0\> def +(\*a)p a end  
=\> nil  
irb(main):002:0\> self.+ 1,2,3  
[1, 2, 3]  
=\> nil  
irb(main):003:0\> self + 1  
[1]  
=\> nil

Kind regards

robert
