Rebmu's FUNQTION (FQ): Dialecting Function Definition Itself

After writing this I realized I had already written a post about this in 2020, but... here it is again, I guess! Maybe I said it better or worse this time?

(Note: FQ is pronounced EFF-QUEUE, say it carefully. :slight_smile:)

So in Rebmu, FN is a superset of FUNC (itself a synonym for FUNCTION).

It doesn't do anything terribly tricky because its arguments are both evaluative. So you can pass it specs and bodies that are variables. Here's a useless example of taking advantage of that with a spec in a variable:

; define a spec which takes two arguments
S[xY]   ; => s: [x y]

; define function A that adds X and Y.
AfnS[adXy]  ; => a: fn s [ad x y]
            ; => a: function s [add x y]

; define function M that multiplies X and Y
MfnS[mpXy]  ; => m: fn s [mp x y]
            ; => m: function s [multiply x y]

...but what might a Code-Golf-Dialected FUNQTION (FQ) Do, unbound by rote evaluation of its parameters? Let's use our imagination...

A Quoted Spec could permit Spec Compression

How about if you gave a WORD! that was a letter and a number, you'd get 3 args starting with that letter?

fqR3[adMPrSt]
; => fq r3 [ad mp r s t]
; => fn [r s t] [ad mp r s t]
; => function [r s t] [add multiply r s t]
; => function [r s t] [add (multiply r s) t]

That's a three character savings vs. having to express the block for [r s t] explicitly with a plain function:

fn[rSt][adMPrSt]

If you didn't include a number that might be a different memoization of what the arguments were, such as:

fqA[...] => fn [a] [...]
fqB[...] => fn [a b] [...]
fqC[...] => fn [a b c] [...]

fqX[...] => fn [z y x] [...]
fqY[...] => fn [z y] [...]
fqZ[...] => fn [z] [...]

The idea being that you need to sort of spread out your variable names in code golf, for instance when working with nested functions. From a tactical standpoint one might be served to throw in curveballs:

fqM[...] => fn [m j z] [...]

Though that lessens the readability/learnability. Anyway, what else...?

Variadically Quoted Bodies Could Circumvent Brackets

Let's say if it found a word in the slot where the body block would ordinarily be, it would treat that as a function that should be called.

To make it easier, let's just think about this un-Rebmu'd:

foo: func [x y z] [any [x y z]]

bar: funq [x y z] any [x y z]

If FUNQ is variadic and quoting its body slot, it could notice the body does not contain a block but a WORD!. Seeing that function is ANY, it could count the number of parameters ANY needs and pick them up from the callsite.

Such mechanics are within reach using today's FRAME!s, in fact they are used by things like POINTFREE...itself clearly useful in Rebmu.

What Else Might FQ do?

There's also things like GROUP!s, and fq(x)... could imply a completely different thing from fq[x]..., suggesting a mode switch in how the ensuing information is interpreted.

Or fqX(...) and fqX[...] could be completely different. What about strings? How might string interpolation fit into all of this?

ZfqC{Implicit printing of $a and $b and $c?}
; => z: fn [a b c] [print interpolate {Implicit print of $a and $b and $c}]

Maybe the implicit printing is different, like FP, and FQ with a string simply interpolates it.

Hopefully you get the drift. I'm talking about making Rebmu a powerhouse showcase of what Ren-C is driving at.

How can quoting, variadics, frames, interpolation, and all of that be applied to dialecting the act of function definition itself?

[insert your ideas here]

1 Like

I say not terribly tricky, but it's a little tricky.

It defines R and RT as local synonyms for the function's definitional return. Remember you can't globally say something like:

r: rt: :return

Because each function defines its own local RETURN function. So you have to basically augment the body during construction to get it bound to local definitions of RT and R:

fn: adapt :function [
    body: compose [
        let rt: :return
        let r: :rt 
        (as group! body)
    ]
]

Another twist I think would be smart would be that while normal parameters don't accept isotopes in plain functions...it could turn all normal parameters to be ^META and then un-meta them implicitly. Though that would affect the function's interface in ways that could lead to undesirable behaviors, so it might be better to put that in FQ (or something else, FX?)

There could also be some decisions that once an argument has been evaluated, it could treat invalid types differently:

X 1  ; => x: 1
Y 2  ; => y: 2
fnADxY[...] ; => fn ad x y [...]
            ; => function add x y [...]
            ; => function 3 [...]   ; could mean something vs. error?

But again: I don't know how far one wants to bend the "standard" definitions in the space where things are errors today. Worth being cautious about it.

1 Like