Rebmu is a laboratory for cool dialecting tricks... one of those tricks I imagined was to see just how much mileage we could get for defining functions with a single character primitive that has no holds barred...
F
The idea is to make F use tricks with quoting and variadics in order to eliminate the need for certain boilerplates. For example, it can quote its first argument, allowing a WORD! without a block around it to use as a spec for an arity-1 function:
f x [...] ; Would act the same as f [x] [...]
Bear in mind that in when "mushed" in Rebmu, that would be
fX[...]
acting as f x [...] because the case transition signals when a new token begins.And a quick reminder of the game for anyone who has forgotten: if a run of transitions starts with a capital letter instead of a lowercase one, the first acts as a SET-WORD!. So
Fx[...]
would act as f: x [...]
Being able to avoid the brackets of a spec block and quoting a WORD! is trick number one. But that's old hat, and even lambda uses that. x -> [...]
So let's get crazier.
Automatic Naming Of Multiple Arguments
The first generation of Rebmu introduced things like B-FUNCTIONS or C-FUNCTIONS. The concept was that if you asked for such a function, you'd actually get arguments for a series of letters.
fc [...] ; acts like `f [a b c] [...]`
fd [...] ; acts like `f [a b c d] [...]
This idea for taking letters at the start of the alphabet was complemented by functions that counted letters backwards. This way when you were declaring functions inside functions, the names would be less likely to collide:
fx [...] ; acts like `f [z y x] [...]`
fw [...] ; acts like `f [z y x w] [...]`
Sacrificing two letter names starting with F for this is probably too much, so you might imagine this coming from ISSUE! usage:
f #c [...] ; giving `f [a b c] [...]`
But at best that would mush as f#c[...]
, at which point you're using up two characters. So if the word-named feature were variadic you'd break even on two characters:
f a b [...] ; if this meant `f [a b] [...]` you could write as `fAb[...]`
f m x [...] ; and you could pick any characters you wanted, `fMx[...]`
So the idea would only make sense if there was another meaning for things like fMx
, which leads us to...
Removing The Need For Blocks In The Body
If we look aside from the spec for a moment, we can ask how quoting might be used in the body. For instance, what if instead of writing:
f [args] [case [...]]
You could just write:
f [args] case [...]
That points to an alternate potential meaning for something like fMx[...] as f [m] [x [...]] instead of f [m x] [...], and is probably a more potent idea.
This behavior when the body isn't a block would essentially flip F into a mode of being a spin on POINTFREE...which would try to consume "one whole expression's worth" of body code based on what it could figure out from the material it variadically quoted.
Such a feature assumes that generated bodies are the unusual case you would use GROUP!s to escape. So while in plain Ren-C it would run the reverse once on function creation and make a function that prints:
func [] reverse ["Hello" print] ; e.g. `func [] [print "Hello"]`
We'd see a different effect, making a function that returned a BLOCK!, calling reverse each time:
f [] reverse ["Hello" print] ; e.g. `func [] [reverse ["Hello" print]]`
You'd thus need some kind of escaping mechanism like a GROUP! to get the "use code to generate a body" behavior:
f [] (reverse ["Hello" print])
I think it probably makes sense to have the generator that gets the single letter NOT be tailored to generating body blocks from code. The F would not be an alias for FUNCTION (obviously) but for FUNCTION-MU. So FN would be just one letter away for anyone who wanted the more conventional version.
The LET and Auto-Gathering Distinction for Locals
When you make an assignment to a SET-WORD! inside the body of a function to something that isn't a parameter, how is this interpreted? How do you designate a local variable vs. reaching outside into the enclosing binding environment?
We still don't have answers to this in the language proper. Which is frustrating.
But if there's anywhere that auto-gathering of SET-WORD!s as locals is useful as a feature, it's in Rebmu. So:
- Is it the default behavior for F?
- How do you turn it on or off?
I'll point out here that how characters are counted in code golf varies...but if all of unicode is allowed where unicode characters "cost" the same as ASCII, there are choices like dotted-F (ḟ) on the table. Some golfing languages go crazy with this. But as a general baseline, I think ASCII should be used and then have Unicode definitions as an extension.)
For now, I think the default should be to assume arguments are not local. It may be that defining locals is done with a separator like BAR!:
f[aB|cDe][...] ; acts as `f [a b <local> c d e] [...]`
[Your Brainstorm Here]
Feel free to throw out ideas for any combination.
For instance, what if the body of a function is a text:
foo: f [] "Some String"
It doesn't make a lot of sense for that to mean "evaluate to the string", because you could have just assigned the string to the variable directly:
foo: "Some String" ; shorter for same effect
This would suggest that maybe the body being a string means it should print that string. But if that's all it does, then why would it need a spec? So if F gets a string in the spec position it could consider that the end of the variadic definition, and make a function that prints that string.
>> h: f "Hello World"
>> h
Hello World
ISSUE! can print strings without spaces with one less delimiter, so there's that. But I kind of liked my idea above about auto-generating multiple parameter names. Then again, there's FILE! for an alternative: f %c [...]
So what if the spec is a TUPLE!, or a PATH!, or if the body is a SET-GROUP!?? What kinds of practical shortcuts can these take to get the maximum leverage out of F? Maybe if an INTEGER! is in the body position it assumes that means to loop that many times.
>> x: f y 3 [p y] ; let's say P is PRINT
>> x "test"
test
test
test
The concept of "pulling out the block" mentioned above could even cascade there, letting you write x: f y 3 p y which can mush as XfY 3 pY
There's a lot to explore here, and @razetime please let me know if this is making any sense or not....I've started on bringing Rebmu back to life and hopefully will have it in usable shape this week.