D has this (called Uniform Function Call Syntax (UFCS) ) and also has optional parenthesis for call with no more arguments which turns this:
send(getInvoice(calculatePrice(x)));
into
x.calculatePrice.getInvoice.send;
It also eliminates the need for extension methods since any function that takes any given type as its first argument is automatically callable as if it were a method of that type, this also applies to templates with the type of the first argument determined by a template parameter.
As for a "wrong way around", you can overdo it both ways, use your judgement. I prefer UFCS for more heavily nested calls which you get when you do a while lot of data transformations all in a row. Some times I use it for a single call but not very often.
Flow seems like an interesting package to check out if I ever go and start using Haskell seriously.
My favorite is Elm, which has |> and <| for application, and >> and << for composition, in the intuitive directions. It makes it easy and natural to eta-reduce/expand, when you want to.
I know we like to fight here, but I think both are valid approaches. They may correlate with top-down vs bottom-up design, or which side of the API you're designing. If you're consuming an API, yes autocomplete and suggestions are hugely helpful, as is a type system to prevent you passing garbage to the API and having to have it return errors.
The specific use case from the OP:
> Well a lot of work I do has to do with very messy business logic. Situations were a company wants to convert their receipt system, trading engine, or something of that nature into computer code. Often this data is very complex and hard to define. Situations where a importer may bring in 100 fields but we only care about 10. Thus it's often important to require that certain data match a model, but allow for extra data to flow through a system without much effort. In addition, the problem with nominal k/v types is that I often find myself converting between two types simply because function A requires a DBPerson, and function B requires a UIPerson. If the keys and values are the same, they should flow through, while still keeping me from saying PersonName = ProductID.
I can certainly see where they're coming from - they neither need nor want schema enforcement as they have no control over the input data. Most of their types relate to business semantics, but since the semantics are loose it's not suitable to ram everything into a Person object. And certainly in OO-heavy systems you do end up having to convert between similar-but-not-identical objects that were intended to represent the same thing but defined in different systems.
I'm going to (very lightly) push back and say no, I don't think that's the way I want to program. Certainly I've seen functional systems where it's mostly about syntax, but I think there's also a difference here that is more than technicality.
I'm having a hard time thinking more concretely about exactly what it is, but intuitively the statement you made rings a few alarm bells for me.
If so, I'd point out that methods can just be pure functions and objects can be immutable.
Or, more controversially, partial application is just a lazy person's method definition.
This is true, but then you start wondering what the data hiding is for, especially if an object has getters for all its immutable members.
I think it's more about organization? And more about how often structs in my functional systems evolve over the course of a single function call. Maybe it's that when you're attaching methods to an object, you have a finite number of things you can do to that data.
With a struct, I'm always just one `map` (or even a mutation) away from being in a different format that can be consumed by different methods. Of course this can happen with classes as well -- you can have transformation methods, there's nothing technical stopping you from setting up a class system where you're jumping around that much. But I feel like it happens more when I'm doing functional programming.
An IDE that was focused on "what methods can consume this data" might not capture that -- I'm not saying it wouldn't occasionally be useful, it's just that "what methods can consume this" is not the first question I ask when I see a struct. All of the methods consume it, I can just transform the data or combine it with another struct to fit whatever format a method requires.
> Or, more controversially, partial application is just a lazy person's method definition.
I reasonably strongly agree with this.
Matlab! Which uses a pretty wild form of dynamic dispatch when the (more common) f(x) form is used:
> When MATLAB® invokes an ordinary method that has an argument list, it uses the following criteria to determine which method to call
> The class of the leftmost argument whose class is not specified as inferior to any other argument's class is chosen as the dominant class and its method is invoked.
> If this class does not define the called method, then a function with that name that is on the MATLAB path is invoked.
> If no such function exists, MATLAB issues an error indicating that the dominant class does not define the named method.
Also, it doesn't care at all if you pass in an array or a scalar (everything's an array). Methods must be written to handle a "this" of any size - even empty.
What an odd language.
Isn't the common case that you already have "the thing", you have a rough idea what should be done, and you want to see what operations/transformations are available? That's when autocomplete and a static type system comes in handy.
Some (more obscure) languages unify this, i.e. f(x) is the same as x.f(). I don't think there's a "wrong way around", the difference is a technicality.