Efficacy of sticking to just the functional paradigm in Scala
Asked Answered
B

4

16

I recently bought Programming Scala, and have been reading through it. The language definitely isn't what I expected! Specifically, it seems to implement just about every programming language idea I'm aware of, outside of Lisp macros and Haskell's type-level side-effect segregation.

Frankly, it has me somewhat overwhelmed. Though I suppose it's nice to have so many tools at my disposal, I was really just looking for a strongly-typed functional language on the JVM. I imagine I could probably use Scala that way, but I imagine if I interact with any libraries or go through anyone else's code, I'll be running into a lot of this advanced (for me) OOP stuff--traits and "object hierarchy linearization," all this abstract and overriding business, singleton, package, and companion objects, implicit conversions... not to mention the various syntactic shortcuts and sugars.

People often bemoan programmers who try to shoehorn one language's style into another, for lots of good reasons. But not all languages are as multi-paradigm as Scala, so perhaps its community has a different view? In F#, for example, there seems to be some leeway in programming styles and how much OOP you use. But just from reading I'm not sure if this is a good philosophy for Scala as well.

Can more experienced Scala programmers help me out here? Edit for clarity: Basically, can I safely use just (or mostly) the FP features of Scala without worrying about its advanced OOP side?

Sorry for the rambling question!

Brazzaville answered 22/11, 2010 at 16:12 Comment(3)
You may find this useful (thought its not 100% answering your question): #1723226Wineglass
I think it will happen as with C++, where people just pick a subset of the language and stick with it.Crespi
@J Cooper--I don't mean to be nasty or mean but, for me anyway, it's hard to tell what you're asking. Maybe you want to take a moment to edit your question to make it more apparent what you're actually asking?Hannis
W
7

I think that there is most certainly a solid point in this question. It is illuminated by looking into how any library might handle exceptions.

