Terminology: Thunking vs Quoting

In Cat the construction of a nullary constant generating function (e.g. a thunk) is done using the "quote" operator. It pops a value off the stack, and pushes a nullary function onto the stack. In other words the quote operation has the type: ('a -> ( -> 'a))

I could have called the operation "thunk", but I find the term discordant (a purely subjective opinion). I wonder if there are other associations with the term "quote" which suggest maybe I would be better off if I called the operation "thunk"? Perhaps there is a better term?

Any suggestions would be appreciated.

Comment viewing options

What about "constant" (or "k")? as it creates a constant function?

Thanks for the suggestion

I believe in lisp they have something similar called "constantly". Do you prefer the terms "constant" or "constantly" to "quote"? I don't have a formal definition of what a "constant function" actually is, so I find that "constant" is somewhat unclear to my intuition of "1" being a constant and "[1]" being a nullary function.

The "k" operation is similar to the "quote" operation but has a slightly different type signature:

  k : ('a -> ('b -> 'a))

where "quote" has the type:

  quote : ('a -> ( -> 'a))

Interestingly you could construct "quote" from "k" as:

  define quote { [] swap k }

And "k" from "quote" as:

  define k { quote [pop] swap compose }

Yes

(and constantly reads better than constant), but thunk sounds good to. I think quote would be rather missleading as in all other languages that I know of, quote is a non-strict construct that don't evaluate it(s) argument(s), and that doesn't seem to be the case here.

On the evaluation of arguments

Interesting. If I was to quote a function, it wouldn't be evaluated. In fact functions passed to functions are never evaluated. To pass a function as an argument to a function you have to use what I am calling the the quote operators "[" and "]".

If I was to write a function with a side-effect:

  >> define f { 1 writeln }
stack: _empty_
>> define g { [f] pop }
stack: _empty_
>> g
stack: _empty_           // nothing hapens

If I was to call quote as follows:

  >> [f] quote  // nothing happens
stack: [[f]]
>> eval
stack: [f]
>> eval
1             // first time something is written to the screen
stack: _empty_

So perhaps it would be accurate to say Cat is in general non-strict since arguments are never evaluated.

eval versus apply

arguments are never evaluated

I think you're going to confuse people by saying this. In a stack-based language, the line between application and evaluation is fuzzy, but based on your examples it seems clear that function arguments are always values and therefore must have been evaluated. You seem to be saying that it is possible to pass functions as values without applying them, but the functions still must be evaluated (converted from a name to a function value) first. I'm not sure what a non-strict stack-based language would look like but I'm guessing something like this would need to terminate:

 define f { f } f pop 

Perhaps Call by Push Value

Perhaps Call by Push Value is relevant?

lexical scope

In Lispy languages there's a huge difference between quoting and thunking, namely what happens with free variables. If x is bound to (lambda () e) then (x) will evaluate the same in any context.

But if x is bound to (quote e) then (eval x) will not necessarily evaluate the same in all contexts. For example, if e is (+ 1 y) then in the context (let ((y 1)) _), (eval x) evaluates to 2, whereas in the context (let ((y 42)) _), (eval x) evaluates to 43.

I don't know much about stack-based languages, but if I'm not mistaken, there are no lexically-bound variables in stack-based languages, so there are no closures. Am I right? If that's the case, then I imagine there really is no difference between quoting and thunkifying.

Yes you are right

Thanks for clarifying the difference for me. In stack-based languages lacking names (like Joy) there is no closure over environment, so quoting and thunkifying are equivalent.

However, in the current version of Cat I've added local names. You can write:

define f(x) { x quote }

Which behaves like:

define f { quote }

The problem then is that the lisp "quote" behavior of late-binding the names (correct terminology?) does not hold. For example:

define f(x) { x quote }
define g(x) { 13 f eval }
define h { 12 g + }
h == 25 // not 26

Do you think it is a bad idea then for me to use the name "quote"? Or is it an excusable break from tradition. I am loathe to use an unweildy name like "constantly", and I am not fond of "thunk", though it is looking more and more like something I should just get used to.

I prefer 'constantly'. This

I prefer 'constantly'. This may be more of an end-user perspective than you're looking for, but constantly maps perfectly onto my mental concept of what a constant function does, whereas phrases such as quote or thunk seem closer to a language designer's view of what the function does. Thunk is very obscure to me in that context, quote less so (but quote collides with the Lisp meaning of quote which I would find confusing given the different semantics in a stack-based language).

Thanks a lot, cdiggins.

Thanks a lot, cdiggins. Believe it or not, after reading a boring book and without being able to understand the difference reading 20 pages, your simple explanation made me understand the difference between thunking and quoting.
Actimel Casei

Write a book! :)

______________________