10 ms·
This is my hang up with Lisps over and over again. I read through SICP and did almost all of the exercises. I've played with Clojure and done some small project
by city41 14y ago
This is my hang up with Lisps over and over again. I read through SICP and did almost all of the exercises. I've played with Clojure and done some small projects in it. I've recently started dabbling in ClojureScript. And I just can't seem to get to the point where Lisp becomes readable and quickly parsable by my brain. That snippet of Python you wrote is immensely more readable than the Lisp in the article. The equivalent snippet in Ruby, JavaScript, C#, Haskell, whatever, would also be immensely more readable than Lisps.
Does it just take some serious perseverance? Or am I just Lisp-dumb?
- orthecreedence 14y agoIt seems some people are able to read it, some people aren't. I made it a personal goal a few years back to learn Common Lisp, and while the first month after I started learning was hard, I've never really looked back since then. If I was to go back before that point, I'm sure I would find most languages more readable than lisp, but now that I know it fairly well, the syntax/parens don't bother me at all. I can parse it really easily with a passing glance. Maybe it's just a matter of experience. In the end, a language is a language...if you don't like one, you can use another. I happen to love lisp, but it's a personal choice, and I can understand why people wouldn't like the syntax.
- meric 14y agoDid you also learn emacs in parallel with Common Lisp?
- orthecreedence 14y agoNo, I was learning Vim at the exact same time, so ended up using Slimv (vim equivalent of Slime). I think in my entire life, I've spent about 10 minutes in emacs. Not because I don't like it, but more so because I never took the time to sit down and learn.
- eksith 14y agoNope, you're not. Readability is crucial for those of us not wired the same way as those who seem to be more comfortable in Lisp. Can you get a lot done in Lisp? Sure, if you can scan through and make sense of it. I've tried for a long time, almost to the point of barging in on my work time, but I haven't been able to get comfortable. The innumerable parentheses, for example, make perfect sense to those with the Lisp brain, but since I'm reading it in the context of English, where too many of those are frowned upon, it's nearly impossible for me to follow quickly. Whenever I bring this up among my colleagues, I get shot down by the proficient folks. The argument then turns into how I'm deficient somehow or haven't tried hard enough -- the word "stupid" came up a few times -- and that just completely turned me off the language. Religion is a touchy subject.
- ScottBurson 14y agoThere's no excuse for people calling you stupid. But see orthecreedence's post. It can be learned with practice.
- eksith 14y agoThank you. I should make it clear that I'm still on OK terms with those people. It wasn't so much a direct "you're stupid" or else I wouldn't speak to them again, but more of a "that's just stupid that you can't get it". Which I guess is a long about way of saying almost the same thing, but I think they held back. I can try to do something with it again if I have time, but I feel it's going to be a long and laborious process before I start to get comfortable. I used to unconsciously put semicolons ;)
- tensor 14y agoInterestingly, I now unconsciously do this switching back to C: (printf "%d" i) Before I forget and switch back. I strongly suspect that the people who can't adapt are having difficulty because they are not programming with the new syntax full time. Practicing at night while the majority of your time is still spent with some other language is not the same thing. This is also true for learning human language and is why immersion programs are so successful. Further, I absolutely do not buy the claims that people have that they can understand haskell easily but not lisp. Haskell might look more familiar at a casual glance, but its syntax takes a substantial amount of time to really understand.
- btilly 14y agoHere is my theory. When we read code, we use our language abilities. Our ability to read syntax uses some sort of built in grammar recognition, which has a maximum capacity that it can handle and doesn't abstract well. Thus in "normal" programming languages a certain amount of flow of control is pushed into syntax and grammar, and the offloading of that work makes it easier. Lisp goes the opposite way. There is pretty much no syntax, thus all flow of control is automatically pushed to your higher reasoning area, which suddenly does a lot more work and you notice it. Thus it feels like more work. The tradeoff is that everything is more flexible and easier to build abstractions on. But after you have programmed enough Lisp, the "flow of control" key words get wired properly into your grammar processing, and you stop noticing the effort again. But it takes longer for your brain to start processing things this way. Something similar happens in normal language. The same grammar areas of the brain pay attention to pauses, speech emphasis, and so on. Which in written form we notice as punctuation. But it is also wired to pick up and process small connective words like and, not, or, etc. Note, I have no evidence for my theory other than "it makes sense to me". However it is based on my limited knowledge of how brains process speech, which we have learned about because of the fact that when strokes take out specific areas of speech, we wind up with specific speech impediments.
- stan_rogers 14y agoIt's not so much that Lisp has no grammar, but that it's a VSO language (or it has the tail-first/head-final parameter set, if you prefer), where infix programming languages more closely resemble the SVO natural languages most of us in Europe or North America are used to. I'm sure that something more "normal" like Python, C, Pascal or BASIC would be as hard for uninitiated speakers of verb-first languages to wrap their heads around.
- bdr 14y agoThat's a fair point, but it's a different point than the one btilly is making. (I'm not trying to be rude, I just think btilly's theory is interesting enough to merit some defense.) Consider the formal grammar that might be used to implement a programming language. When we use the word 'grammar' here, it's obvious that Lisp has less of it than, say, Python. It's roughly equivalent to saying that Lisp has less syntax. So, his argument is independent of any VSO/SVO distinction. Ben is arguing that Python's additional syntax, by formalizing common structures, allows us to (in some sense) externalize the inherent complexity of a problem (i.e. out of our brain). The downside is that it introduces some rigidity into the language. Lisp makes a different tradeoff: we are forced to handle all of the complexity ourselves, but in return the language is flexible enough that we can build exactly the right abstractions for our problem. There's a kind of conservation law.
- snprbob86 14y agoThrough the lens of this example, Lisp does not offer any advantage. In fact, I'd argue, that Python, Ruby, JavaScript, C#, and even Haskell are simply explorations of this example, and others like it, with intentional ignorance of some of the other advantages Lisp offers. The one thing that all those languages drop from Lisp is Homoiconicy [1]. There are entire other categories of "Eureka Moments" that you can experience with Lisp through the lens of homoiconicy. This is at the heart of the utility of Macros, but macros can exist without homoiconicy and there are other benefits besides easier macros. What makes Clojure, in particular, interesting is that it's Homoiconic in terms of more than just sequences: There's also maps, sets, etc. Common Lisp & Scheme encode maps, sets, etc in terms of lists. If you're having a hard time seeing past the syntax (or a lack thereof), I suggest exploring Mathematica. Download the demo [2]. The Homoiconic parts of Mathematica are hidden behind more traditional syntax. Use the FullForm[...] function to see the Lispiness leak through. I suggest exploring the Rules & Patterns documentation [3] to get a feel for a non-macro approach to homoiconic transformations. Rules & Patterns makeup a rewrite system, which are strictly more complex than macro systems, but often easier to grasp during initial exposure. [1] http://c2.com/cgi/wiki?HomoiconicLanguages http://c2.com/cgi/wiki?HomoiconicLanguages [2] http://www.wolfram.com/mathematica/trial/ http://www.wolfram.com/mathematica/trial/ [3] http://reference.wolfram.com/mathematica/guide/RulesAndPatterns.html http://reference.wolfram.com/mathematica/guide/RulesAndPatte...
- emiljbs 14y ago>Common Lisp & Scheme encode maps, sets, etc in terms of lists. What do you mean by this? You do know that I can write some reader macros to get the same syntactic sugar for dictionaries and vectors as in Clojure, right?
- snprbob86 14y agoOf course you can, but almost no one does. If people started to do it a lot, it would be just as interesting as it is with Clojure.
- marssaxman 14y agoI have a similar experience, but it applies to Haskell, too. I understand functional programming just fine, but I can't read the source code at all. I can slowly grind my way through a snippet and work out what it means, but I can't read it. I wonder whether this experience has anything to do with one's comfort reading mathematical notation - I basically can't, and skip over all the formulas when I'm reading a paper. It's at least 100x easier to just infer the principle from a working example.
- neutronicus 14y agoI get a distinctly Perl-esque vibe whenever I try to read Haskell. So many pieces of type-system plumbing with non-alphanumeric names and uncertain precedence.
- papsosouid 14y agoWhat is the deal with haskell? It seems it has some sort of weird property where it causes seemingly rational people to invent crazy nonsense whenever they talk about it. I can't even imagine what type system "plumbing" would be, or how having a type system would make code harder to read. Would you mind providing an example so I know what you mean?
- neutronicus 14y ago'<*>', '>>=', '=<<', '>>>' off the top of my head. The first has something to do with Functors, the second two something to do with Monads, and the last something to do with Arrows, and I have no idea what their precedence is. The first three all more or less solve the problem of "use a function I'd normally use on values of type `a` on values of type `m a`, where `m` is a Monad or a Functor. The reasons this stuff makes code hard to read (for me) are: 1. They're all infix and I don't know the precedence. 2. It's not restricted to standard-library code. Oftentimes, learning a new Haskell library involves figuring out which part of the infix line-noise namespace it's staked out for itself.
- 14y ago
- protomyth 14y ago> Does it just take some serious perseverance? Or am I just Lisp-dumb? I've had the same difficulty with Lisp, but I can read Forth and Postscript (another postfix language) easily. I am really not sure what that says about how brains get wired other than I encountered both postfix languages early in my career.
- postfuturist 14y agoPerseverence. Time and exposure is all you need. Eventually you will be comfortable with it. I know I am, and it probably took about a year.
- 23david 14y agoA year! How did you have the patience to plod on for that long?
- bdunbar 14y agoTime flies when you're having fun? Maybe we don't realize how long it takes to acquire a new skill. If someone had told me it would take a year to just become comfortable with emacs, I would never have picked it up. I already have sublime installed, and textmate! But I picked it up because I respected people I knew who were wielding with great skill, and I wanted to try org-mode for TODO lists. I'm glad I did.
- pistacchioso 14y agoMy personal "wow" moment with Lisp was this: (+ 1 2) I was thrilled in the moment when I realized that all of the three parts of this banal form can be an arbitrarily complex forms themselves. For example, you can in place substitute "+" with a long code that contacts a web service and in the end, after 100 lines of code, returns "+". This 100 line function is made of forms made of forms made of forms and each can be replaced by the code that you might need. It's the beauty of the conciseness of the ternary operator in other language (a = b? 1 : 2) taken to a possibly infinite extreme. This can sometimes be achieved in other languages with the use of temporary variables, one-shot functions if the language doesn't have lambdas (or multi-line lambdas like Python) and in the end litter your soul with the use of "eval" This also leads to the other wow moment, when using Lisp makes it appear other languages' syntax so inelegant and cumbersome. At its core everything in Lisp is just like this: (FUNCTION argument1 argument2 …) When it clicks, it really hits you with the beauty of its perfect mathematical purity and you wonder how can you feel so comfortable with the average C-like language, where for has a syntax that is different from while, switch case is a beast of its own, sometimes you use curly brackets, sometimes square, sometimes regular or even angular, you don't have to forget commas and semicolons, you use colons and dots and question marks and myriads of keywords each with its own syntax and some things are functions and other operators and equal means something different from the double equals and so on.
- neutronicus 14y agoHaving access to the compiler at run-time is really neat.
- city41 14y agoBut I'd argue `case` in Lisp does have different syntax from `if`. They are built out of the same primitives, but you have to know how to compose those primitives. It's much like saying all functions are the same, but in reality you need to know the arity, order of parameters, etc before calling a function. To me, Lisp often felt like if the English language only had commas for punctuation. We then formulated all possible scenarios out of words and commas. Sure it's simple, easy for a computer to parse, etc, but it off loads a lot of work onto us as we read. I'm also reminded of when I took a typography class in art school. My professor was adament about typography not being "grey". He really wanted us to use weight, contrast, spacing, to create and enforce a hierarchy within our typography which would guide and aid the reader. I'd argue Lisp is completely "grey", while other languages are not. Don't get me wrong, this thread has been a great read and I've gained new respect from Lisp from it. I'm inspired to give it another go.
- grannyg00se 14y agoYou crushed SICP and still aren't extremely comfortable with LISPs? That's worrisome. I'm in the process of working through SICP and hoping that there will be some kind of fundamental change in the way I think about code.
- momo-reina 14y agoi can tell you that after going through only a few chapters of SICP, it radically changed the way i wrote code. i took the MITx 6.00X programming course after and was incredibly uncomfortable at using destructive methods (to give an exmaple), even though i used to write and think code in that way.
- dxbydt 14y ago>Python..is immensely more readable than..Lisp fwiw, it is immensely easier to build a parser for (= z (+ y x)) than for z=x+y you might ask, why should that matter ? Ad outside the eyeglass store: why do we have ears ? so we can wear spectacles! The point being, we first evolved as creatures with ears and later on devised spectacles so we could wear them over the ears. But we've now taken the ears so much for granted we think of spectacles as the innovation! Parsing should have been the whole point, but we now prize readability. We then add fluffy monikers like "serious perseverance" and "Lisp dumbness" to further tilt the balance in our favor. http://briancarper.net/blog/442/lisp-syntax-doesnt-suck http://briancarper.net/blog/442/lisp-syntax-doesnt-suck
- CJefferson 14y agoWhy would I need to write a python, or lisp, parser myself from scratch?
- ataggart 14y agoYou might not want to write parser from scratch, but you might want a new syntactic abstraction, and that usually requires a language change. For example, Python's "with" statement. If Clojure did not already provide the analogous `with-open` macro, you could create it yourself.
- dxbydt 14y agoIt isn't about writing Lisp parsers so much as about writing a parser for your particular language that solves your particular problem. Instead of writing a python program that plays minesweeper, you write a minesweeper language where minefield, detonate, mine, digit, grid are keywords in some sense, where minesweeping can be explained in terms of your minesweeper language itself, not in terms of python & variables & functions & all that. I will let the master explain - http://lib.store.yahoo.net/lib/paulgraham/onlisp.pdf http://lib.store.yahoo.net/lib/paulgraham/onlisp.pdf Read Section 1.2 - "Change the language to suit the problem. In Lisp, you don’t just write your program down toward the language, you also build the language up toward your program. Language and program evolve together. Like the border between two warring states, the boundary between language and program is drawn and redrawn, until eventually it comes to rest along the mountains and rivers, the natural frontiers of your problem. In the end your program will look as if the language had been designed for it. And when language and program fit one another well, you end up with code which is clear, small, and efficient. The greatest danger of Lisp is that it may spoil you. Once you’ve used Lisp for a while, you may become so sensitive to the fit between language and application that you won’t be able to go back to another language without always feeling that it doesn’t give you quite the flexibility you need.".
- orangethirty 14y agoIt took me perseverance. Not that I'm some Lisp god or anything, but I can sure follow 90% of it from reading it. It's like learning Japanese when all you know is English.
- cscurmudgeon 14y agoIt takes some time. You have not experienced Lispy syntactical nirvana yet. I was in your place when I started out. I kept on going. Now, even English seems artificially hard compared with s-expressions :D
- zosima 14y agoMost Lisps aren't so great with arithmetic. Afterall arithmetic notation has been refined through 100's of years to be readable and concise, and I've never seen anybody use prefix notation for operators voluntarily. But infix notation can be added easily: this is a quick'n dirty solution in Clojure with left associativity, no precedence and many gotchas. Incanter has a much better implementation called $= with less gotchas and many more features: (defmacro arith [& args] (letfn [(res [v] (cond (vector? v) (apply arith-body v) (list? v) (map res v) :else v)) (arith-body [s & args] (reduce (fn ([expr] expr) ([expr [op arg]] `(~op ~expr ~(res arg)))) (res s) (partition 2 args)))] (apply arith-body args))) (defn deriv [f] (let [dx 0.001] (fn [x] (arith (f [x + dx]) - (f x) / dx)))) ((deriv (fn [x] (arith x * x))) 3) Another common problem is the piping of results from one function to the next: (f (g (h a))) where you usually want to start reading the code in the lower rightmost corner and go upwards towards the left. Very messy in many lisps. Clojure has solved that problem with the threading macros, yielding postfix notation when you need it the most: (-> a h g f) Piping subresults between functions really doesn't get much better in any language. And that's of course some of the appeal of Lisp: The syntax may start controversial, but you can choose most of it yourself and make it depend on the problem, your tastes and of course, your readers.
- lispm 14y agoWell, Lisp has excellent arithmetic capabilities. Bignums, Floats, Ratios, Complex numbers built in. Infix notation is provided by macros or read macros. Infix notation is provided by math packages on top of Lisp: Macsyma, Reduce, Derive, Axiom, ... Those provide REAL extensive math syntax capabilities, not just what typical programming languages provide.
- zosima 14y agoSloppy me. I would of course be referring to arithmetic syntax or notation. And you make my point exactly: there is many ways to express arithmetically heavy operations in a natural, readable way.
- pkrishnakamal 14y agoHere's what I did. Be Naive about Lisp and its abilities. It's a simple list structure how expressive can it get. First understand the difference between a statement and an expression. I had a lot of procedural code hangover and it took me sometime to understand that difference. Lisp limits your expressive ability by a simple list structure, all you have is the ability to nest expressions. So, Lisp invariably lets you break down your ideas into small expressions. So when you read code, just look the operator at the beginning of each sub expression and you will understand the code. Trust me, its as simple as that. It sounds very easy but it took me over 6 months to understand that. You might argue lisp is the most expressive language ever. Its true, but for a beginner who is having trouble reading lisp code.. you should look at just the first element of a expression and its nested expression and you will get the idea.
- mosselman 14y agoI am with you on this. I wouldn't want to use this type of syntax. It obviously serves a different purpose to Java or Ruby though, it might have to do with a different mindset. I doubt that there is any syntactical advantage though. In the end it is just a matter of opinion.
- PySlice 14y agoI read more about Lisp than I program in it, and I feel just like you about the language. Everything looks the same. Some time ago I read that Common Lisp had multiple return values. I was expecting something like Lua, where a function like this: function fn() return 1, 2, 3 end Is called like this: a, b, c = fn() But in Lisp, it's just the same old (some-magic-words-here (other-things) (other-things)) Could I have some commas and equals signs to separate things at least? :-( Then I heard various Lisps have classes, structs, objects and what not. Does it look like this? { name: value, name: value } Or this? class Name { Type name; Type name; } No... It looks like this: (def-something ((something-here)) (something-else) (((something-else-2)))) If you are lucky you have a few :keywords or &keywords so your eyes have something to hang onto. Other than that, everything looks so... positional, and a closing parenthesis could mean anything from the end of a simple expression like (+ 1 1) or the end of the declarative part and the start of the executable part of a complex structure. You don't even need to go that far to find these problems: just look at: (let ((new-var-2 value) (new-var-2 value)) (some-code-here)) (if (condition) (runs-if-true) (runs-if-false)) You'd better use a very consistent indentation, because there is almost no visual separation between the "runs-if-true" and "runs-if-false"!