Re: Help Getting Sente to Work

2014-07-26 Thread Bob Hutchison

Hi Tim,

I think I went through this when I was first starting with Sente. You need to 
setup the CSRF handling part, in the example code by including 
ring-anti-forgery/wrap-anti-forgery in your routes. *AND* you have to make sure 
that you are using one of those routes before you try to use Sente's connection 
stuff, otherwise your session won't have certain critical attributes set (e.g. 
__anti-forgery-token). I think the 404s are from the anti-forgery stuff 
rejecting your request. And I think Sente is assuming it's setup. This was a 
while ago so maybe I'm not remembering it quite right.

Cheers,
Bob

On Jul 26, 2014, at 12:33 AM, Timothy Washington twash...@gmail.com wrote:

 Hi all, 
 
 I'm using [com.taoensso/sente 0.15.1], and having trouble connecting the 
 client to the server. I'm sure it's something simple, but not obvious, as 
 this is taken directly from the examples on sente's github page. Anyone seen 
 and fixed the error in fig.1? The clojurescript and clojure code are in fig 2 
 and 3 respectively. 
 
 
 WebSocket connection to 'ws://172.28.128.5:58269/chsk' failed: Error during 
 WebSocket handshake: Unexpected response code: 404
 WebSocket error: [object Event] VM1707:1689
 Chsk is closed: will try reconnect (8). VM1707:1689
 
 fig.1 - Chrome network error message 
 
 (ns my.ns
   (:require-macros
[cljs.core.match.macros :refer (match)] ; Optional, useful
[cljs.core.async.macros :as asyncm :refer (go go-loop)])
   (:require
;;[clojure.browser.repl :as repl]
[cljs.core.match] ; Optional, useful
[cljs.core.async :as async :refer (! ! put! chan)]
[taoensso.sente :as sente :refer (cb-success?)]))
 
 
 (let [{:keys [chsk ch-recv send-fn state]}
   (sente/make-channel-socket! /chsk {:type :auto})]
 
   (def chsk   chsk)
   (def ch-chskch-recv) 
   (def chsk-send! send-fn) 
   (def chsk-state state))
 
 (defn one []
   (chsk-send! [:some/request-id {:name Rich Hickey :type Awesome}]))
 
 fig.2 - my.cljs 
 
 
 (ns my.http.ns
   (:require [compojure.core :refer :all]
 ...
 
 ;; Sente stuff
 [clojure.core.match :as match :refer (match)] ; Optional, useful
 [clojure.core.async :as async :refer (! !! ! !! put! chan go 
 go-loop)]
 [taoensso.sente :as sente]))
 
 
 (let [{:keys [ch-recv send-fn ajax-post-fn ajax-get-or-ws-handshake-fn]}
   (sente/make-channel-socket! {})]
   
   (def ring-ajax-postajax-post-fn)
   (def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn)
   (def ch-chsk   ch-recv)
   (def chsk-send!send-fn))
 
 ...
 
 (defn create-approutes [project-config browserrepl]
 
   (defroutes app-routes
 
 ;; Sente stuff
 (GET  /chsk req (ring-ajax-get-or-ws-handshake req)) ; tried both 
 ring-ajax-get-or-ws-handshake and #'ring-ajax-get-or-ws-handshake
 (POST /chsk req (ring-ajax-postreq)); same here 
 for trying both 
 
 
 (GET / []
  (- (ring-resp/response (with-browser-repl index.html browserrepl))
  (ring-resp/content-type text/html)))
 
 (route/resources / {:root resources/public/})
 (route/not-found Not Found)))
 
 fig.3 - my.clj 
 
 
 Tim Washington 
 Interruptsoftware.com 
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Is this behavior with recur and pre/post a bug?

2014-07-25 Thread Bob Hutchison

On Jul 25, 2014, at 12:27 AM, Michael O'Keefe michael.p.oke...@gmail.com 
wrote:

 Andy, good advice and I agree. Thanks. I'll think on it then.

Would you want one of your users going though this kind of thought process: I 
won't file a ticked because I don't think it can be fixed? It's a bug, file the 
ticket. At the very least it can be documented.

Cheers,
Bob


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: unexpected behavior of clojure.core/empty

2014-07-18 Thread Bob Hutchison

On Jul 18, 2014, at 5:45 AM, Brian Craft craft.br...@gmail.com wrote:

 = (empty [:foo 5])
 []
 = (first (mapv identity {:foo 5}))
 [:foo 5]
 = (empty (first (mapv identity {:foo 5})))
 nil

= (class (first (mapv identity {:foo 5})))
clojure.lang.MapEntry
= (class (first (mapv (fn [[k v]] [k v]) {:foo 5})))
clojure.lang.PersistentVector
= (empty (first (mapv (fn [[k v]] [k v]) {:foo 5})))
[]

by mapping identity over the map you're returning a vector of MapEntries (which 
print/deconstruct like a two element array).

Cheers,
Bob

 
 What just happened there? Is this expected? In the second and third cases the 
 type of the vector is clojure.lang.MapEntry, which I expect is the root of 
 the behavior, but this seems very inconsistent. Is there a way to get the 
 behavior one would expect? Should clojure.core/empty be avoided?
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Local variable

2014-07-08 Thread Bob Hutchison

On Jul 8, 2014, at 9:40 AM, Cecil Westerhof cldwester...@gmail.com wrote:

 In Clojure you can define a local constant with let, but I need a variable (I 
 think).
 
 I want to do the following. I have a function that checks several things. 
 Every time an error is found I want to set the variable errors to:
 (concat errors new-error)
 
 Is this possible? Or is there a better way to do this?

Here's a different take on your question, and a few comments about how I'd 
write that code. I don't think you need the atom -- kinda ugly and the 
reduce/map/filter family of sequence functions will take you a long way.

; This is not a predicate, so don't use the -p suffix (and in Clojure it's a ? 
normally)
; There's no reason not to pass those two objects into this function, so I do.
(defn errors-in-datastruct [locations objects]
  (if (= (count objects) (count locations))
; 'remove' makes a new sequence containing elements that had a falsey 
; (false or nil) result to the provided function -- that is the objects
; with no location

; the mapv maps a function over a sequence resulting in a vector.
; the function creates a vector pair for each object containing the error
; code and object

; I find vectors more natural to use in Clojure

; I also find keywords more natural (and useful)

; In my mind, finding the errors and reporting them are two separate 
functions. If you want to make
; a nicer error report, then map a reporting function over the error codes.

(mapv #(vector :no-location %) (remove locations objects))

; This reduce does something similar to the mapv/remove combination above, 
but 
; it gives you more flexibility.

#_(reduce (fn [errors obj] 
(if (locations obj) 
  errors 
  (conj errors [:no-location obj]))) [] objects)

[[:counts-differ]]))

; use locally scoped variables if you can
(let [locations {:whiskey :living-room
 :bucket  :living-room
 :chain   :garden
 :frog:garden
 :dummy   :nowhere}]
  (println (errors-in-datastruct locations [:whiskey :bucket :chain :frog 
:dummy]))
  (println (errors-in-datastruct locations [:whiskey :bucket :chain :frog :pole 
:dummy]))
  (println (errors-in-datastruct locations [:whiskey :bucket :chain :frog 
:pole]))
  (println (errors-in-datastruct locations [:whiskey :bucket :chain :frog1 
:pole]))
  (println (errors-in-datastruct locations [:whiskey :whiskey :whiskey :whiskey 
:whiskey])))


; If you need to use the same locations map and don't want to pass it around, 
you can
; partially apply the errors-in-datastruct function to the locations, and use 
that function.
; You probably don't care about this but the technique can be very handy when 
getting
; rid of global variables.
(let [f (partial errors-in-datastruct {:whiskey :living-room
   :bucket  :living-room
   :chain   :garden
   :frog:garden
   :dummy   :nowhere})]
  (println (f [:whiskey :bucket :chain :frog :dummy]))
  (println (f [:whiskey :bucket :chain :frog :pole :dummy]))
  (println (f [:whiskey :bucket :chain :frog :pole]))
  (println (f [:whiskey :bucket :chain :frog1 :pole])))


I hope you can make sense of that :-)

Cheers,
Bob

 
 -- 
 Cecil Westerhof
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Local variable

2014-07-08 Thread Bob Hutchison

On Jul 8, 2014, at 7:08 PM, Cecil Westerhof cldwester...@gmail.com wrote:

 2014-07-08 23:11 GMT+02:00 Bob Hutchison hutch-li...@recursive.ca:
 
 On Jul 8, 2014, at 9:40 AM, Cecil Westerhof cldwester...@gmail.com wrote:
 
  In Clojure you can define a local constant with let, but I need a variable 
  (I think).
 
  I want to do the following. I have a function that checks several things. 
  Every time an error is found I want to set the variable errors to:
  (concat errors new-error)
 
  Is this possible? Or is there a better way to do this?
 
 Here's a different take on your question, and a few comments about how I'd 
 write that code. I don't think you need the atom -- kinda ugly and the 
 reduce/map/filter family of sequence functions will take you a long way.
 
 ; This is not a predicate, so don't use the -p suffix (and in Clojure it's a 
 ? normally)
 
 ​As I understood it (I am rewriting land of lisp to Clojure) that when a 
 function returns a true/false state, that you then use the -p suffix. When 
 returning () there are no errors. But I should use the ? then?

You’re returning a list of errors. You can interpret that as a truthy/falsy 
kind of thing, in which case make sure you’re returning a nil for the no-error 
case. And use the ‘?’ in Clojure.

 
 ​ 
 ; There's no reason not to pass those two objects into this function, so I do.
 
 ​Good idea. Makes it easy to test the function also.

it does

 
 […]​ 
  
 I hope you can make sense of that :-)
 
 ​Not immediately. I need to digest it.

Have fun.

 
 By the way. The current function is only the start of the checks.​  ​After 
 the if I need to do several other checks also. So I think I do need the atom. 
 But maybe I am mistaken. ;-)

I thought maybe your checks would be a little more than that. That’s why I left 
the ‘reduce’ version in there. Just make the function that is applied by reduce 
more powerful, perhaps pull it out into a separate function rather than an 
inline anonymous function. This will work as long as all tests are performed on 
one object at a time.

No matter what, I’d recommend not going using an atom if you can help it.

Cheers,
Bob

 
 -- 
 Cecil Westerhof
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Workflow: cljx, cljsbuild tdd in one process

2014-06-22 Thread Bob Hutchison
Thanks for the tip, works nicely. I was doing the same thing Michal was doing.

Cheers,
Bob

On Jun 20, 2014, at 11:07 AM, Michael Griffiths mikeygriffi...@gmail.com 
wrote:

 There's also a Leiningen plugin called lein-pdo that lets you run tasks in 
 parallel: https://github.com/Raynes/lein-pdo
  
 Example usage for cljx auto  cljsbuild auto: 
 https://github.com/DomKM/omelette/blob/master/project.clj#L59
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Clojure:Lisp :: LSD:Meditation

2014-06-13 Thread Bob Hutchison

On Jun 13, 2014, at 6:58 AM, Jonas jonas.enl...@gmail.com wrote:

 I found this post from 2011 which probably is still relevant: 
 https://groups.google.com/d/msg/clojure/t0pGIuoyB7I/RQtuuAOhes8J

And just for fun, from that thread... Rich Hickey wrote:

