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.
25610780d5bc83006b9bf9fdba37b93c?d=identicon&s=25 Dirk Traulsen (Guest)
on 2006-03-29 06: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
C1bcb559f87f356698cfad9f6d630235?d=identicon&s=25 Hal Fulton (Guest)
on 2006-03-29 07:19
(Received via mailing list)
Dirk Traulsen 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
7fc44a188234969e359b5f901e85fee8?d=identicon&s=25 Just Another Victim of the Ambient Morality (Guest)
on 2006-03-29 07:44
(Received via mailing list)
"Dirk Traulsen" <dirk.traulsen@lypso.de> wrote in message
news:442A2F49.10564.F61BC9B@dirk.traulsen.lypso.de...
> 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...
25610780d5bc83006b9bf9fdba37b93c?d=identicon&s=25 Dirk Traulsen (Guest)
on 2006-03-29 07:53
(Received via mailing list)
Am 29 Mar 2006 um 14:18 hat Hal Fulton geschrieben:

> Dirk Traulsen 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
25610780d5bc83006b9bf9fdba37b93c?d=identicon&s=25 Dirk Traulsen (Guest)
on 2006-03-29 08:15
(Received via mailing list)
Am 29 Mar 2006 um 14:43 hat Just Another Victim of the Am geschrieben:

>
> "Dirk Traulsen" <dirk.traulsen@lypso.de> 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
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-29 08:59
(Received via mailing list)
Dirk Traulsen wrote:
> Am 29 Mar 2006 um 14:18 hat Hal Fulton geschrieben:
>
>> Dirk Traulsen 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
Ced5fff44ff8929fc974012ea108b284?d=identicon&s=25 vsv (Guest)
on 2006-03-29 09:38
(Received via mailing list)
in lisp we have macro which does not evaluate arguments,
is it possible in Ruby?
Sergey
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-29 10: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
Ced5fff44ff8929fc974012ea108b284?d=identicon&s=25 vsv (Guest)
on 2006-03-29 10: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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-29 15: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 Gray II
Ced5fff44ff8929fc974012ea108b284?d=identicon&s=25 vsv (Guest)
on 2006-03-29 16: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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-29 16: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 Gray II
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-29 16: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 Gray II
F0d821a746f93cece1240d52d3e2617f?d=identicon&s=25 Pierre-Charles David (Guest)
on 2006-03-29 17:03
(Received via mailing list)
On 3/29/06, James Edward Gray II <james@grayproductions.net> 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).
Ced5fff44ff8929fc974012ea108b284?d=identicon&s=25 vsv (Guest)
on 2006-03-29 17: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
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-04-01 22:27
(Received via mailing list)
On Mar 29, 2006, at 9:53 AM, James Edward Gray 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.