If you interact with a Java library, any method may throw an exception. This could be either explicitly, via a checked exception - or transparently (from an API perspective), via a runtime exception. What are you supposed to do about this, as a programmer who might be trying to use the more functional Either type to indicate failure (or scalaz's Validation)?

It's not at all clear to me how this will play out in scala (i.e. approaching the problem and choosing the purely functional approach). Certainly it is likely to produce many different styles of coding. That said, there is much that is rich and useful along the functional side of scala which you can pick from; and it is certainly possible to have this mix of functional and imperative code in your program work alongside each other. Although a functional purist may of course disagree about whether this an optimal situation.

For what it's worth, I've found that the application of functional paradigms within my programs has improved my code no end. As I haven't tried either Haskell or F# I couldn't tell you whether the net result is better or worse.

But it wipes the floor with Java; and to get that on the JVM (with the practical advantage of coexisting with all our Java libraries) is a killer app, from my perspective.


At the edges, as you begin to use scala's functional side more, there are a number of issues which you will run into. These are most obviously:

  • the lack of implicit function currying (i.e. equivalence of A => B => C and (A, B) => C)
  • the lack of implicit function tupling (i.e. equivalence between an n-ary function and a 1-ary function which takes an n-tuple as a parameter)
  • the lack of inference for partially-applied type constructors (i.e. the equivalence of M[A] with, for example, Either[Int, A])

Both of these issues make what should be pretty and clear functional code, ugly and obscure.

Wintertime answered 23/11, 2010 at 0:4 Comment(3)
Agreed, there's a great deal of merit to the question. Given the number of people currently claiming "Java is simple and Scala is complex, because it's not Java", I find it refreshing to see the other perspective. Specifically that "Scala is complicated because it inherits this complex object-oriented legacy from Java"Aridatha
I think this answer comes closest to what I was particularly worried about, though of course the other answers were informative and appreciated.Brazzaville
And I even missed out the most important missing functional piece!Wintertime
A
16

One of the things you're seeing is that Scala is, above all, a strongly-typed functional language on the JVM

Scala is not just a Functional language. It did start off as one (Funnel: http://lamp.epfl.ch/funnel/), but this was then extended to make it an Object-Oriented language, with the explicit goal of making it strongly interoperable with Java classes.

abstraction and overriding and packages are all examples of this interoperability in action.


The remainder might be considered not as new features, but simply as removing restrictions from Java. Taking them one at a time:

traits and object hierarchy linearization

Removes the restriction that Java interfaces can only contain abstract methods. Linearisation is how Scala resolves the diamond-inheritance problems that this would otherwise cause.

singletons

Java static methods are a hangover from it's C++ syntax heritage, which in turn added them to better support the procedural style need for interop with C. Static methods are very much NOT object oriented (see this question: Why are singleton objects more object-oriented?)

companion objects

Allow singletons to be used in lieu of static methods, with their privileged access rights.

implicit conversions

Java already does this, but it's restricted to only implicitly converting objects and primitives to strings, as in the expression "" + 3. Scala just extends this idea and allows the programmer to use it for other conversions.

Aridatha answered 22/11, 2010 at 16:59 Comment(5)
I thinks that there is a bit more to implicits than conversions; there are also the implicit parameters which, together with scala's type system, allow libraries like scalaz to do so much cool, functional stuffWintertime
Oh, absolutely there's a lot more to implicits. I was just addressing the specific mention of "implicit conversions" in the original question :)Aridatha
I was being picky - I know full well that you know about this stuff :-)Wintertime
Makes sense. So those things are mainly used for Java interop?Brazzaville
Not at all, objects are first class citizens in Scala-land. The exact shape of Scala's objection-orientation was, however, strongly influenced by the design of the underlying JVM platform, and by the need for Java interop.Aridatha
S
8

Let me add a few comments to Kevin's answer.

Traits are primarily used as abstractions (loosely speaking, the same way that Haskell type classes define abstractions) and mixins. So, my code might use the Map trait, but it's really using an instance of type like HashMap. Conversely, if I want my "Service" type to have logging functionality, I might mix in a reusable Logging trait.

Fortunately, you rarely have to think about the linearization algorithm beyond the simple cases, e.g., I can mix in a trait that intercepts (wraps) a method call to log the fact that the method was invoked. The algorithm needs to handle the more complicated linearization cases (like the examples we show in the book), but really such complicated types are a poor design, IMHO.

Singletons, including the special subset companion objects, are designed to make everything an object, but you could also just view them as namespaces wrapping functions and possibly some state.

The implicit conversions are very useful, if a bit "magical". You might find it useful to see how they are used to simulate Haskell type-classes. Here's a great post by Debasish Ghosh: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

Satellite answered 22/11, 2010 at 18:0 Comment(1)
I think your book did a fine job of explaining those concepts; I was mostly curious about to what degree I'd interact with them when sticking to a purely-functional-if-possible style. That link was quite interesting :)Brazzaville
W
7

I think that there is most certainly a solid point in this question. It is illuminated by looking into how any library might handle exceptions.

If you interact with a Java library, any method may throw an exception. This could be either explicitly, via a checked exception - or transparently (from an API perspective), via a runtime exception. What are you supposed to do about this, as a programmer who might be trying to use the more functional Either type to indicate failure (or scalaz's Validation)?

It's not at all clear to me how this will play out in scala (i.e. approaching the problem and choosing the purely functional approach). Certainly it is likely to produce many different styles of coding. That said, there is much that is rich and useful along the functional side of scala which you can pick from; and it is certainly possible to have this mix of functional and imperative code in your program work alongside each other. Although a functional purist may of course disagree about whether this an optimal situation.

For what it's worth, I've found that the application of functional paradigms within my programs has improved my code no end. As I haven't tried either Haskell or F# I couldn't tell you whether the net result is better or worse.

But it wipes the floor with Java; and to get that on the JVM (with the practical advantage of coexisting with all our Java libraries) is a killer app, from my perspective.


At the edges, as you begin to use scala's functional side more, there are a number of issues which you will run into. These are most obviously:

  • the lack of implicit function currying (i.e. equivalence of A => B => C and (A, B) => C)
  • the lack of implicit function tupling (i.e. equivalence between an n-ary function and a 1-ary function which takes an n-tuple as a parameter)
  • the lack of inference for partially-applied type constructors (i.e. the equivalence of M[A] with, for example, Either[Int, A])

Both of these issues make what should be pretty and clear functional code, ugly and obscure.

Wintertime answered 23/11, 2010 at 0:4 Comment(3)
Agreed, there's a great deal of merit to the question. Given the number of people currently claiming "Java is simple and Scala is complex, because it's not Java", I find it refreshing to see the other perspective. Specifically that "Scala is complicated because it inherits this complex object-oriented legacy from Java"Aridatha
I think this answer comes closest to what I was particularly worried about, though of course the other answers were informative and appreciated.Brazzaville
And I even missed out the most important missing functional piece!Wintertime
A
3

Though I've started programming in scala, I am definitely not a more experienced member of the scala community. But I've worked for long with another language - python, which to a lesser extent has a similar situation. It supports procedural, object oriented and functional styles. I've found that while some folks tend to stick to one extreme, many combine constructs from different styles. Thus idiomatic python will consist of heavy use of list comprehensions, first class, higher order and partial functions, even as the data these functions work on are objects. However it is to be noted that over the years, the tendency has been to shift slightly towards functional.

I think given the inclusivity of styles that scala supports it is only likely that there will be no one right way to solve a problem. But I wouldn't be surprised to see that a larger proportion of programmers slowly tend towards a style which makes judicious use of both, even as they remain tolerant of programmers wishing to stick to one of the extremes.

Ambages answered 22/11, 2010 at 17:57 Comment(1)
So you think those preferences/styles haven't been fully developed yet?Brazzaville

© 2022 - 2024 — McMap. All rights reserved.