Instructor: Stefan Mitsch
def f (n:Int) = if n<=1 then 1 else n * f (n-1)def g (n:Int) = f (n) * g (n-1)def h (n:Int) = h (g (n), f (n))def i (n:Int) = n * n
int* f(int x) { return &x; }int* g(int x) { int* y = (int*) malloc (sizeof (int)); *y=x; return y; }int main(void) { int* p = f(5); printf("%d\n", *p); int* q = g(5); }
p
q
What is printed in a statically-scoped vs. dynamically-scoped language?
var x:Int = 10def foo() = x = 20 def bar() = var x:Int = 30 foo() println(x) def zee() = var x:Int = 40 bar() println(x)print("bar: "); bar(); print(" " + x)print("zee: "); zee(); print(" " + x)print("foo: "); foo(); print(" " + x)
bar: 30 20zee: 30 40 20foo: 20
bar: 20 10zee: 20 40 10foo: 20
Define an algebraic datatype for arithmetic expressions with literals, variables, and operators +, -, *
+
-
*
enum Expr: case Literal(x:Int) case Variable(n:String, v: Option[Expr]) case Neg(e:Expr) case Plus(l:Expr, r:Expr) case Minus(l:Expr, r:Expr) case Times(l:Expr, r:Expr)
Define a toInt method for arithmetic expressions
toInt
enum Expr: case Literal(x:Int) case Variable(n:String, v:Option[Expr]) case Neg(e:Expr) case Plus(l:Expr, r:Expr) case Minus(l:Expr, r:Expr) case Times(l:Expr, r:Expr)
def toInt : Int = this match case Literal(x) => x case Variable(n, None) => ??? case Variable(_, Some(e)) => e.toInt case Neg(e) => -e.toInt case Plus(l,r) => l.toInt + r.toInt case Minus(l,r) => l.toInt - r.toInt case Times(l,r) => l.toInt * r.toInt
What is printed in a call-by-value vs. a call-by-reference language?
def f(a:Int, b:Int) = { a = b b = b + 1}var x = 5var y = 10f(x,y); println(s"x=$x, y=$y")f(x,x); println(s"x=$x")f(x,x+2); println(s"x=$x")
x=5, y=10x=5x=5
x=10, y=11x=11x=13
def f(): String=>String = { var s = "" (t:String) => { s = s + t; s }}val a = f()println(a("x"))println(a("y"))println(a("z"))
a
String=>String
xxyxyz
public class f { private String s = ""; public String fn(String t) { s = s+t; return s; }}f a = new f()System.out.println(a.fn("x"));
def f(): ()=>String=>String = { var s = "" () => { var i = 0 (t:String) => { s = s + t + i; i = i+1; s } } }val factory = f()val a = factory()val b = factory()println(a("x"))println(a("y"))println(b("z"))
b
s
i
class A { def f() = { println("A.f") }}class B extends A { override def f() = { println("B.f"); super.f() } def g() = { println("B.g") }}val b:A = new B() // b:B?b.f()
b.g()
val b:B = new B()
class B extends A {}var as: List[A] = List(new A(), new B())
Which code compiles and why/why not?
val bs: List[B] = as
val bs: List[B] = List(new B(), new B())
as = bs
val a1: Any = as(0) // a1: A // a1: B
function f() { return { a: 1, b: "hello" c: function () { return 2; } }}
f().a
f().d
f().c()
function f(n) { var fs = []; for (var i = 0; i < n; i++) { var x = i; fs.push(x); } return fs;}
f(3)
[0,1,2]
function f(n) { var x = n; return { get: function(y) { x = x+y; return x; } }}
f(3).get(1)
c
var a = f(3); var b = a.get(1); var c = a.get(2);
val xs = 1 :: 2 :: Nilval ys = List(1, 2)val zs = 0 :: xsval as = List(0) :: xsval bs = List(0) ::: xs
xs
ys
zs
0 :: ys
as
bs
def f(xs:List[?3]): ?4 = xs.map(x => x+1)def g(ys:?2): ?1 = ys.foldLeft(0)(_ + _)g (f (List (1,2,3,4)))
?1
?2
?3
?4