Live data from Hacker News

Why Lisp?

blog.rongarret.info

111–120 of 248 posts

Re: Why Lisp?

#111

> The reason that code represented as XML or JSON looks horrible is not because representing code as data is a bad idea, but because XML and JSON are badly designed serialization formats. By that same token, a Volkswagen Beetle is a badly-designed boat. XML was never designed as a data serialization format. It's a markup language . It was designed to sprinkle structure and metadata into large human-readable plaintext…

> XML was never designed as a data serialization format. It's a markup language.

Those two things are not mutually exclusive.

> Likewise, JSON is a subset of a general-purpose programming language's literal notation that happened to be very fast to parse in a browser by virtue of the browser implementing that language.

That's true. That is not in conflict with anything I said.

> The problem is that there's no one-sized-fits-all for serialization.

No, that's not true. S-exprs really are a global optimum in the space of serialization designs. All the alternatives are logically equivalent to S-exprs but with extra punctuation that makes them arguably harder to read, but inarguably harder to write. That is why S-exprs are the ONLY syntax ever designed (some would say "discovered") by humans that has been successfully used to represent both code and data.

Re: Why Lisp?

#113

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…

It's true, as others have explained, that for many of the most common uses of macros, you can get the same effect with a higher-order function.

But since macros operate at the syntax level, they can do things functions can't do. For example, they can generate and manipulate declarations. Say you're working with abstract syntax trees (assembly trees in a CAD app might be another example). These trees are built from nodes, where each node is of some class corresponding to a syntactic construct: if-statement, addition-expression, etc. etc. There's some functionality you want to have on every node class; a common example is a "children" method that gathers up all the node's child slots into a set and returns it. It is very convenient to have a 'define-node-class' macro that automatically generates the 'children' method, so that when you add a child slot, the method is updated automatically; there's no need for manual effort to keep them in sync.

In this case, the macro is expanding to multiple top-level declarations: the class declaration along with the method declaration (probably, in practice, several methods). Higher-order functions don't begin to let you do stuff like this.

Re: Why Lisp?

#115

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…

