Arrow operator with dash instead of equals (->)

Hi, all,

Is it possible to use -> as a method name in Ruby?

This code:

    class A
      def ->(arg)
        puts arg
      end
    end

    foo = A.new
    foo -> "dummy_argument"

Produces:

    ~/test2.rb:2: syntax error, unexpected '>', expecting '\n' or
    ';'
      def ->(arg)
            ^
    ~/test2.rb:5: syntax error, unexpected kEND, expecting $end

But if I substitute the ‘->’ with ‘>>’, the program works and I get:

    dummy_argument

Any idea what’s going on here?

Running ruby 1.8.6 on Debian unstable.

Many thanks in advance, greetings,
Andrew G.

Andrew G. wrote:

Hi, all,

Is it possible to use -> as a method name in Ruby?

No. A subset of Ruby’s operators are implemented as methods. ‘>>’ is one
of those operators. ‘->’ isn’t a Ruby operator at all.

The operators that are implemented as methods are: [], []=, **, !, ~, +,
-, *, /, %, <<, >>,& ^, |, <=>, <=, <, >, >=, ==, ===, and =~.

Is it possible to use -> as a method name in Ruby?

No. A subset of Ruby’s operators are implemented as methods. ‘>>’ is one
of those operators. ‘->’ isn’t a Ruby operator at all.

The operators that are implemented as methods are: [], []=, **, !, ~, +,
-, *, /, %, <<, >>,& ^, |, <=>, <=, <, >, >=, ==, ===, and =~.

So is there no way to make ‘->’ an operator and define its behavior?

If not, what about ‘=>’?

On Apr 22, 2007, at 8:15 PM, Andrew G. wrote:

o is there no way to make ‘->’ an operator and define its behavior?

No. Ruby does not support user defined operators.

If not, what about ‘=>’?

No, ‘=>’ is not an operator in Ruby.

Andrew G. wrote:

So is there no way to make ‘->’ an operator and define its behavior?

If not, what about ‘=>’?

I listed the Ruby operators that are implemented as methods. ‘=>’ isn’t
in the list, is it?

Now, for completeness’ sake, it actually is possible to define a method
named ‘->’, but the only way you could call it would be by using ‘send’,
and I’m guessing you don’t want to do that. It would look like this:

o.send(’->’, args)

On Apr 22, 2007, at 7:54 PM, Timothy H. wrote:

No. A subset of Ruby’s operators are implemented as methods. ‘>>’
is one of those operators. ‘->’ isn’t a Ruby operator at all.

The operators that are implemented as methods are: [], []=, **, !,
~, +, -, *, /, %, <<, >>,& ^, |, <=>, <=, <, >, >=, ==, ===, and =~.

! is not a re-definable operator.

Gary W.

On Mon, Apr 23, 2007 at 09:47:14AM +0900, Timothy H. wrote:

Now, for completeness’ sake, it actually is possible to define a method
named ‘->’, but the only way you could call it would be by using ‘send’,
and I’m guessing you don’t want to do that. It would look like this:

o.send(’->’, args)

This can lead to smiley programming. I recently found myself writing

o.send(:[]=, *args)

It’s shorter than

o[args[0…-2]] = args[-1]

Brian C. wrote:

It’s shorter than

o[args[0…-2]] = args[-1]

:smiley: very nice!

It’s not possible to define a -> operator in Ruby, but you can
(sometimes) define <-. Watch:

class Right
def -@
return Negated.new(self)
end

class Negated
def initialize(right)
@inner=right
end

 attr :inner

end
end

class Left
def <(negated_right)
self.inspect + " <- " + negated_right.inner.inspect
end
end

Left.new <- Right.new #=> “#Left:0x403cf68c <- #Right:0x403cf678

It’s actually two operators, so there’s a caveat: if the right-side
class already defines unary minus, this won’t work.

(I first read about this trick in a C++ book. I’m not necessarily
recommending it.)

On Tue, Apr 24, 2007 at 02:25:33AM +0900, Andrew G. wrote:

    (x -> last_names).to_s + ", " + (x -> first_names).to_s

Using a dot instead of an arrow here is not an option for various
reasons.

Any ideas as to how to hack around this limitation in Ruby, then?

As you say, you could use >>, although it has a fairly low operator
precedence, so

x >> last_names + x >> first_names

would be parsed, I think, as

x >> (last_names + x) >> first_names

If you’re going to run through a preprocessor to substitute ->, then “.”
may
be a better substitution.

Our interpreter eventually gets the code blocks as strings, so I could
just substitute the -> for >> behind the user’s back, but that would be
messy, because it would substitute all occurrences of ->, even if
they’re in quotes or interpretable by Ruby in some other, unforseen way.
Or is there some clean way of doing this? With ri or something similar,
maybe?

The cleanest way I suspect would be to define a grammar for your own
language, and write a parser for it. I believe there’s a Ruby parser
generator out there.

Then you are not bound by the rules of Ruby syntax at all.

Regards,

Brian.

El lun, 23-04-2007 a las 09:52 +0900, Gary W.
escribió:> > o is there no way to make ‘->’ an operator and define its behavior?

No. Ruby does not support user defined operators.

If not, what about ‘=>’?

No, ‘=>’ is not an operator in Ruby.

Many thanks for your replies, everyone…

I’ll explain briefly why I’m asking:

We’re working on a domain-specific language that is mainly declarative
but that includes little snippets of executable code. These snippets
are, at least in our first implementation, in Ruby.

In some of the non-executable parts of the language we declare rules for
traversing segments of a graph using an arror (->). For example:

    author -> place_of_birth

or

    sibbling -> children -> age

