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

To whom did 'functional' mean the same thing as 'lisp'?

I'm always astonished when people conflate these two things. Lisp encourages you to put the forms that evaluate to a value in the position you would otherwise put a variable that has been set to that value, sortof code in place. That is kindof like functional programming. However, lisp does not avoid side effects or mutability, in fact virtually all operators in lisp are either destructive or have a destructive equivalent. The destructive equivalents are there because if you are limited to the nondestructive versions only you can't implement lots of algorithms without doing a bunch of consing and copying. In lots of ways it is easier to implement a performant functional language if it is pure and without side effects, because you can make strong assumptions everywhere.

Lisp was much more interesting 10 or 20 years ago than it is today. Today, most languages have stolen most of the good parts of Lisp. Strong but dynamic typing (or the gross weak but dynamic typing), pass by reference only, generic data structures, garbage collection, first class functions, ability to introspect objects at runtime, and most other features it pioneered are just taken for granted in modern languages. What is left as an advantage is the lisp syntax, and advantages that come from that, such as data-as-code and therefore powerful macro systems. That is also the main disadvantage to lisp, as much as people will claim that eventually you can see through it, I have never seen anyone do math either on paper or on a whiteboard in anything but infix notation. There are infix and postfix calculators, but I have never seen a prefix calculator.

TLDR; Lisp isn't really that functional unless you use a restrictive and inefficient subset of the language.



You are also not getting the point you complain about completely clear, it is not that "Lisp isn't really that functional", Lisp != Common Lisp and being a Lisp and being functional is to some extent orthogonal those days - Clojure is a very functional Lisp for example, similarly Racket, Common Lisp much less so. The original McCarthy Lisp paper was to a large extent a paper in theory of computation, using Lisp as a vehicle for things like proving program correctness, so that Lisp was purely functional, otherwise you could not do much formal reasoning with it. I guess to be completely clear one has first to define what one means by "Lisp".


That's an interesting point about infix and postfix calculators but no prefix calculators. Though I wouldn't go so far to say there aren't any, I feel pretty sure I've seen one before--though don't care enough to go looking--they do seem pretty rare. I wonder what lisp/scheme/whatever-I-need-to-say-to-get-you-to-stop-being-pedantic would look like with post-fix evaluation.


I think it would be not that much better than prefix.

Infix is easier to read, because it is just more natural to parse. An expression like:

sin(1 + (5 + x + y) / (n + k)) is just really easy to understand

(sin (+ 1 (/ (+ 5 x y) (+ n k))) is inscrutable, at least to me.

The second thing is, intermediate variables makes code much more readable, but lisp strongly discourages this. The only way to create a lexical variable is with LET. But this causes indenting, which is pretty ugly. In fact, the use of indenting for both logical nesting and variable creation is a really nasty thing:

so this:

    def qualifies_for_free_shipping(item_price, weight, shipping_factor, category):
        if category is in FREE_SHIPPING_CATEGORIES:
            return True

        item_cost = item_price * TAX_RATE
        shipping_cost = weight * shipping_factor + 2.00
        total_price = item_cost + shipping_cost

        if item_cost >= 80:
            return True

        if total_price >= 100 and category in ELECTRONICS_CATEGORIES:
            return True

        return False

becomes, in some lisp dialect I am making up but is like common lisp

    (defun qualifies-for-free-shipping (item-price weight shipping_factor category)
      (if (in category FREE_SHIPPING_CATEGORIES)
        t
        (let* ((item-cost (* item-price TAX-RATE))
               (shipping-cost (+ (* weight shipping-factor) 2))
               (total-price (+ item-cost shipping-cost))
          (if (>= item-cost 80)
            t
            (if (and (>= total-price 100) (in category ELECTRONICS-CATEGORIES))
              t
              nil)))))

I could have cleaned up the code and used a better conditional than nested if's or something, but this is my point. I can't just glance at the code and see what is going on, I have to parse it and keep track of where I am as I move around the s expressions. In the python version I can just jump in the middle and move around without keeping a mental bookmark, because I always know from indentation how I can get to where I am now.


Your argument amounts to "I know Python better than Lisp." And it may be true that because most languages and especially most popular languages are like Python that you have a head start. But it doesn't mean that Lisp is insensible or harder to read. It just means you have less experience reading it.

I say this as a decent Haskell programmer, and a very poor Lisper. There was a time I found Haskell code so unbelievably befuddling I thought it was a prank. Now I know it, so I know what to expect and I can read it as easily as Java. Lisp remains harder for me, like you, but it's a matter of practice.


I personally have trouble quickly parsing expressions like sin(1 + (5 + x + y) / (n + k)), but do really well with things like:

    (sin (+ 1 (/ (+ 5 x y)
                 (+ n k))))
Similarly, your Lisp could be reformatted to something like:

    (define (qualifies-for-free-shipping item-price weight shipping-factor category)
        (let* ((item-cost (* item-price TAX-RATE))
               (shipping-cost (+ (* weight shipping-factor) 2))
               (total-price (+ item-cost shipping-cost)))
         (cond ((in category FREE-SHIPPING-CATEGORIES) #t)
               ((>= item-cost 80) #t)
               ((and (>= total-price 100) (in category ELECTRONICS-CATEGORIES)) #t)
               (else #f))))
I think you’re trying to use Lisp as if it were Python, and that’s going to make things more difficult for you than they need to be.

(A lot of my college classmates ran into trouble in a class where we programmed in Scheme [since renamed to Racket] because they tried to use it like Java, the standard curriculum language. If/when they grokked Scheme, they became just as proficient in it as they were in Java, but until they did they spent a lot of time effectively complaining about how Scheme wasn’t Java.)


I know it's not real code but I honestly find the second example way easier to read. It's indeed very common to use a 'let' like that and I don't see what's wrong with a "two spaces" indent (between your 'let' and the next 'if'). If you're talking about the indent after the 'let*' then, if anything, I think it makes the scope just so much more obvious.

So YMMV.




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

Search: