Comment by umanwizard

Comment by umanwizard 2 days ago

13 replies

Is CL really particularly more “functional” than JavaScript? I don’t know CL but I know it bears some passing similarity to Emacs Lisp, which is usually written in a pretty imperative style. Sure, it has first-class closures but so does JS.

wk_end 2 days ago

I kind of agree, but in the interest of discussion: even if CL isn't necessarily a more functional language in practice, culturally it's got a long history of being more functional. It took something like a decade at least for people to widely recognize to how elegant (in its quirky way) JavaScript could be. Just as a point of comparison (I'm sure the idea goes further back) PAIP - one of the definitive CL books - was first published in 1991 and encourages pure functions and immutability wherever possible.

Devs in the 90s were handed a language that looked like a weird Java and so they programmed it like a weird Java. If they were handed a language that looked like Lisp instead, maybe they would have made their way to SICP that much sooner.

  • behnamoh 2 days ago

    > ... culturally it's got a long history of being more functional

    Sure, but CL also culturally has a long history of macro-ridden code that make it harder to understand other people's code.

    We already suffer from dozens of JS frameworks. Just imagine what it would look like under a CL-dominant world...

cultofmetatron 2 days ago

CL is the Ditto (pokemon) of programming langauges. It commits to nothing and does everything better than you'd expect. The problem is its very much a lone warrior type of language. you can attain great productivity due to macros and just how maleable it is but it makes it near impossible to get a team to work together on it without very extensive styling and conventions strictly adhered to by the team. In a way, you could say its a direct influence to go, in that the go team saw everything common lisp did and decided to do the opposite.

  • behnamoh 2 days ago

    > It commits to nothing and does everything better than you'd expect.

    Idk man, every time someone makes that claim my immediate reaction is: "what's the catch?". I much rather use 5 tools designed for specific purposes than general-purpose tools that are 50% good at 5 tasks.

    • cultofmetatron 2 days ago

      the catch is that the langauge is so maleable that no two lisp codebases look the same. Makes it very difficult to establish broader idioms. But in terms of what it cando, its got ridiculously good runtime speed for how dymanic it is and the debugger is one of the best around. you can literally pause on an exception, rewind, fix your code and continue from where you left off.

      • behnamoh 2 days ago

        I love the restarts system but the fact that the industry as a whole chose other approaches makes me wonder if there's something the "wisdom of the crowds" knows that I'm not aware of.

        > you can literally pause on an exception, rewind, fix your code and continue from where you left off.

        Does it only work on source codes or can I distribute a binary and let my users debug the code like this? Should I distribute the 'image' for it to work?

        And is the fix temporary (until the program dies) or permanant?

iLemming 2 days ago

Both CL and Elisp are arguably more functional than Javascript in several key ways - Immutable data by convention, First-class function from the start (js added this later), powerful higher-order function are more idiomatic, lexical closures, FP culture that goes back decades. JS has caught up in some aspects - arrow functions, array methods, const, libs like Rambda.

I think, Lisp in general is very flexible - you can write imperatively, or you can do more FP; if you need object-orientation - you have it, polymorphic dispatch - sure why not?, etc., etc.

  • xigoi a day ago

    I object to the claim that a Lisp-2 has first-class functions.

taeric 2 days ago

As the sibling says, CL can be written in most any style. Which, I think it is fair to say for any general programming language? The book Exercises in Programming Style highlights that. That said, CL feels far friendlier to the various styles than other languages, to me.

Link to book on Amazon: https://www.amazon.com/dp/0367350203

jackdaniel 2 days ago

CL enables many paradigms of programming, including functional one and imperative. Currently the most popular way of programming among CL programmers is OOP with CLOS.

tmtvl a day ago

CL is pretty multi-paradigm. To give the boring 'double all numbers in a list' example:

  (defun double-numbers (numbers)
    "Doubles a list of NUMBERS.
  Docstring and type declarations are optional."
    (declare (type List numbers))
    (mapcar (lambda (x)
              (declare (type Number x))
              (* x 2))
            numbers))

  (defun double-numbers (numbers)
    (labels ((accumulate-loop (nums acc)
                (if (null nums)
                    (funcall acc nums)
                    (destructuring-bind (first-number &rest other-numbers)
                        nums
                      (accumulate-loop other-numbers
                                       (lambda (result)
                                         (funcall acc
                                                  (cons (* first-number 2)
                                                        result))))))))
      (accumulate-loop numbers (lambda (result) result))))

  (defun double-numbers (numbers)
    (if (null numbers)
        numbers
        (cons (* (first numbers) 2)
              (double-numbers (rest numbers))))

  (defun double-numbers (numbers)
    (loop :for number :in numbers
          :collect (* number 2)))

  (defun double-numbers (numbers)
    (if (null numbers)
        numbers
        (prog ((remaining-numbers (rest numbers))
               (first-pair (list (* (first numbers) 2)))
               last-pair)
          (setf last-pair first-pair)
        :start-loop
          (when (null remaining-numbers)
            (return first-pair))
          (setf (rest last-pair)
                (list (* (pop remaining-numbers) 2)))
          (setf last-pair (rest last-pair))
          (go :start-loop))))
And that's before going into libraries like SERIES or iterate. There are, of course, benefits and disadvantages (readability, performance, some CL implementations don't do TCO,...) to every option, but generally CL lets you code in any way you want (you could even write some macros to let you write it using more infix or postfix style syntax, but I don't see the appeal of doing so).