Live data from Hacker News

Why Lisp?

blog.rongarret.info

221–230 of 248 posts

Re: Why Lisp?

#221
post #203

Earlier quoted context omitted.

Part of the visibility issue is that there are very few big-name open source Common Lisp success stories which aren't CL implementations, or CL ecosystem tools. Most of the things in that list are big-ticket enterprisey applications.

There are a lot of CL open source tools and applications. But they tend to be specialized to domains which are exotic to many people. Math: Maxima and Axiom Blackboards: GBB Robots: ROS Music: OpenMusic Bioinformatics: Biobike Theorem Provers: ACL2, PVS AI / Logic: Racer, KM etc etc...

There's a lisp client for ROS, but also c++ and python clients (and others), it's not immediately clear what language the "core" is written in.

Re: Why Lisp?

#222
post #133
post #53

Earlier quoted context omitted.

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 functio…

Your point seems to be that macros allow for a slightly more natural syntax for certain things, but I can do pretty much the same thing in a language with a natural HOF syntax (Ruby): with_open_file filename do |f| do stuff with file end And for your second example: # our 'macro' function def defclass(name, parent, &blk) k = Class.new(parent) k.instance_eval(&blk) Kernel.const_set(name, k) end defclass :Tiger, Animal…

Notice that in your Ruby code you have to use quoted symbols like :Tiger and :age and :name, because you cannot extend Ruby's syntax with your own. Ruby has good metaprogramming facilities, but it's no substitute for a real macro system.

Re: Why Lisp?

#223

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.

Paul Graham addressed this in On Lisp (page 59) [0]:

>So yes, reading a bottom-up program requires one to understand all the new >operators defined by the author. But this will nearly always be less work than >having to understand all the code that would have been required without them. >If people complain that using utilities makes your code hard to read, they >probably don’t realize what the code would look like if you hadn’t used them.

>Bottom-up programming makes what would otherwise be a large program look >like a small, simple one. This can give the impression that the program doesn’t >do much, and should therefore be easy to read. When inexperienced readers look >closer and find that this isn’t so, they react with dismay.

>We find the same phenomenon in other fields: a well-designed machine may >have fewer parts, and yet look more complicated, because it is packed into a >smaller space. Bottom-up programs are conceptually denser. It may take an effort >to read them, but not as much as it would take if they hadn’t been written that way.

[0] http://www.paulgraham.com/onlisp.html

Re: Why Lisp?

#224
post #203

Earlier quoted context omitted.

There are a lot of CL open source tools and applications. But they tend to be specialized to domains which are exotic to many people. Math: Maxima and Axiom Blackboards: GBB Robots: ROS Music: OpenMusic Bioinformatics: Biobike Theorem Provers: ACL2, PVS AI / Logic: Racer, KM etc etc...

Exactly. Where's CL's Rails, or Eclipse, or Postgres?

Lisp's Eclipse is called GNU Emacs and it's free software. It comes with more than a million lines of Lisp code supporting all kinds of development tasks.

Re: Why Lisp?

#225
post #183

Earlier quoted context omitted.

Aren't macros breaking the homocionicity of the lisps? And making maintenance more difficult (aren't you re-inventing a new language with macros?)? Where does the "First rule of the macro club" coming from? When should you break it?

>maintenance If used right, macros make things much more maintainable. If you have a hundred nearly-identical codeblocks, where only (say) a string constant is varying, and suddenly you need to change what those blocks do, bam, you've got a hundred blocks to change. If those blocks had been refactored with a macro, all you have to do is change the macro once. It also prevents the new guy from coming and doing a banda…

Not a lisper, so bear with me please. Couldn't you do this with a function?

Re: Why Lisp?

#226

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…

Similar, similar, only if you don't look too closely: what about break and continue? They are usually supported by native foreach construct but are difficult to build with macros..

Re: Why Lisp?

#227
post #46

Earlier quoted context omitted.

Aren't macros breaking the homocionicity of the lisps? And making maintenance more difficult (aren't you re-inventing a new language with macros?)? Where does the "First rule of the macro club" coming from? When should you break it?

>Aren't macros breaking the homocionicity of the lisps? No. How would macros break homoiconicity? They expand into atoms and lists (and other datatypes), the same stuff of which macro-free programs are made. >And making maintenance more difficult? No. Unless you intentionally write unmaintainable macros. It's the same as if you write unmaintainable functions, classes, etc. They're just abstracting a different thing—…

I have heard the “first rule of the macro club” to be “don’t write macros”. The idea is before writing a macro, you should try writing it as a function instead. If that is possible, that is usually better, because functions, unlike macros, can be passed around as first-class values, and I think they are easier to debug.

You should break that rule only when the behavior can’t be written as a function, such as these cases:

• The call needs to avoid evaluating its arguments. For example, the `if` built into the language is sometimes defined as a macro.

    (if (= (+ 2 2) 4)
      (print "math works")
      (print "math is broken"))
If `if` were a function, it would first print both statements, and then return the return value of `print` in whichever branch. By making `if` a macro, it can avoid evaluating the branch that is inapplicable.

• The call relies on information about the environment only available at compile-time. Perhaps the macro reads a configuration file on the developer’s computer to decide how to set something up.

