Live data from Hacker News

Why Lisp?

blog.rongarret.info

51–60 of 248 posts

Re: Why Lisp?

#51
post #30

I'm hacking on TXR these days which contains a Lisp dialect called TXR Lisp. Lisp hacking and research is fun, in particular if you have the freedom of your own dialect. The current public release TXR Lisp still has an embarrassingly shoddy implementation of "places": expressions which not only evaluate, but serve as assignable locations. I implemented most of the place-manipulating operators (set, inc, push, ...) as…

> The rlet macro [in the above code] is something I just invented days ago. This perfectly illustrates both the power and danger of Lisp; also known as “The Lisp Curse”¹ ① http://www.winestockwebdesign.com/Essays/Lisp_Curse.html

> The expressive power of Lisp has drawbacks. There is no such thing as a free lunch.

This line doesn't hold on its own but as the ending of the article it was very powerful.

I had heard that extra power can make it easier to do things wrong, but the idea that extra power can cause problems even when you do things right is fascinating.

Re: Why Lisp?

#52

Earlier quoted context omitted.

Could someone please explain the difference between Lisp macros and, say, languages that have first-class functions? I get that a Lisp macro will be expanded into the respective code, while a function's execution is different. However, at the practical (i.e., developer's) level, are there any additional benefits? Can, say, a Lisp macro be 'partially formed', in the sense that it can expand into some boilerplate that…

One difference is flow control. When you call a function, all the arguments are evaluated before being passed into the function. If you want to delay evaluation, you have to wrap the argument values in a function. When you call a macro, the text forms get passed with no evaluation. Say Clojure forgot to ship with the boolean "or". "or" should evaluate its arguments one at a time (to allow for short circuiting) and re…

I wonder how much macros are necessary one you add call-by-name parameters e.g. scala.

Re: Why Lisp?

#53

The article doesn't discuss macros, which is one of the answers to "Why Lisp?" I didn't "get" macros until I read a footnote in the (freely available) book Practical Common Lisp . In chapter 7, it introduces the `dolist` macro. DOLIST loops across the items of a list, executing the loop body with a variable holding the successive items of the list. This is the basic skeleton (leaving out some of the more esoteric opt…

Could someone please explain the difference between Lisp macros and, say, languages that have first-class functions? I get that a Lisp macro will be expanded into the respective code, while a function's execution is different. However, at the practical (i.e., developer's) level, are there any additional benefits? Can, say, a Lisp macro be 'partially formed', in the sense that it can expand into some boilerplate that…

A higher order function doesn't serve the same purpose as a macro. A higher order function is meant to be applied, called, composed etc. A lisp macro is a different type of abstraction. For example, many people think that macros are just hiding lambda's of higher order functions. This is wrong. A macro abstracts over implementation details of a construct to make it read naturally. For example, you can write a function that opens and then closes a file like so...

  with-open-file(filename, lambda file: do stuff with file)
but with a lisp macro, you only have to write

  with-open-file (filename):
     do stuff with file
The point of an abstraction is so you don't have to think about the implementation. Written like the latter, with-open-file is simply more natural to write this way. You only have to think, "oh, its a construct that opens a file then closes it after the body is done", rather than "oh, its a higher order function that i have to pass another function into that takes the file as an argument..." etc.

When you write with-open-file as a macro, it could be implemented as a higher order function, or it could be implemented as a low level set of GOTO statements. It doesn't matter. The macro abstracts away the low level detail, just providing the most natural way for you to use the construct. It might not seem like the macro is doing much in that particular example, but a construct that defines a class (like defclass) is something you can write as a macro, which can expand into functions that do the actual defining. You could write a class defining construct as a higher order function, but then you'd have to constantly worry about how your construct was implemented as a function. instead of just writing something natural like

  defclass tiger (animal):
    age init-value: 0
    name type: string
which you could write if you implemented defclass as a macro. otherwise, you'd have to do something crazy stupid like

  defclass(name='tiger', inherits-from = find-class('animal')
           slots=['age, name'] ...)
how could a higher order function possibly implement that without making people using it tear their hair out? They have to bend to the implementation, not make the abstraction bend to what's natural.

Re: Why Lisp?

#54

