5 ms·
Interestingly I've never seen the parallels between the Unix way and functional programming. But it makes perfect sense. Code programs/functions that do one thi
by tsahyt 14y ago
Interestingly I've never seen the parallels between the Unix way and functional programming. But it makes perfect sense. Code programs/functions that do one thing and do them well. However, that's how code should work in general. That's what we got functions/methods for in the first place.
I agree, functional programming is great but sometimes I just see ideas being sold as "functional" that apply to programming in general. Splitting programs into smaller parts that are easily solvable and work in a predictable way is one of the most fundamental parts of coding.
Sure, that's not all there is to it, but I'm a little bothered that it's being marketed as the new thing.
- samdk 14y agoThe parallels to Unix are strong enough that having an actual pipe operator can be very useful. I frequently write code that looks something like this: List.map data ~f:(fun elem -> ...) |! List.find ~f:( ... ) |! Option.map ~f:( ... ) (This is OCaml, not Haskell, but the syntax is similar.) The definition of the '|!' operator is quite simple: let (|!) x f = f x
- IvoDankolov 14y agoYes, in fact F# has that built in as |> , which I've taken to using in Haskell as well. Though it's a bit more intuitive to me when it has the lowest precedence like so: (|>) :: a -> (a->b) -> b (|>) x f = f x infixl 0 |> There infixl 0 means infix operator with left associativity and 0 precedence. Then you can use all sorts of expressions inbetween: (5 + 3 |> show) ++ " times" |> putStrLn Also, tying this back to one of the article's ideas, this piping-like syntax for doing things really manages to take away the emphasis from the function and put it back on the data. It isn't all about functions after all!
- minikomi 14y agoUsing -> and ->> in clojure also feels pretty close to this, and can clean up over-nested blobs very quickly. Eg: (reduce + (take 10 (filter even? (map #(* % %) (range))))) Can be expressed as: (->> (range) (map #(* % %)) (filter even?) (take 10) (reduce +))
- draegtun 14y agoIn Perl6 this is called the Feed Operator: http://perlcabal.org/syn/S03.html#Feed_operators http://perlcabal.org/syn/S03.html#Feed_operators
- Toshio 14y agoI think the first time I've seen someone make that connection was when I watched the Haskell presentation @ GoogleTechTalks.
- gtani 14y agoHere's a more detailed http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html#id624895 http://book.realworldhaskell.org/read/code-case-study-parsin... (also you can read about the F# (|>) forward pipe, and there'll be operator precedence/associativity and thunk forcing issues)
- batista 14y agoWell, speaking of the Unix philosophy, this could possibly blow your mind. It's tens of Unix command line tools (well, the gist of them, not every functionality), implemented in a few lines of Haskell: http://www.haskell.org/haskellwiki/Simple_unix_tools http://www.haskell.org/haskellwiki/Simple_unix_tools
- jeffdavis 14y agoI think one of the differences is pipelining/laziness, which makes it easier to decompose problems into smaller pieces. For instance, look at his solution to FizzBuzz. Would you use a similar solution in ruby? He uses an infinite list, so if you naively translated it, you'd run out of memory. Instead, you'd have to explicitly use a generator in order to achieve a similar solution. Of course, you can try always returning a generator in ruby, but that would be incredibly awkward because the built-in operators compute the entire result (like the + operator on lists). So, in practice, people intuitively avoid creating large intermediate results because it's wasteful, even in cases where that would simplify the code and make it more modular. But in haskell, go ahead and use the large intermediate result, because it won't actually compute it before returning. It will just return a generator for the large intermediate result, and compute only the parts of that large result that are needed.
- tmhedberg 14y agoIn fact, with compiler optimizations such as GHC's stream fusion, the intermediate result may never actually exist at all.
- stonemetal 14y agoTrue, but my limited experience in Haskell, and Ocaml says FP makes it harder to do the wrong thing. It is really hard to write a large Haskell function(on the order of 100s of lines of code.) I am not sure I could do it without breaking the function up in to a bunch of sub functions in a where clause, which is a case I am not even sure I would count since each of those sub functions could be moved out of the parent function with no change in functionality. Whereas my experience in C and C++ points to it being easy to write functions that run in to the low thousands.