Why don't we have a composition operator in Pervasives?


#61

“most people agree that straight-forward composition does not actually occur that often”

Maybe because there is no syntax for it, so people are tired of having to define
this function and hence use it less.
Don’t forget that the syntax of the language may influence the style of programmers.

Monads are also rare in OCaml code. Why? Maybe because there is no syntax support for them out_of_the_box_and_without_mangling_with_the_build_system and hence programmers are influenced to not use them.
I just know Lwt and Async as OCaml code bases that have and use monads.

I’ve done some Haskell in the past. I was amazed by the high level code I saw.
There were monads everywhere and using the composition operator was a real pleasure.


#62

I am also amazed at how ‘high level’ Haskell frequently is :slight_smile: I experience emotions very similar to what I feel when someone shows me highly golfed Perl. If some very mild discouragements are enough to keep typical OCaml from looking like typical Haskell, I will be relieved.

That sounds like it’s just a snipe, but it really comes across that you do not think there even exists an opposing position to yours. That there are just people who haven’t connected the dots yet, or who don’t quite understand your position yet, but would understand it if you would beat the drum for a little bit longer. That you are speaking to people who want OCaml to be like Haskell but just haven’t figured out how to do that yet.

I think, when you do understand that an opposition really exists, that you will be more comfortable with a kind of “fine I’ll go build my own treehouse and you’ll all see just how much people prefer it to yours” solution: use, or create, a standard library that offers the compose operator, and encourage the use of it. There’s a whole book that relies on people using an alternative standard library so it’s not something unprecedented.


#63

Actually, both Batteries and Containers define % for function composition. So the only standard library not supporting it is Base/Core.


#64

For the record, (%) is already used in Base/Core for the modulus operation, which to me at least is less confusing.


#65

That’s a shame. OCaml hacked the ‘mod’ keyword as infix specifically as a replacement for (%). I don’t know the history here, but my reasoning is that modulus is a very niche operator that’s rarely used, and therefore doesn’t deserve to occupy a full ASCII symbol that’s easily accessible on the keyboard. I like the idea of re-purposing it for something more useful like composition. Nevertheless, if that’s the way it’s used in Base, it’s fundamentally incompatible and won’t be placed in the standard library. It would still be nice to have composition as a primitive, at the very least.


#66

For me, something named compose or even e.g. comp wouldn’t be very useful on its own, without a matching (ideally single-character) operator. (Too bad about %. :frowning:)


#67

You can always type let (%) = foo into your text editor. In fact, you can define the composition operator yourself in far less time than it takes to read even one reply in this thread.


#68

Yes, I think that’s the best option at present: Define %, or some other operator, at the top of every file where I use it, so that anyone reading the code can scan up and figure out what it means. I still think it would be best to have a standard for a composition operator.

OK! I will refrain from discussing language issues in the future, and just define everything that I want on my own. :slight_smile:


#69

(%) is not completely equivalent to (mod), viz.:

─( 16:42:35 )─< command 0 >──────────────────────────────────────{ counter: 0 }─
utop # open! Core;;
─( 16:42:37 )─< command 1 >──────────────────────────────────────{ counter: 0 }─
utop # (-3) % 5;;
- : int = 2
─( 16:42:39 )─< command 2 >──────────────────────────────────────{ counter: 0 }─
utop # (-3) mod 5;;
- : int = -3

(I find (%)'s behavior generally more useful, e.g., (index - 1) % length.)

This thread has become quite long enough, though :confused:


#72

I did some tests and it seems that with flamba the equivalence between the two idioms is restored. I tested with this functions:

let f x = 
  ignore (Array.create ~len:50 x);
  fun y -> x + y

let f_staged x =
  ignore (Array.create ~len:50 x);
  Staged.stage (fun y -> x + y)

let g x y = x + y

let h x y = x * y

I composed or piped f or g with h and got this results:

  Name                 Time/Run   mWd/Run   Percentage  
 -------------------- ---------- --------- ------------ 
  f composed             3.20ns                  3.51%  
  f with pipe           91.09ns    51.00w      100.00%  
  g composed             3.19ns                  3.50%  
  g with pipe            3.17ns                  3.48%  
  compose with stage     3.19ns                  3.50%  
  pipe with stage        3.18ns                  3.49%

The pipe idiom works well only with functions of the form fun x y -> ... but if we do some heavy computation with x before defining fun y -> ... then we have to stage the result or use the composition idiom.


#73

It may be related to my lack of experience with the language, but reading this thread I deduct that function composition (which I consider key on any FP language) is not very performant on Ocaml and it is go some extent discouraged. Is that correct?


#74

No, you’re not correct. I’m not sure where you got the notion from.


#75

From all those benchmarks and people saying that, because it is not an operator but a function call and that it needs to create intermediate closures it has bad performance.


#76

What would you imagine it is in any other functional language? There’s no difference. It’s the same issue in all of them. Performance of any such construct depends on the compiler, not how the abstraction is represented at the PL level. Since essentially everything in OCaml is in principle a function call (adding two numbers, accessing the head of a list, whatever you can name) the compiler knows how to handle such things well.

So, your presumption that performance is bad here makes no sense. In fact, OCaml is a very fast language, comparable in benchmarks to most other compiled modern languages, in spite of the fact that everything in the language is conceptually just function composition, and naive implementations of function call chains would be slow.


#77

@perry your replies here don’t seem sensitive to the context of the discussion. This thread includes remarks from numerous established members of the OCaml community indicating reservations about, or complications involving, the composition operator. The topics discussed include problems with typing, issues of performance, and critiques of the general usefulness of the operator.

Given all of this context, imo, your dismissive replies to @Danielo_Rodriguez don’t make much sense. This is not to say that there isn’t ample room to correct or elaborate on the topic of their question. However, it seems quite clear to me why they would have come away from this thread with the stated impression.

[Edited for a bit more clarity]


#78

None of the issues, including performance issues, are particularly different from what you would find in Haskell, SML, or any other similar language.


#79

No real difference. A standard composition operator is needed. Maybe at some point we’ll be using UNICODE math symbols in progs huh?


#80

Ok, I can assume some performance overhead if it is the normal one. I got the impression that it was worse than in other languages.
I still think that ocaml needs an official composition operator


#81

Just to rehash what’s been said before, OCaml doesn’t encourage point-free style. You may also note that idiomatic OCaml read from left to right is bottom-up, whereas function composition and where clauses are naturally top-down.

Some people will find point free style and top-down style more legible, some will find it less legible. That’s subjective. But there is something to be said for only encouraging one of the two styles in a language to make things more consistent. Anyone who has ever read code that mixes both styles will know what I mean.


#82

That doesn’t sound quite right to me, composing functions encourages a more functional programming approach. In the end what matters is whether the code is legible and works I suppose, but that’s an important point. I understand the parameter passing style in standard library wasn’t done with this in mind, but there will be libs using it.