Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

    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:

    <Term term="slick">
      <PartOfSpeech pos="adj">
        <Definition>
          impressive.
        </Definition>
        <Definition>
          smart.
        </Definition>
      </PartOfSpeech>
    </Term>
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.



That's a great example right there.

Notice, the end result is just data, as terse and minimal as possible. But to act on (aka "interpret) that data, he wrote functions called "term", "part-of-speech" and "definition."

So now, that data is code. Code is data and data is code.


Agreed - that example is amazing. However, the devil's advocate in me can't help but ask: what if I want more than one transformation? What if I want to generate both HTML and, say, JSON for returning that information from a web service?

Hmm... it might work if I use some sort of global parameter: I first "execute the data" (damn!) with the output type set to HTML and then do it again with an output type of JSON.


There's an answer there too. In Lisp, it is possible to have local functions. In other words, you're defining a function, and inside it you have a couple of functions that are local to the containing function.

That's one way for "term" and the other items to have different definitions.

There are probably other even better ways to do it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: