lab19: init
This commit is contained in:
67
lab19/eval/eval.rb
Normal file
67
lab19/eval/eval.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user