Live data from Hacker News

Getting Started With Clojure

jrheard.tumblr.com

101–110 of 113 posts

Re: Getting Started With Clojure

#101
post #92
post #88

Earlier quoted context omitted.

At ILC 2009, Guy Steele asked Rich Hickey how Clojure's STM interacted with I/O. To which, Rich replied that it doesn't. No further discussion continued on the subject. I have found that this rarely enters discussions regarding Clojure, although the STM is frequently lauded. GHC's STM also does not work with the IOMonad, which is clear because of the types, and is articulated in books such as such as Real World Haske…

That's odd, that seems a little inaccurate to me. Clojure's agents are useful for encapsulating I/O-related resources, and are integrated with the STM system. Per http://clojure.org/agents - Agents are integrated with the STM - any dispatches made in a transaction are held until it commits, and are discarded if it is retried or aborted.

I'm a clojure newb myself, but I thought STM transactions weren't allowed to have side-effects and IO would be a side-effect, no?

Re: Getting Started With Clojure

#102
post #63
post #61

Earlier quoted context omitted.

Thanks for this. I'd hate to start down the road of writing a game in clojure.... I may try the blog/webapp idea with Clojure.

Programming a game in Clojure might not be such a bad idea - mikera has some really great thoughts at http://stackoverflow.com/questions/9755882/are-functional-pr... . Also, you might find this series of blog posts interesting: http://briancarper.net/blog/520/making-an-rpg-in-clojure-par...

Don't forget: The Caves of Clojure - steve losh

http://stevelosh.com/blog/2012/07/caves-of-clojure-01/

Re: Getting Started With Clojure

#103
post #72
post #46

Earlier quoted context omitted.

On the other hand it means the semantics become quite tied up in underlying JVM-related details and don't seem as clean/elegant as (say) Scheme. That's not very true. Instead, Clojure is defined in terms of specific abstractions. Whether those take the form of interfaces or protocols is irrelevant because it's the abstractions that count. If it were tied strictly to JVM-related details then ClojureScript would have b…

You have to use the java interop facilities if you want your own types to implement these abstractions though right? I recall some debate about changing this so you can implement them using the native abstraction facilities in clojure (protocols), at which point I'd probably withdraw my point. But yeah elegance is subjective. I use Clojure and broadly like it, JVM interop is really useful, but the lack of a crisp sep…

I'm still a clojure newb, but if I understand you correctly:

>> I recall some debate about changing this so you can implement them using the native abstraction facilities in clojure (protocols)

You mean records (defrecord): http://clojure.org/datatypes

Re: Getting Started With Clojure

#104
post #76
post #40

Earlier quoted context omitted.

matthavener wrote: "Running everything inside the JVM means you only need to ship what any arbitrary JVM library requires. In this case, its as simple as a .jar." Considering a .jar is a zipped directory tree, and a virtualenv is a directory tree, would you be happy if we zipped up virtualenvs and called them .par or something? I'm not sure what "language as library" will mean if you are not installing a VM or interp…

I think the important difference between virtualenv and lein is not the implementation detail of whether it is a zipped file or whatever, but in how you use them. If you run a python program with virtualenv who decides weather to use python2.5 python2.7 or python3? Is it the author of the program? No, typically it is the user of the program who decides by symlinking /usr/bin/python If you run a clojure program "lein…

That is exactly what the other JVM languages do. You download your version, of the language compiler and runtime, as libraries with a build tool. Then the build tool uses that compiler library to build your code. Saying that the idiomatic way of running groovy code is 'groovy myscript.groovy' is no more true than saying that the idiomatic way of running clojure code is 'clojure myscript.clj'

edit: grammer

Re: Getting Started With Clojure

#105
post #40
post #33

Earlier quoted context omitted.

True clojure assumes the existence of the JVM. However no other jvm language has gone with the language as library system which is a shame. Also, I don't think anything would preclude non jvm hosted languages from doing something similar. I think it is a better solution than say virtualenv from python.

matthavener wrote: "Running everything inside the JVM means you only need to ship what any arbitrary JVM library requires. In this case, its as simple as a .jar." Considering a .jar is a zipped directory tree, and a virtualenv is a directory tree, would you be happy if we zipped up virtualenvs and called them .par or something? I'm not sure what "language as library" will mean if you are not installing a VM or interp…

... and called them .par or something?

.par is already taken. See PAR, the Perl Archiving Toolkit, which attempts to replicate jar for Perl.

- http://par.perl.org/

- https://metacpan.org/module/PAR

Re: Getting Started With Clojure

#106
post #92

Earlier quoted context omitted.

That's odd, that seems a little inaccurate to me. Clojure's agents are useful for encapsulating I/O-related resources, and are integrated with the STM system. Per http://clojure.org/agents - Agents are integrated with the STM - any dispatches made in a transaction are held until it commits, and are discarded if it is retried or aborted.

I'm a clojure newb myself, but I thought STM transactions weren't allowed to have side-effects and IO would be a side-effect, no?

Refs and atoms shouldn't have side effects, but agents are great for performing side effects. From page 214 of Clojure Programming:

    Unlike refs and atoms, it is perfectly safe to use agents to coordinate 
    I/O and perform other blocking operations. This makes them a vital
    piece of any complete application that use refs and Clojure’s STM
    to maintain program state over time. Further, thanks to their semantics,
    agents are often an ideal construct for simplifying asynchronous
    processing involving I/O even if refs are not involved at all.
Further:

    Agents are integrated into Clojure’s STM implementation such that
    actions dispatched using send and send-off from within the scope
    of a transaction will be held in reserve until that transaction
    is successfully committed. This means that, even if a transaction
    retries 100 times, a sent action is only dispatched once, and that
    all of the actions sent during the course of a transaction’s
    runtime will be queued at once after the transaction commits.

Re: Getting Started With Clojure

#107

I'm interested in learning LISP. How good a choice is learning Clojure as a way of achieving this? I've read a page[1] listing differences between Clojure and other LISPs, but I'm not sure that I fully understand the implications of these differences. [1] http://clojure.org/lisps

Clojure's a great lisp. I recommend it highly. I haven't spent much time with Scheme, but I can definitely say that I greatly prefer Clojure to Common Lisp.

Re: Getting Started With Clojure

#108
post #97
post #55

Earlier quoted context omitted.

> That means whenever you call it you always getting it back - this is behavior of a constant. No! You're confusing functions-as-callable-things and functions-as-values. The phrase "a constant" does not generally imply anything about a thing's behavior when called . It just means something whose value will never change. A self-evaluating constant is a constant that circularly evaluates to itself — nothing else can ha…

@baar: FYI, you appear to be hellbanned (your comments are being automatically killed as soon as you post them). New accounts are particularly susceptible to this, as it seems like the auto-ban algorithm kicks in when you have low karma and get too many downvotes in a short time, or something like that. You should be OK if you make a new account and avoid making very harsh comments so you don't draw downvotes.

(Just in case you can see this:)

Thanks for letting me know. I'd figured as much (from browsing anonymously) -- I guess the powers that be don't care enough to get new commenters. Oh well.

I won't bother to create a new account; I really shouldn't wasting time posting here anyway.

Re: Getting Started With Clojure

#109
post #88
post #71

Earlier quoted context omitted.

I'd like to contrast this: if your application is heavily dependent on state, especially state which is shared between threads, Clojure offers a concise, safe, and uniform way to understand and organize state transformations--at the cost of performance. Where fast mutability is required, it's easy to drop down to explicit locks, atomics, java.util.concurrent collections, et al. I find the majority of my time in writi…

At ILC 2009, Guy Steele asked Rich Hickey how Clojure's STM interacted with I/O. To which, Rich replied that it doesn't. No further discussion continued on the subject. I have found that this rarely enters discussions regarding Clojure, although the STM is frequently lauded. GHC's STM also does not work with the IOMonad, which is clear because of the types, and is articulated in books such as such as Real World Haske…

Riemann is a giant ball of mutable state and IO, and makes extensive use of the STM: https://github.com/aphyr/riemann/blob/master/src/riemann/str...

The critical thing, as you observed, is to separate IO from retryable STM transactions with a barrier; e.g. by receiving data, doing an idempotent computation inside dosync or swap!, and then emitting results. Haskell has an advantage in that this separation is provable by the type system, whereas in Clojure you need to remember.

A contrived example:

  (let [pizza (get-from-fridge)
        meal  (dosync
                (alter eaten-foods conj pizza)
                (deref eaten-foods))]
    (tell-friend "So far I ate" meal))
where get-from-fridge and tell-friend are IO operations, and our list of eaten foods is mutated by pure functions.

In practice I don't find this particularly limiting: dosync and swap! are almost always short operations for performance reasons anyway. Then you return a consistent snapshot of the updated state from dosync--where multiple pieces of state are involved, you can use vectors or maps along with destructuring bind. Sometimes it's a tad unwieldy, but typically much shorter than the equivalent mutex dance.

There are other aspects of Clojure's concurrency libraries, like agents, futures, and promises, which are useful in IO. Specifically, agents give you asynchronous serializability, futures give you asynchronous concurrency, and promises allow for synchronous handoff of delayed values. Those are quite useful when working with IO, though for heavy lifting you may be better off using explicit queues and worker pools from java.util.concurrent.

Sometimes I think of Clojure (as an imperative language) as the dual of Haskell's lazy evaluation model. Clojure uses futures, promises, and lazy sequences to provide explicit laziness, where Haskell uses the IO monad to provide explicit ordering. Both have an STM for serializable, atomic mutability between threads.

Re: Getting Started With Clojure

#110
post #59
post #53

I have been thinking about getting into Clojure, but time is precious. It doesn't seem like there are that many jobs out there, but I could be wrong. For those of you in the industry, why would I want to use Clojure? What would be a good project to try it on? A Web app? Why is it worth learning it?

I started learning Clojure because it seemed to be the logical next step for me. In the few years that I've been programming full-time, I've noticed some patterns: in general, imperative code with lots of side effects in it is difficult to reason about and hard to test, and pure functions are easy to reason about and trivial to test. The same rule seems to hold for code that uses mutability vs code that deals only wi…

I realize this is quite off the main topic, but I thought it was interesting and worth passing on.

If you really think that "four different kinds of equality" in Common Lisp is a wart, then I recommend that you read "The Best of Intentions" (http://www.nhplace.com/kent/PS/EQUAL.html) by Kent Pitman. The article explains why that situation is quite intentional, and why it is very rational, and why it is in fact ill-advised to expect a single meaning for "equal" ... or, in fact, other "obvious" concepts like "copy" ... to be sufficient.

That article was one of the many over the years that helped me refine the way I think about programming and programming languages.

Post reply on HN