Strange order of execution


#1

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


#2

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? :wink:

Hal


#3

“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…


#4

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


#5

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? :wink:

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


#6

in lisp we have macro which does not evaluate arguments,
is it possible in Ruby?
Sergey


#7

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

#8

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

#9

Is there something you cannot do without?
can’t name it now, but I don’t have enough practical experience with
Ruby :frowning:
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 :slight_smile:

regars
Sergey


#10

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

| >> 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


#11

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 :slight_smile:

We have it today:

ruby_code = “2 + 2”
=> “2 + 2”

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

James Edward G. II


#12

On Mar 29, 2006, at 8:43 AM, vsv wrote:

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

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


#13

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


#14

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).


#15

| >> 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 :slight_smile:

BRs
Sergey


#16

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.