• You have profiled the program and determined that it is better to run the function at compile-time. For example, you might want to make `(regex "[a-z][a-z0-9]+")` compile the string to a regular expression at compile-time instead of run-time.

Re: Why Lisp?

#228
post #183

Earlier quoted context omitted.

>maintenance If used right, macros make things much more maintainable. If you have a hundred nearly-identical codeblocks, where only (say) a string constant is varying, and suddenly you need to change what those blocks do, bam, you've got a hundred blocks to change. If those blocks had been refactored with a macro, all you have to do is change the macro once. It also prevents the new guy from coming and doing a banda…

Not a lisper, so bear with me please. Couldn't you do this with a function?

Yes, you could do that with a function. I think that was a bad example.

I listed some situations where you need a macro in my comment that explains the “first rule of the macro club” you asked about: https://news.ycombinator.com/edit?id=9513988

Re: Why Lisp?

#229

(I have a subtle optimization for S-expression syntax)(I am surprised nobody ever thought of it)(When S-expressions are in a sequence use an extra (special) delimiter plus the regular token separator to separate expressions)(Maybe use dot? (period I think some call it)) Like so. I think it could catch on. And you get rid of so many round bracket block delimiters (at least for S-expressions on the same level. for nest…

So this code (from https://github.com/axch/test-manager/blob/c4fc3224e873716c58...)

    (define-record-type omap-entry
      (make-omap-entry key item next prev)
      omap-entry?
      (key omap-entry-key set-omap-entry-key!)
      (item omap-entry-item set-omap-entry-item!)
      (next omap-entry-next set-omap-entry-next!)
      (prev omap-entry-prev set-omap-entry-prev!))
would be written like this?

    (define-record-type omap-entry
      make-omap-entry key item next prev.
      omap-entry?,
      key omap-entry-key set-omap-entry-key!.
      item omap-entry-item set-omap-entry-item!.
      next omap-entry-next set-omap-entry-next!.
      prev omap-entry-prev set-omap-entry-prev!)
(To mark `omap-entry?` as being a value, not the S-expression `(omap-entry?)`, I decided to place a comma after it instead of a period. The alternative is requiring no punctuation and making newlines significant.)

Well, I suppose it does look better.

However, the idea is of limited applicability. While looking through the example project (https://github.com/axch/test-manager), I had trouble finding some code where this would actually be useful – most code has too much nesting.

That’s why I prefer another solution for removing excess parens from Lisp syntax: making whitespace significant. It improves the syntax in cases where your periods would help, and it applies in additional cases as well.

“Sweet-expressions” (http://readable.sourceforge.net/) is an implementation of that. Here is the above code ran through the `sweeten` tool to convert it to sweet-expressions:

    define-record-type
      omap-entry
      make-omap-entry key item next prev
      omap-entry?
      key omap-entry-key set-omap-entry-key!
      item omap-entry-item set-omap-entry-item!
      next omap-entry-next set-omap-entry-next!
      prev omap-entry-prev set-omap-entry-prev!
Absolutely no parentheses necessary, while still preserving homoiconicity. You don’t even have to remember the `)` at the end of the last nested line. And I chose this example code to look good with your idea – when the code has more nesting, sweet-expressions look even better.

About the interrogative mood `?` you describe: it might simplify `if` statements. But that would require removing the convention where boolean-returning functions have a name ending in `?`, such as `omap-entry?` in the example. It’s a tradeoff.

Re: Why Lisp?

#230
post #161

Earlier quoted context omitted.

One that helped some Java friends understand is passing blocks of code, but still having it look like just writing code. Imagine instead of try/catch/finally, a transaction/commit/rollback in Java: transaction { // everything in here is in one transaction } commit { // do stuff if the commit is successful } rollback { // do stuff if we rollback } All the try's and catch's can be stuff into the macro. It can be made t…

I find this argument pretty unconvincing too. >For all practical purposes, you can't add that to Java. You'll always have to wrap up your transactions in boilerplate. Aren't you wrapping the lisp code in boilerplate when doing the macro too? This appears to be the same as your other example. Java has lambda expressions (since Java 8) that could do this. If you are wrapping it in a macro, how is it different than wrap…

So there's some boilerplate that needs to happen. With macros, you write the macro to insert the boilerplate, and then you never think about it again. You don't write it, you don't read it, it's not in the way. Without macros, you have to write the boilerplate every time you write the code. You have to read the boilerplate every time you read the code.

Here's the version with macros:

    (transaction (do-stuff)
                 (do-stuff-if-commit-successful)
                 (do-stuff-if-rollback))
Here's the version without macros:

    (transaction (lambda () (do-stuff))
                 (lambda () (do-stuff-if-commit-successful))
                 (lambda () (do-stuff-if-rollback)))
Which do you find more readable? Notice how there's no boilerplate in the macro version.

> This appears to be the same as your other example. Java has lambda expressions (since Java 8) that could do this.

What are the odds that Java 8 has provided everything you could want in out of Java? Macros let you add things in a better way than you could otherwise get. Look back to my prior example of Java 5's expanded for. You see how useful that was? If Java had had macros, people wouldn't have had to suffer through nine years without the improved for loop.

Post reply on HN