10 ms·
Every time, I see one of these links or videos, I feel the urge to learn Lisp. But after some time, I lose the motivation. I think that is because I don't know
by nafizh 9y ago
Every time, I see one of these links or videos, I feel the urge to learn Lisp. But after some time, I lose the motivation. I think that is because I don't know what benefit learning lisp will provide me concretely. Anyone has any suggestion?
- ShaneWilton 9y agoLisp teaches you that there's always a better tool for the job than something that's already in your toolkit. More than any other language I've worked with, Lisp makes it incredibly easy and low-friction to write domain-specific languages to solve the exact problem you're working with. That's not always a good thing -- it can make working with a foreign codebase difficult -- but it's definitely a powerful concept when applied correctly.
- goatlover 9y agoLisp seems to take the exact opposite approach as Go. The power of languages like Lisp appeal to me, so I have a hard time understanding why people want a language that intentionally limits itself. Read Graham's book and he's talking about how macros are great for writing maintainable code because you can make it both short and very readable because it's close to the domain. But then you hear the arguments in favor of Go maintainability, and it's about copy/pasting being preferable to abstraction and not having too many ways to do things, so everyone's code looks familiar. Also that the extra LOC are more readable to Go maintainers than powerful abstractions. That surprises me, because languages like Lisp, Smalltalk, Ruby and Haskell are all about powerful abstraction capabilities so you can express yourself exactly as you need instead of writing a lot of boilerplate.
- flavio81 9y ago>Lisp seems to take the exact opposite approach as Go. The power of languages like Lisp appeal to me, so I have a hard time understanding why people want a language that intentionally limits itself. Me too. I don't understand how people in HN vouch for restrictive languages.
- deleted 9y ago[deleted]
- zardo 9y agoPeople don't want powerful features because they can be misapplied, making a mess. These people aren't worried that they will make a mess of their own code, they are worried that they will have to deal with someone else's mess. What happens as you add more developers to a code base, with larger variance in ability and favored abstractions is going to be important in some cases, and irrelevant in others.
- AnimalMuppet 9y agoTo expand a bit on this: Imagine that you're joining a project. It's been worked on by a team of 100 people for a decade. Half of those people were below-average programmers. Many were newbies in the language, and some were newbies to programming. And you're going to get to try to maintain this code. Now, do you want it to be written in a restrictive language, or in one that gives developers the ultimate amount of freedom?
- flavio81 9y ago>Many were newbies in the language, and some were newbies to programming. I wouldn't join this project, no matter what the language is. Imagine it's a popular languae. Javascript or C code, for example. There are no true namespacing / packages and modules facilities in JS or C. It would be even worse than the theoretical nightmare you think Lisp would be. (Lisp has extensive namespacing facilities; code can be contained within modules that don't clash.) If it was Java, you will see wrongly applied Design Patterns, leading to over-complicated, hard to mantain code. No, thanks. I wouldn't accept no matter the languages. Newbies to programming should be educated and trained, not incorporated directly into an important project.
- JetSpiegel 9y ago>>Many were newbies in the language, and some were newbies to programming. >I wouldn't join this project, no matter what the language is. Then you will never be employed, because that describes virtually every software project at a for-profit company.
- xstartup 9y agoThe complex features, lots of syntax and many ways to do things are not a problem for experienced devs in a particular language. The real trouble comes when these experienced folks leave the project for something more challenging and you start with newbie devs with no experience and they feel demotivated when they come across these tricky features and abstractions which requires months of conditioning. At that point, all you want to do is make a meaningful contribution in the reasonable amount of time increasing your motivation level. The beginning is the hardest part.
- pjmlp 9y agoThat is the theory, the practice is the factory factory pattern, design pattern books, code generation frameworks, IDE plugins,error handling libraries,... all to workaround the language limitations. So when a new one comes into the project there is this spaghetti of workarounds in place.
- argv_empty 9y agoThat surprises me, because languages like Lisp, Smalltalk, Ruby and Haskell are all about powerful abstraction capabilities so you can express yourself exactly as you need instead of writing a lot of boilerplate. There is a mindset that's popular among programmers which says, "I cannot understand what anything does except by knowing all about its internals." Languages like Go let the programmer keep that mantra instead of understanding the things they use based on a description of external behavior.
- gnufx 9y agoAn old epi²gram: There should be only one way to do it. — Python There's more than one way to do it. — Perl Do the right thing. — Lisp
- astrange 9y ago"Do the right thing" is a brave statement for a language with no typechecking!
- flavio81 9y ago"Do the right thing", in this context, goes beyond just the presence or absence of typechecking. But regarding type checking, Lisp (at least Common Lisp) is strongly typed. Really, very strongly typed (for example it will complain about putting a "byte" in a "character" array; or of using an "array" when a "simple-vector" was expected... Lisp is very nitpicky regarding types!), but the type checks happens mostly at runtime. Some checking also happens at compile time, even more if you intentionally include type declarations. (Type declarations are part of the ANSI Common Lisp standard.)
- kbp 9y ago> Some checking also happens at compile time, even more if you intentionally include type declarations. (Type declarations are part of the ANSI Common Lisp standard.) Just a note that this is entirely implementation-dependent. SBCL, for instance, is very good about using type declarations as correctness checks (those that can't be statically verified transparently degrade to runtime assertions) but their exact behaviour isn't specified in the standard; for example, implementations are free to take them as declarations that the programmer knows things the implementation doesn't and to trust them, which could cause weird bugs if they're not correct.
- TeMPOraL 9y agoPlenty of typechecking primitives are available, and CL itself is strongly - but dynamically - typed. Now, the Lisp way strongly favours interactivity with programming, so by default, those typecheck helpers are not too convenient, to use, and a lot happens at runtime. But: - CL standard defines a pretty decent type hierarchy (not Haskell-level decent, though). - While not required by the standard, good CL implementations make use of typing for optimization and safety checks at compile-time. SBCL is particularly great in that domain, employing a solid type inference engine. - CL allows you to override optimization/safety levels at very small granularity - even sub-function level - with (declare (optimize ...)) forms - like, you can e.g. drop (declare (optimize (speed 3) (safety 0))) inside a loop inside a function, to optimize just this particular section of code. - Even though CL type-related primitives aren't very convenient (they generate a bit of line noise in the code), the macro system gives you all the power you need to hide it under whatever syntactic sugar you like. There's nothing stopping you from writing (or finding a library defining) e.g. a macro: (defun* foo ((real x) ((fixnum 0 100) y) z) -> rational ... some code ...) that will get expanded into: (declaim (ftype (function (real (fixnum 0 100) t) rational) foo) (defun foo (x y z) (check-type x real) (check-type y (fixnum 0 100)) (the rational (progn ... some code ...))) which will give you both runtime checks and, with compilers at SBCL, plenty of compile-time type checks too. -- I see "do the right thing" in the context of that epigram as meaning that you can choose to do the right thing without having to make compromises for syntax and semantics, as Lisp will happily let you remove any and all boilerplate with its macro system.
- macintux 9y agoLearning a functional language has been eye-opening, but I've always struggled with Lisp. It was Erlang that finally clicked with me. I would suggest, if you haven't already learned one, to find some FP language that looks interesting. Elm, perhaps, or Elixir. I'm not a fan of "hybrid" languages like Scala; finding one that hews closely to the FP ideas will be more useful, I think, in learning how to think functionally. Any new language that doesn't operate exactly like the ones you already know can give you new ideas on how to program. Don't get bogged down in the expectations others have; just find one that piques your interest and dive in.
- ShaneWilton 9y agoWhile I agree with you, it's important to note that the defining trait of Lisp isn't that it's a functional language. It can be functional, just as it can be object oriented or procedural, but those labels matter less to what Lisp is than does the intense focus on things like metaprogramming, in my opinion.
- taeric 9y agoThat is far from the defining trait of lisp. Probably brought about because it was easy to pass around functions in lisp. However, i find lisp is at its most powerful when you understand some of the imperative abstractions that are available to you.
- kbp 9y agoAround 60 years ago, Lisp pioneered functional programming and was the only thing that supported it at all. Up until the mid-90s or so it was still far and away the most popular language that had meaningful support for closures and higher order functions. That hasn't been true anymore for about 20 years, but for a long time anyone interested in using that stuff probably learnt it from Lisp, and Lisp was probably their best bet for getting to use it. There was always more to Lisp (I read a cute essay from the mid-60s about how to balance assignment-and-goto style programming with recursive-pure-function style programming in Lisp), but older people making that connection isn't unreasonable, or younger people who've only heard older people talk about it.
- defenestration 9y agoI enjoyed learning Clojure by doing the exercises at http://www.4clojure.com/ http://www.4clojure.com/. I documented my progress and learned a lot from solutions of others.
- flavio81 9y agoNote that Clojure is not really a Lisp dialect, so you will need a different tutorial if you want to try a Lisp like Scheme, Common Lisp, Racket, TXR Lisp, etc.
- gnufx 9y agoHow is Hickey wrong about that?
- flavio81 9y agoI am not saying that Hickey is "wrong". Clojure simply differs too much from the Lisp languages. For example take into account the "atom" keyword and its meaning in Lisp versus Clojure. And also the way lists are used in Clojure, see "cons" for example. These are not frivolous differences -- atoms and conses are the key building blocks of the Lisp language!
- lispm 9y agoTake any Lisp book from 1958 onwards: not a single example program will work in Clojure. Most would need a complete rewrite, because the concepts are different.
- agumonkey 9y agoDon't force it. It will come at the right time. Enjoy your spot on the programming map, it's no use to learn Foo if it means you'll suffer your day job or can't get enough value out of it. That said, lisp is a goldmine / rabbithole crossover. As other said: - opens for a hackable tool mindset, use lisp on lisp to make it do what you need [1] - as said in this talk, if you want a dsl, you don't need a parser. Only later if you need others to write it without '(lisp syntax) you can do so. And if all are happy with lisp, you just skip that entirely. - it's often highly interactive, and value oriented. You get to "touch" the data a bit like material. Nowadays repl's are common, so it doesn't seem special but it was so for 30years. - lists mindset is different from mutable arrays, saving you immense amount of time in the first phase (by avoiding the vast majority of stupid bugs). When you need speed you can tailor; also lisp implementations are performant (SBCL is in the top 10 of all IIRC) - functional mindset also open for a lot of new ways to think about problems, leads to other languages like ml/haskell too - similarly you often get a step in the logic programming world (prolog, kanren) which are very mind opening about "programming computers" it's not perfect, and if abused you can get stupid code, too cryptic because you used too many weird notation or structure; this is a balance skill you get to learn, lispers are not that asocial, they know when to stay in the human readable most of the time.
- kbp 9y ago> it's often highly interactive, and value oriented. You get to "touch" the data a bit like material. Nowadays repl's are common, so it doesn't seem special but it was so for 30years. REPL's are common, but they're rarely as useful in other languages. Even relatively basic (to Lisp programmers) things are almost universally missing, for example: [1]> (defun f (x) (1+ (g x))) F [2]> (f 4) *** - EVAL: undefined function G The following restarts are available: USE-VALUE :R1 Input a value to be used instead of (FDEFINITION 'G). RETRY :R2 Retry STORE-VALUE :R3 Input a new value for (FDEFINITION 'G). ABORT :R4 Abort main loop Break 1 [3]> :r3 New (FDEFINITION 'G)> (lambda (x) (* x 2)) ;; Now that we gave an fdefinition for G, our (f 4) call can continue, so it ;; resumes execution and completes. Until now, it was just paused--no stack ;; unwinding unless we ask for it. 9 [4]> (g 10) ;; Because we used STORE-VALUE, it went ahead and saved the value we gave in ;; G for future use. If we had used USE-VALUE, it would have finished the (f ;; 4) call using that definition, but G still wouldn't be fbound after. 20 > lists mindset is different from mutable arrays Mutable arrays are ubiquitous in Lisp. Explicitly cdring down lists is mostly only done in introductory textbooks; in practice, most people will use MAP, REDUCE, REMOVE-IF-NOT, etc instead, which all work just as well on arrays or lists, or they might use an imperative construct like DO, LOOP, or ITER (also note that conses are mutable as well; it's not at all unusual to setf a car or cdr or call NCONC). It's not terribly different from what you would do in eg modern Java (aside from the part where none of it requires special support from the implementation and it could all be implemented in user code). I would also add that learning Lisp will teach you a lot about object-oriented programming. Even things that Java programmers use extensions for and give names like aspect-oriented programming just come built in as part of Lisp's stock object system. But then, Lisp's stock object system is also extremely flexible, especially given the pseudo-standard metaobject protocol. Quoting from Wikipedia about the MOP book: "In his 1997 talk at OOPSLA, Alan Kay called [The Art of the Metaobject Protocol] "the best book anybody's written in ten years", and contended that it contained "some of the most profound insights, and the most practical insights about OOP", but was dismayed that it was written in a highly Lisp-centric and CLOS-specific fashion, calling it "a hard book for most people to read; if you don't know the Lisp culture, it's very hard to read"."
- flavio81 9y agoIt is one of the very few languages where the source code is made of a data structure that the language is very good at manipulating. Thus, writing code that generates code, be it at runtime or at compile-time, is downright easy in Lisp. This opens up enormous possibilities not found in other languages. Also, on regular programming languages, your code executes only at run time. In Lisp, or at least in Common Lisp (and probably on Scheme as well), there are three times: Read time, Compile time, and Run time, and your code can selectively run at one of those three. This also opens up lots of possibilities. Another feature is that it is really suitable to interactive development in a way that isn't matched by any other language except for Smalltalk. It allows, for example, changing the definition of a function while your code is running. Now, two features that are particular to some Lisps: Scheme has continuations. Continuations are like magic teleportation within your code. They are very powerful. Common Lisp has the Common Lisp Object System (CLOS), possibly the most powerful OOP system out there. It rocks!
- Slackwise 9y agoWhenever I want someone to understand Lisp being a homoiconic metaprogramming language, I link them this: http://www.defmacro.org/ramblings/lisp.html http://www.defmacro.org/ramblings/lisp.html
- flavio81 9y agoThat's a great link!
- geokon 9y agomaybe someone can help me understand. I now get homoiconisity but the example he uses doesn't seem to explain why the macro is needed. He explains a problem that can be solved by writing a function. Instead he presents what seems to be in effect an unevaluated function... so what's the point?
- yorwba 9y agoI agree that the macro example is not chosen well. Macros are just functions that take their arguments unevaluated and output code, so each macro call could be replaced by a function call where the arguments are wrapped in a list and the function executes the code directly instead of generating it. Then the only reason you'd have to use macros is if you want to do something at compile time. Like generating specialized code so the compiler can optimize it, instead of reinterpreting the describing data on each invocation. Or like reading the database schema to generate accessors.
- dreamcompiler 9y agoDo you like Python? Python is basically simplified Lisp. Common Lisp is Python plus first-class lexical closures (rather than second-class) plus true multithreading plus a real compiler so it runs much faster. Plus parentheses rather than indentation to delimit expressions; parentheses are much more versatile once you get used to them.
- reikonomusha 9y agoPython and Common Lisp are pretty wildly different in almost every social, technological, and philosophical sense.
- flavio81 9y agoYep! This video was awesome, and entertaining as well, Mr. Tarballs-are-good/Symbol1cs/Stylewarning ("stylewarning" as a twitter ID made me ROFL). In particular, the comparison between calligraphy and Lisp programming was a very good one. I've sent you a LinkedIn request, by the way. I'm the bald one in business suit.
- flavio81 9y ago>Do you like Python? Python is basically simplified Lisp. Common Lisp is Python I am very experienced and proficient with Python. Common Lisp goes way, way beyond what Python brings to the table. Take CLOS for example and compare it with Python's OOP facilities. CLOS is light years ahead. Another differences (among many): Python is a high-level language. In CL, you can be high level and low level at the same time. For example, in CL you can disassemble your code to machine language and apply optimization directives and declarations to produce the shortest code, which can approach C speeds if done right. That said, I still like Python a lot. >Python is basically simplified Lisp. ... and I thank you for this phrase, perhaps I can use it whenever I need to justify my usage of Common Lisp at my workplace.
- pjmlp 9y agoThe sad part is that Ruby and Python could have taken some lessons from Lisp, how to have a dynamic language that has a good toolchain to generate native code. Thankfully we have now Julia, as yet another Algol-Lisp attempt.
- vbuwivbiu 9y agoit takes like 3 minutes to learn lisp
- tasty_freeze 9y agoIt takes three minutes to learn the rules of the game go. Of course it takes years of concerted effort for a human to know how to play it well.