Operator meaning "complete fully"...what is that?

I'd like something to help notice when an operation did not consume all its input.

Something along the lines of:

>> (completely-consume add 1 2)
== 3

>> (completely-consume add 1 2 3)
** Error: ADD did not completely consume args, leftover is [3]

I've wanted such a thing for a while, but it's especially pressing now. The API is getting more solid, so it's tempting to use it for doing things like calling from C the "System helpers written in Rebol"... a.k.a. what's in SYS. But the existing mechanisms for doing that have a "no leftovers" flag, something like:

DECLARE_LOCAL (result);
bool leftovers = false;
if (Apply_Throws(result, add_function, leftovers, arg1, arg2, arg3, rebEND))
    fail (Error_No_Catch_For_Throw(result));

I don't want such flags in the API. It seems useful to have a generic operator.

In the past, I've tried "double-bar", because it would allow for a more forceful kind of separation than just a single bar. Unfortunately, it has to be prefix...as there's no way at present in usermode to know the left hand side completed exactly one expression:

>> (x: add 1 2 "foo" | print x)
3

>> (|| x: add 1 2 "foo" || print x)
** Error: extra stuff (["foo"])

I'm wondering if the idea of || is sound, but just needs a new piece of machinery. Because this seems superior for the intent:

>> (x: add 1 2 "foo" || print x)
** Error: extra stuff ["foo"]

>> (x: add 1 2 || "foo" print x)
** Error: extra stuff [print x]

>> (x: add 1 2 || print x "foo")
** Error: extra stuff ["foo"]

>> (x: add 1 2 || print x)
3

So what do people think? Better ideas for the prefix operator? Time for a new parameter marker, e.g. <solo>?

This might be something that could be a use for the debated "variadic left enfix". Maybe it could be possible to take a value from the left, and then tell you if you were at the "tail" or not...while not actually being able to give you more than one value? They're lost to history, but it wouldn't be hard to keep just a bit's worth of memory for this purpose.

As an API client it would be up to you to put it at the beginning or the end (or both?)

Value *v = rebValue("||", whatever, ..., ...);

Value *v = rebValue("whatever", ..., ..., "||");

We have this thing now. It's called APPLY.

>> apply :add [10 20 1020]
** Error: Too many values in APPLY argument block (see /RELAX)

You have to explicitly tell it to /RELAX if you want it to ignore extra parameters.

>> apply/relax :add [10 20 1020]
== 30

With the infix quoting version, you can do this succinctly.

>> add // [10 20 1020]
** Error: Too many values in APPLY argument block (see /RELAX)

:+1:

Stupid (?) Idea of the Moment

Make triple slash the relaxed form of APPLY

>> add /// [10 20 1020]
== 30

We don't technically need rebApply() and rebApplyRelax() (or rebApplyRelaxed()?) in the API, but it could save on constructing a block for the apply parameters and give a little bit more efficiency to not need to look up the APPLY operator.

 rebValue("apply", some_func, "[", arg1, arg2, arg3, "]");

 rebApply(some_func, arg1, arg2, arg3);

It's probably worth it--we'll be needing all the performance tricks we can get.

We could soft quote the first slot so you could use WORD! or TUPLE! or CHAIN! or PATH! there.

 rebApply("lib/append:dup", arg1, arg2, arg3);
1 Like