No, this is not correct. Representing the user's input and the system's output as lists of characters works just fine with lazy evaluation, except for the problem of synchronizing them. However, if we are doing eager evaluation, when we try to pass the list of input characters to a function Eager Haskell would want the entire list, even though the user hadn't typed all of them yet. Similarly, any output function would want the entire list of output characters.
rPart
and
iPart
for the real
and imaginary parts.
Show the appropriate methods so that you can provide a
class-specific initialization message, so that you can write
Complex r: 3.4 i: 5.0
to create a new complex number. Describe
how the expression
Complex r: 3.4 i: 5.0
We would add the following method to Complex class (i.e. to the metaclass for Complex):
Complex r: 3.4 i: 5.0
r:i:
to the class Complex with the arguments
3.4 and 5.0. As always, we look in the receiver's class for a method, so
we look in the metaclass for Complex and find the r:i:
method
just defined. "self new" in the code sends the metaclass the method "new",
which creates a new instance of Complex. We then send the new instance the
message "setR:setI:". This looks in its class, namely Complex, to find the
method that sets the r and i parts. We then return the initialized complex
number.
We might have a prototypical complex number, with 0.0 in the r and i slots, along with other slots with methods for +, print, and so forth. To make a new complex number c, we make a descendant of the prototypical complex number, copying down the r and i slots (but not the others). When a message is sent to c, we first look in its slots for a method; if none is found, then its parent's slots, and so forth. Thus, the r and i slots would be found locally in c, while the methods for + and print would be found in the parent.
Lookup of an exception handler is done using dynamic lookup since which exception handler is appropriate will depend on the context in which the erroneous method is called. For example, if x/y is being evaluated in a method m1, and the division raises a divide by zero exception, we want to look for an exception handler in m1.
Dictionary
parameterized by K
, the types of the
keys, and by V
, the types of the values.
Dictionary
has two operations: lookup
, which
takes a single argument of type K
and returns an object of
type V
; and store
, which takes two arguments of
types K
and V
respectively. Thus
lookup
looks up a key in the dictionary and returns the
corresponding value, while store
enters a new key-value pair
in the dictionary, or replaces the value in an existing key-value pair.
We also have an abstract type Array
, parameterized by a single
type T
. Array also has two operations: lookup
,
which takes a single argument of type integer
and returns an
object of type T
; and store
, which takes two
arguments of types integer
and T
respectively.
Thus, an array is a kind of dictionary where the keys are restricted to being integers.
Using the contravariant rule, what is the subtype relation between the
following pairs of types? The answer to each question would be either
X
is a subtype of Y
, Y
is a subtype
of X
, they are equivalent (i.e. each is a subtype of the
other), or neither is a subtype of the other.
Dictionary[Object,Object]
and Array[Object]
Dictionary[Object,Object]
is a subtype of
Array[Object]
Dictionary[Integer,Object]
and Array[Object]
Dictionary[Integer,Object]
and Array[Object]
are each subtypes of each other.
Array[Integer]
and Array[Object]
Dictionary[Object,Object]
and Array[Object]
Array[Object]
is a subtype of
Dictionary[Object,Object]
, but this isn't right. Here is an
example of a program that gives an error (in some random language):
Dictionary[Integer,Object]
and Array[Object]
Dictionary[Integer,Object]
and Array[Object]
are each subtypes of each other.
Array[Integer]
is a subtype of Array[Object]
Hint: Java supports overloading, so that a method
void mytest(Object x)
void mytest(String x)
void mytest(Object x)
void mytest(String x)
void mytest(String x)
The covariance/contravariance question doesn't arise for ordinary classes, since the methods with separate signatures are simply considered to be different, and neither orverrides the other. Subtyping for arrays is handled using the covariant rule; to preserve type safety Java includes runtime type checks.
max
for
Comparable
that finds the maximum of the receiver and the
argument. Add specifications for a method add_all
for
Set
that adds all of the elements in the argument (also a set)
to the receiver, and another method maximum
that finds the
maximum element in a set.
Comparable
interface? What would be wrong with just writing
Suppose that both Integer and String implement the Comparable interface. With the F-bounded polymorphic type, we can check that an integer is less than an integer and a string is less than a string, but trying to see if a string is less than an integer doesn't type check. However, in the version that doesn't use F-bounded polymorphism, string less than integer would type check correctly.
Consider the following Smalltalk code. There is a class named
Squid
, with three methods named method1
,
method2
, and method3
.
s method1
for an instance s
of
Squid, what is printed to the transcript? Explain your reasoning.
The following is printed:
value
to the block. The block prints
out 'x=2' (since the x is the one from method2), and then returns. This
immediately returns to where method2 was called in method1. So we print
'returning from method 1' and terminate.
not
:
x
in the following
equality constraint:
y
here:
y
to
satisfy the constraint. Briefly discuss the implications for the language
semantics and implementation. (One paragraph is enough.)
In general the true and false branches of the conditional might contain any Kaleidoscope code, including assignment statements, input/output statements, and others with side effects. If the truth or falsity of the conditional weren't known, the runtime would need to checkpoint the current state, choose one of the branches arbitrarily, and backtrack if the resulting constraints were unsatisfiable. This is potentially costly, and it wouldn't function correctly with side effects that can't be undone (for example, getting input from the user).
The situation is a bit better for conditionals within a constraint constructor, since a constraint constructor can't have non-local side effects. (Note: I don't expect that anyone's answer will mention this point, since it wasn't emphasized in class.) So in a constructor we'd still need to do a search, but it would be possible to checkpoint the current state for backtracking.
m display
. If we encounter the expression
super display
in the method for display
, we'll
look for a display
method starting in C's immediate
superclass.
False. The method lookup starts in the superclass of the
class that has the display
method being run (which might not
be the same as C).
X := X+5
is represented
by temporarily asserting the constraint Temp = X+5
, then
retracting the constraint using backtracking, and finally asserting
X = Temp
.
False. CLP(R) doesn't have any assignment statement.
False. Actually the typechecking function will return a type that is the same as or a supertype of the actual type of v.
False. Pizza is statically typed (by any but the most fussy of definitions of statically typed), but array subtyping still requires runtime type tests.
True.
False.
True.