# hiiamboris's WITH

**URL:** <https://rebol.metaeducation.com/t/hiiamboriss-with/2138>\
**Category:** Dialects/DSLs\
**Created:** [January 30, 2024, 9:14pm UTC](https://rebol.metaeducation.com/t/hiiamboriss-with/2138 "2024-01-30T21:14:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![hostilefork](https://rebol.metaeducation.com/user_avatar/rebol.metaeducation.com/hostilefork/32/421_2.png) [@hostilefork](https://rebol.metaeducation.com/u/hostilefork)\
**Post date:** [January 30, 2024, 9:14pm UTC](https://rebol.metaeducation.com/t/hiiamboriss-with/2138/1 "2024-01-30T21:14:23Z")

</div>

I've mentioned that binding might be helped by a dialect, and it turns out there is some precedent in **[hiiamboris's WITH](https://codeberg.org/hiiamboris/red-common/src/branch/master/with.red)**:

> ### USAGE SUMMARY
> 
> ```
> with x [..] == bind [..] x
> with 'x [..] == bind [..] 'x
> with :fun [..] == bind [..] :fun
> with [:fun] [..] == bind [..] :fun
> with [x y 'z] [..] == bind bind bind [..] 'z y x
> with [x: 1 y: 2] [..] == bind [..] context [x: 1 y: 2]
> 
> ```
> 
> ### EXAMPLES
> 
> #### omit the path to an object, but work inside it's context:
> 
> ```
> do with face/parent/pane/1 [
> color: red
> text: mold color
> visible?: yes
> ]
> 
> if true with system/view/fonts [print [serif size]]
> 
> f: func [/- /+ /*] [ ;-- redefines important globals locally
> (do something with local flags)
> foreach x [set..] with system/words [
> (do something with global * + -)
> ]
> ]
> 
> ```
> 
> #### create static storage for functions where existing literal forms don't allow you to:
> 
> ```
> factorial: func [x] with [cache: make hash! [0 1]] [
> any [
> select/skip cache x 2
> put cache x x * factorial x - 1
> ]
> ]
> 
> ```
> 
> #### anonymize words used during initialization of the program:
> 
> ```
> first item in the block should be of set-word! type
> 
> do with [x: 1 y: 2] [
> z: x * y
> ... other code that uses x or y ...
> ]
> 
> ```
> 
> #### bind a block to multiple contexts at once (in the list order):
> 
> First item in the block should be of word!/get-word!, path!/get-path! or lit-word! type
> 
> 1. words and paths values are fetched, while lit-words are converted into words  
> get-words and get-paths should be used for function context, otherwise they get evaluated
> 
> 2. if resulting value is a context, block is bound to it  
> if resulting value is a word, block is bound to the context of this word
> 
> Thus, `with [c]` is equivalent to `with c`, while `with ['c]` - to `with 'c`.
> 
> ### WHY IS IT DESIGNED LIKE THIS?
> 
> 1. It does not evaluate
> 
> 2. It accepts blocks

---

<div class="post-metadata">

**Author:** ![hostilefork](https://rebol.metaeducation.com/user_avatar/rebol.metaeducation.com/hostilefork/32/421_2.png) [@hostilefork](https://rebol.metaeducation.com/u/hostilefork)\
**Post date:** [November 14, 2024, 4:28am UTC](https://rebol.metaeducation.com/t/hiiamboriss-with/2138/2 "2024-11-14T04:28:43Z")

</div>

So I think it's best to kill off the **`<static>`** annotation in function specs, replacing it with something like WITH.

```
accumulate: function [
    return: [integer!]
    num [integer!]
    <static> state (0)
][
    return state: state + num
]

```

transitioning to...

```
accumulate: function [
    return: [integer!]
    num [integer!]
] with {state: 0} [
    return state: state + num
]

```

It looks a little more awkward (maybe?).

But statics are a fairly rarely-used ability, and leveraging a generic part like WITH is just a better bet.

* * *

> [@](#):
>
> WHY IS IT DESIGNED LIKE THIS?
> 
> `with` does not evaluate the block, so:
> 
> - it can be used after `context`s, `if`s, `loop`s, `func`s, etc.
> 
> - it can be chained `with x with y ...`I've found that this makes code much more readable than it would be with `bind`.
> 
> Prefix it with `do` if you want immediate evaluation.

So Ren-C DO is for running whole scripts or code from any language (e.g. JavaScript and CSS instead of Rebol), requires a header on Rebol scripts, etc. It's not for evaluating blocks. You have to use EVAL (or unabbreviated EVALUATE).

So instead of **do with** you'd say **eval with**.

EVAL WITH would thus be similar to (but more powerful than) what has historically been known as USE.

```
x: 10 y: 20
use [x y] [ ; Redbol USE
    x: 100 y: 200
    print ["Inside the USE X and Y are" x y] ; 100 200
]
print ["Outside the USE X and Y are" x y] ; 10 20

```

There's not a lot of that in Ren-C. Instead it uses LET, which is generally preferable since it doesn't make you indent your code.

In the narrow cases where I would want to do this, I don't feel it would be that terrible to say:

```
x: 10 y: 20
eval with [x y] [ ; could be (with {x: y: ~})
    x: 100 y: 200
    print ["Inside the EVAL WITH X and Y are" x y] ; 100 200
]
print ["Outside the EVAL WITH X and Y are" x y] ; 10 20

```

Especially because you often could do the assignments right in place, as you can here:

```
x: 10 y: 20
eval with {x: 100, y: 200} [
    print ["Inside the EVAL WITH X and Y are" x y] ; 100 200
]
print ["Outside the EVAL WITH X and Y are" x y] ; 10 20

```

My concept for retaking the word USE is to import things into the current scope. So like WITH, but not requiring a level of indentation.

```
obj: {foo: 1000 bar: 2000}

use obj
print ["FOO is" foo "and BAR is" bar] ; 1000 2000

```

Among the many uses for such a thing would be bringing GATHER'd declarations inside a PARSE into scope:

```
if 1 < 2 [
    let filename: "demo.txt"
    use parse filename [gather [
        emit base: between <here> "."
        emit extension: thru <end>
    ]] else [
        fail "Not a file with an extension"
    ]
    print ["The base was" base] ; demo
    print ["The extension was" extension] ; txt
]
; base and extension would not be defined here!

```

## Is WITH the Right Word for WITH?

The thing that bothers me is that WITH is a very generic term, that seems to me to be a good refinement.

```
>> join:with "," tag! ["abc" "def" "ghi"]
== <abc,def,ghi>

```

This is really a bind-specific operation. And I wonder if perhaps, since it is going in the direction of dialecting, if it should be the BIND dialect itself?

```
accumulate: function [
    return: [integer!]
    num [integer!]
] bind {state: 0} [
    return state: state + num
]

```

In this model, BIND's first argument is the binding instructions, and the second argument is the block (or whatever) to bind.

This would kill the idea I had of the "arity-0 BIND", but that would just be a synonym for the **`$`** operator, and since there's a short operator for it the name of it doesn't have to be quite that short or critical.

**I think that it's probably best to say that this is what BIND is.** People can just learn that the second argument is the thing that gets bound.

---

<div class="post-metadata">

**Author:** ![hostilefork](https://rebol.metaeducation.com/user_avatar/rebol.metaeducation.com/hostilefork/32/421_2.png) [@hostilefork](https://rebol.metaeducation.com/u/hostilefork)\
**Post date:** [November 18, 2024, 9:29pm UTC](https://rebol.metaeducation.com/t/hiiamboriss-with/2138/3 "2024-11-18T21:29:06Z")

</div>

> [@hostilefork](#):
>
> ```plaintext
> with x [..] == bind [..] x
> with 'x [..] == bind [..] 'x
> with :fun [..] == bind [..] :fun
> with [:fun] [..] == bind [..] :fun
> with [x y 'z] [..] == bind bind bind [..] 'z y x
> with [x: 1 y: 2] [..] == bind [..] context [x: 1 y: 2]
> 
> ```

So I was wondering in the design of the WITH-like BIND what plain words should do, as opposed to `@word`.

One concept I had was that with plain words, BIND could serve the role of "old USE" and create new bindings. Then, an `@word` would mean that you wanted to bind to that particular word.

```
x: 10
y: 20
eval bind [@x y] [
   x: 100 ; overwrites X
   y: 200 ; would not overwrite as plain Y word made new variable
]

```

That would be making a distinction between words and `@word` that lines up with how FOR-EACH and others treat variables. It was chosen over `$word` due to the ability to pass the variable reference without a block:

```
iterate @var [...] ; the @ sticks, but $var makes a plain bound word

```

But BIND has a competing intent, which is when you want to bind to the thing the word points to.

```
foo: make object! [x: 10 y: 20]
bar: make object! [z: 30]

eval bind [@foo @bar] [ ; alternative intent of @
   assert [all [x = 10, y = 20]]
   assert [z = 30]
]

```

This is more like the PARSE meaning of @ which means "dereference this word".

Another way of doing that could be GROUP! evaluations:

```
eval bind [(foo) (bar)] [
   assert [all [x = 10, y = 20]]
   assert [z = 30]
]

```

It's worth pointing out that making new variables with BIND can be done easily another way, with FENCE!, so we could say:

```
x: 10
y: 20
eval bind [x {y: ~}] [; instead of [@x y]
   x: 100 ; overwrites X
   y: 200 ; would not overwrite as {Y: ~} made new variable
]

```

And I think giving a value to a new variable is probably more common than not wanting to, anyway.

That frees up the `@foo` to mean "what I intend to bind to is what you get by dereferencing this" intent.

So binding a single word means bind using the binding of that word.

```
block: [print ["The value of x is:" x]]

foo: func [x] [
    eval bind $x block
    eval bind [x] block
]

foo 10 ; would print the message with x as 10

```

**I can't necessarily prove it offhand, but I feel like having `bind [@x y]` mean something parallel to `for-each [@x y]` would be beneficial.**

That would indicate producing a new variable for Y, and reusing a binding for X.

This makes BIND able to function easily as a "LET that takes a block"

```
let x
x: 10

bind 'x [x: 10]

```

Something about pushing on these symmetries seems more important than giving you a way to dereference variables to implicate the objects they point to, that's briefer than a GROUP!.

(Honestly, multiple binds are probably not that common, and in fact you wouldn't get a lot of benefit out of it by saying **`bind [(obj1) (obj2)] ...`** as opposed to **`bind obj1 bind obj2 ...`** )

## The Binding Dialect Likely Needs More Features

This is sort of the tip of the iceberg in "meanings you might have for binding requests". So could be another way of saying you should dereference, as part of a broader idea of TAG!-instructions:

```
foo: make object! [x: 10 y: 20]
bar: make object! [z: 30]

eval bind [<in> foo <in> bar] [
   assert [all [x = 10, y = 20]]
   assert [z = 30]
]

```

So really we're talking about the needs of the most common form.

## Although...Ignoring The Binding Is Annoying

This has some consequence, for instance this would have the binding ignored and make a new variable:

```
 eval bind (bind obj 'x) code

```

While this would use the binding:

```
 eval bind (bind obj '@x) code

```

That would be true of FOR-EACH as well.

It does point out that if you want to bind to a single object's field and not all of it, then it would be helpful to have a notation for that.

```
eval bind [@obj.x] code

```

This could suggest that maybe undecorated means "evaluate this", such that these would be equivalent:

```
 bind foo [...]
 bind [foo] [...]

```

As opposed to the FOR-EACH equivalency, which would be:

```
 bind 'foo [...]
 bind [foo] [...]

```

I don't know. 😾 I guess I'll just have to try things and see what's most useful.

---

<div class="post-metadata">

**Author:** ![hostilefork](https://rebol.metaeducation.com/user_avatar/rebol.metaeducation.com/hostilefork/32/421_2.png) [@hostilefork](https://rebol.metaeducation.com/u/hostilefork)\
**Post date:** [November 27, 2025, 4:51am UTC](https://rebol.metaeducation.com/t/hiiamboriss-with/2138/4 "2025-11-27T04:51:38Z")

</div>

We currently don't have a user exposed datatype for a "Context stack". Someday we will, and there will be a CONTEXT! type. For now, `BINDING OF` is a very limited operation that only looks up words to tell you what specific place it gets found in... you don't have its entire context.

So today, if you want to grab a context from somewhere and apply it somewhere else, you use an operation called INSIDE. For instance, here it is making it possible to [automatically return a function's last evaluative product](https://rebol.metaeducation.com/t/making-func-variant-that-auto-returns-last-result/2124):

```plaintext
func: adapt lib.func/ [
    body: inside body compose '[
        return (as group! unbind body)
    ]
]

```

If you could extract a CONTEXT! you would be able to write this as:

```plaintext
func: adapt lib.func/ [
    body: bind (binding of body) compose '[
        return (as group! unbind body)
    ]
]

```

This would grab the context off the tip of the BODY block, and then apply it to the unbound product of the COMPOSE.

## Binding Dialect Concept: `^body` to "Use Tip Binding"

We could avoid having a separate INSIDE operator if BIND had a way of saying "use the tip".

I thought a ^META word might be nice in that dialect:

```plaintext
func: adapt lib.func/ [
    body: bind [^body] compose '[
        return (as group! unbind body)
    ]
]

```

It's something to consider, though a little disappointing that you need a BLOCK! to suppress the ^META evaluation. (We can't really make BIND's first argument literal the way FOR-EACH can in order to accomplish the [Literal Arguments as Proxy for Dialecting](https://rebol.metaeducation.com/t/literal-arguments-as-proxies-for-dialects/2489)... BIND wants to evaluate its arguments.)
