# Thunk vs. lambda and doc confusion

**URL:** <https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388>\
**Category:** Questions & Answers\
**Tags:** question\
**Created:** [September 16, 2026, 12:08am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388 "2026-09-16T00:08:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![gbellinoz](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gbellinoz/32/2738_2.png) [@gbellinoz](https://racket.discourse.group/u/gbellinoz)\
**Post date:** [September 16, 2026, 12:08am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/1 "2026-09-16T00:08:41Z")

</div>

Hi team,

The [Thunk glossary entry](https://docs.racket-lang.org/racket-glossary/#(part._.Thunk)) has a second example that is supposedly turning a function into a thunk, yet it uses the `lambda` keyword!

But [thunks exist as a keyword](https://docs.racket-lang.org/reference/procedures.html?version=9.3#%28form._%28%28lib._racket%2Ffunction..rkt%29._thunk%29%29), so why use `lambda`?

Am I missing something, or is that confusing?

---

<div class="post-metadata">

**Author:** ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)\
**Post date:** [September 16, 2026, 12:32am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/2 "2026-09-16T00:32:49Z")

</div>

I pasted this exact question to ChatGPT, and got a pretty good answer, so I will just paste the response here (with slight modifications to improve correctness).

> the confusing part is that **“thunk” and `thunk` are two different things**.
> 
> The glossary is using _thunk_ in the general programming-language sense: **a thunk is a procedure that takes zero arguments**. A thunk can be constructed in many different ways. The example uses `lambda` to construct a thunk. But `thunk` can also be used to construct a thunk.
> 
> Meanwhile, **`thunk` is a Racket macro/syntax**. It is essentially a convenience for constructing a thunk. `(thunk (displayln "yes"))` is just another way of writing something equivalent in purpose to `(lambda () (displayln "yes"))`.
> 
> The important distinction is:
> 
> - **thunk** — a _concept_: a zero-argument procedure whose body can be run later.
> - **`thunk`** — a particular Racket macro provided by the language/library to construct a thunk, but not necessarily the only way to construct a thunk.
> - **`lambda`** — a core form for constructing procedures, including zero-argument procedures (thunk).

---

<div class="post-metadata">

**Author:** ![gbellinoz](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gbellinoz/32/2738_2.png) [@gbellinoz](https://racket.discourse.group/u/gbellinoz)\
**Post date:** [September 16, 2026, 12:47am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/3 "2026-09-16T00:47:49Z")

</div>

Really disappointing to come here for conversation with people and getting an "answer" pasted from an LLM that I also have access to 😑 Thanks for editing it, at least.

---

<div class="post-metadata">

**Author:** ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)\
**Post date:** [September 16, 2026, 4:31am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/4 "2026-09-16T04:31:38Z")

</div>

Alright, now you have a full human response.

Let me ask you (and @LiberalArtist and @Zeb who seem to share your concern) this: how do you want the response to be different?

On top of the raw LLM response, I corrected how it says that `thunk` is a procedure. I cut about 5 verbose paragraphs that I thought have little values (e.g., it spent a few paragraphs affirming that the glossary is poorly worded, which I disagree with). I added the bit that a thunk can be constructed from various ways to make the answer flows better. And I vetted that everything is accurate. Most text is still from the original response though.

Would having me spending time typing the answer out character-by-character be really that valuable to you?

---

<div class="post-metadata">

**Author:** ![gbellinoz](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gbellinoz/32/2738_2.png) [@gbellinoz](https://racket.discourse.group/u/gbellinoz)\
**Post date:** [September 16, 2026, 6:30am UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/5 "2026-09-16T06:30:11Z")

</div>

Now two topics. I'll nip the first:

1. The question is when/whether we should be asking each other questions and having discussions when LLMs can "do it all anyway". That's societal, and locally cultural (eg. the Racket community), and I cannot answer it, only indicate my personal disappointment when I ask for a yarn and get modem noises. Eeeeeee ahhhhh brrrrrrrrrrrrr. Beep beep boop.

On topic:

1. I believe you have answered my question, thanks again for the effort. My rewording to check comprehension: Yes, it's a little weird that a glossary entry doesn't use the keyword of the same name, but that is for conceptual clarity and explanatory power. The way you make a little unit of deferred execution (ie. a "thunk") _is_ with a lambda, and the `thunk` keyword is just syntatic sugar for that same thing.

(By the way, I'm trying to _not_ type anything out character-by-character these days because speech recognition has gotten so good! Currently using the very lightweight [asryx](https://github.com/rccyx/asryx) and can't believe it actually works given its size and simplicity).

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [September 16, 2026, 4:26pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/6 "2026-09-16T16:26:03Z")

</div>

> But thunks exist as a keyword, so why use `lambda`?

1. To nitpick, `thunk` is not a "keyword" -- it's not special or privileged. It's merely a macro, which anyone could write themselves -- not just the creators of Racket. I nitpick because this extreme extensibility a pretty important idea in Racket (and some other languages including most lisps).

2. Another small point to consider is that `racket/base` is a lighter set of things to require in a program -- unlike `racket`, which automatically imports dozens of libraries like `racket/function`. Often people avoid `racket` because it's so "heavy", use `racket/base`, and `require` just the specific modules they need.

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [September 16, 2026, 4:31pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/7 "2026-09-16T16:31:00Z")

</div>

I am probably the least-big fan of LLMs here, so I understand where you're coming from.

OTOH @sorawee did disclose, and did proof-read and edit. You got not just an "answer" but an answer, IMHO.

Also, if you want to be mad, I would prioritize first being mad about the "Summarize with AI" button that Discourse slammed into the UI here. That is present on every flopping topic here.

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [September 16, 2026, 5:13pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/8 "2026-09-16T17:13:31Z")

</div>

> [@gbellinoz](#):
>
> 1. I believe you have answered my question, thanks again for the effort. My rewording to check comprehension: Yes, it's a little weird that a glossary entry doesn't use the keyword of the same name, but that is for conceptual clarity and explanatory power. The way you make a little unit of deferred execution (ie. a "thunk") _is_ with a lambda, and the `thunk` keyword is just syntatic sugar for that same thing.

The one thing I'd add is that is that I almost never use the `thunk` syntactic sugar, and I also don't see it especially often in code I read. Some people like it and use it often, and there's nothing wrong with it, I just wouldn't want to give the impression that it's “better style” or something to write a thunk using `thunk`. In particular, note that `(λ () 1)` is actually shorter than `(thunk 1)`.

(On the other hand, `thunk` _is_ used idiomatically with `for/foldr`, where it's helpful to have a keyword of the same shape as other `delay`-like forms.)

* * *

> [@sorawee](#):
>
> Let me ask you (and @LiberalArtist and @Zeb who seem to share your concern) this: how do you want the response to be different?

First let me say that I don't claim to have a definitive answer to this area of rappidly-evolving social norms!

Given the premise of starting with an LLM response, I think your post handled it more or less optimally. Even before you described your modifications in more detail, I assumed you had done something like that, first because the content was all accurate and relevant (which I can rarely say of raw LLM output), but also because you have been a trusted member of this community for a long time.

One thing I wonder is, given the amount of editing and checking for accuracy, does starting with an LLM still feel like it saves you time, effort, etc.? (Even ignoring this ensuing meta-discussion.)

Part of my concern is for the usefulness of answers for people newer to the Racket community. Since I already knew how I would answer this question, I could check the LLM output for accuracy, and I also had confidence that you, @sorawee, would have done so. But if I didn't already have a level of trust in you, and I couldn't check the accuracy of the LLM output myself—because I didn't already know the answer to my question—I would have very low confidence in relying on it.

I can also imagine it feeling offputting from the perspective that, if I'd wanted an LLM’s response, I could have asked one.

Another concern is that, often, I find the conversation in these threads at least as valuable as an “answer” per se. That's especially true with a question like this one, which is largely about matters of style and taste, where responding to questions is one of the main ways perspectives get written down. For instance, I know there are some Racketeers who _do_ use `thunk` regularly, and I'd be interested to hear their perspectives! To me, LLM output doesn't add to these conversations, and editing the output seems only partially to help: what I really want to know is each commenter’s personal thoughts.

I am glad that the Racket community includes people with a broader range of stances toward LLMs than my personal views, and I'm not advocating for any sort of “rule.” But there are some of my concerns about LLM-driven responses, especially if they were to become more widespread while being handled with less care than you did, @sorawee.

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [September 16, 2026, 5:23pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/9 "2026-09-16T17:23:18Z")

</div>

> [@greghendershott](#):
>
> 1. To nitpick, `thunk` is not a "keyword" -- it's not special or privileged. It's merely a macro …

To further nitpick, sometimes “keyword” is used to mean the identifier which introduces a macro or other syntactic form. I think that use is more common in broader Scheme circles, but I believe I've seen it in Racket contexts, too. I tend to avoid using it that way, in part because we usually use “keyword” to mean `#:one-of-these` (which I think is why it's a less common formulation in Racket in general). But that is the sense that I understood here.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [September 16, 2026, 6:01pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/10 "2026-09-16T18:01:36Z")

</div>

> [@LiberalArtist](#):
>
> For instance, I know there are some Racketeers who _do_ use `thunk` regularly, and I'd be interested to hear their perspectives!

Since you asked 😉

The advantage of `thunk` for me when I use it is probably semantics: it names the thing. (It’s also easier to remember “thread over thunk” in my head.) And `thunk*` is nice for not naming an unused arg list.

And I get to type one less set of `()`, but that’s a finger macro at this point, so…

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [September 16, 2026, 6:02pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/11 "2026-09-16T18:02:10Z")

</div>

Somehow I understood OP to mean "keyword" in the sense of "reserved keyword" in many languages.

But I might have misunderstood.

Anyway that's a great point that, in Racket, "keyword" usually means `#:one-of-these`.

---

<div class="post-metadata">

**Author:** ![ndykman](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/ndykman/32/2140_2.png) [@ndykman](https://racket.discourse.group/u/ndykman)\
**Post date:** [September 16, 2026, 11:20pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/12 "2026-09-16T23:20:49Z")

</div>

The history of the term always makes me smile. Algol 60 had call by name, which meant expressions as a parameter of a routine could be evaluated multiple times. The fix was to wrap it in a tiny little subroutine that returns a reference to the result value. When looking at, they realized they could do some compile time optimizations because the type was already "thought of" by the compiler. Or, as they put it, the compiler had thunked it.

Hence the macro. Also, while this isn't true in Racket, the original intent is that the function will always return the same value, so it can be evaluated once and later uses of the thunk are replaced with a simple memory dereference. Some use the macro to imply those semantics, where as a `lambda () ...` is just like any other function.

---

<div class="post-metadata">

**Author:** ![ryanc](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/ryanc/32/71_2.png) [@ryanc](https://racket.discourse.group/u/ryanc)\
**Post date:** [September 16, 2026, 11:34pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/13 "2026-09-16T23:34:50Z")

</div>

I don't think I've heard that explanation of the name before. I heard it explained as "the sound of an empty activation record hitting the stack".

---

<div class="post-metadata">

**Author:** ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)\
**Post date:** [September 16, 2026, 11:56pm UTC](https://racket.discourse.group/t/thunk-vs-lambda-and-doc-confusion/4388/14 "2026-09-16T23:56:51Z")

</div>

For the record, this conflates two distinct concepts: thunks and delays.

The point of a (n Algol) `thunk` is to return the result of re-evaluating an argument whenever it is referenced. Algol's designers understood that this could one a _different_ value for each reference. There is even a name for exploiting this property: Jensen's device.

The point of a `'delay` is to _cache_ the result from the first evaluation, even if this is an exception in Racket, and to yield this result every time it is requested again. The idea goes back to the "Lazy Cons" article of Friedman and Wise. Haskell is the modern version of this.

-- Matthias, an Algol programmer
