Parameter Order in Rebol

With the advent of Point-Free expression, things that were wordy using SPECIALIZE are now succinct. You don't have to name the parameters...which saves typing and also keeps you from having to look it up:

next: specialize 'skip [offset: 1]
;
; ...becomes
;
next: (=> skip _ 1)

Though that placeholder is a little bit unsatisfying. Which means one starts looking at questions like "in Rebol, why isn't the offset to skip by first". In the narrow case of this specialization, it would make it a bit briefer and seem more natural...

next: (=> skip 1)

And to play devil's advocate, if Rebol is to be English-inspired instead of traditional OOP inspired...wouldn't you say:

"Skip 10 pages ahead"

Instead of the more awkward:

"Skip pages ahead by 10"

It's almost like the underscore in the partial specialization is playing the role of "by". But, anyway--is there some kind of universal rule to guide such decisions?

Most-or-Least Important Thing First

Since this looks very Haskell-y, here's a good summary paragraph from a StackOverflow answer on why Haskell users would favor (=> skip 1) to (=> skip _ 1):

"It's common practice in Haskell to order function parameters so that parameters which "configure" an operation come first, and the "main thing being operated on" comes last. This is often counter intuitive coming from other languages, since it tends to mean you end up passing the "least important" information first. It's especially jarring coming from OO where the "main" argument is usually the object on which the method is being invoked, occurring so early in in the call that it's out of the parameter list entirely!"

One thing about the least important parameter is it is often briefer to express. Consider the example we hit with DELIMIT when the data to act on was first:

delimit [
    "here" "is" "my"
    long block of code stuff
    "and we go on for a while"
] ","

By the time you get to the comma, you might have forgotten what you are doing. It seems it's pretty rare for the thing you're delimiting with to be coming from a long and complex expression, while the thing you're operating on may well be a giant expression (like a COLLECT).

So @johnk and I thought it seemed better to say:

delimit "," [
    "here" "is" "my"
    long block of code stuff
    "and we go on for a while"
]

So that was changed...and as a consequence we get natural-looking specializations now like:

spaced: (=> delimit space)

What does this mean for old-school institutions like SKIP? I don't know. But I do know it's getting faster and clearer to bend the system to anything you want it to be...

2 Likes

I think it has been mentioned somewhere before:
If refinements are there own parameters, couldn't parameters also be there own refinements?
This would mean, you could change the order of parameters at the callsite.
It feels a little weird, that you would have to add a parameter as refinement to the call, to move it to the end.

f: func [a b][print spaced [a b]]
== make action! [[a b] [...]]

‌>> f 1 2
1 2

‌>> f/a 1 2
2 1

1 Like

There's a little bit of a mechanical reason why this is hard, but yes, I did say... I intend to make this happen... !