In practice, it's way too easy to mix up obj.field
and obj/field
. And it's a very frustrating bug if you thought you were running a function but it just evaluates to the function and keeps going. So I think obj.field
being an error on an action is important
It doesn't get any less likely to make the mistake when you throw in a leading or terminal slash. So I think that /xxx
for any XXX not running a function causes more harm than good. And similarly, knowing that xxx/
will give you an action as-is has too much value as a guarantee.
I'm finding that I really like the terminal slash to mean both "it's a function" and "don't run it".
apd2: specialize append/ [
dup: 2
]
In the new model, slashes are tied to function mechanics. And having it in that position helps throw up a barrier that says "nope, the next thing is not an argument.
And I like being able to specialize right from a chain:
>> apd: append:dup/
>> apd [a b c] [d e] 2]
== [a b c [d e] [d e]]
...BUT...
In practice, the "I don't know if it's an action or not" does come up pretty often, and I think having a different syntax would be nice.
I Think We Should "Use The Parts"
For instance, there was always a question of if GET-WORD! should allow you to get unset variables... I mentioned above how I dislike this conflation:
red>> type? :append ; you might have used GET-WORD! to get as-is action
== action!
red>> type? :asdfasdf ; but you would get as-is UNSET!s too :-(
== unset!
So at least there, we could do better with:
abc/ ; get what's definitely an action antiform as-is
abc/~ ; get as-is if action, but nothings/tripwires/holes ok
/abc: ... ; assign what is definitely an action
~/abc: ... ; assign what could be an action or vacancy
abc/~: ... ; maybe same, but doesn't look as good imo
That's rather communicative, and avoids the frustrating conflation. You can get some nice behaviors there, e.g. the following need has come up in practice several times:
~/foo: other/~ ; copies what may be antiform action or unset OTHER
And it's not throwing out anything, e.g. if you can write negate/multiply/
and that's some sort of function composition, you aren't at risk of multiply/~
taking away the ability to compose with a function called ~
because that's a blank quasiform and it can't be assigned to name a function.
So the question turning around in my head here is: is there some syntax jumble of this form which could meaningfully communicate "action-or-plain-value" for purposes of setting and getting.
At first I thought maybe terminal dot on a tuple would do this. But it's very subtle. Also, the meaning for leading dot as select member out of "current object" is going ahead, and that would put a lot of asymmetry on the trailing dot meaning.
If this would support anything, it would be terminal dot plus ~ for "vacancy okay on non-action".
abc.def ; get non-action as-is
abc.def.~ ; get non-action as-is, vacancy okay
But here we have the issue that you can legitimately pick ~
out of things, so you're losing a capability.
All this makes it feel more like it's better to diminish the constraint slash than try to augment the ability of dot.
There's #...it can't be reassigned
abc/ ; get what's definitely an action antiform as-is
abc/# ; get as-is if action, but other values ok
/abc: ... ; assign what is definitely an action
#/abc: ... ; assign what could be an action or other value
Oh, oops. /
is valid in "ISSUECHAR!" literals at this time, so #/abc:
doesn't put # at the head of a path, it makes an issue with a slash in it.
But that is changeable. You have to put some characters in quotes, e.g. #)
, is not a parentheses character... you have to do #")"
otherwise (#)
couldn't be a space character literal in a GROUP!. Slash may just be added to the exceptions, so #"/"
in order to allow #
in paths. This is certainly a motivating case.
I definitely think there is value added by distinguishing this, and letting plain slash in the most common case convey "I know this is an action".