Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #4735 > unrolled thread

Generating Functions in Ruby

Started byAndreas Lundgren <andreas.lundgren.x@gmail.com>
First post2011-05-18 06:44 -0700
Last post2011-05-24 16:54 -0500
Articles 20 on this page of 28 — 6 participants

Back to article view | Back to comp.lang.ruby


Contents

  Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-18 06:44 -0700
    Re: Generating Functions in Ruby Steve Klabnik <steve@steveklabnik.com> - 2011-05-18 09:34 -0500
    Re: Generating Functions in Ruby Robert Klemme <shortcutter@googlemail.com> - 2011-05-18 09:54 -0500
      Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-18 14:44 -0500
      Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-18 20:55 -0500
        Re: Generating Functions in Ruby Robert Klemme <shortcutter@googlemail.com> - 2011-05-19 08:31 +0200
          Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-19 13:00 -0500
            Re: Generating Functions in Ruby Robert Klemme <shortcutter@googlemail.com> - 2011-05-20 01:28 -0500
              Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-23 05:54 -0700
                Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-23 16:25 -0500
    Re: Generating Functions in Ruby Thomas Preymesser <thopre@gmail.com> - 2011-05-19 04:35 -0500
    Re: Generating Functions in Ruby Brian Candler <b.candler@pobox.com> - 2011-05-19 10:06 -0500
    Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-23 16:09 -0500
    Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-23 20:51 -0500
    Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-23 21:07 -0500
      Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-24 00:10 -0700
        Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-24 00:24 -0700
          Re: Generating Functions in Ruby Brian Candler <b.candler@pobox.com> - 2011-05-24 03:12 -0500
          Re: Generating Functions in Ruby Robert Klemme <shortcutter@googlemail.com> - 2011-05-24 03:39 -0500
            Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-24 06:46 -0700
              Re: Generating Functions in Ruby Robert Klemme <shortcutter@googlemail.com> - 2011-05-24 10:20 -0500
        Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-24 17:27 -0500
          Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-24 17:53 -0500
            Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-25 03:59 -0700
              Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-25 12:26 -0500
              Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-25 17:12 -0500
                Re: Generating Functions in Ruby Andreas Lundgren <andreas.lundgren.x@gmail.com> - 2011-05-27 04:48 -0700
    Re: Generating Functions in Ruby 7stud -- <bbxx789_05ss@yahoo.com> - 2011-05-24 16:54 -0500

Page 1 of 2  [1] 2  Next page →


#4735 — Generating Functions in Ruby

FromAndreas Lundgren <andreas.lundgren.x@gmail.com>
Date2011-05-18 06:44 -0700
SubjectGenerating Functions in Ruby
Message-ID<5e21af14-befb-406e-b1c3-6758fe1527ab@s14g2000vbi.googlegroups.com>
Hi!

I'm looking for a construction in Ruby to generate a (big) set of
functions. I need these functions to be class methods and called by
unique names since they are called via an external API.

As an example, let me create two functions that hard codes an addition
and then uses this in a small test program.

def FivePlusFour
  return 5+4
end

def OnePlusSeven
  return 1+7
end

puts("Five + Four is " + FivePlusFour().to_s)
puts("One + Seven is " + OnePlusSeven().to_s)


I would like a way to generate the methods in runtime. As an old C-
programmer, I'm looking for something like this:

# Define a macro
define SUM_TEMPLATE(namn,x,y) \\
def namn \\
  return x+y \\
end

# Create each function with a one-liner in runtime.
SUM_TEMPLATE(FivePlusFour, 5, 4)
SUM_TEMPLATE(OnePlusSeven, 1, 7)

# Test program
puts("Five + Four is " + FivePlusFour().to_s)
puts("One + Seven is " + OnePlusSeven().to_s)

Is this possible in Ruby?

(Please don't reply how to solve this silly example in a better way,
the true use case is of cause much more complex. But conceptually it's
the same.)

Best Regards,
Andreas Lundgren - Sweden

[toc] | [next] | [standalone]


#4737

FromSteve Klabnik <steve@steveklabnik.com>
Date2011-05-18 09:34 -0500
Message-ID<BANLkTi=bR3CSaHi2mFz9TtUjHvHLXgeuFA@mail.gmail.com>
In reply to#4735
[Note:  parts of this message were removed to make it a legal post.]

