Scala versus F# question: how do they unify OO and

2019-03-07 23:08发布

What are the key differences between the approaches taken by Scala and F# to unify OO and FP paradigms?

EDIT

What are the relative merits and demerits of each approach? If, in spite of the support for subtyping, F# can infer the types of function arguments then why can't Scala?

7条回答
时光不老,我们不散
2楼-- · 2019-03-07 23:50

If functional programming means programming with functions, then Scala bends that a bit. In Scala, if I understand correctly, you're programming with methods instead of functions.

When the class (and the object of that class) behind the method don't matter, Scala will let you pretend it's just a function. Perhaps a Scala language lawyer can elaborate on this distinction (if it even is a distinction), and any consequences.

查看更多
贪生不怕死
3楼-- · 2019-03-07 23:58

The syntax of F# was taken from OCaml but the object model of F# was taken from .NET. This gives F# a light and terse syntax that is characteristic of functional programming languages and at the same time allows F# to interoperate with the existing .NET languages and .NET libraries very smoothly through its object model.

Scala does a similar job on the JVM that F# does on the CLR. However Scala has chosen to adopt a more Java-like syntax. This may assist in its adoption by object-oriented programmers but to a functional programmer it can feel a bit heavy. Its object model is similar to Java's allowing for seamless interoperation with Java but has some interesting differences such as support for traits.

查看更多
疯言疯语
4楼-- · 2019-03-07 23:59

There are quite a few points that you can use for comparing the two (or three). First, here are some notable points that I can think of:

  • Syntax
    Syntactically, F# and OCaml are based on the functional programming tradition (space separated and more lightweight), while Scala is based on the object-oriented style (although Scala makes it more lightweight).

  • Integrating OO and FP
    Both F# and Scala very smoothly integrate OO with FP (because there is no contradiction between these two!!) You can declare classes to hold immutable data (functional aspect) and provide members related to working with the data, you can also use interfaces for abstraction (object-oriented aspects). I'm not as familiar with OCaml, but I would think that it puts more emphasis on the OO side (compared to F#)

  • Programming style in F#
    I think that the usual programming style used in F# (if you don't need to write .NET library and don't have other limitations) is probably more functional and you'd use OO features only when you need to. This means that you group functionality using functions, modules and algebraic data types.

  • Programming style in Scala
    In Scala, the default programming style is more object-oriented (in the organization), however you still (probably) write functional programs, because the "standard" approach is to write code that avoids mutation.

查看更多
走好不送
5楼-- · 2019-03-08 00:04

From this article on Programming Languages:

Scala is a rugged, expressive, strictly superior replacement for Java. Scala is the programming language I would use for a task like writing a web server or an IRC client. In contrast to OCaml [or F#], which was a functional language with an object-oriented system grafted to it, Scala feels more like an true hybrid of object-oriented and functional programming. (That is, object-oriented programmers should be able to start using Scala immediately, picking up the functional parts only as they choose to.)

I first learned about Scala at POPL 2006 when Martin Odersky gave an invited talk on it. At the time I saw functional programming as strictly superior to object-oriented programming, so I didn't see a need for a language that fused functional and object-oriented programming. (That was probably because all I wrote back then were compilers, interpreters and static analyzers.)

The need for Scala didn't become apparent to me until I wrote a concurrent HTTPD from scratch to support long-polled AJAX for yaplet. In order to get good multicore support, I wrote the first version in Java. As a language, I don't think Java is all that bad, and I can enjoy well-done object-oriented programming. As a functional programmer, however, the lack of (or needlessly verbose) support of functional programming features (like higher-order functions) grates on me when I program in Java. So, I gave Scala a chance.

Scala runs on the JVM, so I could gradually port my existing project into Scala. It also means that Scala, in addition to its own rather large library, has access to the entire Java library as well. This means you can get real work done in Scala.

As I started using Scala, I became impressed by how cleverly the functional and object-oriented worlds blended together. In particular, Scala has a powerful case class/pattern-matching system that addressed pet peeves lingering from my experiences with Standard ML, OCaml and Haskell: the programmer can decide which fields of an object should be matchable (as opposed to being forced to match on all of them), and variable-arity arguments are permitted. In fact, Scala even allows programmer-defined patterns. I write a lot of functions that operate on abstract syntax nodes, and it's nice to be able to match on only the syntactic children, but still have fields for things such as annotations or lines in the original program. The case class system lets one split the definition of an algebraic data type across multiple files or across multiple parts of the same file, which is remarkably handy.

Scala also supports well-defined multiple inheritance through class-like devices called traits.

Scala also allows a considerable degree of overloading; even function application and array update can be overloaded. In my experience, this tends to make my Scala programs more intuitive and concise.

One feature that turns out to save a lot of code, in the same way that type classes save code in Haskell, is implicits. You can imagine implicits as an API for the error-recovery phase of the type-checker. In short, when the type checker needs an X but got a Y, it will check to see if there's an implicit function in scope that converts Y into X; if it finds one, it "casts" using the implicit. This makes it possible to look like you're extending just about any type in Scala, and it allows for tighter embeddings of DSLs.

From the above excerpt it is clear that Scala's approach to unify OO and FP paradigms is far more superior to that of OCaml or F#.

HTH.

Regards,
Eric.

查看更多
干净又极端
6楼-- · 2019-03-08 00:05

F# is functional - It allows OO pretty well, but the design and philosophy is functional nevertheless. Examples:

  • Haskell-style functions
  • Automatic currying
  • Automatic generics
  • Type inference for arguments

It feels relatively clumsy to use F# in a mainly object-oriented way, so one could describe the main goal as to integrate OO into functional programming.

Scala is multi-paradigm with focus on flexibility. You can choose between authentic FP, OOP and procedural style depending on what currently fits best. It's really about unifying OO and functional programming.

查看更多
\"骚年 ilove
7楼-- · 2019-03-08 00:08

What are the key differences between the approaches taken by Scala and F# to unify OO and FP paradigms?

The key difference is that Scala tries to blend the paradigms by making sacrifices (usually on the FP side) whereas F# (and OCaml) generally draw a line between the paradigms and let the programmer choose between them for each task.

Scala had to make sacrifices in order to unify the paradigms. For example:

  • First-class functions are an essential feature of any functional language (ML, Scheme and Haskell). All functions are first-class in F#. Member functions are second-class in Scala.

  • Overloading and subtypes impede type inference. F# provides a large sublanguage that sacrifices these OO features in order to provide powerful type inference when these features are not used (requiring type annotations when they are used). Scala pushes these features everywhere in order to maintain consistent OO at the cost of poor type inference everywhere.

Another consequence of this is that F# is based upon tried and tested ideas whereas Scala is pioneering in this respect. This is ideal for the motivations behind the projects: F# is a commercial product and Scala is programming language research.

As an aside, Scala also sacrificed other core features of FP such as tail-call optimization for pragmatic reasons due to limitations of their VM of choice (the JVM). This also makes Scala much more OOP than FP. Note that there is a project to bring Scala to .NET that will use the CLR to do genuine TCO.

What are the relative merits and demerits of each approach? If, in spite of the support for subtyping, F# can infer the types of function arguments then why can't Scala?

Type inference is at odds with OO-centric features like overloading and subtypes. F# chose type inference over consistency with respect to overloading. Scala chose ubiquitous overloading and subtypes over type inference. This makes F# more like OCaml and Scala more like C#. In particular, Scala is no more a functional programming language than C# is.

Which is better is entirely subjective, of course, but I personally much prefer the tremendous brevity and clarity that comes from powerful type inference in the general case. OCaml is a wonderful language but one pain point was the lack of operator overloading that required programmers to use + for ints, +. for floats, +/ for rationals and so on. Once again, F# chooses pragmatism over obsession by sacrificing type inference for overloading specifically in the context of numerics, not only on arithmetic operators but also on arithmetic functions such as sin. Every corner of the F# language is the result of carefully chosen pragmatic trade-offs like this. Despite the resulting inconsistencies, I believe this makes F# far more useful.

查看更多
登录 后发表回答