Generating Functions in Ruby

R

Robert Klemme

your example generates code looks like this:
params =3D x1, x2, x3, x4
But with that I get an error (eval):3:in `+': can't convert Fixnum
into String (TypeError)

Without the code you are executing that error is pretty useless.

It works for me:

irb(main):023:0> STUB_CALLS=3Dfalse
(irb):23: warning: already initialized constant STUB_CALLS
=3D> false
irb(main):024:0> GET_VALUE "f", "m", "r", 4
def f(x0, x1, x2, x3)

oai =3D OA.instance
handle =3D oai.getWIN32OLEHandle()
handle.call(['MethodNameIn','Params'],['m', [x0, x1, x2, x3]]);
ret_val =3D handle.GetControlValue(r);
error =3D handle.GetControlValue('error out');
return oai.checkForError(error) ? 'NaN': ret_val

end
=3D> nil
irb(main):025:0> STUB_CALLS=3Dtrue
(irb):25: warning: already initialized constant STUB_CALLS
=3D> true
irb(main):026:0> GET_VALUE "f", "m", "r", 4
def f(x0, x1, x2, x3)
printf("Calling m(x0, x1, x2, x3) with parameters <%p>\n", [x0, x1, x2, x3]=
)
end
=3D> nil
irb(main):027:0>

(with my definition of GET_VALUE from earlier)
Yes, I could use this, but still I need to assembly this line since I
dont know the number of input parameters at coding time. And I know
that no input parameters contain any expressions that needs to be
evaluated since it is an input from my generated function.

I find the solution with printf "%p" and the Array more elegant.

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
7

7stud --

Speaking of elegance, you can change this:

class <<self;self;end.class_eval code

to this:

instance_eval(code)
 
7

7stud --

Andreas Lundgren wrote in post #1000535:
First params does not contain a simple string;
please note the escaped string characters in the code
that generates params. Kind of strings within strings

Yes, I noted that--see comment 6). What I failed to recognize was that
the line:

params = #{params}

was part of a multiline string.


"1) Strings are mutable in ruby, so get rid of all those +'s." - I'm
not sure that I understand this but it sounds interesting, what does
it mean?

Every quoting mechanism creates a string and every + creates a new
combined string. So it's more efficient to use string interpolation:

i = 2
params = 'x1.to_s'
params = "#{params}, x#{i}.to_s"
p params

--output:--
"x1.to_s, x2.to_s"


In ruby not only can you push elements onto an array with the << method,
you can also push a string onto another string with the << method--which
alters the first string:


i = 2
params = 'x1.to_s'
params = "#{params}, x#{i}.to_s"

puts params
puts params.object_id

params << ', x3.to_s'

puts params
puts params.object_id

--output:--
x1.to_s, x2.to_s
77684510
x1.to_s, x2.to_s, x3.to_s
77684510
 
7

7stud --

7stud -- wrote in post #1000754:
Andreas Lundgren wrote in post #1000535:

What I failed to recognize was that the line:

params = #{params}

was part of a multiline string.




Every quoting mechanism creates a string and every + creates a new
combined string. So it's more efficient to use string interpolation:

i = 2
params = 'x1.to_s'
params = "#{params}, x#{i}.to_s"
p params

--output:--
"x1.to_s, x2.to_s"


In ruby not only can you push elements onto an array with the << method,
you can also use the << method to push a string onto another
string--which
alters the first string:


i = 2
params = 'x1.to_s'
params = "#{params}, x#{i}.to_s"

puts params
puts params.object_id

params << ', x3.to_s'

puts params
puts params.object_id

--output:--
x1.to_s, x2.to_s
77684510
x1.to_s, x2.to_s, x3.to_s
77684510

So your loop here:

params = 'x1.to_s';
for i in 2..no_of_params do
arg_list = arg_list + ', x' + i.to_s;
params = params + ' + \', \' + x' + i.to_s + '.to_s';
end
params = params+';';


would simplify to:


num_params = 4
params = 'x1.to_s'

2.upto(num_params).each do |i|
params << ", x#{i}.to_s"
end

p params

--output:--
"x1.to_s, x2.to_s, x3.to_s, x4.to_s"


Also, compare that output to the output your loop produces:

"x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s"

You would get many errors using that string as an argument list for a
method.
 
A

Andreas Lundgren

--output:--
"x1.to_s, x2.to_s, x3.to_s, x4.to_s"

Also, compare that output to the output your loop produces:

  "x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s"

You would get many errors using that string as an argument list for a
method.

I need this since parameters to win32ole are sent as a string with a
comma separated list of arguments. That is to send in x1=1, x2='A' and
x3=1.5 I do the call:
handle.call(['MethodNameIn','Params'],['x1, x2, x3', '1, A, 1.5']);

The receiver mechanism does an "explode" on "," and it's then up to
the receiver to type cast the different elements to the expected types
(integer, character, float in this example)

BR,
Andreas
 
7

7stud --

Andreas Lundgren wrote in post #1000859:
--output:--
"x1.to_s, x2.to_s, x3.to_s, x4.to_s"

Also, compare that output to the output your loop produces:

"x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s"

You would get many errors using that string as an argument list for a
method.

I need this since parameters to win32ole are sent as a string with a
comma separated list of arguments. That is to send in x1=1, x2='A' and
x3=1.5 I do the call:
handle.call(['MethodNameIn','Params'],['x1, x2, x3', '1, A, 1.5']);

If you need to send the string 'x1, x2, x3', then you need to create
that string, not this garbage:

"x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s"


Do you not see the difference between these two strings:

"x1, x2, x3"
"x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s"


Do you not see that those strings have different lengths? You seem to
think that ruby is going to do some type of eval on the second string
and you will end up with the first string, but ruby is not going to do
that. The second string above is a *string*, it is not an *expression*.
 
7

7stud --

Andreas Lundgren wrote in post #1000859:
How do you get from this function signature:
def GET_VALUE(f_name, method, return_format, no_of_params)

to this:
handle.call(['MethodNameIn','Params'],['x1, x2, x3', '1, A, 1.5']);

Where do 1, 'A', and 1.5 come from?
 
A

Andreas Lundgren

Hi!

This will be my last post in this thread, since now I'm back
explaining what was already described in the beginning.

Thanks all for your good answers.

If you just found this thread and are looking for answers about how to
generate functions in Ruby, the begining of this thread is very
informative.
How do you get from this function signature:
def GET_VALUE(f_name, method, return_format, no_of_params) to this:
handle.call(['MethodNameIn','Params'],['x1, x2, x3', '1, A, 1.5']);

This is described earlier in this thread, see my post from Mon, 23 May
2011 05:56:34
Where do 1, 'A', and 1.5 come from?

Thas in example of input from the control layer that calls the
generated ruby glue function.

BR,
Andreas
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top