1. a. "Statically typed" means that the type of every expression can be determined at compile time. We also check at compile time that all functions and operations are applied to expressions of the correct type. "Strongly typed" means that the language guarantees that one type can't be incorrectly used in place of another type, in other words, that all expressions are guaranteed to be type consistent. This can be checked at compile time, run time, or a mixture. Statically typed implies strongly typed. Therefore, there are no languages that are statically typed but not strongly typed. There are languages that are strongly typed but not statically typed, for example Lisp. [I will also accept an answer that says strongly typed = statically typed, since some authors use the term "strongly typed" in this way.] b. Regarding the claim about the Ada program, I disagree with the claim. Ada would define both J and K to be of type INTEGER. The subtype LITTLE has an additional constraint that values of this type are in the range 0 to 10. However, a LITTLE can always be passed to an operation expecting an INTEGER without violating the type system; a runtime range check may be needed however. Violating this range check isn't a type error, though, in the same way that array-out-of-bounds and divide-by-zero exceptions aren't type errors. 2. The output if n is passed using: (a) call by value 8 3 3 (b) call by value result 8 3 8 (c) call by reference 11 11 11 3. "in procedure oak -- n=3 k=10" [This is all that is expected for an answer. If you want to know why this happens, here's an explanation. The procedure pine is called with n=1, then it recursively calls itself with n=2, n=3,... n=10. When n=3 it inserts procedure oak in the call, to be passed along to later calls as the formal parameter p. Finally, when n=10, pine calls p with the formal parameter k=10. However, p was bound to the version of oak, whose statically enclosing environment was the activation of pine with n=3.] 4. and 5. Here are the answers, straight from Miranda: ______________________________________________________________________ Script started on Thu Nov 7 11:12:04 1991 lynx% mira midt T h e M i r a n d a S y s t e m version 2.010 last revised 6 January 1990 Copyright Research Software Ltd, 1989 compiling midt.m checking types in midt.m for help type /help Miranda twice add5 3 13 Miranda map cube [1..] [1,8,27,64,125,216,343,512,729,1000,1331,1728,2197,2744,3375,4096,4913,5832,6859,8000,9261,10648,12167,13824,15625,17576,19683,21952,24389,27000,29791,32768,35937,39304,42875,46656,50653,54872,59319,64000,68921,74088,79507,85184,91125,97336,103823,110592,117649,125000,132651,140608,148877,157464,166375,175616,185193,195112,205379,216000,226981,238328,250047,262144,274625,287496,300763,314432,328509,343000,357911,373248,389017,405224,421875,438976,456533,474552,493039,512000,531441,551368,571787,592704,614125,636056,658503,681472,704969,729000,753571,778688,804357,^C3<<...interrupt>> Miranda twice double [1..5] [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5] Miranda mymember [1..] 0 <> [in other words, either runtime error or nonterminating computation are acceptable answers] Miranda second (mymember [1..] 0) 3 3 Miranda twice add5 :: num->num Miranda mymap :: (*->**)->[*]->[**] Miranda mymap double :: [[*]]->[[*]] Miranda second :: *->**->** Miranda mymember :: [*]->*->bool ______________________________________________________________________ 6. a. T1 and T2 can run concurrently, except when T2 invokes T1.ZORK. When T2 invokes T1.ZORK, T2 is blocked during the time T1 is executing the statements between the "accept ZORK" and "end ZORK" statements. (This communication is called a rendezvous.) After the "end ZORK" statement, T1 and T2 can again execute concurrently. b. Here are the two possible outputs: before invoking ZORK in accept in T1 outside of accept in T1 after invoking ZORK before invoking ZORK in accept in T1 after invoking ZORK outside of accept in T1 7. A weakly typed language is one that is not strongly typed, in other words, a language that allows one type to be used incorrectly in place of another type. Fortran is weakly typed because the COMMON statement allows two variables of different types to be aliased. For example, in one subroutine one could have the statement COMMON X for a real X, and in another suroutine the statement COMMON J for an integer J. X and J would occupy the same storage location, and the real value could be misinterpreted as an integer or vice versa. Another reason Fortran is weakly typed is that the EQUIVALENCE statement allows the same sort of aliasing, for example EQUIVALENCE X,J [Only one example is needed in your answer.] Pascal is weakly typed because of a loophole in variant records. One can for example define a variant record with either an integer or a real in the variant part. Unfortunately, Pascal allows the tag field to be assigned independently of the rest of the fields of the record. Therefore, one could make an instance of the variant record with an integer in the variant part, then change the tag, leaving the integer value to be mis-interpreted as a real. 8. a. When a parameter is passed using call-by-name in Algol 60, whenever the formal parameter is needed in an expression in the body of the procedure, the value of the actual parameter is recomputed. (If the value of the parameter is never needed, the value of the actual is never computed.) In addition, if the actual parameter is a variable or array element reference, one can assign to the formal parameter in the procedure, and have the value immediately assigned to the actual parameter. When parameters are passed using lazy evaluation, the value of the actual parameter isn't computed until it is needed (which may be never). The first time the value is computed, it is cached, so that subsequent uses of the formal parameter just retrieve this cached value. The essential similarity is that, for both call-by-name and lazy evaluation, if the value of the formal parameter is never used, the actual parameter won't be evaluated. The differences are thus as follows: call-by-name may result in evaluating the actual parameter many times (each time the formal's value is needed), while lazy evaluation will evaluate it at most once. For call-by-name, if the actual parameter is an l-value (e.g. variable or array reference), the programmer can assign to the formal parameter and have the value stored back into the actual. b. There would be no effect on the semantics. (Since this is a functional language, evaluating the same expression again will always give the same result.) The efficiency would be less, if the parameter's value were used more than once, since there would be extra evaluations. c. The semantics would change. First, since Algol-60 is an imperative language, it would be possible to change a value that the actual parameter depends on in between uses of the formal parameter, so that re-evaluating the actual parameter would give different results. If lazy evaluation were used, the first time it was evaluated the result would be cached and returned thereafter. Second, lazy evaluation wouldn't allow information to flow backwards (unless you interpret lazy evaluation in a weird way). The efficiency would improve if the value of the parameter were used more than once (if you're willing to get the same value each time!)