Laziness and deadlocks
Consider: (def as (lazy-seq (cons 1 bs))) (def bs (lazy-seq (cons 2 cs))) ;; ... (def zs (lazy-seq (cons 26 as))) Suppose you start two threads concurrently. The first forces 'as' and the second forces 'zs'. If the timing is just right, this can result in a deadlock: // LazySeq.java final synchronized Object sval(){ if(fn != null) { try { sv = fn.invoke(); fn = null; } catch(Exception e) { throw new RuntimeException(e); } } if(sv != null) return sv; return s; } final synchronized public ISeq seq(){ sval(); if(sv != null) { Object ls = sv; sv = null; while(ls instanceof LazySeq) { ls = ((LazySeq)ls).sval(); } s = RT.seq(ls); } return s; } For this sort of reason (as well as the general overhead of locking), GHC and other compilers for lazy languages only approximately implement call-by-need: if two threads force an unevaluated thunk almost simultaneously, they will both evaluate the thunk, and the first to successfully complete the CAS at the end wins. This is an excellent implementation strategy in a pure language. However, in Clojure, it's common to use lazy sequences for side effects, and evaluating the same thunk multiple times would be very bad. I'm not sure what of the best compromise. You could use a non-synchronized wrapper around seq that checks a volatile variable (maybe fn itself) to check for multiple evaluation and, in that case, throw an error. That would amount to deadlock detection. -Per -- 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: Laziness and deadlocks
Hi, On 26 Apr., 11:22, Per Vognsen per.vogn...@gmail.com wrote: Consider: (def as (lazy-seq (cons 1 bs))) (def bs (lazy-seq (cons 2 cs))) ;; ... (def zs (lazy-seq (cons 26 as))) Suppose you start two threads concurrently. The first forces 'as' and the second forces 'zs'. If the timing is just right, this can result in a deadlock: How? As far as I understand the code forcing as and zs are basically independent tasks. seq does not recursively call into the rest. And then you'd even need a circular structure (which is - I believe - what you indicate with your fill the next number dots). Even a fixed version of forcing wouldn't return anyway on such a structure, no? But maybe I just don't understand what you mean with forcing. Sincerely Meikel -- 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: Laziness and deadlocks
On Mon, Apr 26, 2010 at 5:55 PM, Meikel Brandmeyer m...@kotka.de wrote: Hi, On 26 Apr., 11:22, Per Vognsen per.vogn...@gmail.com wrote: Consider: (def as (lazy-seq (cons 1 bs))) (def bs (lazy-seq (cons 2 cs))) ;; ... (def zs (lazy-seq (cons 26 as))) Suppose you start two threads concurrently. The first forces 'as' and the second forces 'zs'. If the timing is just right, this can result in a deadlock: How? As far as I understand the code forcing as and zs are basically independent tasks. seq does not recursively call into the rest. And then you'd even need a circular structure (which is - I believe - what you indicate with your fill the next number dots). Even a fixed version of forcing wouldn't return anyway on such a structure, no? The idea is to try to create a situation where a pair of LazySeqs, xs and ys, are interlinked in a cycle such that the first thread forces them in order xs, ys while the second thread concurrently forces them in order ys, xs. This could happen if thread #1 evaluates (doall (take 3 xs)) and thread #2 evaluates (doall (take 3 ys)). -Per -- 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: Laziness and deadlocks
On Mon, Apr 26, 2010 at 6:15 PM, Per Vognsen per.vogn...@gmail.com wrote: [...] The idea is to try to create a situation where a pair of LazySeqs, xs and ys, are interlinked in a cycle such that the first thread forces them in order xs, ys while the second thread concurrently forces them in order ys, xs. This could happen if thread #1 evaluates (doall (take 3 xs)) and thread #2 evaluates (doall (take 3 ys)). Actually, it occurs to me that they wouldn't have to be physically interlinked at all. It's enough for their thunks to be mutually referential: (def xs (lazy-seq (first ys) nil)) (def ys (lazy-seq (first xs) nil)) -Per -- 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: Laziness and deadlocks
Okay, that is a blatant infinite loop that has nothing to do with deadlocks. I give up. This combination of laziness and concurrency and locking is giving me a headache. Sorry about the distraction, everyone. -Per On Mon, Apr 26, 2010 at 6:23 PM, Per Vognsen per.vogn...@gmail.com wrote: On Mon, Apr 26, 2010 at 6:15 PM, Per Vognsen per.vogn...@gmail.com wrote: [...] The idea is to try to create a situation where a pair of LazySeqs, xs and ys, are interlinked in a cycle such that the first thread forces them in order xs, ys while the second thread concurrently forces them in order ys, xs. This could happen if thread #1 evaluates (doall (take 3 xs)) and thread #2 evaluates (doall (take 3 ys)). Actually, it occurs to me that they wouldn't have to be physically interlinked at all. It's enough for their thunks to be mutually referential: (def xs (lazy-seq (first ys) nil)) (def ys (lazy-seq (first xs) nil)) -Per -- 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: TransactionalHashMap hash computation bug
On Apr 25, 2010, at 8:33 PM, John wrote: I got no response since I posted the previous message. Should I be posting bugs to assembla space instead of here ? Yes, please create an issue. Do I need to be a member to do that ? No, you can use the support tab if you are not a member. Note that TransactionalHashMap is an unsupported experiment, so will not be prioritized without a patch. Rich On Apr 24, 7:38 pm, John jvsha...@gmail.com wrote: Hi all, I think I found my first bug in Clojure. It's in the TransactionalHashMap computation of the bin at line 30. return h % bins.length; should be replaced by return (h 0x7FFF) % bins.length; to avoid array out of bound exceptions. -- 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 athttp://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: Laziness and deadlocks
Hi, On 26 Apr., 13:27, Per Vognsen per.vogn...@gmail.com wrote: Okay, that is a blatant infinite loop that has nothing to do with deadlocks. I give up. This combination of laziness and concurrency and locking is giving me a headache. Sorry about the distraction, everyone. Well, we can step through the code and see whether this sheds some light on the issue. Calling .seq on zs, which is meant by forcing, I believe. zs.seq() sval() ; fn != null since zs was not forced before. sv = fn.invoke() ; sv is a Cons, namely (cons 26 as) fn = null return sv ; Up to now no chance of deadlock. Back to seq() ; sv != null ls = sv sv = null ; a Cons is not an instance of LazySeq s = RT.seq(ls) ; s == ls since .seq is the identity on a Cons return s ; Still no chance of deadlock. There is no other way to force a sequence in Clojure than traversing it via next/rest, which implicitely call seq on the rest. So even in the circular case there is no chance of deadlock. The recursive .sval() call is for lazy-seq evaluating to lazy-seqs. ie. (lazy-seq (lazy-seq ...)). Here - again - is no chance of deadlock. Does this make sense? Sincerely Meikel -- 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: Datatypes and Protocols update
On Apr 23, 2010, at 11:48 PM, Mark Engelberg wrote: A few meandering observations: I like the latest change to include a this argument. It makes the number of arguments line up which is a good thing. I like the idea of defrecord for the common case, rather than having to request default implementations of various interfaces within deftype. Still, I think the splitting of deftype and defrecord has merely delayed, not eliminated, the need to eventually find a convenient, general scheme for layering in default implementations of interfaces. I look forward to seeing how this evolves. I like Rich's description of Clojure's datatypes/protocols as opinionated, and mostly agree with his manifesto. The one opinion I have the most difficulty with is: It has always been an unfortunate characteristic of using classes for application domain information that it resulted in information being hidden behind class-specific micro-languages, e.g. even the seemingly harmless employee.getName() is a custom interface to data. Putting information in such classes is a problem, much like having every book being written in a different language would be a problem. You can no longer take a generic approach to information processing. This results in an explosion of needless specificity, and a dearth of reuse. OO programmers write employee.getName() methods to preserve the option of doing something more sophisticated later, which isn't readily possible once all your clients start using employee.name everywhere. So if you really want to create a generic approach to information processing, it seems like the best approach is to address the underlying reason that these custom interfaces are needed. For this reason, I've always found appealing languages which let you optionally write getter/setter methods that hook into the standard field access syntax. This lets you start out with your fields public, and let your clients use the standard field access interface. Later, if you realize you need to do something special, you can easily add a custom getter without breaking your clients. As far as I know, Clojure doesn't currently make any attempt to address this problem of allowing a standard way to access public data from an object, while preserving the option of doing something more sophisticated later. So a programmer is still forced to choose between the convenience of keyword lookup of data, versus a protocol filled with get-name functions to preserve future flexibility. Ideally, I'd like to see a way to allow me to write a program using (:name employee), and later, if I need to, customize the employee datatype so that (:name employee) actually dispatches to some other function. Ditto with (assoc employee :name Mark) (for example, to validate the data in some way?). If I'm off-base, and these issues are easy to currently workaround in Clojure, I'd love to hear more about how others are handling this in their own programs. You can use functions if you don't like unencapsulated data. Weren't you also advocating for serialization? Such things become much simpler when one knows they are dealing with just data, and not the results of some (possibly irreversible) function, of some other possibly uninitialized dependents etc. You need a level that is the data (even under some 'property' system). The keyword-accessible, constructor-mapped fields are that layer. You can always build functions on top of that. Calculated getters/setters are one of those rich sources of incidental complexity, with little real-world benefit IMO. That said, defrecord is simply implemented in terms of deftype. People can easily prototype alternatives for consideration. Rich -- 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: Datatypes and Protocols update
On Apr 24, 2010, at 1:11 PM, Richard Newman wrote: Neither of those attributes reveal information about the implementation of the objects in question. They both reveal information about the state that some client could find useful. They are both values that, if not directly available from the object should be calculated by the object, as calculating the value requires knowledge about the implementation. This approach still isn't 'good' OO -- it might not leak implementation details, but it supports asking, not telling. http://pragprog.com/articles/tell-dont-ask That is, you should endeavor to tell objects what you want them to do; do not ask them questions about their state, make a decision, and then tell them what to do. To the extent OO tries to make information into objects, it isn't 'good', IMO. That article is a good example of how goofy things get when you try to turn information into objects. Information is data. Records are for information. Why ever would I want to try to 'tell' a piece of information anything? The datatype and protocol system is there to support the polymorphic manipulation of data by functions, not for recreating OO rabbit holes. Rich -- 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
ClojureCLR multiple .dll files
Hello, I'm using ClojureCLR, at the moment I've created a couple of files that each have a (ns .. :gen-class .. ) in them. I then compiled both clj and the result is a [name].clj.dll for each file. The question I have: is there a way to create just a single dll as a result of compilation. I'm aware that in the Java version of Clojure each function produces a single .class file, and in the end all of the .class files can be packaged as part of a .jar file. In .NET there really isn't such a thing as a .class file (as far as I know). I have attempted to merge them using the ILMerge program found at MSDN. It appears that __Init__, __InternalDynamicExpressionInit, and __REPL__ would wind up being duplicate types. My guess is that individually it makes sense for these classes to exist per dll, but in a single dll perhaps only 1 of these type definition(s) should be generated. I have used the /allowDup flag to turn off errors, but I am not certain of the consequences, and perhaps the better solution is to create a common type only once when outputting these dlls based on parameters to compile, or a *flag* of some kind. Any thoughts or suggestions welcome. Thanks, L- -- 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: Datatypes and Protocols update
On 24.04.2010, at 05:48, Mark Engelberg wrote: As far as I know, Clojure doesn't currently make any attempt to address this problem of allowing a standard way to access public data from an object, while preserving the option of doing something more sophisticated later. So a programmer is still forced to choose between the convenience of keyword lookup of data, versus a protocol filled with get-name functions to preserve future flexibility. This is basically a question of how you choose your abstractions (the documented interfaces) and your implementations (the data structures), and in particular on where you draw the boundaries. That is a design issue, so I don't expect any language feature to remove the necessity to think about this carefully. For this reason, I've always found appealing languages which let you optionally write getter/setter methods that hook into the standard field access syntax. That's little more than syntactic sugar, considering that field access is equivalent to calling a method with no arguments. The closest equivalent in Clojure would be to define a functional accessor API for all access to your data. A first implementation would simply set the accessor to be a field-name keyword: (defrecord foo [bar baz]) (def get-bar :bar) (def get-baz :baz) If necessary you can then replace the accessor functions by something more complicated, or turn them into prototype functions to allow multiple implementations. Client code won't see the difference. Konrad. -- 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: Questions about program design
Hi Andrew, It's getting old now but you mind find this helpful: http://groups.google.com/group/clojure/browse_thread/thread/6333791e49fbca7f/c724f1681dac3102?lnk=gstq=drummond#c724f1681dac3102 and this: http://clojure.org/state Cheers, Paul Drummond On 25 April 2010 18:45, Andrew Brookins a.m.brook...@gmail.com wrote: Hey, all, Writing in a functional language and using a REPL for the first time, I feel like I'm playing with awesome magic. However, I'm a little confused. I have about two years of experience working with object-oriented scripting languages and C. I am somewhat familiar with thinking in terms of object-oriented design -- organizing functionality and state within classes, etc. I am trying to keep my mind fluid, though, especially as I look for a language and a platform that supports concurrency well. While a lot of Clojure really hits home with me, a nagging voice in my head says, These are just blobs of functions divided by namespaces... So, for people like me, can any of you suggest some transcribed lectures, screencasts, books, blog posts, or other errata that discuss the difference between program design in a language like Clojure and an OO language like Ruby or Java? Andrew -- 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 -- Iode Software Ltd, registered in England No. 6299803. Registered Office Address: 12 Sancroft Drive, Houghton-le-Spring, Tyne Wear, DH5 8NE This message is intended only for the use of the person(s) (the intended recipient(s)) to whom it is addressed. It may contain information which is privileged and confidential within the meaning of applicable law. If you are not the intended recipient, please contact the sender as soon as possible. The views expressed in this communication may not necessarily be the views held by The Company. -- 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: Questions about program design
On Mon, Apr 26, 2010 at 5:49 AM, Paul Drummond paul.drumm...@iode.co.uk wrote: Hi Andrew, It's getting old now but you mind find this helpful: http://groups.google.com/group/clojure/browse_thread/thread/6333791e49fbca7f/c724f1681dac3102?lnk=gstq=drummond#c724f1681dac3102 and this: http://clojure.org/state Cheers, Paul Drummond Thanks, Paul! Those links do help. Best, Andrew -- 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
tutorial on clojure protocols 1.2
I have created a short (30 min) tutorial on clojure protocols at http://vimeo.com/11236603 . Hope some of you will find it useful. Feedback welcome! Stu -- 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: Conflicting definition for IPersistentVector
Bumping. Let me emphasize this paragraph, which is really the crux of the problem: Put another way, the problem is that if I have an Associative which I know maps integers to strings, and I invoke seq(), I don't know what kind of values I'm going to get. Is this expected behavior or a bug? What's the appropriate place to submit bug reports? On Apr 13, 9:37 am, Dan dansmit...@gmail.com wrote: I'm a Java developer; I work on a project that has adopted Clojure's data structures as a convenient implementation of immutable sets, maps, etc. In attempting to add type parameters to the Clojure interfaces, I noticed a conflict in the definition of IPersistentVector. I assume the problem exists when programming in Clojure, too. IPersistentVector implements both Associative and IPersistentStack. These, in turn, both implement Seqable. But the element type in the two cases is different: if I have a vector of Strings, IPersistentStack says that seq() should enumerate the strings; Associative says that seq() should enumerate Map.Entries. The APersistentVector implementation resolves this conflict by going with the first: seq() gives you a list of strings. Put another way, the problem is that if I have an Associative which I know maps integers to strings, and I invoke seq(), I don't know what kind of values I'm going to get. When I say an interface says something, there's not actually much documentation, so that's based on what I think is the natural interpretation of the interface. The page at http://clojure.org/ data_structures does say this about IPersistentMap: seq returns a sequence of map entries, which are key/value pairs. There is no such assertion made about Associatives, but since IPersistentMap implements Seqable through Associative, it would be odd to specify the contract for Associative differently. It looks to me like the best way to handle this would be to eliminate the connection between Associative and IPersistentCollection, leaving that connection to the subtypes. But I don't know what kind of impact that would have on existing code (if it breaks something, does that code behave well when given an IPersistentVector?) -- 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: tutorial on clojure protocols 1.2
On Mon, Apr 26, 2010 at 10:20 AM, Stuart Halloway stuart.hallo...@gmail.com wrote: I have created a short (30 min) tutorial on clojure protocols at http://vimeo.com/11236603. Hope some of you will find it useful. Feedback welcome! Stu Watched it today during lunch, it was great! Thanks Stuart. -- 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: Conflicting definition for IPersistentVector
On Apr 13, 2010, at 9:37 AM, Dan wrote: I'm a Java developer; I work on a project that has adopted Clojure's data structures as a convenient implementation of immutable sets, maps, etc. In attempting to add type parameters to the Clojure interfaces, I noticed a conflict in the definition of IPersistentVector. I assume the problem exists when programming in Clojure, too. You should note that by doing so you are superimposing homogeneity on collections that are otherwise heterogeneous. IPersistentVector implements both Associative and IPersistentStack. These, in turn, both implement Seqable. But the element type in the two cases is different: if I have a vector of Strings, IPersistentStack says that seq() should enumerate the strings; Associative says that seq() should enumerate Map.Entries. As you note below, they don't say any such thing. The APersistentVector implementation resolves this conflict by going with the first: seq() gives you a list of strings. Put another way, the problem is that if I have an Associative which I know maps integers to strings, and I invoke seq(), I don't know what kind of values I'm going to get. Objects When I say an interface says something, there's not actually much documentation, so that's based on what I think is the natural interpretation of the interface. The page at http://clojure.org/ data_structures does say this about IPersistentMap: seq returns a sequence of map entries, which are key/value pairs. There is no such assertion made about Associatives, but since IPersistentMap implements Seqable through Associative, it would be odd to specify the contract for Associative differently. It looks to me like the best way to handle this would be to eliminate the connection between Associative and IPersistentCollection, leaving that connection to the subtypes. But I don't know what kind of impact that would have on existing code (if it breaks something, does that code behave well when given an IPersistentVector?) One way to look at the Seqable in high-level interfaces is just as specifying a sequence of whatever the value type is for the ultimate concrete implementation. Java supports return type covariance, so you could put a more specific signature on seq for IPersistentMap. In any case, Associative shouldn't constrain the seq or value type of the collection. All it specifies is that, given keys you can get items. Rich -- 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: tutorial on clojure protocols 1.2
Yeah, Stuart, well done ! On Apr 26, 10:44 pm, Tim Harper timchar...@gmail.com wrote: On Mon, Apr 26, 2010 at 10:20 AM, Stuart Halloway stuart.hallo...@gmail.com wrote: I have created a short (30 min) tutorial on clojure protocols at http://vimeo.com/11236603. Hope some of you will find it useful. Feedback welcome! Stu Watched it today during lunch, it was great! Thanks Stuart. -- 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 athttp://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: tutorial on clojure protocols 1.2
From the perspective of a clojure beginner, it was good information and I grokked almost everything. Specifically, any lack of comprehension on my part has more to do with the topic and my lack of clojure expertise than with your presentation. ; ) I wasn't aware of all the resources at the end so I'm glad those items were included, too. Thank you! - Ryan On Apr 26, 11:20 am, Stuart Halloway stuart.hallo...@gmail.com wrote: I have created a short (30 min) tutorial on clojure protocols athttp://vimeo.com/11236603 . Hope some of you will find it useful. Feedback welcome! Stu -- 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 athttp://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
Any window user familiar with clojure-contrib development ?
Hi, I am wondering if there is any windows user who is familiar with clojure-contrib project. The reason I asked is that I encountered quite some issues when trying to build my own copy of clojure-contrib(on windows). That includes: 1. I cannot clone http://github.com/richhickey/clojure-contrib.git as it would die in the middle for some item(i.e. certain git hash object) not found. I have to use git:// instead 2. Even after successful cloning, certain files seems to be suffering from the CRLF/LF conversion issue, I have to turn off git's CRLF auto conversion or else the newly cloned tree would already been showing changes(while the diff shows lines deleted then added with no noticeable difference, which I traced to the CRLF). 3. Then while building clojure-contrib, certain tests failed which based on the test log is again about the odd case of file system naming(file:/foo 'file://C:/foo) and CRLF LF -- 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.contrib.logging and Google App Engine
On Sun, Apr 25, 2010 at 4:47 PM, ataggart alex.tagg...@gmail.com wrote: Yeah, the fix-patch was submitted prior to the final release of 1.1.0, but alas none of those with the power to actually commit the patch got around to it until it was too late. I have built the 1.2.0-snapshot which seems to be even worse as it is now throwing exception during the build process. BUILD FAILED java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at clojure.lang.RT.loadClassForName(RT.java:1550) at clojure.lang.RT.load(RT.java:379) at clojure.lang.RT.load(RT.java:361) at clojure.core$load__5214$fn__5221.invoke(core.clj:4394) at clojure.core$load__5214.doInvoke(core.clj:4393) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one__5155.invoke(core.clj:4222) at clojure.core$load_lib__5170.doInvoke(core.clj:4259) at clojure.lang.RestFn.applyTo(RestFn.java:143) at clojure.core$apply__3699.invoke(core.clj:480) at clojure.core$load_libs__5186.doInvoke(core.clj:4293) at clojure.lang.RestFn.applyTo(RestFn.java:138) at clojure.core$apply__3699.invoke(core.clj:482) at clojure.core$use__5210.doInvoke(core.clj:4371) at clojure.lang.RestFn.invoke(RestFn.java:409) at guestbook.xmppc$loading__5103__auto8.invoke(xmppc.clj:1) at guestbook.xmppc__init.load(Unknown Source) at guestbook.xmppc__init.clinit(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at clojure.lang.RT.loadClassForName(RT.java:1550) at clojure.lang.RT.load(RT.java:379) at clojure.lang.RT.load(RT.java:361) at clojure.core$load__5214$fn__5221.invoke(core.clj:4394) at clojure.core$load__5214.doInvoke(core.clj:4393) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one__5155.invoke(core.clj:4222) at clojure.core$compile__5226$fn__5227.invoke(core.clj:4404) at clojure.core$compile__5226.invoke(core.clj:4403) at clojure.lang.Var.invoke(Var.java:365) at clojure.lang.Compile.main(Compile.java:56) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217) at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152) at org.apache.tools.ant.taskdefs.Java.run(Java.java:764) at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:218) at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:132) at org.apache.tools.ant.taskdefs.Java.execute(Java.java:105) at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) at org.apache.tools.ant.Task.perform(Task.java:348) at org.apache.tools.ant.Target.execute(Target.java:357) at org.apache.tools.ant.Target.performTasks(Target.java:385) at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337) at org.apache.tools.ant.Project.executeTarget(Project.java:1306) at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) at org.apache.tools.ant.Project.executeTargets(Project.java:1189) at org.apache.tools.ant.Main.runBuild(Main.java:758) at org.apache.tools.ant.Main.startAnt(Main.java:217) at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257) at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104) Caused by: java.lang.RuntimeException: Valid logging implementation could not be found. at clojure.contrib.logging$fn__37.invoke(logging.clj:188) at clojure.contrib.logging__init.load(Unknown Source) at clojure.contrib.logging__init.clinit(Unknown Source) -- 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: Any window user familiar with clojure-contrib development ?
I build on Windows and it's fine most of the time. I didn't deal with (1) and (2) as my initial clone was OK; I avoid (3) with - Dmaven.test.skip=true But sometimes I get these errors even though I don't change any files. I work around this by deleting the files and repeating the pull. I don't know if that's a good practice but I get the update. git pull ... Updating 2938997..db3466e error: Entry 'src/jvm/clojure/lang/APersistentMap.java' not uptodate. Cannot merge. Updating 2938997..db3466e error: Entry 'src/jvm/clojure/lang/ASeq.java' not uptodate. Cannot merge. -- 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
ClassCastException using let
I'm a clojure newbie, trying to automate a script at work and running into an issue. Given a function (defn diffCommonOrders For each order, checks the two execs maps for the entries and reports the differences [orders1 orders2 execs1 execs2] (for [order (vals orders1) :when (not-empty (get execs1 (order :receiving_order_id )))] (let [order2 (orders2 (order :cl_ord_id)) recOrdId1 (get order :receiving_order_id) recOrdId2 (get order2 :receiving_order_id)] (difference (set (get execs1 recFirmOrdId1)) (set (get execs2 recFirmOrdId2)) with orders1 and orders2 defined as a map of String to Map with keys {:receiving_order_id :cl_ord_id } and execs1 and execs2 defined as maps of String to Vector, when I try to execute this function in the REPL, I get: java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to java.util.Map$Entry I believe the error is occurring on the last line. Why is it expecting a Map Entry? Why can I not return whatever I want from the let? -- 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.contrib.logging and Google App Engine
On Mon, Apr 26, 2010 at 6:26 PM, gary ng garyng2...@gmail.com wrote: On Sun, Apr 25, 2010 at 4:47 PM, ataggart alex.tagg...@gmail.com wrote: Yeah, the fix-patch was submitted prior to the final release of 1.1.0, but alas none of those with the power to actually commit the patch got around to it until it was too late. I have built the 1.2.0-snapshot which seems to be even worse as it is now throwing exception during the build process. BUILD FAILED java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at clojure.lang.RT.loadClassForName(RT.java:1550) at clojure.lang.RT.load(RT.java:379) at clojure.lang.RT.load(RT.java:361) at clojure.core$load__5214$fn__5221.invoke(core.clj:4394) at clojure.core$load__5214.doInvoke(core.clj:4393) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one__5155.invoke(core.clj:4222) at clojure.core$load_lib__5170.doInvoke(core.clj:4259) at clojure.lang.RestFn.applyTo(RestFn.java:143) at clojure.core$apply__3699.invoke(core.clj:480) at clojure.core$load_libs__5186.doInvoke(core.clj:4293) at clojure.lang.RestFn.applyTo(RestFn.java:138) at clojure.core$apply__3699.invoke(core.clj:482) at clojure.core$use__5210.doInvoke(core.clj:4371) at clojure.lang.RestFn.invoke(RestFn.java:409) at guestbook.xmppc$loading__5103__auto8.invoke(xmppc.clj:1) at guestbook.xmppc__init.load(Unknown Source) at guestbook.xmppc__init.clinit(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at clojure.lang.RT.loadClassForName(RT.java:1550) at clojure.lang.RT.load(RT.java:379) at clojure.lang.RT.load(RT.java:361) at clojure.core$load__5214$fn__5221.invoke(core.clj:4394) at clojure.core$load__5214.doInvoke(core.clj:4393) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one__5155.invoke(core.clj:4222) at clojure.core$compile__5226$fn__5227.invoke(core.clj:4404) at clojure.core$compile__5226.invoke(core.clj:4403) at clojure.lang.Var.invoke(Var.java:365) at clojure.lang.Compile.main(Compile.java:56) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217) at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152) at org.apache.tools.ant.taskdefs.Java.run(Java.java:764) at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:218) at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:132) at org.apache.tools.ant.taskdefs.Java.execute(Java.java:105) at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) at org.apache.tools.ant.Task.perform(Task.java:348) at org.apache.tools.ant.Target.execute(Target.java:357) at org.apache.tools.ant.Target.performTasks(Target.java:385) at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337) at org.apache.tools.ant.Project.executeTarget(Project.java:1306) at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) at org.apache.tools.ant.Project.executeTargets(Project.java:1189) at org.apache.tools.ant.Main.runBuild(Main.java:758) at org.apache.tools.ant.Main.startAnt(Main.java:217) at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257) at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104) Caused by: java.lang.RuntimeException: Valid logging implementation could not be found. at clojure.contrib.logging$fn__37.invoke(logging.clj:188) at clojure.contrib.logging__init.load(Unknown Source) at clojure.contrib.logging__init.clinit(Unknown Source) Seems that the problem is deeper(well into the clojure compiler). I took out the catch_all and let the exception shows up Caused by: java.io.IOException: The system cannot find the path specified (NO_SOURCE_FILE:0) at clojure.lang.Compiler.analyzeSeq(Compiler.java:5285) at clojure.lang.Compiler.analyze(Compiler.java:5099)