On Wed, Mar 05, 2014 at 12:41:10PM +0000, Carl Smith wrote:
Just for the record, I never called them bills just because they contain a dollar sign! I was thinking of a short word which describes an expression who's evaluation changes depending on the local circumstances. Like a legal bill, not a dollar bill.
Hmmm. Well, I don't really get the connection between legal bills and delayed evaluation, and I still really dislike the name.
The name macro doesn't really work, as it's only an expression, it's not a code block.
There is nothing about macros that *require* them to accept a full block of code. In fact, there are multiple different meanings for macro, although they are all related they do have significant differences:
Macros in C are not the same kind of thing as macros in Lisp.
The idea was never to start passing complex expressions around the place.
What you consider a complex expression somebody else may consider a simple expression. Unless you want to demand some arbitrary hard limit on complexity (and how do you measure complexity?) this "bill" system would have to allow the exact same types of expressions that are legal elsewhere in Python.
What the hell is a thunk anyway? It's a horrible name.
Wikipedia is your friend: http://en.wikipedia.org/wiki/Thunk
Also, more here: http://c2.com/cgi/wiki?CallByName
The meaning of thunk I'm referring to comes from the call-by-name argument passing model. Suppose we pass an expression to a function:
and the body of the function looks like this:
if arg > 1: y = arg + 1 else: y = arg - 1 return y*arg
In the "call-by-name" model, the function body executes like this:
if (x+1) > 1: y = (x+1) + 1 else: y = (x+1) - 1 return y*(x+1)
which not only duplicates the "x+1" part four times, but may require evaluating it three times. To avoid this wasteful duplication, the compiler creates a special thunk value, which is something like a function with no arguments:
def thunk(): if cache is None: cache = x-1 return cache
(This should be considered pseudo-code, not the exact way Algol or Haskell work -- real thunks also allow you to assign a value back to the "name". Also, technically the presence of a cache makes it call-by-need rather than call-by-name).
The body of the function then becomes:
if thunk() > 1: y = thunk() + 1 else: y = thunk() - 1 return y*thunk()
So as you can see, what I've been calling a thunk is not precisely like Algol thunks. One thing which is missing is the dynamic scoping: in the thunk evaluation, the x comes from the caller's scope. But the delayed evaluation part is quite similar, enough that I think the name may be appropriate. Another name for this might be a "promise", as in the promise to execute a computation later.