HN user

brehaut

594 karma
Posts5
Comments130
View on HN

Pedantic note: #^ for metadata has been deprecated for at least 2 if not 3 versions. ^{ and ^:x aren't special. It's just ^ (reader metadata symbol) followed by a map and keyword respectively. Other things can also be metadata (for instance you can tag something with a classname to indicate a type hint).

You also missed out a few of the syntax quote stuff.

So, other tokens are #{} ^ #() #_ #'x ` ~ ~@

Full details: http://clojure.org/reader

kickstarters are not the sole way people contribute to projects and communities. ibdknox has created some very popular (in the clojure community anyway) software (noir, korma etc) that a lot of people build on top of. Surely this should count for something.

While not addressed to me, i'd like to chime in with some comments of my own here.

One of my personal gripes with javascript as an environment is that out of the box there is exactly two composite data structures, and both are associative: Objects, and Arrays.

As you are probably aware, Objects are the bread and butter of Javascript and double as full OO objects and also as map/dictionary types with the limitation of only allowing String keys. Arrays have their own quirks but lets leave that aside for now.

Javascript lacks a well understood model of value identity[1]. Without a common model for value identity (i.e. more than reference identity) it becomes very difficult to implement custom data structures (e.g. a BTree for implement a true dictionary type) in a way that can easily (and naturally) be consumed by third parties. Lacking the ability to hook into the [] operator increases the awkwardness for anyone attempting to provide their own custom collections. I would suggest that the lack of good quality collections deployed widely in the javascript world underscores this problem. Contrast this with just about any other language you can think of and it is even more stark.

As an example, any good language probably has a Set datastructure these days. There are two ways to fake it: Degenerate map with the key being the real value and either some sentinal (such as true) or the key itself as the value, or (as is very common in javascript) an array and then doing indexOf.

Let that sink in: a common approach to sets in javascript (when you cant easily provide a string key for your object) is to do a linear search. Yuck.

For a wonderful counter point, have a look at how ClojureScript implements its own collection types, complete with value identity, indentity partitions and proper maps with object keys.

[1] Leaving aside all the unknowns most javascript programmers have about the `valueOf` method.

