Encapsulating Sub-Systems with Protocols
Has anyone used protocols to create explicit boundaries between the bigger pieces of their systems? We want to track/control the interactions between these sub-systems and are considering using protocols to define public APIs. Is this good practice? Would it be better to simply create our API like a normal library and be explicit about which functions are part of the public API? -- 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.
:default catch blocks with core.async and clojurescript
I'm having an issue where :default catch blocks are not working in clojurescript when in a go block. The following code prints "a str" as expected: (prn (try (throw "a str") (catch :default e e ))) The same code in a go block results in an unhandled exception (go (prn (try (throw "a str") (catch :default e e I can see an old core.async issue that added support for :default (http://dev.clojure.org/jira/browse/ASYNC-42) but no other references, is this a regression or something I'm missing? I'm using clojurescript "1.8.51" and core.async "0.2.374" Cameron. -- 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.
[JOB] - Clojure job in Melbourne, Australia - IOOF
Apologies for the job spam, there are still relatively few Clojure jobs so I hope people don’t mind. We're currently recruiting for an experienced polyglot developer familiar with Clojure (no commercial experience necessary) and Java in Melbourne, Australia. We have grand plans to transition our existing platform to a more flexible micro services based architecture and have spent the last few years building out Clojure and Java rest based services to make it happen. There are number of interesting technical challenges in our future including managing large numbers of services (dev-ops, cloud based provisioning, fault tolerance, monitoring distributed systems) and providing a flexible technical platform. Our company is IOOF, a financial services company specialising in superannuation and wealth management products and we're offering: - a competitive salary - agile work practices - opportunities to work on both front and back end systems - a friendly work environment - the opportunity to contribute to technical decisions for our platform If you're interested please send a copy of your CV to recruitm...@ioof.com.au with Clojure developer in the title -- 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: abysmal multicore performance, especially on AMD processors
I've posted a patch with some changes here (https://gist.github.com/4416803), it includes the record change here and a small change to interpret-instruction, the benchmark runs 2x the default as it did for Marshall. The patch also modifies the main loop to use a thread pool instead of agents and allows you to set the number of threads, this might help diagnosing the parallel performance issue. On the modified benchmark I'm seeing ~4x speedup with the parallel version on an 8 core machine and the profiler reports that the parallel version is using twice as much cpu time. I also had another look at the native calls issue modified the clojure runtime to avoid most to the calls the profiler said were taking significantly more time in the parallel version, it did speed things up but only by ~6%, not the large margin the profiling results had led me to believe were possible, it looks like the profiler overstates these methods times. The modified clojure 1.5 is available here https://github.com/cdorrat/clojure/commit/dfb5f99eb5d0a45165978e079284bab1f25bd79f if anyone's interested YourKit is reporting that a number of clojure.core functions are taking longer in the parallel version than the serial and they all seem to be methods that have one or more instanceof or instance? calls but given the results above I'm not sure how much weight to give this. It's seems the elephant is still in the room and responsible to ~50% of the cpu time :) Cameron. On Saturday, December 22, 2012 10:57:28 AM UTC+11, Marshall Bockrath-Vandegrift wrote: Lee Spector lspe...@hampshire.edu javascript: writes: FWIW I used records for push-states at one point but did not observe a speedup and it required much messier code, so I reverted to struct-maps. But maybe I wasn't doing the right timings. I'm curious about how you changed to records without the messiness. I'll include below my sig the way that I had to do it... maybe you can show me what you did instead. I just double-checked, and I definitely see a 2x speedup on Josiah’s benchmark. That may still be synthetic, of course. Here’s what I did: (eval `(defrecord ~'PushState [~'trace ~@(map (comp symbol name) push-types)])) (let [empty-state (map-PushState {})] (defn make-push-state Returns an empty push state. [] empty-state)) Still, I guess the gorilla in the room, which is eating the multicore performance, hasn't yet been found. No, not yet... I’ve become obsessed with figuring it out though, so still slogging at it. -Marshall -- 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: abysmal multicore performance, especially on AMD processors
Hi Lee, I've done some more digging and seem to have found the root of the problem, it seems that java native methods are much slower when called in parallel. The following code illustrates the problem: (letfn [(time-native [f] (let [c (class [])] (time (dorun (f (fn [_] (.isArray c)) (range 1000))] (println Sequential Test:) (time-native map) (println Parallel Test:) (time-native pmap)) On a dual quad-core xeon box I get the following results: Sequential Test: Elapsed time: 1054.807725 msecs Parallel Test: Elapsed time: 15302.605697 msecs ie. the code executed in parallel was 15 times slower than the sequential version. The same can be seen with isInstance and isArray members of java.lang.Class. I'm not sure where to go from here, these functions are frequently used by clojure.core Perhaps someone with more JVM implementation knowledge can help? Cameron. -- 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: abysmal multicore performance, especially on AMD processors
No, it's not the context switching, changing isArray (a native method) to getAnnotations (a normal jvm method) gives the same time for both the parallel and serial version. Cameron. On Saturday, December 29, 2012 10:34:42 AM UTC+11, Leonardo Borges wrote: In that case isn't context switching dominating your test? .isArray isn't expensive enough to warrant the use of pmap Leonardo Borges www.leonardoborges.com On Dec 29, 2012 10:29 AM, cameron cdo...@gmail.com javascript: wrote: Hi Lee, I've done some more digging and seem to have found the root of the problem, it seems that java native methods are much slower when called in parallel. The following code illustrates the problem: (letfn [(time-native [f] (let [c (class [])] (time (dorun (f (fn [_] (.isArray c)) (range 1000))] (println Sequential Test:) (time-native map) (println Parallel Test:) (time-native pmap)) On a dual quad-core xeon box I get the following results: Sequential Test: Elapsed time: 1054.807725 msecs Parallel Test: Elapsed time: 15302.605697 msecs ie. the code executed in parallel was 15 times slower than the sequential version. The same can be seen with isInstance and isArray members of java.lang.Class. I'm not sure where to go from here, these functions are frequently used by clojure.core Perhaps someone with more JVM implementation knowledge can help? Cameron. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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: abysmal multicore performance, especially on AMD processors
I've been moving house for the last week or so but I'll also give the benchmark another look. My initial profiling seemed to show that the parallel version was spending a significant amount of time in java.lang.isArray, clojush.pushstate/stack-ref is calling nth on the result of cons, since it isn't an instance of clojure.lang.Indexed nth resorts to a series of tests before returning the value (including isArray). I changed clojush.pushstate/push-item implementation to (assoc state type (vec (cons value (type state ;; vec added to ensure result is indexable This slowed down my single threaded version a bit but improved my parallel speedup from 2x to 3x on an 8 physical core machine. We could easily improve this by replacing the cons with conj and updating the code that pops the state or by implementing a more efficient indexable stack with deftype. After the change above clojush.interpreter/execute_instruction is looking like a hotspot with clojure.lang.ArraySeq creation seeming to spend more time in java.lang.Class.getComponentType() in the parallel version than the serial one. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
Thanks Herwig, I used your plugin with the following 2 burn variants: (defn burn-slow [ _] (count (last (take 1000 (iterate #(reduce conj '() %) (range 1)) (defn burn-fast [ _] (count (last (take 1000 (iterate #(reduce conj* (list nil) %) (range 1)) Where conj* is just a copy of clojure.core/conj. In the first case I see the same behaviour you saw, fast serially and in separate processes (~115 ms) but slow in parallel for both the same and different class loaders (708ms - 950ms). In the second case where I avoid any references to clojure.lang.PersistentList$EmptyList and use a clean copy of conj I see much better performance in all cases (~ 40ms - 50ms) and no slow down in the parallel cases in the same JVM. Until Lee has a representative benchmark for his application it's difficult to tell if he's experiencing the same problem but there would seem to be a case for changing the PersistentList implementation in clojure.lang. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
I'd be interested in seeing your GP system. The one we're using evolves Push programs and I suspect that whatever's triggering this problem with multicore utilization is stemming from something in the inner loop of my Push interpreter (https://github.com/lspector/Clojush)... but I don't know exactly what it is. Originally I was using ECJ (http://cs.gmu.edu/~eclab/projects/ecj/) in java for my GP work but for the last few years it's been GEVA with a clojure wrapper I wrote (https://github.com/cdorrat/geva-clj). I realize that I could go back to this sort of thing, or something more modern and reasonable like hadoop, but of course it'd be a lot nicer if parallelization via agents (or some other mechanism central to the language) just didn't have whatever pathology we've uncovered. Agreed, I'd like clojure to be my preferred language when I have a 100 core machine, it's certainly something I'd like to get to the bottom of. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
On Friday, December 14, 2012 5:41:59 AM UTC+11, Wm. Josiah Erikson wrote: Does this help? Should I do something else as well? I'm curious to try running like, say 16 concurrent copies on the 48-way node Have you made any progress on a small deterministic benchmark that reflects your applications behaviour (ie. the RNG seed work you were discussing)? I'm keen to help, but I don't have time to look at benchmarks that take hours to run. I've also been using clojure for genetic programming and have been getting very good parallel speedups on a single jvm, this type of problem should see excellent performance gains, it has many medium size cpu intensive sub-problems that require no shared resources. I used hadoop to scale beyond single machines, in the worst case you can use this approach and you should see speed-ups equivalent to your multiple jvm test. I just split the population into small blocks and had each map function calculate the fitness and return a map of individual-id - fitness. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
Hi Marshall, the megamorphic call site hypothesis does sound plausible but I'm not sure where the following test fits in. If I understand correctly we believe that it's the fact that the base case (an PersistentList$EmptyList instance) and the normal case (an PersistsentList instance) have different types and when run in paralell the interleaving invocations are causing problems for the JIT but when we use a vector it's a single type so we see a better speedup. I was toying with the idea of replacing the EmptyList class with a PersistsentList instance to mitigate the problem in at least one common case, however it doesn't seem to help. If I replace the reverse call in burn with the following code: #(reduce conj (list nil) %) I get the same slowdown as we see if reverse (equivalent to #(reduce conj '() %)) where: (class '())= clojure.lang.PersistentList$EmptyList (class (list nil)) = clojure.lang.PersistentList I'm not convinced were at the bottom of it yet, perhaps the earlier post on memory contention by Carlos might yield some clues. If the issue was related to memory access it might help explain why the impact differed significantly between intel and amd hardware. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
On Thursday, December 13, 2012 12:51:57 AM UTC+11, Marshall Bockrath-Vandegrift wrote: cameron cdo...@gmail.com javascript: writes: the megamorphic call site hypothesis does sound plausible but I'm not sure where the following test fits in. ... I was toying with the idea of replacing the EmptyList class with a PersistsentList instance to mitigate the problem in at least one common case, however it doesn't seem to help. If I replace the reverse call in burn with the following code: #(reduce conj (list nil) %) I get the same slowdown as we see if reverse (equivalent to #(reduce conj '() %)) Ah, but include your own copy of `conj` and try those two cases. The existing clojure.core/conj has already been used on multiple types, so you need a new IFn class with a fresh call site. Here are the numbers I get when I do that: Ah, I've also been looking at this in the morning and missed that bit. When I use a copy of conj I get similar results to yourself: w/ list-base : map-ms: 4.0, pmap-ms 0.6, speedup 7.02 w/ empty-list-base : map-ms: 9.9, pmap-ms 20.4, speedup 0.48 w/ list-base : map-ms: 9.4, pmap-ms 20.7, speedup 0.45 w/ vector : map-ms: 4.5, pmap-ms 1.4, speedup 3.28 It does seem that once used on the empty list case conj gets tainted and all future list uses incur a performance penalty. On that basis it would seem reasonable to convert the EmptyList uses in core.lang to a PersistentList instance. Interestingly using a tainted conj with other types doesn't seem to incur the penalty (the last vector in the times above) If I get time I might look at a protocol based version of conj out of interest. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
Hi Marshall, I think we're definitely on the right track. If I replace the reverse call with the following function I get a parallel speedup of ~7.3 on an 8 core machine. (defn copy-to-java-list [coll] (let [lst (java.util.LinkedList.)] (doseq [x coll] (.addFirst lst x)) lst)) This function should do as much memory allocation as the clojure reverse but has vastly better parallel performance. There does seem to be something unusual about conj and clojure.lang.PersistentList in this parallel test case and I don't think it's related to the JVMs memory allocation. Cameron. -- 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: abysmal multicore performance, especially on AMD processors
Interesting problem, the slowdown seems to being caused by the reverse call (actually the calls to conj with a list argument). Calling conj in a multi-threaded environment seems to have a significant performance impact when using lists I created some alternate reverse implementations (the fastest uses a vector and cons), the gist with the test code can be found at https://gist.github.com/4243724 On a dual Xeon E5520 (8 physical cores) @ 2.27GHz with Linux runnning OpenJDK 1.7.0_09 I got the following results: fast-reverse: map-ms: 3.3, pmap-ms 0.7, speedup 4.97 list-cons : map-ms: 4.0, pmap-ms 0.7, speedup 6.13 vec-conj: map-ms: 4.0, pmap-ms 1.3, speedup 3.10 list-conj : map-ms: 10.8, pmap-ms 21.2, speedup 0.51 clojure-reverse : map-ms: 13.5, pmap-ms 26.8, speedup 0.50 (this is equivalent to the original code) The following JDK command line options were used: -Xmx20G -XX:MaxPermSize=8G -XX:+UseParallelGC -XX:+UseParallelOldGC Some other notes: I ran the sample under YourKit and garbage collection represents a small percentage of execution time in both single and multi-threaded tests, there are no blocked threads for the duration of the test and there is no unexpected monitor/lock usage. Cheers, Cameron. -- 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: abysmal multicore performance, especially on AMD processors
I forgot to mention, I cut the number of reverse iterations down to 1000 (not 1) so I wouldn't have to wait too long for criterium, the speedup numbers are representative of the full test though. Cameron. On Sunday, December 9, 2012 6:26:16 PM UTC+11, cameron wrote: Interesting problem, the slowdown seems to being caused by the reverse call (actually the calls to conj with a list argument). Calling conj in a multi-threaded environment seems to have a significant performance impact when using lists I created some alternate reverse implementations (the fastest uses a vector and cons), the gist with the test code can be found at https://gist.github.com/4243724 On a dual Xeon E5520 (8 physical cores) @ 2.27GHz with Linux runnning OpenJDK 1.7.0_09 I got the following results: fast-reverse: map-ms: 3.3, pmap-ms 0.7, speedup 4.97 list-cons : map-ms: 4.0, pmap-ms 0.7, speedup 6.13 vec-conj: map-ms: 4.0, pmap-ms 1.3, speedup 3.10 list-conj : map-ms: 10.8, pmap-ms 21.2, speedup 0.51 clojure-reverse : map-ms: 13.5, pmap-ms 26.8, speedup 0.50 (this is equivalent to the original code) The following JDK command line options were used: -Xmx20G -XX:MaxPermSize=8G -XX:+UseParallelGC -XX:+UseParallelOldGC Some other notes: I ran the sample under YourKit and garbage collection represents a small percentage of execution time in both single and multi-threaded tests, there are no blocked threads for the duration of the test and there is no unexpected monitor/lock usage. Cheers, Cameron. -- 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] geva-clj 1.2 - Grammatical evolution in clojure
It doesn't support that out of the box but it should be pretty straight forward to add. Was the use case you were thinking of something like this http://paste.lisp.org/display/130713 ? Cameron. On Thursday, July 26, 2012 11:07:31 PM UTC+10, Jeff Rose wrote: Wow, cool. Over the years we've talked about using some kind of grammar constrained evolution to generate synthesizers and musical ideas in Overtone, and this could be just the tool to do that. Would it be possible to perform iterations manually, rather than having to pass the fitness function to geva-run? That way we could create a new generation, generate mp3's based on their output, let people score them, and once all scored request the next generation. Now I need to think about how to define synthesis grammars... -Jeff -- 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: community interest in machine learning (?)
Hi Lee, apologies for the missing dependencies, it's been a while since I worked on the project and I had local copies of jscheme in .m2. The documentation has been fixed and I've updated the dependencies. I've run the samples a built a fresh checkout on a clean machine so I think you should be ok now though I did have to delete ~/.m2 in one case. Let me know if you have any problems. Cheers, Cameron. On Thursday, July 26, 2012 11:42:07 PM UTC+10, Lee wrote: Cameron, I'm eager to check this out. There's a missing quote mark in the dependency line in the getting started guide, but after fixing it I still get: Downloading: org/clojars/cdorrat/geva-clj/1.2-SNAPSHOT/geva-clj-1.2-SNAPSHOT.pom from repository clojars at http://clojars.org/repo/ Unable to locate resource in repository [INFO] Unable to find resource 'org.clojars.cdorrat:geva-clj:pom:1.2-SNAPSHOT' in repository clojars ( http://clojars.org/repo/) An error has occurred while processing the Maven artifact tasks. This is in a fresh Clojure 1.3 project to which I've just added that one dependency. Am I missing something obvious? Thanks, -Lee On Jul 25, 2012, at 6:04 PM, cameron wrote: I've posted the code for the clojure enhanced GEVA library, there's a getting started guide available at http://cdorrat.github.com/geva-clj/ and the source is available at http://github.com/cdorrat/geva-clj It's currently based on GEVA 1.2 if there's enough interest I'll look at merging the changes from 2.0 release. Cheers, Cameron. -- 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: community interest in machine learning (?)
I've posted the code for the clojure enhanced GEVA library, there's a getting started guide available at http://cdorrat.github.com/geva-clj/ and the source is available at http://github.com/cdorrat/geva-clj It's currently based on GEVA 1.2 if there's enough interest I'll look at merging the changes from 2.0 release. Cheers, Cameron. -- 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
[ANN] geva-clj 1.2 - Grammatical evolution in clojure
Grammatical evolution is a form of genetic programming that allows you to search for a program fragment or form that has a high fitness by evolving and testing multiple models across generations. Grammatical evolution differs from traditional genetic programming in that individuals are created from a BNF grammar, this makes it much easier to specify constraints in the solution and adapt the search to new problem domains. geva-clj allows you to evolve clojure programs or drive java based searches written in the GEVA framework. There's a getting started guide available at http://cdorrat.github.com/geva-clj/ The source is on github at http://github.com/cdorrat/geva-clj The GEVA project page with lots of documentation and Java examples is available at http://ncra.ucd.ie/Site/GEVA.html The core library is available on clojars, add the following to your project.clj [org.clojars.cdorrat/geva-core 1.2-SNAPSHOT] Cameron. -- 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: community interest in machine learning (?)
I wrote a clojure wrapper for GEVA ( a gramatical evolutional library, see http://ncra.ucd.ie/Site/GEVA.html) that I can put on github if theres any interest. I'm not as active in this area as I once was but I'm definitely still interested. -- 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: Bret Victor - Inventing on Principle
Great video, it was interesting that the binary search example only really works with pure functions since you must specify all of the initial state for the debugger/visualiser. In non-pure functions (and oo) the user is unlikely to be able to specify valid values for all the mutable state even if the application could tell them which variables were being referenced. In clojure something like this might not be too difficult, perhaps we could: - define a temporary function with the same text - use CDT or another debugger to set a break-point in the temporary function - call the function and capture the current stack frame variables at each invocation display as in the video Support for higher order functions and list comprehension (map, reduce, for, etc.) may be difficult though. -- 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
ANN: reduce-fsm 0.1.0 released
reduce-fsm provides a simple way to specify clojure finite state machines, it allows you to: - Define define state machines that accumulate values (in the same was that reduce does) - Create lazy sequences from state machines - Perform stateful filtering with clojures filter/remove functions - Visualize the resulting state machines with graphviz All generated state machines are plain clojure functions and read events from clojure sequences. Events are dispatched with core.match and allow the use of all match features (guards, destructuring, regex matching, etc.) Documentation is available at http://cdorrat.github.com/reduce-fsm/ and the source at https://github.com/cdorrat/reduce-fsm Feedback and comments are welcome. Cameron. -- 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
Binding and temporary global state
Hello all, here is an extremely reduced version of a problem I'm not sure how to work around. (It's going to be a toy assembly language if anyone's wondering) When I call assemble in the following code I get the error: java.lang.IllegalStateException: Var reader/*macros* is unbound. I'd like *macros* to always be rebound for whatever source file is being compiled and I'd rather not explicitly pass the map of macros (and other things not shown here) to every function in the hierarchy just to supply some of the bottom level worker functions with the information they need. Is there a way to do this? Besides cleaning up function signatures is this a premature optimization to begin with? (declare *macros*) (defn macro-expand [tokens] (map #(get *macros* % %) tokens)) (defn compile-op [op] (macro-expand op)) (defn assemble [{:keys [macros syms blks fncs]}] (binding [*macros* macros] ;; I thought binding would handle this, but I must be misusing it (let [compiled-ops (map compile-op fncs)] compiled-ops))) -- 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: Binding and temporary global state
Interesting results. By putting (println compiled-ops) it worked, but not by putting it in a doall. (same error) Changing my declares to defs did the trick did though and learning about bound-fn* was also a serious mind-expander for me right now too. Thanks to both of you! On Sep 6, 4:57 pm, Jarkko Oranen chous...@gmail.com wrote: Cameron Pulsford wrote: Is there a way to do this? Besides cleaning up function signatures is this a premature optimization to begin with? (declare *macros*) (defn macro-expand [tokens] (map #(get *macros* % %) tokens)) (defn compile-op [op] (macro-expand op)) (defn assemble [{:keys [macros syms blks fncs]}] (binding [*macros* macros] ;; I thought binding would handle this, but I must be misusing it (let [compiled-ops (map compile-op fncs)] compiled-ops))) Your problem is that compiled-ops is a lazy sequence, and it only gets realised when it's used, which probably happens after it has exited the dynamic scope where *macros* is bound. You can work around the problem by forcing the sequence with doall or by using bound-fn* to save the dynamic environment (ie. (map (bound- fn* compile-op) fns), though double check that from the docs) -- 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: trouble using nested map fn
Again with the bad examples but... (map #(even? %) coll) is faster than (map (partial even?) coll) So it's at least got that going for it. (I know this SHOULD be written as (map even? coll)) On Aug 23, 1:59 pm, Michael Gardner gardne...@gmail.com wrote: On Aug 23, 2010, at 11:13 AM, Luka Stojanovic wrote: On Mon, 23 Aug 2010 18:01:13 +0200, Joop Kiefte iko...@gmail.com wrote: bad example =/ Yes, it is but you get the gist I hope better example: #(first (sort %)) ;) (comp first sort) and #(some-fn x %) can be written as (partial some-fn x) which leaves #(some-fn % x) as case not trivial with other syntax again (fn [y] (some-fn y x)) is about 8 chars longer, so I guess #() form really is not something that should be used that often I don't know about you, but I find #(= 2 (count %)) much nicer and easier to read than (comp (partial = 2) count). -- 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
Unsigned-right-shift patch
Hey all, I had an itch this weekend... so I scratched it. I was doing some bit twiddling stuff and needed the Java operator. I had written some workarounds but they were overly-complicated and slower than I would have hoped, so I dug directly into core and added it as a first class citizen next to bit-shift-left and bit-shift- right. Being a very creative person, I named it . The performance is on par with the normal signed shift operators. To anyone who is interested, the patch can be found at: http://github.com/cpulsford/bitops/blob/logical-assumption/unsigned-right-shift.patch I'd love feedback, especially since this is my first time digging into the Java side of Clojure. Could this maybe be something useful for core? -- 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: Unsigned-right-shift patch
Yes the 1.0 was a slip on my part, and I agree that I should have used the class/staticMembers syntax; at the time I was simply trying to fit in. Regardless, here is the updated patch with those two comments fixed: http://github.com/cpulsford/bitops/blob/logical-assumption/unsigned-right-shift.patch I also made a separate patch that fixes ALL the bit operators in the same way, plus I inlined the few that weren't. This patch can be found at: http://github.com/cpulsford/bitops/blob/logical-assumption/bitops-revamped.patch On Aug 23, 5:43 pm, Alan a...@malloys.org wrote: Without commenting on the usefulness of this (it doesn't really interest me), there are a couple style things I would change. First, :added ought to be 1.3 (maybe 1.2?), not 1.0. Second, the newsgroup seems to think that if you're changing clojure.core you might as well update from (. staticMember class args) to (class/ staticMember args) while you're in there. You could also fix the other shift operators if you wanted. On Aug 23, 1:15 pm, Cameron cpuls...@gmail.com wrote: Hey all, I had an itch this weekend... so I scratched it. I was doing some bit twiddling stuff and needed the Java operator. I had written some workarounds but they were overly-complicated and slower than I would have hoped, so I dug directly into core and added it as a first class citizen next to bit-shift-left and bit-shift- right. Being a very creative person, I named it . The performance is on par with the normal signed shift operators. To anyone who is interested, the patch can be found at:http://github.com/cpulsford/bitops/blob/logical-assumption/unsigned-r... I'd love feedback, especially since this is my first time digging into the Java side of Clojure. Could this maybe be something useful for core? -- 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: trouble using nested map fn
The difference is not HUGE, but in a critical section it might be a valid micro-optimization. I'd also be interested to know why, but I bet you're assumption of apply being thrown in the mix is probably pretty close to true. user= (time (dotimes [_ 1e6] (doall (map #(filter even? %) (for [i (range 0 100 4)] (range i (+ i 4))) Elapsed time: 6589.49 msecs nil user= (time (dotimes [_ 1e6] (doall (map #(filter even? %) (for [i (range 0 100 4)] (range i (+ i 4))) Elapsed time: 6620.396 msecs nil user= (time (dotimes [_ 1e6] (doall (map (partial filter even?) (for [i (range 0 100 4)] (range i (+ i 4))) Elapsed time: 8899.466 msecs nil user= (time (dotimes [_ 1e6] (doall (map (partial filter even?) (for [i (range 0 100 4)] (range i (+ i 4))) Elapsed time: 8949.646 msecs nil (sorry for further hijacking the thread) On Aug 23, 6:09 pm, Alan a...@malloys.org wrote: Really? I would be interested to hear why; is it maybe because partial has to take any number of arguments and then (apply even? args)? I've taken to using partial when I can, precisely because of the difficulty of nesting anonymous functions, and while performance isn't a big deal for me I'm curious. On Aug 23, 12:30 pm, Cameron cpuls...@gmail.com wrote: Again with the bad examples but... (map #(even? %) coll) is faster than (map (partial even?) coll) So it's at least got that going for it. (I know this SHOULD be written as (map even? coll)) On Aug 23, 1:59 pm, Michael Gardner gardne...@gmail.com wrote: On Aug 23, 2010, at 11:13 AM, Luka Stojanovic wrote: On Mon, 23 Aug 2010 18:01:13 +0200, Joop Kiefte iko...@gmail.com wrote: bad example =/ Yes, it is but you get the gist I hope better example: #(first (sort %)) ;) (comp first sort) and #(some-fn x %) can be written as (partial some-fn x) which leaves #(some-fn % x) as case not trivial with other syntax again (fn [y] (some-fn y x)) is about 8 chars longer, so I guess #() form really is not something that should be used that often I don't know about you, but I find #(= 2 (count %)) much nicer and easier to read than (comp (partial = 2) count). -- 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: Protocols and default method implementations
I've been wondering about this topic recently as well. Often such a function does not need to be part of the contract for implementers (i.e. the protocol) at all. Stu, (or anybody) I'd like to ask about a variation on this point. How do you handle the case where you have a general function that works for every type you'd like to implement a protocol for (thus not technically needing to be in a protocol), but maybe 1 or 2 of the many types have more efficient implementations possible? Do you just suck it up and copy and paste the general function around? Or is there a better way? Maybe the new case function? After reading the docs on clojure.org/protocols, it seemed like you could just define the general implementation of functions under Object and then define your specific implementations on the other types, but this didn't seem to work for me. I would get an error to the effect of foo is not defined for Type On Aug 12, 9:51 am, Stuart Halloway stuart.hallo...@gmail.com wrote: The other thing that you should consider is that protocols are the contract for implementers, not the contract for callers. If you change a contract for implementers, then the implementers *must* change. Take your example of a function that has a reasonable default for any object. Often such a function does not need to be part of the contract for implementers (i.e. the protocol) at all. To make this more concrete, look at how protocols are used in Clojure itself. InternalReduce is a contract for implementers, consumers call reduce. Ditto for IOFactory: clients don't call it, they call the functions reader, writer, etc. instead. Stu Does this help?:http://fulldisclojure.blogspot.com/2010/08/thoughts-on-protocols.html And Sean's comment here:http://programming-puzzler.blogspot.com/2010/08/racket-vs-clojure.html Regards, Shantanu On Aug 12, 5:46 pm, Laurent PETIT laurent.pe...@gmail.com wrote: Hi, 2010/8/12 Matthew mattp...@gmail.com Hello all, I've been looking at the new protocol (defprotocol, deftype, defrecord, etc) feature in 1.2 and, while I love the core concepts, it's been bothering me that there's no apparent way to provide *automatic* default implementations for methods on a protocol. I know from reading Rich Hickey's discussions on the design rationale [1] and other threads on providing Scala Trait-like behaviour [2] that you can choose to mix in a set of defaults when you implement the protocol, but it seems important to me that a protocol author be able to provide default implementations to enable protocols to evolve. Allowing a function body in the defprotocol clause would seem to be the obvious way, something like: (defprotocol P (foo [x] (default-foo x)) (bar-me [x] (bar-me [1 x]) [x y])) ; no default implementation As I'm sure most of you know, a key problem with pure interface features in environments like CORBA, COM, Java, etc has been that you can't add new methods to published interfaces: you'd break all existing implementations. Hence you see a history of evolving interfaces indicated by names like IFoo, IFoo2, IFooEx, etc. In contrast, a Scala-like trait system allows you to add a new method *and* a default implementation (supposing that makes sense), so old clients still work fine. The problem, as I see it, with Clojure protocols is that you would have to rely on clients mixing in a set of defaults in order to happily extend a public protocol. Am I missing something key here? I realise there are some very experienced people contributing to Clojure, so am fully expecting to be told I've missed something obvious ;) Maybe have the library writer do this ? : (defprotocol P (foo [x] (default-foo x)) (bar-me [x] (bar-me [1 x]) [x y])) ; no default implementation (def *P-defaults* {:foo default-foo :bar-me #(bar-me 1 %) }) and let the user pick the whole *P-defaults* for its mixins, or just parts of it ? (does this make sense ?) Cheers, Matthew. [1]http://groups.google.com/group/clojure/msg/330c230e8dc857a9 [2]http://groups.google.com/group/clojure/msg/53228e04db4799a5 -- 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
Re: Resource cleanup when lazy sequences are finalized
Not 100% on this, but this is what I do when reading files... (with-open [rdr (BufferedReader. (FileReader. file-name))] (reduce conj [] (line-seq rdr))) That ensures that the whole seq is realized without closing the handle, but it also allows you to wrap the whole block with a take function if you only cared about the first few lines. As far as I know, this would still close the resources after whether you realize the whole sequence or only take part of it. Can someone who knows a bit better confirm? On Aug 3, 5:28 pm, Jeff Palmucci jpalmu...@gmail.com wrote: See my library athttp://github.com/jpalmucci/clj-yield, which makes this trivial. For example, here is a function I use to read a sequence of java serialized objects from a stream: (defn read-objects [path] (with-yielding [out 1000] (with-open [stream (java.io.ObjectInputStream. (java.io.BufferedInputStream. (java.util.zip.GZIPInputStream. (java.io.FileInputStream. (io/file path)] (loop [] (try (let [next (.readObject stream)] (yield out next) (recur)) (catch java.io.EOFException e (.close stream))) When the sequence returned by with-yielding becomes garbage collectable, yield will throw an exception causing with-open to close the file. Note that with-yielding will use a thread from the thread pool, so its a bad idea to have hundreds of active with-yieldings at once. On Aug 3, 3:21 pm, David Andrews dammi...@gmail.com wrote: I want to create a lazy seq backed by an open file (or db connection, or something else that needs cleanup). I can't wrap the consumer in a with-anything. Is there a general method for cleaning up after the consumer discards its reference to that lazy seq? I'm vaguely aware of Java finalize, but am also aware that it is unpredictable (e.g. you aren't guaranteed to be driven at the next gc). Does Clojure even provide the ability to define a finalize method for a lazy seq? (Sipping water from a firehose...) -- 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: destructuring using :as in fn arg vector
Ahhh! It's so obvious now that I'm almost embarrassed. Thank you Randy Cam On Jul 27, 4:17 pm, Randy Hudson randy_hud...@mac.com wrote: The form you're looking for is (defn foo [ [a b :as c]] ...) On Jul 27, 2:57 pm, Cameron cpuls...@gmail.com wrote: Hey all, just wondering if this is normal or not. There seems to be something weird going on with :as in a functions arg vector. This little example works as I'd expect... user= (defn foo [[a b :as c]] c) #'user/foo user= (foo [1 2]) [1 2] But this one does not user= (defn foo [a b :as c] c) java.lang.Exception: Unsupported binding form: :as (NO_SOURCE_FILE:11) user= I would expect to call the second example like (foo 1 2) and have it return [1 2]. So if this happens to be expected behavior, is there an idiomatic way to do destructure args but also refer to them all as one list? -- 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: Idea for personal Clojure project
A very good place to start searching about edit distances between words and some related stuff can be found on Peter Norvigs site at: http://norvig.com/spell-correct.html Also, try to find some wikipedia articles about the bm25 ranking algorithm, I used clojure for an assignment at school that required we write a little ranking mechanism with this algorithm and it's a pretty straightforward approach; not to hard to wrap your head around the whole thing. Can't quite remember if it did semantic stuff or just word simple frequency though. The hard part might be getting a training set. I'd offer you the file I had but I think I deleted it after the semester was over.. -Cameron On Jul 28, 2010, at 4:58 PM, Daniel wrote: I want to write a clojure program that searches for similarities of words in the english language and places them in a graph, where the distance between nodes indicates their similarity. I don't mean syntactical similarity. Related contextual meaning is closer to the mark. For instance: fish and reel don't have much similarity, but in the context of fishing they do, so the distance in such a graph wouldn't be very large. I'm sure research has been done in this area (I suspect with no small portion belonging to google), so can anybody point me in the right direction? 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 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
destructuring using :as in fn arg vector
Hey all, just wondering if this is normal or not. There seems to be something weird going on with :as in a functions arg vector. This little example works as I'd expect... user= (defn foo [[a b :as c]] c) #'user/foo user= (foo [1 2]) [1 2] But this one does not user= (defn foo [a b :as c] c) java.lang.Exception: Unsupported binding form: :as (NO_SOURCE_FILE:11) user= I would expect to call the second example like (foo 1 2) and have it return [1 2]. So if this happens to be expected behavior, is there an idiomatic way to do destructure args but also refer to them all as one list? -- 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: filtering with multiple predicates
Hi Bill, How about something like... (filter #(every? true? ((juxt f g h) %)) my-list) In the character sense it's not more terse than your original example, but it is a little nicer to add additional functions to compare with. Throwing it in a function could be useful too (defn multi-filter [coll funcs] (filter #(every? true? ((apply juxt funcs) %)) coll)) = (multi-filter [0 1 2 3 4] even? (complement zero?)) = (2 4) On Jul 23, 6:33 pm, ataggart alex.tagg...@gmail.com wrote: Not that preserves the short-circuiting behavior of 'and. This works though: (defmacro andf [ fns] (let [x# (gensym)] `(fn [~x#] (and ~@(map #(list % x#) fns) user= (filter (andf integer? odd?) [1 2 3.1]) (1) On Jul 23, 2:27 pm, .Bill Smith william.m.sm...@gmail.com wrote: I want to filter a list based on the logical AND of a set of predicates. For example, let's say I have single-argument functions f, g, and h (without side-effects), and I want those items x in the list such that (f x), (g x) and (h x) are all true. I know I can do this: (filter #(and (f %) (g %) (h %)) my-list) Is there a more terse way to express the same thing? I suspect there is a mechanism similar to (or perhaps a generalization of) composition for that, but I couldn't find it in the API docs. Bill Smith Austin, TX -- 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
Variadic arguments and macros
Hello all! Today, I've either discovered a bug, or I've discovered a flaw in my understanding of macros. Most likely the latter :-) Could anyone set me straight? While this is not the macro I was trying to write, it falls over in the same place. (user= (defmacro foo [ xs] `(map identity ~xs)) #'user/foo user= (foo 1 2) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) However, this does work (though it doesn't feel idiomatic). user= (defmacro foo [ xs] `(map identity [...@xs])) #'user/foo user= (foo 1 2) (1 2) I have tried this on todays (July 7) bleeding edge and 1.1 with the same results. -- 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: Variadic arguments and macros
Thanks for all the replies everyone, I certainly have a solution now. But I am still a little confused. Take this slight variation... user= (defmacro foo [coll] `(map identity ~coll)) #'user/foo user= (foo [1 2 3 `(+ 1 1)]) (1 2 3 (clojure.core/+ 1 1)) In this one, I am passing an explicit list and simply calling unquote on it. I guess what I want to know is, how is passing an explicit list different from having one destructured with '' in the arguments list? On Jul 7, 1:04 pm, Nicolas Oury nicolas.o...@gmail.com wrote: Of course I meant (map identity (1 2)) On Wed, Jul 7, 2010 at 6:03 PM, Nicolas Oury nicolas.o...@gmail.com wrote: If you macroexpand the first foo in (foo 1 2), you will see something like (1 2) when this gets evaluated, Clojure is not happy about 1 not being a function. On Wed, Jul 7, 2010 at 5:49 PM, Cameron cpuls...@gmail.com wrote: Hello all! Today, I've either discovered a bug, or I've discovered a flaw in my understanding of macros. Most likely the latter :-) Could anyone set me straight? While this is not the macro I was trying to write, it falls over in the same place. (user= (defmacro foo [ xs] `(map identity ~xs)) #'user/foo user= (foo 1 2) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) However, this does work (though it doesn't feel idiomatic). user= (defmacro foo [ xs] `(map identity [...@xs])) #'user/foo user= (foo 1 2) (1 2) I have tried this on todays (July 7) bleeding edge and 1.1 with the same results. -- 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
Re: Variadic arguments and macros
Thanks everyone! I certainly have my solution; but, I'm still a bit confused. Here's another example... user= (defmacro foo [coll] `(map identity ~coll)) #'user/foo user= (foo (list 1 2 3)) (1 2 3) In this example, I pass an explicit list and all I have to do is unquote 'coll'. How is passing an explicit list any different than having it destructured via '' in the argument vector? On Jul 7, 1:11 pm, Jason Wolfe jawo...@berkeley.edu wrote: Hi Cameron, On Jul 7, 9:49 am, Cameron cpuls...@gmail.com wrote: Hello all! Today, I've either discovered a bug, or I've discovered a flaw in my understanding of macros. Most likely the latter :-) Could anyone set me straight? While this is not the macro I was trying to write, it falls over in the same place. (user= (defmacro foo [ xs] `(map identity ~xs)) #'user/foo user= (foo 1 2) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) Well, let's look at the macroexpansion: user (macroexpand '(foo 1 2)) (clojure.core/map clojure.core/identity (1 2)) As you can see, this tries to call 1 with an argument of 2, which gives the exception you see. If you want your arguments evaluated, I think your solution is as good as any. If you want them unevaluated, you can do: user (defmacro foo2 [ xs] `(map identity '~xs)) #'user/foo2 user (foo2 1 2) (1 2) The difference: user (foo2 1 (+ 1 1)) (1 (+ 1 1)) -Jason -- 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
Binding broken in 1.1.0-alpha
Not sure if you guys know this but binding doesn't work in 1.1.0-alpha on Snow Leopard and apparently Linux. (def foo 10) ; = '#user/foo foo ; = 10 (binding [foo 42] foo) ; = 10 (binding [user/foo 42] foo) ; = 10 (binding [user/foo 42] (var-get #'user/foo)) ; = 10 Here's the post on StackOverflow: http://stackoverflow.com/questions/1599037/clojure-binding-not-working --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---