Files
cs-252/lab19/eval/eval.rb
2026-04-29 11:33:23 -07:00

68 lines
1.9 KiB
Ruby

# Ruby has rich metaprogramming tools, often bowered from Smalltalk.
# Like JavaScript, it has an eval feature.
prog = "puts 3 + 4"
eval prog
# Eval is one of the most powerful metaprogramming features,
# but it is also one of the most dangerous.
print "Please enter your method name: "
m = gets.chomp
eval "def #{m}; puts 'Hi!'; end"
eval m
=begin
Thomass-MacBook-Pro-3:lab15 taustin$ ruby eval.rb
Please enter your method name: abc; end; puts "Mwah, hah, hah!"; #
Mwah, hah, hah!
eval.rb:11: (eval):1: compile error (SyntaxError)
(eval):1: syntax error, unexpected kEND, expecting $end
abc; end; puts "Mwah, hah, hah!"; #
-----------------------
Eval is horribly abused (Richards et al. 2011, See the Eval that men do,), but it is useful at times.
For instance, in JavaScript, it served as an early (but unsafe) version of JSON.parse.
Similar to goto, it is a powerful but dangerous construct, and is often used in places
where the language is missing a key feature.
"A design pattern is the sincerest form of feature request".
However, it does not tend to show up as often in Ruby.
In part, Ruby has some safer alternatives that are nearly as powerful.
They take blocks rather than expressions.
=end
# instance_eval -- used for prying open objects to get at their private data.
# This can be handy for things like writing a debugger.
class Person
attr_reader :name
def initialize name
@name = name
end
end
bob = Person.new "Robert"
puts bob.name
#bob.name = "Bobby" # Error
bob.instance_eval do
@name = "Bobby"
end
puts bob.name
# And finally class_eval/module_eval, which serve as an alternate way of opening up a class.
favorite_song = "Streets of Laredo"
class Person
#puts favorite_song # error
end
Person.class_eval do
puts favorite_song
#def sing
# puts "When #{@name} went out in the #{favorite_song}..." # Will not see favorite_song
#end
define_method "sing" do
puts "When #{@name} went out in the #{favorite_song}..."
end
end
bob.sing