# Are temporary parameters a silly idea?

**URL:** <https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420>\
**Category:** Questions & Answers\
**Created:** [December 15, 2024, 11:34am UTC](https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420 "2024-12-15T11:34:44Z")\
**Posts on this page:** 4\
**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:** [December 15, 2024, 11:34am UTC](https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420/1 "2024-12-15T11:34:44Z")

</div>

Hi, Racket Discourse.

I am experimenting with ways of exposing mutable variables to programmers within the body of procedures which themselves build-up objects (by which I am implying, that it is difficult to percolate the two sets of results up the nested calls without introducing a lot of machinery just for that).

One idea I had, was to use temporary parameters; surprisingly, I did not realize (although it is obvious in hindsight) one could create and parameterize parameters on the fly.

Take this macro, for example:

```scheme
(define-syntax (let-parameters stx)
  (syntax-parse stx
    [(_ ([name:id init:expr] ...) body:expr ...)
     #'(let ([name (make-parameter #false)] ...)
         (parameterize ([name init] ...)
           body ...))]))

```

Which then might be used something like this:

```scheme
(define page
  '(html
    (body (p ([class "baz"])
             "foo" "bat")
          (p "bar" (br) "qux"))

    (br)

    (body (p ([class "zab"]
              [id "1"])
             "foo" "tab")
          (p "rab" (br) "xuq"))))

(let-parameters ([tag-indexes (hash)])
  (values
   (with-xe '(html body . p)
     (lambda (tag p-body)
       (with-parameters (tag-indexes)
         (define index (hash-count tag-indexes))
         (hash-set tag-indexes index tag))
       (println (cons tag p-body))
       p-body)
     page)
   {tag-indexes}))

; '(p "foo" "bat")
; '(p "bar" (br) "qux")
; '(p "foo" "tab")
; '(p "rab" (br) "xuq")
;=> '(html (body (p ((class "baz")) "foo" "bat") (p "bar" (br) "qux")) (br) (body (p ((class "zab") (id "1")) "foo" "tab") (p "rab" (br) "xuq")))
;=> '#hash((0 . p) (1 . p) (2 . p) (3 . p))

```

The `with-parameters` basically desugars to:

```scheme
{parameter ... {parameter} ...}

```

assigning the results of the body to the parameters without needing to unwrap them.

Now, this is very cute, but is this _silly_?

Technically, all I am doing is avoiding the `set!`--which could be wrapped in similar machinery for the same effect. Moreover, this _allows_ "spooky action at a distance", since if the parameters escape the immediate body of the bindings, they could be used to change the "locally global" values. Which could be cool, but also terrible.

Have you ever used temporary parameters before?

---

<div class="post-metadata">

**Author:** ![usao](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/usao/32/1375_2.png) [@usao](https://racket.discourse.group/u/usao)\
**Post date:** [December 17, 2024, 7:58am UTC](https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420/2 "2024-12-17T07:58:12Z")

</div>

I don’t think parameters are _really_ needed if all you want is a … well, mutable variable, hidden behind the `(case-> (-> R) (R -> Void))` interface. At least the example looks like it really wants a simple mutable variable as opposed to parameter. Parameters are useful when you want to dynamically (in the sense of “dynamic extent/context”) change their values (they are like “dynamic bindings” in Common Lisp, in this respect), but the example doesn’t rely on this dynamic behavior at all (no significant use of `parameterize`). It’s very difficult to imagine how “temporary parameters” can be useful—if you just want to communicate values to a function, you can always pass them as arguments! (Or use boxes, if you love states :P) So I think I’ve personally never used parameters this way.

---

<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:** [December 17, 2024, 4:57pm UTC](https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420/3 "2024-12-17T16:57:32Z")

</div>

Indeed, it is entirely overkill.

Thank you for mentioning the `case->` contract mechanism. It is the second time in a very short amount of time I have seen the identifier, which is always an interesting phenomenon.

I was flirting with the idea of exposing the XML-element (`xexpr`) attributes as such a temporary parameter, since it is _kind of_ a parameterization of the element's tag, and it would allow one to hold on to parameterizations nestedly, unlike using a `current-attributes` parameter which would hide shallower attributes along the path. But ultimately, it doesn't make sense because it can be achieved more easily otherwise.

I am glad I am aware of the idea now, though.

As you rightly observe, I am currently playing around with just using the `lambda`s as looping mechanisms, kind of like one would with `(let loop ...)`, with the optional arguments functioning as looping variables.

It isn't bad, but it feels brittle enough that I suspect there is a more elegant underlying principle yet to appear. Maybe what is necessary, is some form of `#:result` argument, like in a `for/fold` form. Time will tell.

```scheme
(define page
  '(html
    (body (p (p (a 3 2 1) (b 5) (c 3))
             (p (d 3 2 1) (e 3 1) (f 3))))
    
    (body (p (p (a 3) (b 5) (c 3))
             (p (d 1 2 3) (e) (f 3))))))

(define-values (_ counts contents)
  (with-xe '(html body p p)
    (lambda (tag attrs p.* [counts null] [contents* null])
      (define-values (p.*′ count contents)
        (with-xe '(*)
          (lambda (tag attrs p.*.* [count 0] [content null])
            (values
             attrs
             p.*.*
             (+ count (if (not p.*.*) 0 1))
             (if (not p.*.*) content (cons p.*.* content))))
          p.*))
      (values attrs p.*′ (cons count counts) (cons (reverse contents) contents*)))
    page))

(match-define
  `((,html.body.p_0.p_0-counts
     ,html.body.p_0.p_1-counts)
    
    (,html.body.p_1.p_0-counts
     ,html.body.p_1.p_1-counts))
  counts)

