From f08c337b7e00e2cb65982fcf250a605ca86da636 Mon Sep 17 00:00:00 2001 From: Meisterlala <6453306+Meisterlala@users.noreply.github.com> Date: Tue, 18 Aug 2020 19:12:11 +0200 Subject: [PATCH] Week 1 files and Ruby config --- .../Part C/.vscode/launch.json | 14 +++ .../Part C/Week 1/123_ruby_intro.rb | 13 ++ .../Part C/Week 1/124_classes_objects.rb | 58 +++++++++ .../Part C/Week 1/125_object_state.rb | 90 +++++++++++++ .../Part C/Week 1/127_example.rb | 102 +++++++++++++++ .../Part C/Week 1/129_classes_dynamic.rb | 35 ++++++ .../Part C/Week 1/131_arrays.rb | 71 +++++++++++ .../Part C/Week 1/132_blocks.rb | 30 +++++ .../Part C/Week 1/133_using_blocks.rb | 28 +++++ .../Part C/Week 1/134_procs.rb | 21 ++++ .../Part C/Week 1/135_hashes_ranges.rb | 34 +++++ .../Part C/Week 1/136_subclassing.rb | 40 ++++++ .../Part C/Week 1/138_overriding.rb | 74 +++++++++++ .../140_dynamic_dispatch_vs_closures.rb | 39 ++++++ .../140_dynamic_dispatch_vs_closures.sml | 23 ++++ .../Week 1/141_manual_dynamic_dispatch.rkt | 118 ++++++++++++++++++ Programming Languages/Part C/Week 1/test.rb | 0 17 files changed, 790 insertions(+) create mode 100644 Programming Languages/Part C/.vscode/launch.json create mode 100644 Programming Languages/Part C/Week 1/123_ruby_intro.rb create mode 100644 Programming Languages/Part C/Week 1/124_classes_objects.rb create mode 100644 Programming Languages/Part C/Week 1/125_object_state.rb create mode 100644 Programming Languages/Part C/Week 1/127_example.rb create mode 100644 Programming Languages/Part C/Week 1/129_classes_dynamic.rb create mode 100644 Programming Languages/Part C/Week 1/131_arrays.rb create mode 100644 Programming Languages/Part C/Week 1/132_blocks.rb create mode 100644 Programming Languages/Part C/Week 1/133_using_blocks.rb create mode 100644 Programming Languages/Part C/Week 1/134_procs.rb create mode 100644 Programming Languages/Part C/Week 1/135_hashes_ranges.rb create mode 100644 Programming Languages/Part C/Week 1/136_subclassing.rb create mode 100644 Programming Languages/Part C/Week 1/138_overriding.rb create mode 100644 Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.rb create mode 100644 Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.sml create mode 100644 Programming Languages/Part C/Week 1/141_manual_dynamic_dispatch.rkt create mode 100644 Programming Languages/Part C/Week 1/test.rb diff --git a/Programming Languages/Part C/.vscode/launch.json b/Programming Languages/Part C/.vscode/launch.json new file mode 100644 index 0000000..49ea47c --- /dev/null +++ b/Programming Languages/Part C/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Local File", + "type": "Ruby", + "request": "launch", + "program": "${file}" + } + ] +} \ No newline at end of file diff --git a/Programming Languages/Part C/Week 1/123_ruby_intro.rb b/Programming Languages/Part C/Week 1/123_ruby_intro.rb new file mode 100644 index 0000000..0a390c5 --- /dev/null +++ b/Programming Languages/Part C/Week 1/123_ruby_intro.rb @@ -0,0 +1,13 @@ +# Programming Languages, Dan Grossman +# Section 7: Introduction to Ruby + +class Hello + + def my_first_method + puts "Hello, World!" + end + +end + +x = Hello.new +x.my_first_method diff --git a/Programming Languages/Part C/Week 1/124_classes_objects.rb b/Programming Languages/Part C/Week 1/124_classes_objects.rb new file mode 100644 index 0000000..6900791 --- /dev/null +++ b/Programming Languages/Part C/Week 1/124_classes_objects.rb @@ -0,0 +1,58 @@ +# Programming Languages, Dan Grossman +# Section 7: Classes and Objects + +class A + def m1 + 34 + end + + def m2 (x,y) + z = 7 + if x > y + false + else + x + y * z + end + end + +end + +class B + def m1 + 4 + end + + def m3 x + x.abs * 2 + self.m1 + end +end + +# returning self is convenient for "stringing method calls" +class C + def m1 + print "hi " + self + end + def m2 + print "bye " + self + end + def m3 + print "\n" + self + end +end + +# example uses (can type into irb) +# here in a multiline comment, which is not well-known +=begin +a = A.new +thirty_four = a.m1 +b = B.new +four = b.m1 +forty_seven = B.new.m3 -17 +thirty_one = a.m2(3,four) + +c = C.new +c.m1.m2.m3.m1.m1.m3 +=end diff --git a/Programming Languages/Part C/Week 1/125_object_state.rb b/Programming Languages/Part C/Week 1/125_object_state.rb new file mode 100644 index 0000000..7fd40a7 --- /dev/null +++ b/Programming Languages/Part C/Week 1/125_object_state.rb @@ -0,0 +1,90 @@ +# Programming Languages, Dan Grossman +# Section 7: Object State + +class A + def m1 + @foo = 0 + end + + def m2 x + @foo += x + end + + def foo + @foo + end + +end + +class B + # uses initialize method, which is better than m1 + # initialize can take arguments too (here providing defaults) + def initialize(f=0) + @foo = f + end + + def m2 x + @foo += x + end + + def foo + @foo + end + +end + +class C + # we now add in a class-variable, class-constant, and class-method + + Dans_Age = 38 + + def self.reset_bar + @@bar = 0 + end + + def initialize(f=0) + @foo = f + end + + def m2 x + @foo += x + @@bar += 1 + end + + def foo + @foo + end + + def bar + @@bar + end +end + +# example uses +=begin +x = A.new +y = A.new # different object than x +z = x # alias to x +x.foo # get back nil because instance variable not initialized +x.m2 3 # error because try to add with nil object +x.m1 # creates @foo in object x refers to +z.foo # remember, x and z are aliases +z.m2 3 +x.foo +y.m1 +y.m2 4 +y.foo +x.foo + +w = B.new 3 +v = B.new +w.foo + v.foo + +d = C.new 17 +d.m2 5 +e = C.new +e.m2 6 +d.bar +forty = C::Dans_Age + d.bar + +=end diff --git a/Programming Languages/Part C/Week 1/127_example.rb b/Programming Languages/Part C/Week 1/127_example.rb new file mode 100644 index 0000000..415be0b --- /dev/null +++ b/Programming Languages/Part C/Week 1/127_example.rb @@ -0,0 +1,102 @@ +# Programming Languages, Dan Grossman +# Section 7: A Longer Example + +class MyRational + + def initialize(num,den=1) # second argument has a default + if den == 0 + raise "MyRational received an inappropriate argument" + elsif den < 0 # notice non-english word elsif + @num = - num # fields created when you assign to them + @den = - den + else + @num = num # semicolons optional to separate expressions on different lines + @den = den + end + reduce # i.e., self.reduce() but private so must write reduce or reduce() + end + + def to_s + ans = @num.to_s + if @den != 1 # everything true except false _and_ nil objects + ans += "/" + ans += @den.to_s + end + ans + end + + def to_s2 # using some unimportant syntax and a slightly different algorithm + dens = "" + dens = "/" + @den.to_s if @den != 1 + @num.to_s + dens + end + + def to_s3 # using things like Racket's quasiquote and unquote + "#{@num}#{if @den==1 then "" else "/" + @den.to_s end}" + end + + def add! r # mutate self in-place + a = r.num # only works b/c of protected methods below + b = r.den # only works b/c of protected methods below + c = @num + d = @den + @num = (a * d) + (b * c) + @den = b * d + reduce + self # convenient for stringing calls + end + + # a functional addition, so we can write r1.+ r2 to make a new rational + # and built-in syntactic sugar will work: can write r1 + r2 + def + r + ans = MyRational.new(@num,@den) + ans.add! r + ans + end + +protected + # there is very common sugar for this (attr_reader) + # the better way: + # attr_reader :num, :den + # protected :num, :den + # we do not want these methods public, but we cannot make them private + # because of the add! method above + def num + @num + end + def den + @den + end + +private + def gcd(x,y) # recursive method calls work as expected + if x == y + x + elsif x < y + gcd(x,y-x) + else + gcd(y,x) + end + end + + def reduce + if @num == 0 + @den = 1 + else + d = gcd(@num.abs, @den) # notice method call on number + @num = @num / d + @den = @den / d + end + end +end + +# can have a top-level method (just part of Object class) for testing, etc. +def use_rationals + r1 = MyRational.new(3,4) + r2 = r1 + r1 + MyRational.new(-5,2) + puts r2.to_s + (r2.add! r1).add! (MyRational.new(1,-4)) + puts r2.to_s + puts r2.to_s2 + puts r2.to_s3 +end diff --git a/Programming Languages/Part C/Week 1/129_classes_dynamic.rb b/Programming Languages/Part C/Week 1/129_classes_dynamic.rb new file mode 100644 index 0000000..c927c8f --- /dev/null +++ b/Programming Languages/Part C/Week 1/129_classes_dynamic.rb @@ -0,0 +1,35 @@ +# Programming Languages, Dan Grossman +# Section 7: Class Definitions are Dynamic + +require_relative './127_example' # similar to ML's use + +# above line defines the MyRational class, but now we can change it + +class MyRational + def double + self + self + end +end + +class Fixnum + def double + self + self + end +end + +def m + 42 +end + +class Object + def m + 43 + end +end + +# this one will crash irb +# class Fixnum +# def + x +# 42 +# end +# end diff --git a/Programming Languages/Part C/Week 1/131_arrays.rb b/Programming Languages/Part C/Week 1/131_arrays.rb new file mode 100644 index 0000000..41bb155 --- /dev/null +++ b/Programming Languages/Part C/Week 1/131_arrays.rb @@ -0,0 +1,71 @@ +# Programming Languages, Dan Grossman +# Section 7: Arrays Longer Example + +a = [3,2,7,9] +a[2] +a[0] +a[4] +a.size +a[-1] +a[-2] +a[1] = 6 +a +a[6] = 14 +a +a[5] +a.size + +a[3] = "hi" + +b = a + [true,false] +c = [3,2,3] | [1,2,3] + +# array make fine tuples + +triple = [false, "hi", a[0] + 4] +triple[2] + +# arrays can also have initial size chosen at run-time +# (and as we saw can grow later -- and shrink) +x = if a[1] < a[0] then 10 else 20 end +y = Array.new(x) + +# better: initialized with a block (coming soon) +z = Array.new(x) { 0 } +w = Array.new(x) {|i| -i } + +# stacks +a +a.push 5 +a.push 7 +a.pop +a.pop +a.pop + +# queues (from either end) + +a.push 11 +a.shift +a.shift +a.unshift 14 + +# aliasing + +d = a +e = a + [] +d[0] +a[0] = 6 +d[0] +e[0] + +# slices + +f = [2,4,6,8,10,12,14] +f[2,4] +f.slice(2,2) +f.slice(-2,2) +f[2,4] = [1,1] + +# iterating: next segment, teaser here: + +[1,3,4,12].each {|i| puts (i * i)} diff --git a/Programming Languages/Part C/Week 1/132_blocks.rb b/Programming Languages/Part C/Week 1/132_blocks.rb new file mode 100644 index 0000000..8815043 --- /dev/null +++ b/Programming Languages/Part C/Week 1/132_blocks.rb @@ -0,0 +1,30 @@ +# Programming Languages, Dan Grossman +# Section 7: Passing Blocks + +3.times { puts "hello" } + +[4,6,8].each { puts "hi" } + +i = 7 +[4,6,8].each {|x| if i > x then puts (x+1) end } + +a = Array.new(5) {|i| 4*(i+1)} +a.each { puts "hi" } +a.each {|x| puts (x * 2) } +a.map {|x| x * 2 } #synonym: collect +a.any? {|x| x > 7 } +a.all? {|x| x > 7 } +a.all? # implicit are elements "true" (i.e., neither false nor nil) +a.inject(0) {|acc,elt| acc+elt } +a.select {|x| x > 7 } #non-synonym: filter + +def t i + (0..i).each do |j| + print " " * j + (j..i).each {|k| print k; print " "} + print "\n" + end +end + +t 9 + diff --git a/Programming Languages/Part C/Week 1/133_using_blocks.rb b/Programming Languages/Part C/Week 1/133_using_blocks.rb new file mode 100644 index 0000000..a2815ad --- /dev/null +++ b/Programming Languages/Part C/Week 1/133_using_blocks.rb @@ -0,0 +1,28 @@ +# Programming Languages, Dan Grossman +# Section 7: Using Blocks + +class Foo + def initialize(max) + @max = max + end + + def silly + yield(4,5) + yield(@max,@max) + end + + def count base + if base > @max + raise "reached max" + elsif yield base + 1 + else + 1 + (count(base+1) {|i| yield i}) + end + end +end + +f = Foo.new(1000) + +f.silly {|a,b| 2*a - b} + +f.count(10) {|i| (i * i) == (34 * i)} diff --git a/Programming Languages/Part C/Week 1/134_procs.rb b/Programming Languages/Part C/Week 1/134_procs.rb new file mode 100644 index 0000000..4595be1 --- /dev/null +++ b/Programming Languages/Part C/Week 1/134_procs.rb @@ -0,0 +1,21 @@ +# Programming Languages, Dan Grossman +# Section 7: Procs + +a = [3,5,7,9] + +# no need for Procs here +b = a.map {|x| x + 1} + +i = b.count {|x| x >= 6} + +# need Procs here: want an array of functions +c = a.map {|x| lambda {|y| x >= y} } + +# elements of c are Proc objects with a call method + +c[2].call 17 + +j = c.count {|x| x.call(5) } + + + diff --git a/Programming Languages/Part C/Week 1/135_hashes_ranges.rb b/Programming Languages/Part C/Week 1/135_hashes_ranges.rb new file mode 100644 index 0000000..d36aff2 --- /dev/null +++ b/Programming Languages/Part C/Week 1/135_hashes_ranges.rb @@ -0,0 +1,34 @@ +# Programming Languages, Dan Grossman +# Section 7: Hashes and Ranges + + +h1 = {} +h1["a"] = "Found A" +h1[false] = "Found false" +h1["a"] +h1[false] +h1[42] +h1.keys +h1.values +h1.delete("a") + +h2 = {"SML"=>1, "Racket"=>2, "Ruby"=>3} +h2["SML"] + +# Symbols are like strings, but cheaper. Often used with hashes. +h3 = {:sml => 1, :racket => 2, :ruby => 3} + +# each for hashes best with 2-argument block + +h2.each {|k,v| print k; print ": "; puts v} + +# ranges +(1..100).inject {|acc,elt| acc + elt} + +def foo a + a.count {|x| x*x < 50} +end + +# duck typing in foo +foo [3,5,7,9] +foo (3..9) diff --git a/Programming Languages/Part C/Week 1/136_subclassing.rb b/Programming Languages/Part C/Week 1/136_subclassing.rb new file mode 100644 index 0000000..a5a0ec7 --- /dev/null +++ b/Programming Languages/Part C/Week 1/136_subclassing.rb @@ -0,0 +1,40 @@ +# Programming Languages, Dan Grossman +# Section 7: Subclassing + +class Point + attr_accessor :x, :y + + def initialize(x,y) + @x = x + @y = y + end + def distFromOrigin + Math.sqrt(@x * @x + @y * @y) # why a module method? Less OOP :-( + end + def distFromOrigin2 + Math.sqrt(x * x + y * y) # uses getter methods + end + +end + +class ColorPoint < Point + attr_accessor :color + + def initialize(x,y,c="clear") # or could skip this and color starts unset + super(x,y) # keyword super calls same method in superclass + @color = c + end +end + +# example uses with reflection +p = Point.new(0,0) +cp = ColorPoint.new(0,0,"red") +p.class # Point +p.class.superclass # Object +cp.class # ColorPoint +cp.class.superclass # Point +cp.class.superclass.superclass # Object +cp.is_a? Point # true +cp.instance_of? Point # false +cp.is_a? ColorPoint # true +cp.instance_of? ColorPoint # true diff --git a/Programming Languages/Part C/Week 1/138_overriding.rb b/Programming Languages/Part C/Week 1/138_overriding.rb new file mode 100644 index 0000000..0c14a43 --- /dev/null +++ b/Programming Languages/Part C/Week 1/138_overriding.rb @@ -0,0 +1,74 @@ +# Programming Languages, Dan Grossman +# Section 7: Overriding and Dynamic Dispatch + +class Point + attr_accessor :x, :y + + def initialize(x,y) + @x = x + @y = y + end + def distFromOrigin + Math.sqrt(@x * @x + @y * @y) # uses instance variables directly + end + def distFromOrigin2 + Math.sqrt(x * x + y * y) # uses getter methods + end + +end + +# design question: "Is a 3D-point a 2D-point?" +# [arguably poor style here, especially in statically typed OOP languages] +class ThreeDPoint < Point + attr_accessor :z + + def initialize(x,y,z) + super(x,y) + @z = z + end + def distFromOrigin + d = super + Math.sqrt(d * d + @z * @z) + end + def distFromOrigin2 + d = super + Math.sqrt(d * d + z * z) + end +end + +class PolarPoint < Point + # Interesting: by not calling super constructor, no x and y instance vars + # In Java/C#/Smalltalk would just have unused x and y fields + def initialize(r,theta) + @r = r + @theta = theta + end + def x + @r * Math.cos(@theta) + end + def y + @r * Math.sin(@theta) + end + def x= a + b = y # avoids multiple calls to y method + @theta = Math.atan2(b, a) + @r = Math.sqrt(a*a + b*b) + self + end + def y= b + a = x # avoid multiple calls to y method + @theta = Math.atan2(b, a) + @r = Math.sqrt(a*a + b*b) + self + end + def distFromOrigin # must override since inherited method does wrong thing + @r + end + # inherited distFromOrigin2 already works!! +end + +# the key example +pp = PolarPoint.new(4,Math::PI/4) +pp.x +pp.y +pp.distFromOrigin2 diff --git a/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.rb b/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.rb new file mode 100644 index 0000000..dc7711b --- /dev/null +++ b/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.rb @@ -0,0 +1,39 @@ +# Dan Grossman, Programming Languages +# Section 7: Dynamic Dispatch Versus Closures + +# Ruby methods use late binding: simple example: + +class A + def even x + puts "in even A" + if x==0 then true else odd(x-1) end + end + def odd x + puts "in odd A" + if x==0 then false else even(x-1) end + end +end + +a1 = A.new.odd 7 +puts "a1 is " + a1.to_s + "\n\n" + +class B < A + def even x # changes B's odd too! (helps) + puts "in even B" + x % 2 == 0 + end +end + +a2 = B.new.odd 7 +puts "a2 is " + a2.to_s + "\n\n" + +class C < A + def even x + puts "in even C" # changes C's odd too! (hurts) + false + end +end + +a3 = C.new.odd 7 +puts "a3 is " + a3.to_s + "\n\n" + diff --git a/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.sml b/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.sml new file mode 100644 index 0000000..181c9fc --- /dev/null +++ b/Programming Languages/Part C/Week 1/140_dynamic_dispatch_vs_closures.sml @@ -0,0 +1,23 @@ +(* Programming Languages, Dan Grossman *) +(* Section 7: Dynamic Dispatch Versus Closures *) + +(* ML functions do not use use late binding: simple example: *) + +fun even x = (print "in even\n" ; if x=0 then true else odd (x-1)) +and odd x = (print "in odd\n" ; if x=0 then false else even (x-1)) + +val a1 = odd 7 +val _ = print "\n" + +(* does not change behavior of odd -- which is too bad *) +fun even x = (x mod 2) = 0 + +val a2 = odd 7 +val _ = print "\n" + +(* does not change behavior of odd -- which is good *) +fun even x = false + +val a3 = odd 7 +val _ = print "\n" + diff --git a/Programming Languages/Part C/Week 1/141_manual_dynamic_dispatch.rkt b/Programming Languages/Part C/Week 1/141_manual_dynamic_dispatch.rkt new file mode 100644 index 0000000..33e4d0b --- /dev/null +++ b/Programming Languages/Part C/Week 1/141_manual_dynamic_dispatch.rkt @@ -0,0 +1,118 @@ +; Programming Languages, Dan Grossman +; Section 7: Optional: Dynamic Dispatch Manually in Racket + +#lang racket + +;; We can "use" dynamic dispatch in a language without it manually + +;; Our "objects" will have: +;; * an immutable list of mutable "fields" (symbols and contents) +;; * an immutable list of immutable "methods" (symbols and functions taking self) +(struct obj (fields methods)) + +; like assoc but for an immutable list of mutable pairs +(define (assoc-m v xs) + (cond [(null? xs) #f] + [(equal? v (mcar (car xs))) (car xs)] + [#t (assoc-m v (cdr xs))])) + +(define (get obj fld) + (let ([pr (assoc-m fld (obj-fields obj))]) + (if pr + (mcdr pr) + (error "field not found")))) + +(define (set obj fld v) + (let ([pr (assoc-m fld (obj-fields obj))]) + (if pr + (set-mcdr! pr v) + (error "field not found")))) + +(define (send obj msg . args) ; convenience: multi-argument functions (2+ arguments) + (let ([pr (assoc msg (obj-methods obj))]) + (if pr + ((cdr pr) obj args) ; do the call + (error "method not found" msg)))) + +(define (make-point _x _y) + (obj + (list (mcons 'x _x) + (mcons 'y _y)) + (list (cons 'get-x (lambda (self args) (get self 'x))) + (cons 'get-y (lambda (self args) (get self 'y))) + (cons 'set-x (lambda (self args) (set self 'x (car args)))) + (cons 'set-y (lambda (self args) (set self 'y (car args)))) + (cons 'distToOrigin + (lambda (self args) + (let ([a (send self 'get-x)] + [b (send self 'get-y)]) + (sqrt (+ (* a a) (* b b))))))))) + +(define (make-color-point _x _y _c) + (let ([pt (make-point _x _y)]) + (obj + (cons (mcons 'color _c) + (obj-fields pt)) + (append (list + (cons 'get-color (lambda (self args) (get self 'color))) + (cons 'set-color (lambda (self args) (set self 'color (car args))))) + (obj-methods pt))))) + +(define (make-polar-point _r _th) + (let ([pt (make-point #f #f)]) + (obj + (append (list (mcons 'r _r) + (mcons 'theta _th)) + (obj-fields pt)) ; Java-style field extension + (append ; overriding by being earlier in the list (see send function) + (list + (cons 'set-r-theta + (lambda (self args) + (begin + (set self 'r (car args)) + (set self 'theta (cadr args))))) + (cons 'get-x (lambda (self args) + (let ([r (get self 'r)] + [theta (get self 'theta)]) + (* r (cos theta))))) + (cons 'get-y (lambda (self args) + (let ([r (get self 'r)] + [theta (get self 'theta)]) + (* r (sin theta))))) + (cons 'set-x (lambda (self args) + (let* ([a (car args)] + [b (send self 'get-y)] + [theta (atan b a)] + [r (sqrt (+ (* a a) (* b b)))]) + (send self 'set-r-theta r theta)))) + (cons 'set-y (lambda (self args) + (let* ([b (car args)] + [a (send self 'get-x)] + [theta (atan b a)] + [r (sqrt (+ (* a a) (* b b)))]) + (send self 'set-r-theta r theta))))) + (obj-methods pt))))) + +(define p1 (make-point -4 0)) +p1 +(send p1 'get-x) +(send p1 'get-y) +(send p1 'distToOrigin) +(send p1 'set-y 3) +(send p1 'distToOrigin) + +(define p2 (make-color-point -4 0 "red")) +p2 +(send p2 'get-x) +(send p2 'get-y) +(send p2 'distToOrigin) +(send p2 'set-y 3) +(send p2 'distToOrigin) + +(define p3 (make-polar-point 4 3.1415926535)) +p3 +(send p3 'get-x) +(send p3 'get-y) +(send p3 'distToOrigin) +(send p3 'set-y 3) +(send p3 'distToOrigin) diff --git a/Programming Languages/Part C/Week 1/test.rb b/Programming Languages/Part C/Week 1/test.rb new file mode 100644 index 0000000..e69de29 -- 2.51.2