A method for summing several variables

H

Harry Truax

------=_NextPart_000_0174_01C4838F.445DB390
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Hi everyone,

Just wanted to say thank you for all of your suggestions and coding =
examples. I will be studying your ideas closely to see if I can =
implement them in our product. I really=20
do not have the leeway to alter our product's code structure, I have to =
live with this fact (argh!!).

Our field variables (the ones we do arithematic on) are set up like:

box1_1 =3D ''
box1_2 =3D ''
box1_3 =3D ''
box1_4 =3D ''
box1_5 =3D ''
box1_6 =3D ''
box1_7 =3D ''
box1_8 =3D ''
box1_9 =3D ''
box1_10 =3D ''
box1_11 =3D ''
etc.

The actual amount and thus naming of these variables vary from =
application to application. Some of the summing operations are quite =
lengthy as in:

box5_189 =3D $CUR % (box5_5.to_f + box5_10.to_f + box5_15.to_f + =
box5_20.to_f + box5_25.to_f + box5_30.to_f + box5_35.to_f + box5_40.to_f =
+ box5_45.to_f + box5_50.to_f + box5_55.to_f + box5_60.to_f + =
box5_65.to_f + box5_70.to_f + box5_75.to_f + box5_80.to_f + box5_85.to_f =
+ box5_90.to_f + box5_95.to_f + box5_100.to_f + box5_105.to_f + =
box5_110.to_f + box5_115.to_f + box5_120.to_f + box5_125.to_f + =
box5_130.to_f + box5_135.to_f + box5_140.to_f + box5_145.to_f + =
box5_150.to_f + box5_155.to_f + box5_160.to_f + box5_165.to_f + =
box5_170.to_f + box5_175.to_f + box5_180.to_f + box5_185.to_f + =
box5_187.to_f)

I will try to find a shortcut method to handle this based on your =
suggestions, but if I have to manually type in each box name in setting =
up the implementation, I may
as well just type in the lengthy sum operation as shown above.=20

Thanks again for all of your help,

Harry Truax
------=_NextPart_000_0174_01C4838F.445DB390--
 
A

Austin Ziegler

Hi everyone,

Just wanted to say thank you for all of your suggestions and coding examples. I will be studying your ideas closely to see if I can implement them in our product. I really
do not have the leeway to alter our product's code structure, I have to live with this fact (argh!!).

Our field variables (the ones we do arithematic on) are set up like:

box1_1 = ''
box1_2 = ''
box1_3 = ''
box1_4 = ''
box1_5 = ''
box1_6 = ''
box1_7 = ''
box1_8 = ''
box1_9 = ''
box1_10 = ''
box1_11 = ''
etc.

The actual amount and thus naming of these variables vary from application to application. Some of the summing operations are quite lengthy as in:

box5_189 = $CUR % (box5_5.to_f + box5_10.to_f + box5_15.to_f + box5_20.to_f + box5_25.to_f + box5_30.to_f + box5_35.to_f + box5_40.to_f + box5_45.to_f + box5_50.to_f + box5_55.to_f + box5_60.to_f + box5_65.to_f + box5_70.to_f + box5_75.to_f + box5_80.to_f + box5_85.to_f + box5_90.to_f + box5_95.to_f + box5_100.to_f + box5_105.to_f + box5_110.to_f + box5_115.to_f + box5_120.to_f + box5_125.to_f + box5_130.to_f + box5_135.to_f + box5_140.to_f + box5_145.to_f + box5_150.to_f + box5_155.to_f + box5_160.to_f + box5_165.to_f + box5_170.to_f + box5_175.to_f + box5_180.to_f + box5_185.to_f + box5_187.to_f)

I will try to find a shortcut method to handle this based on your suggestions, but if I have to manually type in each box name in setting up the implementation, I may
as well just type in the lengthy sum operation as shown above.

I didn't participate in the initial round, but why not do a generator
and then eval your generated string in the current binding?

s = (5..185).to_a.select { |e| e % 5 == 0 }.map { |e| "box5_#{e}.to_f" }
s << "box5_187.to_f"
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)]

This will work so long as there's some kind of pattern you can deal
with (I don't get the box5_187 in your example, but I added it as an
exception).

I tested in irb with:

v = (5..187).to_a
v = v.select { |e| (e % 5 == 0) or (e == 187) }.map { |e| "box5_#{e}" }
v << "box5_187"
b = binding
v.each_with_index { |e, i| eval("#{e} = 1.25", b) }
puts box5_10 # => 1.25
$CUR = "%020.10f"

# the above set the test data; the below is the implementation
s = (5..187).to_a.select { |e| (e % 5 == 0) or (e == 187) }
s.map! { |e| "box5_#{e}.to_f" }
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)
puts box5_189 # => 000000047.5000000000
puts v.size * 1.25 # => 47.5

-austin
 
L

Lennon Day-Reynolds

Austin,

The $SAFE level has to be set to 3 for Harry's project (per the thread
last week), so 'eval' is out.
 
H

Harry Truax

Thanks Austin,

But unfortunately $SAFE needs to be set to 3 which will preclude the use of
eval( ).

Harry

----- Original Message -----
From: "Austin Ziegler" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Monday, August 16, 2004 1:13 PM
Subject: Re: A method for summing several variables

examples. I will be studying your ideas closely to see if I can implement
them in our product. I reallyapplication to application. Some of the summing operations are quite lengthy
as in:box5_20.to_f + box5_25.to_f + box5_30.to_f + box5_35.to_f + box5_40.to_f +
box5_45.to_f + box5_50.to_f + box5_55.to_f + box5_60.to_f + box5_65.to_f +
box5_70.to_f + box5_75.to_f + box5_80.to_f + box5_85.to_f + box5_90.to_f +
box5_95.to_f + box5_100.to_f + box5_105.to_f + box5_110.to_f + box5_115.to_f
+ box5_120.to_f + box5_125.to_f + box5_130.to_f + box5_135.to_f +
box5_140.to_f + box5_145.to_f + box5_150.to_f + box5_155.to_f +
box5_160.to_f + box5_165.to_f + box5_170.to_f + box5_175.to_f +
box5_180.to_f + box5_185.to_f + box5_187.to_f)suggestions, but if I have to manually type in each box name in setting up
the implementation, I may
as well just type in the lengthy sum operation as shown above.

I didn't participate in the initial round, but why not do a generator
and then eval your generated string in the current binding?

s = (5..185).to_a.select { |e| e % 5 == 0 }.map { |e| "box5_#{e}.to_f" }
s << "box5_187.to_f"
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)]

This will work so long as there's some kind of pattern you can deal
with (I don't get the box5_187 in your example, but I added it as an
exception).

I tested in irb with:

v = (5..187).to_a
v = v.select { |e| (e % 5 == 0) or (e == 187) }.map { |e| "box5_#{e}" }
v << "box5_187"
b = binding
v.each_with_index { |e, i| eval("#{e} = 1.25", b) }
puts box5_10 # => 1.25
$CUR = "%020.10f"

# the above set the test data; the below is the implementation
s = (5..187).to_a.select { |e| (e % 5 == 0) or (e == 187) }
s.map! { |e| "box5_#{e}.to_f" }
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)
puts box5_189 # => 000000047.5000000000
puts v.size * 1.25 # => 47.5

-austin
 
R

Robert Klemme

Harry Truax said:
Thanks Austin,

But unfortunately $SAFE needs to be set to 3 which will preclude the use of
eval( ).

You can set up an evaluator before you switch to $SAFE 3 if you know the
variables beforehand, IMHO that should work:

box1_1 = nil
box1_2 = nil
sum_up = eval( "lambda { " + ((1..2).map {|i| "(box1_#{i} ||
0).to_f" }.join( " + " )) + "}" )
$SAFE = 3
box1_1 = '10'
box1_2 = '20'
p sum_up.call

But personally, I'd prefer a different approach, where you store values
either in an array or you store the UI elements (or whatever your boxes are)
in some kind of container (array, matrix whatever). That's IMHO a better
soltution, but then again I don't know your exact scenario since I didn't
follow the original thread.

Regards

robert

Harry

----- Original Message -----
From: "Austin Ziegler" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Monday, August 16, 2004 1:13 PM
Subject: Re: A method for summing several variables

examples. I will be studying your ideas closely to see if I can implement
them in our product. I really to
live with this fact (argh!!).application to application. Some of the summing operations are quite lengthy
as in:box5_20.to_f + box5_25.to_f + box5_30.to_f + box5_35.to_f + box5_40.to_f +
box5_45.to_f + box5_50.to_f + box5_55.to_f + box5_60.to_f + box5_65.to_f +
box5_70.to_f + box5_75.to_f + box5_80.to_f + box5_85.to_f + box5_90.to_f +
box5_95.to_f + box5_100.to_f + box5_105.to_f + box5_110.to_f + box5_115.to_f
+ box5_120.to_f + box5_125.to_f + box5_130.to_f + box5_135.to_f +
box5_140.to_f + box5_145.to_f + box5_150.to_f + box5_155.to_f +
box5_160.to_f + box5_165.to_f + box5_170.to_f + box5_175.to_f +
box5_180.to_f + box5_185.to_f + box5_187.to_f)suggestions, but if I have to manually type in each box name in setting up
the implementation, I may
as well just type in the lengthy sum operation as shown above.

I didn't participate in the initial round, but why not do a generator
and then eval your generated string in the current binding?

s = (5..185).to_a.select { |e| e % 5 == 0 }.map { |e| "box5_#{e}.to_f" }
s << "box5_187.to_f"
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)]

This will work so long as there's some kind of pattern you can deal
with (I don't get the box5_187 in your example, but I added it as an
exception).

I tested in irb with:

v = (5..187).to_a
v = v.select { |e| (e % 5 == 0) or (e == 187) }.map { |e| "box5_#{e}" }
v << "box5_187"
b = binding
v.each_with_index { |e, i| eval("#{e} = 1.25", b) }
puts box5_10 # => 1.25
$CUR = "%020.10f"

# the above set the test data; the below is the implementation
s = (5..187).to_a.select { |e| (e % 5 == 0) or (e == 187) }
s.map! { |e| "box5_#{e}.to_f" }
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)
puts box5_189 # => 000000047.5000000000
puts v.size * 1.25 # => 47.5

-austin
 
M

Martin DeMello

Robert Klemme said:
You can set up an evaluator before you switch to $SAFE 3 if you know the
variables beforehand, IMHO that should work:

Or even set up a way to specify the formulae in as convenient a manner
as possible, then do a one time code-generation pass to generate ruby
code from those formulae. The code itself can be run at whatever safe
level you want, exactly as though you'd typed it in by hand.

This is assuming, of course, that the formulae are all known at compile
time - if they change at runtime, your code generation step will look
more like

1.upto(m) {|i| 1.upto(n) {|j|
rubyfile.puts "box[#{i}][%{j}] = box_#{i}_#{j}"
}}

And then write your code after that using the box[j] references.

Neither of these use any form of runtime code generation, and should
therefore satisfy the pickiest of safe levels.

martin
 
P

Phil Tomson

Thanks Austin,

But unfortunately $SAFE needs to be set to 3 which will preclude the use of
eval( ).

Harry

----- Original Message -----
From: "Austin Ziegler" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Monday, August 16, 2004 1:13 PM
Subject: Re: A method for summing several variables

examples. I will be studying your ideas closely to see if I can implement
them in our product. I reallyapplication to application. Some of the summing operations are quite lengthy
as in:box5_20.to_f + box5_25.to_f + box5_30.to_f + box5_35.to_f + box5_40.to_f +
box5_45.to_f + box5_50.to_f + box5_55.to_f + box5_60.to_f + box5_65.to_f +
box5_70.to_f + box5_75.to_f + box5_80.to_f + box5_85.to_f + box5_90.to_f +
box5_95.to_f + box5_100.to_f + box5_105.to_f + box5_110.to_f + box5_115.to_f
+ box5_120.to_f + box5_125.to_f + box5_130.to_f + box5_135.to_f +
box5_140.to_f + box5_145.to_f + box5_150.to_f + box5_155.to_f +
box5_160.to_f + box5_165.to_f + box5_170.to_f + box5_175.to_f +
box5_180.to_f + box5_185.to_f + box5_187.to_f)suggestions, but if I have to manually type in each box name in setting up
the implementation, I may
as well just type in the lengthy sum operation as shown above.

I didn't participate in the initial round, but why not do a generator
and then eval your generated string in the current binding?

s = (5..185).to_a.select { |e| e % 5 == 0 }.map { |e| "box5_#{e}.to_f" }
s << "box5_187.to_f"
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)]

This will work so long as there's some kind of pattern you can deal
with (I don't get the box5_187 in your example, but I added it as an
exception).

I tested in irb with:

v = (5..187).to_a
v = v.select { |e| (e % 5 == 0) or (e == 187) }.map { |e| "box5_#{e}" }
v << "box5_187"
b = binding
v.each_with_index { |e, i| eval("#{e} = 1.25", b) }
puts box5_10 # => 1.25
$CUR = "%020.10f"