html.body.p_0.p_0-counts
html.body.p_0.p_1-counts

html.body.p_1.p_0-counts
html.body.p_1.p_1-counts

#|
;=>
'(3 1 1)
'(3 2 1)
'(1 1 1)
'(3 0 1)
|#

(match-define
  `((,html.body.p_0.p_0-contents
     ,html.body.p_0.p_1-contents)

    (,html.body.p_1.p_0-contents
     ,html.body.p_1.p_1-contents))
  contents)

html.body.p_0.p_0-contents
html.body.p_0.p_1-contents

html.body.p_1.p_0-contents
html.body.p_1.p_1-contents

#|
'((3 2 1) (5) (3))
'((3 2 1) (3 1) (3))
'((3) (5) (3))
'((1 2 3) () (3))
|#

```

* * *

Edit: Thinking about it some more, maybe the shadowed parameters aren't a bad compromise, if it simplifies the function signatures.

Then, using a _final_ #false result which is passed to the `app` procedure among the `with-xe` procedure's arguments, one can signal to the programmer that the results have been exhausted, providing a space to do clean-up of the accumulator arguments.

```scheme
(with-xe '(p p *)
  (lambda (p.p.*.* [count 0])
    (if (not p.p.*.*)
        (values
         p.p.*.* (format "counted ~a things in a ~a-tag" count {<xel>}))
        (values
         p.p.*.* (+ count 1))))
  '(p
    (p
     (p ([class "upper"])
        (g "G for short")
        (g "Gee, normally"))
     (p ([class "lower"])
        (h "h for short")
        (g "... uh")
        (g "nevermind"))
     (br)
     (div))))

#|
'(p (p (p ((class "upper")) (g "G for short") (g "Gee, normally")) (p ((class "lower")) (h "h for short") (g "... uh") (g "nevermind")) (br) (div)))

'(("counted 2 things in a p-tag"
   "counted 3 things in a p-tag"
   "counted 0 things in a br-tag"
   "counted 0 things in a div-tag"))
|#

```

Programming is awesome.

Now just to come up with a way of flattening them nicely, or, accessing the nested results more seamlessly.

P.S. If anyone has not yet tried the [debugger](https://docs.racket-lang.org/drracket/buttons.html#%28idx._%28gentag._7._%28lib._scribblings%2Fdrracket%2Fdrracket..scrbl%29%29%29) in `DrRacket`, I would recommend giving it a go. I did for the first time today, and it helped me sus out a bug when coalescing the `values` of the accumulator arguments in the code above.

---

<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, 11:09pm UTC](https://racket.discourse.group/t/are-temporary-parameters-a-silly-idea/3420/4 "2025-07-18T23:09:06Z")

</div>

Although not strictly speaking temporary (maybe "inlined" would be a better term?), the use-case for on-demand parameters does come up (in my framing thereof) when trying to implement out-parameters, as in my [Out-parameters in Racket](https://racket.discourse.group/t/out-parameters-in-racket/3855) post. I just thought this was a relationship worth mentioning.