What you want is define_method. Ill gives you some links when I'm not on my
phone.

[toc] | [prev] | [next] | [standalone]


#4738

FromRobert Klemme <shortcutter@googlemail.com>
Date2011-05-18 09:54 -0500
Message-ID<BANLkTik9J+XjqBwd8Wo0_0v3qXheQB02Tg@mail.gmail.com>
In reply to#4735
On Wed, May 18, 2011 at 3:46 PM, Andreas Lundgren
<andreas.lundgren.x@gmail.com> wrote:
> Hi!
>
> I'm looking for a construction in Ruby to generate a (big) set of
> functions. I need these functions to be class methods and called by
> unique names since they are called via an external API.
>
> As an example, let me create two functions that hard codes an addition
> and then uses this in a small test program.
>
> def FivePlusFour
>  return 5+4
> end
>
> def OnePlusSeven
>  return 1+7
> end
>
> puts("Five + Four is " + FivePlusFour().to_s)
> puts("One + Seven is " + OnePlusSeven().to_s)
>
>
> I would like a way to generate the methods in runtime. As an old C-
> programmer, I'm looking for something like this:
>
> # Define a macro
> define SUM_TEMPLATE(namn,x,y) \\
> def namn \\
>  return x+y \\
> end
>
> # Create each function with a one-liner in runtime.
> SUM_TEMPLATE(FivePlusFour, 5, 4)
> SUM_TEMPLATE(OnePlusSeven, 1, 7)
>
> # Test program
> puts("Five + Four is " + FivePlusFour().to_s)
> puts("One + Seven is " + OnePlusSeven().to_s)
>
> Is this possible in Ruby?

def SUM_TEMPLATE(name, x, y)
  class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
end

> (Please don't reply how to solve this silly example in a better way,
> the true use case is of cause much more complex. But conceptually it's
> the same.)

Is it really?  Do you always have one name and two values as input?
Can you give a bit more contextual information?

Cheers

robert

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

[toc] | [prev] | [next] | [standalone]


#4742

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-18 14:44 -0500
Message-ID<57836d5d927311efda42e4036904bf8d@ruby-forum.com>
In reply to#4738
Robert K. wrote in post #999483:
> On Wed, May 18, 2011 at 3:46 PM, Andreas Lundgren
> <andreas.lundgren.x@gmail.com> wrote:
>> return 5+4
>> I would like a way to generate the methods in runtime. As an old C-
>> SUM_TEMPLATE(OnePlusSeven, 1, 7)
>>
>> # Test program
>> puts("Five + Four is " + FivePlusFour().to_s)
>> puts("One + Seven is " + OnePlusSeven().to_s)
>>
>> Is this possible in Ruby?
>
> def SUM_TEMPLATE(name, x, y)
>   class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
> end
>

>> I need these functions to be class methods

..of what class?  Perhaps something like this:


def SUM_TEMPLATE(the_class, meth_name, x, y)
  class_obj = Object.const_get(the_class)

  class_obj.singleton_class.class_eval do
    define_method(meth_name) do
      x + y
    end
  end
end


class Dog
end

SUM_TEMPLATE('Dog', 'FivePlusFour', 5, 4)
puts Dog.FivePlusFour

--output:--
9

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4752

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-18 20:55 -0500
Message-ID<b170292747e065962ce90f546e15cccd@ruby-forum.com>
In reply to#4738
Robert K. wrote in post #999483:
>
> def SUM_TEMPLATE(name, x, y)
>   class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
> end
>

I'm curious how you expected the op to use that method?

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4753

FromRobert Klemme <shortcutter@googlemail.com>
Date2011-05-19 08:31 +0200
Message-ID<93jrqvFrf0U2@mid.individual.net>
In reply to#4752
On 19.05.2011 03:55, 7stud -- wrote:
> Robert K. wrote in post #999483:
>>
>> def SUM_TEMPLATE(name, x, y)
>>    class<<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
>> end
>>
>
> I'm curious how you expected the op to use that method?

I am not sure I get your point.  The method was intended to be used as a 
top level method similarly to how he formulated his C macro sample.

$ ruby19 <<CODE
 > def SUM_TEMPLATE(name, x, y)
 >   class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
 > end
 > SUM_TEMPLATE("f",1,2)
 > p f
 > CODE
3

But, frankly, this use case seems to be so far away from his real use 
case that this approach is likely not what is needed.  Since I have no 
further information I stick with the example and leave speculation about 
the nature of the real issue aside.

Kind regards

	robert

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

[toc] | [prev] | [next] | [standalone]


#4775

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-19 13:00 -0500
Message-ID<41214f15ab9bccbeb6ceab7f7fb220b0@ruby-forum.com>
In reply to#4753
Robert K. wrote in post #999582:
>
> I am not sure I get your point.  The method was intended to be used as a
> top level method similarly to how he formulated his C macro sample.
>
> $ ruby19 <<CODE
>  > def SUM_TEMPLATE(name, x, y)
>  >   class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
>  > end
>  > SUM_TEMPLATE("f",1,2)
>  > p f
>  > CODE
> 3
>

Oh, okay.  But that isn't a class method.

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4796

FromRobert Klemme <shortcutter@googlemail.com>
Date2011-05-20 01:28 -0500
Message-ID<BANLkTinzF8wMFVU0NVcP4p5XvTgDAx3-7A@mail.gmail.com>
In reply to#4775
On Thu, May 19, 2011 at 8:00 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
> Robert K. wrote in post #999582:
>>
>> I am not sure I get your point.  The method was intended to be used as a
>> top level method similarly to how he formulated his C macro sample.
>>
>> $ ruby19 <<CODE
>>  > def SUM_TEMPLATE(name, x, y)
>>  >   class <<self;self;end.class_eval "def #{name}; #{x} + #{y}; end"
>>  > end
>>  > SUM_TEMPLATE("f",1,2)
>>  > p f
>>  > CODE
>> 3
>>
>
> Oh, okay.  But that isn't a class method.

That's true.  But OP mentioned class methods in just one sentence but
all his examples (Ruby and C) were not using class methods.  Besides
it should not be too difficult to modify the code to generate class
methods.  I still would like to see more realistic requirements as all
speculations about proper ways to solve the problem are moot as long
as we do not know the problem.

Kind regards

robert

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

[toc] | [prev] | [next] | [standalone]


#4922

FromAndreas Lundgren <andreas.lundgren.x@gmail.com>
Date2011-05-23 05:54 -0700
Message-ID<5d31b677-f378-4a9a-9046-65dd3dbbfab1@dn9g2000vbb.googlegroups.com>
In reply to#4796
Hi, and thank you all!

Yes, the example is far from reallity in one sense, but your example
really did the trick and conceptually it's the same!

So, for the interessted reader, I will provide my code here. (I have a
similar method for setting values.) Via an Ole32 server i communicate
with a sw that can extract all types of data from a odd type of
database.

(My final dilemma is how to get the value of STUB_CALLS into
Templates.rb by defining it in my test program Impl.rb. To define it
direcrly in the template file in not very nice... And of cause I don't
want to have to define it at all when running in non-test-mode.)

______Templates.rb______
STUB_CALLS = 1; # If this is '1', all instruments are stubed for
debugging purpouse

