Forum: Ruby strange order of execution

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dirk T. (Guest)
on 2006-03-29 08:54
(Received via mailing list)
Hi list!

I had a strange effect, when I combined print with several strings
and a method.
Please look at this example:

##############
def method1
    print "string_2_method", " - "
    return "return_string_method - "
end

print "\n"
print "string_1", " - ", method1, "string_3\n"
##############

Surprisingly it results in:
string_2_method - string_1 - return_string_method - string_3

But I expected it to result in:
string_1 - string_2_method - return_string_method - string_3

Even if any method would be executed first, independant of the
position in the line, then shouldn't it be the following:
string_2_method - return_string_method - string_1 - string_3

Can somebody please explain this strange order of execution to me?

Thanks
Dirk
Hal F. (Guest)
on 2006-03-29 09:19
(Received via mailing list)
Dirk T. wrote:
>
> Can somebody please explain this strange order of execution to me?
>

All the arguments to your print are evaluated, including the
method call. So the stuff inside that method is printed first.
Then the print occurs normally (with your return value in place
of the method call). Thus your result.

However: Why would you ever do this?  ;)


Hal
Just Another Victim of the Ambient M. (Guest)
on 2006-03-29 09:44
(Received via mailing list)
"Dirk T." <removed_email_address@domain.invalid> wrote in message
news:removed_email_address@domain.invalid...
> end
>
> Even if any method would be executed first, independant of the
> position in the line, then shouldn't it be the following:
> string_2_method - return_string_method - string_1 - string_3
>
> Can somebody please explain this strange order of execution to me?

    Interestingly enough, this doesn't really have anything to do with
Ruby,
in particular...

    In your example, "method1" is a method call that executes and
returns a
value.  You are calling it as a parameter to another method call, the
one to
"print."  Just in case it makes it more clear to you, I will add the
optional brackets like how you would have to in some other languages...

print("\n")
print( "string_1", "-", method1(), "string3\n");

    So, you're calling "print" and passing it four parameters.  But,
with
the third parameter, you're passing in the return value of "method1."
Therefore, you need to call it and, as such, you will be calling it
before
you call "print."  But "method1" has a side effect.  It calls:

print( "string_2_method", "-")  # brackets added for possible clarity...

    So, because "method1" is called first, the string printed from
within
that method gets printed first, as its side effect.  Then the return
value
of that method gets returned to the caller, as a parameter to the method
call "print."  So then "print" gets called with its four parameters and
they
are printed, in that order.
    Hopefully, the order of your printed strings is a mystery no more...

    Again, this has nothing to do with Ruby.  This will happen in any
procedural programming language that I can think of...
Dirk T. (Guest)
on 2006-03-29 09:53
(Received via mailing list)
Am 29 Mar 2006 um 14:18 hat Hal F. geschrieben:

> Dirk T. wrote:
> >
> > Can somebody please explain this strange order of execution to me?
> >
>
> All the arguments to your print are evaluated, including the
> method call. So the stuff inside that method is printed first.

Alright, so the method calls are executed first already during
evaluation. I thought

print "string", method1

would be identical to

print "string"
print method1

> Then the print occurs normally (with your return value in place
> of the method call). Thus your result.

Ah, got it.

> However: Why would you ever do this?  ;)

To improve my still humble Ruby knowledge I was analyzing scripts I
find on the net to see whether I understand them. I found this case
and couldn't understand the output.

Thanks for your help!
Dirk
Dirk T. (Guest)
on 2006-03-29 10:15
(Received via mailing list)
Am 29 Mar 2006 um 14:43 hat Just Another Victim of the Am geschrieben:

>
> "Dirk T." <removed_email_address@domain.invalid> wrote in message
(..)
> > Can somebody please explain this strange order of execution to > > > me?
(..)
>     So, you're calling "print" and passing it four parameters.  But, with
> the third parameter, you're passing in the return value of "method1."
> Therefore, you need to call it and, as such, you will be calling it before
> you call "print."

That was my misunderstanding. I thought

print "string", method1

would be identical to

print "string"
print method1

> So, because "method1" is called first, the string printed from
> within that method gets printed first, as its side effect.
> Then the return value
> of that method gets returned to the caller, as a parameter to the method
> call "print."  So then "print" gets called with its four parameters and they
> are printed, in that order.
>     Hopefully, the order of your printed strings is a mystery no more...

That is very clear now. Thanks a lot for the really good explanation.

I must say that I'm impressed by the fast and friendly help of this
list even in case of this clear beginner question.

Dirk
Robert K. (Guest)
on 2006-03-29 10:59
(Received via mailing list)
Dirk T. wrote:
> Am 29 Mar 2006 um 14:18 hat Hal F. geschrieben:
>
>> Dirk T. wrote:
>>> Can somebody please explain this strange order of execution to me?
>>>
>> All the arguments to your print are evaluated, including the
>> method call. So the stuff inside that method is printed first.
>
> Alright, so the method calls are executed first already during evaluation. I thought

The method invocation *is* the evaluation.

> print "string", method1
>
> would be identical to
>
> print "string"
> print method1

No, not at all.  Btw, if you want to watch what's going on, you can
insert this at the top of your script and follow the execution as it's
printed

set_trace_func lambda {|*a| p a}