There is no one framework (in fact, most of clj's web ecosystem is not frameworks) that is far and away more popular than the others.

At the heart of everything is Ring[1]. Ring is roughly equivalent to WSGI or Rack. However, if you use Django in python you basicly dont ever have to know about WSGI. In Clojure you do want to know about Ring. Thankfully Ring is very simple; its a spec describing request maps and response maps. In addition provides common adapters for various JVM web servers (In the general ring ecosystem there is support for Jetty, Netty (via Aleph/Lamina), Google App Engine (via appengine magic), Servlets, Mongrel2) and middlewares.

There are three sets of libraries on top of ring that are commonly used to build sites:

## Moustache

Probably the closest to raw ring of the three, moustache provides a sophisticated url routing API. Of the three I'm mentioning here it is probably the least suitable for clojure beginners, however it is my personal favorite.

## Compojure

This was the most popular [noir is apparently on par] and oldest (it predates ring but was rewritten ontop of it in the 0.4.0 release). The best analogy here is apparently sinatra for ruby.

## Noir

Noir is the most recent addition and is higher level than Moustache or Compojure. In fact, Noir is built on Compojure. I havent had any real experience with Noir myself but it is probably the easiest entry point into web programming in clj.

Compojure and Noir both use Hiccup for HTML generation, and Moustache uses Enlive. Enlive is extremely powerful; even if you choose hiccup I would encourage you to take a good look at enlive anyway, the two solutions dont need to be mutually exclusive.

  [1] Ring: http://github.com/mmcgrana/ring/

"If you come from a javascript background, you will have a leg up on most people in terms of learning clojure. You get used to inlining functions pretty regularly."

You'd be better off listing the languages that don't have some sort of 'inline functions' than claims about javascript superiority here; Heres a handful of common imperative/OO languages that have an analogous construction: Python, Ruby, C#, Visual Freaking Basic Dot Net, Smalltalk, Objective C and other C languages with Apple's blocks extension, probably PHP and Lua…

ClojureScript 15 years ago

The other libraries are clojure libs that implement javascript analogies[1] as clojure macros and functions and generate javascript.

ClojureScript is a Clojure The Language compiler that implements Clojure (its datastructures, standard lib, protocols, deftypes etc etc) and is hosted[2] on javascript rather than the JVM.

In ClojureScript you are not writing reskinned javascript, you are writing Clojure.

[1] simplified for the argument

[2] By outputting javascript

xmlrpc[1] is similar.

    <?xml version="1.0"?>
    <methodCall>
       <methodName>examples.getStateName</methodName>
       <params>
          <param>
             <value><i4>41</i4></value>
          </param>
       </params>
    </methodCall>
my favorite part[2] is how <params> only contain <param> elements within. each <param> has exactly one child. Why is it not just <params><i4>41</i4></params>?. Its no surprise that the creator of xmlrpc was involved with soap.

[1] http://www.xmlrpc.com/spec [2] not really.

The obvious reason for no Object/Relational Mappers in Clojure is that while Clojure has objects available, it doesn't orient around them. It makes much more sense to treat a set of records from the DB as a sequence of maps.

For DBs and Clojure in general I can only speak about CouchDB via Clutch and SQL via ClojureQL and clojure.contrib.SQL. I don't want to claim to be an expert in either of these technologies, but if you have some more specific questions i'm happy to do my best to answer them. you might find some answers about couch in an older post of mine http://brehaut.net/blog/2010/couch_impedance

Regarding Clojure, while compojure is popular, a compojure centric view of web programming is misguided. Compojure is part of a growing ecosystem of libraries built on top of ring[1][2].

Firstly this ecosystem is not analogous to rails or django. The closest is that Compojure is similar to Sinatra i believe.

If you are looking at getting started with web programming in Clojure you need to get familiar with ring (the http abstraction) and look at Compojure and Moustache (routing and handler composition), and Enlive[4] and Hiccup[5] (templating/html generation). Compojure and Moustache are fairly similar, but Enlive and Hiccup are extremely different. A web application will consist of ring plus one of each layer.

As has been mentioned by others in this thread, the depth, breadth and currentness of documentation for these libraries varies. David Nolen has a great tutorial for enlive[6] that i would encourage anyone looking at these libs to work through. Enlive is one of the most compelling aspects of the clojure web ecosystem at present.

These libraries provide the core pieces you would expect to see in any web framework, but a lot of the smaller details are missing. Of note there is no ORM for clojure (for obvious reasons) - If you are looking for a good SQL abstraction you should look at ClojureQL[7] - and aspects such as form generation, validation and processing is still in early days.

My day job has me building web apps with Django. I wouldnt suggest that my coworkers and I jump to clojure / ring et al yet. The breadth of libraries and out of the box stuff in django is still a huge advantage for the day to day rapid web site / web app development, however clojure's story is improving rapidly and i think that the functional model is a particularly good fit for web applications.

I cannot compare clojure's story with the other languages and frameworks mentioned.

  [1] https://github.com/mmcgrana/ring/ 
  [2] This is true of compojure 0.4 and newer. compojure existed prior to ring (with hiccup as part of it).
  [3] https://github.com/cgrand/moustache
  [4] https://github.com/cgrand/enlive
  [5] https://github.com/weavejester/hiccup
  [6] There is a link in the enlive readme
  [7] https://github.com/LauJensen/clojureql/

Server side code is what they have the affero GPL for:

“The GNU Affero General Public License is a modified version of the ordinary GNU GPL version 3. It has one added requirement: if you run the program on a server and let other users communicate with it there, your server must also allow them to download the source code corresponding to the program that it's running. If what's running there is your modified version of the program, the server's users must get the source code as you modified it.…” — http://www.gnu.org/licenses/why-affero-gpl.html

presumably they dont want the back end of gmail being proprietary either but its not the point of the article?

    main = print "Hello, World!"
Not a monad in sight. Yes, print is an IO Action, but you don't have to use monads to do IO. Add in 'interact' and a you can be writing trivial stdin / stdout programs very quickly.

In a python repl dir(object) and help, help(object) are what you are looking for. Both these functions are in the default namespace

    dir(__builtins__) 
Returns a list of strings for all the names bound in the prelude namespace.
    dir(list)
Returns a list of strings for all the methods on the list class.
    dir([])
Will return a all the methods on a particular instance.

etc… the same caveats apply to dir with getattr etc as to method_missing. additional caveat i dont care to test; it may not work on an old style class instance.

help has its __repr__ defined to tell you how to use it. It will allow you to read the doc strings for a namespace, object or function. However i prefer to run 'pydoc -p 8888' in my projects top level; this will start an http server on port 8888 that lets you interactively browser your projects docstrings and all the modules on its pythonpath.

Hope that helps

You have (understandably) been led astray by a poorly considered title.

The article demonstrates a vector based 'hand drawing' algorithm that happens to use the HTML5 logo and be implemented in javascript with canvas.

Unfortunately it doesn't appear to implement a generalised library for scruffy drawing.

I think that is exactly his point; if those features (the interestingly academic or algorithmic but very tricky) are the ones that are most likely to make the workflow lumpy or weird.

My interpretation (based on the actual text, not the abbreviated quotation) is that Arment prioritises straight forward user experience over wizbangery