Variable from array to function to array

anyone know if it is possible to pass elements from an array (eg 20,50 )
to the function
number_range(min,max) and have the returned value used in the variable
|age| below…

def number_range(min,max) # Chooses a random number within
specified range.
num = min + rand(max - min)
end

array = [ lambda { |age| “An #{age} year old…”}, 20, 50 ]

puts array[0][age returned from number_range method]

An 18 year old…

On Fri, Aug 17, 2012 at 2:39 AM, Dave C. [email protected]
wrote:

array = [ lambda { |age| “An #{age} year old…”}, 20, 50 ]

puts array[0][age returned from number_range method]

An 18 year old…

The obvious thing would be:

puts array[0][number_range(array[1], array[2])]

but this data structure starts to be too complicated. Why is it an
array? Will you have some (many) more entries (lambda + range)? If so,
you could be better off with a class to represent that information:

RangedInterpolation = Struct.new :lambda, :min, :max

array = [ RangedInterpolation.new(lambda { |age| “An #{age} year
old…”}, 20, 50) ]
array.each {|interpolation| puts
interpolation.lambda(number_range(interpolation.min,
interpolation.max))}

You could go one step further and make the pair min,max a Range
object, and even include the number_range method inside the class.

Jesus.

Am 17.08.2012 02:39, schrieb Dave C.:

anyone know if it is possible to pass elements from an array (eg 20,50 )
to the function
number_range(min,max) and have the returned value used in the variable
|age| below…

def number_range(min,max) # Chooses a random number within
specified range.
num = min + rand(max - min)
end

This will never return max!

Use min + rand(max - min + 1) or simply rand(min…max)

array = [ lambda { |age| “An #{age} year old…”}, 20, 50 ]

puts array[0][age returned from number_range method]

This would work:

array = [lambda { |age| “An #{age} year old…”}, 20, 50]
puts array[0][rand(array[1]…array[2])]

But this approach seems very odd to me. What are you trying to do?
Why not do it like this:

def random_age_string(range)
“A #{rand(range)} year old”
end

puts random_age_string(20…40)

But it is rather impossible to provide useful help
unless you give us the bigger picture.

The bigger picture… I am saving multiple question templates in a
array and need to store all the info (the question, the min and max
ranges, the units of measure etc assoc with each question. The
associated info is used to build the question … eg in question one,
need to pass 20,40 to number_range(min,max) and use the returned value
as u.

def number_range(min,max)
min + rand(max - min + 1) **Thanks!
end

array =[
[ lambda {|u,u_unit| “A slide is placed #{u} #{u_unit} to the left of a
lens…”, 20, 40, “cm”],
[ lambda {|v,v_unit| “An image is in focus #{v} #{v_unit} to the right
of a…”, 10, 25, "mm],
[…
]

puts array[n][variable returned from number_range method]

A slide is placed 25 cm…

Also,
def random_age_string(range)
“A #{rand(range)} year old”
end

puts random_age_string(20…40)

Does not work as I am not able to embed “#{}” in a string in an array…
it just returns the string without evaluating…

On Fri, Aug 17, 2012 at 1:15 PM, Dave C. [email protected]
wrote:

The bigger picture… I am saving multiple question templates in a
array and need to store all the info (the question, the min and max
ranges, the units of measure etc assoc with each question. The
associated info is used to build the question … eg in question one,
need to pass 20,40 to number_range(min,max) and use the returned value
as u.

If you’re using ruby 1.9, you can use the new hash interpolation syntax:

puts “Hello %{who}” % { :who => “world” }

outputs

Hello world

For example:

def number_range(min,max)
min + rand(max - min + 1)
end

array =[
[ “A slide is placed %{value} %{unit} to the left of a
lens…”, 20, 40, “cm”],
[ “An image is in focus %{value} %{unit} to the right of
a…”, 10, 25, “mm” ],
]

array.each do |item|
text, min, max, unit = item
puts text % { :value => number_range(min, max), :unit => unit }
end

puts “Hello %{who}” % { :who => “world” }

Regards,
Sean

Am 17.08.2012 14:15, schrieb Dave C.:

The bigger picture… I am saving multiple question templates in a
array and need to store all the info (the question, the min and max
ranges, the units of measure etc assoc with each question. The
associated info is used to build the question … eg in question one,
need to pass 20,40 to number_range(min,max) and use the returned value
as u.

Ok… :slight_smile:

First: did you consider using a templating system for your
“question templates”? You could avoid the lambdas;
instead, you provide a template as a simple string that gets
evaluated later when the needed values are known.

Second: Instead of using nested arrays I would put all the
question-generating functionality into a class.

Assuming the structure of your questions is always the same,
below is one possible way to do it:

require ‘erb’

class Question

attr_reader :unit

def initialize(text, range, unit)
@text = ERB.new(text)
@range = range
@unit = unit
end

def val
rand(@range)
end

def to_s
@text.result(binding)
end
end

questions = [
Question.new(‘A slide is placed <%= val %> <%= unit %>…’,
20…40, ‘cm’),
Question.new(‘An image is in focus <%= val %> <%= unit %>…’,
10…15, ‘mm’)
]

questions.each {|q| puts q }
questions.each {|q| puts q } # results in different values

BUT:

  • Can’t you simply include the unit in the text part?
  • Do you really need to have the same question with
    different values in the same run of your program?

How about:

questions = [
“A slide is placed #{rand(20…40)} cm…”,
“An image is in focus #{rand(10…15)} mm…”
]
questions.each {|q| puts q }

Am 18.08.2012 01:15, schrieb Sean O’Halpin:

If you’re using ruby 1.9, you can use the new hash interpolation syntax:

puts “Hello %{who}” % { :who => “world” }

Nice, thanks!

Here an improved version that allows you to use an arbitrary,
possible different set of properties for each question.
Random values are returned if you provide a Range or an Array.

(And it now uses the hash interpolation pointed out by Sean
instead of erb,)

class Question

def initialize(text, substitutions)
@text = text
@substitutions = substitutions
end

def to_s
subst = {}
@substitutions.each do |k, v|
if v.class == Range
subst[k] = rand(v)
elsif v.class == Array
subst[k] = v.sample
else
subst[k] = v
end
end
@text % subst
end
end

You can use arbitrary keys.

For ranges or arrays a random number / element is used.

questions = [
Question.new(‘A slide is placed %{val} %{unit} %{side} of…’,
{:val => 20…40, :unit => ‘cm’,
:side => [‘left’, ‘right’]}),
Question.new(‘An image is … %{val} mm … and %{factor} times…’,
{:val => 10…15, :factor => 2…9})
]

questions.each {|q| puts q }
questions.each {|q| puts q } # gives different values