I've an idea that METHOD be a left-quoting version of FUNCTION...looking for a SET-WORD! or SET-PATH! on its left, and doing the assignment. The reason it would do this would be so that it had access to the word to read the binding out of it. That means it can look to see what fields were in that object, to solve a problem today with using FUNCTION in objects:
obj: make object! [
x: 10
f: function [] [
x: 10 ;-- would assign a local, since it's gathered
y: 20 ;-- would also assign a local
]
f2: function [<in> obj] [ ;-- today's workaround
x: 10 ;-- would assign obj/x
y: 10 ;-- would assign a local
]
m: method [] [
x: 10 ;-- would assign obj/x, since it's in binding of `m:`
y: 20 ;-- would assign a local, not in binding of `m:`
]
]
This seems like a pretty darn cool idea to me. The left quoting gives METHOD the missing piece of the binding it needs, so you don't need the workaround.
Cool as it is, it makes me wonder about the naming situation of having a PROCEDURE form. If method needed a parallel to that, what would you call a method that doesn't return a value? PROCMETHOD? :-/
This leads me to feel that maybe PROCEDURE's semantics (0-arity "return", kill any result that might drop out) should be something you can indicate in either kind of spec easily. And with the new VOID! type, we might have a coherent answer. So...
Is there any really good reason why f: function [return: <void>] [...]
couldn't be the signal to act like PROCEDURE does today, drop LEAVE, and just make RETURN not take an argument when that's that signature?
When definitional returns were being created, I was a bit worried about the idea that you might accidentally use a 0-arity RETURN with an argument. But we are starting to need a test for "residual" execution anyway, to catch cases where you've got non-invisible content following something that RETURNs or throws, else we can't catch the "dark corner" of return if x [...] else [y]
. So why not take a cue from C and just have a 0-arity RETURN in these cases?
People can still define PROCEDURE if they like it:
procedure: func [spec body] [
function compose [return: <void> (spec)]
compose [leave: :return (body)]
]
To me it seems worth it to standardize so that METHOD can get the feature of auto-suppressing the result falling out of the bottom without needing another name, and it keeps from having to come up with two names for everything that wants to be function-like but do that.
There's technically no real reason why having this ability for FUNCTION needs to affect PROCEDURE. It just may be more of a smooth transition to using METHOD to not teach people that a different action generator is how you get no-result. Also, we could still say that return: <void>
gives you a LEAVE instead of an arity-0 return if we wanted to. It's perhaps no more of a non-sequitur than it was with PROCEDURE. That's a separate decision... anyone have an opinion?