On Tue, Mar 04, 2014 at 11:09:02PM +0000, Carl Smith wrote:
The tentatively proposed idea here is using dollar signed expressions to define 'bills'. A bill object is essentially an expression which can be evaluated any number of times, potentially in different scopes.
Please don't invent "cute" names for things which already have names. What you are describing could be considered a thunk, or a macro, or a lazily-evaluated expression, depending on the precise details of how it works. But calling it a "bill" just because it starts with a $ just makes me cringe.
The following expression [a bill literal] would be pointless, but would define a bill that always evaluates to 1.
My personal feeling here is that if you have to explicitly call eval on the "bill" to evaluate it, it's not worth doing. If we were happy with that, we've already got compile(), or we have functions. Or just eval a string directly. My feeling is that evaluating the expression needs to be implicit, performed at need rather than up front, rather in the same way that short-circuiting operators don't actually evaluate the expression unless needed:
x or expr # expr is only evaluated if x is a falsey value
Yes, I know, the Zen of Python says that "explicit is better than implicit", but the Zen is intended as guidelines, not thought-blockers. We have perfectly good explicit idioms for delaying computations (eval and functions), to make the thunk/macro/whatever worth doing it has to offer something different.
Some better examples...
- assign a bill to `a` so that `a` will evaluate to the value of the name
`foo` any time that `a` is evaluated, in the scope of that evaluation
a = $foo
as above, but always plus one
a = $foo + 1
make `a` a bill that evaluates to the value of the name `foo` at the time
that `a` is evaluated, in that scope, plus the value of `bar` **at the time and in the scope of the assignment to `a`**
a = $foo + bar
Hmmm. That implies that if you want an entire expression to have delayed evaluation, you have to tag everything with a sigil:
a = $spam + $eggs - $spam*$eggs + $cheese*$spam
I think it is better to have syntax with delimiters, to turn delayed evaluation ON and OFF, rather than having to tag each and every sub-expression:
a = `spam + eggs - spam*eggs + cheese*spam`
(disclaimer: using ` ` is just for the sake of illustration.)
Note. Similarly to mixing floats with ints, any expression that contains a bill evaluates to a bill, so if `a` is a bill, `b=a+1` makes `b` a bill too. Passing a bill to eval should be the obvious way to get the value.
The point? It allows functions to accept bills to use internally. The function would specify any names the bill can reference in the function's API, like keywords.
Well, this contradicts your previous point. If any expression that contains a "bill" is a "bill", then so is func(bill). So given that, your example here:
def f(b): # the bill arg `b` can reference `item` for item in something: if eval(b): return True
f($item < 0)
would actually need to be written as:
eval(f($item < 0))