Lecture 10, CSE341, Spring 2004 summary Equivalence and Syntactic Sugar * There are many definitions of equivalence, based on what _context_ two expressions must be equivalent in and what is _observable_ about how the expressions evaluate. * When considering equivalence, inputs and outputs matter, but so do potential _effects_, such as raising exceptions, printing or going into an infinite loop. * We can use equivalence to _define_ constructs in terms of more primitive constructs -- the less primitve ones are called "syntactic sugar". Examples in ML include andalso, conditionals, and things like #foo. * There are a few standard equivalences involving function definitions: 1. We can systematically rename a function parameter and all its uses, but we must not pick a new name that already _occurs as a free variable_ in the function body. 2. We can substitute an actual argument for a function parameter, but only if the argument is effect-free and does not have free variables _captured_ in the function body. 3. We can replace (fn x => e x) with e, but only if e is effect-free and does not have a free occurrence of x. * The notion of a "free occurrence" is straightforward: A variable use is "free" if it is not bound by a function parameter or val-binding in the expression. For example, in (fn x => x + y), x and y are free in the function body x+y, but only y is free in the whole expression.