6 ms·
Lisp has never been noticeably better overall. - In the past, it was better at abstraction, but slow and niche and you needed to shell out for hardware. - In
by JulianMorrison 7y ago
Lisp has never been noticeably better overall.
- In the past, it was better at abstraction, but slow and niche and you needed to shell out for hardware.
- In the present it is not better. Common Lisp is about on a par with Python in what it has built in, inferior in its ecosystem, and for some modern stuff (threads, sockets) you will have to go outside the language standard into the wild west of implementation extensions or third party libraries.
Lisp's one big selling point is macros. Macros are magic that lets you reprogram the language. Reprogrammed languages break the ability of a programmer to drop in and read the code. Languages that need reprogramming to get basic shit done are unfinished or academic (Scheme). Languages that can get stuff done, but tempt you to reprogram them are attractive nuisances (Common Lisp, Ruby). In use, they create incompatible tangles that don't mix well with other people's incompatible tangles. I have been bitten by this repeatedly in Ruby. But Ruby is still easier to get work done in than Common Lisp.
Basically it died of being meh with a side of footgun.
- dual_basis 7y agoAbsolutely agree regarding metaprogramming
- flavio81 7y ago>Common Lisp is about on a par with Python in what it has built in, inferior in its ecosystem about 20x+ faster than Python, too; speed in the same order of magnitude than C. >and for some modern stuff (threads, sockets) pretty amazing you bring out threads in this comparison, when Python doesn't even support true multithreading. >Macros are magic that lets you reprogram the language. Reprogrammed languages break the ability of a programmer to drop in and read the code. It's the other way around. Lisp macros allow to eliminate boilerplate and produce clearer code. This is obvious to any lisper.
- JulianMorrison 7y agoFor reference, I'm not holding up Python as a good language, I'm holding it up as a comparable one. Python is warty and creaky, but more mainstream than CL, so it's a fair comparison. A good language would be Go.
- flavio81 7y ago>Python is warty and creaky, but more mainstream than CL, so it's a fair comparison. How can it be a fair comparison, when Python isn't even a real functional language? (lambdas have been intentionally crippled, there is a separation between statements and functions, not everything is an expression, and so on...)
- JulianMorrison 7y agoBecause that doesn't matter. It's "about on a par" as I said. More in some places and less in others.
- ACow_Adonis 7y agoAs a Common Lisper (among others) interested in language design, I've just started reading up on Go, after I've been told it's "simple, robust, safe, well-designed". Purely subjectively, alot of what I'm seeing in Go so far looks to me like a "2nd system design" for C programmers. I'm hoping that the concurrency model is where it shines through with some good new ideas and implementations because I've been relatively unimpressed with the rest of it so far. That's not to say it's bad per se, but I've seen nothing in it that makes it stand out from other languages design-wise, and it feels rather warty to me so far... Purely my own subjective opinion.
- shanemhansen 7y ago> looks to me like a "2nd system design" for C programmers That seems fairly accurate. > I'm hoping that the concurrency model is where it shines I'd say that channels aren't quite the magic thing they are made out to be and goroutines aren't that amazing. The real win of go for me is three things: 1. Evented runtime with a synchronous interface. "Go is my favorite epoll library" 2. A standard lib that has great http support (things like keepalive and connection pooling and http2) 3. A build and test toolchain that makes coverage and race detection and memory and CPU and lock contention profiling trivial.
- c256 7y agoGo was designed by strong programmers as a “good enough” language aimed at the combination of two goals: 1.) Letting good programmers get things done without feeling too many constraints, and without hating the output of #2. 2.) Enabling decent programmers understand the output of #1, while still getting things done themselves. It is an extremely practical language ‘project’, in that it doesn’t pretend that all programmers are great, or average, and it tries to help the two subsets work together.
- jcranmer 7y ago> It's the other way around. Lisp macros allow to eliminate boilerplate and produce clearer code. This is obvious to any lisper. I don't have any particular experience with Lisp macros, but my experience with the closest equivalent in every language I've experienced them in is very different from your experience. For the person who wrote the system, it's a clean and expressive way that eliminates boilerplate. For everybody else, though, it's an underdocumented mess of magic incantations with some mental notes of "don't try to combine these things together, it will blow up," and if you ever have to debug a problem in the macro itself, you're going to find it to be a royal pain.
- flavio81 7y ago>I don't have any particular experience with Lisp macros, but my experience with the closest equivalent in every language I've experienced them in is very different from your experience. Yes, because the way metaprogramming is achieved in other languages is very different than the way it is done in Lisp, thanks to s-expressions. >and if you ever have to debug a problem in the macro itself, you're going to find it to be a royal pain. Yes, because you're not dealing with Lisp macros. If i'm looking at a Lisp source code, and there's a macro invocation, and I want to see what this macro is going to do to the code,i just press a key, and I can immediately visualize, in-place, how the source code gets transformed. A big part of the standard library of Common Lisp itself is implemented as macros too, it's no big deal. Dealing with others' macros has no particular difficulty in Lisp; or in any case, no additional difficulty to dealing with others' functions.
- jcranmer 7y agoFrom what I understand, the Rust procedural macro system should basically be similar in structure to Lisp macros, much closer than any other language I've used. It still has all of the aforementioned problems, in my experience.
- slaymaker1907 7y agoRacket (which admittedly is a particular Lisp) has a very useful tool which lets you view each basically debug macro expansion by viewing each code transformation. This tool is even built into Dr. Racket so it doesn’t need any complex setup. I’ve written both procedural Rust macros and Racket. Racket is far easier to debug and write macros compared to Rust despite their macros having similar features (in particular source locations and doing macro evaluation as a compilation step rather than at runtime).
- xuejie 7y ago> about 20x+ faster than Python, too; speed in the same order of magnitude than C. I think this is exactly into parent thread's point: yes the performance can be great but you need to tail the code for the hardware, which is niche and the beautiful abstraction might never hold anymore
- flavio81 7y ago>but you need to tail the code for the hardware, which is niche Not really. You just need to declare the data types (Common Lisp supports type declarations) and tell the compiler you want the code to be fast, which reads just like that: (declare (optimize (speed 3))) You also need to use the same tactics you would use in C to gain speed: Use arrays instead of lists, use threads. All of this is easily doable in Lisp and IMO while it takes more effort than writing typical Lisp code, it is easier than using C and the end result is more elegant and debuggable. This is not hardware dependent, mind you.
- xuejie 7y agoThis is really depending on your view, but the moment you step outside of lists and use arrays, you are keeping modern CPU architecture in mind. And all of a sudden all those wonder car/cdr/cons concepts as well as things built upon it no longer holds, which, again depending on the view, actually harms the abstractions in Lisp, and we are actually back at the same page with all the other programming languages. Also, when you are promoting something, it might not a good idea to compare against Python when it comes to speed, but when talking maintainability, only C is talking as a target here.
- voldacar 7y ago>Lisp's one big selling point is macros. Maybe not quite as big of a selling point, but lisp has also always been the best environment for writing programs that need to modify themselves at runtime. Homoiconicity removes the limitation that code must be known and constructed at compile-time.
- JulianMorrison 7y agoI can see good uses for that if you're programming a Mars rover. On the other hand, you lose the concept of "known versions" with that, and I wouldn't want it anywhere near audited code. And in most circumstances it suffices to stop and restart.
- voldacar 7y agoYeah, it is definitely niche. However it is super cool to be able to do optimizations like constant propagation and loop unrolling using information that would never be available at compile time. For instance if you have a function that evaluates an argument and branches based on the value, and if for some other reason your program knows that after a certain condition the argument will always have the same value, it can just optimize away that branch while the program runs. Now that is kind of contrived, but one real world example I ran into happened when I was writing a program to render 2d plots of complex functions. If you hardcode the equation of the function into the source code, the compiler can optimize it (important, since this function gets called for every pixel in the image being rendered) but the program is limited to rendering that one function. If you let the user enter that function at runtime in the form of a text string, your program has to essentially act as an interpreter by creating an AST from the string then walking the AST repeatedly for every single pixel, so obviously much more costly. The ideal solution is to have an environment where code can be seamlessly compiled at runtime and executed without extra ceremony or semantics that would be out of place in compile-time known code. In C you would have to attach a JIT to your program and manually write to an executable page etc, whereas in lisp the system handles all of that for you. Another example happens with config files: Config file data is used for conditional branching, but since it only becomes known at runtime, your progarm ends up with a lot of branches that would get optimized away if the config info had been known at compile time. You could just make all the config data compile-time known by having a something like a massive config.h full of #defines, but this is obviously not user friendly at all and makes it necessary to recompile every time you want to change a setting. If your code is able to introspect and optimize itself based on data that only becomes available at runtime, this tradeoff is eliminated.
- reikonomusha 7y agoIt is inaccurate to call things like threading a Wild West of implementation-defined stuff. It is true these things aren’t de jure standard, but most important stuff has de facto standard portability libraries in Common Lisp. For threading, use BORDEAUX-THREADS. For filesystem operations, use UIOP. For module definitions, use ASDF.
- flavio81 7y agoThis. We even have an almost de-facto standard library for easy parallelization (lparallel) and software transactional memory (stmx).