Kind regards

	robert
vsv (Guest)
on 2006-03-29 11:38
(Received via mailing list)
in lisp we have macro which does not evaluate arguments,
is it possible in Ruby?
Sergey
Robert K. (Guest)
on 2006-03-29 12:31
(Received via mailing list)
vsv wrote:
> in lisp we have macro which does not evaluate arguments,
> is it possible in Ruby?

No, unless you resort to putting your code into strings and evaluating
it later.  IMHO this looks ugly most of the time - not to mention
efficiency.  Is there something you cannot do without?

Kind regards

	robert
vsv (Guest)
on 2006-03-29 12:54
(Received via mailing list)
> Is there something you cannot do without?
can't name it now, but I don't have enough practical experience with
Ruby :(
btw: macros in lisp are expanded in compile time, so there is no any
efficiency lost.
I belive Ruby will get implemented in bytecode eventually, at that time
'compile' time evaluation feature will be required; and then, I hope,
we'll get 'read' time evaluation too (just dreaming :)

regars
Sergey
James G. (Guest)
on 2006-03-29 17:59
(Received via mailing list)
On Mar 29, 2006, at 2:53 AM, vsv wrote:

> I belive Ruby will get implemented in bytecode eventually, at that
> time
> 'compile' time evaluation feature will be required; and then, I hope,
> we'll get 'read' time evaluation too (just dreaming :)

We have it today:

 >> ruby_code = "2 + 2"
=> "2 + 2"
 >> "2 + 2 = #{eval(ruby_code)}"
=> "2 + 2 = 4"

James Edward G. II
vsv (Guest)
on 2006-03-29 18:45
(Received via mailing list)
|> we'll get 'read' time evaluation too (just dreaming :)
|
|We have it today:
James, you are dreaming too :)

| >> ruby_code = "2 + 2"
|=> "2 + 2"
| >> "2 + 2 = #{eval(ruby_code)}"
|=> "2 + 2 = 4"
it's not reader, but run-time string expantion,
reader it would be, when you can get result after _read_;
now in Ruby:
>> gets
"#{2+2}"
=> "\"\#{2+2}\"\n"
string was read and returned unmodified;

btw: why eval in your sample? "#{ruby_code}" is good enough for
evaluation sample in string;

Sergey
James G. (Guest)
on 2006-03-29 18:51
(Received via mailing list)
On Mar 29, 2006, at 8:43 AM, vsv wrote:

> |> we'll get 'read' time evaluation too (just dreaming :)
> |
> |We have it today:
> James, you are dreaming too :)

Sorry, I misunderstood what you were asking for.

> btw: why eval in your sample? "#{ruby_code}" is good enough for
> evaluation sample in string;

 >> ruby_code = "2 + 2"
=> "2 + 2"
 >> "2 + 2 = #{ruby_code}"
=> "2 + 2 = 2 + 2"

James Edward G. II
James G. (Guest)
on 2006-03-29 18:54
(Received via mailing list)
On Mar 29, 2006, at 8:43 AM, vsv wrote:

> reader it would be, when you can get result after _read_;
> now in Ruby:
>>> gets
> "#{2+2}"
> => "\"\#{2+2}\"\n"
> string was read and returned unmodified;

 >> require "erb"
=> true
 >> ruby_code = "<%= 2 + 2 %>"
=> "<%= 2 + 2 %>"
 >> template = ERB.new(ruby_code)
=> #<ERB:0x317020 @src="_erbout = ''; _erbout.concat(( 2 + 2 ).to_s);
_erbout", @safe_level=nil, @filename=nil>
 >> template.result
=> "4"

?

James Edward G. II
Pierre-Charles D. (Guest)
on 2006-03-29 19:03
(Received via mailing list)
On 3/29/06, James Edward G. II <removed_email_address@domain.invalid> wrote:
> => "2 + 2"
>  >> "2 + 2 = #{eval(ruby_code)}"
> => "2 + 2 = 4"

This is "read-time" evaluation only because currently read-time ==
evaluation time. If Ruby had a compilation phase, string interpolation
would need to be done at execution time. Otherwise a simple program
such as puts "Hello, #{gets}" would require user input during the
compilation phase...

Common Lisp for example has both compile-time evaluation (macros,
(eval-when (:compile) ...)) and read-time evaluation (#., #+ and #-,
the last two being used a little like #ifdef/#ifndef).
vsv (Guest)
on 2006-03-29 19:21
(Received via mailing list)
|   >> template = ERB.new(ruby_code)
| => #<ERB:0x317020 @src="_erbout = ''; _erbout.concat(( 2 + 2 ).to_s);

| _erbout", @safe_level=nil, @filename=nil>
|  >> template.result
| => "4"
|
| ?
ERB does nothing with Ruby reader,
Ruby does not support reader customization with Ruby code;
AFAIK, nobody complained so far :)

BRs
Sergey
Logan C. (Guest)
on 2006-04-02 00:27
(Received via mailing list)
On Mar 29, 2006, at 9:53 AM, James Edward G. II wrote:

> ?
If I may interject, in Lisp, you can do the equivalent of hooking
into the lexer, and then expanding something into a new sequence of
tokens, this is what he means by reader.
This topic is locked and can not be replied to.