It would be really, really nice to be able to use this same syntax in
the executable Ruby snippets, more or less along the lines of:

    (x -> last_names).to_s + ", " + (x -> first_names).to_s

Using a dot instead of an arrow here is not an option for various
reasons.

Any ideas as to how to hack around this limitation in Ruby, then?

Our interpreter eventually gets the code blocks as strings, so I could
just substitute the → for >> behind the user’s back, but that would be
messy, because it would substitute all occurrences of ->, even if
they’re in quotes or interpretable by Ruby in some other, unforseen way.
Or is there some clean way of doing this? With ri or something similar,
maybe?

Thanks again,
Andrew


(For anyone curious about what we’re doing here, here are some links (in
Spanish):
http://200.67.231.185/mediawiki/index.php/Pescador:Recursos_para_desarrolladores
http://durito.nongnu.org/
)

El mar, 24-04-2007 a las 04:31 +0900, Brian C.
escribió:> The cleanest way I suspect would be to define a grammar for your own

language, and write a parser for it. I believe there’s a Ruby parser
generator out there.

Then you are not bound by the rules of Ruby syntax at all.

Perhaps I didn’t explain myself clearly… We do have our own parser
and grammar. The thing is that within our language there are “blocks”
of code that are meant to be processed by the Ruby interpreter. At the
risk of being acused of going off topic, let me offer a little example:

<RuleSet person>
    <Structure>
        <Descriptor has_given_names>
            property swv:hasGivenNames
            minCardinality 1
            maxCardinality 1
            outRequirement fromPropRange
        </Descriptor>
        <Descriptor has_last_names>
            property swv:hasLastNames
            minCardinality 1
            maxCardinality 1
            outRequirement fromPropRange
        </Descriptor>
        <Descriptor has_parent>
            property swv:hasParent
            minCardinality 2
            maxCardinality 2
            outRequirement fromPropRange
        </Descriptor>
    </Structure>

    <KRRelationRules>
        <KRRelationRule parent_place_of_birth>
           has_parent->place_of_birth
        </KRRelationRule>
    </KRRelationRules>

    <BPVFunctions>
        <TextBPVFunction full_name_fl>
            orderUsing has_last_names
            |{ (ROOT->has_given_names).textBPV + " " + 

(ROOT->has_last_names).textBPV }|

    <Descriptions>
        defaultOrderBy has_last_names
        VariableDesc default
        ShortDesc default
        FullDesc default
    </Descriptions>
</RuleSet>

(I know, it’s very ugly… In the next version we’ll replace all the
xml-ish tags with angle brackets and make it all much more succinct.)

Anyway, all of this is processed by our own interpreter, including, for
example, the rule

    has_parent->place_of_birth

As you can see it’s mainly declarative. However this part

    |{ (ROOT->has_given_names).textBPV + " " + 

(ROOT->has_last_names).textBPV }|

is read by our interpreter only as a string between a |{ and a }| .

That string is then passed to the Ruby interpreter and is meant to be
run (from within a specific context that our interpreter determines). In
these bits we don’t want just our language running about, of course, we
want full-blown Ruby code with extensions that allow a programmer to
refer to the graph traversal rules using a syntax similar to that used
in the rule definitions that appear outside the Ruby code blocks.

Thanks again for your advice and apologies if this is considered
off-topic.

On Tue, Apr 24, 2007 at 06:52:14AM +0900, Andrew G. wrote:

That string is then passed to the Ruby interpreter and is meant to be
run (from within a specific context that our interpreter determines). In
these bits we don’t want just our language running about, of course, we
want full-blown Ruby code with extensions that allow a programmer to
refer to the graph traversal rules using a syntax similar to that used
in the rule definitions that appear outside the Ruby code blocks.

And my suggestion still stands: if what you want to appear inside {…}
is a
language which has -> as an operator, then a ‘clean’ (albeit
heavyweight)
option is to write your own expression parser using an LALR parser
generator.

The expression parser can build a syntax tree, and then you can either
walk
this tree yourself, or use it to generate Ruby code as its output, which
you
can then run.

A completely different option would be to use Perl instead of Ruby,
since
Perl has a -> dereference operator. But then you will have to put lots
of
dollar signs and curly brackets in.

B.

On 4/24/07, Andrew G. [email protected] wrote:

want full-blown Ruby code with extensions that allow a programmer to
refer to the graph traversal rules using a syntax similar to that used
in the rule definitions that appear outside the Ruby code blocks.

Rather than leaving the |{}| blocks entirely alone, you could
preprocess them to change the → to something ruby will accept, and
then run the interpreter over the preprocessed string. Won’t be a
trivial task, but should be easier than any of the alternatives.

martin

El mar, 24-04-2007 a las 06:52 +0900, Andrew G.
escribió:> (I know, it’s very ugly… In the next version we’ll replace all the

xml-ish tags with angle brackets and make it all much more succinct.)

(Did I say angle brackets…? I meant curlies… I guess now I’m
really off-topic… sorry.)

El mié, 25-04-2007 a las 00:04 +0900, Martin DeMello
escribió:> Rather than leaving the |{}| blocks entirely alone, you could

preprocess them to change the -> to something ruby will accept, and
then run the interpreter over the preprocessed string. Won’t be a
trivial task, but should be easier than any of the alternatives.

El mar, 24-04-2007 a las 17:48 +0900, Brian C.
escribió:> On Tue, Apr 24, 2007 at 06:52:14AM +0900, Andrew G. wrote:

generator.

The expression parser can build a syntax tree, and then you can either walk
this tree yourself, or use it to generate Ruby code as its output, which you
can then run.

OK. Everything seems to indicate this is the way to go, in the
long-to-medium term. Thanks, Brian, Martin and everyone else, for all
your help.

Andrew