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

Is this really a philosophical difference? Granted, I've only used Clojure as far as Lisps go, but composability seems to be something that's emphasized.

Rather than

   (remove-if-not #'p xs :count 5 :start 3)
It seems to me like most Clojure users would do something like

   (->> xs (drop 3) (filter p) (take 5))
which is much closer to

   take 5 . filter p . drop 3


Clojure, and to a slightly lesser extent scheme, are much more Haskell-like than common lisp or emacs lisp.

Clojure of course has pattern matching and lazy sequences, so naturally for collections it is very compatible with Haskell's philosophy.


My first contact with programming (besides BASIC) was (auto)lisp. It was kind of a first love: every language I tried after Lisp was a disappointment. Then I found Haskell..


A bit off topic: interesting link with project euler solutions written in haskell and clojure (and sometimes other languages). With execution time log.

http://zach.se/project-euler-solutions/


Minor nitpick. Technically, this:

    #(->> % (drop 3) (filter p) (take 5))
Is equivalent to:

    take 5 . filter p . drop 3


One could also change the Haskell. Data.Function (&); Control.Arrow (>>>)

  -- the pipe operator seems to be all the rage these days
  (|>) = (&)
  
  -- forward application + forward composition
  xs |> (drop 3 >>> filter p >>> take 5)
Only function application

  xs |> drop 3 |> filter p |> take 5


I never understood the appeal of the pipe operator. It's a kludge to work around the need to eta-expand chained function compositions, which in turn is a kludge to work around the value restriction, which in turn is a kludge to prevent the combination of polymorphism and storage effects from breaking type soundness. Haskell doesn't need any of this.


I agree with you. I'm going to write a post about function application and composition (right-to-left / left-to-right) so other communities can stop discussing non-essential matters.

I do like the fact that the `pipe operator` is often mentioned along the bash '|' which is used in a pointfree style.

Well it might make sense sometimes, so its good to know one's options :)

  p x y z = f (g x y) z
  p       = ((.) f) . g


Of course, something is very wrong if you ever use a section of the function composition operator. Use point-free within reason... :-p


Or go completely, absolutely nuts with point-free and use J (http://www.jsoftware.com/).


Is

    take 5 . filter p . drop 3
An anonymous function call in Haskell? I don't know the language (although it's on my to-learn sequence).


Yes. It's three anonymous ("take 5", "filter p" and "drop 3") functions composed by the "." operator, creating another anonymous function.

One of the types, for example:

take :: Int -> [a] -> [a]

What means a function that takes an Int argument and returns another function, that takes a list and returns a list of the same type.


Yes, written in pointless style. You could make it less pointless by replacing the (.)s with a point.

    \xs -> take 5 (filter p (drop 3 xs))
https://wiki.haskell.org/Pointfree


It's an anonymous function, which it not being called.


[deleted]


You probably meant to reply to mietek.


ghci will (usually) tell you:

    phil@arod:~$ ghci
    GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    Prelude> :t take 5 . filter (\ _ -> True) . drop 3
    take 5 . filter (\ _ -> True) . drop 3 :: [a] -> [a]
So it’s a function from List of a to List of a


Is not the same, in lisp :count 5 means that you remove at most 5 elements, so that the result can be a list of 100 elements, while take 5 will always produce a sequence with at most 5 elements.

(remove-if-not #'evenp (loop for i below 10 collect i) :count 3 :start 0) result is (0 2 4 6 7 8 9), there are three elements deleted.


Well, that is different, but I suppose the Haskell example suffers from the same difference then.


Funny how when I think about Lisp I think about that kind of code, while other people see elisp imperative, autolisp and common-lisp full-featured system.


Unlike CL/EL, Clojure is lazy by default. So it's closer to Haskell in that regard.


Clojure isn't lazy by default. It is a strict language with lazy streams in the standard library.


Sorry, yes. That's what I meant.


It's not really lazy by default, it just has a lazy stream type with nice syntax.




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

Search: