321

In your code, you have made multiple changes: destructuring assignment to access fields in the pages is a good change. extracting the parseFoo() functions etc. is a possibly good change. introducing a functor is … very confusing. One of the most confusing parts here is how you are mixing functional and imperative programming. With your functor you aren't ...


225

If you are in doubt, it probably is too clever! The second example introduces accidental complexity with expressions like foo ? parseFoo(foo) : x => x, and overall the code is more complex which means it is harder to follow. The purported benefit, that you can test the chunks individually, could be achieved in a simpler way by just breaking into ...


201

Object-oriented code is not by definition cleaner, and conversely non-OO code is not by definition crappy. While there does seem to be a rather obvious object-oriented mapping to this particular problem, I would suggest that you try the functional programming approach anyway. Give it your best shot, try to solve the problem in the best functional ...


173

Kevin succinctly points out how this particular code snippet works (along with why it's quite incomprehensible), but I wanted to add some information about how trampolines in general work. Without tail-call optimization (TCO), every function call adds a stack frame to the current execution stack. Suppose we have a function to print out a countdown of ...


138

The actual pattern is actually significantly more general than just data access. It's a lightweight way of creating a domain-specific language that gives you an AST, and then having one or more interpreters to "execute" the AST however you like. The free monad part is just a handy way to get an AST that you can assemble using Haskell's standard monad ...


126

With curried functions you get easier reuse of more abstract functions, since you get to specialize. Let's say that you have an adding function add x y = x + y and that you want to add 2 to every member of a list. In Haskell you would do this: map (add 2) [1, 2, 3] -- gives [3, 4, 5] -- actually one could just do: map (2+) [1, 2, 3], but that may be ...


108

There is absolutely no reason to pass a function, and its parameters, only to then call it with those parameters. In fact, in your case you have no reason to pass a function at all. The caller might as well just call the function itself and pass the result. Think about it - instead of using: var formattedRate = GetFormattedRate(getRate, rateType); why not ...


97

The reason people say functional languages are better for parallel processing is due to the fact that they usually avoid mutable state. Mutable state is the "root of all evil" in the context of parallel processing; they make it really easy to run into race conditions when they are shared between concurrent processes. The solution to the race conditions then ...


96

If a function doesn't have any side effects and it doesn't return anything, then the function is useless. It is as simple as that. But I guess you can use some cheats if you want to follow the letter of the rules and ignore the underlying reasoning. For example using an out parameter is strictly speaking not using a return. But it still does precisely the ...


89

You can't create a pure function called random that will give a different result every time it is called. In fact, you can't even "call" pure functions. You apply them. So you aren't missing anything, but this doesn't mean that random numbers are off-limits in functional programming. Allow me to demonstrate, I'll use Haskell syntax throughout. Coming from ...


89

The reason your brain is rebelling against the function loopy() is that it is of an inconsistent type: function loopy(x){ if (x<10000000){ return function(){ // On this line it returns a function... // (This is not part of loopy(), this is the function we are returning.) return loopy(x+1) } }else{ ...


85

I'm not sure about universal definitions of purity, but from the point of view of Haskell (a language where programmers tend to care about things such as purity and referential transparency), only the first of your functions is "pure". The second version of add isn't pure. So in answer to your question, I'd call it "impure" ;) According to this definition, ...


84

The function name should say what you're doing. The implementation will tell you how you're doing it. Use comments to explain why you're doing it.


71

Is Javascript a functional language? I know it has objects & you can do OOP with it also, but is it also a functional language, can it be used in that way? Sometimes, people will say functional programming, when what they mean is imperative programming or procedural programming. Strictly speaking, functional programming is: In computer science, ...


70

Java's choice to do it that way with a separate name for every arity was stupid. It's not exactly worth emulating. However, if you must for the sake of consistency, or if you're writing very generic library code, Konrad's suggestions are good. I might throw Procedure into the ring. Using a pseudo-functional paradigm doesn't mean normal naming principles ...


69

It depends what you mean by "functional programming" and by "possible". You can obviously implement things following a functional paradigm. However the Java language doesn't provide the syntactic sugar for it, so some things will be tedious at best, and some other ones will be extremely arcane. Similarly, you can very well write object-oriented code in a ...


68

You mention that the client used to program in a functional language, maybe he has a reason that he requires you to write the code in a functional style. You should ask him why. Maybe he intends to keep the code and maintain it himself later. Moreover, I don't think the two choices are either do it OO-style or write crappy code like you mentioned. Sure ...


67

Jeremy Gibbons is writing the book. Until it's finished, you can read his blog, Patterns in Functional Programming. He recommends reading his posts from oldest to newest. Browse his publications as well. He covers Gang of Four patterns in Design Patterns as Higher-Order Datatype-Generic Programs and describes the patterns of programming with recursive ...


64

The main reason is that referential transparency (and even more so laziness) abstracts over the execution order. This makes it trivial to parallelize evaluation. For example, if both a, b, and || are referentially transparent, then it doesn't matter if in a || b a gets evaluated first, b gets evaluated first, or b doesn't get evaluated at all (because a ...


62

Referential transparency, referred to a function, indicates that you can determine the result of applying that function only by looking at the values of its arguments. You can write referentially transparent functions in any programming language, e.g. Python, Scheme, Pascal, C. On the other hand, in most languages you can also write non referentially ...


61

A lot of the answers are going into things like infinite lists and performance gains from unevaluated parts of the computation, but this is missing the larger motivation for laziness: modularity. The classic argument is laid out in the much-cited paper "Why Functional Programming Matters" (PDF link) by John Hughes. The key example in that paper (Section 5) ...


59

Must I think about compiled machine code when I write my code? No, not when you write your code the first time and don't suffer from any real, measurable performance problems. For most tasks, this is the standard case. Thinking too early about optimization is called "premature optimization", and there are good reasons why D. Knuth called that "the root of ...


59

which seems to be the more mathematical way functional languages are inspired by lambda calculus. In this field, parentheses are not used for function application. I also think that the latter style is much more clear and readable than without the parens. Readability is in the eye of the beholder. You are not used to reading it. It is a bit like ...


59

To my mind, the phrase "easy to reason about", refers to code that is easy to "execute in your head". When looking at a piece of code, if it is short, clearly written, with good names and minimal mutation of values, then mentally working through what the code does is a (relatively) easy task. A long piece of code with poor names, variables that constantly ...


57

Because lists are simpler than trees. (You can see this trivially by the fact that a list is a degenerate tree, where every node has only a single child.) The cons list is the simplest possible recursive data structure of arbitrary size. Guy Steele argued during the design of the Fortress programming language that for the massively parallel computations of ...


56

Using Maybe (or its cousin Either which works basically the same way but lets you return an arbitrary value in place of Nothing) serves a slightly different purpose than exceptions. In Java terms, it's like having a checked exception rather than a runtime exception. It represents something expected which you have to deal with, rather than an error you did ...


55

Are you aware that functional programming doesn't just mean "programming without classes"? See the Wikipedia article about it for the full schtick, but in short... In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the ...


53

The practical answer is that currying makes creating anonymous functions much easier. Even with a minimal lambda syntax, it's something of a win; compare: map (add 1) [1..10] map (\ x -> add 1 x) [1..10] If you have an ugly lambda syntax, it's even worse. (I'm looking at you, JavaScript, Scheme and Python.) This becomes increasingly useful as you use ...


51

From a practical viewpoint combinators are kind of programming constructs that allow you to put together pieces of logic in interesting and often advanced manners. Typically using them depends on the possibility of being able to pack executable code into objects, often called (for historical reasons) lambda functions or lambda expressions, but your mileage ...


50

Is it readable? For me: Yes, but I have come to understand, that the Python community often seems to consider list comprehensions a cleaner solution than using map()/filter(). In fact, GvR even considered dropping those functions altogether. Consider this: filtered = [item for item in measures if included(item.time, dur)] Further, this has the benefit ...


Only top voted, non community-wiki answers of a minimum length are eligible