Don't think that would work out, because there are simply too many things that generate functions (think ADAPT, SPECIALIZE, AUGMENT, CHAIN, METHOD...) to give them all different names.
The fundamental issue I'm trying to address is that it's important to be able to write stuff like:
x: (some arbitrary expression)
switch type of x [...]
if x [...]
That should be reasonable and safe (allowing for giving errors with correct locality on things like voids or unset states). If it's not safe, then trying to write any kind of "interesting" code becomes a fairly harrowing experience.
I find it particularly harrowing because of the awareness that what "looks good" might work for a simple example, but won't be correct down the line. So you wind up in weird justifications of leaving some parts "clean-but-wrong"--in the hopes that situations won't actually arise in practice that break it.
You can imagine people fighting over this in a particular bit of code. (e.g. someone in Rebol2 who is GET-WORD! obsessed finding a bug and then going through turning every reference into a GET-WORD!. The original author says "...but it's not needed in all those places" and they say "...well what about the bug, how many more of those are there? how do you know it won't become an issue when code reorganizes in the future?")
Pushing the burden to annotating the "live" function word assignments may seem ugly to the uninitiated, but it can solve this problem near-perfectly. I feel like one easy-to-type character that you don't have to stretch for is reasonable. It would help people get their bearings.
>> foo: x -> [print ["X is" x]]
>> /foo 10
X is 10
>> foo
== #[action! {foo} [x]]
>> /foo: x -> [print ["X is" x]]
>> foo 10
X is 10
To see why it's important you only need to think of one little step of abstraction away:
abstraction: func [] [
return does [print "Boo!"]
]
Once you start thinking about that, you don't take the annotation of the live reference for granted.
This really offers a way of thinking about it where there's a "default" (not executing without the slash) and then you can twist it by convention... a bit like introducing quoting parameter conventions to someone who learns a normal function parameter first.
Leading-Slash-Executes Is A Better Story (and Better Look)
This improves things like action combinators in UPARSE...which were trailing slash before:
>> parse [1] [negate/ integer!]
== -1
>> parse [1 2] [add/ integer! integer!]
== 3
...but look nicer with leading-slash, that kind of "puts the function and its arguments on the same side of the divider" (vs. walling off the function from its arguments):
>> parse [1] [/negate integer!]
== -1
>> parse [1 2] [/add integer! integer!]
== 3
I think tying this in with the "LIB/APPEND executes, LIB.APPEND doesn't" puts together a story that holds together for solving a lot of historically "harrowing" problems.
Minor Gripe: Refinement Notation Inconsistency
When you write a function spec and it says:
sorter: func [series [any-series!] /comparator [action!]] [...]
The combination of the slash with the fact that it's an action might suggest that it would run by default. That wouldn't be the meaning here.
But that's dialects for you. :-/ Here the slash is a callback to being a component of a function invocation, nothing to do with actually being a function.
Would This Be Overrideable?
Redbol would override it...but it would be done at the level of an actually-hooked evaluator that would run the ACTION!s regardless of isotopic status. In order to make Redbol functions callable by non-Redbol code, all SET-WORD! would have to turn
There'd clearly need to be some way to say SET-TRIGGERED-ACTION on a word, vs. making people write a function that ran do compose [/(word): (action)]
. So a FUNC-like construct would be possible using something like that. But if function isotopes can be relegated to an implementation detail and never created by expressions in practice, I'll reiterate that would be a substantial benefit...