There will be times, yes, when the most considerate thing will be to write 
opinions in a blog post, perhaps putting only a pointer here and following up 
on the blog.


 
 On Friday, June 13, 2014 1:05:47 PM UTC+3, David Della Costa wrote:
 You raise a good point, which is that I don't know what the group policy 
 is or where it's posted.  I just see this in the header on the google 
 groups page: 
 
 Welcome to the Clojure mailing list. Please note that posts by new 
 members are moderated to prevent spam. 
 
 Anyone know better than this? 
 
 (2014/06/13 18:50), Josh Kamau wrote: 
  If i were to be asked, i would restrict the group to: 
  1. Any type of question that is related to clojure 
  2. Any type of announcement on clojure core library 
  3. Any new library/version 
  4. Any link to a narration on real life usages (e.g how we did xyz with 
  clojure) or benchmarks  (generally hard facts ) 
  5. Any link to new book, tutorial, training materials. 
  
  This is just my opinion, I dont know the group policy and may be its all 
  up to me to choose what i want to read and what i dont want to and 
  probably keep my feelings to myself ;) 
  
  Josh 
  
  
  On Fri, Jun 13, 2014 at 12:34 PM, Dave Della Costa 
  ddell...@gmail.com mailto:ddell...@gmail.com wrote: 
  
  I'm not sure what the problem is here.  I've posted personal blog links 
  before that were Clojure related; I sincerely thought that it was 
  potentially useful to the group, and I more or less got responses that 
  supported that. 
  
  That being the case, I'm having a hard time understanding what is so 
  different about my blog post and Divyansh's; as far as I can tell, this 
  post is relevant to Clojure, even if it's a bit more...exploratory.  It 
  has Clojure code examples, it talks about Common Lisp and Python and 
  metaprogramming.  It's clearly not random spam. 
  
  So it seems to me that some folks simply don't like the content; that's 
  fine, but I think it's a stretch to say that it's not appropriate for 
  this list.  Or if it is not appropriate, then even relevant blog posts 
  should never be appropriate, and arguably stuff like, say, epic 
  ruminations on the nature of literate programming would arguably be 
  even 
  less appropriate for the list. 
  
  DD 
  
  (2014/06/13 11:25), Gary Trakhman wrote: 
   To be fair, I actually read the thing, but I hoped to see more 
   interesting information on LSD, meditation and Clojure than the 
  headline 
   would suggest :-). 
   
   
   On Thu, Jun 12, 2014 at 10:01 PM, Atamert Ölçgen mu...@muhuk.com 
  mailto:mu...@muhuk.com 
   mailto:mu...@muhuk.com mailto:mu...@muhuk.com wrote: 
   
   There's also Planet Clojure http://clojure.in/. 
   
   @Divyansh 
   
   Josh, Hussein and Gary are not the only ones who think this 
  sort of 
   traffic building is uncool. By traffic building I mean; sending a 
   message with a link that has no valuable information for the 
  group 
   members. They are probably just nodding their head and 
  thinking that 
   sending another response is not necessary. At least that's what I 
   did before I saw your response. 
   
   90% of the messages in this group doesn't interest me. That's 
  fine. 
   Valuable information for someone else. But I certainly 
  wouldn't want 
   everybody to post their blogs here regularly. Because each 
  message 
   is a tiny little distraction. I'm willing to pay the price 
  because 
   when a really cool library is announced for example, I get a big 
   reward. Let's keep the benefit/cost ratio, time-wise  
   attention-wise, high. 
   
   
   
   
   On Thu, Jun 12, 2014 at 10:05 PM, Gary Trakhman 
   gary.t...@gmail.com mailto:gary.t...@gmail.com 
  mailto:gary.t...@gmail.com mailto:gary.t...@gmail.com 
  wrote: 
   
   Twitter's a more organic way to do this.  Your followers can 
   read it, decide to retweet or not. 
   
   
   On Thu, Jun 12, 2014 at 5:37 PM, Divyansh Prakash 
   divyansh...@gmail.com 
  mailto:divyansh...@gmail.com 
   mailto:divyansh...@gmail.com 
  mailto:divyansh...@gmail.com wrote: 
   
   Sorry if you feel that way. Thought i could share my 
   thoughts and start an interesting discussion. 
   That is what the group is for. 
   You are obviously free to skip anything that doesn't 

Re: in Clojure I rarely find myself reaching for something like the state monad, as I would in Haskell

2014-05-19 Thread Bob Hutchison

On May 16, 2014, at 8:49 PM, Julian juliangam...@gmail.com wrote:

 A quick shoutout to the Clojure Community - thanks for the way you've all 
 contributed to make my life (mentally) richer. 
 
 James Reeves (author of Compojure and many other wonderful libraries) made 
 this interesting comment on Hacker News:
  Clojure has libraries that implement monads, but these aren't often used 
  for threading state. I can't quite place my finger on why, but in Clojure I 
  rarely find myself reaching for something like the state monad, as I would 
  in Haskell.
 Clojure tends to view mutability as a concurrency problem, and the tools it 
 provides to deal with mutability, such as atoms, refs, agents, channels and 
 so forth, are not mechanisms to avoid mutation, as to provide various 
 guarantees that restrict it in some fashion.
 It might be that in the cases where I'd use a state monad in Haskell, in 
 Clojure I might instead use an atom. They're in no way equivalent, but they 
 have some overlapping use-cases.
 https://news.ycombinator.com/item?id=7751424
 My question is - have other Clojure/Haskell programmers had this experience? 
 (ie I rarely find myself reaching for something like the state monad). I'm 
 interested to hear if so, and why. 
 

I'm perhaps an atypical specimen (and I'm not what I'd call an expert Haskell 
programmer) but... I've written a fairly substantial prototype in Haskell 
(maybe 25k sloc, whatever that means) that made heavy use of the state monad. 
I've re-written the same application in Clojure and it never, even once, 
occurred to me to use the state monad. As James Reeves pointed out, Clojure 
programmers normally use atoms or refs to manage this kind of state. Looking at 
my two code bases you'd notice that the state monad would have been replaced in 
Clojure by a bunch of refs and atoms. If the state had been less complex and 
the application less concurrent I'd have used a single atom.

In Haskell you'd not be able to use this technique nearly as frequently, if at 
all, and certainly not in the same way. 

Please excuse the imprecision in the following... 

In Haskell, all IO is marked in the type signatures, and so if you want to 
perform any IO you have to carry the IO monad with you (IO appears in your type 
signature) into all 'sub' computations. The IO monad exists at the top level of 
your program, and so must be 'carried' all the way from the top level, you 
can't just suddenly start using IO deep within some computation. And this is 
exactly what you want in Haskell -- it's a *good* thing. In Clojure you can 
perform IO wherever you wish, and in Clojure this is exactly what you want, and 
is also a *good* thing. 

Haskell's STM transactions can be thought of as a form of IO action (like 
reading a file is an IO action) that modify refs (there are no atoms in 
Haskell, only refs). A transaction must be started in the IO monad and then, 
like IO, the STM monad is 'carried' in type signatures through all intervening 
computations that could take part in the transaction. The STM type/monad 
'blocks' the IO type/monad (you can't do other IO actions if you might take 
part in an STM transaction (IO action), this is an effect of, and enforced by, 
Haskell's type system (i.e. it's a compilation not a runtime error)). In 
Clojure the STM isn't part of the IO system, and you can start or take part in 
a transaction anywhere you want to, even nest dosyncs within a single 
transaction, and intermingle transactional code with IO (no matter how bad an 
idea that is).

That's a lot of talk to get to the point that using the STM has an 
insignificant impact on the structure of your Clojure programs, while in 
Haskell the impact is huge (of course, it's possible to argue that that's a 
*good* thing). In Haskell the state monad is pretty flexible, well supported by 
the language, and allows you to sidestep a lot of this impact (for one thing, 
you can introduce it anywhere). In Clojure the state monad would buy you 
nothing (in my opinion) while using it would have an impact on your programs 
structure. In Haskell there are forces pushing you to use the state monad, 
while in Clojure there are forces pushing you away from the state monad.

In my opinion.



I've 'simplified' my explanation, and obscured some of the actual 
issues/powers/advantages of Haskell's type system. For example, I hand-wavingly 
using the phrase 'you can/can't introduce...' -- it isn't quite like that, but 
that's the effect, so, I think, close enough for this discussion.

 

As an aside, a Clojure programmer might get a feel for what Haskell's state 
monad is like by considering the - and - macros. Within the - macro you 
start by defining your initial state then applying a sequence of operations to 
an updated state. You don't have to mention the state in your code again. The 
functions called in the - and - macros have either their first or last 
argument 'receiving' the state and returns the updated 

Re: in Clojure I rarely find myself reaching for something like the state monad, as I would in Haskell

2014-05-19 Thread Bob Hutchison

On May 19, 2014, at 1:44 PM, Ben Wolfson wolf...@gmail.com wrote:

 I wouldn't say that I *often* find myself reaching for monads, or the state 
 monad in particular, but I certainly have found them useful on occasion (and 
 would have sometimes refrained from using them where I'd naturally lean to 
 doing so solely to avoid creating an dependency). For instance, whenever 
 there's a couple of functions that return either a success value or an error 
 message that have to be threaded together---an error monad to do the plumbing 
 makes this a lot nicer.

I badly miss the Maybe and Either monads, but would want the syntactic support 
Haskell provides (which I can't see will ever be available in Clojure)

 
 We've got a library at ReadyForZero for walking though json and xml 
 structures and doing transformations based on the values found there, or a 
 bit of configuration, using a combined reader-writer-state monad, and a bunch 
 of code that uses it. The state that's held is actually just a zipper into 
 the structure, the configuration at this point is only a keyword, and the 
 writer log holds reports of unexpected values. This could all be done with 
 other machinery---pass the zipper around directly (or hold it in an atom), 
 pass the log around directly (or hold it in an atom), use a dynamic variable 
 + binding for the configuration (since the reader monad amounts to that 
 anyway). However, I think the monadic code is easier to work with, partly 
 because nothing does need to be managed or passed around explicitly (so it's 
 easier to put together lots of little pieces), and partly because it enables 
 the use of generic tools. Also, traversing the the structures has a fairly 
 imperative feel---go here, go there, do this transformation---with occasional 
 variable binding, and the macro for monadic computations the monad library 
 we're using provides makes expressing that fairly convenient. (Though I may 
 be biased, since I wrote it.)
 
 It's true that there doesn't seem to be much need for introducing a monad 
 library and using the state monad if you *only* had the state monad, since 
 Clojure has other ways to deal with mutation (incidentally, I don't think 
 it's true to say that Haskell only has refs, not atoms; there are functions 
 to modify IORefs, which live outside the STM system, atomically).

Which is why I didn't call them atoms :-) There's also a ref in the ST monad 
(which is a bells-and-whistles state monad that has fallen into a bit of disuse 
since the IO monad appeared)

 
 
 
 On Fri, May 16, 2014 at 5:49 PM, Julian juliangam...@gmail.com wrote:
 A quick shoutout to the Clojure Community - thanks for the way you've all 
 contributed to make my life (mentally) richer. 
 
 James Reeves (author of Compojure and many other wonderful libraries) made 
 this interesting comment on Hacker News:
  Clojure has libraries that implement monads, but these aren't often used 
  for threading state. I can't quite place my finger on why, but in Clojure I 
  rarely find myself reaching for something like the state monad, as I would 
  in Haskell.
 Clojure tends to view mutability as a concurrency problem, and the tools it 
 provides to deal with mutability, such as atoms, refs, agents, channels and 
 so forth, are not mechanisms to avoid mutation, as to provide various 
 guarantees that restrict it in some fashion.
 It might be that in the cases where I'd use a state monad in Haskell, in 
 Clojure I might instead use an atom. They're in no way equivalent, but they 
 have some overlapping use-cases.
 https://news.ycombinator.com/item?id=7751424
 My question is - have other Clojure/Haskell programmers had this experience? 
 (ie I rarely find myself reaching for something like the state monad). I'm 
 interested to hear if so, and why. 
 JG
 PS If this post is unhelpful, could be worded better - please let me know. 
 I'm asking out of curiosity, not with intent to troll. 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.
 
 
 
 -- 
 Ben Wolfson
 Human kind has used its intelligence to vary the flavour of drinks, which 
 may be sweet, aromatic, fermented or spirit-based. ... Family and social life 
 also offer numerous other occasions to consume drinks for pleasure. 
 [Larousse, Drink entry]
 
 
 -- 
 You received this message because you are subscribed 

Re: in Clojure I rarely find myself reaching for something like the state monad, as I would in Haskell

2014-05-19 Thread Bob Hutchison

On May 19, 2014, at 1:50 PM, Ben Wolfson wolf...@gmail.com wrote:

 On Mon, May 19, 2014 at 7:48 AM, Bob Hutchison hutch-li...@recursive.ca 
 wrote:
 
 Haskell's STM transactions can be thought of as a form of IO action (like 
 reading a file is an IO action) that modify refs (there are no atoms in 
 Haskell, only refs). A transaction must be started in the IO monad and then, 
 like IO, the STM monad is 'carried' in type signatures through all 
 intervening computations that could take part in the transaction. The STM 
 type/monad 'blocks' the IO type/monad (you can't do other IO actions if you 
 might take part in an STM transaction (IO action), this is an effect of, and 
 enforced by, Haskell's type system (i.e. it's a compilation not a runtime 
 error)). In Clojure the STM isn't part of the IO system, and you can start or 
 take part in a transaction anywhere you want to, even nest dosyncs within a 
 single transaction, and intermingle transactional code with IO (no matter how 
 bad an idea that is).
 
 You can use regular IO in an STM action with unsafeUItoSTM: 
 http://hackage.haskell.org/package/base-4.7.0.0/docs/GHC-Conc-Sync.html#v:unsafeIOToSTM.
  IMO it's advantageous that you have to explicitly say that you want to do IO 
 inside a transaction, given that (in general) you probably shouldn't be doing 
 it.

You're right. I didn't want to bring that up though. It's well named. I used 
the various unsafe* functions regularly while debugging, and even then only for 
writing to the console. I would be *very* *very* reluctant to use any of them 
in production, and certainly not intentionally design something that required 
their use. So, for the purposes of this discussion, I figured I'd just pretend 
they didn't exist.

Cheers,
Bob

 
 -- 
 Ben Wolfson
 Human kind has used its intelligence to vary the flavour of drinks, which 
 may be sweet, aromatic, fermented or spirit-based. ... Family and social life 
 also offer numerous other occasions to consume drinks for pleasure. 
 [Larousse, Drink entry]
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: in Clojure I rarely find myself reaching for something like the state monad, as I would in Haskell