# the above set the test data; the below is the implementation
s = (5..187).to_a.select { |e| (e % 5 == 0) or (e == 187) }
s.map! { |e| "box5_#{e}.to_f" }
box5_189 = $CUR % [eval("(#{s.join(' + ')})", binding)
puts box5_189 # => 000000047.5000000000
puts v.size * 1.25 # => 47.5

-austin

Here's a crazy idea:
You can't do an 'eval' with $SAFE set to 3, but you could instead of
generating Ruby code, you could generate C code and use something like
RubyInline or Cgenerator (see: http://redshift.sourceforge.net/cgen/ ).
Either one of those can take C code and generate a shared lib (dll) that
can then be called from Ruby.

The idea is generally the same as Austin's. The only drawback is if
you're on a system that doesn't have a C compiler (*nix's generally do
have a C compiler available, Windows generally doesn't).



Phil
 
J

Joel VanderWerf

Phil Tomson wrote:
...
Here's a crazy idea:
You can't do an 'eval' with $SAFE set to 3, but you could instead of
generating Ruby code, you could generate C code and use something like
RubyInline or Cgenerator (see: http://redshift.sourceforge.net/cgen/ ).
Either one of those can take C code and generate a shared lib (dll) that
can then be called from Ruby.

That's no better than generating ruby code. $SAFE=3 won't let you create
or load a shared lib.
 
P

Phil Tomson

Phil Tomson wrote:
..

That's no better than generating ruby code. $SAFE=3 won't let you create
or load a shared lib.

Ooops... I suppose that makes sense.

So basically, you can't use extensions when you're in $SAFE=3

Phil
 
R

Robert Klemme

Phil Tomson said:
Ooops... I suppose that makes sense.

So basically, you can't use extensions when you're in $SAFE=3

Not exactly: as long as you load them before switching $SAFE or from another
thread it should work.

robert
 
T

ts

H> But unfortunately $SAFE needs to be set to 3 which will preclude the use of
H> eval( ).

Just switch to $SAFE = 4 (in a new thread), to make your eval


Guy Decoux
 
D

daz

ts said:
H> But unfortunately $SAFE needs to be set to 3 which will
H> preclude the use of eval( ).

Just switch to $SAFE = 4 (in a new thread), to make your eval

We watch and learn, ts :)
Guy Decoux


Harry,

With that advice from Guy, your original code can be changed
to something like this:

#------------------------------------------------------------
$SAFE=3

box1_1 = '12.9'; box1_2 = '-7'; box1_3 = '33.7'
box1_4 = '5.8'; box1_5 = '1244.66'; box1_6 = '38.8'
box1_7 = '200'; box1_8 = '4.4'; box1_9 = '-23'

#
# Use of lambda (formerly proc), allows direct access to
# the box00_00 variables -- (difficult from a method).
#
box_value = lambda do | box |
ret_ = nil
Thread.new { $SAFE=4; eval("ret_ = #{box}") }.join
ret_.to_f
end

add_boxes = lambda do | box, step, last |
box_pfx, box_num = box.match(/\A([a-z]+\d+_)(\d+)\z/)[1, 2]
print 'Summing:'
sum = 0
box_num.to_i.step(last, step) do | box_n |
box = "#{box_pfx}#{box_n}"
print ' + ', box
sum += box_value[box]
end
res = '%0.2f' % [sum]
puts "\n = #{res}"
end

add_boxes['box1_1', 4, 9]
add_boxes['box1_2', 2, 8]

#-> Summing: + box1_1 + box1_5 + box1_9
#-> = 1234.56
#-> Summing: + box1_2 + box1_4 + box1_6 + box1_8
#-> = 42.00
#------------------------------------------------------------


I really think that other responses were encouraging you to
consider some much better ways of approaching this problem,
but you stated your constraints very clearly :(

Using a combination of a hash with keys of (e.g.) :box1_6
and the trick below, you might be able to convince your
superiors that the constraints would still be intact.


#------------------------------------------------------------

HBox = {:box10_27 => 4.16, :box11_29 => 11.2}

class Object
def method_missing(meth)
bm = meth.to_s.match(/\A([a-z]+)(\d+)_(\d+)\z/) or super
p bm.to_a
HBox[meth]
end
end

p box10_27
p box11_29
p box100_100
p blah

#-> ["box10_27", "box", "10", "27"]
#-> 4.16

#-> ["box11_29", "box", "11", "29"]
#-> 11.2

#-> ["box100_100", "box", "100", "100"]
#-> nil

#-> C:/TEMP/rb8270.TMP:6:in `method_missing': undefined local variable or method 'blah' ...

#------------------------------------------------------------

Hope that's of some help,

:daz
 

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,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top