I agree. Macros are what made lisp, not parentheses. However, if we broaden the concept a little, we can do this type of macros for any language with a meta-layer such as MyDef. e.g. if you observe certain foreach pattern in Java, you can make a macro for that pattern and have the meta-layer look out and translate that for you (like having an automatic translator between you and javac. All you need is a scope type ma…

    Macros are what made lisp, not parentheses.
The parentheses are huge, though. It enables "Code is data" and "Data is code" in a powerful way.

About Lisp, people always say "Macros are great" and "Code is data" and "Data is code", but it's hard to see what they mean without good examples. I mean, you can write code that writes code in any language that has a `print` statement. And obviously code is data, so what is that aside from some pseudo-philosophic BS?

There's a lot of discussion in this thread about macros - so here's an example of Code and Data Being One, for those that are unconvinced. I hope it'll shed some light.

I have a slang dictionary website. It's backed by a database now, but it used to be statically-generated HTML. I represented the data as XML. It looked something like this:

    
      
        
          impressive.
        
        
          smart.
        
      
    
So then I needed an XML parser to parse the data. Maybe it parsed the XML into a object model that the code would navigate and output the appropriate HTML. Or maybe the code got callbacks according to node type and would output the appropriate HTML then.

XML is a pretty verbose format, so - this being a Lisp example - we could probably save some typing if we represented the data as an S-expression. The above XML would become something like this:

    (Term "slick"
      (PartOfSpeech "adj"
        (Definition
          "impressive."
        )
        (Definition
          "smart."
        )
      )
    )
But that's an idiosyncratic style.

So, let's lowercase the node types, use hyphens rather than camelCase, and remove the unnecessary line breaks. Now the data looks like this:

    (term "slick"
      (part-of-speech "adj"
        (definition "impressive.")
        (definition "smart.")))
Great. We've got our data.

Now we need to write the Lisp code to convert that S-expression data into the appropriate HTML output.

We'll need some Lisp functions to handle the nodes and their attributes (such as the definition text and part of speech) and write the HTML for them. We could use an S-expression parser library to load the data, and then walk through it and call those functions. But that's not necessarily the best way. We can simplify it by creating exactly 3 functions that take some arguments and output HTML: term, part-of-speech, and definition.

Since Lisp code is - like the data - also represented as S-expressions, once we've written those 3 functions, the data is literally executable Lisp code.

Re: Why Lisp?

#116

> The reason that code represented as XML or JSON looks horrible is not because representing code as data is a bad idea, but because XML and JSON are badly designed serialization formats. By that same token, a Volkswagen Beetle is a badly-designed boat. XML was never designed as a data serialization format. It's a markup language . It was designed to sprinkle structure and metadata into large human-readable plaintext…

> What we value is brevity, but basic information theory tells we can only make expressing some things more terse by making others more verbose.

But the reverse is not necessarily true. It's possible for a badly-designed serialization format to be longer in all cases than some other format.

And, in particular, I suspect that for the same data, XML is longer in all cases than S expressions.

Re: Why Lisp?

#117
post #61

The interactive model is insanely cool. When building a toy game engine a while back ( https://github.com/orthecreedence/ghostie ) I saved probably half the development time by being able to redefine functions/values while the game was running . The old way of lisping is to prototype in lisp, then build in a "real" language (c/java). However nowadays the lisp implementations (CCL/SBCL specifically) are fast/advanced…

Even better you can attach the repl to a remote instance. I had a problem a little while ago that could only be reproduced on the server. I could connect to the repl over ssh and evaluate and modify code directly. Compare that to a similar problem I had with a C# app we had. For that I had to stick in a load of logging code, check it in then wait half an hour for the CI server to deploy before running and checking th…

Do you know if the attaching to a remote instance is available in Racket? I spent some time learning racket a year or two ago, but was under the impression they took out some of the really cool features (or I never discovered them)

Re: Why Lisp?

#118
post #107

Earlier quoted context omitted.

I'm not entirely convinced. Which definition of "macro" are you using, if you equate lazy evaluation with a kind of "hardcoded macro"? More importantly, "it's hard to make a convincing argument that [these hardcoded macros] provide all the expressivity you would conceivably ever need" doesn't convince me. A better argument would be to produce a compelling example where these "macros" are not enough. And by compelling…

> Which definition of "macro" are you using, if you equate lazy evaluation with a kind of "hardcoded macro"? That definition of "macro" equivalent with "phrase structure rule in your functional language's compiler" which takes the input structure and generates whatever code brings about the lazy semantics (which is not inherent in the x86 instruction set or what have you). > example where these "macros" are not enoug…

> An example is any instance of language extension where, say, the maintainers of the compiler for a functional language have to ship a new compiler to the users to get them to use the new feature.

> Functional languages with lazy evaluation are not finished, right? They are developed actively.

Agreed, they are actively developed.

Correct me if I'm wrong, but you seem to be saying "many interesting features can be implemented in a Lisp language with a macro, therefore Lisp programmers don't need to wait for a new release of their programming language when they want these features".

I'm not convinced this is the case, or rather, that this is such a relevant case. Aren't Lisps actively developed too? Why is there such a multitude of Lisp implementations? Is any relevant real-world feature truly implementable with Lisp macros? Why is that more convenient than implementing them with functions in languages with lazy evaluation?

Maybe I'm falling prey to the Blub paradox. I'm only passingly familiar with Racket, thanks to a course in Coursera, where they introduce macros and why they are so powerful in Lisp. But I still don't see the compelling "killer example"...

Re: Why Lisp?

#119

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…

The majority of macros I write could be represented with HOF and lexically-closed lambdas. That adds significant extra syntax when you use them though. Consider a classic pattern of a with macro: (with-mutex-held-macro (some-mutex) (do-stuff)) (call-with-mutex-held-hof some-mutex (lambda () (do-stuff)) A minor advantage is that a macro will be expanded in-line; a Sufficiently Smart Compiler could transform the HOF ve…

One thing to note is that you're using the macro or lambda to delay evaluation. In a lazy-by-default language, that's unnecessary (which is a part of why macros are less useful in Haskell).

Re: Why Lisp?

#120
post #112

[deleted]

There are more things wrong with XML than the redundant multi-character closing delimiters. The big problem is the "M" in "XML", which stands for "Markup". The driving metaphor is that you start with a bunch of text, then add tags to mark it up, meaning to indicate what the internal structure is.

The problem with this is that the stuff between the tags is always and only text. There's no notion of a token. In Lisp, 2 and "2" are different things: the first a number, the second a string. In XML, that distinction is not in the file; it's only in the schema.

A version of this problem shows up even in your example. Shouldn't you have written this?

  
    abc
    def
    ghi
  
Ah, you say, but we understand that whitespace around the body of each element is to be ignored. Okay, but where does that information live? I don't even know if that can be stated in the schema; it's up to the app consuming this stuff to know that. Supposing it does -- then, what if I wanted a set containing the string " abc"?

See what I mean? The driving metaphor of "markup" is fundamentally broken. A better metaphor is that of a human-readable serialization format for trees -- such as S-expressions or JSON.

"[T]he problem [XML] solves is not hard, and it does not solve the problem well." -- Siméon and Wadler [0]

[0] http://homepages.inf.ed.ac.uk/wadler/papers/xml-essence/xml-...

Post reply on HN