7 ms·
Lisp in 3 words
- dschiptsov 12y agoOh, I too have a few words about what a Lisp is. Remember that DNA structure - an aminoacid in the CAR and the next CONS in CDR?) Lets say that it is not a coincidence, given that the DNA structure was a host topic these days.) Guess where the Actor Model came from?)
- Lambdanaut 12y agoI don't like to be so negative without an objective reason, but that was really very rambling. I don't feel like I learned anything there. I don't doubt Lisp is beautiful, but I don't think the author explained it well.
- rthomas6 12y agoThey didn't. But I think I understood it anyway and can explain it to you. As a result of Lisp being in prefix notation, which is just a fancy way of saying you always put the action first (for instance you add numbers like (+ x y z)), that design choice results in EVERY part of the language having the same syntax. That is, everything is an action that eventually returns a value, and it all is used the same way. There are no special syntaxes -- loops, conditionals, function definitions, everything. Since it's all the same, everything all the way up to the top level is one action composed of other actions chained together. Parentheses in Lisp languages are used differently than other languages: parentheses are used for grouping and ordering in other languages, but in Lisps they're used to denote scope. The first word after an open paren is always an action, and every word thereafter is always an argument. Then arguments can be a lower level of scope which performs another action, and so on. So really, Lisp has almost no syntax at all, and a Lisp program is nothing but a big tree of actions that start at the top level and work down (sort of).
- pkaye 12y ago"Reverse polish notation" is postfix notation where the action is last. For example Postscript or Forth. Lisp is prefix notation where the action is first.
- rthomas6 12y agoOops, corrected. Thanks!
- agentultra 12y ago> So really, Lisp has almost no syntax at all, and a Lisp program is nothing but a big tree of actions that start at the top level and work down (sort of). I've heard of it described as, "programming in the AST." You don't have to think hard about how an expression will be interpreted. In fact you can get very far with just the substitution model of eval and apply as they started off with in the SICP lectures.
- tarentel 12y agoThat's usually how I explain it to people if I know they've taken a compiler class or know about ASTs. If not I'll usually explain Lisp as a language having no order of operation rules because it's syntax are the rules.
- thomaskrauss 12y agoI'm really sorry to hear my article has wasted your time. You are right, it was rambling. I'm kind of like that and it just surfaces, no matter how hard I try to behave! Basically, rthomas6 explained it better. But may you allow me to rephrase myself, as a complement as much as an excuse? There are 3 points. The first says that Lisp is simple because once you know how to write function calls in classic language (like C, Java, Javascript...), you have all you need to write Lisp code. And really any Lisp code, not just function calls in Lisp. The second point was that more classic languages go not just one but many different syntax routes while one is good enough to code. Concretely, for a whole month I was thinking first as writing Java code and then translating it mentally into Lisp. Until I reached enough confidence to let that go and just code in Lisp. When I did that, everything fell apart. Except for one rule: write chainable action perimeters. It is enough, no matter how astonishing it may seem. The last point was not much about saying that Lisp is beautiful. If anything, I find it elegant but not quite beautiful. No, the last point was about saying it is enough to look at Lisp for 5 minutes and then you are good to go. Both ways really. Use it right away, totally possible. Go away from it, entirely reasonable too. Just know that not much other language can maintain such a degree of decency because they generally claim more of your time right at the beginning while also having the nerve to give less. In short, I'm saying Lisp is nothing special. In particular, it hasn't the ability to illuminate your own programming practice. I'm just saying that from my own particular experience, it does have illuminated my practice because of the other languages. Lisp has not made me step forward because of what it is in itself. It made me step forward because every other programming languages I practiced have made me walk backwards.
- nutate 12y agowait, parameter, perimeter
- JeremyReimer 12y agoI feel like I understand what the author is trying to say, because I remember feeling that "click" in my head when I finally understood why LISP syntax was the way it was, and why it was the best possible syntax. (It was at the same time that I realized that RPN was the best possible mathematical syntax, if that makes any sense). It's hard to explain this to other people, however. It's doubly hard trying to explain it to people who have spent their careers building up high levels of skill and knowledge in other languages. I'm not a professional coder-- I'm a hobbyist. I can program badly in many different languages. But I find that with LISP, I am much more productive and happier. I feel like I can "punch above my weight" using LISP, achieving things that would take a lot more skill and effort to do in other languages. I sometimes wish I could explain it better to other people, but other times I'm just happy to work on my own in my "obscure" language with the all the silly parentheses.
- vanderZwan 12y agoI hear you. I've recently enlisted to a course in program design on coursera[1] as a quick and easy entry to Racket (I've been hobby programming for years) and it struck me how consistent the syntax is, and how little explanation it needed beyond the first few videos on how evaluation works. Is there something as easy and small as Processing[2] in LISP form? Because the biggest criticism of Processing is also it's strength: download it, run it, and you have notepad with a compile-and-run button. You need something as un-intimidating as that for beginners of non-technical backgrounds. That's part of why we're using it as the first language in our design programme in Malmö University (apart from the fact that it's also a gateway language into Java proper, which is a useful language to become familiar with because of its widespread adoption). EDIT: Here's a short blog post comparing the two languages and IDEs: http://www.hive76.org/processing-and-racket http://www.hive76.org/processing-and-racket [1] https://www.coursera.org/course/programdesign https://www.coursera.org/course/programdesign [2] https://processing.org/ https://processing.org/
- moron4hire 12y agoHeh, wow, I actually wrote that blog post. That's kind of a weird feeling :) That post led to a big discussion on the Racket mailing list. And the suggestion for this came up: http://www.pawfal.org/fluxus/ http://www.pawfal.org/fluxus/ A 3D game engine for livecoding worlds into existence. Fluxus is a rapid prototyping, playing and learning environment for 3D graphics, sound and games. Extends the Racket language with graphical commands and can be used within it’s own livecoding environment or from within the DrRacket IDE. I've not used Fluxus, but I think this is probably the closest thing to what you want. There is the Turtle graphics API that comes with Racket, but it's not really meant for animation.
- javajosh 12y agoGood piece. There's an even deeper truth about applications - that they are defined by a relatively small set of top level function evaluations, called asynchronously. If you're into pure functions, you can manage all mutable state in one place. Much of the incidental complexity of real software comes from misunderstanding this, just as much of the real complexity comes from the problem of maintaining a big, distributed, mutable state.
- moron4hire 12y agoI would have said, "Mother flipping macros." I think, historically, it's the closest reason to why Lisp stuck with S-Expressions, rather than continuing to develop M-Expressions, as was originally the plan. Homoiconicity makes it easier to develop more advanced macro facilities than in, for example, C. Once we got to see just how powerful macro programming could be, the S-Expression syntax was here to stay.
- cgag 12y ago"code is data" is the traditional incantation
- baddox 12y agoAnd you don't even need three words, just "homoiconicity."
- smacktoward 12y agoThere is definitely something quite Lispy about responding to the question "What is Lisp?" with the word "homoiconicity" and then waiting for the person who asked to figure out what that actually means.
- thomaskrauss 12y agoThe problem I had with "code is data" or "homoiconicity" is that they didn't really help me to code in Lisp. Although they were obviously big, mouth-watering hints that something is there! :) From an operative point of view, I think "chainable action perimeters" delivers more. Also, both "code is data" and "homoiconicity" are notions that ends up showing concretely in macros. And the conflict with the notion of "chainable action perimeters" is twofold but always harmful to properly operate as a programmer. First, we don't deal directly with the true results of macros, which are codes. We let the evaluator compute theses codes internally and it then automatically chains with a call to... itself! So yes, it can be said one can teach the evaluator new tricks but the infrastructure enabling that and justifying the expressions "code is data" and "homoiconicity" feels a bit too much like a three-card trick to me. The fact what seems the best advice on how to use macros is to not use them when functions would do appears to be, I think, another thumbs-up for the expression "chainable action perimeters".
- spacemanmatt 12y agoHe had me at "Escaping this text violence"
- jeffreyrogers 12y agoBefore I ask my question, I'm going to preface it by saying that it is not intended as a criticism of anyone's favorite language, but something I'm genuinely curious about. Here's the question: what substantial pieces of software are written in a functional style (lisp or otherwise). I'm curious because I've used functional languages in the past and even written some fairly substantial projects in one of them (a toy compiler written in Ocaml), however, I've never left with the impression that they are superior to other languages. In my experience functional languages give you some convenience with doing functional things while making lots of other things slightly more difficult.
- mhb 12y agoITA (used by Orbitz) - Lisp Jane Street seems to like OCaml - https://www.janestreet.com/technology/ https://www.janestreet.com/technology/
- sago 12y agoI'm a big fan of Lisps. I like the simple syntax. Scheme is my go-to tool for some jobs, particularly metaprogramming. And I use the syntax a lot for DSLs because it is so trivial to parse. But there is something to be said for using syntax as a way of representing meaning. Conditions, loops, function definitions, types, and so on, can be expressions (depending on the language, they may be fundamentally so), but having them look different, that reduces the interpretive burden, I think. Perhaps the bigger lesson of the OP is how few programmers understand how their language works. A case for people to write their own languages as part of a CS course, maybe? I can't remember who said that learning Lisp makes you a better programmer, even if you don't use it day to day. I strongly agree. It did that for me.
- Bognar 12y ago> Conditions, loops, function definitions, types, and so on, can be expressions (depending on the language, they may be fundamentally so), but having them look different, that reduces the interpretive burden, I think. I think this is a very important point. Since everything is the same in Lisp, it's nearly impossible to have an idea of what the program is doing "at a glance". In (sane) syntax heavy languages, you can glean a significant amount of information in a short period of time just by scanning the syntax without reading the code. This is less of an issue when writing a program, and more of an issue when maintaining one.
- thomaskrauss 12y agoI sure have a bit more problems maintaining Lisp code than writing it. But here I'm more comparing these two endeavors with one another while dealing with Lisp rather than comparing each one to the same endeavor in another language. Writing Lisp code is such a breeze that it is in fact unfair to compare other tasks to it. It's also a bit unfair to compare writing Lisp code to the task of writing code in many other languages. It is very true that in syntax heavy languages, scanning is made very efficient from the syntax of the code. And sure enough, with big chunks of Lisp code, scanning is a chore. But it is important to understand that scanning is an enabler or, in a more mathematical expression, it is a sufficient condition to make scanning a palatable option. But it is absolutely not a necessary condition. How? Lisp code is generally terse and split into several tiny functions. There are some exceptions of course and, based on my experience, there is no exception for such exceptions: they are all tedious to read. How tiny are the functions you may asked? Here's some stats about my project: It has 8368 lines of Lisp code for a total of 676 definitions (variables, functions, macros and some other things). The average ratio of lines of code required per definitions is thus 12.37! That is completely, absolutely way way less than code in C, Java or Javascript. You may say that I just have a lot of very tiny utilities in the range of, say, 3 to 5 lines of codes. While it's true in a way, the overall average holds well to about 12 lines of code even if you look at the level of code systems (rather than the whole project) or even at the level of files (rather than whole libraries). The point that I am trying to get across is that, while I agree there is a connection between having an idea of what the program is doing "at a glance" and gleaning information by scanning thanks to the syntax, this connection is certainly not forwarding any qualitative information about what a program is doing. I mean, from gleaning information from syntax to understand what a code does, nothing is passing that is remotely like 'this does that'. Syntax only guides your eyes. Scanning only allows to locate pieces of interest. But to know what a code does, you have to read it and there is no other way around. And that's the very purpose of my essay. I am like you. I think I know better what a program is doing when I have some syntax but it's only an illusion. Syntax has absolutely no meaning in itself about what is being done. I have to read the name of the actions and what is passed to them. And if I want to really know what is being done, I have to read it all. True, it's easier to read code with syntax guiding your eyes but when your code is only 12 lines, you can just read the whole very quickly and you know everything about it, not just the pieces you have gleaned. Syntax heavy languages make it easy to have a lot of information in a short amount of time but they make it more difficult to get the whole picture because they just spread code on so many lines with things less connected than in Lisp (two problems about that: statements do not return results and ask the programmer to do variable plumbing). At the present time, I think it's all a matter of taste because getting to know what is happening still requires quite some work regardless of the language involved and the more complex what a program should perform, the more code there will be to read. But Lisp has the edge here I think. Note that some of the various code systems I gave some stats about earlier are not trivial. One has two Lisp code parsers (one of them just gives the stats I exposed, the other one identifies dependencies): 1194 lines for 86 definitions thus a ratio of 13.88. Another one "full view debugs" code: 659 lines for 39 definitions thus a ratio of 16.9. Despite the goals these code systems tackle, they do not sky-rocket in their stats; every one of them stays very reasonable. And both projects bring much insights about the structure of the code and what is being done. Especially the latter. Full view debugging is about computing all intermediate results inside a given code and layout them all in the browser. It's like when one debugs by hand except that it is all done automatically and everything is here for you to see. In other words, you can scan and you do not get an idea of what the program is doing. You get what it is really doing. And because Lisp syntax is simple, that full view debugger works on any Lisp code (although of some of the most exotic actions, it does not go into them).
- devsaysstuff 12y agoLisp in 3 words - Too Many Brackets! Tomorrow Discussing Ruby - method missing, or missing method? Stay tuned for our weekly newsletter - Java and GC - if it really worked, it would collect and delete the whole JVM!
- thomaskrauss 12y agoIndeed, Lisp has too many brackets! However, how many different roles do they have apart from writing action perimeters? The answer is 0! And 0 times 10, or 100, or 1000 or well, just go for any number, it doesn't matter, that's still 0. Also, note that Lisp has only parentheses. While in the end, it is a matter of taste, I don't think one can disagree on the fact Lisp only has parentheses and they serve only one purpose. Other languages have in fact many roles for parentheses while also having brackets and many roles for them while also having curly braces and many roles for them.
- jaywunder 12y agoJust a question, does he mean "parameters" instead of "perimeters"?
- thomaskrauss 12y agoI really mean perimeters. An action perimeter returns a value. To perform its work, it needs parameters. That is: values. Some of these values can be written by hand, others need to be computed. In that latter case, you ask for a computation by writing an action perimeter. And there's no need for a special syntax to use the value that results in executing that perimeter. You just write it in the appropriate place, as a parameter. So in practice, you can chain perimeters with one another. Until you have expressed all the computations you wanted the computer to do.
- nutate 12y agoAccording to google you just made that up? I only see action perimeter in reference to expanding the perimeter of action of the coast guard in Canada. So like... how is an "action perimeter" different than a function? In which case you get the more succinct two words "chainable functions." After looking at the French version I see that "action perimeter" is from the french perimeter d'action (accents removed) which translates better in english (once again according to the interwebs) as: sphere of operations. http://dictionary.reverso.net/french-english/p%C3%A9rim%C3%A8tre%20d%27action http://dictionary.reverso.net/french-english/p%C3%A9rim%C3%A... Once again, I'd go so far as saying the concept of functions works just as well here, but at least it gets over the near homonym of parameter/perimeter. The chaining of scoped actions is pretty vital to lisp, and I suppose functional programming in general.
- thomaskrauss 12y agoI haven't read the notion of action perimeter phrased anywhere else. I just came up with it some years ago when I was trying my colleagues to give Lisp a go. An action perimeter is different from a function because, for instance, you can write (if <test> <then-clause> <else-clause>). For a function, all its arguments are evaluated first and then it is applied. That's certainly not the case for if since the whole point of a condition is to refrain from evaluating some code unless a condition is met. Hence, in Lisp, the simple notation encompasses and is fully operative on every action, including the ones that do not behave like functions. While in many language chaining perimeters is only about function calls. And in addition it is rarely idiomatic to chain function calls in such language. Thank you for pointing out the similarity between parameter and perimeter which borders on confusion. Thanks to everyone who brought it up to! It's clear that's an issue I overlooked. The reason is I use the term argument in English and in French, never parameter itself. But that's probably because once I realized the notion of a perimeter is important in Lisp, I stopped using the word 'parameter'. Sorry for that! I'll try to find a better term.