strange order of execution

D

Dirk Traulsen

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
 
H

Hal Fulton

Dirk said:
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
 
J

Just Another Victim of the Ambient Morality

Dirk Traulsen said:
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?

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

Dirk Traulsen

Am 29 Mar 2006 um 14:18 hat Hal Fulton geschrieben:
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
 
D

Dirk Traulsen

Am 29 Mar 2006 um 14:43 hat Just Another Victim of the Am geschrieben:
(..)
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
 
R

Robert Klemme

Dirk said:
Am 29 Mar 2006 um 14:18 hat Hal Fulton geschrieben:


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
 
V

vsv

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

Robert Klemme

vsv said:
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
 
V

vsv

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
 
J

James Edward Gray II

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:
=> "2 + 2 = 4"

James Edward Gray II
 
V

vsv

|> 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:"#{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
 
J

James Edward Gray II

|> 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;
=> "2 + 2 = 2 + 2"

James Edward Gray II
 
J

James Edward Gray II

reader it would be, when you can get result after _read_;
now in Ruby:
"#{2+2}"
=> "\"\#{2+2}\"\n"
string was read and returned unmodified;
=> #<ERB:0x317020 @src="_erbout = ''; _erbout.concat(( 2 + 2 ).to_s);
_erbout", @safe_level=nil, @filename=nil>=> "4"

?

James Edward Gray II
 
P

Pierre-Charles David

We have it today:

=3D> "2 + 2 =3D 4"

This is "read-time" evaluation only because currently read-time =3D=3D
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).
 
V

vsv

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

Logan Capaldo

--Apple-Mail-16-259683664
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


=> #<ERB:0x317020 @src="_erbout = ''; _erbout.concat(( 2 +
2 ).to_s); _erbout", @safe_level=nil, @filename=nil>
=> "4"

?

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.
--Apple-Mail-16-259683664--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,204
Messages
2,571,065
Members
47,672
Latest member
svaraho

Latest Threads

Top