Oldes / Rebol-wishes

Repository for keeping Rebol related wishes out of issues
0 stars 0 forks source link

LET function #51

Open Siskin-Bot opened 4 years ago

Siskin-Bot commented 4 years ago

Submitted by: BrianH

LET would create a new selfless context with a given set of words and values, BIND/copy a body of code to that context, and DO the block. This is the minimal context-creating mezzanine control function of the DO dialect - even USE could call it. LET is so basic it would likely be added to the sys context.

The name LET is best for 3 reasons:

This function would solve half of Oldes/Rebol-issues#539 for REBOL-source control functions - the other half would require a dynamic return throw: option, or preferably definitional return. This requires and uses SELFLESS (#1758). This would likely be done instead of BIND-TO-NEW (#1757).

From a conversation between Ladislav and me.

; The source
let: func [
    "Does the body in a context of the words, initialized to the values."
    word [any-word! block!] "Word or block of words"
    value [any-type!] "Value or block of values"
    body [block!] "Block to evaluate"
    /any "Allows setting words to any value, including unset"
][
    do bind/copy body apply :selfless [word /set :value any]
]

; Equivalent mezzanine source
let: funct [
    "Does the body in a context of the words, initialized to the values."
    word [any-word! block!] "Word or block of words"
    value [any-type!] "Value or block of values"
    body [block!] "Block to evaluate"
    /any "Allows setting words to any value, including unset"
][
    either any-word? :word [w: :word][
        if empty? word [return do body] ; shortcut return
        unless any-word? w: first word [
            cause-error 'script 'expect-arg reduce ['let 'word type? w]
        ]
    ]
    w: first foreach (to word! :w) [0] compose/deep [[(:w)]]
    word: bind/copy/new :word w
    apply :set [word :value any] ; will trigger error if any non-words
    do bind/copy block w
]

Imported from: CureCode [ Version: alpha 110 Type: Wish Platform: All Category: Mezzanine Reproduce: Always Fixed-in:none ] Imported from: https://github.com/rebol/rebol-issues/issues/1759

Comments:

Rebolbot commented on Nov 12, 2010:

Submitted by: abolka

Yes, please!

Note that only the suggested implementation requires and uses SELFLESS. As much as I'd like to see SELFLESS added as well, it's important to note that an alternative implementation of LET could be done along the lines of BIND-TO-NEW in Oldes/Rebol-issues#1757. So even if SELFLESS gets rejected, that's not in and of itself a reason to also reject LET.


Rebolbot commented on Nov 12, 2010:

Submitted by: BrianH

SELFLESS is more important than LET. If LET and BIND-TO-NEW are rejected that isn't a big deal, compared to adding SELFLESS. Nonetheless, having mezzanine equivalent source here will help illustrate the importance of SELFLESS.

Added such source. This includes the not /any check, since FOREACH isn't picky about such things. That little call to DO there means that I can't use the :return hack, and instead have to COPY/part the relevant portion of the values block in order to make sure the loop doesn't overrun.

The fully mezzanine version of this function would not be able to be used in other mezzanine code - it blows the budget for both complexity and overhead. We really need SELFLESS.


Rebolbot commented on Nov 12, 2010:

Submitted by: maxim

+1

when I saw this ticket it occured to me... shoudn't this have been the very first function evaluator?

then it occurred to me how important SELFLESS is.


Rebolbot commented on Nov 12, 2010:

Submitted by: Ladislav


Rebolbot commented on Nov 13, 2010:

Submitted by: BrianH

"LET yields a result that is wanted ..."

more often in a lot of code, but not always.

"LET will be more popular than CONTEXT."

Probably so, because of the "more often" part. Agreed on the rest.

Rewrote the mezzanine version using a technique that Ladislav came up with that reduces the overhead of the FOREACH workaround code. The [0] is there instead of [#[unset!]] because serialized syntax gets messed up by the code that builds the mezzanine source - the word gets SET later anyways. The explicit CAUSE-ERROR is to make the the error happen before we get too much overhead. We can't avoid the overhead of BIND/copy of word without a native SELFLESS function, but it shouldn't be too bad in practice.

This version could be used as a mezzanine as-is, though it would still be too much overhead for use in other low-level mezzanine code. We could still benefit from having this in native, or basing it on a native SELFLESS/set function. SELFLESS could be written as mezzanine if based on a native LET, but it would still have the problems with empty contexts that other mezzanine implementations of it have.


Rebolbot commented on Nov 14, 2010:

Submitted by: BrianH

Me: "SELFLESS is more important than LET". Not anymore. With the rewrites and above reasons LET is more important now, though it should be native.

See this http://www.rebol.net/r3blogs/0350.html and http://www.rebol.net/cgi-bin/r3blog.r?view=0350#comments for what we should do instead of SELFLESS.


Rebolbot commented on Nov 14, 2010:

Submitted by: BrianH

We want /any because allowing #[unset!] by default is a bad idea. The whole point of #[unset!] is to trigger errors - if we didn't want that, we could just use #[none]. It's the same reason that SET has /any. FOREACH allows #[unset!] because of better error locality, the same as EXTRACT (#1540); it lets you get a better idea of exactly where in the data the unset value is, so it is easier to track down the (possible) error that put it there.


Rebolbot added the Type.wish on Jan 12, 2016