The article doesn't discuss macros, which is one of the answers to "Why Lisp?" I didn't "get" macros until I read a footnote in the (freely available) book Practical Common Lisp . In chapter 7, it introduces the `dolist` macro. DOLIST loops across the items of a list, executing the loop body with a variable holding the successive items of the list. This is the basic skeleton (leaving out some of the more esoteric opt…

Could someone please explain the difference between Lisp macros and, say, languages that have first-class functions? I get that a Lisp macro will be expanded into the respective code, while a function's execution is different. However, at the practical (i.e., developer's) level, are there any additional benefits? Can, say, a Lisp macro be 'partially formed', in the sense that it can expand into some boilerplate that…

A higher order function doesn't serve the same purpose as a macro. A higher order function is meant to be applied, called, composed etc. A lisp macro is a different type of abstraction. For example, many people think that macros are just hiding lambda's of higher order functions. This is wrong. A macro abstracts over the detail. For example, you can write a function that opens and then closes a file like so...

with-open-file(filename, lambda file: do stuff with file) but with a lisp macro, you only have to write with-open-file filename:

Re: Why Lisp?

#55

The article doesn't discuss macros, which is one of the answers to "Why Lisp?" I didn't "get" macros until I read a footnote in the (freely available) book Practical Common Lisp . In chapter 7, it introduces the `dolist` macro. DOLIST loops across the items of a list, executing the loop body with a variable holding the successive items of the list. This is the basic skeleton (leaving out some of the more esoteric opt…

On the other hand, this really hurts readability. When reading other people's code you now effectively have to learn what "language" they use too. I'd say it's probably worth that cost, if used judiciously.

>When reading other people's code you now effectively have to learn what "language" they use too

And? This is true of code in languages without macros, too. You have too learn all the vocabulary, all the types they use, all the functions, all the structure of the program— macros are just a tool for taking these domain-specific things and packing them into a denser syntactic abstraction. A well-written macro improves readability in both the short and long terms.

I mean, say I write a couple of macros to deal with a database and I write code like

    (with-sql-connection ("localhost" ...)
      (select *
         from  "customers"
         where (= "lastname" "Smith")))
Do you really think that's less readable than the nonsense you'd have to write a typical "framework," or worse, building the command string by hand?

Re: Why Lisp?

#56
post #27

Earlier quoted context omitted.

Clozure CL is easy to install/run on just about any desktop platform (windows included). On *nix, SBCL is a good choice. I've heard good things about MOCL but haven't tried it myself, and I know getting ECL working on mobile is an uphill battle (but achievable if you have the time). ECL switched maintainers recently, so maybe mobile is something they will focus on in the future.

The only downside to Clozure CL that I found was the fact that it requires SSE2 instruction support from the processor. There are still some processors around that don't support that -- which can be a bummer if you want to use Clozure CL on one of those machines. Unfortunately, one doesn't always have the option of upgrading the hardware to get around that. I don't think the developers have worked around that, though…

Another issue I've had is that you can't use 32-bit libraries from a 64-bit image, even with a multilib (in linux or windows). In other words, if your DLLs/SOs are 32bit, you have to use the 32bit CCL executable.

That's not usually a showstopper for me, though.

Re: Why Lisp?

#57
post #45

Earlier quoted context omitted.

It would help if I saw a real world problem and how you can solve it Lisp and not in say Python.

The best you'll get are examples of something solvable in Python being "beautiful" in Lisp. Then some real world Lisp examples will be references to a 20 year old storefront generator and the initial release of reddit. Lisp(s) are certainly better than Python in every way, except when it comes to successful projects completed.

I think you need a bigger reference frame of Lisp's usage over its 50 year history that extends even to 2015. But even then, quoting Kent Pitman: "Please don't assume Lisp is only useful for Animation and Graphics, AI, Bioinformatics, B2B and E-Commerce, Data Mining, EDA/Semiconductor applications, Expert Systems, Finance, Intelligent Agents, Knowledge Management, Mechanical CAD, Modeling and Simulation, Natural Language, Optimization, Research, Risk Analysis, Scheduling, Telecom, and Web Authoring just because these are the only things they happened to list." (My additions are video games and Mars rovers.)

Re: Why Lisp?

#58

The article doesn't discuss macros, which is one of the answers to "Why Lisp?" I didn't "get" macros until I read a footnote in the (freely available) book Practical Common Lisp . In chapter 7, it introduces the `dolist` macro. DOLIST loops across the items of a list, executing the loop body with a variable holding the successive items of the list. This is the basic skeleton (leaving out some of the more esoteric opt…

On the other hand, this really hurts readability. When reading other people's code you now effectively have to learn what "language" they use too. I'd say it's probably worth that cost, if used judiciously.

    When reading other people's code you now effectively
    have to learn what "language" they use too.
That's well said, and in fact it's not uncommon to talk about Lisp's capacity for crafting the language to solve the problem at hand.

Paul Graham's essay "Programming Bottom-Up" explains it really really well:

"Experienced Lisp programmers divide up their programs differently. As well as top-down design, they follow a principle which could be called bottom-up design-- changing 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. As you're writing a program you may think 'I wish Lisp had such-and-such an operator.' So you go and write it. Afterward you realize that using the new operator would simplify the design of another part of the program, and so on. 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."

http://www.paulgraham.com/progbot.html

    On the other hand, this really hurts readability.
As others have pointed out, no more than unfamiliar classes and so forth.

In any language, you can think of programming as building mini languages to solve problems. You have nouns and verbs - types/classes/instances and methods/functions/operators. Lisp gives you those parts of speech and also lets you manipulate the fundamental grammar as well!

Re: Why Lisp?

#59
post #2

> The act of describing what you want the machine to do is interleaved with the machine actually doing what you have described, observing the results, and then changing the description of what you want the machine to do based on those observations. That sounds really powerful and interesting, but wondering how often is that used in practice? I can imagine maintaining and understanding a large self-modifying program l…

I think he's describing interactive programming, not necessarily self-modifying programs. With that said, yes interactive programming is incredibly useful and I do it all the time. It really shines on apps with a lot of state (such as a game) where normally you'd have to quit, change the code, recompile, run the app, and reproduce the original state as closely as possible. With lisp you can just replace the function…

> I think he's describing interactive programming, not necessarily self-modifying programs. With that said, yes interactive programming is incredibly useful and I do it all the time

I do it too in python via ipython. Maybe what the author meant is "Why exploratory programming using a REPL is great".

Re: Why Lisp?

#60

Earlier quoted context omitted.

Could someone please explain the difference between Lisp macros and, say, languages that have first-class functions? I get that a Lisp macro will be expanded into the respective code, while a function's execution is different. However, at the practical (i.e., developer's) level, are there any additional benefits? Can, say, a Lisp macro be 'partially formed', in the sense that it can expand into some boilerplate that…

This is only ~90% likely to be correct, since it's second-hand information and I don't use LISP actively. A LISP macro is a syntax transformation. It lets you write code in the way you want to, instead of whatever level of abstraction you used to have. I'm not sure about 'partially formed' code output, but 'partially formed' input is definitely possible. The way to invoke a LISP macro need not be valid LISP. In short…

In my Lisp-esque language I use a temporary macro to automate the creation of some similar standard library procedures. This happens at runtime in the stdlib source file that is loaded:

    # Define procedures named int? float? etc that test the type of a value.

    (def def-type-predicate (mac (type-name)
         `(def ,(string-to-symbol (join "" $type-name "?"))
               (proc (x) (eq? (type x) ',type-name)))))
    (def-type-predicate int)
    (def-type-predicate float)
    (def-type-predicate bool)
    (def-type-predicate string)
    (def-type-predicate symbol)
    (def-type-predicate file)
    (def-type-predicate nil)
    (def-type-predicate pair)
    (def-type-predicate procedure)
    (def-type-predicate macro)
    (zap def-type-predicate)
The crucial thing about what happens there being that the (def foo? ...) value produced by each macro invocation then gets evaluated in the root/top-level environment and so results in a "global" procedure definition. Using them:

    (string? (add 2 2))
    => FALSE

    (float? 4.7)
    => TRUE

    (procedure? string?)
    => TRUE
I thought it was a nice contained example of "code writing code" in the data realm.
Post reply on HN