views:

631

answers:

4

Which techniques or paradigms normally associated with functional languages can productively be used in imperative languages as well?

e.g.:

  • Recursion can be problematic in languages without tail-call optimization, limiting its use to a narrow set of cases, so that's of limited usefulness
  • Map and filter have found their way into non-functional languages, even though they have a functional sort of feel to them

I happen to really like not having to worry about state in functional languages. If I were particularly stubborn I might write C programs without modifying variables, only encapsulating my state in variables passed to functions and in values returned from functions.

Even though functions aren't first class values, I can wrap one in an object in Java say, and pass that into another method. Like Functional programming, just less fun.

So, for veterans of functional programming, when you program in imperative languages, what ideas from FP have you applied successfully?

+7  A: 

Pretty nearly all of them?

If you understand functional languages, you can write imperative programs that are "informed" by a functional style. That will lead you away from side effects, and toward programs in which reading the program text at any particular point is sufficient to let you really know what the meaning of the program is at that point.

Back at the Dawn of Time we used to worry about "coupling" and "cohesion". Learning an FP will lead you to write systems with optimal (minimal) coupling, and high cohesion.

Charlie Martin
+2  A: 

Not having first-class functions really puts a damper on writing functional programs, but there are a few things that you can do that don't require them. The first is to eschew mutable state - try to have most or all of your classes return new objects that represent the modified state instead of making the change internally. As an example, if you were writing a linked list with an add operation, you would want to return the new linked list from add as opposed to modifying the object.

While this may make your programs less efficient (due to the increased number of objects being created and destroyed) you will gain the ability to more easily debug the program because the state and operation of the objects becomes more predictable, not to mention the ability to nest function calls more deeply because they have state inputs and outputs.

Kyle Cronin
+3  A: 

Here are things that get in the way of doing FP in a non-FP language:

  • If the language doesn't support lambda/closures, and doesn't have any syntactic sugar to easily mostly hack it, you are dead in the water. You don't call map/filter without closures.
  • If the language is statically-typed and doesn't support generics, you are dead in the water. All the good FP stuff uses genericity.
  • If the language doesn't support tail-recursion, you are hindered. You can write implementations of e.g. 'map' iteratively; also often your data may not be too large and recursion will be ok.
  • If the language does not support algebraic data types and pattern-matching, you will be mildly hindered. It's just annoying not to have them once you've tasted them.
  • If the language cannot express type classes, well, oh well... you'll get by, but darn if that's not just the awesomest feature ever, but Haskell is the only remotely popular language with good support.
Brian
+2  A: 

I've successfully used higher-order functions a lot, especially the kind that are passed in rather than the kind that are returned. The kind that are returned can be a bit tedious but can be simulated.

All sorts of applicative data structures and recursive functions work well in imperative languages.

The things I miss the most:

  • Almost no imperative languages guarantee to optimize every tail call.

  • I know of no imperative language that supports case analysis by pattern matching.

Norman Ramsey