First class environments: Difference between revisions

(→‎{{header|Go}}: update for library hosting change)
Line 369:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Ruby}}==
{{trans|PicoLisp}}
 
The ''object'' is an environment for instance variables. These variables use the <code>@</code> sigil. We create 12 objects, and put <code>@n</code> and <code>@cnt</code> inside these objects. We use <code>Object#instance_eval</code> to switch the current object and bring those instance variables into scope.
 
<lang ruby># Build environments
envs = (1..12).map do |n|
Object.new.instance_eval {@n = n; @cnt = 0; self}
end
 
# Until all values are 1:
while envs.find {|e| e.instance_eval {@n} > 1}
envs.each do |e|
e.instance_eval do # Use environment _e_
printf "%4s", @n
unless 1 == @n
@cnt += 1 # Increment step count
@n = if 1 & @n == 1 # Calculate next hailstone value
@n * 3 + 1
else
@n / 2
end
end
end
end
puts
end
puts '=' * 48
envs.each do |e| # For each environment _e_
e.instance_eval do
printf "%4s", @cnt # print the step count
end
end
puts</lang>
 
----
 
Ruby also provides the ''binding'', an environment for local variables. The problem is that local variables have lexical scope. Ruby needs the lexical scope to parse Ruby code. So, the only way to use a binding is to evaluate a string of Ruby code. We use <code>Kernel#binding</code> to create the bindings, and <code>Kernel#eval</code> to evaluate strings in these bindings. The lines between <code><<-'eos'</code> and <code>eos</code> are multi-line string literals.
 
<lang ruby># Build environments
envs = (1..12).map do |n|
e = class Object
# This is a new lexical scope with no local variables.
# Create a new binding here.
binding
end
eval(<<-'eos', e).call(n)
n, cnt = nil, 0
proc {|arg| n = arg}
eos
next e
end
 
# Until all values are 1:
while envs.find {|e| eval('n > 1', e)}
envs.each do |e|
eval(<<-'eos', e) # Use environment _e_
printf "%4s", n
unless 1 == n
cnt += 1 # Increment step count
n = if 1 & n == 1 # Calculate next hailstone value
n * 3 + 1
else
n / 2
end
end
eos
end
puts
end
puts '=' * 48
envs.each do |e| # For each environment _e_
eval(<<-'eos', e)
printf "%4s", cnt # print the step count
eos
end
puts</lang>
 
=={{header|Tcl}}==
Anonymous user