# How to introduce new bindings without using \`define-\*\`?

**URL:** <https://racket.discourse.group/t/how-to-introduce-new-bindings-without-using-define/3856>\
**Category:** Questions & Answers\
**Created:** [July 17, 2025, 10:27am UTC](https://racket.discourse.group/t/how-to-introduce-new-bindings-without-using-define/3856 "2025-07-17T10:27:33Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![bakgatviooldoos](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bakgatviooldoos/32/1381_2.png) [@bakgatviooldoos](https://racket.discourse.group/u/bakgatviooldoos)\
**Post date:** [July 17, 2025, 10:27am UTC](https://racket.discourse.group/t/how-to-introduce-new-bindings-without-using-define/3856/1 "2025-07-17T10:27:34Z")

</div>

Hi, Racket Discourse.

I am curious about how one introduces a new binding into a definition context--if I am using these terms correctly.

I am looking at defining [`out-parameters`](https://racket.discourse.group/t/out-parameters-in-racket/3855) in Racket, but my method of introducing these identifiers is crude, to say the least, and its scoping can be somewhat confusing due to its arbitrariness.

Basically, I want to introduce an identifier binding as if it were done via `define-*` but without strictly using a `define-*` form in the immediate context.

As an example:

```scheme
(let ([exists? (my-out-proc 'input #out result))])
;; | ^^^^^^ value depends on whether it `exists?` or not
;; ^^^^^^^^^^^^ returns true or false
  (if exists? (do-something result) #false))

```

In this piece of code, I would like to introduce the `result` identifier as if it were defined normally, but obviously because the context of the surrounding call can be arbitrary (other than a `let`, say), I don't want to explicitly introduce a `define` because where would it go, practically speaking?

If you use this expression inside another procedure call, e.g.

```scheme
(another-proc (my-out-proc 'input #out result))
...
(do-something result)

```

I would expect the `result` to still work, which of course becomes tricky once you have to start traversing which contexts it belongs to and so on, in an ad hoc manner.

I have stumbled more or less vaguely onto this [thread](https://racket.discourse.group/t/how-to-use-the-binding-space/1717), but honestly, it is so unfamiliar that I am not sure how to take the information and run with it.

---

<div class="post-metadata">

**Author:** ![michaelballantyne](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/michaelballantyne/32/252_2.png) [@michaelballantyne](https://racket.discourse.group/u/michaelballantyne)\
**Post date:** [July 18, 2025, 2:59pm UTC](https://racket.discourse.group/t/how-to-introduce-new-bindings-without-using-define/3856/2 "2025-07-18T14:59:35Z")

</div>

I think I understand the behavior you'd like to implement, but unfortunately I think that this would be quite difficult to achieve with Racket's expansion process.

Generally a macro cannot control the expansion of syntax surrounding it, so `my-out-proc` wouldn't have a way of rewriting the surrounding code to insert the definitions. `syntax-local-lift-expression` is one way to lift a definition into the surrounding context, but it generates a fresh name for the definition. So that operation is useful to lift the computation of an expression in order to avoid re-computing it, but it is not useful for making the definition of a name visible in a wider scope.

In order to transform the surrounding context, you would need to have a macro call around it. So let's imagine your sample code is wrapped with another macro you define, say `with-out-parameters`:

```scheme
(with-out-parameters
  (let ([exists? (my-out-proc 'input #out result))])
    (if exists? (do-something result) #false)))

```

The `with-out-parameters` macro could potentially use `local-expand` to partially expand the syntax within, transform it, and then continue expansion. You could in principle have a `#lang racket/out` that is just like Racket, but replaces `#%module-begin` with such a `with-out-parameters` that knows how to use `local-expand` and traverse the entire Racket core syntax in order to perform the transformation. The implementations of `#%printing-module-begin` or `splicing-syntax-parameterize` could provide some hints here. This is a quite complicated kind of macro! I'm not totally sure it would work for your objective.

The above assumes that you want out-parameters to work with general, macro-extensible Racket code. The problem is of course much simpler if instead you want to make your own restricted, non-extensible syntax with basic features like let, function application, etc where you apply this transformation.

---

<div class="post-metadata">

**Author:** ![bakgatviooldoos](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bakgatviooldoos/32/1381_2.png) [@bakgatviooldoos](https://racket.discourse.group/u/bakgatviooldoos)\
**Post date:** [July 18, 2025, 5:13pm UTC](https://racket.discourse.group/t/how-to-introduce-new-bindings-without-using-define/3856/3 "2025-07-18T17:13:16Z")

</div>

Hi, @michaelballantyne. Interesting, thank you for the thoughtful reply, the references to `splicing-syntax-parameterize`, and `#%printing-module-begin` are good--the former never even crossed my mind, and the latter I am unfamiliar with.

A similar thought crossed my mind, specifically regarding creating either:

- Anchors, like you do for namespaces when `eval`-ing code, in the sense that you create a free-standing link to an "out-context" which can then be used as needed, or
- As you mention, a scoping mechanism which achieves the desired effect explicitly, like with `parameterize-*` and friends, by wrapping the context.

I am willing to admit that perhaps these two cases are essentially the same, only slightly different in their usage, if you think about defining a parameter and then using it later to create a separate context.

I would have preferred it to be "plug-n-play" and work cleanly with mostly arbitrary code, but perhaps I am saddling up a horse that should be parked in the field a bit.

I am reminded of the `define-new-top` macro in @Eutro's `cadnr` sources.

Let's say you make a macro, `(define-out-parameter-context ...)` that allows you declare which forms are out-parameter contexts. The scoping mechanism itself is simple, since we are already leaning on `syntax-parameterize` and `parameterize`.

It would only need a way to tag certain expressions in the body of the definition as these contexts. In other words, segregate them from one another.

It sort of works that way already, since I overrode the `define` and `lambda` syntaxes to detect out-parameters in their formals and accordingly wrap the body.

This avoids one having to be prescient about usage at the cost of some "boilerplate" (it's `C#` all over again 😂).

Much obliged.
