Live data from Hacker News

Clojure core.async and Go: A Code Comparison

blog.drewolson.org

71–80 of 81 posts

Re: Clojure core.async and Go: A Code Comparison

#71
post #69

Earlier quoted context omitted.

I do not consider them verbose What a curious statement. James did not consider the 'minimum expression of an idea' a virtue, he's almost infamous for his verbosity, as are many of the others in that list. I'll leave you with something from the start of The Ambassadors as an example: The principle I have just mentioned as operating had been, with the most newly disembarked of the two men, wholly instinctive--the frui…

I don't consider that verbose at all. It expresses a great deal more information than you're giving it credit. It would not be easy to pare down without destroying this information. Thus, it is very close to the minimum expression of the intended idea.

One mans verbosity is another's great literary detail.

The same is true for programming languages, the fact some languages make you two say 2 lines, to achieve what another language does with one, can itself be a benefit or not. It might force the developer to make the same mistake twice, otherwise resulting in a compiler error. Or it might allow extra space for a mistake to creep in.

It is the perspective of the users and the context that determine if something is right or not. This project has apparently 14,000 classes, with about 3,500,000 lines of code. It is verbose, but it is also very manageable. A smaller more 'intelligent' less static language would make working with this a lot harder.

Re: Clojure core.async and Go: A Code Comparison

#72
post #5

Are the clojure threads actually lightweight? Thread/sleep is blocking so you'd need to occupy 10 threads right? If you wanted to sleep without blocking a real thread would you use an executor service to write to a channel after delay and block on that?

Isn't this a major difference between core.async and go?

If you perform a blocking operation (Thread/sleep there, but could be, for example, a socket read?) will you run the risk of exhausting the thread pool?

The go runtime handles this by detecting how many threads are in blocking syscalls and spawning more as needed (which I guess could be undesirable).

If I've understood correctly, this is perhaps best summarised as "go makes your sync code run well in goroutines, with core.async you can block everything with sync syscalls in your go block"?

Or perhaps just "go will adjust the size of your thread pool dynamically, core.async requires it to be big enough"

Re: Clojure core.async and Go: A Code Comparison

#73
post #4

I have never used Go or Clojure, but this is the first time I have heard of Go as being verbose - or is that just in comparison to Clojure?

It's the difference between "programmable programming languages" (which the lisps are, as are haskell and ruby) versus "languages for programming in" (exemplified by go and java). Go code is very terse compared to the general run of "languages for programming in". And if you know the language, you can just read it . On the other hand, you've got some serious digging to do if you want to understand a clojure macro. Me…

Another interpretation is that you can read "programmable programming languages" at the level of the problem domain, rather than at the level of the base language. (Assuming the problem domain is encoded sufficiently decently in a DSL).

Re: Clojure core.async and Go: A Code Comparison

#74
post #30

