4 ms·
I've got little experience with Scala, but judging from your sample it looks like what's happening is that Scala follows more Java-y idioms for how code is stru
by bunderbunder 13y ago
I've got little experience with Scala, but judging from your sample it looks like what's happening is that Scala follows more Java-y idioms for how code is structured.
So in
List(1,2,3,4) filter isEven sum
it looks like filter and sum are instance methods on the List class, and I'm guessing isEven is a predicate that's being passed as an argument to the filter method.
F# leans closer to its functional roots in this respect, so it's more idiomatic to keep object-oriented constructs at arm's reach in most your code. The language has full support for OOP, it's just that you're not expected to trot it out except when you're writing public interfaces that are meant to be consumed by code that might be written in C# or VB.NET. So the List class mostly sticks to static methods in its public interface because that approach fits better with traditional functional idioms.
That gets you as far as something like this:
List.sum (List.filter isEven [1;2;3;4])
The next step is the "pipeline" operator, which is defined as
let inline (|>) x f = f x
So it's just letting you swap a function and its argument, which facilitates reorganizing the code so that the functions are listed in the order in which they execute. That's what gets you to the example you give - or better yet:
[1;2;3;4]
|> List.filter isEven
|> List.sum
which I think captures some of the natural expression that you were talking about while still sticking with functional idioms instead of object-oriented ones.
- jdmichal 13y ago> So the List class mostly sticks to static methods in its public interface because that approach fits better with traditional functional idioms. And also fits perfectly with the C# and VB.NET extension method syntactic sugar, which was used extensively for LINQ. They're really just static methods in the .NET VM and bytecode.
- frowaway001 13y ago> 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? Looks like a bad compromise to me.
- bunderbunder 13y agoOne 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.
- frowaway001 13y agoBut 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?
- bunderbunder 13y ago> 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#.
- frowaway001 13y agoIt 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.
- 13y ago
- frowaway001 13y ago> F# leans closer to its functional roots in this respect, so it's more idiomatic to keep object-oriented constructs at arm's reach in most your code. The language has full support for OOP, it's just that you're not expected to trot it out except when you're writing public interfaces that are meant to be consumed by code that might be written in C# or VB.NET. Wouldn't it have been better to keep such things out of the language instead of having a considerable amount of complexity in the language for stuff people are not even supposed to be doing in the first place?
- noblethrasher 13y agoNo, The .NET Base Class Library is object-oriented at the core, and one of the value propositions of F# is that you can fully leverage that library.
- frowaway001 13y agoIsn't there a large difference between supporting interop with code written in other languages and importing all the stuff into the language itself?
- noblethrasher 13y agoWell, if the language was only meant to be an API consumer then eliding OO stuff would make more sense, but they designed it for bi-directional interop. And besides, F# was based on OCaml (as I'm sure you know), which itself was an existence proof that you could successfully bolt OO onto a functional language.
- frowaway001 13y ago> successfully bolt OO onto a functional language Yes, I think that's a good description. It's not great, but it somehow works (although the whole F# community tends to tell people to stay away from OOP when not necessary). Would have been interesting to explore better ways to support OOP so that it doesn't need to be considered a second class citizen, but I guess it's too late for that now.