Parameter-passing and the lambda calculus

The choice of a parameter-passing technique is an important decision in the design of a high-level programming language. To clarify some of the semantic aspects of the decision, we develop, analyze, and compare modifications of the J-calculus for the most common parameter-passing techniques, i.e., call-byvalue and call-by-name combined with pass-by-worth and pass-by-reference, respectively. More specifically, for each parameter-passing technique we provide 1. a program rewriting semantics for a language with side-effects and first-class procedures based on the respective parameter-passing technique; 2. an equational theory that is derived from the rewriting semantics in a uniform manner; 3. a formal analysis of the correspondence between the calculus and the semantics; and 4. a strong normalization theorem for the imperative fragment of the theory (when applicable). A comparison of the various systems reveals that Algol’s call-by-name indeed satisfies the well-known ,8 rule of the original ~-calculus, but at the cost of complicated axioms for the imperative part of the theory. *The authors are supported in part by NSF and DARPA. The Instituto de Computation of the Universidad de la Republics Oriental del Uruguay generously provided facilities for preparing the final version of the paper. Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association fnr Computing Machinery. To copy otherwise , or to republish, requires a fee and/or specific permission. @ 1990 ACM 089791-419-8/90/0012/0233 $1.50 233 The simplest and most appealing axiom system appears to be the one for a call-by-value/pass-by-worth language with reference cells as first-class values. 1 Parameter-Passing and Lambda Calculi The choice of a parameter-passing technique is an important element in the design of a high-level programming language. The wide variety of techniques in modern languages, e.g., call-by-value, call-by-name, pass-by-reference, suggests a lack of consensus about the advantages and disadvantages of the various techniques. In this paper we analyze the most common techniques by studying and comparing equational theories for each of them. Plotkin [20] was the first to consider equational theories for the analysis of parameter-passing techniques. Starting from the folklore that Church’s A-calculus captures the essence of call-by-name in a ~rmctionai language, he developed a variant of the calculus, the ~. -calculus, to formalize the notion of call-by-value in a simple framework comparable to the ~-calculus. More importantly, he used these two examples, callby-name and call-by-value, to analyze the formal relationship between programming languages and calculi. Both the ~-calculus and the Av-calculus satisfy general correspondence conditions with respect to the appropriate semantics: (1) the calculi are sufficiently strong to evaluate a program to its answer and (2) they are sound in the sense that the equality of terms in the calculus implies their interchangeability in all program contexts. Recently, Felleisen with Friedman [9] and Hieb [10] extended Plotkin’s work to call-by-value programming languages with imperative constructs like assignments and jumps, Their result shows that, like functional constructs, imperative constructs have a simple rewriting semantics, and that there are conservative extensions of the Au-calculus for reasoning about them, namely the Av-{C,S,CS}-calculi. The extension of Plotkin’s work to imperative languages is important because it enables us to consider the whole spectrum of conventional parameterpassing techniques. Specifically, it is only through the addition of imperative constructs that the design options for alternative parameter-passing techniques become interesting. Whereas in a functional setting the only observable differences between call-by-value and call-by-name versions of a program is the termination behavior, the two versions of the same program can produce different results in imperative languages. Moreover, in the presence of assignments, it is also possible to distinguish parameter-passing techniques that bind parameters to values from those that bind parameters to references to values. Based on these observations, we classify parameterpassing techniques according to their respective evaluation and binding strategies. The evaluation strategy determines when -10 evaluate procedure arguments, while the binding strategy determines what part of the argument to bind to formal parameters. The two prevailing evaluation strategies are eager evaluation (call-by-value), which evaluates the argument to a procedure call before binding the parameter, and delayed evaluation (call-by-name), which does not evaluate the argument until the value of the parameter is needed.1 As for binding strategies, we consider pass-byworth, which binds the parameter to the value, i.e., “worth,” of the argument, and pass-by-reference, which binds the parameter to a variable, i.e., a “reference” to a value. A third strategy, pass-by-vaJueresuli, has properties of both pass-by-worth and passby-reference. In this paper, we analyze the parameter-passing techniques produced by the various combinations of evaluation and binding strategies. Also included is a discussion of the reference cell, a language construct that provides an alternative to the pass-by-reference binding technique. For each technique we develop a rewriting semantics and a calculus for a higher-order programming language that uses the technique. The calculi satisfy variants of Plotkin’s correspondence criteria. In addition, their imperative fragments sat] Two other delayed evaluation strategies, which we do not consider in this paper, are call-by-text and call-by-need. Callby-text never evaluates procedure arguments, thus, delaying evaluation forever. Muller [17] recently analyzed some of the problems of deriving equational theories in the presence of callby-text. Call-by-need is an optimization of call-by-name in a functional language, but produces different answers than caUby-name in the presence of side-effects. The extended version of this paper [4] contains a brief discussion of call-by-need. isfy strong normalization theorems and are therefore decidable. The next section of this paper describes in more detail the steps of the analysis: the definition of an operational semantics, the derivation of an equational calculus, and the formal analysis of correspondence between the semantics and the calculus. Section 3 examines each of the parameter-passing techniques using the methods outlined in Section 2. We discuss related work and compare the different techniques in Sections 4 and 5. 2 From Operational Semantics to Calculi In our analysis of parameter-passing, there are three main steps. First, we define an operational semantics for a language with a particular parameter-passing technique. Next, we derive an equational calculus directly from the semantics, and finally, we analyze the correspondence between the calculus and the semantics. This section describes each of these steps in more detail. Definition of a Language and its Operational Semantics The definition of a language consists of two parts: the specification of a syntax and an operational semantics. We provide one for each of the parameterpassing techniques. The core of our languages, A, consists of const ants (c), variables (z), A-abstractions and applications of the A-calculus: e ::= 8 I v I (ee) v ::= c I Xr.e The languages extend A with constructs for sideeffects, which we describe in later sections. Following Barendregt’s [1] conventions, we assume that, in the following definitions and theorems, the bound variables are distinct from the free variables in expressions, and we identify expressions that differ only by a renaming of the bound variables. The expression e [z +e’] denotes the expression resulting from the substitution of all free occurrences of the variable ~ in e with the expression e’. The set of free variables in an expression e is denoted by FV(e). An expression with no free variables is closed. Below we need the notion of a context for several definitions. A context, C, is a term with a “hole” ([]) in the place of a subexpression; C[e] is the expression produced by replacing the hole in a context C with the expression e.