Quick question for anyone here familiar with core.async: Would it be possible (and if so what would be the simplest way) to implement something like Python's generators and `yield` statement in Clojure using core.async? I'm thinking something like: (defn range [n] (generator (loop [i 0] (yield i) (when ( 0 (generator) ;; => 1 ;; etc )

you could do it with channels, but also by extending the go macro itself. The mini compiler behind the go macro is designed to be extensible. In the test suite for core.async the compiler is run through a series of tests using a "runner" implementation of the go macro: https://github.com/clojure/core.async/blob/master/src/test/c... I've had generators working several times with an approach like this, but as it doesn'…

Aha, thanks for the pointers, that helps. I suspected something simpler might be possible using these ioc macros but was frankly a bit scared off by them at first :)

It'd be nice if the coroutine/inversion-of-control stuff was given a stable public API at some point, because those macros seem very powerful and neat in themselves and might have other interesting uses aside from channels.

Re: Clojure core.async and Go: A Code Comparison

#75
post #29

This is very cool and intressting. I have to think about something to do with core.async. This is also a good example why macros are just awesome. Go is a language design to work well with goroutins and channels, but the clojure code looks just as good and readable. You could simply not have such idiomatic use of these concepts without macros. Or am I wrong, can a flexible language like scala or python be extended to…

>but the clojure code looks just as good and readable. But don't mistake this for having the same runtime characteristics- For what its worth the Computer Language Benchmarks Game shows Go as generally being faster, using much less memory and less code. http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?t...

Agreed on go being faster and using less memory, however, in practice, I think idiomatic clojure would have less code then compared idiomatic go, when writing similar programs.

Re: Clojure core.async and Go: A Code Comparison

#76
post #49

Totally off topic, when i see ")))))))" it makes me want to run the other way.

Fair point, but once you understand that every clojure form is:

(function arg1 arg2 ... argN)

The same impulse that made you want to run the other way should make you want to run screaming towards the language. :)

Re: Clojure core.async and Go: A Code Comparison

#77
post #47
post #38

Earlier quoted context omitted.

Oh for sure, more as an exercise in curiosity than anything else. (Although I am also playing with generator- and iterator-like abstractions as part of a resource-scoped foldable stream abstraction to help process big files.) Looks like I managed to answer the 'is it possible?' part of the question anyway -- something like this: (defn range [n] (let [c (chan)] (go (loop [i 0] (>! c i) (if (

Yes, but I wouldn't do that. Every time you pull an item out of the channel, you actually submit a task to execute in a separate thread pool (to produce the next number), block your own thread, and wait for the task to complete on its thread and then wake your thread up. That's a lot of task-switching going on just to generate the next consecutive number :) OTOH, you could use async's coroutine code (used to implemen…

Yep I figured this would probably not be very efficient.

About lazy sequences: sometimes you want to avoid the allocation of lots of intermediate cons cells when mapping/filtering/etc. The reducers framework for example manages to avoid this sort of cost when the data structure supports something faster than first/rest recursion. I'm interested in extending reducers to work nicely over large files and other sequences which don't fit in memory, and some kind of iterable or generator-like abstraction could play a useful role in this.

(Actual coroutine-based generators might not be necessary, but would allow for a neat outward-facing API)

Re: Clojure core.async and Go: A Code Comparison

#78

Are the first two examples equivalent? In the go version, an anonymous function is being declared and then called with the value of the outer 'i'. In the clojure version, it appears that the value of 'i' is part of the closure for that function. The go version does what it does to avoid a race condition, because the goroutines are being spun up in the background and it's highly likely that it will take longer to spin…

It's a difference of the language. In the Go version, i is a mutable variable that can be read and written to. In Clojure, it's an immutable bound value. The i of one iteration is not in any way directly linked to the i of another iteration.

[deleted]

Re: Clojure core.async and Go: A Code Comparison

#79

Earlier quoted context omitted.

>but the clojure code looks just as good and readable. But don't mistake this for having the same runtime characteristics- For what its worth the Computer Language Benchmarks Game shows Go as generally being faster, using much less memory and less code. http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?t...

Agreed on go being faster and using less memory, however, in practice, I think idiomatic clojure would have less code then compared idiomatic go, when writing similar programs.

> would have less code

Based on what?

Re: Clojure core.async and Go: A Code Comparison

#80
post #67

Earlier quoted context omitted.

>but the clojure code looks just as good and readable. But don't mistake this for having the same runtime characteristics- For what its worth the Computer Language Benchmarks Game shows Go as generally being faster, using much less memory and less code. http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?t...

That is true. I have not looked at the much of the clojure code and non of the go code but both probebly are written in a very unidiomitic style that one does normally not use. Also with clojure, the actual timeconsuming calculations can be made with java and that should be at least as fast as go (with a bit more memory). So all in all I value the architectural things much more then pure speed. Go simply has a diffre…

> I have not looked at the much of the clojure code and non of the go code

:-)

> can be made with java

Would that be idiomatic Clojure? :-)

Post reply on HN