> that approach fits better with traditional functional idioms
Just interested, what's the real value here? "Familiarity" alone seems to be a pretty poor reason.
> They're really just static methods in the .NET VM and bytecode.
Doesn't this mean that either your methods won't be dynamically dispatched or that you would need to rewrite your code if you ever change from e. g. List to Array?
> Doesn't this mean that either your methods won't be dynamically dispatched...
The MSIL (.NET bytecode) for calling an extension method and a static method are exactly the same. So yes, it will not be dynamically dispatched. Specifically, it emits a "call" and not a "callvirt" instruction.
However, the compiler will always prefer a class method over an extension method of the same signature. Meaning that extension methods can be specifically implemented by a class and the compiler will emit a "callvirt" instruction for that instance method instead.
> ... or that you would need to rewrite your code if you ever change from e. g. List to Array?
I'm not sure what you mean here. Arrays implement IList, so if you need random access, you would just write a method against IList. If you don't need random access, you should write it against IEnumerable, which all collections implement.
Perhaps what the parent is saying is that if you implement an extension method to IList, you can't subsequently implement an extension method to Array and expect it to be called on an Array stored in an IList variable? Which is true for exactly the reason you state.
One of the big values is currying. Instance methods don't always interact well with partial application and design patterns that rely on it, because with instance methods one of the function's (logical) operands is a special snowflake that isn't curried.
But currying isn't even consistently supported, e. g. when calling C# APIs as far as I remember. Wouldn't it have been better to explore a way which either works for all code or, if that doesn't work out, just embrace instance methods?
The current API situation looks kind of weird. What's the point of having an API (like the collection one) which is meant to be chained together, but needs additional boilerplate (|>) to actually work that way?
Maybe it would have been better to do away with these inconsistencies and make the idiomatic way of writing code the default one, working without any additional effort of flipping stuff around?
> Wouldn't it have been better to explore a way which either works for all code or, if that doesn't work out, just embrace instance methods?
I suppose the answer to that question ultimately depends on one's preferences. I like F#'s way of doing things because I like functional programming and idioms, but I also like being able to play nice with a rich pre-existing ecosystem, and don't want to have to do it through a (probably) leaky abstraction.
When I instead want a primarily object-oriented language with some extra support for functional programming slapped on top, I just use C#.
It seems to be kind of insane having to choose between a "better functional" and a "better OOP" language.
Why not just combine the good parts into a single language.
That would probably be more consistent than the current 80%OCaml + 50%C# => F# mess.
Just interested, what's the real value here? "Familiarity" alone seems to be a pretty poor reason.
> They're really just static methods in the .NET VM and bytecode.
Doesn't this mean that either your methods won't be dynamically dispatched or that you would need to rewrite your code if you ever change from e. g. List to Array?
Looks like a bad compromise to me.