Re: commute
On Nov 26, 2:35 pm, "Mark Volkmann" <[EMAIL PROTECTED]> wrote: > On Wed, Nov 26, 2008 at 1:13 PM, Shawn Hoover <[EMAIL PROTECTED]> wrote: > > > On Wed, Nov 26, 2008 at 1:55 PM, Mark Volkmann <[EMAIL PROTECTED]> > > wrote: > > >> The documentation for commute says "Sets the in-transaction-value of > >> ref ...". This implies to me that when the transaction ends, the ref > >> will have its previous value. > > >> (def myRef (ref 19)) > >> (dosync (commute myRef inc)) -> 20 > >> @myRef -> 20 > > >> Why isn't the value of the last line 19? > > >> -- > >> R. Mark Volkmann > >> Object Computing, Inc. > > > "in-transaction" just means that the new value is seen if code later in the > > transaction dereferences myRef, while the rest of the program (other > > threads) will not see the new value until the transaction succeeds. Once the > > transaction commits, then the rest of the program will also see the new > > value. If you need something that takes on a new value within a defined > > scope and then pops off to the previous value, check out Vars and binding. > > Is that the main difference between commute and set-ref? > commute sets a value that isn't seen outside the transaction until the > transaction ends. > set-ref sets a value that is immediately seen outside the transaction > before it ends. > Not at all. Nothing done in a transaction is seen outside until the transaction commits. You need to read (doc commute) all the way through, where it subsequently says: At the commit point of the transaction, sets the value of ref to be: (apply fun most-recently-committed-value-of-ref args) ... commute allows for more concurrency than ref-set. i.e. the commute fn gets called twice. The point about the in-transaction value with commute is that it may differ from the post-commit value, as the effect of commute is a function of the value of the ref at commit time. See also: http://clojure.org/refs 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: trampoline for mutual recursion
On Nov 26, 10:28 am, dreish <[EMAIL PROTECTED]> wrote: > Now that you've gone this far, why not do this? > > - class clojure.lang.TailCall contains an AFn > - Compiler checks for a tail call position and instead of calling it, > returns new TailCall(AFn) > - In invoke, while returnvalue instanceof TailCall, returnvalue = > returnvalue.fn.invoke(returnvalue) > > I confess I don't yet have much familiarity with the compiler; I'm > just reading through it now. Is the above idea workable? > > Upside: you could have real TCO tonight, with J2SE 5. > > Downside: as soon as they finally get around to putting TCO in the > JVM, it becomes useless cruft. > > I would think you could take it back out, though. And who knows when > they'll finally do it? And wouldn't it be better to put TCO workaround > cruft in the compiler, rather than in the language definition, around > which people are already (foolishly, perhaps) starting to build > serious programs? > There's a very simple reason - such built-in trampolines are incompatible with interoperability. Anyone can build a trampoline system into their lang to get tail calls and make sure it is used consistently within lang - but what do those TailCall return values mean to a Java caller? Also, in what you've described every invoke turns into a loop, every tail call allocates etc. I made a conscious decision here, and it was a pragmatic one. People using Clojure are pragmatic, not foolish. The vast majority of tail calls requiring TCO are self-calls handled by recur. I'm all for TCO, but trampolines are simplistic TCO and no substitute for real jumps. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: trampoline for mutual recursion
On Nov 25, 10:42 am, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > On Nov 25, 2008, at 9:05 AM, Rich Hickey wrote: > > > I've added trampoline to ease the conversion/creation of mutually > > recursive algorithms in Clojure. > > Very cool! Thanks for enabling that. > > In looking over the implementation, I found a small problem: the arg > vector precedes the doc string leading to: > Fixed (SVN 1123) - thanks for the report. I've also added support for passing initial args, so the top-level call can be: (trampoline foo 100) 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Adapting a functional pretty-printer to Clojure
On Nov 25, 12:51 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 25, 12:50 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> > wrote: > > > On Nov 25, 12:22 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> > > wrote: > > > > This approach might just be too inefficient -- perhaps it would be > > > best to implement the pretty-printer in an imperative style after all. > > > OTOH it is pretty darn nifty... > > ...or would be if Google Groups didn't wrap so well... I've added trampoline, which could significantly ease the work you are trying to do: http://groups.google.com/group/clojure/msg/3addf875319c5c10 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
trampoline for mutual recursion
I've added trampoline to ease the conversion/creation of mutually recursive algorithms in Clojure. Trampolines are a well known technique for implementing TCO - instead of actually making a call in the tail, a function returns the function to be called, and a controlling loop calls it, thus allowing chained execution without stack growth. In order to do this I've made the following changes (SVN 1122): Added clojure.lang.Fn marker interface, used on all true fns. Breaking change - fn? now tests for Fn, not IFn (this was frequently requested) Added ifn? which will test for anything callable (IFn) Added trampoline, implements trampoline protocol for TCO Here's how it works. Normally, if you have mutual recursion (i.e. which can't be replaced with recur), you can blow the stack: (declare bar) (defn foo [n] (if (pos? n) (bar (dec n)) :done-foo)) (defn bar [n] (if (pos? n) (foo (dec n)) :done-bar)) (foo 100) -> java.lang.StackOverflowError To convert to a trampoline, simply return closures over your tail calls, rather than direct calls. This is as simple as prepending # (declare bar) (defn foo [n] (if (pos? n) #(bar (dec n)) :done-foo)) (defn bar [n] (if (pos? n) #(foo (dec n)) :done-bar)) Then make the top-level call via trampoline: (trampoline #(foo 100)) -> :done-foo 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Distributed concurrent applications in Clojure?
On Nov 24, 6:41 pm, dokondr <[EMAIL PROTECTED]> wrote: > Any ideas how Clojure can be used for distributed concurrent > applications ? > To my mind it should be possible to implement in Clojure mechanism > similar to Erlang light-weight processes running on distributed > 'nodes' that can be addressed by 'ports' to send them 'commands'. > How this can be done with Clojure 'agents'? > An obvious solution would be to create an 'agent proxy' on every node > that will maintain a list of its agents and will forward (send ...) > messages to other nodes, as well as receive messages addressed to its > own agents from remote nodes and then deliver these messages to > correct agents. > Addressing scheme and message protocols should be developed as well. > Other ways to provide for communication between nodes? There's JMS: http://en.wikipedia.org/wiki/Java_Message_Service https://mq.dev.java.net/ http://joram.objectweb.org/ http://activemq.apache.org/ XMPP: http://en.wikipedia.org/wiki/Xmpp http://www.igniterealtime.org/projects/index.jsp JXTA/Shoal: http://en.wikipedia.org/wiki/Jxta https://shoal.dev.java.net/ JINI: http://en.wikipedia.org/wiki/Jini http://incubator.apache.org/projects/river.html DHTs like Pastry: http://freepastry.org/ JGroups: http://www.jgroups.org/javagroupsnew/docs/index.html Terracotta: http://www.terracotta.org Jinterface: http://www.erlang.org/doc/apps/jinterface/ NetKernel: http://www.1060.org/ and more. All useful from Clojure. Given the diversity, sophistication, maturity, interoperability, robustness etc of these options, it's unlikely I'm going to fiddle around with some language-specific solution. That said, I have been thinking about putting a simple wrapper API around queues that would work both locally and over something like JMS. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Isolating I/O and other side-effects?
On Nov 24, 7:22 pm, dokondr <[EMAIL PROTECTED]> wrote: > Providing that Clojure is NOT a pure functional language like Haskell, > yet how can I isolate imperative-style computational structures from > the main body of the functional program? You can't, other than manually. > How can I ensure referential transparency in Clojure? You can't, other than manually. > What I/O primitives Clojure provides? > All of Java's. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Keyword constraints not enforced
On Nov 23, 9:09 am, James Reeves <[EMAIL PROTECTED]> wrote: > On Nov 23, 11:38 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> > wrote: > > > Hi, > > > According tohttp://clojure.org/reader: > > > > Keywords are like symbols, except: > > > > o They can and must begin with a colon, e.g. :fred. > > > o They cannot contain '.' or name classes. > > > Shouldn't this throw an exception? It seems that keywords aren't > > checked for correctness at all right now. > > I'd like to request that keywords continue to allow the '.' character, > as it's useful for certain edge cases (Compojure and clj-html use it > to specify class attributes, for instance). Does the inclusion of a > '.' in a keyword introduce any syntax ambiguity I'm unaware of? > > Disallowing class names in keywords seems a little odd too, especially > with AOT. If you compiled a Clojure file like clojure.contrib.def, > would that mean you'd lose the ability to use the keyword :def? > I think you've both misread "they cannot name classes" to be - "They cannot contain class names". The symbol String can name a class but the keyword :String can't, that's all I meant there. As far as '.', that restriction has been relaxed. I'll try to touch up the docs for the next release. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: seq and vector
On Nov 24, 2:41 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 24, 12:41 am, "Kevin Downey" <[EMAIL PROTECTED]> wrote: > > > I don't think you understand. clojure data structures are IMMUTABLE. > > every call to conj, or anyother function returns a "new" object. To > > optimize there is sharing of structure. > > In the particular case at hand, i.e. calling vec on a seq, there is no > structural sharing involved. On the contrary a new Object array of the > same length as the seq is created. See RT.seqToArray for details. This is going around in circles. If you are going to replace every element in a vector, there can be no sharing with any prior vector, under any method. If you will only replace a few elements, use reduce. If you are going to replace most elements, creating a new vector will be more efficient than sharing. All of these would be true whether or not you had vmap or vfilter. The seq functions don't change any types etc. They are functions of collections/seqs to seqs. Were filter/map etc to return vectors for vectors, then chained operations would have to return fully-realized intermediate results. That's wasteful in comparison to the behavior of the seq-based functions. Try this: (def v (vec (range 100))) (defn vmap [f v] (into [] (map f v))) (time (count (vmap inc (vmap inc v user=> "Elapsed time: 1171.923 msecs" (time (count (into [] (map inc (map inc v) user=> "Elapsed time: 613.164 msecs" Speculating about inefficiency without a concrete counter-proposal is not productive. While there could no doubt be some higher-performance vector constructor/reducers, producing vector-returning versions of the sequence ops is not generally a good idea. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: No complex numbers?
On Nov 23, 10:28 am, Rock <[EMAIL PROTECTED]> wrote: > I think the best bet would be implementing them in Clojure itself. I'm > saying this because otherwise it would really get harder given the > constraints regarding immutability. Furthermore, the implementation > should, I think, be generic, that is, we should be capable of creating > complex numbers, the real and imaginary parts of which can be > integers, rationals, or reals. For instance, it sould be possible to > do this: > > (1/3 + 2/5i) + (1/2 + 1/10i) = (5/6 + 1/2i) > > without any loss of precision due to type conversion (ex. towards > float). > > So, from what I gather, a good choice might be to use structures, and > perhaps multimethods. > > Rich, would it be possible to "overload" the arithmetic operators with > this strategy, so that they'll work with the new complex numbers? > > Opinions? There's likely to be performance pressure on any numeric types. Rich > > On Nov 23, 3:42 pm, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > On Nov 23, 8:56 am, Rock <[EMAIL PROTECTED]> wrote: > > > > On Nov 23, 2:37 pm, André Thieme <[EMAIL PROTECTED]> wrote: > > > > > On 23 Nov., 13:29, Rock <[EMAIL PROTECTED]> wrote: > > > > > > I've just noticed there is no support for complex numbers in Clojure. > > > > > There are a few posts on the issue here, but no rationale. I'm a > > > > > mathematician, and complex numbers pop up all over the place. CL and > > > > > Scheme have always had native support for them. I took it for granted > > > > > they were there until I needed them recently. > > > > > I think the reason is, that Java still does not have them in its > > > > standard lib. It puzzles my why they didn’t come up with > > > > something in the past 13 years. > > > > If you want them you will have to use some lib for that. > > > > Yes, I see, but the JVM hasn't got native support for rational numbers > > > either, and yet we do have them in Clojure thanks to the Ratio class > > > Rich created. I can't see why something analogous can't be done for > > > complex numbers as well. We even have unbound integers! And you don't > > > have them in Java natively. Maybe, for the time being, some Complex > > > class like the ones found in Apache.Commons or in JScience could be > > > incorporated into Clojure, so that we have a common basis to work on, > > > and there would be compatibility among different people's code > > > (somthing important I believe). > > > I have nothing against complex numbers, and interested parties should > > contribute to this discussion on how best to incorporate them in > > Clojure. The issues are: > > > What support is required? > > How hard to do with no other libs, a la Ratio? > > If a 3rd-party lib is required, which one, what's the license, how to > > make it optional, how well does it fit with Clojure's immutability > > requirements, etc. > > > I'm amenable to a patch after consensus, but it's not something I have > > time to do myself. > --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: No complex numbers?
On Nov 23, 8:56 am, Rock <[EMAIL PROTECTED]> wrote: > On Nov 23, 2:37 pm, André Thieme <[EMAIL PROTECTED]> wrote: > > > On 23 Nov., 13:29, Rock <[EMAIL PROTECTED]> wrote: > > > > I've just noticed there is no support for complex numbers in Clojure. > > > There are a few posts on the issue here, but no rationale. I'm a > > > mathematician, and complex numbers pop up all over the place. CL and > > > Scheme have always had native support for them. I took it for granted > > > they were there until I needed them recently. > > > I think the reason is, that Java still does not have them in its > > standard lib. It puzzles my why they didn’t come up with > > something in the past 13 years. > > If you want them you will have to use some lib for that. > > Yes, I see, but the JVM hasn't got native support for rational numbers > either, and yet we do have them in Clojure thanks to the Ratio class > Rich created. I can't see why something analogous can't be done for > complex numbers as well. We even have unbound integers! And you don't > have them in Java natively. Maybe, for the time being, some Complex > class like the ones found in Apache.Commons or in JScience could be > incorporated into Clojure, so that we have a common basis to work on, > and there would be compatibility among different people's code > (somthing important I believe). I have nothing against complex numbers, and interested parties should contribute to this discussion on how best to incorporate them in Clojure. The issues are: What support is required? How hard to do with no other libs, a la Ratio? If a 3rd-party lib is required, which one, what's the license, how to make it optional, how well does it fit with Clojure's immutability requirements, etc. I'm amenable to a patch after consensus, but it's not something I have time to do myself. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure HTML Documentation
On Nov 21, 3:17 am, Mark McGranaghan <[EMAIL PROTECTED]> wrote: > I've created some experimental HTML docs for Clojure. You can see them > on S3:http://clj-doc.s3.amazonaws.com/tmp/doc-1116/index.html > > Or, just for kicks, on Amazon's new Cloud Front > CDN:http://d2nbqsesuabw8o.cloudfront.net/tmp/doc-1116/index.html > > You can see the code I used to generate them on > GitHub:http://github.com/mmcgrana/clj-doc > > The generation code is open for public perusal but will require some > tweaking for public use (e.g. I still have paths hard coded). Any help > along these lines would be greatly appreciated. > > Most methods in the clj-doc source have docstrings and in total its > only a couple hundred lines of code: you should be able to find your > way around if you're interested. The best entry point is bin/gen.clj. > Again, any comments or suggests would be appreciated. > > I hope that some of you find this interesting/useful/helpful in your > Clojure endeavors, You can't post source code from Clojure without the copyright and license notice. Please put the proper copyright and license notice on all pages containing Clojure code. You can copy the text and link from http://clojure.org/license. You can put it below the results so it doesn't spoil anything. Thanks, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: seq and vector
On Nov 22, 4:59 pm, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 22, 9:48 pm, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > map and filter don't modify anything. What does it mean to filter a > > vector? > > Yes yes, I know that. Still in English its sometimes easier to be > sloppy and pretend that I modify something even though I get another > vector. > > > In any case, the vector itself is immutable, so calling vec on the > > return value of filter is fine. > > Well yes its fine but what happens is that filter returns a (lazy) seq > and calling vec on that seq will allocate a new array of the same > length and copy every item over. > I still don't understand your expectation here. If the filter does any filtering, it won't return everything in the vector, so the new result will have fewer items. Do you want a vector with fewer items? Then you'll have a new vector. > > As far as map, if you have a function that will only affect a few of > > the items in the vector, you might want to reduce, making 'changes' as > > you go. > > Thanks. That sounds like it would work out nicely. Still in general my > issue seems to be that data strucutres turn into seqs and this can > cause subtle issues as for instance the different behaviour of conj > and a simple rule such as calling vec on the seq seems to be to > costly. Nothing turns anything into seqs - a seq is a view on a collection. If you are 'modifying' every element, then you'll have to have an entirely new vector. Calling a mapping function and pouring the result into a new vector will be more efficient than pretending to modify each element in place with assoc. In general, it can be efficient to perform a series of transformations in the seq space and then realize a vector at the end if you want. The lazy seqs just act as a cursor over the data, and a stream of results, and building a new vector from scratch by appending, as vec or (into [] ...) would do, is more efficient than element 'replacement'. If you don't expect a copy when mapping across an entire vector, and you want to use the immutable data structures, what alternative do you imagine? 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: error in java interop documentation
On Nov 22, 4:20 pm, JMan <[EMAIL PROTECTED]> wrote: > If you look here: > > http://clojure.org/java_interop > > you will see the following example: > > (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2)) > > This produces the following error: > > java.lang.IllegalArgumentException: No matching method found: .put > > I believe the correct code is: > > (doto (new java.util.HashMap) (put "a" 1) (put "b" 2)) > The doc is correct for the latest SVN. I've updated it with info about the prior syntax, for those using the last release. Thanks for the report, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: seq and vector
On Nov 22, 1:07 pm, [EMAIL PROTECTED] wrote: > In one of my data structures I have a vector as a buffer where things > are appended to. In addition the things in that buffer sometimes get > modified using map or filter. Now as map and filter return sequences I > wonder how to get a vector back efficiently. I need a vector in order > for conj to append and not to prepend as it happens with sequences, > otherwise the order would be screwed. What is the most efficient (and > still idiomatic) way to achieve this? map and filter don't modify anything. What does it mean to filter a vector? In any case, the vector itself is immutable, so calling vec on the return value of filter is fine. As far as map, if you have a function that will only affect a few of the items in the vector, you might want to reduce, making 'changes' as you go. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: loss of gen-and-load-class functionality
On Nov 21, 10:15 am, Stuart Sierra <[EMAIL PROTECTED]> wrote: > On Nov 21, 8:46 am, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > I'd appreciate examples of gen-and-load-class and gen-and-save-class > > use not well supported by the AOT gen-class. > > Don't know if this is supported now not, but here's my old > gen_classes.clj: > > (defmacro defclass [name & args] > `(do > (println ~(str "Generating " name)) > (gen-and-save-class *dir* ~name [EMAIL PROTECTED]))) > > (defmacro defmapreduce [name] > `(defclass ~name > :extends org.apache.hadoop.mapred.MapReduceBase > :implements [org.apache.hadoop.mapred.Mapper > org.apache.hadoop.mapred.Reducer])) > > (defmapreduce "org.altlaw.func.ohm1.GroupFiles") > (defmapreduce "org.altlaw.func.ohm1.AssignIds") > (defmapreduce "org.altlaw.func.ohm1.ProcessUpdate") > (defmapreduce "org.altlaw.func.pro.Process") > ... lots more like that ... > And how did you organize the implementation side? 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Use of "/" to call static method in generated classes
On Nov 21, 4:20 pm, Craig McDaniel <[EMAIL PROTECTED]> wrote: > Testing the new (ns ... :genclass ...), I copied Rich's example > fromhttp://paste.lisp.org/display/70665: > > (ns my.hello > (:gen-class >:extends javax.swing.DefaultCellEditor >:constructors {[Integer] [javax.swing.JCheckBox]} >:factory makeone >:methods [[mymax [int] int]] >:init init >:main true >:state myint >:exposes {clickCountToStart {:get get-c-count :set set-c-count}}) > ) > > (defn- -main [foo] > (println "Hello" foo "World!") > (let [x (my.hello. 42)] > (prn (.mymax x 21 > > (defn- -init [myint] > [[(javax.swing.JCheckBox.)] myint]) > > (defn- -mymax [this i] > (max i (.myint this))) > > (defn- -getCellEditorValue [this] > (prn :getCellEditorValue) > nil) > > I can compile and run the example, but it doesn't work with the "/" > syntax for main, even though main is a static method: > > user> (.getProperty System "java.class.path") > "/home/kreg/src/clojure/trunk/clojure.jar:/home/kreg/src/junk" > user> (binding [*compile-path* "/home/kreg/src/junk"] (compile > 'my.hello)) > #{my.hello swank ...} > user> (.main my.hello (into-array ["Bizarro"])) > Hello Bizarro World! > 42 > nil > user> (my.hello/main (into-array ["Bizarro"])) > > java.lang.Exception: No such var: my.hello/main > > Works from command line ok: > > [EMAIL PROTECTED] ~/src/junk > $ java -cp .:/home/kreg/src/clojure/trunk/clojure.jar my.hello > "Bizarro" > Hello Bizarro World! > 42 Right. The x/y syntax is used both for namespaces and static methods, and namespaces win. Here you have both a namespace and a classname called my.hello. So, for calling gen-class'ed static methods, you'll need to use (. classname static-method) for now. I'm not sure this is really an issue, but I'm open to feedback. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Which paper discusses Henry Baker's (sp?) egal?
On Nov 21, 12:36 pm, Brett Hoerner <[EMAIL PROTECTED]> wrote: > I've watched a lot of Clojure videos now, and keep hearing Rich > mention "Henry Baker's egal". Does someone have the actual paper > title where Baker talks about this? I have an ACM subscription (and > assume that's where I'd find it) - but no dice on finding egal (sp?) > and Henry G Baker has a hell of a lot of papers. ;) > http://home.pipeline.com/~hbaker1/ObjectIdentity.html 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Creating a MapEntry
On Nov 21, 11:40 am, samppi <[EMAIL PROTECTED]> wrote: > Yes, thank you—(key) and (val) were what I was interested in, so I'll > use the latter function you gave. What I'm wondering though is, if > MapEntries aren't guaranteed for the future, what is being planned for > (key) and (val) too. Oh, well. :) > There's a difference between supporting key and val and allowing you to create MapEntries directly. key and val will stick around. Rich > On Nov 21, 8:23 am, "J. McConnell" <[EMAIL PROTECTED]> wrote: > > > On Fri, Nov 21, 2008 at 12:03 AM, samppi <[EMAIL PROTECTED]> wrote: > > > > Is it possible to create a MapEntry from scratch? The reason why I'm > > > asking is because I want to mess with sequences of two-sized vectors, > > > and it would be really cool if I could use the key and val functions > > > on them rather than (get % 0) and (get % 1): > > > > (map #(str "Key:" (key %) "Value:" (val %)) [(map-entry :a 3) (map- > > > entry :b 2) (map-entry :a 1) (map-entry :c 0)]) > > > Since Rich discouraged use of the MapEntry class, here are a couple of > > options. > > > First, one thing worth remembering is that vectors are functions of > > their indexes, so you can do this and get rid of the "get"'s: > > > (map #(str "Key: " (% 0) "Value: " (% 1)) [[:a 3] [:b 2] [:a 1] [:c 0]]) > > > Second, if it was the use of (key) and (val) that you were most > > interested in, you could create your own (map-entry) function: > > > user=> (defn map-entry [k v] (first {k v})) > > #'user/map-entry > > user=> (map #(str "Key:" (key %) "Value:" (val %)) > > [(map-entry :a 3) (map-entry :b 2) (map-entry :a 1) (map-entry :c 0)]) > > ("Key::aValue:3" "Key::bValue:2" "Key::aValue:1" "Key::cValue:0") > > > HTH, > > > - J. --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: loss of gen-and-load-class functionality
On Nov 20, 4:42 pm, Stuart Sierra <[EMAIL PROTECTED]> wrote: > On Nov 20, 2:14 pm, Stephen Wrobleski <[EMAIL PROTECTED]> wrote: > > > Furthermore, requiring the use of (ns ..) to create a class makes defining a > > class with a macro somewhat tedious (seems like you'd have to bind *ns*, so > > that (ns ..) could mutate it), if even possible. > > This is probably temporary, but it's something to think about. I have > also used macros to define classes with gen-and-save-class. > -S I'd appreciate examples of gen-and-load-class and gen-and-save-class use not well supported by the AOT gen-class. What I am interested in is the scenarios/use-cases. Thanks, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure Box (was Working combination of .emacs, Aquamacs, swank-clojure, clojure-mode?)
On Nov 20, 7:49 pm, "Shawn Hoover" <[EMAIL PROTECTED]> wrote: > On Thu, Nov 20, 2008 at 8:27 AM, Daniel Renfer <[EMAIL PROTECTED]> wrote: > > perhaps what we need is a clojure-in-a-box solution. We could create a > > package containing a version of clojure, emacs, slime, swank-clojure, > > clojure-mode, and clojure-contrib. This could be as simple as a zip > > file, but even better would be to have a simple installer exe. > > > All a new user would have to would be to download the exe, run it, and > > choose emacs from their start menu. Everything would already be > > configured to work with whatever version these tools were built > > against. You could even install links to clojure > > documentation/resource sites. (clojure.org, the wiki, the irc logs, > > projecture, etc.) > > > I, of course, focus on Windows users because they are the people that > > would most appreciate an all-in-one installer package. You could > > easily create packages for OSX and distros of Linux. > > > This wouldn't help those that already have a running version emacs > > that they're trying to set up, but that's what the other documentation > > sites are for. > > > Does anyone have experience in creating windows installers like this? > > I could look into it if people think it's a good idea, but I'm > > inexperienced in these matters. > > I made a first pass at a Windows installer today. It's similar to the > Lispbox from gigamonkeys.com, targeting Windows users who want to try > Clojure and are willing to learn Emacs at the same time (I wouldn't think > this would include many users, but then again it worked out for me with the > Lispbox). Components include a recent Emacs 23 from the EmacsW32 project and > the latest CVS/Subversion/Git versions of Clojure, Clojure Contrib, > clojure-mode, swank-clojure, and Slime. Once Clojure has a release I would > want to use that and all the compatible tools. > > There is a single MSI that installs the programs and code, creates a > shortcut, associates clj files, launches with minimal emacs configuration > (hides the GNU splash screen!), and automatically starts a REPL. I couldn't > get inferior-lisp to launch today (Java just wasn't liking my > inferior-lisp-program). I think slime is fine for new users as long as they > don't have to configure it. The benefit of tab-completion at the REPL makes > it worth it. And what better welcome to Clojure than "Connected. Hack and be > merry!" > > The result so far packs all of the above features in a 46MB installer. I'm > willing to pursue finishing it (and possibly making it smaller) if it would > be useful to others and if I can find a place to put it up. > I'm sure a lot of people will appreciate this, thanks, although I have to admit to a pang of sadness that tiny Clojure comes in a box 100x its size :( 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Creating a MapEntry
On Nov 21, 12:07 am, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > On Nov 21, 2008, at 12:03 AM, samppi wrote: > > > Is it possible to create a MapEntry from scratch? > > user=> (def a (clojure.lang.MapEntry. 3 4)) > #'user/a > user=> (key a) > 3 > user=> (val a) > 4 > user=> > > You can also make it a little shorter by importing > clojure.lang.MapEntry . > I make no promises about the continued existence of MapEntry. Please don't use it. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure at the JVM Languages Summit
On Sep 30, 1:17 pm, Allen Rohner <[EMAIL PROTECTED]> wrote: > > Thanks. The summit was really fantastic - so many interesting and > > smart people and lots of great presentations and conversations. Left > > me exhausted and a bit MIA here, which I'm afraid will continue > > through my talk Monday at the Boston Lisp Group: > > >http://fare.livejournal.com/134108.html > > > Looking forward to seeing some of you there! > > > Back on the case Tuesday... > > > Rich > > Looks like your Boston Lisp group presentation was well > received:http://xach.livejournal.com/191581.html > > Is there video for either theJVMor Boston talk yet? > JVM Languages Summit talk is up: http://www.infoq.com/presentations/hickey-clojure;jsessionid=2826B81451C4EBFB6F676A26DC937E34 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Suggest allowing java property to specify *compile-path*
On Nov 20, 11:28 am, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > Currently the compiler writes classes to the hierarchy under the value > of *compile-path* whose root binding is "classes". > > As we see in Stuart's build.xml patch, it can convenient to be able to > specify such a path as part of the JVM's environment. > > To support that, I suggest the following: > > - give *compile-path* a root binding of nil. > - make the compilation itself use (effectively) > (or *compile-path* (System/getProperty "clojure.compile.path") > "classes") > > In this way, the default behavior is still present, but can be > overridden either by a Clojure binding or by a JVM property. > I'm in favor. I'd like to get a single story together incorporating Stuart's build.xml, his file compiler: http://groups.google.com/group/clojure/msg/4f0aa3be9a2dc79d and this path suggestion. Right now I'm not clear as to how they fit together, as we had a few overlapping patches/suggestions. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Possible bug? StringIndexOutOfBoundException
On Nov 20, 12:37 pm, Feng <[EMAIL PROTECTED]> wrote: > I start getting StringIndexOutOfBoundException since svn rev 1113 (use > source name in smap). Fixed - rev 1120 - thanks for the report. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: No matching method found: getString
On Nov 20, 10:47 am, "Michael Wood" <[EMAIL PROTECTED]> wrote: > Hi > > > > On Thu, Nov 20, 2008 at 12:10 AM, Chouser <[EMAIL PROTECTED]> wrote: > > > On Wed, Nov 19, 2008 at 4:00 AM, Michael Wood <[EMAIL PROTECTED]> wrote: > > >> Exception in thread "main" java.lang.IllegalArgumentException: No > >> matching method found: getString for class > >> org.dcm4che2.data.BasicDicomObject (dinfo.clj:0) > > > This was discussed on IRC: > > >http://clojure-log.n01se.net/date/2008-11-19.html#15:46a-16:07 > > > So it looks like there may be no good, general, solution. Unless or > > until there is, there's a work-around using reflection manually. > > > Start by getting a reference to the Method you're trying to call: > > > (def bdo-get-string (.getMethod (identity BasicDicomObject) > > "getString" (into-array [Integer/TYPE]))) > > Thanks. That works fine. I'll use that in the mean time. > > > > > The three args to .getMethods are: > > 1. The class (use identity to get the instance of Class instead of > > trying to BasicDicomObject's non-existent getMethod method) > > 2. The name of the method as a string, "getString" > > 3. An array of the argument types for the method you want to call. > > Use Interger/TYPE to specify the primitive 'int' > > > You can then call the method you found above using the .invoke method > > of the Method instance: > > > (.invoke bdo-get-string (BasicDicomObject.) (to-array [0x00100010])) > > > The .invoke method always takes 3 args: > > 1. The Method instance we got earlier > > 2. The instance of the class you want call (in this example I created > > a new instance on the spot) > > 3. And array holding all the args to pass to the Method. > > Thanks for the explanation. > > > Not too pretty, but of course if you find you actually need this you > > can wrap either step in a function to make calling it more pleasant. > > Yes, I've changed print-tag from: > > (defn print-tag [dcm tag] > (.getString dcm tag)) > > to: > > (defn print-tag [dcm tag] > (def bdo-get-string > (.getMethod >(identity BasicDicomObject) "getString" (into-array [Integer/TYPE]))) > (.invoke bdo-get-string dcm (to-array [tag]))) > > -- SVN rev 1119 has my latest attempt to reconcile these bridge methods, trying to make all of these work: http://groups.google.com/group/clojure/browse_frm/thread/a4e1b58061962479/23a1efe8d9f45eb3 http://groups.google.com/group/clojure/browse_frm/thread/ee1c729f1577d530/a21fbfedafb1998b http://groups.google.com/group/clojure/browse_frm/thread/c584c41ebe1caaf2/03ac73e2abd8e425#03ac73e2abd8e425 without breaking anything else. Please let me know the effects, positive or negative, on method resolution. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros and namespaces
On Nov 20, 10:33 am, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote: > Hi, > > On 20 Nov., 16:00, Simon Brooke <[EMAIL PROTECTED]> wrote: > > > And this in turn is because, in core.clj > > > (defmacro cond > > "Takes a set of test/expr pairs. It evaluates each test one at a > > time. If a test returns logical true, cond evaluates and returns > > the value of the corresponding expr and doesn't evaluate any of the > > other tests or exprs. (cond) returns nil." > > [& clauses] > > (when clauses > > (list 'if (first clauses) > > (second clauses) > > (cons 'cond (rest (rest clauses)) > > Yes. This is a bug. cond is not a special form, so the > 'cond in the last line should read `cond basically > qualifying the symbol. All other macros in clojure.core > are defined using syntax-quote (hence you get this > for free) or are correctly quoted, as far as I can tell. > cond is fixed in rev 1118. > However note, that there are special forms like def, do, > fn, let, etc. which will remain there special meaning. > More info on:http://clojure.org/special_forms. > Right. Currently I don't support the redefinitions of special ops. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: ants.clj: question about sleep in dosync
On Nov 19, 5:05 pm, Stephan Mühlstrasser <[EMAIL PROTECTED]> wrote: > Hi, > > first of all hello to everybody as I'm new to this group. > > I'm starting to learn Clojure, and therefore I studied the ants.clj > program. It's more or less clear to me how it works, but I stumbled > across a small detail that made me wonder. > > In the "behave" function for the ant agent, there's the "(. Thread > (sleep ant-sleep-ms))" inside the dosync transaction block. The sleep > time is pretty short, but doesn't sleeping inside a dosync increase > the probability that transactions must be restarted? Would it be > better to put the sleep immediately before the dosync block, or > doesn't it matter? > Yes, it would. Sleeping (blocking, in general) in dosync is very bad practice - it didn't have much effect in this case, but normally would. I've updated ants.clj here on the group. Thanks for the report, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros and syntax-quote
On Nov 20, 7:38 am, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote: > Hi, > > On 20 Nov., 13:30, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > Yes. Please use auto-gensyms (name#): > > > `(let [frame# ~frame] > >(.setTitle frame# ~title) > >(.setVisible frame#) > >frame#) > > With this specific example, my intention was to show, how > using a macro where a function would do actually causes > a lot of trouble, like multiple evaluation, variable capture, > etc. > > > ~' should be used for intentional capture only, i.e. rarely. > > I think this was clearly stated in the wiki: only in rare cases, > well-defined situations and well documented. > > > That section of the Wiki should be re-worked, IMO. > > Yes. It is rather chaotic and not very clear over long > passages. I will tackle this as soon as I find out, who > has to approve my changes to the wiki > I didn't see any issues with wiki editing, ar eyou still having a problem? As far as the section goes, the problem is people will grab code without reading the text carefully. Given its tutorial nature, I think it's best for the Wiki to show examples of the right way to do things rather than the wrong way. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Bug + Patch: compile fails for namespaces with dashes in their names.
On Nov 20, 12:18 am, Chouser <[EMAIL PROTECTED]> wrote: > Since SVN rev 1110: > > user=> (compile 'clojure.contrib.str-utils) > java.lang.Exception: Namespace name must match file, had: > clojure.contrib.str-utils and clojure/contrib/str_utils.clj > (NO_SOURCE_FILE:0) > > I think the only problem is that the test to generate this exception > asserts that classnames equal namespace names. I think the actual > convention is meant to be that namespaces can have dashes, but the > generated classes will have underscores in their place. The attached > patch fixes the assertion. > > With this fix I can compile, and then without the .clj sources in the > classpath anymore, load the generated .class files. > Patch applied -thanks! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros and syntax-quote
On Nov 20, 6:39 am, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote: > Hi, > > On 20 Nov., 11:29, Rock <[EMAIL PROTECTED]> wrote: > > > I was what the difference might be with respect to this: > > > `(let [frame ~frame] > >(.setTitle frame ~title) > >(.setVisible frame) > >frame) > > This won't work, since - assuming you are in namespace > user - the backquote will expand to... > > (let [user/frame (new JFrame)] > (.setTitle user/frame "Sometitle") > (.setVisible user/frame) > user/frame) > > ... and hence the let will complain, since you are not > allowed to use fully qualified symbols in a let form. > > Hence you need ~'frame (capturing frame => bad) or > frame#/gensym (not capturing frame => good). > Yes. Please use auto-gensyms (name#): `(let [frame# ~frame] (.setTitle frame# ~title) (.setVisible frame#) frame#) ~' should be used for intentional capture only, i.e. rarely. That section of the Wiki should be re-worked, IMO. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Reclaiming scan and touch
On Nov 19, 6:51 pm, mifrai <[EMAIL PROTECTED]> wrote: > I know it's minor and nit-picky but so long as we're rolling out so > many breaking changes is it possible to reclaim scan and touch instead > of leaving dead functions that need an :exclude? Yes, done. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Bug + Patch: LazilyPersistentVector mutated by sort
On Nov 19, 8:23 pm, Chouser <[EMAIL PROTECTED]> wrote: > _Jordan_ in IRC discovered a bug that can be distilled to: > > user=> (let [x [3 2 1]] (sort x) x) > [1 2 3] > > The sort function mutates the vector. This can happen because the > toArray() method of LazilyPersistenVector returns its own internal > array, instead of creating a new array like most other collections do. > sort then passes this along to Java's Arrays.sort() which mutates the > array. > > Attached is a patch that makes LPV toArray() return a clone of the > array. This is of course somewhat less efficient, but it seems like > any less drastic solution leaves open the possibility of mutating the > array inside the vector. > Patch applied (rev 1114) - thanks! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: multimethods + derive question
On Nov 19, 2:35 pm, Stuart Halloway <[EMAIL PROTECTED]> wrote: > Rich, > > Very helpful, as always. Alias + the ability to pull in symbols names > via refer was exactly what I was looking for. > > One scenario still worries me: > > 1. I create a multimethod that dispatches around a tag whose value is > an unresolved keyword (:Foo instead of ::Foo). Everything works fine. > > 2. If at some later point I want the dispatch to depend on (derive), > it is breaking change for clients to switch to from :Foo to ::Foo. > > I am tempted to conclude that you should never use unqualified > keywords as type tags, because you are exposing an implementation > detail. That is, the implementation promises not to rely on derive. > Agreed. Qualified keywords or symbols as :tag values makes sense, independent of derive, as many people will be using :tag, you can't assert that you alone own the tag :Foo. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Is this boolean behavior intentional?
On Nov 19, 1:12 pm, Raffael Cavallaro <[EMAIL PROTECTED]> wrote: > user> (def test-array (make-array (. Boolean TYPE) 100)) > #'user/test-array > user> (aget test-array 0) > false > user> (= (aget test-array 0) false) > true > user> (if (aget test-array 0) 'true-value 'false-value) > true-value > > Same issue with when, and when-not as well. IOW, (aget some-boolean- > array some-index) is treated as returning true even if the actual > return value of aget is false. Fixed (svn 1112) - thanks for the report. The problem is that the Java reflection APIs return new Boolean values other than the canonic Boolean.TRUE and Boolean.FALSE when boxing booleans, but for efficiency only canonic false is logical false in Clojure. Apparently, Array.get also falls into this category, so I had to fix up all Boolean returns from Array.get 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: (Newbie) simple tack
On Nov 19, 11:18 am, capricorn20 <[EMAIL PROTECTED]> wrote: > I want create seq which keep indexes of non-zero elements of > collection. > Code: > > (defn nonzero-inx [s] > (filter (fn [x] (not (nil? x))) (map (fn [a b] (if (not (== a 0)) > b)) s (range (count s) > > look complicated than solution in most imperative languages. > May be possible simplest way in Clojure? You are on the right track, this a bit more succinct: (defn nonzero-idxs [s] (remove nil? (map #(when-not (zero? %1) %2) s (iterate inc 0 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Use of unprintable/readable values
On Nov 19, 10:07 am, Stuart Sierra <[EMAIL PROTECTED]> wrote: > Hmm, it seems strange to me that this works at all: > > user=> (eval '(list + 1 2 3)) > (# 1 2 3) > user=> (eval *1) > 6 > > Does that mean that functions evaluate to themselves? > Sure, they always have (think map). The trick is, what happens when you embed them in code, as the above does, or some macros would like to do. In the early work towards AOT I wasn't able to serialize fns, such serialization being necessary for putting constants in to bytecode. I've relaxed that restriction for fns that are not closures - they are now print-dup'able. Rich > > On Nov 19, 9:01 am, "J. McConnell" <[EMAIL PROTECTED]> wrote: > > > In writing up tests for clojure.contrib.test-clojure that cover the > > Evaluation page of clojure.org, I came across the fact that the > > following threw a CompilerException due to a > > "java.lang.ClassNotFoundException: clojure._PLUS___224": > > > (eval (eval '(list + 1 2 3))) > > > After the AOT changes, this no longer throws an exception and instead > > produces what I had expected previously, the value 6. Is this > > something that will be supported now, i.e. should I be testing to > > ensure that the above form produces 6? My suspicion is yes, but I > > wanted to check anyhow. > > > Thanks, > > > - J. --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Modified doto
On Oct 23, 9:53 am, Rich Hickey <[EMAIL PROTECTED]> wrote: > On Oct 21, 10:30 am, mb <[EMAIL PROTECTED]> wrote: > > > Hi, > > > On 21 Okt., 14:41, mb <[EMAIL PROTECTED]> wrote:> (defmacro doto-> > > > The name is actually also up to discussion. doto is already > > in use and this change is incompatible to "legacy" code. > > I couldn't come up with a good alternative... > > I'd rather enhance doto to do this and not add another variant. The > break would be that current (doto x (foo 42)) would have to become > (doto x (.foo 42)). > Rev. makes this (breaking) change, hopefully the last breakage pre 1.0. I've updated the ants.clj file here, and would appreciate it if people could touch up the wiki and any other public demos. Thanks, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Use of unprintable/readable values
On Nov 19, 9:01 am, "J. McConnell" <[EMAIL PROTECTED]> wrote: > In writing up tests for clojure.contrib.test-clojure that cover the > Evaluation page of clojure.org, I came across the fact that the > following threw a CompilerException due to a > "java.lang.ClassNotFoundException: clojure._PLUS___224": > > (eval (eval '(list + 1 2 3))) > > After the AOT changes, this no longer throws an exception and instead > produces what I had expected previously, the value 6. Is this > something that will be supported now, i.e. should I be testing to > ensure that the above form produces 6? My suspicion is yes, but I > wanted to check anyhow. > I've added support for non-closure fns as code, so yes. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: multimethods + derive question
On Nov 19, 7:45 am, Stuart Halloway <[EMAIL PROTECTED]> wrote: > Hi all, > > I am working on the multimethod chapter this week. This has required a > lot of exploration, as the multimethod feature set goes well beyond > what most people are using yet. I have hit one rough spot: derive. I > have working code (below), but I don't like the way I have to call it > with fully qualified keywords, e.g. > > (service-charge {:tag :examples.multimethods.service-charge-3/ > checking :balance 100}) > -> 25 > (service-charge {:tag :examples.multimethods.service-charge-3/ > checking :balance 1}) > -> 0 > > I feel that I have made a wrong turn somewhere. Here are my assumptions: > > 1. I (the implementer) have to write my dispatch functions with > qualified names, if I want to use derive. Derive works only with qualified names for an important reason - so it can be extensible without clashes. But it's important to logically segregate hierarchical things from non, as namespace control is orthogonal. > > 2. John Doe (the caller) must use fully qualified names *everywhere*. > Since he does not live in my namespace he cannot use the ::. > Qualified names, yes, fully, no. In particular, :: supports aliases, as shown below, or ` can be used with symbols. > It's the latter that bothers me. It seems so ugly that I would never > use hierarchical names for anything, which makes me think I am missing > something. To make matters worse: > > 3. Once I use :: once on any keyword in my implementation, it is a > quick slope to using it other places too, just so I don't have to > remember which ones I chose to qualify and which ones I didn't. In the > code below, :premium and :basic become ::premium and ::basic just for > consistency with ::checking and ::savings. Keywords are going to be used in different contexts for different reasons, saying they should all use :: for consistency is sort of punting on making decisions about their use. > > --- > (ns examples.multimethods.service-charge-3) > > (defmulti account-level :tag) > (println ::checking) > (defmethod account-level ::checking [acct] >(if (>= (:balance acct) 5000) ::premium ::basic)) > (defmethod account-level ::savings [acct] >(if (>= (:balance acct) 1000) ::premium ::basic)) > > (derive ::savings ::account) > (derive ::checking ::account) > > (defmulti service-charge (fn [acct] [(account-level acct) (:tag acct)])) > (defmethod service-charge [::basic ::checking] [_] 25) > (defmethod service-charge [::basic ::savings][_] 10) > (defmethod service-charge [::premium ::account] [_] 0) Here are two ways to do it that I would consider idiomatic, or at least as intended. In both implementations, account tags are hierarchical, and account levels are considered an enumeration, account 'types' are capitalized. Consumer code uses normal namespace management to deal with the names. In the keyword version, note how you can use ::alias/name and get a resolved keyword. In the symbol version note the consistent use of syntax-quote, and the ability to pull in names using use/refer. Other than the default resolution (symbols are resolved and keywords aren't), they pretty much have parity here. In particular, note symbols are functions of maps like keywords, a feature not used below but important for their use as keys in maps. ;; using keywords ;; (ns examples.multimethods.service-charge-3) (defmulti account-level :tag) (defmethod account-level ::Checking [acct] (if (>= (:balance acct) 5000) :premium :basic)) (defmethod account-level ::Savings [acct] (if (>= (:balance acct) 1000) :premium :basic)) (derive ::Savings ::Account) (derive ::Checking ::Account) (defmulti service-charge (fn [acct] [(account-level acct) (:tag acct)])) (defmethod service-charge [:basic ::Checking] [_] 25) (defmethod service-charge [:basic ::Savings][_] 10) (defmethod service-charge [:premium ::Account] [_] 0) (in-ns 'user) (alias 'sc 'examples.multimethods.service-charge-3) (sc/service-charge {:tag ::sc/Checking :balance 100}) (sc/service-charge {:tag ::sc/Checking :balance 1}) ;; using symbols ;; (ns examples.multimethods.service-charge-4) (defmulti account-level :tag) (defmethod account-level `Checking [acct] (if (>= (:balance acct) 5000) :premium :basic)) (defmethod account-level `Savings [acct] (if (>= (:balance acct) 1000) :premium :basic)) (declare Account Savings Checking) (derive `Savings `Account) (derive `Checking `Account) (defmulti service-charge (fn [acct] [(account-level acct) (:tag acct)])) (defmethod service-charge [:basic `Checking] [_] 25) (defmethod service-charge [:basic `Savings][_] 10) (defmethod service-charge [:premium `Account] [_] 0) (in-ns 'user) (refer 'examples.multimethods.service-charge-4) (service-charge {:tag `Checking :balance 100}) (service-charge {:tag `Checking :balance 1})
Re: Can functions be decompiled?
On Nov 18, 2:48 pm, Konrad Hinsen <[EMAIL PROTECTED]> wrote: > On 18.11.2008, at 19:32, Shawn Hoover wrote: > > > For functions defined in libs that you load into Clojure, you can > > find out the file and line from the metadata. For functions you > > define in the REPL, this trick won't help. Say you have (defn myfn > > [] :test) in the user namespace. ^#'user/myfn gets the metadata > > from the var that holds the function. To get the file try (:file > > ^#'user/myfn). And for the line number, (:line ^#'user/myfn). > > Thanks, that sounds useful already. Normally everything I have is > defined in the REPL (through clojure-mode in Emacs), but I will > happily load a bunch of functions from a file if that helps me > debugging! You'll also get line numbers and local variable names in the classfiles, for use by a Java debugger. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Working combination of .emacs, Aquamacs, swank-clojure, clojure-mode?
On Tue, Nov 18, 2008 at 9:42 AM, Raffael Cavallaro < [EMAIL PROTECTED]> wrote: > > > > On Nov 18, 1:46 am, "Cosmin Stejerean" <[EMAIL PROTECTED]> wrote: > > > What kind of bugs are acceptable for the > > purpose of a known good combination? Is slime starting up sufficient? > > It's a whole lot better than slime *not* starting up. Again, context: > "Getting Started." > > BTW, it's this sort of thinking, that one wants to constantly update > because some bug or other may have been fixed in the latest svn/cvs > commit that leads to projects never making releases, which is a Bad > Thing(TM). > > > > > Assuming some automated tests can be created to define the > characteristics > > of a known good combination I'll volunteer to create a continuous > > integration server to report the status of trying to use the latest > version > > of each project so interested users can quickly see if the most recent > > combination works, and if not look, at the history to find the most > recent > > one that does. Is providing automated tests something you'd like to help > > with? > > > Again, *not* looking for the latest and greatest in the context of > "Getting Started." Merely looking for "known to work even though it's > 6 months old." > > As the old chestnut goes, one never gets a second chance to make a > first impression. The first impression one gets now does *not* reflect > the quality of clojure at this point. The first impression one gets > now is "OK, broken, check back later." Clojure is more mature than > this, and the initial setup brokenness is easily solved by putting up > an archive of working versions of the various components even if they > grow to be many months old before they're refreshed. This would not > require an automated testing server, just a single tar command line > once or twice a year. > > regards, > > The complexity here lies on the Emacs/Swank/Slime side, and the coordination it requires with a matching Clojure. You can always grab the latest Clojure from svn, run ant, and have a working Repl with java -jar clojure.jar in under 30 seconds. Might I suggest that for "Getting Started", Swank/Slime is a bit much? For many people, this will be their first use of Emacs. Perhaps some simple instructions for getting clojure-mode going would be better? Its functionality/complexity ratio seems much higher. Also, I'd like not to imply that emacs+swank/slime is the only way, or a prerequisite for using Clojure. There's a mode for vim, and there's also enclojure, something for TextMate, etc. Let's not make getting started any harder than it need be. People can move up to swank/slime when they are ready. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agent errors reporting
On Tue, Nov 18, 2008 at 3:14 AM, Toralf Wittner <[EMAIL PROTECTED]>wrote: > On Sun, 2008-11-16 at 01:35 +0100, [EMAIL PROTECTED] wrote: > > Currently agent errors are only reported when the agent is derefenced > > or further actions are dispatched to the agent. It would be great if > > one can get immediate notification of agent errors maybe through a > > callback. > > I also have a need for early error reporting in case of agent errors, so > I changed Agent.java to optionally take an addition error handler > function that will be used as a callback as soon as exceptions occur. > For example: > > user=> (def agt (agent 0)) > #'user/agt > user=> (defn trouble [_] (throw (new Exception "Trouble"))) > #'user/trouble > user=> (send agt trouble) > # > user=> @agt > java.lang.Exception: Agent has errors (NO_SOURCE_FILE:0) > user=> (clear-agent-errors agt) > nil > user=> @agt > 0 > user=> (set-errorhandler agt (fn [a e] (.printStackTrace e) > (clear-agent-errors a))) > nil > user=> (send agt trouble) > java.lang.Exception: Trouble >at user$trouble__2.invoke(Unknown Source) >at clojure.lang.AFn.applyToHelper(AFn.java:193) >at clojure.lang.AFn.applyTo(AFn.java:184) >at clojure.lang.Agent$Action.doRun(Agent.java:72) >at clojure.lang.Agent$Action.run(Agent.java:117) >at > java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) >at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) >at java.lang.Thread.run(Thread.java:619) > # > user=> @agt > 0 > user=> (def agt (agent 0 :error-fn (fn [a e] (.printStackTrace e) > (clear-agent-errors a > #'user/agt > #'user/agt > user=> (send agt trouble) > java.lang.Exception: Trouble >at user$trouble__2.invoke(Unknown Source) >at clojure.lang.AFn.applyToHelper(AFn.java:193) >at clojure.lang.AFn.applyTo(AFn.java:184) >at clojure.lang.Agent$Action.doRun(Agent.java:72) >at clojure.lang.Agent$Action.run(Agent.java:117) >at > java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) >at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) >at java.lang.Thread.run(Thread.java:619) > # > user=> @agt > 0 > > > The agent function is now keyword based and accepts :error-fn > and/or :validate-fn. Alternatively error handlers can be set on an agent > later. Since the change of the agent function is breaking existing code > it is probably not what you (or Rich) want to have. Overloading it to > take 3 parameters might be the better way. > > Anyway I second your request and would love to see some error reporting > functionality in agents, as this really helped me a couple of times. > > Cheers, > Toralf > > I'm definitely interested in more centralized agent error handling, but I don't want to jump into the per-agent error handler thing just yet. At some point I'm probably going to provide abstractions over some of the java.util.concurrent workflow stuff like queues and latches (since so few people know they are there or how to use them). Then there might be a default queue for agent errors, with the possibility of connecting an agent to a specific error queue. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch: standalone compiler (almost)
On Nov 18, 2008, at 12:53 AM, Stephen C. Gilardi wrote: > > On Nov 17, 2008, at 11:42 PM, Stephen C. Gilardi wrote: > >> It seems there's something not quite right, though. I did a fresh >> checkout of 1108 and built with "ant" and ran with "java -jar >> clojure.jar" and got an exception: > > Making pushNS public on line 4461 of src/jvm/clojure/lang/ > Compiler.java fixes the exception. > > Fixed - thanks. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch: standalone compiler (almost)
On Nov 17, 8:50 am, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > On Nov 16, 2008, at 10:34 PM, Rich Hickey wrote: > > > Since it only requires main, might I suggest you write this in > > Clojure instead? > > I gave that a try. > > Here's a simple version of a driver for the compiler, stored in src/ > clj/clojure/compile.clj: > > (ns clojure.compile) > > (defn main > "Compiles libs into class files stored at compile-path. > All args are strings" > [compile-path & libs] > (printf "Compiling %d libs to %s\n" (count libs) compile-path) > (flush) > (binding [*compile-path* compile-path] > (doseq [lib libs] > (compile (symbol lib) > > It works when run from within the Clojure repl: > > % ls build/classes/clojure/hello* > ls: build/classes/clojure/*hello*: No such file or directory > % java -cp clojure.jar:src/clj/ clojure.lang.Repl > Clojure > user=> (require 'clojure.compile) > nil > user=> (clojure.compile/main "build/classes" "clojure.hello") > Compiling 1 libs to build/classes > nil > user=> > % ls build/classes/clojure/hello* > build/classes/clojure/hello$main__8.class build/classes/clojure/ > hello.class > > but when run as a standalone main, it gives an exception that appears > to be related to static initializers: > > % java -cp clojure.jar:src/clj/ clojure.compile build/classes > clojure.hello > Compiling 1 libs to build/classes > Exception in thread "main" java.lang.IllegalStateException: Var null/ > null is unbound. (hello.clj:3) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4067) > at clojure.lang.Compiler.analyze(Compiler.java:3896) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4050) > at clojure.lang.Compiler.analyze(Compiler.java:3896) > at clojure.lang.Compiler.access$100(Compiler.java:38) > at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:365) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4060) > at clojure.lang.Compiler.analyze(Compiler.java:3896) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4050) > at clojure.lang.Compiler.analyze(Compiler.java:3896) > at clojure.lang.Compiler.analyze(Compiler.java:3869) > at clojure.lang.Compiler.compile(Compiler.java:4498) > at clojure.lang.RT.compile(RT.java:408) > at clojure.lang.RT.load(RT.java:450) > at clojure.lang.RT.load(RT.java:422) > at clojure.core$load__4423$fn__4425.invoke(core.clj:3343) > at clojure.core$load__4423.doInvoke(core.clj:3342) > at clojure.lang.RestFn.invoke(RestFn.java:413) > at clojure.core$load_one__4386.invoke(core.clj:3189) > at clojure.core$compile__4429.invoke(core.clj:3347) > at clojure.compile$main__5162.doInvoke(compile.clj:23) > at clojure.lang.RestFn.invoke(RestFn.java:428) > at clojure.lang.Var.invoke(Var.java:323) > at clojure.lang.AFn.applyToHelper(AFn.java:195) > at clojure.lang.Var.applyTo(Var.java:436) > at clojure.compile.main(Unknown Source) > Caused by: java.lang.IllegalStateException: Var null/null is unbound. > at clojure.lang.Var.get(Var.java:129) > at clojure.lang.Compiler$FnExpr.parse(Compiler.java:2947) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4058) > ... 25 more > % > > For reference, here is the test compilee: src/clj/clojure/hello.clj: > > (ns clojure.hello) > > (defn main > [greetee] > (printf "Hello, %s wow\n" greetee) > (flush)) > > I'd appreciate help in getting a standalone invocation of something > like compile.clj above (i.e., using it's own main without Repl or > Script) to work. > > In working through this, I also found that a compiler driver written > in Java may be preferable for use via build.xml because of a bootstrap > problem. Until we compile (something like) "compile.clj", we can't > call it as a standalone main. (One could add a step that builds the > compiler driver via a clojure.lang.Script invocation.) > Fixed (SVN 1108) - thanks for the report. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Default map parameters
On Nov 17, 5:16 pm, "Mark Volkmann" <[EMAIL PROTECTED]> wrote: > On Mon, Nov 17, 2008 at 3:48 PM, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > On Nov 17, 4:22 pm, samppi <[EMAIL PROTECTED]> wrote: > >> Inhttp://groups.google.com/group/clojure/browse_thread/thread/62140a28b..., > >> the following example was given: > > >> (defn test1 [{x :x, y :y, :or {:y 3}}] > >> [x y]) > >> (test1 {:x 2}) => [2 3] > > >> But this doesn't work on the latest Clojure from Subversion I just > >> got: > > >> (test1 {:x 2}) => [2 nil] > > >> Was this a feature that was removed? Or should it work? > > > That's a typo in the original, should be: > > > (defn test1 [{x :x, y :y, :or {y 3}}] > > [x y]) > > Can someone explain what this does? Yes! > It looks to me like the function named test1 returns a vector > containing the values of x and y. Right. > Are you suppose to pass a map to the function? Yes. > Does it take the value for the key :x and put it in the parameter x, > and similarly for y? Yes. > Is the value 3 used for y if the key :y isn't present in the map? > Right again. > I'm still at the point where reading some Clojure code is like trying > understand a complicated regular expression. > You seem to be doing fine! This is an example of Clojure's destructuring binding. The basic idea is that you are in a context in which you'd normally be using a symbol, intended to be bound to something, e.g. a fn arglist or let binding. But instead of using a symbol, you instead use a data structure. In it, there are symbols. Those symbols will be bound to corresponding parts of a composite data structure. There is general destructuring for sequences and associative things, like maps. Destructuring is described here: http://clojure.org/special_forms#let While it may look like a regular expression to you right now, it actually still is code-as-data. The vector and map binding forms are actual vectors and maps, there are just some rules for interpretation of things like :or, :keys, :as etc., all described above. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Default map parameters
On Nov 17, 4:22 pm, samppi <[EMAIL PROTECTED]> wrote: > Inhttp://groups.google.com/group/clojure/browse_thread/thread/62140a28b..., > the following example was given: > > (defn test1 [{x :x, y :y, :or {:y 3}}] > [x y]) > (test1 {:x 2}) => [2 3] > > But this doesn't work on the latest Clojure from Subversion I just > got: > > (test1 {:x 2}) => [2 nil] > > Was this a feature that was removed? Or should it work? That's a typo in the original, should be: (defn test1 [{x :x, y :y, :or {y 3}}] [x y]) 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: add-classpath erroring out, post r1100...
On Nov 17, 1:00 pm, Scott Fleckenstein <[EMAIL PROTECTED]> wrote: > Hi All, > > I've run into a bug since upgrading past revision 1100, specifically > around adding to the classpath at runtime using add-classpath. I've > attached a test case > here:http://s3.amazonaws.com/nullstyle/precompile-bug.tar.gz > > That file has three versions of clojure (r1100, r1101, r1106) and > web.clj, a sample app that loads jetty and starts a simple web > server. You can use run.sh in that same tar to run each revision, one > after the other, to illustrate the breakage. > > Basically, after adding a jar to the classpath, when importing a class > file from that jar I get a ClassNotFoundException thrown. I don't > have enough java experience to know what would cause this problem. > Things work as expected on revision 1100. > > Does anyone know what would cause this? I'd be happy to put in the > time to help debug and fix this, but I'm at a loss for where next to > go. > Such use of add-classpath is discouraged. The only reason for add- classpath is to let you pull in something if you've started up the repl without it. It shouldn't be a permanent part of any application design. In your case, you can get the local Jetty jars in the mix by supplying an extension dirs directive (-Djava.ext.dirs=) on the command line: java -Djava.ext.dirs=. -cp clojure-r1106.jar clojure.lang.Script web.clj All three revisions work with this change, and you can remove the add- classpath calls. The change that caused this is that now .class files for Clojure fn classes can be found and loaded by a classloader higher up in the chain, one which can't see the effects of add-classpath. I'm going to deprecate add-classpath because people consistently use it to avoid the standard classpath-setting mechanisms, at least until I can figure out a way to coordinate it with the standard classloader. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch: standalone compiler (almost)
On Nov 17, 8:50 am, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > On Nov 16, 2008, at 10:34 PM, Rich Hickey wrote: > > > Since it only requires main, might I suggest you write this in > > Clojure instead? > > I gave that a try. > > Here's a simple version of a driver for the compiler, stored in src/ > clj/clojure/compile.clj: > > (ns clojure.compile) > > (defn main > "Compiles libs into class files stored at compile-path. > All args are strings" > [compile-path & libs] > (printf "Compiling %d libs to %s\n" (count libs) compile-path) > (flush) > (binding [*compile-path* compile-path] > (doseq [lib libs] > (compile (symbol lib) > > It works when run from within the Clojure repl: > > % ls build/classes/clojure/hello* > ls: build/classes/clojure/*hello*: No such file or directory > % java -cp clojure.jar:src/clj/ clojure.lang.Repl > Clojure > user=> (require 'clojure.compile) > nil > user=> (clojure.compile/main "build/classes" "clojure.hello") > Compiling 1 libs to build/classes > nil > user=> > % ls build/classes/clojure/hello* > build/classes/clojure/hello$main__8.class build/classes/clojure/ > hello.class > > but when run as a standalone main, it gives an exception that appears > to be related to static initializers: > > % java -cp clojure.jar:src/clj/ clojure.compile build/classes > clojure.hello > Compiling 1 libs to build/classes > Exception in thread "main" java.lang.IllegalStateException: Var null/ > null is unbound. (hello.clj:3) > For reference, here is the test compilee: src/clj/clojure/hello.clj: > > (ns clojure.hello) > > (defn main > [greetee] > (printf "Hello, %s wow\n" greetee) > (flush)) > > I'd appreciate help in getting a standalone invocation of something > like compile.clj above (i.e., using it's own main without Repl or > Script) to work. > I think you've got some of the interim work I've done integrating gen- class. main now needs to be called -main, as all methods will be defined with leading -. > In working through this, I also found that a compiler driver written > in Java may be preferable for use via build.xml because of a bootstrap > problem. Until we compile (something like) "compile.clj", we can't > call it as a standalone main. (One could add a step that builds the > compiler driver via a clojure.lang.Script invocation.) > Good point. This may just be an exercise then. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure for LISP programmers....
You contend that Lisp is regular, without defining regular. I contend that as soon as you have ' it is not regular, and no one writes Lisp without '. You keep using the term 'syntax' for Clojure's non-list data structures. If list literals are not syntax, neither are vector or map literals. You consistently presume the differences in Clojure are gratuitous. That presumption isn't going to help you, as it is wrong. I understand, you have a world with which you are familiar, and enter a new world where things are different, and it's frustrating. But you are complaining about how it ought to be more similar to what you know, without spending any time to understand why it is the way it is. Part of that may come from expectations driven by the claim that Clojure is a Lisp. It is a Lisp, but in a much more expansive notion of Lisp than a mere syntactic one. I've presented Clojure to many of the people who wrote CL and Scheme, and no one can deny it is a Lisp. But it is not Common Lisp, nor Scheme, nor a derivative thereof. I am not 'changing things'. I've written a new Lisp. In some ways, you sound a lot like the people drifting into comp.lang.lisp over the years, who within the first few hours/days with CL know what's wrong with it and how it should be changed in order to be better. Those people normally get responses of this sort: once you understand it, these differences will seem less gratuitous and you'll see how it all fits together. Same here, with fewer flames :) I contend that Clojure is as regular as Common Lisp, i.e. both are mostly regular, except for reader macros. That the point of Lisp is not 'everything is a list', but that 'code is data', which is true for Clojure. Clojure is not like Dylan, or Arc. Nothing about the differences is gratuitous. There is a holistic nature to Clojure that it may take a while to see. Not every decision is ideal, but all were considered. I think you'll have a much better experience if you: Keep an open mind. Ask questions rather than presume. If you must presume, presume the better rather than the worse. Leverage the documentation and support channels - there are 82 people logged in to the #clojure IRC right now. Someone there could get you unstuck in an instant rather than an hour. Accept up front that it is going to be different. Yes, cond has fewer parens, and do and assoc mean something different etc. These things, while initially frustrating, are superficial. Many Lispers have become productive with Clojure. Yes, there could be more of a roadmap for Lispers, but there's a Wiki and I encourage users to help each other out by contributing any advice or tips they feel will be helpful. I think, if you stick with it, you'll find that Clojure is indeed a Lisp, at a deep level, and its core non-list data structures are considerably lispier than their counterparts in other Lisps. That Clojure programs are shorter and clearer than corresponding CL programs. That the sequence abstraction is a powerful expansion of the list concept. That adding first-class maps/sets/vectors to lists is empowering. That functional programming and concurrency are well supported. And much more. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: recur in catch and finally?
On Nov 17, 2:06 am, mb <[EMAIL PROTECTED]> wrote: > Hi, > > On 17 Nov., 02:09, Chouser <[EMAIL PROTECTED]> wrote: > > > You could of course work around this by putting your loop in some > > other function and calling it from inside catch. > > In this specific case I used: > (last (take-while #(not (nil? %)) (iterate #(.getCause %) e))) > > However, a separate function would also work. That is not > the point. One can work around it. But I try to follow the > principle of least surprise as much as possible. So when > valid looking code doesn't work for an obscure reason, this > certainly is a surprise. > > I have no problem putting the loop into a dedicated function. > Or find some equivalent way to express it. However then it > should be documented somewhere, that this is actually > necessary. ("for technical reasons loop/recur cannot be > used in/at/for") Yes, it's an arbitrary restriction (due to complexity) which I should document. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Strange behaviour
On Nov 17, 7:56 am, Konrad Hinsen <[EMAIL PROTECTED]> wrote: > On Nov 17, 2008, at 13:33, mb wrote: > > > vals returns a clojure.lang.APersistentMap$ValSeq, which > > is not a list. Hence list? returns false and you get the true > > branch, ie. the thing itself. > > A. It looks like a list, but it isn't a list. > > > I know. It doesn't help much, but it shows, that you have to take > > care to distinguish the abstraction vs. the specific implementation. > > That's fine with me in principle, but not if the language makes an > effort to hide the implementation from me. > > A fix that works (at least for the examples I tried) is > > (defn replace-syms > [sym-map expr] > (let [replace #(replace-syms sym-map %)] >(cond (contains? sym-map expr) (get sym-map expr) > (vector? expr) (into [] (map replace expr)) > (map? expr) (into {} (map replace (seq expr))) > (set? expr) (set (map replace expr)) > (seq? expr) (map #(replace-syms sym-map %) expr) > :else expr))) > > I have moved the seq? test to the end just in case that one day > vectors, sets, or maps implement the seq interface as well. > It's best to do this as generally as possible, building on something like this: (defn map-same [f coll] (let [ret (into (empty coll) (map f coll))] (if (seq? coll) (reverse ret) ret))) (map-same inc [1 2 3 4]) -> [2 3 4 5] (map-same inc '(1 2 3 4)) -> (2 3 4 5) (map-same inc (seq [1 2 3 4])) -> (2 3 4 5) (map-same inc #{1 2 3 4}) -> #{2 3 4 5} (map-same (fn [[k v]] [k (inc v)]) {:a 1 :b 2 :c 3}) -> {:a 2, :c 4, :b 3} 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch: standalone compiler (almost)
On Nov 16, 9:47 pm, "Stuart Sierra" <[EMAIL PROTECTED]> wrote: > Hi Rich, and all, > > I took a stab at writing a static compiler class, i.e. a main() that > just compiles all the .clj files on the command line and saves the > .class files. Patch attached. > > It almost works. The only thing that seems to be missing is creating > the class for the namespace itself, like "clojure/core.class". Not > sure what needs to be added to make that work. > Interesting. I think you've hooked in at the wrong point - better to grab the clojure.core/compile var and call that. You should also keep the unit of compilation the lib, not files. Since it only requires main, might I suggest you write this in Clojure instead? 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Filter repeats
On Nov 16, 12:18 pm, "Craig Andera" <[EMAIL PROTECTED]> wrote: > One way I could think of to do this would be to build a map with each > unique item as a key and the count as its value. Then it would be > trivial to pull out the keys with the count as a specified value. I > started writing this, but my SLIME is royally screwed up right now > after the upgrade to Clojure HEAD. Sorry. Anyway, it shouldn't require > any refs - probably just a loop/recur. > > Or maybe someone has a far more clever idea. :) > > > On Sun, Nov 16, 2008 at 12:02 PM, npt11tpn <[EMAIL PROTECTED]> wrote: > > > Hi guys, > > This is my first post to the group, but have been following the > > discussions for almost a year. Many thanks to Rich Hickey for creating > > a fantastic future-proof language which is a pleasure to use and to > > the great community! > > The following function (as part of a chemistry-related application) > > filters the elements of a sequence that a repeated a specified number > > of times. Wondering if the function could be simplified and written > > without the reference (newseq). > > Thanks a lot! > > Nik > > > (defn filter-repeats [seq n] > > "Returns a vector of the elements of a sequence that are repeated n > > times" > > (let [newseq (ref [])] > >(doseq [u (set seq)] > > (when (= (count (filter #(= % u) seq)) n) > >(dosync (commute newseq conj u > >@newseq)) > > > Usage e.g. > > (filter-repeats '(2 3 1 4 2 2 4 3 5 ) 2) > > [3 4] (defn filter-repeats [n coll] (let [counts (reduce (fn [m k] (assoc m k (inc (m k 0 {} coll)] (for [[k v] counts :when (= v n)] k))) 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: reader macros
On Nov 16, 7:59 am, Jeff Rose <[EMAIL PROTECTED]> wrote: > Thanks for responding. I had already seen the shebang script hack on > the wiki, and although impressive I don't think it's a solution. It's > shocking to me that someone who is into lisp would even think of getting > rid of read macros though. For sure, there is a potential for abuse, > but I don't think it actually happens much. The tone set forth by the > built-in libraries will probably have more to do than anything with > these types of policies. I've never experienced the pain from this, so > maybe I'm just lucky and/or naive, but I always considered read macros > one of the primary reasons that lisp is such a wonderful place to > explore language ideas. > > Anyways, I don't want to get into a debate for now. In the meantime how > about defining #! to read through until the end of the line? Hell, it > could even be restricted to the first line of the first file. This > change shouldn't effect anything else, but it will make clojure programs > as easily runnable as any other script, which should really be a must > have for a new language on the scene. People coming to lisp, say from > Ruby, Python or Pearl, already have to rewire their brains a bit, and > making them substitute this garbage: > > #^:shebang '[ > exec java -cp "$HOME/src/clj/clojure/clojure.jar" clojure.lang.Script > "$0" -- "$@" > > for this: > > #!/usr/bin/env clj > > makes it seem like a big hack. For that matter, a standard clj script > or executable should probably be a part of the package too. How about > it? For the children. Oh, and if the read table is getting modified, I > vote for Ruby like string evaluation too :-) > > Cheers, > Jeff > > Stephen Gilardi wrote: > > Clojure does not currently allow programs to define new reader macros. That > > is unlikely to change. > > > There are more details here: > > >http://groups.google.com/group/clojure/search?group=clojure&q=reader+... > > > There is a clever technique described on the wiki that allows Clojure > > Shebang scripts: > > >http://en.wikibooks.org/wiki/Clojure_Programming#Shebang_Scripting_in... > > > (There's a link there that points to a posting that explains how it works.) > > > --Steve > > > On Saturday, November 15, 2008, at 07:52PM, "Jeff Rose" <[EMAIL PROTECTED]> > > wrote: > >> Hi, I'm finding comments talking about reader macros, but nothing about > >> defining them. Does anyone know of an example for adding new read > >> macros? I'd like to define a #! macro that passes over the rest of the > >> line so we can use clojure scripts just as easily as a ruby script would > >> be. If anyone knows another way to do this, that would be great too. > I've added #! as a to-end-of-line comment, like ; 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Improved exception reporting
On Nov 14, 3:50 pm, "Stephen C. Gilardi" <[EMAIL PROTECTED]> wrote: > On Nov 14, 2008, at 3:11 PM, Howard Lewis Ship wrote: > > > The point is, an exception that said something like: > > > "Expected java.lang.Comparable but received :king" would have helped > > me unravel this much, much easier! > > I agree. Clojure should give all the information it can about the > object(s) involved in the failure. There are other places where the > class of the object is given, but not its string representation. Any > juicy info that's easily available should be made part of the > exception message. I'm certainly interested in improving the error reporting, but in this partiicular case: java.lang.ClassCastException: clojure.lang.LazyCons is my all-time pet-peeve exception message, and it comes from the JVM. Why on earth they didn't report the types of both what you had and what you were trying to cast to is completely baffling and can only be described as a bug, which seems to be fixed in JDK 6, which reports "XXX cannot be cast to YYY". For every library and every app to have to wrap every cast in a try block simply in order to get this message to say what it ought to is not productive, IMO. One issue with trying to capture string representations is that they can be arbitrarily long. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Missing attachments when posting here
On Nov 15, 2:34 pm, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote: > Hi, > > Am 15.11.2008 um 19:20 schrieb Stephen C. Gilardi: > > > I usually use Mac OS X's Mail from a "mac.com/MobileMe" > > account to send and receive mail with this group. > > I'm using Mail.app on Mac OS X and had never problems sending > attachments to the group. However Google Groups seems to be > rather cheesy. I didn't have so many problems with a mailing > list since ten years ago. It breaks lines giving ugly formatting. > Sometimes messages take hours up to a day to show on the list > or the web interface. Resulting in double posts, because the > author doesn't know: did it work or not? The web interface > sometimes goes completely banana. It allows attachments only > via mail. > > So I wouldn't be surprised if Google Groups has some cheesy > setting behind the scenes which makes your attachments go away. > So the tip with the MIME type might be a good idea. > Delays are associated with first posts. In order to catch spam, I have the 'new members messages are moderated' setting on. So your first post has to wait for me to moderate it. When doing so, I set it so further posts from you go right through. (This wasn't always the case, they've recently made it easier to do both in one shot.) So, first time posters - please be patient. I haven't seen delays otherwise. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: FindBugs run on Clojure source code
On Nov 15, 4:53 am, Attila Szegedi <[EMAIL PROTECTED]> wrote: > Hi folks, > > I run FindBugs on Clojure source code, and there are few things it > uncovered. I'd be happy to fix these and submit patches (after I > submitted a contributor agreement), except if someone already a > contributor wants to tackle these instead (they're easy to fix for the > most part). > > 1. withMeta() in CachedSeq, LazilyPersistedVector, and LazyCons isn't > synchronized, and it looks like a potential for race condition. I've > looked into some usages of withMeta() to make sure I'm not crying wolf > in vain (i.e. there's a guarantee of synchronization higher up the > call chain), but it looks like there isn't, so I'm fairly certain this > is a real problem. > > 2. Keyword and Ref define compareTo, but don't redefine equals (and > hashCode) to be consistent with it. It ain't necessarily a problem if > you know what you're doing, but since they're public it's usually a > good rule of thumb to have equals consistent with compareTo (and then > hashCode consistent with equals). > > 3. There are lots of usages of "new Integer(...)", "new Short(...)", > "new Long(...)" etc. Now, in Java 5 and above, "Integer.valueOf(...)" > and similar methods for all primitive wrapper types are the preferred > idioms as the valueOf() methods return canonical instances for certain > value range (usually -128..127) - these are used behind the scenes for > Java autoboxing as well. > > There are a lot of other FindBugs warnings as well, but I won't go > into them as any contributor/committer can run FindBugs on their own > and review them. These three however I think desire emphasis. > Welcome Attila, I've run findbugs on Clojure before and cleaned up a few things. These that you mentioned, however, stand as a good example of such an analyzer not knowing enough, and I count as spurious, if well- intended. As mentioned by Phil, the refs are still correct. The UUID is some unfinished work on ref persistence (of the db kind). Don't look behind the curtain :) As far as the synchronization, let's take LazyCons. _first and _rest are normally accessed under a lock. The semantics and behavior of the class is such that these fields make a once-and-once-only transition into a final state. Those transitions happen under locks, in first() and rest(), and rest() calls first(). So, in the withMeta call, the call to rest() ensures that the subsequent use of _first and _rest will see the final values. I don't expect findbugs to understand that, but it's certainly correct. CachedSeq is similar. In LazilyPersistentVector the v field is an optimization cache and can be freely recreated. As far as valueOf, Cliff Click at the JVM Languages Summit had some interesting details about how those caches can thwart optimization in the presence of escape analysis. Instead of having a simple path, they cause a branch into array lookup code. Without such a branch an optimizer could get rid of the boxed object entirely in some circumstances. It left me skeptical of the universal value of valueOf. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Getting a flat sequence from a map (and vice versa)
On Nov 15, 12:09 am, "Brian Doyle" <[EMAIL PROTECTED]> wrote: > Another way to create a map is: > > user=> (apply hash-map [:a 1 :b 2 :c 3]) > {:a 1, :c 3, :b 2} > Yes, that's fine, and for the flatten: (interleave (keys m) (vals m)) Rich > On Fri, Nov 14, 2008 at 9:42 PM, samppi <[EMAIL PROTECTED]> wrote: > > > Excellent! I must remember about the apply function. Thank you very > > much. > > > On Nov 14, 9:35 pm, "Kevin Downey" <[EMAIL PROTECTED]> wrote: > > > On Fri, Nov 14, 2008 at 8:33 PM, Kevin Downey <[EMAIL PROTECTED]> wrote: > > > > On Fri, Nov 14, 2008 at 8:17 PM, samppi <[EMAIL PROTECTED]> wrote: > > > > >> Yeah, I need to be able to do this to easily manage trees of maps. I > > > >> meant, how would you idiomatically implement their algorithms? > > > > >> Fold isn't build into Clojure, but they should still somehow be > > > >> possible...right? > > > > >> On Nov 14, 9:12 pm, Michel Salim <[EMAIL PROTECTED]> wrote: > > > >>> On Nov 14, 10:56 pm, samppi <[EMAIL PROTECTED]> wrote:> I'm trying > > to figure out how to do this: > > > > >>> > (flat-map-seq {:a 3, :b 1, :c 2}) ; returns (:a 3 :b 1 :c 2) > > > > >>> (defn flat-map-seq [m] > > > >>> (if (empty? m) '() > > > >>> (let [kv (first m)] > > > >>> (lazy-cons (kv 0) (lazy-cons (kv 1) (flat-map-seq (rest > > m)))> ...and vice versa: > > > > >>> > (map-from-flat-collection {} [:a 3 :b 1 :c 2]) ; returns {:a 3, > > :b > > > >>> > 1, :c 2} > > > > >>> (defn map-from-flat-collection [c] > > > >>> (if (empty? c) {} > > > >>> (conj (map-from-flat-collection (rrest c)) [(first c) (frest > > > >>> c)]))) > > > > >>> > Anyone have any idiomatic ideas? > > > > >>> Well, not sure how idiomatic this is; apart from conj, this is how > > > >>> you'd do it in Lisp/Scheme. I'd use fold to do the first function if > > > >>> it's built into Clojure. > > > > >>> Regards, > > > > >>> -- > > > >>> Michel > > > > > (apply assoc {} [:a 1 :b 2 :c 3]) > > > > -> {:c 3, :b 2, :a 1} > > > > -- > > > > The Mafia way is that we pursue larger goals under the guise of > > > > personal relationships. > > > >Fisheye > > > > user=> (apply concat (seq {:c 3, :b 2, :a 1})) > > > (:c 3 :b 2 :a 1) > > > user=> > > > > -- > > > The Mafia way is that we pursue larger goals under the guise of > > > personal relationships. > > > Fisheye --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch: precompiling Clojure core sources in Ant build script
On Nov 14, 12:51 pm, "Stuart Sierra" <[EMAIL PROTECTED]> wrote: > Patch attached. This precompiles everything except parallel.clj, > which requires an extra Jar. It also omits the source .clj files from > the clojure.jar file. > -Stuart Sierra Patch applied (svn 1101) - thanks! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: UTF-16 bugfix [patch]
On Mon, Nov 10, 2008 at 2:42 AM, Toralf Wittner <[EMAIL PROTECTED]>wrote: > Dear list members, > > There is a small problem with unicode escapes in Clojure strings. When > StringReader encounters a unicode escape it checks Character.isDigit > which is only true for decimal digits, but not hexadecimal. > > The other problem is that CharacterReader accepts a character constant > denoting a high or low surrogate as a valid character which it is not. > Cf. http://en.wikipedia.org/wiki/UTF-16 and > http://java.sun.com/javase/6/docs/api/java/lang/Character.html > > > The attached patch (against r1092) corrects both issues. > Patch applied (svn 1099) - thanks! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Changes for AOT compilation
On Nov 14, 4:51 am, Zak Wilson <[EMAIL PROTECTED]> wrote: > It's currently possible to compile the files and rebuild the jar. It > does result in a faster startup time. > > There doesn't seem to be a way to generate precompiled class files > with main methods at this point. Is there any reason such > functionality can't be added? Right now, if I want an executable > precompiled jar, I have to make a wrapper with gen-and-save-class or > Java. Support for main (and the other features of genclass) is coming. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Changes for AOT compilation
On Nov 14, 4:21 am, Parth Malwankar <[EMAIL PROTECTED]> wrote: > On Nov 13, 11:43 pm, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > We're coming around the other side of the few breaking changes I > > wanted to get done before release 1.0. > > > The changes are: > > > New regex format: > > >http://groups.google.com/group/clojure/msg/eddd7f0d292da683 > > > Uniform binding syntax using vectors: > > >http://groups.google.com/group/clojure/browse_frm/thread/55213f2eb203... > > > And ahead-of-time (AOT) compilation (SVN 1094+) > > Thanks very much Rich. All these changes are very exciting. > I look forward to using them. > > Does this mean that at some point clojure.jar would > contain precompiled class files for clojure code? > I suppose that would mean faster startup of the > repl. > That's just a matter of adding precompiling to the ant script. Patch welcome. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: clojure.zip: replace error
On Nov 13, 11:20 pm, Parth Malwankar <[EMAIL PROTECTED]> wrote: > Hello, > > While setting ns to clojure.zip, I get the following error: > > user=> (ns clojure.zip) > java.lang.IllegalStateException: replace already refers to: > #'clojure.zip/replace in namespace: clojure.zip (NO_SOURCE_FILE:0) > clojure.zip=> > > Is this expected? > Do not use ns to change namespaces, use in-ns. ns is for defining a namespace. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Simple Namespace Question
On Nov 13, 2:31 pm, Stuart Halloway <[EMAIL PROTECTED]> wrote: > (clojure.core/ns clojure) > > or if you are on an old build I think it would be > > (clojure/ns clojure) > This is coming in my book notes, I promise :), but ns should not be used to change namespaces in the repl, only in-ns should be used. ns is for defining namespaces, once only per namespace. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Changes for AOT compilation
We're coming around the other side of the few breaking changes I wanted to get done before release 1.0. The changes are: New regex format: http://groups.google.com/group/clojure/msg/eddd7f0d292da683 Uniform binding syntax using vectors: http://groups.google.com/group/clojure/browse_frm/thread/55213f2eb203ca39# And ahead-of-time (AOT) compilation (SVN 1094+) There is now an AOT compiler that can compile .clj files to .class files on disk. This can be used to save startup time, deliver applications without source, interop with bytecode-based tools etc. The main structural change related to AOT is that the mapping between a Clojure namespace and a Java package has changed. Where it was ns maps to package: my.fancy.lib ==> my/fancy/lib/lib.clj it is now ns maps to class: my.fancy.lib ==> my/fancy/lib.clj, when compiled, my/fancy/lib.class Just lift your files up a directory to accommodate this change. Note that this implies that all namespaces should have at least 2 segments, and following the Java package name guidelines, e.g. com.mydomain.mylib, is recommended. Accordingly, the clojure ns has been renamed clojure.core. Any explicitly qualified references will need to be changed. boot.clj has been renamed core.clj. The only other source-level change here was a small one to load - you no longer should supply the .clj extension, in keeping with load's new ability to load from .class files. The latter is the only functional difference AOT brings to existing code - load will load from a .class file if it is newer than the .clj. Both files need to be in the classpath, using a directory structure corresponding the the Java package as per above. Once compiled, .clj files need not be present at all if .class files are supplied. The unit of compilation is the lib. To compile a lib, simple say: (compile 'my.fancy.lib) The source must be in the classpath, in my/fancy/lib.clj Compilation output will go under the path designated by *compile-path*, which defaults to the "classes" directory under cwd. Output will go to *compile-path*/my/fancy/lib.class, and the subdirectories will be created if needed. *compile-path* is bound in the repl and can be set! or bound with binding. The *compile-path* directory must also be in the classpath. Compilation occurs under a same-world model, i.e. compiling a file has the effect of loading it as well. As each file/fn is compiled, it is loaded using the standard class lookup (thus the *compile-path* in classpath requirement above). This is so that definitions can see and utilize the definitions and macros that preceded them. While compiling, a *compile-files* flag is set. This will cause nested load/ require/uses to compile as well, if needed. If your file has some def initializers you don't want to run at compile-time, you can conditionalize them like this: (def foo (when-not *compile-files* (my-runtime-init))) in which case foo will be nil at compile time. A .class file will be produced for every file loaded. This file defines a class called my.fancy.lib, which will have a static void load () method (this name is likely to change). Calling this method has the same effect as loading the original .clj would. Namespaces defined in multiple files are supported. Simply (load "lib- helper-file") for any helper files at the bottom of your ns- defining .clj file. Note that classes will be created for these files as well, even though they are not namespaces, and are not intended for standalone use In addition to the class file per .clj file, there will be a .class file for every function. These will be named my/fancy/lib $myfun__.class. They too are not intended for standalone use. There will be many of these, so please use jar files for distribution. The clojure.contrib and tools folks are working on getting in sync with these changes. For minimal disruption, please stick with the SVN rev they support (say, 1088), or lend a hand in testing their patches. Still to come is a folding of genclass functionality into AOT, making for a much smoother process. Those of you who've used Clojure for a while know such breaking changes are few and far between. AOT compilation is an important, non- trivial, and often requested feature. Please be patient during the transition. As always, feedback and bug reports welcome. Thanks, 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Donations
Some people have asked how to donate to Clojure, so I've turned donations on in SF: https://sourceforge.net/project/project_donations.php?group_id=137961 Thanks to all for your support! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: let accepting a vector
On Nov 13, 8:36 am, Stuart Halloway <[EMAIL PROTECTED]> wrote: > Hi Meikel, > > I spent a few minutes trying to write a macro to do this that doesn't > use eval. So far no good. Is it truly impossible, though? I have never > seen a good discussion of "things that can be done only with eval". > Any pointers? > The admonitions against eval are important, because people frequently get confused about macros, compile time, runtime etc. 99.9% of the time, especially when you are starting out, you shouldn't be using eval. The purpose of a macro is to transform a form into another form on behalf of the compiler. That's all! The fact that CL and Clojure macros can run arbitrary code makes them powerful, but doesn't change that fundamental purpose. People see them and think - oh, this is just a function that doesn't evaluate its arguments, and start writing macros for their runtime values, or worse yet, their effects. That's wrong! People often think they need runtime code generation without thinking it all the way through - if you write something that generates code at runtime, especially new names, how can the other code that you wrote prior to runtime use it? Macros allow you to do dynamic code generation that is accessible to other code prior to runtime. Is there ever a reason to generate code at runtime? Sure - to write a repl, or an interpreter. Of course, I've overstated everything, but it's only because, until you've developed an understanding of the above, you shouldn't be trying anything trickier. That said, and I'm loath to show this, the original example begs the conflation of compile and runtime. Here's how to do it without eval: ; gross - please don't write code like this!!! (def bindings-list '[one 1]) (defmacro list-let "a horrible macro that expects to be passed the name of a global var that contains a binding list" [bs & body] (let [blist (var-get (resolve bs))] `(let ~blist [EMAIL PROTECTED]))) (macroexpand-1 '(list-let bindings-list one)) -> (clojure.core/let [one 1] one) (list-let bindings-list one) -> 1 list-let is passed the name of a var that it needs to resolve at compile time. It does so, gets its value, then inserts that form into its expansion. The problem is, people may write things like this and expect the expansion to use the runtime value of bs at each expansion point - not so. The purpose of a macro is to transform a form into another form on behalf of the compiler. That's all! 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Just Wondering: Tag metadata
On Nov 12, 7:21 pm, samppi <[EMAIL PROTECTED]> wrote: > Ah, yes. I meant, what are these hints? What does the compiler change? > Is it some sort of informal type enforcement or something? > The hints are described here: http://clojure.org/java_interop#typehints It is strictly a performance optimization so calls to Java can avoid reflection. There is no compile-time enforcement. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Just Wondering: Tag metadata
On Nov 12, 6:49 pm, samppi <[EMAIL PROTECTED]> wrote: > Onhttp://clojure.org/reader... > > A shorthand version allows the metadata to be a simple symbol or > keyword, in which case it is > treated as a single entry map with a key of :tag and a value of > the symbol provided, e.g.: > #^String x is the same as #^{:tag String} x > Such tags can be used to convey type information to the compiler. > > I'm just wondering, does tag metadata do anything right now? If not, > what is planned for its use? > Tag metadata is used currently to convey type hints to the compiler. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Why are symbols resolved when a function is defined?
On Nov 11, 10:13 am, "Daniel Renfer" <[EMAIL PROTECTED]> wrote: > Rich, > > Would you recommend using declare even if you are able to arrange your > code to avoid dependency issues, or only if you can't work around it? > I think it's a personal preference thing, certainly not necessary. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Bio
On Nov 10, 9:38 pm, "Mike DeLaurentis" <[EMAIL PROTECTED]> wrote: > Hi Rich, > > I'm giving a talk about Clojure tomorrow night in Philadelphia for a > functional programming user group, and I'd like to include some > information about you. Do you have a standard bio you use for things > like that? Just a few sentences about your background and your > motivation for writing Clojure? > How did the talk go? For everyone doing talks on Clojure: please feel free to post announcements and pointers to meeting notes/slides/recordings here on the group. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Why are symbols resolved when a function is defined?
On Nov 11, 12:24 am, Paul Barry <[EMAIL PROTECTED]> wrote: > In Common Lisp and Scheme, if you have an expression that evaluates a > symbol, it doesn't evaluate it until you call the function, not when > you define it. So you can do this: > > Common Lisp: > [1]> (defun b () a) > B > [2]> (defvar a 5) > A > [3]> (b) > 5 > > Scheme: > 1 ]=> (define (b) a) > ;Value: b > 1 ]=> (define a 5) > ;Value: a > 1 ]=> (b) > ;Value: 5 > > But you can't do this in Clojure: > user=> (defn b [] a) > java.lang.Exception: Unable to resolve symbol: a in this context > (NO_SOURCE_FILE:1) > > But if you def a to something, you can then redef it and it will use > the value defined later: > user=> (def a nil) > #=(var user/a) > user=> (defn b [] a) > #=(var user/b) > user=> (def a 5) > #=(var user/a) > user=> (b) > 5 > > So is there a reason that Clojure tries to resolve symbols when you > define a function? The downside of this is that when you have a file > with multiple functions in it that call each other, you have to make > sure they are defined in order of dependency. I can't speak for Scheme, but CL resolves symbols earlier than does Clojure - at read time. This causes a number of problems and a lot of complexity [1]. In Clojure, I had to solve the Lisp-1 vs defmacro problem, and did so by separating symbols from vars. That means that symbols are simple when read, and only get resolved when compiled. Were compilation to auto-create vars for never before seen symbols, many of the problems of packages would remain, so I decided that vars and other name resolutions needed to be created intentionally, via def/import/refer. This leads to many fewer errors, and avoids the problems identified in [1]. There is now a declare macro that makes it simple and obvious to intentionally claim names for later use: (declare a b c) ; ...def a b c in any order This expands into (def a) (def b) (def c). Note that no initial values are supplied, so they are unbound, and you will get a runtime error if you use them before subsequently defining them, unlike your (def a nil) above, which I don't recommend. So, you don't need to define things in any specific order - use declare. Rich [1] http://www.flownet.com/gat/packages.pdf --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Bio
On Nov 10, 9:38 pm, "Mike DeLaurentis" <[EMAIL PROTECTED]> wrote: > Hi Rich, > > I'm giving a talk about Clojure tomorrow night in Philadelphia for a > functional programming user group, and I'd like to include some > information about you. Do you have a standard bio you use for things > like that? Just a few sentences about your background and your > motivation for writing Clojure? > How's this: http://www.lisp50.org/schedule/schedule/hickey.html 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: The Dread Revision 1089
On Nov 10, 10:17 am, Rich Hickey <[EMAIL PROTECTED]> wrote: > On Nov 10, 2008, at 9:46 AM, Graham Fawcett wrote: > > > > > Hi folks, > > > I haven't been bitten by the "do not use" revisions, R1089 onward, but > > it seems that others have. > > > I'm just curious why the team decided not to use a branch for these > > breaking changes, and merging back with trunk once the breakage was > > finished? > > For one, there's no 'team' for the trunk, just me. Branches and > merging are a pain, and if there's no reason for them other than to > keep head clean, I don't buy it, i.e. there aren't 2 paths. > > > > > Like many open-source projects, Clojure seems to have a HEAD culture > > rather than a Release culture, so intentionally breaking HEAD should > > be taboo, IMHO. > > I agree in general, and that is what I usually try to do. But the > interim commits are clearly labeled as such. I think it's just good > habits to read the commit messages before you pull. Why grab HEAD if > it doesn't fix a bug or add a feature you need? > > People that want to track SVN closely should definitely utilize the > IRC channel. If I'm not there, there is usually someone who can > provide guidance on revisions etc, and immediate get-out-of-trouble > support. > > Anyone using SVN needs to be able to read the commit messages and back > out to a prior revision - even with the best of intentions, HEAD may > be (unintentionally) broken. > > In any case, this set of breaking changes is the work due to precede a > release 1.0, and a subsequent 'release-oriented' view of the world, > with multiple real paths, and merging of fixes into release branches > etc. > I'll also add that I didn't check in something that didn't run, just something that contains changes that require changes to your code or environment. Tracking SVN HEAD certainly implies a willingness to make such changes. As for what those changes are, hop on the IRC or send a message to the group. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: The Dread Revision 1089
On Nov 10, 2008, at 9:46 AM, Graham Fawcett wrote: > > Hi folks, > > I haven't been bitten by the "do not use" revisions, R1089 onward, but > it seems that others have. > > I'm just curious why the team decided not to use a branch for these > breaking changes, and merging back with trunk once the breakage was > finished? For one, there's no 'team' for the trunk, just me. Branches and merging are a pain, and if there's no reason for them other than to keep head clean, I don't buy it, i.e. there aren't 2 paths. > > Like many open-source projects, Clojure seems to have a HEAD culture > rather than a Release culture, so intentionally breaking HEAD should > be taboo, IMHO. > I agree in general, and that is what I usually try to do. But the interim commits are clearly labeled as such. I think it's just good habits to read the commit messages before you pull. Why grab HEAD if it doesn't fix a bug or add a feature you need? People that want to track SVN closely should definitely utilize the IRC channel. If I'm not there, there is usually someone who can provide guidance on revisions etc, and immediate get-out-of-trouble support. Anyone using SVN needs to be able to read the commit messages and back out to a prior revision - even with the best of intentions, HEAD may be (unintentionally) broken. In any case, this set of breaking changes is the work due to precede a release 1.0, and a subsequent 'release-oriented' view of the world, with multiple real paths, and merging of fixes into release branches etc. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Readable names
On Nov 10, 2008, at 8:48 AM, Robert Lally wrote: > One of the many things that I really like about Clojure is that it > abandoned Lisp tradition where it was pragmatic to do so. One of the > prime examples for me was the use of first and rest rather than car > and cdr. Sure, I can read code with car and cdr but it never really > communicated that well; I always had to go through a translation > step in my head. It's important to note right away that car and cdr aren't abbreviations for anything more meaningful than car and cdr. > With this in mind it surprises me ( and disappoints a little ) that > there are still abbreviated function names in many places - aget, > aset, assoc, conj, coll?, comp, and so on. Is there any need for > this in the 21st century? I think so, but I understand this is somewhat subjective. It is useful to look at the 'competition' here (from random other languages): array-get -> [] associate -> put conjoin -> add compose -> . I don't see people coming from a language where array access is [] feeling good about the verbosity of array-get. put and add have imperative connotations that don't fit what assoc and conj do, so using them would only confuse people more. > The trade off between meaningful method names and number of > characters typed doesn't seem to be a good one from my perspective; > particularly as IDE support matures and you will only need to type > 'asso' to have the IDE expand the function name to 'associate' for > you. IDEs can be great, but having to rely on them is a real problem. People stumble over Lisps due to editors without adequate paren matching, and if my experience with Clojure users is a guide, people tend to try to stick with the editor they already know, leaving them waiting for specific language support. Adding completion to the 'things your editor must do before you can write Clojure effectively' sets a high bar. > Using full words as function names leads to more readable code .. > which can only be a good thing. They do only to a point, and then the code gets larger and harder to scan, lines spill etc. > I'm not suggesting that terseness is bad, merely that I don't > believe the trade off is worth it in this case. I've shown Clojure > to a number of people and the Lisp derived syntax coupled with > abridged names makes it harder for people to comprehend, makes it > less likely that on first encountering a piece of Clojure code that > they'll be able to understand it, and so make it less likely that > I'll get to write Clojure for a living ... which makes me sad. Well, people have to learn something new when they approach a new language. I'm not sure associate or conjoin would be more readily understood without some background on persistent immutable data structures. But at least it's not a lot of arbitrary syntax and associativity rules, and most of the short names are true abbreviations. Short names are one way Clojure can compete for brevity with languages that get their brevity from syntax. IMO, it's more approachable than Haskell, Erlang, Scala or any of the ML variants. array-get, associate, conjoin and compose etc are all still available. I wonder - would people use them if they were provided as aliases? I know I wouldn't. The vocabulary of seqs and collections is so small. While I appreciate the approachability argument, a language is ultimately for its practitioners. I imagine there are those that wish assoc/conj/apply et al were even shorter, or dedicated symbols... Since I don't hear this argument too often, I image Clojure is striking an acceptable balance. What does everyone else think? 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: a macro question, this time completely specified :-)
On Nov 9, 8:21 am, Stuart Halloway <[EMAIL PROTECTED]> wrote: > You should be able to do this without the ref. Have the agent's state > contain a pair of [has-run, fn-result]. The semantics of your runonce aren't clear to me, but here are some strategies: As Chouser proposed, if you only want a one-time effect, atomics are the simplest. I prefer to use compareAndSet so it's clear what the governing transition is, and I've written this more verbosely so it corresponds to the other solutions: (defn runonce "Create a function that will only run once. All other invocations return nil" [function] (let [first-call (Object.) atom (java.util.concurrent.atomic.AtomicReference. first- call)] (fn [& args] (when (.compareAndSet atom first-call nil) (apply function args) If you don't want any callers to proceed until it has been run once, then they'll need to queue up somehow. You can use either transactions or agents, and which to choose depends on whether or not the function has side-effects. If it doesn't, you can use transactions, the benefits being multiple such calls can compose: (defn runonce "Create a function that will only run once. All other invocations return the first calculated value. The function must be free of side effects" [function] (let [first-call (Object.) ret (ref first-call)] (fn [& args] (dosync (when (= @ret first-call) (ref-set ret (apply function args))) @ret If the function has side effects, agents are the way to go: (defn runonce "Create a function that will only run once. All other invocations return the first calculated value. The function can have side effects" [function] (let [first-call (Object.) agt (agent first-call)] (fn [& args] (send-off agt #(if (= % first-call) (apply function args) %)) (await agt) @agt))) Note that there is no magic bullet here - the agents approach does not compose, each such function must run autonomously (that's not bad, just must be understood). This is enforced by the fact that await will fail if called in an action. Note also the use of a private sentinel value in order to avoid managing both the return and the flag. Both the ref and agent solutions support a 'peek' optimization to avoid the transaction/action-send: (defn runonce "Create a function that will only run once. All other invocations return the first calculated value. The function must be free of side effects" [function] (let [first-call (Object.) ret (ref first-call)] (fn [& args] (when (= @ret first-call) (dosync (when (= @ret first-call) (ref-set ret (apply function args) @ret))) (defn runonce "Create a function that will only run once. All other invocations return the first calculated value. The function can have side effects" [function] (let [first-call (Object.) agt (agent first-call)] (fn [& args] (when (= @agt first-call) (send-off agt #(if (= % first-call) (apply function args) %)) (await agt)) @agt))) You must still re-examine the flag inside the transaction/action. If you want runonce to return both the once-running function and a way to detect if it has been run, I recommend returning a has-run fn which encapsulates the mechanism: (defn runonce "Create a function that will only run once. All other invocations return the first calculated value. The function must be free of side effects. Returns [has-run-predicate once-fn]" [function] (let [first-call (Object.) ret (ref first-call) has-run #(not= @ret first-call)] [has-run (fn [& args] (when-not (has-run) (dosync (when-not (has-run) (ref-set ret (apply function args) @ret)])) You can do something similar for the agent version. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: nth and take-nth argument order
On Nov 8, 2:44 pm, "Michael Wood" <[EMAIL PROTECTED]> wrote: > Is there any particular reason for the reversal of the order of > arguments between nth and take-nth? Short answer - take-nth is more like take. Longer answer: http://groups.google.com/group/clojure/browse_frm/thread/8b2c8dc96b39ddd7/a8866d34b601ff43 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch and audit: Use vectors for bindings in doseq, et al.
On Nov 8, 8:52 am, Chouser <[EMAIL PROTECTED]> wrote: > Attached is an updated patch. Instead of using "for" in the > implementation of "doseq", this has a "doseq" that uses loop/recure. > The interface is the same, but it should run faster. This also means > "doseq" is only defined once (nor redefined as in the earlier patch). > > This patch is against 1089, the "Interim checkin - DO NOT USE!!" version of > SVN. > Patch applied - many thanks!! Rich > > On Sat, Nov 8, 2008 at 7:42 AM, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > On Nov 7, 5:09 pm, James Reeves <[EMAIL PROTECTED]> wrote: > >> On Nov 7, 9:32 pm, Chouser <[EMAIL PROTECTED]> wrote: > > >> > > And in which case, your vector syntax could be misleading, because it > >> > > seems to imply you're assigning i to 10: > > >> > > (dotimes [i 10] > >> > > (prn i)) > > >> > Vectors are also used for "for": > > >> > (for [i (range 10)] > >> > (* 2 i)) > > >> > Here i is not bound to the seq (range 10) but to each of the numbers > >> > in turn. > > >> I'm still not convinced on this one. Currently, you have single > >> assignments, where a value is assigned to a symbol as in let and > >> binding, and sequence assignments, where each item in the sequence is > >> assigned to a symbol. Adding a vector to dotimes would add a third > >> type, and I don't think it's obvious what the [i 10] does. I mean, you > >> originally put it down as [i (range 10)], so you were thinking in > >> terms of [symbol sequence] too. > > > The general idea behind this patch is that all macros that introduce > > names will do so in vector syntax. The nature of the bindings is going > > to be open, as is the set of macros - doseq/dotimes/let/loop all have > > different semantics. As it stands, it is confusing for people because > > they don't know if they need a vector or not, for each macro. > > >> > > Second, with your patch, is the following valid: > > >> > > (doseq [i (range 10) > >> > >j (range 10)] > >> > > (prn i) > >> > > (prn j)) > > >> > It behaves the same as "for" does, that is with j in an inner loop. > >> > It also supports :while and :when as "for" does. > > >> Well, not that my opinion matters ;) - but you've sold me on this one. > >> Consistency with the for macro seems reasonable. > > > This is a much-needed enhancement, as so many people use for for side- > > effects and forget dorun. Plus it will be faster for that use. > > >> > My first inclination is to disallow it -- add a check to make sure > >> > only one binding pair is given. Alternatively it could act as if it > >> > were nested, as "for" (and now "doseq") do, in which case it would act > >> > like an "and", and both x and y would be bound to non-false values. > > >> Hm. A nested if would be consistent with the nested for and doseq > >> macros. If this is implemented, nesting ifs would be my preference for > >> this. > > > I'd like to see this patch limit its enhancements to "doseq a la for", > > and otherwise just be a syntax change for all the others. > > > Rich > > > > doseq-vector-2.patch > 27KViewDownload --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch and audit: Use vectors for bindings in doseq, et al.
On Nov 7, 5:09 pm, James Reeves <[EMAIL PROTECTED]> wrote: > On Nov 7, 9:32 pm, Chouser <[EMAIL PROTECTED]> wrote: > > > > And in which case, your vector syntax could be misleading, because it > > > seems to imply you're assigning i to 10: > > > > (dotimes [i 10] > > > (prn i)) > > > Vectors are also used for "for": > > > (for [i (range 10)] > > (* 2 i)) > > > Here i is not bound to the seq (range 10) but to each of the numbers > > in turn. > > I'm still not convinced on this one. Currently, you have single > assignments, where a value is assigned to a symbol as in let and > binding, and sequence assignments, where each item in the sequence is > assigned to a symbol. Adding a vector to dotimes would add a third > type, and I don't think it's obvious what the [i 10] does. I mean, you > originally put it down as [i (range 10)], so you were thinking in > terms of [symbol sequence] too. > The general idea behind this patch is that all macros that introduce names will do so in vector syntax. The nature of the bindings is going to be open, as is the set of macros - doseq/dotimes/let/loop all have different semantics. As it stands, it is confusing for people because they don't know if they need a vector or not, for each macro. > > > Second, with your patch, is the following valid: > > > > (doseq [i (range 10) > > >j (range 10)] > > > (prn i) > > > (prn j)) > > > It behaves the same as "for" does, that is with j in an inner loop. > > It also supports :while and :when as "for" does. > > Well, not that my opinion matters ;) - but you've sold me on this one. > Consistency with the for macro seems reasonable. > This is a much-needed enhancement, as so many people use for for side- effects and forget dorun. Plus it will be faster for that use. > > My first inclination is to disallow it -- add a check to make sure > > only one binding pair is given. Alternatively it could act as if it > > were nested, as "for" (and now "doseq") do, in which case it would act > > like an "and", and both x and y would be bound to non-false values. > > Hm. A nested if would be consistent with the nested for and doseq > macros. If this is implemented, nesting ifs would be my preference for > this. > I'd like to see this patch limit its enhancements to "doseq a la for", and otherwise just be a syntax change for all the others. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: macro/eval question
On Nov 7, 5:41 pm, Stuart Halloway <[EMAIL PROTECTED]> wrote: > Hi Rich, > > Sorry for being unclear. define-ant-task will be called as I > reflectively walk Ant's object model. A more complete listing follows. > The problem is that I am passing (.getKey td) to the macro, where > (.getKey td) returns a string--or would if I evaled it :-) > No problem. I phrased things the way I did because the answer to all macro problems usually lies in answering those 2 questions. So I'll ask again: What do you want to write? What do you want it to expand into? For instance, where does ant-project come from? I could imagine an answer like this - I want to write: (generate-ant-tasks "my-ant-project-name") And I want it to expand into: (def task-name1 (create-ant-task "task-name1")) (def task-name2 (create-ant-task "task-name2")) (def task-name3 (create-ant-task "task-name3")) ... for every task in the project. But again. I don't know the ant model or pattern of use you want. Generally speaking, because defs have special evaluation rules, to generate defs your top-level call should be a macro, i.e. def is not something you call, it is something you emit, which in turn gets compiled. Internally your macro can use functions and even do the walk of the ant model. Because it can only yield one expansion form, what it will actually emit will be: (do (def ...) (def ...)) Rich > > P.S. The whole thing is athttp://github.com/stuarthalloway/lancet/tree/master > . > > (defn instantiate-task [project name props] >(let [task (.createTask project name)] > (throw-if (nil? task) (str "No task named " name)) > (doto task >(init) >(setProject project)) > (set-properties! task props) > task)) > > (defn create-ant-task [task-name] >(fn f > ([] > (f {})) > ([props] > (let [task (instantiate-task ant-project task-name props)] > (.execute task) > > (defmacro define-ant-task [task-name] >`(def ~(symbol task-name) (create-ant-task ~task-name))) > > (doseq td (.getTaskDefinitions ant-project) > (do > (println (.getKey td)) > (define-ant-task (.getKey td > > > > > On Nov 7, 3:48 pm, Stuart Halloway <[EMAIL PROTECTED]> wrote: > >> The following macro in lancet defines an ant task. > > >> (defmacro define-ant-task [task-name] > >> `(def ~(symbol task-name) (create-ant-task ~task-name))) > > >> (At least) one of the following assumptions is wrong: > > >> (1) define-ant-task needs to be a macro so it can drop args into def. > > >> (2) define-ant-task needs to be a function because task-name needs to > >> be evaled on the way in. > > >> (3) using eval (which would solve the contradiction in 1 & 2) is evil > >> and should be avoided. > > >> On a quick look through boot.clj and other places I don't see any > >> other macros that deal with this issue, which makes me think there is > >> some totally different way to approach the problem. > > >> Suggestions? > > > It's common for people to post only their macros, but actually more > > useful to (additionally) post: > > > What I'd like to say (what a usage would look like) > > > What I'd like that to expand into > > > Doing so can greatly clarify things. For instance it's not clear to me > > what you will be passing to define-ant-task if not a symbol, so I > > don't understand the call to symbol inside. > > > 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: macro/eval question
On Nov 7, 3:48 pm, Stuart Halloway <[EMAIL PROTECTED]> wrote: > The following macro in lancet defines an ant task. > >(defmacro define-ant-task [task-name] > `(def ~(symbol task-name) (create-ant-task ~task-name))) > > (At least) one of the following assumptions is wrong: > > (1) define-ant-task needs to be a macro so it can drop args into def. > > (2) define-ant-task needs to be a function because task-name needs to > be evaled on the way in. > > (3) using eval (which would solve the contradiction in 1 & 2) is evil > and should be avoided. > > On a quick look through boot.clj and other places I don't see any > other macros that deal with this issue, which makes me think there is > some totally different way to approach the problem. > > Suggestions? > It's common for people to post only their macros, but actually more useful to (additionally) post: What I'd like to say (what a usage would look like) What I'd like that to expand into Doing so can greatly clarify things. For instance it's not clear to me what you will be passing to define-ant-task if not a symbol, so I don't understand the call to symbol inside. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Print compiled Clojure svn revision?
On Nov 7, 1:02 pm, "Graham Fawcett" <[EMAIL PROTECTED]> wrote: > On Fri, Nov 7, 2008 at 11:46 AM, vdm <[EMAIL PROTECTED]> wrote: > > > Is there a way to make Clojure print the svn revision it was compiled > > from? A standard or idiomatic way to do this (print clojure--svn-rev) > > would help when trying to isolate whether observed behaviour is > > happening on old or current code. > > Hi, as far as I know, no. But I agree it would be great to have, and > is certainly possible to do. > > If Rich would be willing to add this to boot.clj, > > (defn clojure-svn-revision [] > (if-let rev (re-find #"Rev: (\d+) \$" "$Rev$") > (second rev) > "unknown")) > > and then do this, > > svn propset svn:keywords "Revision" boot.clj > svn commit boot.clj > > ...then (clojure-svn-revision) ought to return the revision number as > a string. > This works by making $Rev$ magic in some way? 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Generalized Type Inference Optimization
On Nov 6, 8:42 pm, Daniel Spiewak <[EMAIL PROTECTED]> wrote: > > So you'd need a runtime instanceof test for Class, and use the > > fastpath if true, reflection if not. > > > Perf could be harder to pin down, as adding an import could cause > > previously fast code to get slow. > > Actually, I was thinking of performing the inference based on *all* > classes on the classpath, not just the ones which have been imported. > However, considering the fact that Clojure allows dynamic additions to > the classpath, coupled with the fact that not all available classes > need to be loaded, this might not be the best idea. In my mind, the whole value of this is to leverage the imports. If you could get fast performance by just importing the classes you know your code is intending to utilize, without actually having to specify again at the point of use, there's maximum leverage. Looking at the whole classpath is definitely too much. > The idea of call- > point import scoping is an interesting one, I'm not sure how solid you > could make it though. I mean, don't you look at the FnExpr types > prior to analyzing its usage? (at least, that's how I've always > written my compilers) At the very least, it might make library > functions a little more interesting (certainly ruling out any pre- > compilation). > > With respect to the separate paths issue, I assume that you're talking > about something like this: > > (defn bad-boy [c x] > (if c > (.getMethods x) > (.length x))) > > I think in this case the proper inference would be #{} -- in other > words, reflection. The overhead of trying to fastpath and then > fallback in certain branches would probably outweigh any benefits in > this sort of edge case. > I think you missed my point here, which was that the job is not to determine a single type for x above, but to determine the right method at each method call. If only class Class has getMethods, then the inferred type of the first call would be ((Class)x).getMethods, similarly if only String had length, then the second would be ((String)x).length. There's no need to unify the types. There's nothing 'bad' about the code above, that's why we're using Lisp - the type systems are still struggling to be expressive enough. If some third class had both methods, that would become the preferred branch. I was not talking about analyzing the contexts of the calls to bad- boy, or any whole-program analysis. > > The best you could do is make a type-inferred fastpath, since you > > could always be wrong > > Yeah, that is annoying. I hadn't thought of the fact that you could > infer at declaration point and get a totally unambiguous type but > still be wrong (since calls in different scopes could pass unexpected > types that happen to fulfill the structural signature). How much > overhead does #getClass() impose these days? I heard they were > optimizing some of that in Java 6, but I haven't actually benchmarked > anything. I suppose a simple check of that sort wouldn't ever be more > expensive that a full-blown reflective call, but still. > A type check would be significantly faster than a reflective call, is a subset of same, and is happening in any case, as the arguments to all fns are Objects. Even if you found 2 or 3 candidates, making a multiway branch would be faster. > At what point are functions actually compiled? When loaded. > Is it possible to > apply some of the techniques used in tracing VMs (e.g. V8) to get some > improved context before performing the inference? In that case, you > could actually create several different fast-path compilations > +fallback. There are just so many complicated places you could go > with this, it's just a question of implementation details (and of > course, time to do it). > There's no need to go there, IMO. What I've described would be relatively simple and effective. Communication with the user about reflection might have to become more nuanced. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Generalized Type Inference Optimization
On Nov 6, 4:31 pm, Daniel Spiewak <[EMAIL PROTECTED]> wrote: > I've been perusing Stu Halloway's beta of "Programming Clojure" and I > came across the following example: > > (defn describe-class [c] > {:name (.getName c) >:final (java.lang.reflect.Modifier/isFinal (.getModifiers c))}) > > As demonstrated by the *warn-on-reflection* flag, Clojure is unable to > determine a type for c, therefore all (or rather, almost all) of the > calls made upon it must be handled reflectively. The performance > "solution" suggested in the book is just to annotate the c parameter > with a type: > > (defn describe-class [#^Class c] ...) > > This is a perfectly valid solution, but it seems a little ugly to me. > The thought that I had is perhaps the Clojure compiler could actually > infer this type automatically. Languages like ML and Haskell have > been doing this for decades. Traditionally, Hindley-Milner isn't > applied to object-oriented languages (or rather, languages which deal > with uncontrolled OO constructs), but from what I understand, most of > the reasoning behind this does not apply to Clojure. For example, > Clojure doesn't have structural or parametric types because of its > dynamic nature. There would be no *need* to infer any type parameters > on calls out to Java, so the type system could be treated as nominal. > > The algorithm I'm thinking of would be something like this: > > * Maintain a multi-map of method and field names to classes (this > could be done incrementally based on what classes the compiler knows > are in scope) > * For each parameter with an unfixed type: >* Traverse the FnExpr AST and find all Java member access to that > parameter >* For each access, obtain a set of possible classes from the scope > multi-map >* At each step, intersect the previous set of possible classes with > the subsequent one (think: a fold) >* Final set can be optimized by choosing the most-specific type > (eliminating the inheritance case) >* If the final set has size of 1, then the type has been inferred > and can be used to avoid reflection >* If the set has size 0, then fallback on reflection >* If the set has size >1, either fallback on reflection or get more > sophisticated > > Improvements on this could be added to the >1 case where the second > pass could look for methods of a given name *and* a specific arity. > Subsequent passes could also incorporate inferred types for the method > parameters. > > It's not a complete inference algorithm, but it doesn't have to be. > There's nothing stopping Clojure from falling back on reflection for > unfixed types. The whole logic behind this dance is to avoid > reflection as much as possible, producing a fairly serious > optimization in Java-interop without requiring those ugly type > annotations. > > I briefly looked at implementing this myself, but Clojure's compiler > code is...well, it's a compiler. :-) At first glance, I couldn't > even figure out where to place the appropriate hooks to kick off this > process. A better question though is: has this been tried/considered > before? What are your overall thoughts with regards to this? It's not a bad idea, and I'm sure Clojure could do more inference than it does, but the devil's in the details as usual. You'd want the least specific type. The best you could do is make a type-inferred fastpath, since you could always be wrong: In the case above, let's say you had imported Class (actually Clojure did that for you), and nothing else you imported had getName and getModifiers methods. Making the inference 'must be Class' could be wrong, since the function should work fine on java.lang.reflect.Method, for instance, and maybe that was the intent. So you'd need a runtime instanceof test for Class, and use the fastpath if true, reflection if not. Perf could be harder to pin down, as adding an import could cause previously fast code to get slow. Calls can be made only in specific conditional branches, which some higher-level logic might understand maps to non-overlapping types, so the inference should be of the call site, not the parameter itself - i.e. it's perfectly fine to write fns that expect a set of unrelated types, without being duck-typed. In fact it's even ok to type hint it even though the hint is only correct in one path. You have to allow for by-name duck-type calls or call them out specifically. Right now they are allowed. I think a simple version of this would be easy to do, when I get some time. I think it hasn't been a priority as it takes very few hints at the moment to remove reflection, given that types are tracked from calls to new and static calls, and from any other hinted calls. But it would be great to not need them at all! 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 To unsubs
Re: A trivial question about type and class
On Nov 6, 7:50 am, mb <[EMAIL PROTECTED]> wrote: > Hi, > > On 6 Nov., 13:30, Chanwoo Yoo <[EMAIL PROTECTED]> wrote: > > > > Is {:a 1} not a hash-map? It seems that there is some inconsistency... > > Clojure holds promises about the interface and the performance > characteristics of the provided functions. In general Clojure is > a lot about abstract interfaces. The underlying thing may change > as necessary to provide the best implementation for the specific > case. > > An array map may be good for maps with a very small number of > entries, but inappropriate for maps with a big number of entries. > Since Clojure only promises the interface, it's free to decide > that assoc should now return a converted map for performance > reasons. > > At least this is the impression I got from Rich's talk at - I think - > the Boston Lisp Group. I think he mentioned something like this. > Please correct me if I'm wrong. > You are right - this is the correct answer to the question. Clojure is about programming to abstractions, among other things. So you don't want to rely on the exact concrete types of things, but rather the interfaces they implement. There are many useful interfaces in Clojure. Chouser put together a nice visualization: http://clojure.googlegroups.com/web/chart.png If you use class as a dispatch function in a multimethod, you can use an interface, like IPersistentMap, as a dispatch value and it will match all classes that extend IPersistentMap, since multimethod dispatch uses isa? There are also predicates that correspond to most of the interfaces, like map?, list?, vector?, sorted? etc, all of which internally use (instance? someInterface x). The aforementioned chart includes the corresponding predicates. In general, it is bad style to use class equality, as in (= (class this) (class that)) - better to use instance? or isa?. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: sort with custom comparator
On Nov 6, 2008, at 7:05 AM, [EMAIL PROTECTED] wrote: > > On Nov 6, 12:43 pm, Rich Hickey <[EMAIL PROTECTED]> wrote: >> On Nov 6, 5:23 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> >> wrote: >> >>> To answer my own question - AFn.java implements >>> java.util.Comparator. >> >> That is documented here: >> >> http://clojure.org/special_forms > > "IFns implement the Java Callable, Runnable and Comparator > interfaces." > > Pedantically speaking IFn extends Callable and Runnable, and AFn > implements IFn and additionally Comparator (and Serializable). I was > checking IFn.java first but couldn't see the Comparator interface > being listed there which made me writing my initial post. Now reading > the sentence above I wonder if it counts as a bug that IFn doesn't > extend from Comparator? > It's a documentation bug - it should say fns and not IFns, and now does. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: sort with custom comparator
On Nov 6, 5:23 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > To answer my own question - AFn.java implements java.util.Comparator. > That is documented here: http://clojure.org/special_forms 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
On Nov 5, 4:13 pm, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 5, 12:00 pm, Mibu <[EMAIL PROTECTED]> wrote: > > > Why can't we debate whether a license is needed at all for a > > free project? > > (Too idealistic? Hey, it's a flame war. Just playing by the rules...) > > This is sounding awfully trollish of you. I didn't start this thread > to cause a "flame war". My apologies to Rich and others if it seemed > that way. I genuinely care about removing barriers to open source > interoperability. My motives are pure. > I'll grant that as true, and would like to end the current discussion for now, as it's gone on pretty long and has run out of productive content. This list has been free of 'wars' and I'd like to keep it that way. Here's where I stand with Clojure's licensing: For the short term, it's going to remain CPL. The next likely candidate would be EPL, CPL's successor, in wide use by Eclipse et al, and acceptable to Google Code. If the EPL and GPL folks can hammer out compatibility, great. Until then, I'll not let it become my problem. I will not be using any 'customized' license. Using a well known license intact is the only way to make it easy for users to vet the license for use. Anything else requires lawyers for me and them. I will not be dual licensing with GPL or LGPL. Both licenses allow the creation of derived works under GPL, a license I cannot use in my work. Allowing derived works I cannot use is not reciprocal and make no sense for me. Thanks to all for your opinions - let's move on. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: STM criticisms from Bryan Cantrill (Sun)
On Nov 4, 1:22 pm, "Raoul Duke" <[EMAIL PROTECTED]> wrote: > hi, > > > Though I don't know much about TMs, I will grant that I have not > > actually seen such tools for TMs, so your argument probably still > > holds, but I don't think it will hold forever. > > it is an interesting thing: the ecosystem of tools and things in the > crappy shared mutable state world is large and advanced, especially if > you have $$$ to throw at the problem (e.g. Azul's tools). which might > make it harder for the new idea to get fast and wide adoption. still, > one can hope that somehow the time + energy + resources somehow get > applied to making TM tools. > > sincerely. > > p.s. in java you can write a little thread which detects deadlock in > any other threads, so you can see it right away. we have such a thing > in our server code at the moment. Once detected, a deadlock can still be a bear to reproduce/debug, and often does not appear until the worst possible time - production. What's even more insidious is the memory not accessed under a lock that should have been, and the ensuing corruption. Contrast this with STM+refs, where there is no avoiding using transactions for writes. As far as livelock, if you get it to happen it is usually due to long-running transactions competing with short ones, and you can readily see/reproduce it under test loads. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Swing GUI Builder and Clojure
On Nov 4, 11:56 am, Justin Henzie <[EMAIL PROTECTED]> wrote: > My preference is that the book focuses on the default java stack. > +1 I know people have built UIs with Netbean's Matisse, which is supposed to be very good, and wired them up with Clojure. IMO that's a promising approach. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
On Nov 4, 2008, at 11:37 AM, Matthias Benkard wrote: > > On Nov 4, 1:35 pm, Rich Hickey <[EMAIL PROTECTED]> wrote: >> So far, you are only the third person to complain about lack of GPL >> compatibility. > > For the sake of balance, I _am_ actually concerned about the CPL > because it effectively denies developers the freedom to be politically > unneutral. > > Let's say I want to write a library that may only be used by free > software, out of political reasons. (That should be okay, right? > It's my code, after all.) The natural license choice in this case is > the GPL, which is widely used and makes my new library compatible with > all the other GPL-compatibly licensed stuff out there. > > The CPL doesn't allow me to choose the GPL. You've got this completely backwards - the GPL doesn't allow you to combine with certain things, whereas the CPL is fine with it. > Instead, it forces me to > apply a CPL-compatible, GPL-like license -- a thing which may or may > not currently exist, but which will certainly make my library useless > to almost everybody because without GPL compatibility, it in turn > forces a non-GPL-compatible license onto my library's users, who will > probably want to make use of GPL-licensed libraries as well as mine. Completely untrue - the CPL makes no requirements whatsoever on libraries with which it is combined. The problem lies with GPL. > > If it was only about Clojure, it wouldn't be so bad, since because of > the license conflict, there can't be any GPL-licensed Clojure > libraries out there. But it's not just Clojure -- it's about all of > the Java ecosystem. > > That's also why your suggestion to ask the authors of a GPL'd library > to LGPL it seems to me a bit unrealistic. After all, the authors > probably released the library under the GPL out of political reasons, > so they're unlikely to hamper their political motives by changing the > license. Then they (and their consumers) have to live with the effects of the choices they make and not blame others for making different choices. > > > Therefore, by choosing the CPL, you're making a political statement > against a sizable part of the Free Software movement. This ought not > to be done without thorough consideration, I think. > I'm not making any statement. Some people who choose the GPL end up with restrictions about which they are unhappy. LGPL and classpath exceptions exist for a reason. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Back on max again...
On Nov 4, 9:00 am, "Christian Vest Hansen" <[EMAIL PROTECTED]> wrote: > On Tue, Nov 4, 2008 at 1:45 PM, Rich Hickey <[EMAIL PROTECTED]> wrote: > > > On Nov 4, 2:56 am, "Christian Vest Hansen" <[EMAIL PROTECTED]> > > wrote: > >> On Tue, Nov 4, 2008 at 6:23 AM, Mark H. <[EMAIL PROTECTED]> wrote: > > >> > On Nov 3, 6:48 pm, Cosmin Stejerean <[EMAIL PROTECTED]> wrote: > >> >> I think clearly spelling out how objects of a type should be sorted is > >> >> the point of the Comparable interface. > > >> > Ah, yes, this is true, I hadn't realized that String and Date both > >> > implement Comparable. Comparable is supposed to impose a total > >> > ordering on a set, so in a finite set of objects of the same type, the > >> > max is always well defined. > > >> +1 on (min) and (max) operating on Comparables. > > > Hmm... > > > Do you want: > > > (max 1 2.1 4/5) > > > to work? > > > If so, you can't base it on Comparable, which generally only supports > > homogenous types. > > "Generally" by custom but not required by contract of the Comparable > interface. And those are all Numbers, right? > > Comparable imposes natural ordering, and the individual implementor is > free to decide how to handle objects of different types; throwing a > ClassCastException only being one of the possible reactions. > True, except the individual implementors of Integer, Long, Double etc have already decided to have them compare only to their exact type, so we're stuck with that fact. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: STM criticisms from Bryan Cantrill (Sun)
On Nov 4, 3:47 am, "Christian Vest Hansen" <[EMAIL PROTECTED]> wrote: > Just reading through the first CACM article, they raise a number of > issues that I think are more addressed in Clojure than they give > credit to TMs in general based on whatever implementation they were > investigating. > > I present my feeble attempt to join the TM debate: > > > TM introduces a variety of programming issues that > > are not present in lock-basedmutual exclusion. > > For example, semantics are muddled by: > >* Interaction with non-transactional codes, > > including access to shared data from outside > > of a transaction (tolerating weak atomicity) > > and the use of locks inside a transaction > > (breaking isolation to make locking operations > > visible outside transactions); > > The referencing part is at least clearly defined: outside a > transaction, the refs are read-only. > > Locking is a different beast. While true that it is a side-effect that > will creep to the outside world, I don't see how a lock inside a > transaction is bad in any way that a lock outside a transaction is > not. (But they might have yet to tell me since still not through with > the paper.) > > >* Exceptions and serializability: how to handle > > exceptions and propagate consistent exception > > information from within a transactional context, > > and how to guarantee that transactional execution > > respects a correct ordering of operations; > > A consistent snapshot of the world is presented inside a transaction. > Exceptions and serialization will be based on that world view. > > I don't get what they mean by correct ordering of operations. Ordering > inside a transaction would matter just as much as it does in a > single-threaded scenario, would it not? > > >* Interaction with code that cannot be > > transactionalized, due to either communication > > with other threads or a requirement barring > > speculation; > > Just don't do that. Transactions are not a silver bullet. Use an agent > instead. > > >* Livelock, or the system guarantee that all > > transactions make progress even in the > > presence of conflicts. > > True, TMs don't solve this for you. Just like locking doesn't solve > deadlocks for you. > > A key assumption of the paper seems to be that TMs are the solution to > all things concurrency. But perhaps this is exactly the myth they are > trying to debunk? > Exactly my problem with these articles - they sum up to "STM is bad because it's not a panacea". I don't actually see many people claiming it is. Furthermore, STM is not a single thing and more than is GC. There will be many flavors with different tradeoffs and properties. > My view is that TMs are another tool in the box, just like CAS, locks, > agents, volatile, thread-locals, immutables, atomics and all the rest > of java.util.concurrent. Precisely. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Back on max again...
On Nov 4, 2:56 am, "Christian Vest Hansen" <[EMAIL PROTECTED]> wrote: > On Tue, Nov 4, 2008 at 6:23 AM, Mark H. <[EMAIL PROTECTED]> wrote: > > > On Nov 3, 6:48 pm, Cosmin Stejerean <[EMAIL PROTECTED]> wrote: > >> I think clearly spelling out how objects of a type should be sorted is > >> the point of the Comparable interface. > > > Ah, yes, this is true, I hadn't realized that String and Date both > > implement Comparable. Comparable is supposed to impose a total > > ordering on a set, so in a finite set of objects of the same type, the > > max is always well defined. > > +1 on (min) and (max) operating on Comparables. > Hmm... Do you want: (max 1 2.1 4/5) to work? If so, you can't base it on Comparable, which generally only supports homogenous types. max, like >, is a numeric operation as it stands, for the above and speed reasons. If you want a general greatest/least based on Comparable (or better yet Clojure's compare), I'm not opposed, but it should probably be a different thing. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
On Nov 4, 1:11 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 3, 12:36 pm, Matthias Benkard <[EMAIL PROTECTED]> wrote: > > > Yes, it's worth worrying about. The problem is, you're going to have > > the danger of fragmenting the Clojure user base. > > I think Clojure has potential to become *very much* more well known > and used. > Are we sure we want to risk going down this route when things are an > order of magnitude harder? (Think Mozilla.) > There is not the same risk for Clojure, as all of the contributions are covered by a CA that allows me to dual license down the road if it becomes useful to do so. So far, you are only the third person to complain about lack of GPL compatibility. I would turn it around and say - if there is something you want to combine with Clojure that is GPL why don't you ask them to make it LGPL instead, in which case there would be no problem? The problem lies with GPL. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: [EMAIL PROTECTED]
On Nov 2, 11:35 pm, David Hilton <[EMAIL PROTECTED]> wrote: > On Oct 22, 5:15 am, Krukow <[EMAIL PROTECTED]> wrote: > > > Rich, > > > Was this presentation recorded? Any chance you can upload the slides > > and/or video for those of us that didn't participate in Lisp50. > > > Thanks > > - Karl > > I'd also be interested in seeing the Lisp50 presentation (I missed it > because I had SV hours scheduled at the time). > > I just noticed that the Boston Lisp presentation on Clojure has been > posted (http://clojure.blogspot.com/). How similar were the two > presentations? > The Boston Lisp presentation, at 4x the length, was significantly more detailed and interactive, and what I would recommend if you have the time. If you've already seen it, the Lisp50 talk won't add much - probably most interesting in the context of the entire day's talks. I didn't record the Lisp50 talk, but all of the talks were recorded and will eventually end up somewhere, I'll post when I know they are available. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concerned about Clojure's license choice.
On Nov 2, 7:12 pm, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On Nov 2, 1:56 pm, ".Bill Smith" <[EMAIL PROTECTED]> wrote: > > > For an earlier discussion of this same topic, > > seehttp://groups.google.com/group/clojure/browse_thread/thread/735aa7f1c... > > > Bill > > I agree that GPL incompatibility isn't a concern for Clojure *users*. > > It would be a practical problem for others however. As 'a r' > mentioned, it would be problem for someone wanting to share or pull in > other libraries. > > All I'm saying is a lot of FUD could be avoided with MIT or BSD. > MIT and BSD are not reciprocal licenses. I want a reciprocal license. But I don't want the license to apply to, or dictate anything about, non-derivative work that is combined with mine, as GPL does. I think doing so is fundamentally wrong. The fact that GPL is not compatible with that approach is a problem with GPL, and for users of GPL software. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Defining own data types on top of Persistent ones
On Oct 31, 1:20 pm, André Thieme <[EMAIL PROTECTED]> wrote: > In #Clojure Rich mentioned today that we can define our own data > structures on top of the existing ones. > Maybe someone wants/needs his own version of vectors that rearrange > automatically in some specific order or whatever. > > If I now want to add something that works nearly like lists, but a > little bit different, and for which I can use all functions that work > for lists, I will have to use a proxy. > Chris Houser implemented a little helper > tool:http://paste.lisp.org/display/67122#1 > > Now what I would like to see are some minimal examples on how to do > that. Lists are a good candidate as they only have 6 methods which we > need to implement: > > user> (show clojure.lang.IPersistentList) > === #=clojure.lang.IPersistentList === > [ 0] cons : interface clojure.lang.IPersistentCollection (1) > [ 1] count : int (0) > [ 2] empty : interface clojure.lang.IPersistentCollection (0) > [ 3] peek : class java.lang.Object (0) > [ 4] pop : interface clojure.lang.IPersistentStack (0) > [ 5] seq : interface clojure.lang.ISeq (0) > nil > > The numbers in parens at the end tell us how many parameters the > methods should have. They have a hidden one more. We can magically > use “this”. > > Here is what I tried: > > user> (defn make-lyst [& items] > (proxy [clojure.lang.IPersistentList] [] >(cons [obj] (cons obj this)) >(count [] (count this)) >(empty [] ()) >(peek [] 5) >(pop [] 6) >(seq [] this))) > > As I found no examples yet, I was hoping this would return an instance > of my own list type. > (make-lyst 1 2 3) would print like normal lists: (1 2 3) > And it would use the cons function of lists, dito for counting. > (empty lyst) would return an empty IPersistentList, peek always a 5, > pop > always a 6 and seq the list object itself. > > But unfortunately (make-lyst 1 2 3) ==> > java.lang.ClassCastException: clojure.lang.Proxy__5307 cannot be cast > to clojure.lang.ISeq > > Any ideas how this should be done so that it will work? It's still unclear to me what you want to do, e.g. you don't use items in your implementation, count as written is an infinite loop etc. But the cause of your error is that you are saying that this proxy is its own seq (by returning this from seq). In order to do that, the proxy has to implement ISeq as well. If you want seq to pass over items it might be better to implement it as (seq [] (seq items)) It seems to me in all places in which you use 'this you really meant to say items, and should. 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---