Terminology contention with functional programming: COMPOSE, MAP

There's a very entrenched use of the term compose in math and functional programming to refer to the idea of function composition. Ren-C has been pushing on the abilities so that you can CHAIN and SPECIALIZE functions. But if anyone were searching on this they would ask "how to compose two functions".

When I was first experimenting with a new operator that was a replacement for REJOIN that had more predictable behavior (and would "dissolve nones"), I called it COMBINE. Something I noticed that was frustrating is that I kept mixing up COMBINE and COMPOSE...typing one when I meant the other.

Today the replacement is DELIMIT and its specializations SPACED and UNSPACED. Which means the COMBINE word is free. It's the same number of letters as COMPOSE and doesn't carry the baggage.

As I'm not proposing any specific definition for the COMPOSE operation at this time, it could be just left as "error: use COMBINE or do COMPOSE: :COMBINE". This could also help alleviate confusion over COMPOSE's historical splicing behavior: COMBINE could get a fresh start with its behavior of only splicing blocks if ((...)) is used.

On a similar note, I have a lot of questions about the MAP! datatype. But one question would be its name. The map term in almost all functional programming scenarios does something like:

>> map :negate [1 2 3]
== [-1 -2 -3]

Ren-C can do some fancy tricks similar to these languages, e.g.

>> map (=> 10 +) [1 2 3]
== [11 12 13]

It's hard to think of a nicer word for this!

The data structure could have other names... HASH! is a bit misleading (sounds like it's a hash value, as opposed to a HASHTABLE!). DICTIONARY! is a pretty self-explanatory name that's used several places. It's long to type out, but in a language that lets you say dict!: dictionary! it seems that maybe it's something people could abbreviate on their own if they think it's a problem.

I've always felt that the functional programming languages had the most "reusable thought" and vetted libraries. Today's world sees languages like Rust and Elm borrowing heavily from places like Haskell, and I think that's a lot of established prior art to be ignoring. It's hard to imagine coming up with better...so these questions should be taken seriously if one expects to have traction with the thinking people of the world (!)

I don't like map! because it is too verb-y. To me mapping! would be better.

So the math and programming community has also standardized that when it comes to composition, they use dots. In Haskell, this is a period:


It's going to be the case that our . would be both a TUPLE! and executable via a hidden binding that only applies to all-blank tuples. I'm looking forward to making ... be something that breaks into the debugger and lets you enter a value for an unfinished function, so that code like func [x] [...] ca actually have runtime meaning. That's neat.

Then with the . case, we have the opportunity to play along with other languages and make it relate to composing the left and the right things. But the g . f notation they use specifies a new function that applies f first, and then g.

When I've thought about using TUPLE! for predicates, this is backwards to what I wanted. I was imagining something along the lines of:

 >> any .not.negative? [-10 -20 30 -4]
 == 30

Writing that as .negative?.not just for the sake of some supposed "consistency with math" isn't worth it.

I'm imagining it's not worth it to try and unify the meaning of a dot outside of a TUPLE! with a dot on the inside of one. I explored this concept with / and pathing before, and gave up... surrendering it to division.

So What Else could Dot Be?

Note that dot really should represent a function and not an object, because it's unclean to have to say (.).member. Hence we wouldn't want it to be something like "current module" even if that looks nice in ./member, since it wouldn't work in ..member

So if dot isn't "function compose" and isn't "current module" or any other object... what is it? It's likely something that should be either infix or prefix arity 1:

append block a . b
append block . a

It probably is best if it isn't a function composition operator because if it operated on functions you'd wind up seeing :a . :b everywhere unless it quoted implicitly.

make it "compose" (just our compose) :clown_face:

In the "ha ha" category, if COMPOSE is kept as its current meaning, and . were defined as compose, we could make the strange claim that . is compose...but compose just isn't what you think:

>> . [1 + 2 (1 + 2) 1 + 2]
== [1 + 2 3 1 + 2]

It seems to be much easier to come up with funny suggestions for what "dotting" is than serious ones.

>> . I
== i  ; dotting your i

>> / T
== t  ; crossing your t


There'd be parity if tuple's dot were multiply, with path's slash being devoted to divide. That would free up * to mean something else. (I'm not really suggesting that seriously, but it is kind of a strange possibility falling out of this design.)

It could be the identity function. This may sound a bit strange to devote such a short symbol to something that only returns the exact copy of its input. But in practice, it's quite useful. In particular i predicate specification...since dot is a TUPLE! and not a WORD!, you could say:

>> block: [a b c] 

>> compose [<foo> (block) <bar>]
== [<foo> [a b c] <bar>]

>> compose . [<foo> (block) <bar>]
== [<foo> a b c <bar>]

The reason that works that way is that COMPOSE actually does splice blocks unconditionally in its implementation...but only after applying the predicate to all the substitution slots. What (( )) does is suppress predicate application.

expression barrier

For a while, . was considered as an option for expression barriers. Now that expression barriers are implemented in usermode and | is still a WORD! caracter, you can choose other things. So if you liked dot you could do it.

>> any [1 > 2 . 3 < 4]
== #[true]

>> any [1 > . 3 < 4]
** Error: > is missing its second argument

Trying possibilities in the past already rejected this, favoring the idea that BAR be syntax highlit to a weight matching blocks and that it makes what you're looking at clearer:

any [ 1 > 2 | 3 < 4 ]

other ideas?

Out of these considerations, I think identity makes the most sense, but the proof of its usefulness isn't really ready yet. Anyone have other thoughts? What's dot good for?

Dot is very good at being overlooked. A dot could be a piece of dirt on the screen or a broken pixel. A comma with a missing tail.