def GET_VALUE(f_name, method, return_format, no_of_params)
# Make a parameter list and an argument list
  if 0<no_of_params
    arg_list = 'x1';
    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+';';
  else
    arg_list = '';
    params = 0;
  end

  if (0==STUB_CALLS)
    class <<self;self;end.class_eval "def #{f_name}(#{arg_list});
      handle = OA.instance.getWIN32OLEHandle();
      params = #{params};
      handle.call(['MethodNameIn','Params'],[#{method},params]);
      ret_val = handle.GetControlValue(#{return_format});
      error = handle.GetControlValue('error out');
      if OA.instance.checkForError(error);
        return 'NaN';
      else;
        return ret_val;
      end;
    end"
  else
    class <<self;self;end.class_eval "def #{f_name}(#{arg_list});
      params = #{params};
      puts('Calling #{method}(#{arg_list}) with parameters <' + params
+ '>');
    end"
  end
end



______Templates.rb______   <- this is just three out of many
methods...
require '.\Difinitions.rb'
#***ParamsList  ["database"]
GET_VALUE('customer_getFrequency', 'getcustomerfreq', 'ResultDbl', 1)

#***ParamsList  ["database"]
GET_VALUE('customer_getSpend_thr', 'getcustspend', 'ResultDbl', 1)

#***ParamsList  ["database", "start", "stop", "inc"]
GET_VALUE('shop_GetFundReq', 'getfundreq', 'ResultDbl', 4)



______Impl.rb______ <- The implementation does already exist, and it's
huge. This is just a few lines from my test program:
require '.\Difinitions.rb'
f = customer_getFrequency(cdb)
s = customer_getSpend_thr(cdb)
fr = shop_GetFundReq(sdb, 20110101, 20110201, 'all')

[toc] | [prev] | [next] | [standalone]


#4949

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-23 16:25 -0500
Message-ID<dba0a673be313aaa604fd13aeabd3781@ruby-forum.com>
In reply to#4922
Andreas Lundgren wrote in post #1000369:
>

5) Most ruby programmers don't use for-in because that construct just 
calls each(), so ruby programmers call each() directly:

2..no_of_params.each do |i|
  arg_list = arg_list + ', x' + i.to_s;
  params = params + ' + \', \' + x' + i.to_s + '.to_s';
end

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4757

FromThomas Preymesser <thopre@gmail.com>
Date2011-05-19 04:35 -0500
Message-ID<BANLkTikRXDC=eZqr0Pa7EqVSq_Hv+8qS4Q@mail.gmail.com>
In reply to#4735
[Note:  parts of this message were removed to make it a legal post.]

On 18 May 2011 15:46, Andreas Lundgren <andreas.lundgren.x@gmail.com> wrote:

> I'm looking for a construction in Ruby to generate a (big) set of
> functions. I need these functions to be class methods and called by
> unique names since they are called via an external API.
>

another way could be the method_missing method.
In my gem 'weekday' you can call methods like first_monday(yyyy,mm) ,
third_tuesday(...), last_sunday(...) and any other combination of a number
and weekday.

-Thomas


-- 
Thomas Preymesser
thopre@gmail.com
http://thopre.googlepages.com/
http://thopre.wordpress.com/

[toc] | [prev] | [next] | [standalone]


#4764

FromBrian Candler <b.candler@pobox.com>
Date2011-05-19 10:06 -0500
Message-ID<6607a8ddf9ad5da65d6ca70c12e5ae6c@ruby-forum.com>
In reply to#4735
Have a look at how ActionView (from Rails) caches its compiled 
templates. It does this by defining methods on a module.

[actionpack/lib/action_view/template.rb]

      def compile(view, mod) #:nodoc:
..
        code  = arity.abs == 1 ? @handler.call(self) : 
@handler.call(self, view)

        source = <<-end_src
          def #{method_name}(local_assigns)
            _old_output_buffer = @output_buffer;#{locals_code};#{code}
          ensure
            @output_buffer = _old_output_buffer
          end
        end_src
..
        begin
          mod.module_eval(source, identifier, 0)
          ObjectSpace.define_finalizer(self, Finalizer[method_name, 
mod])
        rescue Exception => e # errors from template code
          if logger = (view && view.logger)
            logger.debug "ERROR: compiling #{method_name} RAISED #{e}"
            logger.debug "Function body: #{source}"
            logger.debug "Backtrace: #{e.backtrace.join("\n")}"
          end

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4948

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-23 16:09 -0500
Message-ID<8511c0a8801106dc8bf820321807ccff@ruby-forum.com>
In reply to#4735
1) Strings are mutable in ruby, so get rid of all those +'s.

2) Don't use back slashes in strings--unless you specifically intend to 
use an escape character.

3)
> My final dilemma is how to get the value of STUB_CALLS into
> Templates.rb by defining it in my test program Impl.rb.

Why can't your methods have a 'debug' parameter with a default value? 
Then for debugging, you can 'override' the default.

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4957

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-23 20:51 -0500
Message-ID<229eaaafa7ab13dbdc46143d3c08a655@ruby-forum.com>
In reply to#4735
7) If you will have less than 9 parameters, you can do this:

param_str = temp = 'x1'

10.times do |i|
  temp = temp.succ
  param_str << ', ' << temp
end

p param_str

--output:--
"x1, x2, x3, x4, x5, x6, x7, x8, x9, y0, y1"

But in ruby, you can define variadic methods:

def my_meth(*args)
  args.each {|arg| p arg}
end

