Verbing Nouns Revisited: COMBINATOR and COMB

We've long lamented the unfortunate nature of "verbing" nouns like FUNCTION.

And again, we have this situation where if we use COMBINATOR as the way of declaring a combinator, what do we call instances? C? COMB?

It feels a bit sad that we can't just write something like:

combinator: select state.combinators group!  ; get the GROUP! combinator

If you do that, you're overwriting the function you use to make combinators. And that's no good.

So I wind up writing:

comb: select state.combinators group!  ; get the GROUP! combinator

But it seems that COMBINATOR rightly belongs to the instance, and the thing that makes combinators should be called something like MAKE-COMBINATOR. If anything, COMB should be the shorthand for MAKE-COMBINATOR and we allow the word COMBINATOR for instances of combinators.

I got to wondering why we don't like MAKE-FUNCTION or MAKE-COMBINATOR. Is it the hyphen? What if it were make function and make combinator and it dispatched to the "makers" based on quoting the words?

This would create a little bit of confusion, but we've gotten used to:

length: length of block

Why can't we accept:

combinator: make combinator [...] [...]

I hate to beat this old dead horse again. But FUNCTION is a noun. COMBINATOR is a noun. It still feels like something is wrong with verbing these nouns just for the sake of brevity and familiarity, and then having to contort the names of instances to avoid overwriting the verb.

NEW is shorter and not contentious with the historical meaning of MAKE:

combinator: new combinator [...] [...]

It just seems like we're fighting against the English language to be using nouns wrong, just because other languages have done it. :frowning:

I'm hitting this yet again with the verbing of module.

>> module [Title: "This is annoying"] [i: <can't>, print "Stand it!"]
Stand it!
== make module! [
   i: <can't>
]

...said Yoda...

MODULE is NOT A VERB!

We don't make modules nearly as often as we make functions, so make module seems like not a burden to type.

And in fact, I can kind of type make module about as fast as I can type module!, because typing the exclamation point is awkward. Typewriters did not optimize for it.

Note that if you use a shorthand here, you're overwriting the infix modulus operator.

mod: make module! [...] [...]  ; whoops, there went `1 = 10 mod 3 `

So is it really so bad to put this on the table?

module: make module [...] [...]

There are some details to think about here. Maybe it does have to be another operator like NEW so that the low-level MAKE MODULE! is still available for implementing higher level operations like MAKE MODULE.

Just wanted to bump this to say I really feel this "nouning" is a sticking point that needs to be forcibly confronted.

For me (and that's just personal) make sth doesn't flow. New would be OK.

Okay, well this has continued to stick in my head, because the problems of these nouns being verbs are very pervasive. It forces you to be obscure (e.g. the comb: combinator [..] [..])

I would much prefer the freedom to call a variable combinator.

If we go with NEW and agree to drop the need for the exclamation point, then NEW OBJECT is nicer to look at than MAKE OBJECT!, so it's already an improvement right off the bat.

I don't think having to type NEW MODULE is a burden for the times you say that.

We could say that FUNC is a shortcut for NEW FUNCTION...though this would not generalize well to OBJ as a shortcut for NEW OBJECT, because OBJ is too frequently used as a variable name. Once you start thinking of it that way it makes FUNC feel like it should also be a shorthand for function instance.

So maybe new func [...] [...] ? new obj [...] ? The savings on MAKE OBJECT! might balance out the extra typing of NEW on FUNC. :-/

But this would suggest that deriving would be done with something else, like extend obj-variable [...] ... which is probably a good idea anyway.

This would lead to people being able to say:

function: new function [...] [...]

...if they wanted to. (Though more likely it would be the name of some argument or local of an arbitrary function passed from elsewhere... if you know what a function does because you're the one declaring it with instance data, you probably would name it something other than "function")

I guess that would allow us to revisit the question of whether we call these things ACTION! or FUNCTION!. I guess it depends on if we have some other idea for what an action would be?

action: new action [...] [...]

I've really found myself pretty much at ease with the likes of type: type of value. It seemed weird at first but now completely normal.

(Sidenote: It's actually not bad to have names for entities inside the system that are different from the value names. e.g. having String* pointers as the name of the stored data with no index, and then TEXT! values with the index being cells. So if we renamed the external type FUNCTION! I would keep Action* as the internal name for the non-cell entity. This could also be a nice distinction between Binary* and BLOB!. I don't have a good idea for how to distinguish Frame* from FRAME! though when they compete for variables named frame. :frowning: It's a stack level, so Level* maybe?)

How Would HELP Work?

HELP already needs to be smarter, when given a doorway to a larger universe. HELP PARSE just telling you it takes a BLOCK! of rules isn't very illuminating.

So might HELP NEW be able to give you a table of the registered new-handlers? Could you then say:

>> help new object

...and get something meaningful?

The Pattern Isn't Stopping...

We're going to be facing this same thing again with GENERATOR and YIELDER. Every time this comes up it bothers me and I find myself writing displeasing code.

People will of course be able to define things however they want, but I feel like taking a stance against verbing of nouns is likely necessary.

I'll Repeat Myself that Hiding the NEW Is Didactically Bad

For better or worse, the highly dynamic model of the language is such that you really are making a new function every time you cross a FUNC today.

 Rebol [Type: module ...]

 my-inefficient-2x-sum: func [x y] [  ; created once when module is made
    let summer: func [] [x + y]  ; created each time my-inefficient-2x-sum called
    return summer + summer
]

Other languages can do some form of static analysis and design closures more efficiently. But so long as we would just as easily let you put a COMPOSE there that was fully different, we can't do that...and need a new function identity each time.

(Ren-C and its immutability properties has some wiggle room in making it more efficient than historically the case, if it notices you are truly using the exact same block...but with MUTABLE allowing you to hack on block identities that gets in the way)

So the new helps you cognizant of the true cost--that you really are making a new function every time you cross that line.

Does this mean that DOES would have to be NEW DOES? Or we need to rename -> to new-> ? Er, probably not. But I'm saying that when it fits, the NEW doesn't hurt to know about.