2

I was wondering if it is possible to save some ruby statements inside an Array like:

    a = 1
    b = 0
    statements = ['a += 1','b = a + 4']
    statements.each { |s| s.execute }

The reason for why I want to do this is to be able to use Array permutation to execute every combination of of a subset of the statements in the array.

Perhaps I am making it to difficult for myself and there is an easier (and perhaps more obvious) way.

Thankful for any help.

user3207230
  • 587
  • 7
  • 16
  • 3
    that's a terrible idea, you should use lambdas instead. Could you explain more the result of what would happen. You could simply write those two lines one after the other here. It's not super clear why you need an array. – Loïc Faure-Lacroix Feb 25 '14 at 18:26
  • 1
    Not sure what `use Array permutation to execute every combination of of a subset of the statements in the array` means. – sawa Feb 25 '14 at 18:28

3 Answers3

6

As Loïc Faure-Lacroix suggested, better to use lambdas:

a = 1
b = 0
statements = [ lambda{a += 1}, lambda{b = a + 4} ]
statements.each(&:call)

After execution, this leave a == 2 and b == 6.

Matt
  • 20,108
  • 1
  • 57
  • 70
  • asking out of curiosity, why `lambda` is better here to use ? I mean advantages..? – Arup Rakshit Feb 25 '14 at 19:02
  • 1
    @ArupRakshit For this particular application, it may be fine. In general, however, `eval` really should be a last resort since if used improperly, especially when user input is involved, it can open up security holes. It's a bit like handling a gun - one wants to develop good general habits even if in a particular case there is no harm in leaving a gun loaded. A programmer with good habits is less likely in the long run to introduce security holes than a programmer that uses `eval` on a whim. – Matt Feb 25 '14 at 19:07
1

You could use eval:

a = 1
b = 0
statements = ['a += 1','b = a + 4']
statements.each { |s| eval s }
David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • 1
    Just beware that eval is dangerous, especially if your program takes input from an untrusted user. I would probably use lambdas or procs instead. – David Grayson Feb 25 '14 at 21:52
  • Yes, I am aware of that, but the script I am writing is meant solely to take input from myself. If I were to do something that gathered external users input I would probably look at the alternatives listed here. – user3207230 Feb 27 '14 at 11:12
0

If this involves user input, it would be far more secure to implement a templated formula parser such as Dentaku.

Sample:

calculator = Dentaku::Calculator.new
calculator.store({a:1, b:0})

statements = ['a + 1','(a + b + 5)/2']
statements.map {|s| calculator.evaluate(statement)}

#=> [2,3]

The primary difference is that it doesn't manipulate local variables directly. It supports basic mathematical functions and you can register custom functions.

Mark Thomas
  • 37,131
  • 11
  • 74
  • 101