my_meth(1, 2, 3)
my_meth('a', 'b', 4)

--output:--
1
2
3
"a"
"b"
4

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4959

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-05-23 21:07 -0500
Message-ID<dc2df7d480159878c42c65807d568cd8@ruby-forum.com>
In reply to#4735
10)

params = 'hello'
params = #{params};

--output:--
prog.rb:3: syntax error, unexpected $end


11) Here's some advice: buy a beginning ruby book and read it.

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4964

FromAndreas Lundgren <andreas.lundgren.x@gmail.com>
Date2011-05-24 00:10 -0700
Message-ID<151562ef-aebd-4999-8b7b-816c21a7c6df@m40g2000vbt.googlegroups.com>
In reply to#4959
Hi!

This is why I did not put the real example at first, because then some
people that do not understand the code always brings these stupid
comments. I do not have any compilation errors, and the code works
perfectly, so I don't think that I need a beginning ruby book for that
reason. :-) (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).

I cannot change the function signature since I cannot change the upper
layer that makes calls to my Ruby glue layer... That is why I would
like to introduce debugging by making changes in the glue layer at
"compile" time. (In C I would have used a #define for the pre
processor.)

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

Thanks for input about creating loops, new language = new flavours,
and that is nice to adapt to! :-)

I think that I could make use of the variable parameter input, with
the extended error control code making sure all parameters are in
place, I think that this will be the same amount of code. But I
learned something new, so thanks!

BR,
Andreas

[toc] | [prev] | [next] | [standalone]


#4965

FromAndreas Lundgren <andreas.lundgren.x@gmail.com>
Date2011-05-24 00:24 -0700
Message-ID<71dec76a-e0c1-4a7e-b3e6-a397ca4be291@f9g2000vbz.googlegroups.com>
In reply to#4964
My bad to use the name "param" for two different content, but any
ways:

First params typically assembles to this:
x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s
Now I have created the code, not the string.

The line
params_2 = #{params};
extends to:
params_2 = x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s
and assembles my input so that
params_2 == 'myDB, 20110101, 20110201, all'

Output from the function when STUB_CALLS=1:
Calling shop_GetFundReq(x1, x2, x3, x4) with parameters <myDB,
20110101, 20110201, all>

BR,
Andreas

[toc] | [prev] | [next] | [standalone]


#4966

FromBrian Candler <b.candler@pobox.com>
Date2011-05-24 03:12 -0500
Message-ID<385d62a492942fc7a357c795049cbd57@ruby-forum.com>
In reply to#4965
Andreas Lundgren wrote in post #1000537:
> The line
> params_2 = #{params};
> extends to:
> params_2 = x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s

Or you could do it like this:

params_2 = "#{x1}, #{x2}, #{x3}, #{x4}"

#{} interpolates the value of an expression into a string and calls to_s 
automatically.

A slightly more DRY version:

params_2 = [x1, x2, x3, x4].join(", ")

Again, to_s is called automatically in this case.

Finally, if you used the *args syntax to collect a variable number of 
args into an array, then it would become

params_2 = args.join(", ")

or even just: handle.call(['MethodNameIn','Params'],[method]+args)

> Output from the function when STUB_CALLS=1:

Tiny suggestion: STUB_CALLS = false / true would be clearer, because 
then you could say

do_something if STUB_CALLS

rather than

do_something if STUB_CALLS != 0

A global variable ($stub_calls) would arguably be preferable, since you 
can change it at runtime without generating a warning. And better again 
would be an instance variable of a class or module, because then it 
lives in its own namespace.

module MyStuff
  @stub_calls = false   # set the default
  def self.stub_calls
    @stub_calls
  end
  def self.stub_calls=(x)
    @stub_calls = x
  end
end

puts MyStuff.stub_calls
MyStuff.stub_calls = true
puts MyStuff.stub_calls

Another thing to look at is using heredoc, as it means you don't have to 
worry about quoting double-quotes:

    class <<self;self;end.class_eval <<EOS
      def #{f_name}(#{arg_list})
        puts "Hello world"
      end
    EOS

Anyway, these are just tiny style suggestions. Having working code is 
worth far more :-)

-- 
Posted via http://www.ruby-forum.com/.

[toc] | [prev] | [next] | [standalone]


#4967

