lab19: init
This commit is contained in:
52
lab19/block.rb
Normal file
52
lab19/block.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
def do_noisy
|
||||
puts "About to call block"
|
||||
yield
|
||||
puts "Just called block"
|
||||
end
|
||||
|
||||
do_noisy do
|
||||
puts 3 + 4
|
||||
end
|
||||
|
||||
|
||||
class Array
|
||||
def each_downcase
|
||||
self.each do |word|
|
||||
yield word.downcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
["Alpha", "Beta", "AndSoOn"].each_downcase do |word|
|
||||
puts word
|
||||
end
|
||||
|
||||
def iff b
|
||||
return if b == false
|
||||
yield
|
||||
end
|
||||
|
||||
def test_block
|
||||
iff true do
|
||||
puts "hello block"
|
||||
return
|
||||
end
|
||||
puts "goodbye block"
|
||||
end
|
||||
|
||||
def iff2 b, lam
|
||||
return if b == false
|
||||
lam.call
|
||||
end
|
||||
|
||||
def test_lambda
|
||||
iff2 true, (lambda do
|
||||
puts "hello lambda"
|
||||
return
|
||||
end)
|
||||
puts "goodbye lambda"
|
||||
end
|
||||
|
||||
test_block
|
||||
test_lambda
|
||||
|
||||
25
lab19/conversion.rb
Normal file
25
lab19/conversion.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
def conversion_chart(from_units, to_units, values)
|
||||
puts "#{from_units}\t#{to_units}"
|
||||
left_line = right_line = ""
|
||||
from_units.length.times { left_line += '-' }
|
||||
to_units.length.times { right_line += '-' }
|
||||
puts "#{left_line}\t#{right_line}"
|
||||
for val in values
|
||||
converted = yield val
|
||||
puts "#{val}\t#{converted}"
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
celsius_temps = [0,10,20,30,40,50,60,70,80,90,100]
|
||||
conversion_chart("C", "F", celsius_temps) {|cel| cel * 9 / 5 + 32}
|
||||
|
||||
fahrenheit_temps = [0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200 ]
|
||||
conversion_chart("Fahr.", "Celsius", fahrenheit_temps) {|fahr| (fahr-32) * 5 / 9 }
|
||||
|
||||
|
||||
conversion_chart("Km", "Miles", (1..10)) do |km|
|
||||
mile = 0.621371 * km
|
||||
end
|
||||
|
||||
|
||||
42
lab19/emp.rb
Normal file
42
lab19/emp.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
class Employee
|
||||
# Adding methods to the singleton class of the object
|
||||
# Employee (which has the class Class).
|
||||
class << self
|
||||
def add(emp)
|
||||
puts "Adding #{emp}"
|
||||
@employees = Hash.new unless @employees
|
||||
@employees[emp.name] = emp
|
||||
end
|
||||
def get_emp_by_name name
|
||||
@employees[name]
|
||||
end
|
||||
end
|
||||
#####################################################
|
||||
attr_accessor :name, :ssid, :salary
|
||||
def initialize(name, ssid, salary)
|
||||
@name = name
|
||||
@ssid = ssid
|
||||
@salary = salary
|
||||
Employee.add self
|
||||
end
|
||||
def to_s
|
||||
@name
|
||||
end
|
||||
end
|
||||
|
||||
alice = Employee.new("Alice Alley", 1234, 75000);
|
||||
bob = Employee.new("Robert Tables", 5678, 50000);
|
||||
|
||||
class << bob
|
||||
def signing_bonus
|
||||
2000
|
||||
end
|
||||
end
|
||||
|
||||
puts(bob.signing_bonus);
|
||||
#puts(alice.signing_bonus);
|
||||
|
||||
b = Employee.get_emp_by_name "Robert Tables"
|
||||
puts b.signing_bonus
|
||||
|
||||
|
||||
19
lab19/eval/class-eval-example.rb
Normal file
19
lab19/eval/class-eval-example.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
class Class
|
||||
def my_attr_accessor(*args)
|
||||
args.each do |prop|
|
||||
# Creating the getter
|
||||
self.class_eval("def #{prop}; @#{prop}; end")
|
||||
# Creating the setter
|
||||
self.class_eval("def #{prop}=(v); @#{prop}=v; end")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Musician
|
||||
my_attr_accessor :name, :genre, :instrument
|
||||
end
|
||||
|
||||
m = Musician.new
|
||||
m.name = "Norah Jones"
|
||||
puts m.name
|
||||
|
||||
21
lab19/eval/eval.js
Normal file
21
lab19/eval/eval.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// Assume that this string comes from across the network
|
||||
// representing employee records.
|
||||
var jsonStr =
|
||||
"[{name: 'Philip J. Fry', age: 1000, job: 'delivery boy'}," +
|
||||
" {name: (function(){console.log('***All glory to the Hypnotoad!***')})() }," +
|
||||
" {name: 'Bender Rodriguez', age: 42, job: 'bending unit'}]";
|
||||
|
||||
var employeeRecords = eval(jsonStr);
|
||||
for (var i in employeeRecords) {
|
||||
var emp = employeeRecords[i];
|
||||
console.log(emp.name);
|
||||
}
|
||||
|
||||
/*
|
||||
$ node eval.js
|
||||
***All glory to the Hypnotoad!***
|
||||
Philip J. Fry
|
||||
undefined
|
||||
Bender Rodriguez
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
30
lab19/eval/taint.rb
Normal file
30
lab19/eval/taint.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
=begin
|
||||
Update the Record class so that updates with either
|
||||
a tainted name or a tainted value are ignored.
|
||||
Do this first by explicitly checking the taint on a field.
|
||||
|
||||
Would this be sufficient if an attacker could control part of the code?
|
||||
If not, how could the different taint modes be useful?
|
||||
=end
|
||||
|
||||
class Record
|
||||
def initialize fields
|
||||
@fields = fields
|
||||
end
|
||||
|
||||
def set_property name, value
|
||||
@fields[name] = value
|
||||
end
|
||||
def get_property name
|
||||
@fields[name]
|
||||
end
|
||||
end
|
||||
|
||||
r = Record.new 'fname' => 'Rick', 'lname' => 'Grimes', 'profession' => 'Police Officer'
|
||||
r.set_property 'profession'.taint, 'Zombie Hunter'
|
||||
r.set_property 'lname', 'Smith'.taint
|
||||
|
||||
p r.get_property 'profession'
|
||||
p r.get_property 'lname'
|
||||
|
||||
|
||||
21
lab19/method-missing.rb
Normal file
21
lab19/method-missing.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
class Person
|
||||
attr_accessor :name
|
||||
def initialize(name)
|
||||
@name = name
|
||||
end
|
||||
|
||||
def make_introduction
|
||||
puts "Hi, my name is #{@name}. Nice to meet you."
|
||||
end
|
||||
|
||||
def method_missing(m)
|
||||
puts "Didn't understand #{m}"
|
||||
end
|
||||
end
|
||||
|
||||
alice = Person.new('Alice')
|
||||
|
||||
alice.make_introduction
|
||||
alice.foo
|
||||
|
||||
|
||||
37
lab19/record.rb
Normal file
37
lab19/record.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
=begin
|
||||
Ruby provides a number of hooks that allow a developer
|
||||
to change the behavior of objects.
|
||||
The design is similar to JavaScript's Proxies (both are
|
||||
metaobject protocols), but unlike proxies,
|
||||
these hooks apply for all objects.
|
||||
|
||||
The most famous of these is method_missing,
|
||||
based on Smalltalk's doesNotUnderstand:.
|
||||
=end
|
||||
|
||||
# Consider Ruby on Rails.
|
||||
# With Rails you refer to a record's fields by their names.
|
||||
# We will (crudely) simulate that.
|
||||
class Record
|
||||
def initialize fields
|
||||
@fields = fields
|
||||
end
|
||||
|
||||
def method_missing m, *args
|
||||
meth_name = m.to_s
|
||||
if (meth_name.end_with?("=")) then
|
||||
@fields[meth_name.chop] = args[0]
|
||||
else
|
||||
@fields[meth_name]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
r = Record.new ({ 'fname' => 'Rick', 'lname' => 'Grimes', 'profession' => 'Police Officer' })
|
||||
puts r.profession
|
||||
r.profession = 'Zombie hunter'
|
||||
puts r.profession
|
||||
|
||||
# Ruby has const_missing as well, which works in a similar manner, except that it applies
|
||||
# to missing class constants
|
||||
|
||||
35
lab19/tree.rb
Normal file
35
lab19/tree.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
class Tree
|
||||
attr_accessor :value, :left, :right
|
||||
def initialize(value, left=nil, right=nil)
|
||||
@value = value
|
||||
@left = left
|
||||
@right = right
|
||||
end
|
||||
end
|
||||
|
||||
my_tree = Tree.new(42,
|
||||
Tree.new(3,
|
||||
Tree.new(1,
|
||||
Tree.new(7,
|
||||
Tree.new(22),
|
||||
Tree.new(123)),
|
||||
Tree.new(32))),
|
||||
Tree.new(99,
|
||||
Tree.new(81)))
|
||||
|
||||
my_tree.each_node do |v|
|
||||
puts v
|
||||
end
|
||||
|
||||
arr = []
|
||||
my_tree.each_node do |v|
|
||||
arr.push v
|
||||
end
|
||||
p arr
|
||||
|
||||
p "Getting nodes from tree"
|
||||
p my_tree.left_left
|
||||
p my_tree.right_left
|
||||
p my_tree.left_left_right
|
||||
p my_tree.left_left_left_right
|
||||
|
||||
20
lab19/with-prob.rb
Normal file
20
lab19/with-prob.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
def with_prob (prob)
|
||||
yield if (Random.rand < prob)
|
||||
end
|
||||
|
||||
with_prob 0.42 do
|
||||
puts "There is a 42% chance that this code will print"
|
||||
end
|
||||
|
||||
|
||||
|
||||
def foo x
|
||||
with_prob 0.5 do
|
||||
puts "Executing with_prob block"
|
||||
return 0
|
||||
end
|
||||
return x
|
||||
end
|
||||
|
||||
puts "Foo is #{foo 1}"
|
||||
|
||||
17
lab19/withProb.js
Normal file
17
lab19/withProb.js
Normal file
@@ -0,0 +1,17 @@
|
||||
function withProb(prob, f) {
|
||||
if (Math.random() < prob) {
|
||||
return f();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function foo(x) {
|
||||
withProb(0.5, function() {
|
||||
console.log("Execution withProb callback");
|
||||
return 0;
|
||||
});
|
||||
return x;
|
||||
}
|
||||
|
||||
console.log("Foo is " + foo(1));
|
||||
|
||||
Reference in New Issue
Block a user