3 ms·
This particular set of examples is especially ambiguous because "splitBy" can be read two different ways: as a description of the result (noun having been split
by nybble41 6y ago
This particular set of examples is especially ambiguous because "splitBy" can be read two different ways: as a description of the result (noun having been split by a separator) or as an action (subject split direct object by a separator). Which one you choose will subtly affect the way you group the arguments. Conventions in functional programming tend to prefer the former, whereas imperative (including OOP) languages prefer the latter. Either way, however, the string which directly follows `splitBy` should be the separator. In the functional example:
-- Is this correct?
splitBy "," "1,2,3,4,5"
-- or this?
splitBy "1,2,3,4,5" ","
there really is no question that the first version is correct. Even oversimplifying as the article does and treating "basic English" as the only applicable domain knowledge, I'm not likely to read "split by ',' …" as an instruction to split the string "," by some other separator. To understand how the second string fits in you need more than basic English, because English doesn't have that sort of syntax. However, once you learn that it parses as `(splitBy ",") "1,2,3,4,5"` the result is pretty obvious.
In the OOP language example the second version with the string knowing how to split itself, as it were, does make more sense than the first version. The target of the method is always the subject, and the method name is usually read as a verb, with parameters as direct or indirect objects. (Read as: String "1,2,3,4,5" (S), split yourself (V) by the string "," (I.O.).) However, in functional programming the bias is exactly the opposite, because functional programming is about programming with first-class functions on data, not performing actions. You could easily arrange to write:
"1,2,3,4,5" `splitBy` ","
in Haskell using infix notation, and it even reads fairly well reinterpreted as English prose. However, defining `splitBy` this way would imply the curried prefix version:
splitBy ","
would not be a function that splits its input by ",", as one would expect, but rather one that splits "," by its input. Which just goes to show that not every function is well suited for both infix and prefix notation. Whichever version you choose needs to be used consistently. In general the convention has been to define multi-parameter functions such that they can easily be used as combinators, via currying, which seems fitting to me given the nature of functional programming. Functions which are designed to read well as infix operators usually require operator sections or `flip` to adapt them for use as combinators.
> I think, in general, requiring named arguments is a good thing.
I have no objection to optional named parameters, but making them required would necessarily eliminate currying and simple function composition, and that I have a problem with. Record parameters with named fields are generally sufficient for the situations where named parameters are useful, especially since they're ordinary data which you can manipulate at will and not some special syntax baked into the language just for function calls.
- nybble41 6y ago> Functions which are designed to read well as infix operators usually require operator sections or `flip` to adapt them for use as combinators. It occurs to me that this could have been avoided at the language level by defining infix notation to implicitly flip the arguments. For example, x / 3 == (/ 3) x == (/) 3 x x ++ "suffix" == (++ "suffix") x == (++) "suffix" x x `splitBy` "," == (`splitBy` ",") x == splitBy "," x (The left and center forms are valid and equivalent Haskell code today; the right form has the arguments flipped.) I think on the whole this would have made it easier to transition between the curried forms and the infix forms, since it's more common to want to bind the RHS of an infix operator than the LHS. I would also say that e.g. `(/) 3` reads more naturally as "divided by three" than its actual definition as "three divided by …". No doubt we could find a few counterexamples where it reads better to have the LHS first, though I can't think of any at the moment. Of course, it's much too late to be changing something so fundamental at this point. Even as an extension it would cause far too much confusion.