FromRobert Klemme <shortcutter@googlemail.com>
Date2011-05-24 03:39 -0500
Message-ID<BANLkTin-UeuEPYjg_SaZNyGQEY=iO3fvkw@mail.gmail.com>
In reply to#4965
On Tue, May 24, 2011 at 9:25 AM, Andreas Lundgren
<andreas.lundgren.x@gmail.com> wrote:
> My bad to use the name "param" for two different content, but any
> ways:
>
> First params typically assembles to this:
> x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s

That does not look good.  If you have to encode numbers in variable
names, you probably rather want to use an Array for that or even
generate that directly:

params = no_of_params.times.map {|i| "x#{i}"}.join(', ')

> Now I have created the code, not the string.
>
> The line
> params_2 = #{params};
> extends to:
> params_2 = x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s
> and assembles my input so that
> params_2 == 'myDB, 20110101, 20110201, all'

When looking at your posting from 2:55 you don't really need "params =
.." in the generated code.

> Output from the function when STUB_CALLS=1:
> Calling shop_GetFundReq(x1, x2, x3, x4) with parameters <myDB,
> 20110101, 20110201, all>

SUB_CALLS should be a boolean and treated as such.

I can see why 7stud wrote his recommendation: the code looks overly
complicated.  Also, there are some issues, for example:

     handle.call(['MethodNameIn','Params'],[#{method},params]);

This only works if you call that method with something like

(..., "\"myMethod\"", ...)

where you should really passing the name plainly as string.  Makes
usage much simpler and more robust.  So in the method body you then
had

     handle.call(['MethodNameIn','Params'],['#{method}', params]);

Same reasoning applies in other locations such as return_format.

And if you get rid of the no_of_params you can simply use *args and do
not have to go through the hassle generating argument lists.  If may
be though that you want to be able to query arity from the method and
have it fail fast if the argument list does not match in which case
it's OK to generate the argument list.

All in all it seems this is simpler and more redundancy free:

def GET_VALUE(f_name, method, return_format, no_of_params)
  args = no_of_params.times.map {|i| "x#{i}"}.join(", ")

  body = if STUB_CALLS
    %Q{printf("Calling #{method}(#{args}) with parameters <%p>\\n", [#{args}])}
  else
    %Q{
      oai = OA.instance
      handle = oai.getWIN32OLEHandle()
      handle.call(['MethodNameIn','Params'],['#{method}', [#{args}]]);
      ret_val = handle.GetControlValue(#{return_format});
      error = handle.GetControlValue('error out');
      return oai.checkForError(error) ? 'NaN': ret_val
    }
  end

  code = "def #{f_name}(#{args})\n#{body}\nend"
  puts code if ENV['DEBUG'] == 'true'
  class <<self;self;end.class_eval code
end

Cheers

robert


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

[toc] | [prev] | [next] | [standalone]


#4989

FromAndreas Lundgren <andreas.lundgren.x@gmail.com>
Date2011-05-24 06:46 -0700
Message-ID<ac4f0814-c75d-4c1e-b8f4-c277b3c94f0b@f11g2000vbx.googlegroups.com>
In reply to#4967
> > First params typically assembles to this:
> > x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s
>
> That does not look good.  If you have to encode numbers in variable
> names, you probably rather want to use an Array for that or even
> generate that directly:
>
> params = no_of_params.times.map {|i| "x#{i}"}.join(', ')

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

If it should work, I recon that it has to look like this:
params = "\"\#{" + no_of_params.times.map {|i| "x#{i}"}.join("}, \#{")
+ "}\""

becaus I need the generated code to look like this:
params = "#{x1}, #{x2}, #{x3}, #{x4}"


> handle.call(['MethodNameIn','Params'],[#{method},params]);
Yes, this was a bug...


> params_2 = "#{x1}, #{x2}, #{x3}, #{x4}"
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.



Join and times.map was kind of cool, my prototype has now replaced the
first loops with this:
arg_list = no_of_params.times.map {|i| "x#{i}"}.join(", ")
args = no_of_params.times.map {|i| "x#{i}.to_s"}.join("+','+")

(Using #{} instead of .to_s is basically the same:
args = "\"\#{" + no_of_params.times.map {|i| "x#{i}"}.join("}, \#{") +
"}\""

BR,
Andreas

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.ruby


csiph-web