HN user

ICWiener

70 karma
Posts0
Comments51
View on HN
No posts found.
Why we hate Lisp 11 years ago

I can build strawmen too:

- SmugCeeWeenie: I am so fast, look (oops, core dumped)

- SmugGoWeenie: abstractions are so nasty we should get rid of functions, so that everyhting is laid out clearly. Hopefully, I have copy/paste.

- SmugAdaWeenie: Functions are not procedures and records cannot store objects. Real engineers do not "prototype" code.

- SmugHaskellWeenie: Yeah, it compiles! Job done.

In the space year 2015 people are still doing this.

About first class functions? citation needed.

A functional approach:

      (defun mirror (tree)
        (when tree
          (tree 
              (tree-data tree)
              (mirror (tree-right tree))
              (mirror (tree-left tree)))))
For completness, here are the definitions:
      (defpackage :trees (:use :cl)
                  (:shadow #:copy-tree))
      (in-package :trees)
      (defstruct (tree (:constructor tree (data &optional left right))
                       (:type list))
        data left right)

As well as a test case:
      (mirror (tree 4 
                    (tree 2
                          (tree 1)
                          (tree 3))
                    (tree 7
                          (tree 6)
                          (tree 9))))

      => (4 (7 (9 NIL NIL) (6 NIL NIL)) (2 (3 NIL NIL) (1 NIL NIL)))
Fear of Macros 11 years ago

Macros are not needed. You only need the UNWIND-PROTECT special operator, which is the generic feature you are looking for.

Yes, the use of macros is not always justified in the examples, because Python is quite expressive already.

However, the ability to have macros is orthogonal with the feature set of the language. What is interesting is the ability to inspect and modify a Python AST.

Of course, meta-programming is a way to integrate otherwise absent features of a language as-if they were built-in. Python is sufficiently dynamic that most things can be done using existing facilities, like reflection and metaobjects (the @case example, as you mention).

But there is a difference between using those facilites at runtime and producing some code at macro-expansion time (this might be relevant for Cython, for example).

You can, for example, define a domain-specific language that is directly translated as Python, and not interpreted like an API-based representation would. You can even apply custom type checking for that DSL.

Or, you could analyze an existing python source code and produce a translation in another language without having to reimplement a parser (see the Python-to-Javascript example, or Common-Lisp's Parenscript).

Did you not read my reply, really?

I already mentionned that with a Lisp like data-format, shared sub-expressions could be denoted using CL's reader variables:

      (document
        #1=(author (id "Bob") ... )
        #2=(author (id "Alice") ... )
        (span (author #1#) "written by Bob")
        (span (author #2#) "written by Alice")
        (span (author #1#) "written by Bob"))
I do not claim that this is the most appropriate solution in all cases, just that we are not forced to introduce indirection levels when unnecessary. Now, if I am using Lisp and I want to introduce external references to authors described in other documents, I could introduce a meta-data with an appropriate semantical structure:
       (external-element (pathname (directory (relative "path" "to")) 
                                   (type "lisp")
                                   (name "file")) 
                         (tree-path 2 1 3 2 2 3))
This would be a practical way to encode a precise location in a tree in an external file. And I could use this form everywhere I need to reference an object. Also, the tree-path notation is handy because there is no distinction between an attribute or an element, just which branch to take at each step from the root.

Now, with XML attributes, I would typically have an "xref" attribute. How can we model xref attributes? If we wanted to have structured data, we would need to create external tags with the same concepts as above, like <pathname>, create a local identifier for each xref and refer indirectly to each xref using their local identifier: because we can only put strings. I mean:

     <author xref="xref02"> 
     ...
     <xref id="xref02">
       <pathname> ... </pathname>
       <tree-path> ... </tree-path>
     </xref>
Or, we do as everybody and encode it like for XMI, or ECORE, or any other custom format, with a complex string, hoping that HTML entities are properly escaped.

Besides, you failed to notice that you had <author> tags, which precisely goes against your idea that there should be a place for "meta-data" and a place for "data": effectively, authors are now part of the content of the document, and are not only meta-informations.

If you think my examples are artificial, open the source code of this page, and observe how any kind of complex information written in attributes has to be properly escaped to bypass the limitation of stringly-typed data:

       reply?id=9556252&amp;goto=item%3Fid%3D9555880"

       href="vote?for=9556252&amp;dir=up&amp;auth=0UU000REDACTED000208d8b9f4a45575b4edea3779&amp;goto=item%3Fid%3D9555880"
Notice how you need to escape HTML entities in inline javascript attributes (onclick) but not on script tags. Why are inline javascript not tags instead?

(see http://stackoverflow.com/questions/8749001/escaping-html-ent...).

Whatever example you choose, you cannot deny the fact that attributes are not given the same rights as elements, because the way they do not allow to contain structured data or cannot have meta-attributes themselves.

It's a tradeoff, of course.

Reasonable people can disagree about whether the tradeoff is worth it.

But that's my point: reasonable people can disagree.

Sure, we disagree. I understand that you think there is a tradeoff, like in many design decisions. However, you did not tell me what benefits you expect from having the syntactical distinction.

It syntactically distinguishes information that applies to the tag from information to which the tag applies.

That statement alone does not say why it is a good thing to distinguish syntactically both kind of informations. This looks interesting, of course, to be able to have a distinction. The fact that there is a distinction on the semantical level does not mean it should be there syntactically, though.

The syntax for attributes is unfortunately flawed, which is why ...

Any language feature can be abused. The proper response IMO is to stop abusing the feature, not to eliminate it.

... is taking the problem completely backwards. No language feature were abused. In fact, attributes were acting against a natural organization of information. And that is why, as a workaround, it was needed to express meta-data with tags. I don't expect you to agree with this, so consider a classical example of markup usage.

You want to represent a document, with reviewers, publication dates and authors (those are meta-informations, right?) as well as content (the actual text being stored). However, there exists meta-informations about people (name, title) and dates (calendar). Where do we store structured meta-informations about attributes?

Unfortunately, attributes do not allow to express structured information, and they cannot have meta-informations attached to them. Here is what you obtain:

     <root>      
          <document author="id0"
                    published_in="ACM"
                    publication_date="2010/03/02"
                    publication_volume=345
                    link="doi://1020301.202.301.1023"
                    reviewers_id="id1;id2;id3;id4">

            ... content ...

          </document>

          <peoples>
            <people id="id0"><name>John Doe</name>...</people>
            <people id="id1">...</people>
            <people id="id2">...</people>
            <people id="id3">...</people>
            <people id="id4">...</people>
          </peoples>
     <root>     

Notice how informations about publication are scattered into different attributes instead of being a single attributes with sub-components? (has the document been published in March or February? In which timezeone?)

Authors are only indirectly referenced through identifiers, because the real structure cannot be easily expressed in attributes only. Also, a list of reviewers is actually a string with semicolon-separated identifiers.

An so, peoples are not just meta-informations, but tags with nested children and you must have a "root" element around your document, and a special list of "peoples". Just to be clear, having identifiers is not bad and could be a good way to model relationships. The problem is that you do not have a choice anymore of using different level of meta-attributes.

Notice how the link to a "DOI" identifier is itself encoded in a string (this is a custom format just for this example), instead of using a more useful nested structure:

       (link (protocol doi)
             (path (digits 1020301 202 301 1023)))

Each time you use a string to encode structured information in an attribute with a custom mini-language, you are asking for trouble. Imagine how each of those strings now need to have a dedicated parser because you need to take care of escaping "special" characters.

You might say that this is unfortunate that attributes are "flat", and that maybe a kind of hierarchical way of expressing attributes would be more preferable. And then, you would have nested-attributes as well as nested-elements. Why not merge them into the same syntactical structure?

If you consider that identifiers are not necessary, or if your format allows for sharing common sub-expressions (like #1=(author), #1#), then you could go with that kind of data-format:

       (document (author (name "John Doe") (job-title "Professor") (institution "MIT"))
                 (anchor
                      (link (protocol doi)
                            (path (digits 1020301 202 301 1023)))
                      (target blank-page))
                 (reviewers (reviewer (name "..."))
                            (reviewer (name "..."))
                            ...)
                 (encoding (utf 8))
                 (sections
  
                    ...))
Then, you have multiple layers of "meta"-informations, instead of just 2: "data" and "dumb meta-data". I agree we disagree, but I do not think both approaches are equal. You talk about tradeoffs, but I really do not see anything useful in having attributes, whereby I can see the inconvenience they bring when trying to structure information in a meaningful way.

Not only is he wrong, he's clearly wrong.

You keep repeating that, but the more you discuss it, the less "clear" it is.

I don't understand your question.

You acknowleded that we need to have a specification in order to make sense from a piece of markup. When we know what elements are to be expected in a format, what "clear" and "useful" advantage gives an additional arbitrary syntactic separatation over a sub-element-only layout? and why is it more "reasonnable" to have this separation when it actually make it slightly more difficult to manipulate the data?

My claim is that, in the context of markup languages, there is a useful distinction to be made between data and metadata, ...

Originally, attributes made sense "in the context of markup languages" because attributes were metadata and sub-elements where "content". This is a reason why Naggum was first favorable for the distinction. But then the line was blurred, because not everything is so simple and you find attributes that refer to "data" (title attribute) and sub-elements that refer to "meta-data" (<meta> tag, for example).

(foo [baz bar] bind) ... you could tell that ... BAZ was a variable binding without having to know how FOO was defined. It's not a slam dunk, but it is a defensible position.

You don't need to know how FOO was defined, but you have a contract with FOO: there are many other distinctions one could make (not only bindings/parameters): will you invent a new syntax for everyone of them? Is that really useful? XML is used when you don't want to have a complex syntax and when a standard AST suffice. And then, attributes are an added complexity with little benefits.

Just as code is data and data is code, meta-data is another form of data. Erik' quotes are all taken from https://groups.google.com/d/msg/comp.lang.lisp/8eUxiibm_zA/C...:

[...] is INTENDED to be a MODIFIER for FOO and NOT part of the CONTENT that FOO is marking up

"The intended use has less to do with it than the notion that you can define what is meta-information and what is information at the time you want to decide whether something goes in an attribute or a sub-element. My argument is that this is impossible. Whether it is meta-information or information is a reflection of the actual use, not the intended use.

However, given that the mechanism was created, and I will argue that it was not so much created as it was never thought possible to be any other way, it was used to define several language properties. "Now that we have this, would it not also be nice to have that." This means that several of the attribute types grew very far apart from the contents of sub-elements and you sort of "had" to use them as attributes, but only sort of, because the application can and does define the semantics of everything, and if you want ID and IDREF, you can make the same choice as you would in Common Lisp to use symbols or a hash tables of strings."

Actually, let me try to be excruciatingly precise: my claim is that it is not self-evident that a syntactic distinction between data and metadata is useless. Hence a rendering of XML into sexprs that preserves this distinction is defensible, and dismissing it in the pejorative terms that Erik uses is not justified.

"No, there is nothing that requires there to be element attributes as a distinct concept from element contents. There are, however, a number of practical things that follow from making that arbitrar distinction which can look like rationales, but if you ask yourself "why can it not be a subelement", there are no real answers, only appeals to the idea that there somehow __have to be a distinction. It took me years to figure out that the whole attribute idea is completely vacuous, and I worked with the creator of SGML himself for several years on several SGML-related standards and projects. I started writing "A conceptual introduction to SGML" back in 1994, but as I had pained my way through five chapters, I had to realize that it was all wrong. There was a basic design mistake in the whole language framework. That mistake is that simply put: "what is good enough for the users of the language is not good enough for its creators". Each and every level of "containership" in SGML has its own syntax, optimized for the task. Each and every level has a different syntax for "the writing on the box" as opposed to "the contents of the box". This follows from a very simple, yet amazingly elusive principle in its design: Meta-data is conceptually incompatible with data. This is in fact wrong. Meta-data is only data viewed from a different angle, and vice versa. SGML forces you to remain loyal to your chosen angle of view."

So, the opinion seems to be that the arbitrary structure you put between meta-data and data at the moment you create data is not necessarly well-suited for people using your data: then, despite being useful, the syntactic distinction becomes an annoyance.

By the way, Erik's dissmissal is (1) the result of years of experience working on SGML, and (2) not pejorative, but argumented. He is the one arguing against the "self-evidence" of attributes.

Did you just summarize thousands of sentences in a single one?

Neither <input type=button/> nor <input><type>button</type></input> does mean anything without a spec of your language, and trying to infer that <input>foo</input> or <type>bar</type> is valid is only due to some pre-conception about the underlying semantics you gave to your data (you chose familiar tag names, after all).

If I gave you a sample XML file from work, you'd have a very hard time knowing whether one attribute/element is or isn't optional (or bound) to an element. You'd need a schema/meta-model or even an informal spec.

With attributes/elements, you have two ways of defining data where only one is necessary: (input (type button)). The closet example I can think of is for example, if you had a lisp that is not homoiconic but had two different syntaxes for lists at its core: [] and (), without a simple way to abstract over them. Then your data format would be cumbersome to use with no added benefit: whether or not a []-list means something different than a ()-list depends on the specification of your data.

CSV Challenge 11 years ago

Common Lisp

     (ql:quickload :drakma)
     (ql:quickload :cl-json)
     (ql:quickload :local-time)

     (defparameter *data*
       (cl-json:decode-json-from-string
        (drakma:http-request 
         "https://gist.githubusercontent.com/jorin-vogel/7f19ce95a9a842956358/raw/e319340c2f6691f9cc8d8cc57ed532b5093e3619/data.json")))

     (with-open-file 
         (stream (make-pathname
                  :name (local-time:format-timestring
                         t
                         (local-time:now)
                         :format '((:year 4)(:month 2)(:day 2)))
                  :type "csv") 
          :direction :output
          :if-exists :supersede)
       (loop initially (format stream "Name,Credit Card~%")
             for slot in *data*
             for name = (cdr(assoc :name slot))
             for card = (cdr(assoc :creditcard slot))
             when (and name card)
               do (format stream "~a,~a~%" name card)))

I don't see any kind of error handling, but if I understand correctly, in some cases in Go it is not necessary to check for errors directly (an errorneous output stream would do-nothing on write, for example). Do you think your versions are fault-tolerant or is there anything you should add to gracefully handle errors?

Regarding 1., I don't think it follows that the pattern-macro will end up in one giant namespace. I'd love to understand why you think so.

And for 2, even though what you say seems desirable on the surface, you still approaches the problem in a way that is too fuzzy, or abstract. Just as saying "we should write more secure code" and then failing to attack the problem directly.

No offense, but even though you may have a nice idea, your explanation is a little too handwavy.

Macros will expand into lisp forms, not only expressions. Whether a form is an expression, a declaration or a pattern depends on the surrounding context.

I would say that declarations, ... are not syntax but semantic classes.

Too bad the conclusion does not offer a glimpse of what would the extension mechanism look like. Still, nice article.

Try Three Times 11 years ago

Wait a second--is this really using exceptions for control flow?

No.

If it used exceptions for control-flow, the defined function would actually throw an exception. Here, we catch "Exceptional Problems" and ignore them at most 3 times. A common example of using non-local exit is to return from deeply nested recursive calls.

(edit: of course, you can argue that network delays are not exceptional (surley you love Go), but the code shown by OP is supposed to handle any kind of exceptional situations. Of course, if there was an error value, you could define another function that checks that error value)

That being said, "Exceptions for exceptional situations" is exactly like "never use goto". Non-local exits are definitely useful and not necessarly costly.

Performance is terrible in almost every language

Even in cases where this is true, it can make sense to use them for control flow according to your requirements and actual measures.

My own point of view is biased, admittedly, but I couldn't stop thinking that Common Lisp was relevant for each item in your list.

Of course, much isn't built-in, but this is not as bad as it sounds: concurrent channels are not part of the language specification, but you can install the "calispel" or "cl-actors" libraries that gives you what looks like primitive constructs.

Regarding "modern" languages, I like this quote from the author of pgloader: "I switched from Python to Lisp because I wanted a modern language" (also transcribed as: "[...] in searching for a modern programming language the best candidate I found was actually Common Lisp."; see http://tapoueh.org/blog/2014/05/14-pgloader-got-faster.html)