On Wednesday, March 26, 2014 9:35:53 PM UTC+5:30, Steven D'Aprano wrote: > On Wed, 26 Mar 2014 00:30:21 -0400, Terry Reedy wrote:
> > On 3/25/2014 8:12 PM, Steven D'Aprano wrote: > >> On Tue, 25 Mar 2014 19:55:39 -0400, Terry Reedy wrote: > >>> On 3/25/2014 11:18 AM, Steven D'Aprano wrote: > >>>> The thing is, we can't just create a ∑ function, because it doesn't > >>>> work the way the summation operator works. The problem is that we > >>>> would want syntactic support, so we could write something like this: > >>>> p = 2 > >>>> ∑(n, 1, 10, n**p) > >>> Of course we can. If we do not insist on separating the dummy name > >>> from the expression that contains it. this works. > >>> def sigma(low, high, func): > >>> sum = 0 > >>> for i in range(low, high+1): > >>> sum += func(i) > >>> return sum > >> There is no expression there. There is a function. > >> You cannot pass an expression to a function in Python, > > One passes an unquoted expression in code by quoting it with either > > lambda, paired quote marks (Lisp used a single '), > Passing *strings* and *functions* is not the same as having compiler > support for delayed evaluation. At best its a second-class work-around. > Contrast: Once the language has lambda, most else can be fashioned See the classic papers lambda the ultimate imperative lambda the ultimate declarative lambda the ultimate goto at here http://library.readscheme.org/page1.html > Coincidentally, the Sum function we were discussing is a notable example > of Jensen's Device: > https://en.wikipedia.org/wiki/Jensen%27s_device > which is effectively what I'm referring to. > > > because expressions are not first-class objects. > > The concept is not a class, and the Python stdlib does not have an > > expression class. But people have written classes to represent the > > concept. I used existing classes instead. > > Expressions are not (normally) mathematical objects either. (An > > exception is rewriting theory, or other theories, where strings > > representing expressions or WFFs (well-formed formulas) are the only > > objects.) Mathematicians quote expression strings by context or > > positiion. The sigma form is one of many examples. > Hmmm. I think you are misunderstanding me, possibly because I wrote > "first-class object" when I should have called it a "first-class value". > Sorry. > I'm not necessarily referring to creating something like an "arithmetic > expression class" with methods and attributes. For example, sympy has > things like that, so you can perform symbolic operations on the > expression. That's not what I mean. > What I mean is that you, the programmer, writes down an ordinary Python > expression, using ordinary expression syntax, and the compiler treats it > as a value in and of itself, rather than evaluating it to find out what > value it has. In Python this will probably be some sort of object, but > that's not the important part. The important part is that it is a *value*. > (Compare to languages where functions are not first-class values. You > cannot pass a function to another function, or stick them in a list, or > create them on the fly. You can only call them, evaluating them > immediately.) > In Algol60, the compiler used thunks, which are a type of closure; in > CPython, list comps use a hidden function object; the ternary if compiles > byte code for a test and jump. > In case you haven't read the article on Jensen's Device above, in Algol60 > you can write a Sum function that behaves as a mathematician would > expect. For example, to sum the entries of an array V for indexes 1 > through 100, a mathematician might write it something like this: > 10 > ∑ V[i] > i=1 > which we can rearrange to function-call syntax like this: > Sum(i, 1, 100, V[i]) > In Algol60, this function call would: > - pass the name "i" (not a string!) as the first argument; > - pass 1 as the second argument; > - pass 100 as the third argument; > - pass the expression "V[i]" (not a string!) as the fourth argument > and then *inside* the function Sum the expressions "i" and "V[i]" can be > evaluated or assigned to as needed. Using Python syntax rather than Algol > syntax: > def Sum(name, lower, upper, expression): > total = 0 > for name in range(lower, upper+1): > total += expression > return total > This doesn't work in Python! Python lacks call-by-name semantics, so the > function call would: > - evaluate the expression i, and pass that value as the first argument; > - pass 1 as the second argument; > - pass 100 as the third argument; > - evaluate V[i] and pass that value as the fourth argument > and then inside the function Sum "name" refers to the local variable > name, not the caller's variable i. Likewise "expression" refers to a > local variable, and not the caller's expression V[i]. > Python has no general way of doing this. There are a few ad-hoc special > cases, like list comps, the ternary if operator, etc. which are hard- > coded in the compiler to delay execution of expressions. For the rest, > you have a choice: > - give up on delayed evaluation, and redesign your API; or > - manually manage the delayed evaluation yourself, using > some combination of functions, eval or exec. Heres Jensen device in python First your pseudo algol version with python frills like range removed def sumjensen(i,lower,upper,exp): # i and exp by name # i get and set, exp only get required tot = 0 i = lower while i <= upper: tot += exp i = i + 1 return tot Now actual python def sumjensen(i_get, i_set,lower,upper,exp): tot = 0 i_set(lower) while i_get() <= upper: tot += exp_get() i_set(i_get() + 1) return tot i=0 a=[3,4,5] i_get = lambda : i def i_set(val): global i i = val exp_get = lambda : a[i_get()] call as sumjensen(i_get, i_set, lower, upper, exp_get) [Note that because of lambda's restriction to being only an expression I have to make it a def because of need for global] -- https://mail.python.org/mailman/listinfo/python-list