lab19: init

This commit is contained in:
2026-04-29 11:33:23 -07:00
parent d042a0e016
commit dba2c2b3d6
12 changed files with 386 additions and 0 deletions

52
lab19/block.rb Normal file
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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));