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

Same data in Clojure:

    [{:appt/start #inst "01-02-2014T9:15:00Z" :appt/end #inst "01-02-2014T9:15:00Z" :appt/description "See Anderson"}
     {:appt/start #inst "01-02-2014T10:45:00Z" :appt/end #inst "01-02-2014T11:00:00Z" :appt/description "See Lundstrom"}
     {:appt/start #inst "01-02-2014T13:15:00Z" :appt/end #inst "01-02-2014T16:00:00Z" :appt/description "Attend Y Committee Meeting"}
     ...]

Let's point out some important differences:

1) Clojure prefers maps over cons cells. This means that I always know exactly what I'm looking at. I don't have to guess that the second times are the end-times...I know because it' named :appt/end.

2) We don't overload data types. Have a date? Use a date type. In the CL example we see symbols and numbers sometimes used for descriptions, sometimes for times, etc. Here in Clojure we have #inst ... which creates an actual DateTime object. Now I no longer wonder what I'm looking at, I know it's a date.

3) Clojure prefers data over DSLs. What this calendar example shows is some sort of domain specific language that not only has to be parsed by a program, but it also has to be parsed by a human.

4) Got a meeting description, use a actual string....what's up with the use of symbols as strings (I never understood that about CL).

5) From the perspective of a data modeler...in the CL example if you want a meeting to last over midnight or for longer than a day, it looks like you're sunk.

But thanks for the example, it's fun to see how data modeling is done in other languages.



I think most CL programmers would agree with several of your points. Using lists of symbols instead of strings is not useful. Though there are infinite ways to model the calendar, a slightly better way would be something like the following. Note that it's incredibly similar to your Clojure example, though it uses property lists instead of maps:

    ((:start @2014-01-02T09:15:00Z :end @2014-01-02T09:15:00Z :description "See Anderson")
     (:start @2014-01-02T10:45:00Z :end @2014-01-02T11:00:00Z :description "See Lundstrom")
     (:start @2014-01-02T13:15:00Z :end @2014-01-02T16:00:00Z :description "Attend Y Committee Meeting")
     ...)
Do note that this uses the local-time[1] library's timestamp syntax. If you don't want dependencies you could put numerical universal-time[2] timestamps there.

Of course, depending on the programmer, this would change a lot. For example you could use a simple list or vector of 3 items instead of a property list, or maybe an association list. But if this isn't a one-off thing, most would probably define a class or a struct to store the data in, with proper accessors to get the data out. This wouldn't be so easily PRINTable as the above, but in code it would look something like the following:

    (list (make-appointment :start @2014-01-02T09:15:00Z
                            :end @2014-01-02T09:15:00Z
                            :description "See Anderson")
          (make-appointment :start @2014-01-02T10:45:00Z
                            :end @2014-01-02T11:00:00Z
                            :description "See Lundstrom")
          (make-appointment :start @2014-01-02T13:15:00Z
                            :end @2014-01-02T16:00:00Z
                            :description "Attend Y Committee Meeting"))
Now you have data with actual types, with accessors like appointment-start, appointment-end, and appointment-description.

[1]: https://common-lisp.net/project/local-time/manual.html#Reade... [2]: http://www.lispworks.com/documentation/HyperSpec/Body/25_adb...


Historically, Common Lisp's preference for symbols over strings to represent text is due to the nature of equality comparisons. Symbols are equal based on their pointers. Strings are equal based on their byte sequences. Clojure leverages Java's immutable strings to allow pointer comparisons.

I apologize for not being clearer. The point I was trying to make is that Lisp programs often used lists in a data centric manner and my example based on the 1978 paper was optimistically intended to illustrate that.

Perhaps there's an analogy between lists in traditional Lisp programming and text in *nix systems in so far as each is used as a standard interface when composing systems from sub-systems. Or perhaps not.


> But thanks for the example, it's fun to see how data modeling is done in other languages.

Franky, this example upset me because this is the typical "LISP has only lists and symbols" example. On the first hand, the format is not deprecated: you could write a simple parser today and extract the data back. But on the other hand, it reinforces those core myths about Lisp having no real datatype, no strings, etc.


I wasn't trying to upset anyone. I came across the example in the cited document a few years ago and had an epiphany. What I find elegant is that it does not have all the conceptual overhead of a 'real' database even today. In historical context it does not have all the overhead of the primary alternative COBOL (there weren't widely available relational database systems in 1978). The other thing I found striking was that it was code I could write myself without reference to a pile of documentation.

I mean the parser is something like:

  (defun appt:appointment-date (appt)
    (first (first (appt)))
  (defun appt:appointment-start-time (appt)
    (first (first (rest appt))))
  (defun ...
In fairness, I don't really worry about winning the language war. Partly because I don't draw a big distinction between Clojure and 'Lisp', or at least not one that comes down to more than choosing one or the other based on the runtime that makes sense and the skills of the people writing the code.

Anyway, what I found interesting about the code years ago and yesterday was how lightweight it was. There's nothing inherently wrong with storing appointments in Zulu time, but if I'm talking with Lundstrom it's easier if we both say '10:45'. Reflecting that business logic in the data may make sense in the context. In other contexts it might not.


Thanks for the clarification, I don't mind the actual format and its simplicity; I understand what you mean about being lightweight. What bothers me is that I often see questions or statements about Common Lisp which contain factually wrong statements. The most notable is "Common Lisp has only lists (e.g. hash tables are built using cons cells)"; another one is "you have to write in All Caps". And your example is indirectly confirming that, as shown by the reply you got, saying "here is how we do in Clojure" and "it's fun to see how data modeling is done in other languages" (that was really depressing to read). Sorry for the "upset" part.

As an aside, since I can customize the readtable in CL (which is not considered useful in Clojure), I added a single entry for "#i" (and read-char to ensure it ends with "nst") to read the exact same data as in Clojure; but I got an error about invalid dates; it just happens that the Clojure example does not actually contain valid RFC3339 dates (I also tried to with Clojure => invalid date format).


Like I said, I appreciate Clojure and I took the comment as someone's expression of enthusiasm for the language. Part of the design rationale for Clojure is to improve the lives of Java programmers and Common Lisp isn't usually a viable option in such a context and hence there's less justification for a comprehensive analysis of its features. If someone is more or less committed to the JVM, the numerical sophistication of Common Lisp doesn't change the criteria for choosing a language very much, if at all. Like a lot of things, it depends on context.




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

Search: