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