2014-05-19 Thread Bob Hutchison

On May 19, 2014, at 2:45 PM, Ben Wolfson wolf...@gmail.com wrote:

 On Mon, May 19, 2014 at 11:28 AM, Bob Hutchison hutch-li...@recursive.ca 
 wrote:
 
 I badly miss the Maybe and Either monads, but would want the syntactic 
 support Haskell provides (which I can't see will ever be available in Clojure)
 
 I've been pretty happy with: 
 https://github.com/bwo/monads/blob/master/src/monads/core.clj#L65
 

Hmm. I'm going to have to take another look at that. Thanks!

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Do not understand why loop takes 3 arguments who are all the same

2014-05-03 Thread Bob Hutchison
Hi Roelof,

On May 3, 2014, at 3:09 AM, Roelof Wobben rwob...@hotmail.com wrote:

 Hello, 
 
 Im now at the last exercise of the beginners exercise of 4clojure.

nice!

 
 I figured out that this solution works.
 
 (fn [default lijst1]
   (loop [lijst lijst1 d {}]
  (if (empty? lijst)
d
(recur (rest lijst) (assoc d (first lijst) default)

Yes, it passes the unit tests.

 
 But as I see it lijst lijst 1 and d are all the same. They all contains the 
 collection which has to fill in the end collection.
 As a example I mean  default = 0 lijst 1 [:a :b: :c] 
 then lijst1 and d also contains [:a :b:c]  so what is then the point of using 
 3 arguments.

There's only two arguments (to the loop and to the function). I re-wrote your 
code changing the names of variables and adding a few line breaks as:

(fn [default initial-keys]
  (loop [remaining-keys initial-keys
 result-map {}]
 (if (empty? remaining-keys)
   result-map
   (let [key (first remaining-keys)
 remaining-keys' (rest remaining-keys)
 result-map' (assoc result-map key default)]
 (recur remaining-keys' result-map')

This also passes the unit tests.

Maybe that's a bit clearer as to what's going on. Maybe the new names help a 
bit. Notice the ticks on some of the names (the ' characters). This is just a 
convention some programmers use. The ticks are part of the name, nothing magic, 
and are used to indicate that the value of the name is derived from the value 
of the name with one less tick. Some programmers use numbers instead. Other 
programmers don't care and just use the same name.

When you've understood the solution you've come up with, you might want to try 
using reduce to do this. It'll be both shorter and much easier to understand. 
If you look carefully at your code the only part that isn't boiler-plate is the 
(assoc result-map key default) -- the boiler-plate corresponds closely to what 
reduce does.

I hope this doesn't confuse you even more.

Cheers,
Bob
 
 
 Roelof
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Do not understand why loop takes 3 arguments who are all the same

2014-05-03 Thread Bob Hutchison

On May 3, 2014, at 6:42 AM, Roelof Wobben rwob...@hotmail.com wrote:

 
 (fn [default initial-keys]
   (loop [remaining-keys initial-keys
  result-map {}]
  (if (empty? remaining-keys)
result-map
(let [key (first remaining-keys)
  remaining-keys' (rest remaining-keys)
  result-map' (assoc result-map key default)]
  (recur remaining-keys' result-map')
 
 This also passes the unit tests.
 
 Maybe that's a bit clearer as to what's going on. Maybe the new names help a 
 bit. Notice the ticks on some of the names (the ' characters). This is just a 
 convention some programmers use. The ticks are part of the name, nothing 
 magic, and are used to indicate that the value of the name is derived from 
 the value of the name with one less tick. Some programmers use numbers 
 instead. Other programmers don't care and just use the same name.
 
 When you've understood the solution you've come up with, you might want to 
 try using reduce to do this. It'll be both shorter and much easier to 
 understand. If you look carefully at your code the only part that isn't 
 boiler-plate is the (assoc result-map key default) -- the boiler-plate 
 corresponds closely to what reduce does.
 
 
 Thanks,
 
 Now It more clearer what loop does.
 I can look at a reduce solution but then I have to look which reduce I have 
 to use.
 I know  reduce + and reduce - which does calculations on the collection.

This reduce: http://clojuredocs.org/clojure_core/clojure.core/reduce is what 
you need.

Cheers,
Bob

 
 Roelof
  
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Clojure equivalent of special common lisp vars: still looking for that zen place...

2014-05-03 Thread Bob Hutchison

On May 3, 2014, at 9:45 AM, Dave Tenny dave.te...@gmail.com wrote:

 I'm still struggling with how to write the most readable, simple clojure code
 to deal with dynamically bindings.
 
 What is the graceful clojure equivalent of common lisp special variables for 
 the following scenario.
 
 If I were writing common lisp I'd just do something like (pardon if my lisp 
 is rusty here):
 
 (defvar *x* 1)
 ... do stuff with *x* ...
 (setq *x* 2)
 ... do stuff with *x* ...
 (let ((*x* 3))  (do stuff with *x*...)
 ;; do stuff with *x* that's currently at 2
 
 
 The way I'm tempted to do this in clojure is
 
 (def ^{:dynamic true} *x* (atom 1))
 ... do stuff with @*x* ...
 (reset! *x* 2)
 ... do stuff with @*x* ...
 (binding [*x* (atom 3)] (do stuff with @*x*))

Inside the binding you can call set! if you must.

You can also just use 'def' to redefine the global binding. It says this:

Using def to modify the root value of a var at other than the top level is 
usually an indication that you are using the var as a mutable global, and is 
considered bad style. Consider either using binding to provide a thread-local 
value for the var, or putting a ref or agent in the var and using transactions 
or actions for mutation. in the docs at http://clojure.org/special_forms#def 
which is roughly what you did with the atom. But it'll work.

You can also just write it:

(def ^:dynamic *x* (atom 1))

which is a little less verbose.

Cheers,
Bob

 
 
 Is that the simplest way to map between the two language scenarios?
 Or is there something simpler, perhaps using some var-* apis or what have you?
 
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: My experiments with concurrent programming

2014-04-13 Thread Bob Hutchison
Hi Cecil,

On Apr 12, 2014, at 3:18 PM, Cecil Westerhof cldwester...@gmail.com wrote:

 
 I just started playing with Clojure a few days ago, so I am a tabula rasa. I 
 attached what I have until now. If it can be improved, I like to know it.

I had a look at your code and it's not clear to me what you are trying to 
experiment with. Possibly benchmark using futures to run the do-sequential 
function concurrently. I'll assume that for the moment and make a couple of 
observations...

You are using atoms to store two values (max-diff and max-factor) that are used 
and changed in main-function. Did you really intend to share these across all 
the calculations? The code you've provided will have concurrency errors as a 
result. You might consider writing this as something like (the *completely* 
untested and so only good as a sketch):

(def max-diff (ref 0.0))
(def max-factor (ref 0.0))

(defn init [type]
  (give-message (format Start %s type))
  (dosync
(ref-set max-diff   0.0)
(ref-set max-factor 0.0)))
   
(defn main-function [i diff]
  (dosync
(ensure max-diff)
(ensure max-factor)
(when ( diff @max-diff)
   (give-message (format Different for %12d (%e, %e) i diff (/ diff i)))
   (alter max-diff max diff)
   (when ( (/ diff i) @max-factor)
 (alter max-factor max (/ diff i)

The 'ensures' are there because max-diff and max-factor aren't really 
independent and some interaction between concurrent threads in the outer when 
could lead to some strange situations (like testing for max-diff (or 
max-factor) then finding that some other thread ran and changed max-diff (or 
max-factor) out from under you.

Your concurrency will likely be restricted to (some subset) of your cores since 
there's no IO in there (you're dumping the actual logging off to an agent). 
This isn't a bug, just mentioning it, but there's something to think about 
below.

There's a problem in your calculation of diff... it's always 0.0 which means 
that there's nothing being done in main-function. I changed it to something 
arbitrary (and *completely* untested and so only good as a sketch):

  (let [v (int (Math/sqrt i))
diff (Math/abs (- (Math/pow v 2) i))]

No idea if that's reasonable, but at least main-function does something now.

With the hacked up calculation of diff, I was able to demonstrate the 
concurrency problem in main-function by simply running (the *completely* 
untested and so only good as a sketch):

(defn main-function [i diff]
  (swap! iterations0 inc)
  (when ( diff @max-diff)
(swap! iterations1 inc)
#_(give-message (format Different for %12d (%e, %e) i diff (/ diff i)))
(swap! max-diff max diff)
(when ( (/ diff i) @max-factor)
  (swap! iterations2 inc)
  (swap! max-factor max (/ diff i)

and printing the values of iterations* -- with your swap algorithm you get 
different values for iterations1 and sometimes iterations2 for successive run.

If you didn't intend to share max-diff and max-factor, then you'd likely be 
better off if do-sequential passed local values into main-function, something 
like (the *completely* untested and so only good as a sketch):

(defn main-function [[max-diff max-factor] i]
  (let [v (int (Math/sqrt i))
diff (Math/abs (- (Math/pow v 2) i))]
(if ( diff max-diff)
  (do
#_(give-message (format Different for %12d (%e, %e) i diff (/ diff 
i)))
[(max max-diff diff) (max max-factor (/ diff i))])
  [max-diff max-factor])))

(defn do-sequential [start stop step]
  (reduce main-function [0.0 0.0] (range start stop step)))


You've decided to use futures for concurrency. Maybe that's the whole point, 
but if you're just trying to get a feel for concurrency in Clojure then there 
are some options. I find I directly use futures and promises, at most, rarely 
(I can't remember ever using them directly, maybe in the very early days of 
Clojure). What I find handy for this sort of thing is something like pmap, and 
if you really want this asynchronous then have a look at core.async. Anyway, 
with pmap (the *completely* untested and so only good as a sketch):

(defn check-concurrent [number]
  (doall
(pmap #(do-sequential % check-until number) (range 1 (inc number)

The shutdown-agents call is likely not what you want, you don't need it.

You're using agents for the logging. This gets the IO out of your code being 
tested, but there's still a lot of formatting work happening there (not much of 
a problem). But you don't know the impact of the agent thread pool on your 
benchmark. It's possible that it acts as a throttle. You can avoid this easily 
by not logging anything in main-function (I've commented it out in the example 
above).

Benchmarking is tricky to do. It's a lot easier to use something like 
criterium, kind of like this (I added the *verbose* dynamic variable for fun to 
the *completely* untested and so only good as a sketch):

(def ^:dynamic *verbose* true)
(defn 

Re: [ANN] durable-queue: an in-process disk-backed queue

2014-02-07 Thread Bob Hutchison

On Feb 6, 2014, at 6:45 PM, Zach Tellman z...@factual.com wrote:

 At Factual we get a lot of data thrown at us, and often don't have control 
 over the rate at which it comes in.  As such, it's preferable that our buffer 
 isn't bounded by the process' memory, since a temporary blip in throughput 
 may cause GC pauses, OOM exceptions, and other things that will only 
 exacerbate the problem.  It's also preferable that if the process dies, we 
 won't lose any data which hasn't yet escaped the process.  A disk-backed 
 queue satisfies both of these requirements.
 
 As such, I'm happy to announce that we're open sourcing 'durable-queue': 
 https://github.com/Factual/durable-queue.  It's a small, fast, pure-Clojure 
 implementation that in our production systems is responsible for processing 
 billions of entries daily.  We believe it has broad applications, and are 
 excited to see how others will use it.

What excellent timing! I've been looking at ZeroMQ, RabbitMQ, and Kafka for the 
last week or so. ZMQ is awfully attractive for what I'm trying to do, but there 
are a few things it doesn't do that I need done. I had begun thinking of 
building something similar on top of Redis.

You mention the idea of batching to reduce the impact of fsync. Is there an API 
for batching puts? Is there a way to batch a complete! and put! new tasks to 
the queue?

One pattern that keeps coming up is:
   - take a single task from the queue
   - execute the task, which might generate a set of new tasks to be queued on 
the same queue (and likely on other queues too)
   - signal completion, and put the new tasks

Cheers,
Bob

 
 Zach
 
 P.S. If this sort of work is interesting to you, Factual is hiring: 
 https://groups.google.com/forum/#!searchin/clojure/factual/clojure/8bPIEnNpfyQ/lvv-9gkVozAJ
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: core.async count in a channel

2014-01-21 Thread Bob Hutchison

On Jan 21, 2014, at 11:56 AM, Paul Viola vi...@highspot.com wrote:

 I think this is all well and good for a particular use of channel.
 
 So perhaps I am misusing channels??  
 
 To repeat: in one case I have workers pulling from a channel of real work. 
 For various reasons this channel might get filled rather deeply. In this case 
 I would want to add additional workers or get a bigger machine. I was 
 wondering if monitoring the channel for things like average depth (or 99 
 percentile) would give me the information I needed.
 
 

Often queue length isn’t a particularly good measure of what’s happening, nor a 
particularly good indicator of how to solve a problem, or even if there is a 
problem. You might consider measuring service time more directly by tracking 
how long requests take to be served. Then you might measure the utilisation of 
the workers, maybe by measuring how long they wait for a new job and how long 
it takes to complete a task. These measurements are pretty straightforward to 
implement in core.async (though it’d be more ‘efficient’ to build them right 
into channels). What to do in response to these numbers isn’t necessarily 
obvious (more workers? *fewer* workers? split the queue? faster CPU? More CPUs?)

Core.async introduces it’s own problem by banning unbound queues. The strategy 
of blocking clients as a consequence of maxing out a queue can be bad. So 
there’s a new problem that you have to deal with, making sure the channel size 
is big enough to handle any normal situation (which implies you to know what 
normal actually is, and sometimes you don’t know beforehand). To deal with this 
problem a channel count would be very helpful.

 
 I could of course just skip the channel business, and use a java queue is a 
 fine proposal.

Well…

  
 
 But since the producers of this work are truly asynchronous (attached to the 
 real world) I thought it best to keep the channel methodology.
 
 
 
 
 
 
 On Tue, Jan 21, 2014 at 5:11 AM, Aaron France aaron.l.fra...@gmail.com 
 wrote:
 On 21/01/14 14:09, Moritz Ulrich wrote:
 On Tue, Jan 21, 2014 at 9:43 AM, Aaron France aaron.l.fra...@gmail.com 
 wrote:
 Since channels yield nil when they are devoid of items, surely this is enough 
 to know when the channel is empty?
 That's not correct. Take-Operations block on empty channels. They
 yield nil when they're closed. You could add a timeout to the take
 operation to see if no item arrived in a specific time.
 
 Much appreciated for the clarification. It's the same in Go.
 
 I can imagine this pattern (take on a possibly closed channel being useful) 
 being useful but I'm not convinced knowing the count of channel is a safe 
 thing to know/care about.
 
 My $0.02, perhaps Clojure does this differently.
 
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- You received this message because you are subscribed to a topic in the 
 Google Groups Clojure group.
 To unsubscribe from this topic, visit 
 https://groups.google.com/d/topic/clojure/zD2jl-bIFXI/unsubscribe.
 To unsubscribe from this group and all its topics, send an email to 
 clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
 
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit 

Re: Effects of diving into Clojure

2014-01-14 Thread Bob Hutchison

On Jan 14, 2014, at 2:01 PM, gvim gvi...@gmail.com wrote:

 I recently took the plunge into learning Clojure and love it. Since I tend to 
 be single-minded/all-or-nothing about these things I'm now finding it very 
 difficult to switch mindset when I have to work with Ruby. Anyone else 
 experienced this?

I think everyone who makes the attempt to learn more than one different 
programming language experiences this at some early point (like their second 
major language :-), and then suffers unpredictably recurring bouts over time.

 If you get deeply into a programming language it alters the way you think and 
 approach design/solutions which is one reason I've never understood the 
 advice to try to learn many programming languages.

You’ve described one of the most important reasons behind that advice. Do you 
really think your Ruby experience has not informed your Clojure experience? And 
when you go back to Ruby do you really forget what you learned from Clojure? 
Even the most ‘useless’ of languages have something interesting to say about 
the problem they're designed to address (and for me, that’d be COBOL).

 With Clojure the functional/Lisp structure is so radically different and 
 elegant that switching to standard OO/mutable state/infix approaches starts 
 to feel alien. Maybe it's just me.

No it’s not just you. Hardly! However, I’d caution you against allowing this 
situation to continue. Preference is one thing. Isolating yourself from 
demonstrably successful ideas is another. Not to mention abandoning everything 
you’ve attained through the learning of Ruby. Keep going back and forth until 
all that’s left is preference.

Sorry for the pontificating :-)

Cheers,
Bob

 
 gvim
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Effects of diving into Clojure

2014-01-14 Thread Bob Hutchison

On Jan 14, 2014, at 3:46 PM, gvim gvi...@gmail.com wrote:

 No, you're probably right. It's just that there never seem to be enough hours 
 in a day/life :(

You’re not alone there either :-)

Cheers,
Bob

 
 gvim
 
 
 On 14/01/2014 20:26, Bob Hutchison wrote:
 
 No it’s not just you. Hardly! However, I’d caution you against allowing this 
 situation to continue. Preference is one thing. Isolating yourself from 
 demonstrably successful ideas is another. Not to mention abandoning 
 everything you’ve attained through the learning of Ruby. Keep going back and 
 forth until all that’s left is preference.
 
 Sorry for the pontificating :-)
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


library development

2013-12-20 Thread Bob Hutchison
Hi,

I’m missing something. And it’s annoying me.

Let’s say I’m working on three or four projects and there’s some code that 
really should be developed as a library and used by each of the projects. A 
similar thing happens if I fork a library from github. I don’t want to make any 
of this code public so clojars is not an option. It’s clear enough that the 
solution to this will involve a local maven repository somehow.

Now, I don’t know maven. I like it that way. I *do* *not* want to know maven. 
It’s so low on my priority list that reviewing the new C++ standard is higher. 
Basically it’ll never get to the top of the list.

Furthermore I think requiring someone to know maven to do any non-trivial 
Clojure development is a bad plan. This is surely one of the founding goals of 
Leiningen.

I’ve found some documentation and blog posts that, as soon as they get 
interesting, pretty much all end up assuming you know maven. I’ve found 
lein-localrepo plugin, which is was hopeful until you read it’s docs and see 
that it describes itself in maven terminology (why do I care what the maven 
coordinates of a file are? *WHY* do I have to know? Is this about Clojure or 
Java jar files? Are they different?)

Lein install makes a jar file and a pom file. So what? Is there something you 
do with these? There must be. But since I don’t know maven I’ve not got a clue 
what that might be.

What I’d like to do is type something no more complex than “lein local-install” 
and be done with it. I do not care if every developer on my team has to execute 
that command. I don’t care about sharing. I don’t care about naming. I just 
want to work on my library, install it, and use it in my other four projects.

Running “cp -r” will do it, but it’s a bit crude.

Thanks,
Bob

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: library development

2013-12-20 Thread Bob Hutchison

On Dec 20, 2013, at 9:22 AM, Daniel Higginbotham nonrecurs...@gmail.com wrote:

 lein install actually installs your library ~/.m2/repository in addition to 
 creating the pom and jar. That should be all you need to do.

[message was bounced earlier…]

Thank you. You’re right. As it happens, I just discovered that myself. I nice 
cup of tea and thinking “there’s no way these leiningen guys didn’t do 
something so obvious” led be to suck it up and poke around my maven repository 
to see what I could see. Maven’s getting pretty quick isn’t it?

Cheers,
Bob

 
 On Friday, December 20, 2013 9:09:32 AM UTC-5, Bob Hutchison wrote:
 Hi, 
 
 I’m missing something. And it’s annoying me. 
 
 Let’s say I’m working on three or four projects and there’s some code that 
 really should be developed as a library and used by each of the projects. A 
 similar thing happens if I fork a library from github. I don’t want to make 
 any of this code public so clojars is not an option. It’s clear enough that 
 the solution to this will involve a local maven repository somehow. 
 
 Now, I don’t know maven. I like it that way. I *do* *not* want to know maven. 
 It’s so low on my priority list that reviewing the new C++ standard is 
 higher. Basically it’ll never get to the top of the list. 
 
 Furthermore I think requiring someone to know maven to do any non-trivial 
 Clojure development is a bad plan. This is surely one of the founding goals 
 of Leiningen. 
 
 I’ve found some documentation and blog posts that, as soon as they get 
 interesting, pretty much all end up assuming you know maven. I’ve found 
 lein-localrepo plugin, which is was hopeful until you read it’s docs and see 
 that it describes itself in maven terminology (why do I care what the maven 
 coordinates of a file are? *WHY* do I have to know? Is this about Clojure or 
 Java jar files? Are they different?) 
 
 Lein install makes a jar file and a pom file. So what? Is there something you 
 do with these? There must be. But since I don’t know maven I’ve not got a 
 clue what that might be. 
 
 What I’d like to do is type something no more complex than “lein 
 local-install” and be done with it. I do not care if every developer on my 
 team has to execute that command. I don’t care about sharing. I don’t care 
 about naming. I just want to work on my library, install it, and use it in my 
 other four projects. 
 
 Running “cp -r” will do it, but it’s a bit crude. 
 
 Thanks, 
 Bob
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin

2013-11-30 Thread Bob Hutchison

On Nov 29, 2013, at 11:14 PM, guns s...@sungpae.com wrote:

 Hello,
 
 I am happy to announce version 1.5.0 of Slamhound, technomancy's amazing
 ns rewriting tool.
 
;; ~/.lein/profiles.clj
{:user {:dependencies [[slamhound 1.5.0]]}}
 
 This is a *major* bugfix release. If you've tried Slamhound in the past
 and felt frustrated, now is a great time to give it another try.
 

This is a great idea… but I’m having an awful time getting it to work.

Two problems:

1) if I try it on junky experimental clojure programs, files that execute when 
loaded and don’t do anything serious but explore some feature of clojure, I’m 
getting this error when running from vim:

Error detected while processing function 
slamhound#reconstruct..fireplace#eval..fireplace#session_eval..SNR37_eval..86:
line   38:
E605: Exception not caught: Error running Clojure: Error: Could not 
find or load main class clojure.main^@

   And from the command line it silently does nothing.

2) most of my real code, maybe all since I can’t find anything else, uses 
ring/compojure and midge. Midje is used in-line (the facts are in the source 
file not in the test directory).
  — from inside vim, again since Slamhound never terminates, I’ve got to 
Control-C out of it, and consequently the buffer is never updated.
  — when I run Slamhound from the command line:
  — it never terminates
  — despite not terminating, it does update all but one of the files 
properly
  — it does not handle the file(s) that start ring servers and complains:
 Failed to reconstruct: #File src/jel/server.clj
 Address already in use
 This is even if the address really isn’t in use, I think it’s trying 
to ‘run’ server.clj a second time. And it doesn’t terminate either.

However, the changes it makes to the namespaces are excellent!

I tried updating both fireplace and clojure-static but that made no difference.

Cheers,
Bob

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin

2013-11-30 Thread Bob Hutchison

On Nov 30, 2013, at 10:59 AM, guns s...@sungpae.com wrote:

 On Sat 30 Nov 2013 at 09:29:30AM -0500, Bob Hutchison wrote:
 
 This is a great idea… but I’m having an awful time getting it to work.
 
 Hello Bob,
 
 I'm sorry to hear that setup is problematic. If it's trouble for you,
 it's bound to be trouble for others. Would you be willing to open a new
 issue on the bug tracker?
 
 https://github.com/technomancy/slamhound/issues/new

I’ve split my email into two and have created issues 58 and 59.

 
 Just copying and pasting your email would be very helpful. I suspect
 there are a couple of hidden problems that are general to all users, so
 I am eager to help you.

The next week or so will be busy, but I’ll do what I can to help.

 
 However, the changes it makes to the namespaces are excellent!
 
 I'm glad to hear there is some good news!

Certainly was :-)

 
guns

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] overload-middleware 0.1.1

2013-11-17 Thread Bob Hutchison
Hi Rob,

Nice! Thanks for releasing this. I’m not sure when I’ll use this but I can 
pretty much guarantee that I will give it a go sooner or later. I’ve written a 
few of these in the past, it’s good to see someone make a library out of it.

BTW, things like AngularJS and EmberJS should/could know about 503 errors and 
what they mean. There’s actually a project, that I’ve *not* used (yet), 
https://github.com/kkolstad/angular-servicestack that will re-try on a 503 
after a random delay. Here’s the line from their source code (it’s 
coffeescript):

sleepTime = Math.min (Math.random() * (Math.pow(4, response.collisionCount() - 
1) * 100)), serviceStackRestConfig.maxDelayBetweenRetries

Cheers,
Bob

On Nov 16, 2013, at 1:21 PM, Rob Day r...@rkd.me.uk wrote:

 Hi all,
 
 I've just published the first working version of a Ring middleware that some 
 of you might find useful. It's designed for web apps where, if you're 
 overloaded, it's better to serve some requests quickly and fail the others 
 than to try and serve all the requests   and do it slowly. (My background 
 is in telecoms, where that's often the best approach.)
 
 Specifically, you specify a target latency that you want 90% of requests to 
 try and meet, and it applies the algorithm from 
 http://www.eecs.harvard.edu/%7Emdw/papers/control-usits03.pdf to try and keep 
 your latency below that threshold. The exact parameters of the algorithm are 
 tunable, and different URLs or groups of URLs can have different targets and 
 parameters.
 
 It still needs a bit of tidying - docstrings, cleaning up some of the Midje 
 tests, and so on - but it works and I think the documentation is usable, so 
 I'm announcing it now.
 
 Github (w/ docs): https://github.com/rkday/overload-middleware
 Clojars: https://clojars.org/overload-middleware
 
 Let me know if you have any feedback!
 Rob

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: is PG's imperative outside-in advice any good?

2013-10-15 Thread Bob Hutchison

On 2013-10-15, at 8:29 AM, Daniel Higginbotham nonrecurs...@gmail.com wrote:

 I've been going through On Lisp by Paul Graham and on page 33 he recommends 
 against performing intermediate bindings. Does this advice hold for 
 Clojure? Here are a couple examples:
 
 ;; Common Lisp (from the book)
 (defun bad (x)
 (let (y sqr)
   (setq y (car x))
   (setq sqr (expt y 2))
   (list 'a sqr)))
 
 (defun good (x)
 (list 'a (expt (car x) 2)))
 
 ;; Clojure
 (defn bad [x]
 (let [y (first x)
   sqr (expt y 2)]
   (list 'a sqr)))
 
 (defn good [x]
 (list 'a (expt (first x) 2)))

The closest I can think of to the bad CL code in Clojure would be something 
like:

(defn bad-clojure [x]
  (let [v (first x)
v (Math/pow v 2)
v (list 'a v)]
v))   

I don't think anyone at all would find either the bad CL or Clojure code okay. 
This is more of an admonition to not be an idiot :-)

Your Clojure code is equivalent to the following CL code:

(defun good2 (x)
  (let* ((y (car x))
 (sqr (expt y 2)))
(list 'a sqr)))

There's nothing wrong with writing code that way, it's functional and clear. 
What you're doing with this style of writing is introducing intermediate named 
values. Sometimes those just clutter up the code, sometimes they clarify. Use 
your own good taste. You'd do the same thing in Haskell, but I'd use a where 
clause.

 
 Paul Graham explains:
 
 The final result is shorter than what we began with, and easier to 
 understand. In the original code, we’re faced with the final expression (list 
 'a sqr), and it’s not immediately clear where the value of sqr comes from. 
 Now the source of the return value is laid out for us like a road map.
 
 The example in this section was a short one, but the technique scales up. 
 Indeed, it becomes more valuable as it is applied to larger functions.

Yes, in the bad CL code you don't know where the value of sqr comes from and 
the problem gets much worse as the code gets longer. This is the problem with 
imperative code in general.

You don't have that problem in either Clojure or the 'good2' CL program.

 
 In clojure you can't do setq of course but I find myself going against this 
 advice all the time

He's not talking about intermediate names for values, he's talking about 
imperative assignments using setq, setf, and friends. Clojure's nearest 
equivalent, that I can think of, is shadowing in a let statement, and I think 
you'll find this is frowned upon.

 So, is PG's advice any good?

Yup.

Cheers,
Bob

 
 Thanks!
 Daniel
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Sequential conditional transforms of an argument

2013-07-08 Thread Bob Hutchison

On 2013-07-08, at 2:40 AM, Laurent PETIT laurent.pe...@gmail.com wrote:

 thank you all for your answer.
 
 So to go back to my original concern, there does not seem to be a way
 to do this as I intended by just combining the existing features in
 core.
 

I'm not sure what you're asking for here. Do you mean *in-line* with only core 
features? I suppose that's the same as asking if core already deals with this 
somehow? I don't think it does. And, for what it's worth, I see this pattern 
regularly as well, and I've used something somewhere between Thomas' and 
Y.Kohyama's techniques.

Cheers,
Bob

 Cheers,
 
 --
 Laurent
 
 2013/7/8 Yoshinori Kohyama yykohy...@gmail.com:
 Hi Laurent,
 
 How about a macro like below?
 
  (defmacro tt
([x] x)
([x ts tr  more] `(tt (if (~ts ~x) (~tr ~x) ~x) ~@more)))
 
 To use this,
 
  (tt x test1 transform1 test2 transform2 test3 transform3)
 
 This doesn't work even number of arguments as you see.
 
 HTH,
 Y.Kohyama
 
 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
 
 
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
 
 

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: What's the point of - ?

2013-03-11 Thread Bob Hutchison

On 2013-03-11, at 6:58 AM, edw...@kenworthy.info wrote:

 So I understand that:
 
 (- foo bar wibble)
 
 is equivalent to
 
 (wibble (bar (foo)))
 
 With the advantage that the latter version is better, in the sense that it's 
 clearer what the final result is (the result of the call to wobble).
 
 What I don't understand is the need for - the only thing it seems to do is 
 make something Lispy appear to be imperative.
 
 Is that it?

Consider:

  (- foo
  (f1 p1 p2 p3)
  (f2 p4 p5 p6)
  (f3 p7 p8 p9))

vs

(f3 (f2 (f1 foo p1 p2 p3) p4 p5 p6) p7 p8 p9)

(assuming I cut and pasted correctly) and you can see a little better where 
this is going, especially if you tried putting real names in there.

Is it imperative? Is it declarative? Who cares?

Cheers,
Bob


 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: how would you implement sending out a verification email?

2013-02-21 Thread Bob Hutchison

On 2013-02-20, at 9:32 AM, Balint Erdi balint.e...@gmail.com wrote:

 In the languages I come from (e.g Ruby) I'd use a library that handles the 
 queueing and consumption of tasks. Is this how you'd do it in Clojure or it's 
 one of these cases where Clojure itself suffices where other languages are 
 lacking?

This is how I've done it.

I know this is largely a theoretical question about side-effects and STM in 
Clojure, but… In the end, there's always the chance that you'll send duplicate 
emails, all you can do is try to minimize that. There's also the chance that 
you never actually successfully send the email, if for no other reason than 
there's no way to ensure the email is received or to know if it was received. 
Not to mention spam filters. Using specialist email services is something to 
seriously consider, it'll make your job much easier, all you have to do is make 
sure the email request is received by the service -- there's a protocol for 
that. A decent service will do much better than you can do at making sure the 
email is sent.

Cheers,
Bob

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Why is this so difficult?

2013-02-15 Thread Bob Hutchison

On 2013-02-15, at 4:16 AM, BJG145 benmagicf...@gmail.com wrote:

 I don't know anything about build managers so I think my next step will be to 
 pick up a book on Maven to get the background…)

Don't. Just don't. All you really need to know about maven, and it's role, is 
what you can get from wikipedia. Seriously. Then click around on related 
articles. If you need more than that then lein will have failed (miserably) -- 
but my experience with lein is pretty good. When you know that lein cannot do 
what you need (which may well be never) then it'll be time to look into maven.

http://en.wikipedia.org/wiki/Build_automation
http://en.wikipedia.org/wiki/Apache_Maven

The trick is to get lein installed the first time. This might take a bit of 
work if you haven't already got a machine setup for command line based 
development. (That's important by the way: *command line* -- even if you intend 
to always use IntelliJ or some other IDE)

I completely sympathize with your situation. I've seen this a lot, and 
experienced it myself when starting from a fresh machine. It's very difficult 
to give instructions because of the wildly differing starting points.

Good luck, but you'll get there :-)

Cheers,
Bob

 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Clojure + Web Services + Web Sockets

2013-02-11 Thread Bob Hutchison

On 2013-02-11, at 6:12 PM, Ryan T. arekand...@gmail.com wrote:

 Unless someone has to suggest something better, it seems that the best way to 
 achieve what i want is to use aleph which allows you to initialize it with a 
 wrapped ring handler. 

You might have a look at http://http-kit.org/ 

Cheers,
Bob

 
 If you have more details on the issue or alternatives I would love to hear 
 about them.
 
 On Tuesday, February 12, 2013 12:54:53 AM UTC+2, Ryan T. wrote:
 Hello,
 
 I am trying to figure out how to setup my clojure project in order to be able 
 to serve both normal http requests which will return json and also handle 
 requests over websockets. Is it possible to do both and listen on same port? 
 or do i need two separate projects? or ?
 
 I did find this but from what I read Webbit is not the best solution for what 
 I need. I was hoping to be able to build my clojure project and use jetty in 
 development and tomcat on production.
 
 Thank you for your time
 
 -- 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Clojure web server benchmarks

2013-01-25 Thread Bob Hutchison

On 2013-01-25, at 6:24 AM, Peter Taoussanis ptaoussa...@gmail.com wrote:

 I'd consider adding a graph if folks think these numbers are sufficiently 
 interesting?
 

That would be great! This is very important information for me. And, unless 
things have improved markedly over that last year or so (I hope so), I think 
you'll be 'amused' by what you see.

Cheers,
Bob

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en




Re: [ANN] Formative - render, parse, and validate web forms

2013-01-16 Thread Bob Hutchison

On 2013-01-15, at 5:00 PM, Justin Kramer jkkra...@gmail.com wrote:

 Formative is a library for dealing with web forms. Features:
 Describe forms using simple data
 Render forms via pluggable renderers (comes with Bootstrap and other 
 renderers built-in)
 Parse submitted form data from Ring params
 Validate parsed data using Verily (another new but less interesting lib)
 A live demo can be seen at http://formative-demo.herokuapp.com/. Demo source: 
 https://github.com/jkk/formative-demo
 
 See the README for a usage guide and quick reference:
 
 https://github.com/jkk/formative
 
 It has seem some real-world usage, and I consider the API stable.
 
 Feedback and contributions welcome.

This is *really* interesting! I'll have a look at this more closely over the 
next couple of days, but, really, the timing could not be better… you might 
have just tipped a project I'm working on over to Clojure :-)

It looks as though you've not put any kind of 'structure' on the fields… they 
are 'flat'. For example, I don't see fieldsets. One of my projects has its 
forms in two parts, the input fields which scroll (and have fieldsets) and a 
second part that consists of things like the submit and cancel buttons. The 
second part is pulled into a sidebar and fixed on the page (doesn't scroll with 
the rest of the fields). These forms can be a bit long (but they are a lot more 
usable than you'd think), so there's also an index in the sidebar that on click 
moves the scrollable part to make the corresponding fields come into view. In 
my current project these indexed things aren't fieldsets but they could be. 
Alternatively, some other kind of grouping structure could be used. Or possibly 
just a new field type that created an index entry… I'll have a muck about and 
see what I can come up with.

Cheers,
Bob

 
 Justin
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: [ANN] Formative - render, parse, and validate web forms

2013-01-16 Thread Bob Hutchison

On 2013-01-16, at 11:31 AM, Justin Kramer jkkra...@gmail.com wrote:

 So I went ahead and implemented the first solution I mentioned: the default 
 renderer now groups fields into fieldsets, split by :heading and :submit 
 fields. Each fieldset has a class that you can target with css/js. You can 
 see the result in the demo - http://formative-demo.herokuapp.com/.

Heh, that was quick :-) Thanks!

I don't suppose you've thought much about this situation: I've got a couple of 
standard (what I'll call) mixin-forms that have fields and validations that I 
'mixin' to a form (once or not at all). They aren't forms on their own, just a 
bunch of fields and validation rules. For example, I have a standard way of 
describing an entity (name, title, abbreviated description, full description, 
and a few other things). It's possible to think of tabs this way as well. 
Dropdowns in a nav bar is similar too, maybe. It's pretty clear how to get 
started on implementing something like this, but I'm wondering if you've 
considered anything in this regard.

I've also got groups of several controls that operate together. The bootstrap 
prepended and appended inputs are simple examples. These are to some degree 
like the 'mixin' things I mentioned, but there can be more than one of them and 
they need to be distinguished, and the validation might be different for each 
or need to be extended for each instance. It looks to be easy enough to do this 
by adding new field types (extending the render-field and parse-input 
multimethods). Is that how you'd approach the problem?

While I think of it, do you provide a way to validate that a value corresponds 
to one of the :options?

Cheers,
Bob

 
 Justin
 
 On Wednesday, January 16, 2013 8:35:54 AM UTC-5, hutch wrote:
 
 This is *really* interesting! I'll have a look at this more closely over the 
 next couple of days, but, really, the timing could not be better… you might 
 have just tipped a project I'm working on over to Clojure :-)
 
 It looks as though you've not put any kind of 'structure' on the fields… they 
 are 'flat'. For example, I don't see fieldsets. One of my projects has its 
 forms in two parts, the input fields which scroll (and have fieldsets) and a 
 second part that consists of things like the submit and cancel buttons. The 
 second part is pulled into a sidebar and fixed on the page (doesn't scroll 
 with the rest of the fields). These forms can be a bit long (but they are a 
 lot more usable than you'd think), so there's also an index in the sidebar 
 that on click moves the scrollable part to make the corresponding fields come 
 into view. In my current project these indexed things aren't fieldsets but 
 they could be. Alternatively, some other kind of grouping structure could be 
 used. Or possibly just a new field type that created an index entry… I'll 
 have a muck about and see what I can come up with.
 
 Cheers,
 Bob
 
 
 Justin
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+u...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: [ANN] nrepl-transcript

2013-01-15 Thread Bob Hutchison

On 2013-01-14, at 3:58 PM, Jonas jonas.enl...@gmail.com wrote:

 Hi
 
 I created a middleware for nrepl that saves a transcript of your repl 
 interactions so you can go back and see what you did. 
 
 https://github.com/jonase/nrepl-transcript
 
 Feedback welcome!

Oh! Thank you!

Bob

 
 Jonas
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: [ANN] sublime-lispindent, clojure indenting for sublime text 2

2012-11-25 Thread Bob Hutchison

On 2012-11-25, at 12:45 AM, Anthony Grimes disciplera...@gmail.com wrote:

 I just took a shot at it. I put it in Pristine Packages as described, but it 
 disappears when I restart ST2 and try to use it.


I imagine you tried to put it in:

  ~/Library/Application Support/Sublime Text 2/Pristine Packages

I did that too. You need to put it in:

  /Applications/Sublime Text 2.app/Contents/MacOS/Pristine Packages

Cheers,
Bob

 
 Also, will this work with the built in 'reindent' command? If not, will it 
 work with vintage mode (you can reindent blocks with =ab from Vim)? I really 
 wish the Clojure mode just didn't suck so bad.
 
 On Monday, November 12, 2012 10:25:38 AM UTC-6, Jonathan Fischer Friberg 
 wrote:
 Dear clojure mailing list,
 
 As the indenting for clojure (and lisp in general) was very lacking
 in sublime, I decided to make a plugin:
 
 https://github.com/odyssomay/sublime-lispindent
 
 I hope someone finds this useful.
 
 By the way, if someone with a mac could try the keyboard shortcuts that would 
 be great.
 I don't own a mac so I cannot test them.
 
 Sincerely,
 Jonathan
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Modelling for DAG with identity map - or not?

2012-09-18 Thread Bob Hutchison

On 2012-09-16, at 3:21 PM, Patrik Sundberg patrik.sundb...@gmail.com wrote:

 I'm asking myself though if there's a more functional design for 
 accomplishing the same goals? My main goals are to do things consistently so 
 that changing a value X propagates properly, and being able to find 
 dependencies of a given value. A DAG+identity map is my first take, but there 
 may be something more natural for FP I'm completely missing.

Sounds like a reasonable approach to me. There's nothing wrong with state, just 
how you manipulate it. The STM in Clojure is really nice in this regard. You 
might want to have a look at Functional Reactive Programming (FRP). There's a 
lot of stuff available about that in the Haskell community, but usually for UIs 
and things like that. They sometimes use spread sheets as an example (spread 
sheets can be thought of as a DAG with values and computations in cells… you 
can see the mapping between them in your application (where the mapping doesn't 
work or is hard might be pointing at something quite interesting). There's also 
something called 'Cells' in Common Lisp that might be interesting. I'm not sure 
what's been done in Clojure.

Cheers,
Bob

 
 Thanks,
 Patrik
 

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Enhanced Primitive Support Syntax

2011-01-17 Thread Bob Hutchison
Hi Stuart,

On 2011-01-15, at 4:06 PM, Stuart Halloway wrote:

 In my experience, errors are the problem and we should be avoiding them, 
 almost at all costs. 
 
 This debate always starts by conflating three things into two, and then goes 
 downhill from there. :-( It isn't 
 
 (a) safe/slow vs. 
 (b) unsafe/fast. 

That's how us outsiders are left to look at it.

 
 It is 
 
 (a) unsafe/incorrect value on overflow/fastest/unifiable* vs. 
 (b) safe/error on overflow/fast/unifiable vs. 
 (c) safe/promoting on overflow/slow/not-unifiable
 
 *unifiable: able to deliver same semantics for primitives and objects

This doesn't really help me understand your argument.

It looks to me as though Clojure is trying to steer itself through the middle 
of something. The trouble is that I don't know where the edges of the middle 
are.

Maybe it is just a documentation problem. But I'd also suggest that there's a 
bit of a sales job necessary here.

 
 We have thought about this quite a bit,

Nobody doubts that, certainly I don't. And I'm not trying to minimise or 
dismiss what you've done. And I'm not claiming that I've thought about it 
better or more or deeper. But I do have concerns and I don't see them being 
addressed, and I'd like it if they weren't minimised either. Maybe my concerns 
are completely addressed. Maybe not. I don't know, and I'd like to be convinced.

 and an argument from one axis only (e.g safe/unsafe) that doesn't even 
 mention some of  the other axes is not likely to be persuasive. Would be more 
 interesting to see a new axis we haven't thought of...

Numerical correctness, for some of us, is an overwhelming issue. This is purely 
from experience... bad experience... 30+ years of bad experience in my case :-) 
From my point of view, the approach Clojure is taking isn't persuasive, not to 
say it couldn't be made persuasive.

I think I did add what might be considered an additional axis. Syntax. 
Specifically what annotations are needed and for what purpose. I don't think 
this should be dismissed out of hand.

Cheers,
Bob

 
 Stu
 
 Stuart Halloway
 Clojure/core
 http://clojure.com
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Enhanced Primitive Support Syntax

2011-01-15 Thread Bob Hutchison
I'm going to re-organise this a bit…

 On Jan 14, 2:40 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote:
 Debatable it is, endlessly. ;)  So Clojure committers made a choice.
  Hopefully, they have made a choice that has:

I agree that they've made a choice, and I really don't want to be too critical 
here. However, since Clojure 1.3 is still in an alpha stage, maybe this 
discussion can still contribute something. Maybe what I'm saying is that I want 
to stay constructive and that there's maybe still time to be constructive.

 
 * a small positive effect (better performance with less effort) on a
 majority of users
 
 * a small negative effect (worse performance, extra effort) on a minority

These goals are good, but I don't know that the approach taken achieves them.

In my experience, errors are the problem and we should be avoiding them, almost 
at all costs. Numbers are confusing to people. Numbers approximated on a 
computer are far more confusing. How many times do you see threads discussing 
how a compiler is buggy because it can't divide two numbers and get the right 
answer? I've been doing this stuff for years and I can come up with an awful 
lot of amusing and/or horribly nasty examples. But I don't think this needs to 
be re-established.

Given my experience I *strongly* lean towards not making a 'mistake' due to 
compiler optimisations. In other words, I'd be very annoyed, and I'd expect 
others to be annoyed too, if a numerical error was introduced to one of my 
programs because of an unexpected, silent, compiler optimisation.

Secondly, Clojure has already established that we will use type annotations to 
signal to the compiler what's what. When we annotate, we are relaxing our 
requirements on the compiler to not make a mistake by assuming that 
responsibility ourselves.

I would suggest the following:

1) if there's type annotation on both values of, say, an addition, then the 
optimised version can be used. If there isn't, or the compiler isn't sure, then 
use safe operations.

2) if the compiler isn't cooperating (because it isn't sure what's going on) we 
should be helping it by again assuming the responsibility of being right and 
marking the operator, say with a tick.

And yes, this likely has problems too. I'm not saying that this is an issue 
with easy solutions.

We're heading for a hodgepodge of annotation purposes, some for optimisation, 
some for correctness (and one of these days I'll mention what I think of the 
@/deref thing :-) And now we're pretty much guaranteed ugly code no matter 
what. Though I'd prefer no ugliness, I'd trade ugly code for speed, but I'd 
rather not for correctness.

And there's a practical problem with mixed annotation purposes. If you want to 
track down a bug you can't just remove all annotations temporarily. You'd have 
to remove some and add others. Not looking forward to that. Maybe a macro: 
make-this-safe could be written. Hmm. Maybe a 'defn-safe' would be something to 
think about???

This is also the kind of thing that you just can't fix later. Imagine how we'll 
feel in ten or twenty years about this decision.


 
 -S
 
On 2011-01-14, at 8:40 PM, Armando Blancas wrote:

 They used to give you compile switches for that kind of stuff, not
 hope and wholesome wishes. Seems like every performance improvements
 makes the language more complex, uglier or both.
 


Compiler switches were/are problematic too, but at least they are explicit and 
have to be *added*.

Cheers,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How do I find implemented protocols in Clojure object?

2011-01-12 Thread Bob Hutchison

On 2011-01-12, at 8:38 AM, Stuart Sierra wrote:

 One way:
 
 (ancestors (type the-object))
 
 This will include every interface implemented by the object, including 
 protocols.

This seems to only work if the protocol is mentioned in the defrecord. If it's 
applied using the extend function it doesn't seem to show the protocol.

The functions bases and supers work similarly.

Unless I'm doing something really stupid, which is a distinct possibility.

Any idea how to tell which of the classes returned by ancestors/bases/supers 
are protocols? I copied a function from the source that can tell if something 
is a protocol if written directly in clojure, but does not work on the results 
from those methods.

(defn protocol?
  [maybe-p]
  (boolean (:on-interface maybe-p)))


Cheers,
Bob


 
 -S
 clojure.com
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

help to improve a multimethod with a vaguely interesting dispatch function

2010-11-15 Thread Bob Hutchison

Hi,

I'm trying to work out a way to define a multimethod dispatch function that 
will allow me to make a decision based on two values. In the example below I'm 
using symbols for the values of the major and minor values, mostly for 
convenience. What I'm trying to do is dispatch a multifunction on both values 
if the method exists, on the major value alone if it exists, and to the default 
if there's still no method.

Can anyone see a better way of doing this?

Thanks,
Bob

(declare can-we-not-do-better-dispatcher)

(defmulti can-we-not-do-better (fn [major minor] 
(can-we-not-do-better-dispatcher major minor)))
(remove-all-methods can-we-not-do-better)
(defmethod can-we-not-do-better :default [major minor](str default-default 
-  major minor))
(defmethod can-we-not-do-better :one [major minor](str one-default 
-  major minor))
(defmethod can-we-not-do-better [:one :two] [major minor] (str one-two 
-  major minor))

(defn can-we-not-do-better-dispatcher [major minor]
  (let [method-map (methods can-we-not-do-better)]
(or (and (get method-map [major minor]) [major minor])
(and (get method-map major) major)
:default)))

(defn play []
  (println (can-we-not-do-better :zero :zero))
  (println (can-we-not-do-better :one :two))
  (println (can-we-not-do-better :one :three)))

(play)
default-default - :zero:zero
one-two - :one:two
one-default - :one:three


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: ANN: Programothesis screencast series on Clojure, Emacs, etc

2010-11-12 Thread Bob Hutchison

On 2010-11-12, at 4:25 PM, Scott Jaderholm wrote:

 Hey Clojurians,
 
 I don't think there are any great new movies in the theater this weekend so 
 if you're looking to kick back and relax and watch the tube a bit you might 
 checkout the first few episodes of my new screencast series on Clojure, 
 Emacs, Slime, etc.
 
 http://youtube.com/emailataskcom

Thanks Scott. Nice idea, short to the point demonstrations of how things work. 
I am new to emacs so these are pretty handy.

Cheers,
Bob

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Python is way faster than Clojure on this task

2010-11-06 Thread Bob Hutchison

On 2010-11-06, at 9:08 AM, pepijn (aka fliebel) wrote:

 I increased the heap space a lot, but I'm just bordering on the edge
 of my real memory, so it's not helping much.

Did you try pushing the minimum heap space up. I'm usually lazy and set them to 
the same. I've had serious trouble caused by the way the JVM increases the heap 
space. Setting min to max (and max big) pretty much took care of that issue.

Cheers,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Python is way faster than Clojure on this task

2010-11-06 Thread Bob Hutchison

On 2010-11-06, at 10:22 AM, Peter Schuller wrote:

 I increased the heap space a lot, but I'm just bordering on the edge
 of my real memory, so it's not helping much.
 
 Did you try pushing the minimum heap space up. I'm usually lazy and set them 
 to the same. I've had serious trouble caused by the way the JVM increases 
 the heap space. Setting min to max (and max big) pretty much took care of 
 that issue.
 
 People keep making claims like this in various situations but I don't
 tend to hear details. Exactly what problems are you having that would
 plausibly apply in this situation?
 
 Not that there is no reason to set ms=mx (there are reasons), but the
 need to do so tends to be over-stated in my opinion. But if I'm
 missing something I'd like to know about it :)

I understand your scepticism but, even applaud it, but, in my case, it comes 
from actually trying it and measuring the difference (again in my case you 
didn't need anything fancy it was huge and highly visible). It happened often 
enough on different projects that I just do it routinely now. Anyway, if I 
*ever* see something that might be a GC-like problem I first eliminate heap 
growth from the picture (and, this is all I was suggesting here). Perhaps a 
hold over from earlier versions of the JVM but I don't personally care that 
much with my servers -- I have a machine dedicated to the application, it's got 
a lot of memory, use it. Might have a different attitude for a desktop app :-)

Cheers,
Bob

 
 -- 
 / Peter Schuller
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Clojure on Javascript

2010-10-30 Thread Bob Hutchison

On 2010-10-30, at 12:32 AM, Michael Gardner wrote:

 On Oct 29, 2010, at 11:09 PM, David Nolen wrote:
 
 JS brought me to Lisp, I would love to see the Clojure community bring Lisp 
 back to JS. However I fail to see what advantage JS gives on the server 
 side. From what I've seen the V8 GC and Node.js have a considerable number 
 of years to go before they are serious contenders against the JVM for 
 non-trivial projects, evented or no.
 
 Agreed. What is the point of Javascript on the server side? Familiarity? 
 Consistency with client-side code?

The point isn't entirely Javascript on the server side...

- there are an awful lot of non-non-trivial *web* projects :-)
- it is (very) fast
- websockets/comet based applications absurdly easily set up
- this is the kind of thing the entire node.js community is interested in (it 
isn't a javascript-the-language focused community)

Aleph is extremely interesting. How many in the Clojure community know *of* it, 
let alone *know* it, or have actually *used* it? Know about integrating it with 
Ring? I'm just pointing out a difference in focus the two communities might 
have, this is not a criticism of either.

Aleph isn't the only thing happening out 'there'. What does the Clojure 
community know about Mongrel2 and ZeroMQ?

It is ridiculously easy to set up a quick prototype of a fancy web app using 
node.js, and it seems a lot of people aren't seeing a reason to move away from 
it when they start getting 'serious' about the app.

Like I said, it isn't Javascript on the server that's going on with node.js

 
 More interesting would be something along the lines of CoffeeScript (like 
 ClojureScript) that takes a reasonable subset Clojure and compiles into 
 efficient JS, allowing Clojure programmers to send Clojure code to clients.
 
 Yes! Writing Javascript makes me want to throw things. Client-side Clojure 
 would be fantastic.

Certainly I'd kinda like this too. But being in wet-blanket-mode... it's gotta 
be more. To me the real problem in programming the browser is the DOM, it's 
*not* a language thing[1]. That has to be dealt with or Clojure on the browser 
will make you want to throw things too :-) You've also got to deal with the 
environment: how is Clojure's immutability of data going to fit into an 
environment where the whole purpose is mucking about with a huge hunk of state 
(the DOM)?

In the short term it seems to me that an absurdly easy way to get 
websocket/comet based servers running in Clojure would be good. At least I'd be 
happy. This problem is staring me in the face and I've got to do something next 
week. What do I do? node.js (done in 5 minutes) or somehow get 
Aleph/Ring/Clojure working? or Mongrel2/Ring/Clojure? or ZeroMQ/Ring/Clojure? 
or what? That's the kind of problem *I* am having to deal with.

I should probably bring this up on the Clojure web dev mailing list.

Cheers,
Bob

[1] and mootools and Google's Closure are making real progress with dealing 
with the DOM *and* making Javascript more uniform (so is jQuery for that matter)

 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Fighting with Emacs ;-)

2010-10-05 Thread Bob Hutchison
Hi,

I've been using Clojure  Leiningen for a while, but never reliably with emacs. 
To make things worse I really don't know emacs (vi since 1978 or something, but 
not emacs, and now I think emacs hates me). Questions below.

On 2010-09-28, at 7:37 AM, Mike Meyer wrote:
 
 Actually, this sounds like standard behavior for an integrated
 EMACS/REPL to me: sending code from the edited file to the REPL
 evaluates them in the REPL, but doesn't print them: you either get a
 message in the minibuffer or a short note in the buffer. Normal usage
 is to edit a function, send it to the REPL, then switch to the repl
 and test the newly defined function(s) (usually just M-p to recall the
 just failed test).

Okay. I'm feeling like a total idiot here.

What do you mean by 'switch to the repl', in fact, how do you do that?

I'm using lein swank, I can connect to it, I can evaluate expressions and get 
the correct results, I can see the communication going between emacs and lein 
swank in the *slime-events* buffer. I switched the mode of the *scratch* buffer 
to Clojure and I can ^X^E stuff in there and get the results.

What I cannot do is open up a repl. If I us ^C^Z it'll try to run a program 
called 'lisp', and if it isn't there emacs will moan. If I make a shell script 
called 'lisp' and put 'lien repl' in it, emacs will start the script start up a 
new repl and show the prompt... but it'll be running from the wrong place.

What is this lisp program? How do I bring up a repl that uses the swank I'm 
connected to? Is this even possible?

Thanks *so* much in advance.

Cheers,
Bob


 
 In particular, SWANK/SLIME prints the value of the last expression in
 the evaluate region in the minibuffer. At least, that's what' it's
 always done for me.
 
   mike
 -- 
 Mike Meyer m...@mired.org   http://www.mired.org/consulting.html
 Independent Network/Unix/Perforce consultant, email for more information.



Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Fighting with Emacs ;-)

2010-10-05 Thread Bob Hutchison

On 2010-10-05, at 3:13 PM, Alan wrote:

 Hm. How are you connecting to swank? I use M-x slime-connect (then hit
 yes/RET a few times); as soon as that's done, a new buffer with the
 clojure REPL appears. Then I can switch to it just as with any buffer;
 C-x C-o or similar. The buffer it creates is called *slime-repl
 clojure*. That should be all you have to do. I'm curious what you're
 doing, to cause swank to work, but not give you a REPL.

I'm connecting exactly that way, a couple of questions about host and port, 
then complaints about version incompatibilities which are answered by me with a 
'y', then a success message. The only buffer created is *slime-events*. I'm on 
OSX with three versions of emacs that I can use, all three do exactly the same 
thing.

That version incompatibility thing I've googled, nobody seems to think it 
matters.

Cheers,
Bob

 
 On Oct 5, 11:57 am, Bob Hutchison hutch-li...@recursive.ca wrote:
 Hi,
 
 I've been using Clojure  Leiningen for a while, but never reliably with 
 emacs. To make things worse I really don't know emacs (vi since 1978 or 
 something, but not emacs, and now I think emacs hates me). Questions below.
 
 On 2010-09-28, at 7:37 AM, Mike Meyer wrote:
 
 
 
 Actually, this sounds like standard behavior for an integrated
 EMACS/REPL to me: sending code from the edited file to the REPL
 evaluates them in the REPL, but doesn't print them: you either get a
 message in the minibuffer or a short note in the buffer. Normal usage
 is to edit a function, send it to the REPL, then switch to the repl
 and test the newly defined function(s) (usually just M-p to recall the
 just failed test).
 
 Okay. I'm feeling like a total idiot here.
 
 What do you mean by 'switch to the repl', in fact, how do you do that?
 
 I'm using lein swank, I can connect to it, I can evaluate expressions and 
 get the correct results, I can see the communication going between emacs and 
 lein swank in the *slime-events* buffer. I switched the mode of the 
 *scratch* buffer to Clojure and I can ^X^E stuff in there and get the 
 results.
 
 What I cannot do is open up a repl. If I us ^C^Z it'll try to run a program 
 called 'lisp', and if it isn't there emacs will moan. If I make a shell 
 script called 'lisp' and put 'lien repl' in it, emacs will start the script 
 start up a new repl and show the prompt... but it'll be running from the 
 wrong place.
 
 What is this lisp program? How do I bring up a repl that uses the swank I'm 
 connected to? Is this even possible?
 
 Thanks *so* much in advance.
 
 Cheers,
 Bob
 
 
 
 In particular, SWANK/SLIME prints the value of the last expression in
 the evaluate region in the minibuffer. At least, that's what' it's
 always done for me.
 
   mike
 --
 Mike Meyer m...@mired.orghttp://www.mired.org/consulting.html
 Independent Network/Unix/Perforce consultant, email for more information.
 
 
 Bob Hutchison
 Recursive Design Inc.http://www.recursive.ca/
 weblog:http://xampl.com/so
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Fighting with Emacs ;-)

2010-10-05 Thread Bob Hutchison

On 2010-10-05, at 3:51 PM, Phil Hagelberg wrote:

 On Tue, Oct 5, 2010 at 11:57 AM, Bob Hutchison hutch-li...@recursive.ca 
 wrote:
 What do you mean by 'switch to the repl', in fact, how do you do that?
 
 I'm using lein swank, I can connect to it, I can evaluate expressions and 
 get the correct results, I can see the communication going between emacs and 
 lein swank in the *slime-events* buffer. I switched the mode of the 
 *scratch* buffer to Clojure and I can ^X^E stuff in there and get the 
 results.
 
 The slime project (upstream) foolishly split out slime-repl into a
 separate package from slime itself, so it's a separate elisp package.
 Do M-x package-list-packages and mark slime-repl with i, then press x.
 
 If it fails to install be sure you're using the latest package.el from
 http://github.com/technomancy/package.el since there are some bug
 fixes I've submitted that *still* haven't been accepted upstream. (You
 might get compilation warnings either way; don't worry about those.)
 
 -Phil

Thank you!!

I have a repl now that works quite nicely.

I've updated my package.el as well.

Cheers,
Bob

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Thinking in Clojure

2010-09-03 Thread Bob Hutchison

On 2010-09-02, at 10:02 PM, HB wrote:

 So in idiomatic Clojure applications, maps are considered like
 objects?
 And to operate on them we pass them to functions?

I think that considering maps as a state representation is reasonable. There 
are alternatives, but that's fine-tuning I think.

There's a lot you're going to have to take in, but I suspect the biggest 
sticking point will be around values/immutable-state, references to that state, 
and when/how the reference changes. When you get this, you'll be able to see 
how state/reference/time relate to the OO concepts you already know. At which 
point you'll be laughing.

I don't remember anybody I've worked with that has had any difficulty with 
picking up functional programming (aside from the immutability thing). It's one 
of those things that changes how you work forever -- you are going to feel pain 
when working with Java :-)

I strongly second the recommendation of the book Joy Of Clojure as a next 
thing to read (it's from Manning and you can get from their MEAP in pdf/epub 
formats)

Cheers,
Bob

 
 On Sep 3, 4:55 am, David Nolen dnolen.li...@gmail.com wrote:
 On Thu, Sep 2, 2010 at 9:29 PM, HB hubaghd...@gmail.com wrote:
 Hey,
 I finished reading Programming Clojure and Practical Clojure and
 I'm hooked :)
 Please count me in the Clojure club.
 But I failed how to think in Clojure.
 My main career is around Java web applications (Hibernate, Spring,
 Lucene) and Web services.
 Lets not talk about Java web frameworks neither Clojure ones, I want
 to talk in general.
 Usually we create some domain entities, map them with Hibernate/
 iBatis.
 I don't know how a Clojure application would be build without objects.
 I think Scala really shines here, this OOP/FP is really powerful
 approach (please note I'm not saying Clojure isn't good, I don't seel
 flame war)
 How to think in Clojure? how to achieve this shift?
 
 It does require a significant shift in thinking. I think you'll be surprised
 how far maps and functions will take you if you're used to thinking in OOP.
 
 And contrary to popular belief Clojure is also a hybrid OOP/FP approach:
 multimethods, protocols, deftype, defrecord, definterface, etc. will let you
 utilize the better aspects of OOP design. However you should be cautious to
 reach for these. They are easily misapplied. Stick with the core
 datastructures (maps, vectors, sets, lists) and fns and you'll do just fine.
 
 David
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question about 'chains' of derefs a request for better ideas

2010-04-05 Thread Bob Hutchison

On 2010-04-04, at 2:47 PM, Mark Engelberg wrote:

 I don't understand why you need to get rid of the delay once it has been
 updated.  Delays are cheap; why not just be consistent about having your
 data be a ref of a delay?  It will keep your code simpler, and that's well
 worth it.

That's one of the possibilities I considered. But after the first change the 
delay would always have to be forced (it cannot be left as a delay, see the 
example I've posted below). I also didn't want to expose the delay to the 
users/programmers trying to use the stuff (too ugly). The approach of defining 
a type similar to lazy-ref that can initially have a delay but later have just 
a ref is very attractive since there's a ref-like interface for the user and it 
avoids the problem shown below.

Here's a bit of code using Per's example code:

(defn bad-thing [n]
 (let [not-lazy (ref 0)
   lazy (lazy-ref 0)
   counter  (ref 0)]

   (dotimes [i n]
 (dosync
   (ref-set counter i)
   (lazy-alter lazy (fn [x] (+ x @counter)))
   (alter not-lazy (fn [x] (+ x @counter)

   (println counter:  @counter lazy: @lazy not-lazy: @not-lazy)
   (println (* n @counter)  : (* n @counter))
   (println (/ (* n (- n 1)) 2) : (/ (* n (- n 1)) 2

With output:

lazy-ref= (bad-thing 200)
counter:  199 lazy: 39800 not-lazy: 19900
(* n @counter)  : 39800
(/ (* n (- n 1)) 2) : 19900
nil

You can see the (very) bad situation of the lazy-ref that depends on other refs 
whose values change. This is not just a problem with the lazy-ref, it would be 
easy to have the same effect by setting up delays that don't force previous 
values.


 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 To unsubscribe, reply using remove me as the subject.


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Question about 'chains' of derefs a request for better ideas

2010-04-04 Thread Bob Hutchison

Hi,

I have a situation where:
  1) I have a lot of 'values' that are both expensive to compute and quite 
large (they aren't all going to fit into memory) and most of which will not be 
needed (this time, but maybe later)
  2) I may have a need to update several of them them (in a transaction)

The first case looks to be perfectly suited to delays. The second to refs. The 
values are going to be deftypes.

So what I've come up with is a ref - a delay - a deftype.

This is fine but it gets troublesome fast.

The first time you try to get the deftype you have to write something like 
@@my-thing, and you keep writing that until the value is updated. The update 
will make the 'path' a ref - a deftype (the delay is gone). This is bad I 
think because you now have to write @my-thing to get the value.

The best that I've come up with is to update the ref with another delay, kind 
of like: (dosync (ref-set my-thing (delay my-updated-thing)))

Is the the way to do it? Is there something better I could be doing? Something 
deref-able that I'm missing that is better suited than delay? Some kind of 
deref-all-the-way function?

Thanks,
Bob



Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

To unsubscribe, reply using remove me as the subject.


Re: Question about 'chains' of derefs a request for better ideas

2010-04-04 Thread Bob Hutchison

On 2010-04-04, at 11:15 AM, Per Vognsen wrote:

 Interesting question. Here's something I whipped up in response:
 
 http://gist.github.com/355456
 
 I intentionally provide only lazy-alter and no lazy-ref-set. The
 reason is that lazy-alter can be coded so that all the unwrapping and
 rewrapping of delays can be abstracted away from the user-provided
 transformation function. A lazy-ref-set function would impose a much
 stricter discipline on the user in order to maintain laziness.
 
 All the usual caveats about full laziness apply: beware of space
 leaks, delayed side effects, etc.

That's really interesting. Thanks so much! Now I'll go think about it some more 
:-)

Cheers,
Bob

 
 -Per
 
 On Sun, Apr 4, 2010 at 9:35 PM, Bob Hutchison hutch-li...@recursive.ca 
 wrote:
 
 Hi,
 
 I have a situation where:
  1) I have a lot of 'values' that are both expensive to compute and quite 
 large (they aren't all going to fit into memory) and most of which will not 
 be needed (this time, but maybe later)
  2) I may have a need to update several of them them (in a transaction)
 
 The first case looks to be perfectly suited to delays. The second to refs. 
 The values are going to be deftypes.
 
 So what I've come up with is a ref - a delay - a deftype.
 
 This is fine but it gets troublesome fast.
 
 The first time you try to get the deftype you have to write something like 
 @@my-thing, and you keep writing that until the value is updated. The update 
 will make the 'path' a ref - a deftype (the delay is gone). This is bad I 
 think because you now have to write @my-thing to get the value.
 
 The best that I've come up with is to update the ref with another delay, 
 kind of like: (dosync (ref-set my-thing (delay my-updated-thing)))
 
 Is the the way to do it? Is there something better I could be doing? 
 Something deref-able that I'm missing that is better suited than delay? Some 
 kind of deref-all-the-way function?
 
 Thanks,
 Bob
 
 
 
 Bob Hutchison
 Recursive Design Inc.
 http://www.recursive.ca/
 weblog: http://xampl.com/so
 
 
 
 
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 To unsubscribe, reply using remove me as the subject.
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question about 'chains' of derefs a request for better ideas

2010-04-04 Thread Bob Hutchison

On 2010-04-04, at 11:15 AM, Per Vognsen wrote:

 Interesting question. Here's something I whipped up in response:
 
 http://gist.github.com/355456
 
 I intentionally provide only lazy-alter and no lazy-ref-set. The
 reason is that lazy-alter can be coded so that all the unwrapping and
 rewrapping of delays can be abstracted away from the user-provided
 transformation function. A lazy-ref-set function would impose a much
 stricter discipline on the user in order to maintain laziness.
 
 All the usual caveats about full laziness apply: beware of space
 leaks, delayed side effects, etc.

Okay, I've had a closer look at what you've done. Thanks again.

I don't need the delay after the alter. This makes lazy-ref-set pretty easy to 
use. So I defined that function and modified your lazy-alter implementation.

This is beginning to look like a single type that is the combination of a ref 
wrapping a delay, and it seems to work. I can also do some interesting things 
when the alter/ref-set happens. So this is getting even better.

Still this isn't quite 'in the language'. The user has to know that it's a lazy 
ref: the functions lazy-alter/lazy-ref-set have to be used rather than 
alter/ref-set. This is unfortunate I think. So I tried using defmethod, along 
the lines of the the contrib libraries generic.arithmetic and 
generic.comparison. Anyway, I've managed to define methods for alter and 
ref-set that will dispatch properly, and so only alter/ref-set are needed (it's 
an illusion maybe, but useful)

Anyway, looks like this'll work well.

Cheers,
Bob

 
 -Per
 
 On Sun, Apr 4, 2010 at 9:35 PM, Bob Hutchison hutch-li...@recursive.ca 
 wrote:
 
 Hi,
 
 I have a situation where:
  1) I have a lot of 'values' that are both expensive to compute and quite 
 large (they aren't all going to fit into memory) and most of which will not 
 be needed (this time, but maybe later)
  2) I may have a need to update several of them them (in a transaction)
 
 The first case looks to be perfectly suited to delays. The second to refs. 
 The values are going to be deftypes.
 
 So what I've come up with is a ref - a delay - a deftype.
 
 This is fine but it gets troublesome fast.
 
 The first time you try to get the deftype you have to write something like 
 @@my-thing, and you keep writing that until the value is updated. The update 
 will make the 'path' a ref - a deftype (the delay is gone). This is bad I 
 think because you now have to write @my-thing to get the value.
 
 The best that I've come up with is to update the ref with another delay, 
 kind of like: (dosync (ref-set my-thing (delay my-updated-thing)))
 
 Is the the way to do it? Is there something better I could be doing? 
 Something deref-able that I'm missing that is better suited than delay? Some 
 kind of deref-all-the-way function?
 
 Thanks,
 Bob
 
 
 
 Bob Hutchison
 Recursive Design Inc.
 http://www.recursive.ca/
 weblog: http://xampl.com/so
 
 
 
 
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 To unsubscribe, reply using remove me as the subject.
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: The new deftype and multimethod dispatching

2009-12-07 Thread Bob Hutchison

On 7-Dec-09, at 12:17 PM, Laurent PETIT wrote:

 2009/12/6 Bob Hutchison hutch-li...@recursive.ca


 On 6-Dec-09, at 3:46 PM, Meikel Brandmeyer wrote:

 Hi,

 Am 06.12.2009 um 21:29 schrieb Bob Hutchison:

 It turns out that dispatching on play.foo.Foo is the only way that
 works. I was hoping ::f/Foo or f/Foo would work too (maybe my alias
 is
 wrong??). Especially since, with aliasing in the user namespace, I
 can
 create a play.foo.Foo using f/Foo

 Does the following work?

 (ns play.foo)
 (deftype Foo [])
 (defmulti my-print type)
 (defmethod my-print ::Foo [x] (println Got a foo))

 (in-ns 'user)
 ; Note: normally written as (require [play.foo :as f])
 (alias 'f 'play.foo)
 (def x (f/Foo))
 (f/my-print x)


 Yes! Thanks! The dispatch on type rather than class is the trick. I
 actually ended up writing a macro, this is *much* better.


 Please note that in clojure, it's the dispatch on the class that's the
 trick, not on the type ;-)

Sorry, I don't understand what you mean. Could you expand on that a bit?

Thanks,
Bob




 Cheers,
 Bob


 Sincerely
 Meikel


 
 Bob Hutchison
 Recursive Design Inc.
 http://www.recursive.ca/
 weblog: http://www.recursive.ca/hutch



 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient  
 with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com 
 
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient  
 with your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: The new deftype and multimethod dispatching

2009-12-07 Thread Bob Hutchison

On 7-Dec-09, at 4:16 PM, ataggart wrote:
 On Dec 7, 12:37 pm, Bob Hutchison hutch-li...@recursive.ca wrote:
 On 7-Dec-09, at 12:17 PM, Laurent PETIT wrote:
 2009/12/6 Bob Hutchison hutch-li...@recursive.ca

 Yes! Thanks! The dispatch on type rather than class is the trick. I
 actually ended up writing a macro, this is *much* better.

 Please note that in clojure, it's the dispatch on the class that's  
 the
 trick, not on the type ;-)

 Sorry, I don't understand what you mean. Could you expand on that a  
 bit?


 I think Laurent means that type should be the preferred/standard
 mechanism, and class reserved for sneaking over to java-land.


Okay, that makes sense. Maybe I wasn't paying attention but it seems  
to me that the examples I've seen all use class. But, what I thought  
doesn't matter... type certainly works nicely.

Cheers,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: The new deftype and multimethod dispatching

2009-12-07 Thread Bob Hutchison

On 7-Dec-09, at 4:05 PM, Meikel Brandmeyer wrote:

 Hi,

 Am 07.12.2009 um 21:37 schrieb Bob Hutchison:

 Please note that in clojure, it's the dispatch on the class that's  
 the
 trick, not on the type ;-)

 Sorry, I don't understand what you mean. Could you expand on that a  
 bit?

 Dispatch on the class (or interface) is sometimes the trick in  
 clojure. That means a special case, which solves the problem. Eg.  
 the print-method which causes things to be printed by print  
 dispatches on type. Now, type recognises any type tag on the  
 metadata of a thing. But when there is no method defined for this  
 type, print would barf. So the default print-method simply dissocs  
 the type tag from the metadata and retries causing basically a  
 dispatch on the class of the underlying container. Most likely some  
 Map or so. So dispatching on the class is here the trick.  
 Dispatching on type the usual case.

Thanks.

BTW, I'm thinking that my use of the word 'trick' might have been a  
mistake. Where I come from 'does the trick', 'that's the trick' and so  
on mean something along the line of 'that's how you get the required  
result', and that's what I hoped to say... I didn't mean to imply any  
kind of trickiness existed that would fool me into write 'class'  
rather than 'type'... ignorance explains that quite nicely :-)

Cheers,
Bob


 Sincerely
 Meikel



Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


The new deftype and multimethod dispatching

2009-12-06 Thread Bob Hutchison

Hi,

I'm new to Clojure, not new to lisp (CL and scheme), and having a  
thoroughly good time. I've been having a go at the new deftype stuff  
and using a clone of the new branch from the git repository (up-to- 
date as of this message being posted). So far everything I've tried  
has worked very nicely, except for one thing.

I've put three files up as a gist: http://gist.github.com/250364 that  
illustrate (I hope) my question.

So. I've defined a type 'Foo -- inevitably foo, sorry -- and I want to  
define a very simple multimethod that dispatches on the class of its  
single argument. I understand that defmethod needs a fully ns  
qualified name to dispatch properly. I was hoping there was a shorter  
way of doing this than play.foo.Foo, maybe using some sort of alias- 
based technique like those in Stuary Halloway's book (p233 and  
thereabout).

I've got six variations in there, and I know full well that most of  
these should not work, but I put them in anyway.

I believe that I'm AOT compiling everything (I'm compiling the ./src/ 
play/foo.clj file and the class files are on disk, so...)

It turns out that dispatching on play.foo.Foo is the only way that  
works. I was hoping ::f/Foo or f/Foo would work too (maybe my alias is  
wrong??). Especially since, with aliasing in the user namespace, I can  
create a play.foo.Foo using f/Foo

Obviously, I have a workaround, but that's going to get ugly fast with  
a real namespace name, not to mention making re-naming the namespace  
harder than it should be.

If someone could help me out I'd appreciate it.

Thanks,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: The new deftype and multimethod dispatching

2009-12-06 Thread Bob Hutchison

On 6-Dec-09, at 3:46 PM, ataggart wrote:

 While there may be a way to work around it, if you're just dispatching
 on the type of the first arg, you might want to use defprotocol
 instead of defmulti.

True, and I likely will for most situations. In what I hope to do,  
I've got a common situation where I'd like to dispatch on two  
arguments. In something like Ruby this requires a double dispatch, but  
in CL it doesn't.

Cheers,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: The new deftype and multimethod dispatching

2009-12-06 Thread Bob Hutchison

On 6-Dec-09, at 3:46 PM, Meikel Brandmeyer wrote:

 Hi,

 Am 06.12.2009 um 21:29 schrieb Bob Hutchison:

 It turns out that dispatching on play.foo.Foo is the only way that
 works. I was hoping ::f/Foo or f/Foo would work too (maybe my alias  
 is
 wrong??). Especially since, with aliasing in the user namespace, I  
 can
 create a play.foo.Foo using f/Foo

 Does the following work?

 (ns play.foo)
 (deftype Foo [])
 (defmulti my-print type)
 (defmethod my-print ::Foo [x] (println Got a foo))

 (in-ns 'user)
 ; Note: normally written as (require [play.foo :as f])
 (alias 'f 'play.foo)
 (def x (f/Foo))
 (f/my-print x)


Yes! Thanks! The dispatch on type rather than class is the trick. I  
actually ended up writing a macro, this is *much* better.

Cheers,
Bob


 Sincerely
 Meikel



Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://www.recursive.ca/hutch



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en