STCS8004%IRUCCVAX.UCC.IE@mitvma.mit.EDU (05/08/91)
In response to my question: ... *WHY NOT ALLOW THE USER* to specify normal evaluation when required? John Gateley responds <GATELEY.91May3125853@datura.rice.edu>: Just out of curiosity, how would you compile the following function: (define foo (lambda (f x y z) (f z y x))) Consider (foo + 1 2 3) and (foo if else then pred)? The arguments to ANY application must be assumed to be passed in normal order unless you can prove otherwise. Is this what you really want? No, and I hope that that isn't the unavoidable consequence! As I understand your point, when the evaluator encounters (foo ... ) it will not know whether to evaluate the arguments or not, since in the definition of 'foo' there is nothing to indicate what is to be done. In the one case all the arguments to (f ...) need to be strict and in the other not. But if, as in Pascal, Algol 60, ... one is allowed to specify the calling style for each parameter at definition time is there still a problem? Thus couldn't (define f (lambda (x #!normal y) (... x ... y ...))) be compiled as though we had written (define f (lambda (x y) (... x ... (y) ...))) and the decision whether or not to pass <arg2> by value or as a thunk in (f <arg1> <arg2>) be made when checking that 'f' has been given two arguments - whether compiling or interpreting? Gordon Oulsnam stcs8004@iruccvax.ucc.hea.ie PS to all readers: I will be incommunicado from 1600 GMT 91/05/08 to 91/05/23 so cannot respond immediately to messages *received* in that period (Digest 211 and later) but will reply/summarize as appropriate on return. G.O.
jinx@zurich.ai.mit.edu (Guillermo J. Rozas) (05/09/91)
No, and I hope that that isn't the unavoidable consequence! As I understand your point, when the evaluator encounters (foo ... ) it will not know whether to evaluate the arguments or not, since in the definition of 'foo' there is nothing to indicate what is to be done. In the one case all the arguments to (f ...) need to be strict and in the other not. But if, as in Pascal, Algol 60, ... one is allowed to specify the calling style for each parameter at definition time is there still a problem? Thus couldn't (define f (lambda (x #!normal y) (... x ... y ...))) be compiled as though we had written (define f (lambda (x y) (... x ... (y) ...))) and the decision whether or not to pass <arg2> by value or as a thunk in (f <arg1> <arg2>) be made when checking that 'f' has been given two arguments - whether compiling or interpreting? The problem is that f may be separately compiled (ie. in another module), not visible to the compiler. The compiler must assume the worst in order to be correct, and either compile two versions of the code (for every call), or compile arguments as if they were thunks, and then invoke them if f is found not to expect normal-order parameters. Even in the case of non-separately compiled programs, how are we supposed to handle things like the following? ((vector-ref some-vector 23) (+ x y) (foo x)) or even (define (map-2 f l1 l2) (cond ((and (pair? l1) (pair? l2)) (cons (f (car l) (car l2)) (map-2 f (cdr l1) (cdr l2)))) ((or (null? l1) (null? l2)) '()) (else (error "map-2: Bad arguments" l1 l2)))) When the system was built, neither the compiler nor even the system designer can know the range of values that might be passed to map-2 (or map, or for-each, etc.), so the worst case must be assumed. But that means that everyone pays the cost, not only those people using normal-order parameter-passing. I'm afraid that it IS the unavoidable consequence, and that is why not many implement systems with both normal order and applicative order parameters.