Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'll say this though: functional techniques really can save a lot of time. I'm not sure I'd recommend Scala for a new project if you don't have Scala experts already, but I apply ideas I got from my experience using it to projects all the time.


The question then is whether it was functional programming that actually made the difference, or the people who had enough perseverance and skill to actually learn Scala in the first place running the project.

I've found that people who go out of their way to learn things like that would be more productive regardless of the language itself.


>The question then is whether it was functional programming that actually made the difference, or the people who had enough perseverance and skill to actually learn Scala in the first place running the project.

Oof, it may indeed be the second, but what do they get out of the deal?

A lot of FP programmers refuse to go back, simply because it feels nicer.

It's a hell of a lot easier to "persevere" on a project when your language doesn't make you want to dig your eyes out with a spoon.


I agree, but then you should focus on hiring people with these specific predispositions, and not trying to teach your developers FP from scratch.


Depends on the project, that is exactly what feels to me sbt or scalaz.


Well, the ideas I liked, stuff like deferring side effects and avoiding state, were functional ideas. You see a lot of functional concepts and constructs bleeding out into mainstream languages (just look at the last few C# releases, for instance, which look like a list of features borrowed from Scala), which I think will be their legacy more than widespread adoption.


  > stuff like deferring side effects and avoiding state
is that really "functional programming" or just good practice?


To the extent it’s considered good practice now I think FP deserves a lot of credit.


i see, thanks for the reply

one reason i asked is because while i don't really come from an FP background (as a student, i started with c/obj-c), after working in the field it was always appaling at how many variables and global state people would put in their code and how many side-effects were present... its just something that seemed so obvious even in "oop-land" but maybe im just an outlier...


I think that's been recognized for global state for a long time, but I think that mutating local or instance variables/collections wasn't really thought of the same way as much when I started doing this like 8 years ago.


Functional programming has the same problem as "AI" - as soon as something's adopted by the mainstream, it's "not really functional programming, just common sense". Ten years ago lambdas and map/reduce/filter were "functional programming"; now every language has them. Fifteen years ago having interfaces rather than just classes was "functional programming". Five years ago pattern matching was "functional programming"...


I argued recently that the core to functional programming is composition, rather than specific language features. This goes many ways, such as functional composition (using currying, higher order functions etc) and type composition (using algebraic types). Functional polymorphism using HKT's and typeclasses are also compositional.

Pattern matching, for example, is not itself 'functional programming', and never has been. It's a feature common in functional languages because it compliments algebraic types.

OO/Imperative languages (C# and Rust) getting pattern matching is useful but doesn't make them functional languages. C# and Rust are compositional in the sense types may implement interfaces (or traits), but with varying degrees of power. However, C# can't have HKT's until some work on the CLR is done, Rust is much closer.

Programmers (particularly web programmers) these days don't really consider the computational cost of their actions, so pure functions with immutable data types are now possible, despite the unnecessary allocation. Almost all popular OO architectures now are some variant of 'functional core, imperative shell'. There is definitely a 'functional shift'.

It makes me a little sad tbh, to see OO languages embrace FP principles. I just like writing tiny functions and types, gluing them together somehow (not how Haskell does it*), and building up to a bigger system. You can follow that approach in F# or OCaml, but it's not really possible in an OO language, regardless of how 'functional' it now is.

* Haskell is cool, but trying to explain to someone the difference between `.`, `$`, `<|>`, `|>`, `<$>`, `>>=` and more is quite painful.


>Haskell is cool, but trying to explain to someone the difference between `.`, `$`, `<|>`, `|>`, `<$>`, `>>=` and more is quite painful.

For those who aren't familiar, I'll explain:

First of all, these are all infix operators, meaning they take two parameters: one before the symbol, and one after. You already know many infix operators: +, -, %, etc. I'll be surrounding them in parentheses, as that's idiomatic when they're not being used in the infix position.

(.) is compose: run one function, then feed its result into the other.

($) is just a tool for avoiding parentheses. It means "wrap everything after this in a set of parens".

(<|>) is alternative. Try one computation that can fail. If it doesn't work, try the other.

(|>) is either snoc (the opposite of cons) or pipe--as in bash--depending on what you have imported.

(<$>) is the general form of map, called fmap in Haskell (since map is just for lists). Given a function and a value inside a container, return the function applied to the value, inside the container.

(>>=) ah, bind. One half of the interface to the famously difficult monad. It's really not that hard, conceptually: run a computation, then use the result of that to run another computation. You might say "that sounds like compose!" and you'd be right. The difference is that a "computation" (or "action", or whatever your local monad tutorial calls it) is a function in a context. That context can be "it might not exist", which is called Maybe, or "there are a lot of values in order", which is called List, or "it can do side effectful IO", which is called, well, IO. If you want to compose those kinds of computations, you need to also "compose" their contexts as well. The implentation of that composition varies from context to context, but the interace is the same: (>>=), or bind.

Of course, conceptually is the easy part. This is the one operator in your list that can be a little difficult to gain an intuition for.


It's both. You can defer side effects, and avoid state in most other languages; but it's not enforced, or encouraged; and might even be tedious. The difference with functional languages, is that they encourage or enforce deference of side effects, and avoidance of state.


That’s certainly a big part. The other one is less obvious, but is one that shines through this article as well. Once you learned a functional language or any language that is well designed (for me that typically incorporates functional and possibly logic and relational paradigms) then you’ll be more confident and productive than before and will have a hard time to justify using a tool that is inferior other than adherence to the lowest common denominator.

I’m sure this can be observed with any profession. A good cook can work with a cheap knife and mediocre ingredients, but give them a nice set of professional kitchen tools and fresh, tasty vegetables and they will happily cook you a meal that makes your evening.


a good language would allow you to express thoughts that are difficult in another language. But this presumes that you have those thoughts to express in the first place. If you don't, the language isn't gonna magically be able to give you the ability to have those thoughts.

So learning functional languages is both learning the language, but to also improve your cognitive capabilities to have more thoughts.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: