Weird Little Function: STEAL a Variable's Prior Value

I don't know if it has the best name (suggestions?), but it's kind of interesting...

>> x: 304
== 304

>> steal x: 1000 + 20
== 304

>> x
== 1020

I wrote it as a variadic function for some reason (as a test, maybe?) but you could write it in Redbol. You could even use their lame ALSO.

steal: func [
    {Red version}
    'var [set-word! set-path!]
    value [any-type!]
][
    also get var set var value
]

The Ren-C version of that reads a lot better:

steal: lambda [
    {Ren-C version}
    'var [set-word! set-path!]
    value [any-value!]
][
    get var
    elide set var value
]

It naturally has the benefit of letting you break things across lines. I feel like it's better to point out "this is the thing being erased". And of course the mechanic is far more general.

I definitely like ANY-VALUE! better than ANY-TYPE!.

Anyway, I'm sure I've seen places I could have used it if I thought of it. I'll keep my eyes open.

2 Likes

I just found one in the %prot-http.r code, which I found while reviewing blank uses:

; The port data has been accrued for the client and can be given back
; directly, not as a copy.  If the port data is BLANK!, this returns NULL.
;
return (opt port.data, elide port.data: _)

Not only does that show a good example of "we shouldn't have to be converting between blanks and nulls, just use NULL". But it's an opportunity to steal:

return steal port.data: _

Ah, no. It was to be able to work with constructs that do backwards quoting:

steal x: default [20]

If STEAL consumes the X:, then DEFAULT won't see it.

Hence it peeks variadically long enough to see X: but does not consume it. Then it does one unit of evaluation (to run the x: default [20]) but keeps itself on the stack. This way it can return the original value.

2 Likes