The Application Context Pattern
Some of the reaction for Waterfront was related to the Application Context Pattern (ACP) - The pattern that allows most of Waterfront's code to be purely functional. I'll try to explain the basics in this post. Let me start with the motivation: the reason why FP is at odds with GUI code. (Pure) Functional code has no side effects, which implies immutability of state. There are no fields nor global variables that can be assigned to. Thus, one function can affect the computation carried out by another function only by the passing of parameters. Most GUI systems are built around the notion of event handlers which are invoked by a message processing loop. There is no chain of calls from one event handler to another. In particular, if handler "A" computed some new value it cannot pass it on to handler "B" because the system will call "B" only after "A" returns. That's the predicament. ACP overcomes this by capturing the applications current state in an immutable map. All event handlers receive a single parameter which is the "current" context and compute the "new" context. A typical handler (henceforth: "context processing function") will carry out these activities: (a) Examine the current context; (b) Perform some GUI operations (setSize, setText, etc.); (c) Compute a new context based on the current context and on information obtained from the GUI (getText, etc.). The caller (henceforth: "dispatcher") takes the returned context and will use it as the new current context, the next time a context processing function is invoked. This means that when you register event handler with a Swing widget the handler needs to to call the ACP dispatcher passing it a context processing function. The net effect of this approach is that only the dispatcher has to deal with mutable state. The context processors are functional: they merely compute the new state from the current. application-context-pattern.clj (http://groups.google.com/group/ clojure/web/application-context-pattern.clj) shows a concrete example. It's about 140 LOC (ripped off from the real Waterfront codebase) structured as follows: Lines 1..40: General-purpose helpers. Lines 40..90: The ACP infrastructure Lines 90..140: A quick sample, built around ACP. The sample program opens a JFrame with two buttons: Input and Output. A click on the input button will pop-up an input dialog box. A click on the output button will pop-up a message box showing the last value entered into the input box. There's also a JLabel showing the length of the input, but let's ignore it for the moment. The entry point into the ACP world is the bootstrap function. It takes two parameters: a context processing function and an initial context. In the example, this is carried out at the bottom of the run-it function: (defn run-it [] (let [build-ui (fn [ctx] (let [f (javax.swing.JFrame. "Frame") b-in (javax.swing.JButton. "Input") b-out (javax.swing.JButton. "Output")] (.addActionListener b-in (new-action-listener (fn [event] ((ctx :dispatch) get-input (.addActionListener b-out (new-action-listener (fn [event] ((ctx :dispatch) show-output (.setLayout f (java.awt.FlowLayout.)) (doseq [x [b-in b-out]] (.add f x) ) (doto f (.setSize 500 300) (.setDefaultCloseOperation javax.swing.JFrame/ DISPOSE_ON_CLOSE) (.setVisible true)) (assoc ctx :frame f) ))] (invoke-later #(bootstrap build-ui {})) )) invoke-later is a utility function that is mapped to SwingUtilities/ invokeLater. Let's drill down into the build-ui function: It takes the current context (ctx parameter). Then it creates the frame and the buttons. It uses new-action-listener (another utility) to register an action listener with the buttons. The first listener looks like this: ((ctx :dispatch) get-input It uses (ctx :dispatch) to obtain the dispatcher from which ctx was obtained, and evaluates it passing get-input as the context processing function. The call to bootstrap initialized this dispatcher and added the :dispatch mapping to the initial context. get-input looks like this: (defn- get-input [ctx] (let [reply (javax.swing.JOptionPane/showInputDialog nil "Type in something")] (assoc ctx :user-input reply) )) It pops-up an input box, and returns a new context which is the same as the current context except that :user-input is now mapped to value returned from the input box. show-output is the context processing function for the output button: (defn- show-output [ctx] (javax.swing.JOptionPane/showMessageDialog nil (ctx :user- input)) ) Note that show-output returns nil which the dispatcher interprets as "no change to ctx". What we have is that get-input communicates with show-output by returning a new context. There's no assignment into atoms or the likes. The mutable state is encapsulated within the dispatcher. It is now t
Re: Please help me get rid of my mutable code.
Hi, I just posted about the application context pattern. I believe it addresses the issue you're describing. -Itay On Feb 27, 4:21 am, CuppoJava wrote: > Hi, > After having used Clojure for a few months now, I'm still having lots > of trouble separating my mutable code from my immutable code. My use- > case is pretty typical I think, so I'm wondering what sort of > structure everyone else is using. > > Here's my current structure. > > I have an engine that manages a list of sprites. The engine runs in a > loop and updates all the sprites incrementally sixty times a second. > When an event occurs, the engine notifies each sprite. When a sprite > receives an event, it processes it, and then notifies each of it's > listeners. Typical Java event listener model. > > Well this scheme has mutability written all over it. > I'm currently representing sprites as references of immutable maps. So > my code is literally littered with (dosync) instructions. > > How would I go about separating my mutable code from my immutable > code? I think I need a completely different angle to attack the > problem? > > Thanks a lot for the help > -Patrick --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: namespace docstrings
Hi, Am 27.02.2009 um 08:20 schrieb Konrad Hinsen: I have been trying in vain to get the namespace docstring of anything with print-namespace-doc. It doesn't say what exactly it wants as an argument (a symbol, a string, or a namespace object), but it calls ns-name, which wants a symbol, so I give it a symbol. But the symbol doesn't have any metadata. I went on to look for namespace-related metadata elsewhere, but the namespace object doesn't have any either. Of course I looked at namespaces that actually have docstrings in their source code (for example clojure.contrib.types). So where does the namespace docstring go? I suppose where it belongs: Clojure 1:1 user=> (require 'clojure.contrib.types) nil 1:2 user=> (doc clojure.contrib.types) - clojure.contrib.types nil nil 1:3 user=> (doc clojure.core) - clojure.core Fundamental library of the Clojure language nil 1:4 user=> (ns foo.bar "A Foobar namespace") nil 1:5 foo.bar=> (doc foo.bar) - foo.bar A Foobar namespace nil The only difference between clojure.contrib.types and foo.bar is, that foo.bar is defined at the Repl. clojure.contrib.types is defined in a file, which is then loaded. The same is true for clojure.core, but here the meta data is set via alter-meta and it is not loaded the "usual" way with require. It seems, the metadata gets lost somehow. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Please explain
On the page describing Vars, I cannot get the meaning of this sentence (a typo has made it incomprehensible I think): "Bindings created with binding can be assigned to, which provides a means for nested contexts to communicate with code before it the call stack." Thanks --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Please take mercy on us newbies
Can I make a small plea for people who submit source code to PLEASE insert some sort of explanation of what the code is about. I know it's usual in programming circles to think that if someone can't understand something it's because they are dumb - but really - this is a terribly inefficient way of communicating and also rather arrogant. Please don't take this as the start of a war! Best regards --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
What are you talking about ? It's really vague. It seems to me that people in this list have always been kind to help people discovering the language. And if you turn it the other way around, maybe people are not always explaining each line of code because they don't presuppose that readers will mainly be "dumb" or whatever term you want to use? And also people are taking time to give hints to the person asking, but each one's time is precious (most -if not all- people in this list are not paid for answering questions). If there's something you don't understand, have no complex and ask for further explanation ! Regards, -- Laurent 2009/2/27 timc > > Can I make a small plea for people who submit source code to PLEASE > insert some sort of explanation of what the code is about. > > I know it's usual in programming circles to think that if someone > can't understand something it's because they are dumb - but really - > this is a terribly inefficient way of communicating and also rather > arrogant. > > Please don't take this as the start of a war! > > Best regards > > > --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please explain
Here's an example: user> (def x) #'user/x user> (defn foo [] (set! x 10)) #'user/foo user> (binding [x 1] [x (binding [x 2] [x (do (foo) x)]) x]) [1 [2 10] 1] Foo passes information to the calling form by assigning to x, within the innermost binding only. It sounds like the quote should say "before it [in] the call stack". -Jason On Feb 27, 1:08 am, timc wrote: > On the page describing Vars, I cannot get the meaning of this sentence > (a typo has made it incomprehensible I think): > > "Bindings created with binding can be assigned to, which provides a > means for nested contexts to communicate with code before it the call > stack." > > Thanks --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
OK - choosing files at random: Is it at all obvious what these do? app.clj application-context-patter.clj binary-structure.clj bookmark-tut.clj bsptree.clj chlam-clean-clj and so on... On Feb 27, 9:20 am, Laurent PETIT wrote: > What are you talking about ? It's really vague. > > It seems to me that people in this list have always been kind to help people > discovering the language. > And if you turn it the other way around, maybe people are not always > explaining each line of code because they don't presuppose that readers will > mainly be "dumb" or whatever term you want to use? > > And also people are taking time to give hints to the person asking, but each > one's time is precious (most -if not all- people in this list are not paid > for answering questions). > > If there's something you don't understand, have no complex and ask for > further explanation ! > > Regards, > -- > Laurent > > 2009/2/27 timc > > > > > Can I make a small plea for people who submit source code to PLEASE > > insert some sort of explanation of what the code is about. > > > I know it's usual in programming circles to think that if someone > > can't understand something it's because they are dumb - but really - > > this is a terribly inefficient way of communicating and also rather > > arrogant. > > > Please don't take this as the start of a war! > > > Best regards --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
Hi, Am 27.02.2009 um 10:41 schrieb timc: OK - choosing files at random: Is it at all obvious what these do? app.clj application-context-patter.clj binary-structure.clj bookmark-tut.clj bsptree.clj chlam-clean-clj and so on... I guess for almost all of these files there is a thread in the group discussing their content. Or at least giving some context. I recommend that you search the group archives for the filename and you will digg out quite some information. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: Mathy operations on non-numerics (was "Adding" strings)
On Fri, Feb 27, 2009 at 12:47 AM, Allen Rohner wrote: > > >> I agree regarding concatenation as well, but I think the case for >> comparison of non-numerics is still pretty strong. >> >> -Phil > > Are you referring to using <, >, =, with objects that implement > java.lang.Comparable? > > i.e. given x.compareTo(y) == -1 > (< x y) > => true > > I would find that useful. I think having <, >, <=, >= be based on Comparable has been discussed before. And the conclusion was that it was a bad idea, because in Java: user=> (.compareTo (Integer. "10") (Long. "10")) java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer (NO_SOURCE_FILE:0) And: user=> (.equals (Integer. "10") (Long. "10")) false Whereas in Clojure: user=> (< (Integer. "10") (Long. "10")) false user=> (= (Integer. "10") (Long. "10")) true Given these consequences, I think the current behavior is the best compromise. > > Allen > > > > -- Venlig hilsen / Kind regards, Christian Vest Hansen. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: The Application Context Pattern
thanks, this will be very useful for me On 27 Feb, 09:05, Itay Maman wrote: > Some of the reaction for Waterfront was related to the Application > Context Pattern (ACP) - The pattern that allows most of Waterfront's > code to be purely functional. I'll try to explain the basics in this > post. Let me start with the motivation: the reason why FP is at odds > with GUI code. > > (Pure) Functional code has no side effects, which implies immutability > of state. There are no fields nor global variables that can be > assigned to. Thus, one function can affect the computation carried out > by another function only by the passing of parameters. Most GUI > systems are built around the notion of event handlers which are > invoked by a message processing loop. There is no chain of calls from > one event handler to another. > In particular, if handler "A" computed some new value it cannot pass > it on to handler "B" because the system will call "B" only after "A" > returns. That's the predicament. > > ACP overcomes this by capturing the applications current state in an > immutable map. All event handlers receive a single parameter which is > the "current" context and compute the "new" context. A typical handler > (henceforth: "context processing function") will carry out these > activities: (a) Examine the current context; (b) Perform some GUI > operations (setSize, setText, etc.); (c) Compute a new context based > on the current context and on information obtained from the GUI > (getText, etc.). The caller (henceforth: "dispatcher") takes the > returned context and will use it as the new current context, the next > time a context processing function is invoked. > > This means that when you register event handler with a Swing widget > the handler needs to to call the ACP dispatcher passing it a context > processing function. > > The net effect of this approach is that only the dispatcher has to > deal with mutable state. The context processors are functional: they > merely compute the new state from the current. > > application-context-pattern.clj (http://groups.google.com/group/ > clojure/web/application-context-pattern.clj) shows a concrete example. > It's about 140 LOC (ripped off from the real Waterfront codebase) > structured as follows: > Lines 1..40: General-purpose helpers. > Lines 40..90: The ACP infrastructure > Lines 90..140: A quick sample, built around ACP. > > The sample program opens a JFrame with two buttons: Input and Output. > A click on the input button will pop-up an input dialog box. A click > on the output button will pop-up a message box showing the last value > entered into the input box. There's also a JLabel showing the length > of the input, but let's ignore it for the moment. > > The entry point into the ACP world is the bootstrap function. It takes > two parameters: a context processing function and an initial context. > In the example, this is carried out at the bottom of the run-it > function: > > (defn run-it [] > (let [build-ui (fn [ctx] > (let [f (javax.swing.JFrame. "Frame") > b-in (javax.swing.JButton. "Input") > b-out (javax.swing.JButton. "Output")] > > (.addActionListener b-in (new-action-listener (fn [event] > ((ctx :dispatch) get-input > > (.addActionListener b-out (new-action-listener (fn [event] > ((ctx :dispatch) show-output > > (.setLayout f (java.awt.FlowLayout.)) > (doseq [x [b-in b-out]] > (.add f x) ) > > (doto f > (.setSize 500 300) > (.setDefaultCloseOperation javax.swing.JFrame/ > DISPOSE_ON_CLOSE) > (.setVisible true)) > > (assoc ctx :frame f) ))] > > (invoke-later #(bootstrap build-ui {})) )) > > invoke-later is a utility function that is mapped to SwingUtilities/ > invokeLater. > > Let's drill down into the build-ui function: It takes the current > context (ctx parameter). Then it creates the frame and the buttons. It > uses new-action-listener (another utility) to register an action > listener with the buttons. The first listener looks like this: > ((ctx :dispatch) get-input > > It uses (ctx :dispatch) to obtain the dispatcher from which ctx was > obtained, and evaluates it passing get-input as the context processing > function. The call to bootstrap initialized this dispatcher and added > the :dispatch mapping to the initial context. > > get-input looks like this: > (defn- get-input [ctx] > (let [reply (javax.swing.JOptionPane/showInputDialog nil "Type in > something")] > (assoc ctx :user-input reply) )) > > It pops-up an input box, and returns a new context which is the same > as the current context except that :user-input is now mapped to value > returned from the input box. > > show-output is the context processing function for the output button: > (defn- show-output [ctx] > (javax.swing.JOptionPane/showMessageDialog nil (ctx :user- > input)) ) > > Note that show-ou
Re: Please explain
On Fri, Feb 27, 2009 at 11:08 AM, timc wrote: > > On the page describing Vars, I cannot get the meaning of this sentence > (a typo has made it incomprehensible I think): > > "Bindings created with binding can be assigned to, which provides a > means for nested contexts to communicate with code before it the call > stack." I think there's just an "in" missing. i.e. I think it should be: Bindings created with binding can be assigned to, which provides a means for nested contexts to communicate with code before it _in_ the call stack. It could be a little clearer as follows: Bindings created with _the binding macro_ can be assigned to, which[...] -- Michael Wood --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please explain
On Fri, Feb 27, 2009 at 4:34 AM, Michael Wood wrote: > > On Fri, Feb 27, 2009 at 11:08 AM, timc wrote: >> >> On the page describing Vars, I cannot get the meaning of this sentence >> (a typo has made it incomprehensible I think): >> >> "Bindings created with binding can be assigned to, which provides a >> means for nested contexts to communicate with code before it the call >> stack." > > I think there's just an "in" missing. i.e. I think it should be: > > Bindings created with binding can be assigned to, which provides a > means for nested contexts to communicate with code before it _in_ the call > stack. > > It could be a little clearer as follows: > > Bindings created with _the binding macro_ can be assigned to, which[...] The word "before" is what seems out of place to me. The typically use of binding that I've seen is for binding a different value to a Var for the duration of the binding scope which includes calls that occur *after* the binding keyword, but in its scope. For example, println normally writes to stdout, but you can changes that for a limited scope with binding. (println "This goes to stdout.") (binding [*out* (java.io.FileWriter. "my.log")] (println "This goes to the log file.") (foo "bar") ; If the function foo uses println, that output will also go to the log file. (flush)) (println "Now we're back to writing to stdout.") -- R. Mark Volkmann Object Computing, Inc. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Patch for print-method
On Feb 27, 2:50 am, Konrad Hinsen wrote: > The attached patch to clojure.core fixes the printing problem for > types that have no implementation of print-method. When such objects > are printed or converted to strings, an infinite loop leads to a > stack overflow. The reason is that the :default implementation for > print-method calls str on the object, which in turn calls print- > method again. > > The path makes two changes: > > 1) The current :default implementation becomes the implementation for > Object, thus remaining the default for everything that does not have > a type field in the metadata. > > 2) A new :default implementation calls print-method recursively after > having removed the :type field from the object's metadata. > Patch applied - svn 1311 - 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please explain
On Fri, Feb 27, 2009 at 2:30 PM, Mark Volkmann wrote: > > On Fri, Feb 27, 2009 at 4:34 AM, Michael Wood wrote: [...] >> Bindings created with binding can be assigned to, which provides a >> means for nested contexts to communicate with code before it _in_ the call >> stack. [...] > > The word "before" is what seems out of place to me. The typically use > of binding that I've seen is for binding a different value to a Var > for the duration of the binding scope which includes calls that occur > *after* the binding keyword, but in its scope. For example, println > normally writes to stdout, but you can changes that for a limited > scope with binding. [...] I actually didn't think too hard about that before your e-mail :) but I think "before" is right. Jason's example demonstrates what this means: user> (def x) #'user/x user> (defn foo [] (set! x 10)) #'user/foo user> (binding [x 1] ; first binding form [x (binding [x 2] ; second binding form [x (do (foo) x)]) x]) [1 [2 10] 1] The second binding form is "before" foo in the call stack, yet foo can influence it by calling (set! x 10). I'm not sure if doing this sort of thing is a good idea, though. While reading the description again I noticed a grammatical error. I believe it should be: Bindings created with binding can be assigned to, which provides a means for a nested context to communicate with code before it in the call stack. i.e. "a ... context ... before it" rather than "contexts ... before it" -- Michael Wood --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
functions and macros in memory
Is it correct to say that each loaded function is represented by an AFn object in memory? Are macros represented in memory in the same way? -- R. Mark Volkmann Object Computing, Inc. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: unbean
On Wed, Feb 25, 2009 at 12:18 AM, .Bill Smith wrote: > The map alone is not sufficient to describe the object; you need the > class too. That's true both for the bean and any of it's bean-typed > properties, since a property might be typed with an interface or an > abstract class for which there is no constructor. You could gen-class as needed to create concrete interface implementations or subclasses. This would probably be a terrible idea if unbean were for general use, but if you're focused on testing it could keep things cleaner (and prevent you cluttering up tests with irrelevant details). I suppose the most communicative approach would be to nest unbean calls, but make unbean support abstract classes and interfaces as its first argument. (If unbean inferred the need to gen-class, you couldn't tell from reading the test code whether a property of the top-level bean were a PersistentHashMap or some non-Clojure type being figured out behind the scenes.) -hume. -- http://elhumidor.blogspot.com/ --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: functions and macros in memory
On 27.02.2009, at 14:46, Mark Volkmann wrote: > Is it correct to say that each loaded function is represented by an > AFn object in memory? Each compiled function becomes a class that extends AFn. When the function is created in the Clojure code, an object is generated from this class. If you have a function returning a function (typically a closure), there is only one class for the returned function, but there will be several instances of that class. > Are macros represented in memory in the same way? Yes. Macros are strictly the same as functions. The only difference is that the var that stores the reference has a "macro" flag set, so that the compiler knows to call it correctly. In fact, you can obtain a plain function version of a macro: (def and-as-a-function @(var and)) Of course, this is still a function that expects being called with unevaluated forms and returns a modified form. It's just called explicitly, rather than implicitly by the compiler. Konrad. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Waterfront 148 (was: Waterfront - The Clojure-based editor for Clojure)
Revision 148 is available for download at http://sourceforge.net/project/platformdownload.php?group_id=249246 It addresses some of the requests that were raised in this discussion: * Changed default location of the divider * Fixed the "command-key" issue on Macs. * Java 1.5 compilance (prev. 1.6) * Added a space in the execution time between the digits and "ms". E.g., "34ms" --> "34 ms" * Source -> Doc and Source -> Reflect consolidated into a single menu item triggered by F1 * wf.sh file added * wf.bat handles spaces in the path Thanks you Stephen, Tom, Mike and all the other for the feedback. Also, for those interested in the "application context pattern", please see a post with that title published earlier today. -Itay On Feb 26, 4:25 pm, Itay Maman wrote: > > What ? You used Eclipse, and still wanted to get rid of it and of clojuredev > > ! How sad I am ... ;-) > > :)) > > > > > I've taken a look at what you've done, wow ! > > > How long did it take to realize that ? Were you working on it daily, or > > nightly ? > > I had a couple of weeks off at Dec. Since Jan. it is mostly night- > time. > > > > > Keep up the good work ! > > Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: The Application Context Pattern
I've seen the term "skyhook" used to describe a very similar system. In any event, it looks cool. On Fri, Feb 27, 2009 at 5:24 AM, linh wrote: > > thanks, this will be very useful for me > > On 27 Feb, 09:05, Itay Maman wrote: > > Some of the reaction for Waterfront was related to the Application > > Context Pattern (ACP) - The pattern that allows most of Waterfront's > > code to be purely functional. I'll try to explain the basics in this > > post. Let me start with the motivation: the reason why FP is at odds > > with GUI code. > > > > (Pure) Functional code has no side effects, which implies immutability > > of state. There are no fields nor global variables that can be > > assigned to. Thus, one function can affect the computation carried out > > by another function only by the passing of parameters. Most GUI > > systems are built around the notion of event handlers which are > > invoked by a message processing loop. There is no chain of calls from > > one event handler to another. > > In particular, if handler "A" computed some new value it cannot pass > > it on to handler "B" because the system will call "B" only after "A" > > returns. That's the predicament. > > > > ACP overcomes this by capturing the applications current state in an > > immutable map. All event handlers receive a single parameter which is > > the "current" context and compute the "new" context. A typical handler > > (henceforth: "context processing function") will carry out these > > activities: (a) Examine the current context; (b) Perform some GUI > > operations (setSize, setText, etc.); (c) Compute a new context based > > on the current context and on information obtained from the GUI > > (getText, etc.). The caller (henceforth: "dispatcher") takes the > > returned context and will use it as the new current context, the next > > time a context processing function is invoked. > > > > This means that when you register event handler with a Swing widget > > the handler needs to to call the ACP dispatcher passing it a context > > processing function. > > > > The net effect of this approach is that only the dispatcher has to > > deal with mutable state. The context processors are functional: they > > merely compute the new state from the current. > > > > application-context-pattern.clj (http://groups.google.com/group/ > > clojure/web/application-context-pattern.clj) shows a concrete example. > > It's about 140 LOC (ripped off from the real Waterfront codebase) > > structured as follows: > > Lines 1..40: General-purpose helpers. > > Lines 40..90: The ACP infrastructure > > Lines 90..140: A quick sample, built around ACP. > > > > The sample program opens a JFrame with two buttons: Input and Output. > > A click on the input button will pop-up an input dialog box. A click > > on the output button will pop-up a message box showing the last value > > entered into the input box. There's also a JLabel showing the length > > of the input, but let's ignore it for the moment. > > > > The entry point into the ACP world is the bootstrap function. It takes > > two parameters: a context processing function and an initial context. > > In the example, this is carried out at the bottom of the run-it > > function: > > > > (defn run-it [] > > (let [build-ui (fn [ctx] > > (let [f (javax.swing.JFrame. "Frame") > > b-in (javax.swing.JButton. "Input") > > b-out (javax.swing.JButton. "Output")] > > > > (.addActionListener b-in (new-action-listener (fn [event] > > ((ctx :dispatch) get-input > > > > (.addActionListener b-out (new-action-listener (fn [event] > > ((ctx :dispatch) show-output > > > > (.setLayout f (java.awt.FlowLayout.)) > > (doseq [x [b-in b-out]] > > (.add f x) ) > > > > (doto f > > (.setSize 500 300) > > (.setDefaultCloseOperation javax.swing.JFrame/ > > DISPOSE_ON_CLOSE) > > (.setVisible true)) > > > > (assoc ctx :frame f) ))] > > > > (invoke-later #(bootstrap build-ui {})) )) > > > > invoke-later is a utility function that is mapped to SwingUtilities/ > > invokeLater. > > > > Let's drill down into the build-ui function: It takes the current > > context (ctx parameter). Then it creates the frame and the buttons. It > > uses new-action-listener (another utility) to register an action > > listener with the buttons. The first listener looks like this: > > ((ctx :dispatch) get-input > > > > It uses (ctx :dispatch) to obtain the dispatcher from which ctx was > > obtained, and evaluates it passing get-input as the context processing > > function. The call to bootstrap initialized this dispatcher and added > > the :dispatch mapping to the initial context. > > > > get-input looks like this: > > (defn- get-input [ctx] > > (let [reply (javax.swing.JOptionPane/showInputDialog nil "Type in > > something")] > > (assoc ctx :user-input reply) )) > > > > It pops-up an in
Re: The Application Context Pattern
Interesting approach, nice explained. Does anyone have similar example using one of the cells implementations? What would be pros/cons between this and cells approach? Regards, Marko Kocić --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Synchronous watches
I've added (back) synchronous watches (svn 1309+), which used to exist for agents, now for all reference types. (defn add-watch "Experimental. Adds a watch function to an agent/atom/var/ref reference. The watch fn must be a fn of 4 args: a key, the reference, its old-state, its new-state. Whenever the reference's state might have been changed, any registered watches will have their functions called. The watch fn will be called synchronously, on the agent's thread if an agent, before any pending sends if agent or ref. Note that an atom's or ref's state may have changed again prior to the fn call, so use old-state rather than derefing the reference. Note also that watch fns may be called from multiple threads simultaneously. Var watchers are triggered only by root binding changes, not thread-local set!s" [reference key fn] ...) (defn remove-watch [reference key]...) I've left in add/remove-watcher for now, in order to avoid disruption. It is defined in terms of add-watch, demonstrating add-watch is the more flexible core function. My plan is to remove add-watcher/remove- watcher, since you can build your own such variants. Highlights are: - Deterministic times when callbacks will occur. - Provision of before/after state - you determine what constitutes an interesting change. - Arbitrary key will be passed back to callback. Please try them out for your latest Cells-like and other reactive programs. I'd like to move this out of the experimental category. Feedback and questions 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
Rich, I know I could search through clojure source code for this question (and that this question is not totally related to the current thread), but could you please tell me if there is a possibility to watch for additions/removals of vars to a namespace, and additions/removals of namespaces to the "global set of namespaces". What I would like to do is being able to maintain, dynamically, a dependency graph of the files in a project and what they are really doing (thus correctly handling cases difficult or not possible at all to do via static analysis such as macros defining vars, multiple ns created per file, ns decomposed in multiple files ...). And I guess having the above mentioned facility would help for this. Are namespaces & global set of namespaces "watchable" things ? Thanks in advance, -- Laurent 2009/2/27 Rich Hickey > > I've added (back) synchronous watches (svn 1309+), which used to exist > for agents, now for all reference types. > > (defn add-watch > > "Experimental. > > Adds a watch function to an agent/atom/var/ref reference. The watch > fn must be a fn of 4 args: a key, the reference, its old-state, its > new-state. Whenever the reference's state might have been changed, > any registered watches will have their functions called. The watch > fn > will be called synchronously, on the agent's thread if an agent, > before any pending sends if agent or ref. Note that an atom's or > ref's state may have changed again prior to the fn call, so use > old-state rather than derefing the reference. Note also that watch > fns > may be called from multiple threads simultaneously. Var watchers are > triggered only by root binding changes, not thread-local set!s" > > [reference key fn] ...) > > (defn remove-watch [reference key]...) > > I've left in add/remove-watcher for now, in order to avoid disruption. > It is defined in terms of add-watch, demonstrating add-watch is the > more flexible core function. My plan is to remove add-watcher/remove- > watcher, since you can build your own such variants. > > Highlights are: > > - Deterministic times when callbacks will occur. > > - Provision of before/after state - you determine what constitutes an > interesting change. > > - Arbitrary key will be passed back to callback. > > Please try them out for your latest Cells-like and other reactive > programs. I'd like to move this out of the experimental category. > > Feedback and questions 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
Just to expand on Meikel's answer: when people upload files, it's usually as an attachment to an existing thread. Reading though the file list isn't a very good way of learning Clojure, as it's just a flat list of every file anyone has ever uploaded to the group. Without the context of the original thread, the files are naturally not going to make a lot of sense when studied in isolation. - James On Feb 27, 9:50 am, Meikel Brandmeyer wrote: > Hi, > > Am 27.02.2009 um 10:41 schrieb timc: > > > OK - choosing files at random: > > > Is it at all obvious what these do? > > > app.clj > > application-context-patter.clj > > binary-structure.clj > > bookmark-tut.clj > > bsptree.clj > > chlam-clean-clj > > > and so on... > > I guess for almost all of these files there is a thread > in the group discussing their content. Or at least > giving some context. I recommend that you search > the group archives for the filename and you will > digg out quite some information. > > Sincerely > Meikel > > smime.p7s > 5KViewDownload --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
On Feb 27, 10:13 am, Laurent PETIT wrote: > Rich, > > I know I could search through clojure source code for this question (and > that this question is not totally related to the current thread), but could > you please tell me if there is a possibility to watch for additions/removals > of vars to a namespace, and additions/removals of namespaces to the "global > set of namespaces". > > What I would like to do is being able to maintain, dynamically, a dependency > graph of the files in a project and what they are really doing (thus > correctly handling cases difficult or not possible at all to do via static > analysis such as macros defining vars, multiple ns created per file, ns > decomposed in multiple files ...). And I guess having the above mentioned > facility would help for this. > > Are namespaces & global set of namespaces "watchable" things ? > No they are not. 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Waterfront 148 (was: Waterfront - The Clojure-based editor for Clojure)
Nice work. I have a couple of (mostly cosmetic but important suggestions): - Set look and feel to NativeLookAndFeel - Allow user to increase application fonts, not just editor fonts. Regards, Marko Kocić --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
On Fri, Feb 27, 2009 at 10:14 AM, James Reeves wrote: > > Just to expand on Meikel's answer: when people upload files, it's > usually as an attachment to an existing thread. Reading though the > file list isn't a very good way of learning Clojure, as it's just a > flat list of every file anyone has ever uploaded to the group. Without > the context of the original thread, the files are naturally not going > to make a lot of sense when studied in isolation. It may also be worth noting that the code in the files section of this group isn't vetted in any way. Some may be meant for real world use while other files may be examples of a problem or be in error. Just about anyone can upload a file for just about any purpose. If you're looking for example code to help you learn clojure, there are many better options. The first that comes to mind is the several wikis -- the official wikibook link from clojure.org, a tutorial wiki, a wiki attempting to show an example of every function in clojure.core, and the clojure projecteuler wiki. All of these contain working examples with specific goals, and several of them have lots of English text describing what's going on. Another good place to look is in clojure-contrib. Code submitted there goes through a minimal vetting process and is actively maintained by people who take the time to stay current on Clojure's growing feature set. Hope that helps, --Chouser --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure plugin for IntelliJ IDEA published
On Feb 26, 7:08 pm, CuppoJava wrote: > Hello Ilya, > Thanks for the workaround. > > I'm glad to hear you're working on a "surround with" feature. Some > other parenthesis commands that I most commonly use is: > 1) Delete next Sexp. > 2) Splice Sexp. (Remove the parenthesis around the current sexp). > 3) Move cursor to next/previous sexp. Don't forget Barf and Slurp! Barf - eject an Sexp from this Sexp (front and back): (a b c) -> (a b) c (a b c) -> a (b c) Slurp - incorporate an Sexp into this Sexp (front and back): (a b) c -> (a b c) a (b c) -> (a b c) Also copy this sexp, cut this sexp. All vital! --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
Hi Rich, On Feb 27, 2:57 pm, Rich Hickey wrote: > I've added (back) synchronous watches (svn 1309+), which used to exist > for agents, now for all reference types. > > (defn add-watch > > "Experimental. > > Adds a watch function to an agent/atom/var/ref reference. The watch > fn must be a fn of 4 args: a key, the reference, its old-state, its > new-state. Could you say more about the key? Who gets to decide what it is, and what does it mean? Thanks, Anand --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
Never mind, I get it now. Thanks, Anand On Feb 27, 4:32 pm, Anand Patil wrote: > Hi Rich, > > On Feb 27, 2:57 pm, Rich Hickey wrote: > > > I've added (back) synchronous watches (svn 1309+), which used to exist > > for agents, now for all reference types. > > > (defn add-watch > > > "Experimental. > > > Adds a watch function to an agent/atom/var/ref reference. The watch > > fn must be a fn of 4 args: a key, the reference, its old-state, its > > new-state. > > Could you say more about the key? Who gets to decide what it is, and > what does it mean? > > Thanks, > Anand --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please help me get rid of my mutable code.
Thanks very much Itay, I'm reading through your post very carefully. I sounds like it's the answer to all my problems. -Patrick --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mathy operations on non-numerics
Christian Vest Hansen writes: >> Are you referring to using <, >, =, with objects that implement >> java.lang.Comparable? >> >> i.e. given x.compareTo(y) == -1 >> (< x y) >> => true >> >> I would find that useful. > > I think having <, >, <=, >= be based on Comparable has been discussed before. > > And the conclusion was that it was a bad idea, because in Java: > > user=> (.compareTo (Integer. "10") (Long. "10")) > java.lang.ClassCastException: java.lang.Long cannot be cast to > java.lang.Integer (NO_SOURCE_FILE:0) > > And: > > user=> (.equals (Integer. "10") (Long. "10")) > false Curses, Java! Foiled again. > Given these consequences, I think the current behavior is the best compromise. Agreed. Am curious as to what the idiomatic way to check to see if one string is alphabetically greater than another is though. -Phil --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Waterfront 148 (was: Waterfront - The Clojure-based editor for Clojure)
On Feb 27, 5:22 pm, Marko Kocić wrote: > Nice work. > > I have a couple of (mostly cosmetic but important suggestions): > - Set look and feel to NativeLookAndFeel I'm not sure I understand. Are you referring to UIManager.getSystemLookAndFeelClassName() ? This is the L&F that Waterfront is using. If you don't get this L&F then perhaps the call to setLookAndFeel() fails on your machine. I'll add a piece of code to log the exception. -Itay > - Allow user to increase application fonts, not just editor fonts. > > Regards, > Marko Kocić --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Please take mercy on us newbies
Thanks for the responses - very helpful. On Feb 27, 3:24 pm, Chouser wrote: > On Fri, Feb 27, 2009 at 10:14 AM, James Reeves > > wrote: > > > Just to expand on Meikel's answer: when people upload files, it's > > usually as an attachment to an existing thread. Reading though the > > file list isn't a very good way of learning Clojure, as it's just a > > flat list of every file anyone has ever uploaded to the group. Without > > the context of the original thread, the files are naturally not going > > to make a lot of sense when studied in isolation. > > It may also be worth noting that the code in the files section of this > group isn't vetted in any way. Some may be meant for real world use > while other files may be examples of a problem or be in error. Just > about anyone can upload a file for just about any purpose. > > If you're looking for example code to help you learn clojure, there > are many better options. > > The first that comes to mind is the several wikis -- the official > wikibook link from clojure.org, a tutorial wiki, a wiki attempting to > show an example of every function in clojure.core, and the clojure > projecteuler wiki. All of these contain working examples with > specific goals, and several of them have lots of English text > describing what's going on. > > Another good place to look is in clojure-contrib. Code submitted > there goes through a minimal vetting process and is actively > maintained by people who take the time to stay current on Clojure's > growing feature set. > > Hope that helps, > --Chouser --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mathy operations on non-numerics
What about something like: (defn gt [str1 str2] (first (sort [str1 str2]))) (gt "Zoe" "Bob") ; -> "Bob" On Fri, Feb 27, 2009 at 12:03 PM, Phil Hagelberg wrote: > > Christian Vest Hansen writes: > > >> Are you referring to using <, >, =, with objects that implement > >> java.lang.Comparable? > >> > >> i.e. given x.compareTo(y) == -1 > >> (< x y) > >> => true > >> > >> I would find that useful. > > > > I think having <, >, <=, >= be based on Comparable has been discussed > before. > > > > And the conclusion was that it was a bad idea, because in Java: > > > > user=> (.compareTo (Integer. "10") (Long. "10")) > > java.lang.ClassCastException: java.lang.Long cannot be cast to > > java.lang.Integer (NO_SOURCE_FILE:0) > > > > And: > > > > user=> (.equals (Integer. "10") (Long. "10")) > > false > > Curses, Java! Foiled again. > > > Given these consequences, I think the current behavior is the best > compromise. > > Agreed. Am curious as to what the idiomatic way to check to see if one > string is alphabetically greater than another is though. > > -Phil > > > > --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mathy operations on non-numerics
Hi! Am 27.02.2009 um 18:03 schrieb Phil Hagelberg: > Agreed. Am curious as to what the idiomatic way to check to see if one > string is alphabetically greater than another is though. "compare" seems to do the right thing in most cases. You could define shorthands if that's too much typing: user=> (defn << [a b] (neg? (compare a b))) #'user/<< user=> (defn >> [a b] (pos? (compare a b))) #'user/>> user=> (>> "d" "abc") true user=> (<< "d" "abc") false user=> (<< (Integer. "3") (Long. "4")) true user=> (>> (Integer. "3") (Long. "4")) false Kind regards, achim --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mathy operations on non-numerics
David Nolen writes: > What about something like: > > (defn gt [str1 str2] > (first (sort [str1 str2]))) > > (gt "Zoe" "Bob") ; -> "Bob" If nothing exists yet, defining <, >, <=, and >= in str-utils might work. -Phil --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: ANN: Preliminary Clojure Support in Buildr
I was able to repeat the problem. I suspect that the issue is the way in which GitHub is building its gems. I think Assaf (the lead dev for Buildr) has implemented a workaround in some of the more recent commits, but I haven't been able to merge with his master so I really couldn't say. For the moment, the solution is to just clone the git repository and build using rake. If you were able to get djspiewak-buildr to install (as you did), then you should be able to just run the following: sudo gem uninstall djspiewak-buildr git clone g...@github.com:djspiewak/buildr.git cd buildr rake install Note that there is no need to run rake under sudo, the install task will handle that for you. Daniel On Feb 26, 7:59 pm, Daniel Spiewak wrote: > Crud. I suspect this is something weird with the way that the GitHib > gem server works. I'll try to repeat the problem on Ubuntu as soon as > I get back to my computer. In the meantime, you could try these > commands: > > sudo gem uninstall djspiewak-buildr > sudo gem install djspiewak-buildr > > Daniel > > On Feb 26, 3:59 pm, Christian Vest Hansen > wrote: > > > rowe:~$ buildr --version > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > > `gem_original_require': no such file to load -- buildr (LoadError) > > from > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > > `require' > > from > > /opt/local/lib/ruby/gems/1.8/gems/djspiewak-buildr-1.3.4/bin/buildr:18 > > from /opt/local/bin/buildr:19:in `load' > > from /opt/local/bin/buildr:19 > > rowe:~$ gem --version > > 1.3.1 > > rowe:~$ > > > On Thu, Feb 26, 2009 at 10:30 PM, Daniel Spiewak > > wrote: > > > > I'm not sure what the File not found thing is all about, but you > > > should still be ok (crazy gems). Try the following: > > > > buildr --version > > > > Daniel > > > > On Feb 26, 3:16 pm, Christian Vest Hansen > > > wrote: > > >> On Thu, Feb 26, 2009 at 6:17 PM, Daniel Spiewak > > >> wrote: > > > >> > Odd. Must be a problem with RubyForge. If you try again, does it > > >> > work? > > > >> I tried again at home and got quite a bit further. Maybe it was just a > > >> hiccup at rubyforge. > > > >> However, I still see some questionable things in the output, and I > > >> have yet to actually try it out (this is the first time I'm trying out > > >> buildr). Here in verbatim: > > > >> rowe:~$ sudo gem install djspiewak-buildr > > >> Building native extensions. This could take a while... > > >> Successfully installed builder-2.1.2 > > >> Successfully installed net-ssh-2.0.4 > > >> Successfully installed net-sftp-2.0.1 > > >> Successfully installed rubyzip-0.9.1 > > >> Successfully installed highline-1.5.0 > > >> Successfully installed rubyforge-1.0.1 > > >> Successfully installed hoe-1.7.0 > > >> Successfully installed rjb-1.1.6 > > >> Successfully installed Antwrap-0.7.0 > > >> Successfully installed rspec-1.1.4 > > >> Successfully installed xml-simple-1.0.11 > > >> Successfully installed archive-tar-minitar-0.5.2 > > >> Successfully installed djspiewak-buildr-1.3.4 > > >> 13 gems installed > > >> Installing ri documentation for builder-2.1.2... > > >> ERROR: While generating documentation for builder-2.1.2 > > >> ... MESSAGE: Unhandled special: Special: type=17, text="" > > >> ... RDOC args: --ri --op > > >> /opt/local/lib/ruby/gems/1.8/doc/builder-2.1.2/ri --title Builder -- > > >> Easy XML Building --main README --line-numbers --quiet lib CHANGES > > >> Rakefile README doc/releases/builder-1.2.4.rdoc > > >> doc/releases/builder-2.0.0.rdoc doc/releases/builder-2.1.1.rdoc > > >> (continuing with the rest of the installation) > > >> Installing ri documentation for net-ssh-2.0.4... > > >> Installing ri documentation for net-sftp-2.0.1... > > >> Installing ri documentation for highline-1.5.0... > > >> Installing ri documentation for rubyforge-1.0.1... > > >> Installing ri documentation for hoe-1.7.0... > > >> Installing ri documentation for Antwrap-0.7.0... > > >> Installing ri documentation for rspec-1.1.4... > > >> Installing ri documentation for archive-tar-minitar-0.5.2... > > >> Installing ri documentation for djspiewak-buildr-1.3.4... > > >> File not found: lib > > >> rowe:~$ ruby --version > > >> ruby1.8.7(2008-08-11 patchlevel 72) [i686-darwin8] > > >> rowe:~$ > > > >> A failure to generate the docs I can live with, but that "File not > > >> found" line looks pretty suspect. > > > >> > Daniel > > > >> > On Feb 26, 10:58 am, Christian Vest Hansen > > >> > wrote: > > >> >> Nice initiative! > > > >> >> However, it the net-ssh dependency has problems: > > > >> >> [cvh: ~]$ sudo gem install djspiewak-buildr > > >> >> ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError) > > >> >> timed out (http://gems.rubyforge.org/gems/net-ssh-2.0.4.gem) > > > >> >> On Sat, Feb 21, 2009 at 10:33 PM, Daniel Spiewak > > >> >> wrote: > > > >> >> > I'm pleased to announce preliminary (and very experimental) sup
Re: ANN: Preliminary Clojure Support in Buildr
Correction: git clone git://github.com:djspiewak/buildr.git Daniel On Feb 27, 11:44 am, Daniel Spiewak wrote: > I was able to repeat the problem. I suspect that the issue is the way > in which GitHub is building its gems. I think Assaf (the lead dev for > Buildr) has implemented a workaround in some of the more recent > commits, but I haven't been able to merge with his master so I really > couldn't say. > > For the moment, the solution is to just clone the git repository and > build using rake. If you were able to get djspiewak-buildr to install > (as you did), then you should be able to just run the following: > > sudo gem uninstall djspiewak-buildr > git clone g...@github.com:djspiewak/buildr.git > cd buildr > rake install > > Note that there is no need to run rake under sudo, the install task > will handle that for you. > > Daniel > > On Feb 26, 7:59 pm, Daniel Spiewak wrote: > > > Crud. I suspect this is something weird with the way that the GitHib > > gem server works. I'll try to repeat the problem on Ubuntu as soon as > > I get back to my computer. In the meantime, you could try these > > commands: > > > sudo gem uninstall djspiewak-buildr > > sudo gem install djspiewak-buildr > > > Daniel > > > On Feb 26, 3:59 pm, Christian Vest Hansen > > wrote: > > > > rowe:~$ buildr --version > > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > > > `gem_original_require': no such file to load -- buildr (LoadError) > > > from > > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > > > `require' > > > from > > > /opt/local/lib/ruby/gems/1.8/gems/djspiewak-buildr-1.3.4/bin/buildr:18 > > > from /opt/local/bin/buildr:19:in `load' > > > from /opt/local/bin/buildr:19 > > > rowe:~$ gem --version > > > 1.3.1 > > > rowe:~$ > > > > On Thu, Feb 26, 2009 at 10:30 PM, Daniel Spiewak > > > wrote: > > > > > I'm not sure what the File not found thing is all about, but you > > > > should still be ok (crazy gems). Try the following: > > > > > buildr --version > > > > > Daniel > > > > > On Feb 26, 3:16 pm, Christian Vest Hansen > > > > wrote: > > > >> On Thu, Feb 26, 2009 at 6:17 PM, Daniel Spiewak > > > >> wrote: > > > > >> > Odd. Must be a problem with RubyForge. If you try again, does it > > > >> > work? > > > > >> I tried again at home and got quite a bit further. Maybe it was just a > > > >> hiccup at rubyforge. > > > > >> However, I still see some questionable things in the output, and I > > > >> have yet to actually try it out (this is the first time I'm trying out > > > >> buildr). Here in verbatim: > > > > >> rowe:~$ sudo gem install djspiewak-buildr > > > >> Building native extensions. This could take a while... > > > >> Successfully installed builder-2.1.2 > > > >> Successfully installed net-ssh-2.0.4 > > > >> Successfully installed net-sftp-2.0.1 > > > >> Successfully installed rubyzip-0.9.1 > > > >> Successfully installed highline-1.5.0 > > > >> Successfully installed rubyforge-1.0.1 > > > >> Successfully installed hoe-1.7.0 > > > >> Successfully installed rjb-1.1.6 > > > >> Successfully installed Antwrap-0.7.0 > > > >> Successfully installed rspec-1.1.4 > > > >> Successfully installed xml-simple-1.0.11 > > > >> Successfully installed archive-tar-minitar-0.5.2 > > > >> Successfully installed djspiewak-buildr-1.3.4 > > > >> 13 gems installed > > > >> Installing ri documentation for builder-2.1.2... > > > >> ERROR: While generating documentation for builder-2.1.2 > > > >> ... MESSAGE: Unhandled special: Special: type=17, text="" > > > >> ... RDOC args: --ri --op > > > >> /opt/local/lib/ruby/gems/1.8/doc/builder-2.1.2/ri --title Builder -- > > > >> Easy XML Building --main README --line-numbers --quiet lib CHANGES > > > >> Rakefile README doc/releases/builder-1.2.4.rdoc > > > >> doc/releases/builder-2.0.0.rdoc doc/releases/builder-2.1.1.rdoc > > > >> (continuing with the rest of the installation) > > > >> Installing ri documentation for net-ssh-2.0.4... > > > >> Installing ri documentation for net-sftp-2.0.1... > > > >> Installing ri documentation for highline-1.5.0... > > > >> Installing ri documentation for rubyforge-1.0.1... > > > >> Installing ri documentation for hoe-1.7.0... > > > >> Installing ri documentation for Antwrap-0.7.0... > > > >> Installing ri documentation for rspec-1.1.4... > > > >> Installing ri documentation for archive-tar-minitar-0.5.2... > > > >> Installing ri documentation for djspiewak-buildr-1.3.4... > > > >> File not found: lib > > > >> rowe:~$ ruby --version > > > >> ruby1.8.7(2008-08-11 patchlevel 72) [i686-darwin8] > > > >> rowe:~$ > > > > >> A failure to generate the docs I can live with, but that "File not > > > >> found" line looks pretty suspect. > > > > >> > Daniel > > > > >> > On Feb 26, 10:58 am, Christian Vest Hansen > > > >> > wrote: > > > >> >> Nice initiative! > > > > >> >> However, it the net-ssh dependency has problems: > > > > >> >> [cvh: ~]$ sudo gem install
Re: The Application Context Pattern
2009/2/27 Marko Kocić : > > Interesting approach, nice explained. > > Does anyone have similar example using one of the cells > implementations? > What would be pros/cons between this and cells approach? The cells implementations I've seen posted to this list (in fact pretty much all cells reimplementations) haven't yet approached the sophistication of kenny-cells. It's like editors. Everyone reckons they can make one better than emacs (or vi) but underestimate the man-hours that have gone into them over the years and end up with something that maybe looks as good (or better) superficially but when you delve into the details, just doesn't cut the mustard. I'd love to see some kind of clojure-cells but it's still a long way off. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Opinions on -> macro? (was Re: Extensive use of let?)
On Wed, Feb 25, 2009 at 4:11 PM, Jason Wolfe wrote: > (you'll get use to reading inside-out quickly). As a Java/Ruby guy who is not used to reading inside out, I'm curious as to whether people who ARE accustomed to LISP find the -> macro distracting since it flops things around. Are there circumstances where you prefer it? --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: The Application Context Pattern
On Feb 27, 12:59 pm, Andy Chambers wrote: > The cells implementations I've seen posted to this list (in fact pretty much > all > cells reimplementations) haven't yet approached the sophistication of > kenny-cells. Agreed. And I wrote two of them. They're just toy implementations so far. -Stuart Sierra --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Opinions on -> macro?
Hi, Am 27.02.2009 um 19:39 schrieb John D. Hume: As a Java/Ruby guy who is not used to reading inside out, I'm curious as to whether people who ARE accustomed to LISP find the -> macro distracting since it flops things around. Are there circumstances where you prefer it? I have a Scheme background and I like -> a lot. I would prefer it always over (foo (bar (baz (frobnicate a-thing)) bla)). Eh? To which function belongs the bla argument? I think (-> a-thing frobnicate baz (bar bla) foo) is much clearer. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: Opinions on -> macro? (was Re: Extensive use of let?)
On Feb 27, 6:39 pm, "John D. Hume" wrote: > As a Java/Ruby guy who is not used to reading inside out, I'm curious > as to whether people who ARE accustomed to LISP find the -> macro > distracting since it flops things around. Are there circumstances > where you prefer it? It's pretty useful for nested keywords: (:name (:profile (:user message))) (-> message :user :profile :name) - James --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Opinions on -> macro? (was Re: Extensive use of let?)
> > It's pretty useful for nested keywords: > > (:name (:profile (:user message))) > > (-> message :user :profile :name) > > - James That is really cool. Once again the language and the community impress me with how elegant the language is. Allen --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Clojure + Terracotta = Yeah, Baby!
I've recently done some experimentation with Clojure and Terracotta. I've detailed my experience at: http://paul.stadig.name/2009/02/clojure-terracotta-yeah-baby.html and shared my code at: http://github.com/pjstadig/terraclojure/tree/master/ I'm the first to admit that I'm not an expert in Terracotta. This is actually my first time working with it. I was able to setup a permanent store, and to run a couple of transactions against some refs shared across multiple JVMs. I ran into two snags. The first was that Keyword did not implement hashCode, which was a simple fix. Rich graciously added a hashCode method. :) The other was how to point Terracotta to a var from the Java side. I ended up using a simple Java class to hold on to my refs, since then it was easy to point Terracotta to the right place. It works just fine, but I'm not sure if there is a better way to do it. I'd be interested in knowing if anyone else has experience to share about using Terracotta with Clojure. Paul Stadig --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: ANN: Preliminary Clojure Support in Buildr
On Fri, Feb 27, 2009 at 6:47 PM, Daniel Spiewak wrote: > > Correction: > > git clone git://github.com:djspiewak/buildr.git git clone git://github.com/djspiewak/buildr.git Excellent. Got it installed. > > Daniel > > On Feb 27, 11:44 am, Daniel Spiewak wrote: >> I was able to repeat the problem. I suspect that the issue is the way >> in which GitHub is building its gems. I think Assaf (the lead dev for >> Buildr) has implemented a workaround in some of the more recent >> commits, but I haven't been able to merge with his master so I really >> couldn't say. >> >> For the moment, the solution is to just clone the git repository and >> build using rake. If you were able to get djspiewak-buildr to install >> (as you did), then you should be able to just run the following: >> >> sudo gem uninstall djspiewak-buildr >> git clone g...@github.com:djspiewak/buildr.git >> cd buildr >> rake install >> >> Note that there is no need to run rake under sudo, the install task >> will handle that for you. >> >> Daniel >> >> On Feb 26, 7:59 pm, Daniel Spiewak wrote: >> >> > Crud. I suspect this is something weird with the way that the GitHib >> > gem server works. I'll try to repeat the problem on Ubuntu as soon as >> > I get back to my computer. In the meantime, you could try these >> > commands: >> >> > sudo gem uninstall djspiewak-buildr >> > sudo gem install djspiewak-buildr >> >> > Daniel >> >> > On Feb 26, 3:59 pm, Christian Vest Hansen >> > wrote: >> >> > > rowe:~$ buildr --version >> > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in >> > > `gem_original_require': no such file to load -- buildr (LoadError) >> > > from >> > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in >> > > `require' >> > > from >> > > /opt/local/lib/ruby/gems/1.8/gems/djspiewak-buildr-1.3.4/bin/buildr:18 >> > > from /opt/local/bin/buildr:19:in `load' >> > > from /opt/local/bin/buildr:19 >> > > rowe:~$ gem --version >> > > 1.3.1 >> > > rowe:~$ >> >> > > On Thu, Feb 26, 2009 at 10:30 PM, Daniel Spiewak >> > > wrote: >> >> > > > I'm not sure what the File not found thing is all about, but you >> > > > should still be ok (crazy gems). Try the following: >> >> > > > buildr --version >> >> > > > Daniel >> >> > > > On Feb 26, 3:16 pm, Christian Vest Hansen >> > > > wrote: >> > > >> On Thu, Feb 26, 2009 at 6:17 PM, Daniel Spiewak >> > > >> wrote: >> >> > > >> > Odd. Must be a problem with RubyForge. If you try again, does it >> > > >> > work? >> >> > > >> I tried again at home and got quite a bit further. Maybe it was just a >> > > >> hiccup at rubyforge. >> >> > > >> However, I still see some questionable things in the output, and I >> > > >> have yet to actually try it out (this is the first time I'm trying out >> > > >> buildr). Here in verbatim: >> >> > > >> rowe:~$ sudo gem install djspiewak-buildr >> > > >> Building native extensions. This could take a while... >> > > >> Successfully installed builder-2.1.2 >> > > >> Successfully installed net-ssh-2.0.4 >> > > >> Successfully installed net-sftp-2.0.1 >> > > >> Successfully installed rubyzip-0.9.1 >> > > >> Successfully installed highline-1.5.0 >> > > >> Successfully installed rubyforge-1.0.1 >> > > >> Successfully installed hoe-1.7.0 >> > > >> Successfully installed rjb-1.1.6 >> > > >> Successfully installed Antwrap-0.7.0 >> > > >> Successfully installed rspec-1.1.4 >> > > >> Successfully installed xml-simple-1.0.11 >> > > >> Successfully installed archive-tar-minitar-0.5.2 >> > > >> Successfully installed djspiewak-buildr-1.3.4 >> > > >> 13 gems installed >> > > >> Installing ri documentation for builder-2.1.2... >> > > >> ERROR: While generating documentation for builder-2.1.2 >> > > >> ... MESSAGE: Unhandled special: Special: type=17, text="" >> > > >> ... RDOC args: --ri --op >> > > >> /opt/local/lib/ruby/gems/1.8/doc/builder-2.1.2/ri --title Builder -- >> > > >> Easy XML Building --main README --line-numbers --quiet lib CHANGES >> > > >> Rakefile README doc/releases/builder-1.2.4.rdoc >> > > >> doc/releases/builder-2.0.0.rdoc doc/releases/builder-2.1.1.rdoc >> > > >> (continuing with the rest of the installation) >> > > >> Installing ri documentation for net-ssh-2.0.4... >> > > >> Installing ri documentation for net-sftp-2.0.1... >> > > >> Installing ri documentation for highline-1.5.0... >> > > >> Installing ri documentation for rubyforge-1.0.1... >> > > >> Installing ri documentation for hoe-1.7.0... >> > > >> Installing ri documentation for Antwrap-0.7.0... >> > > >> Installing ri documentation for rspec-1.1.4... >> > > >> Installing ri documentation for archive-tar-minitar-0.5.2... >> > > >> Installing ri documentation for djspiewak-buildr-1.3.4... >> > > >> File not found: lib >> > > >> rowe:~$ ruby --version >> > > >> ruby1.8.7(2008-08-11 patchlevel 72) [i686-darwin8] >> > > >> rowe:~$ >> >> > > >> A failure to generate the docs I can live with, but that "File not >> > > >>
Re: The Application Context Pattern
> > The cells implementations I've seen posted to this list (in fact pretty > > much all > > cells reimplementations) haven't yet approached the sophistication of > > kenny-cells. > > Agreed. And I wrote two of them. They're just toy implementations so > far. I'm still not sure how it should look like given clojure immutablility. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Getting substrings with negative indices
It's a pretty common idiom in other languages for substring functions to count from the end if given a negative index. (substring "hello world!" 6 -1) ;; => "world" I'd be glad if Clojure's "subs" function could work like this. Should I create an issue and patch to implement it? -Phil --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
We are trying to get Clojure shared over Terracotta, not just specific things but the whole Clojure object space (name spaces, root values, ) except stuff that needs to remain local (streams, ). We take an all or nothing approach here, we would to see many Clojure instances work as a single entity. We are facing a number of issues, one of them being the lack of support by Terracotta of AtomicReference. Terracotta has placed this class in the list of classes they will eventually support but has of 2.7.3 it's still not supported. The Sun AtomicReference does peeks and pokes in the heap using internal routines of the JVM (JNI). Clearly this cannot be done with multiple JVMs, different object heaps, Terracotta suggest using the oswego library but since Java 5 has been out, it's in maintenance mode only and integrating another library to the puzzle for that single purpose did not look to us as very efficient. So we created a SharedAtomicReference implementation that uses standard locks to control access to the value with the corresponding Terracotta configuration. We use a factory to decide at run time which implementation to use based on a system property. To preserve the Clojure code base, we implemented an AtomicReference interface and a delegate to the AtomicReference class. The Clojure code uses now interface. This allows us to make progress without disturbing the Clojure code base too much. This has some performance implications that we do not fully understand yet since we need a living Clojure implementation to work with, something we are in the process of creating... what a catch 22 :))) We thought about spending time working on this aspect right now but we prefer to wait for the first alpha release. As for the rest of the Clojure code, we are working on the classes implementing vectors, hash maps, to get them shared through terracotta. Our main challenge these days is putting together the terracotta configuration of the internal classes of Clojure that need to be shared. We may hit issues that make some classes non portable. These will require us to implement an alternative. We will use then a slightly different approach, we need only factories to allocate an alternate version or the "local" implementation. The Clojure code already uses interfaces to access the data objects so this will be almost transparent in the code. We prefer to re implement an "distributed" implementation side by side with the original one and easily switch between them to compare behaviour and performance with the same code base. When we have a clearer understanding of how it performs we will look at how to merge this in the code base that will have changed in between. We may be able then to reduce the number of alternate implementations if more where created. The work is in progress, next week is a school break week here so the pace will slow down a bit. We wanted to start earlier on this (before XMas) but we had updates to put in production , client caring to do, ... and other mundane tasks to get the bread and butter on the table. Comments/suggestions are welcomed... Luc On Fri, 2009-02-27 at 12:20 -0800, Paul Stadig wrote: > I've recently done some experimentation with Clojure and Terracotta. > I've detailed my experience at: > > http://paul.stadig.name/2009/02/clojure-terracotta-yeah-baby.html > > and shared my code at: > > http://github.com/pjstadig/terraclojure/tree/master/ > > I'm the first to admit that I'm not an expert in Terracotta. This is > actually my first time working with it. > > I was able to setup a permanent store, and to run a couple of > transactions against some refs shared across multiple JVMs. I ran into > two snags. The first was that Keyword did not implement hashCode, > which was a simple fix. Rich graciously added a hashCode method. :) > > The other was how to point Terracotta to a var from the Java side. I > ended up using a simple Java class to hold on to my refs, since then > it was easy to point Terracotta to the right place. It works just > fine, but I'm not sure if there is a better way to do it. > > I'd be interested in knowing if anyone else has experience to share > about using Terracotta with Clojure. > > > Paul Stadig > > > > -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
Paul Stadig writes: > I've recently done some experimentation with Clojure and Terracotta. > I've detailed my experience at: > > http://paul.stadig.name/2009/02/clojure-terracotta-yeah-baby.html Very exciting; I'm looking forward to trying this out! Thanks for posting. -Phil --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
Yeah, after sharing clojure.lang.Keyword.table I tried to share clojure.lang.Namespace.namespaces, but ran into a problem because Namespace uses an AtomicReference for its mappings and aliases members. I thought that not sharing namespaces would be a problem (and maybe it still is I don't have as much practical experience with this as you), but I wasn't sure it would be a problem. Looking up a var in a namespace on different JVMs would find different vars, but since they are thread local, then I'm not sure its an issue. Having all of your refs shared without having to specify each specific ref would be interesting, but since most of the stuff (functions, vars, etc.) are immutable or thread local, then I'm not sure how much of an issue it is. Obviously, if you were going to redefine some functions or something, then you'd either have to do so on each JVM, or just restart all of the clients. And as I said in my article, I didn't do any work with agents, so maybe there's a lot missing from my part of the puzzle. Paul On Fri, Feb 27, 2009 at 4:37 PM, Luc Prefontaine wrote: > We are trying to get Clojure shared over Terracotta, not just specific > things but the whole Clojure object space > (name spaces, root values, ) except stuff that needs to remain local > (streams, ). > > We take an all or nothing approach here, we would to see many Clojure > instances work as a single > entity. > > We are facing a number of issues, one of them being the lack of support by > Terracotta of AtomicReference. > > Terracotta has placed this class in the list of classes they will eventually > support but has of 2.7.3 > it's still not supported. > > The Sun AtomicReference does peeks and pokes in the heap using internal > routines of the JVM (JNI). > Clearly this cannot be done with multiple JVMs, different object heaps, > > Terracotta suggest using the oswego library but since Java 5 has been out, > it's in maintenance mode only and > integrating another library to the puzzle for that single purpose did not > look to us as very efficient. > > So we created a SharedAtomicReference implementation that uses standard > locks to control access to > the value with the corresponding Terracotta configuration. > > We use a factory to decide at run time which implementation to use based on > a system property. > To preserve the Clojure code base, we implemented an AtomicReference > interface and a delegate to > the AtomicReference class. The Clojure code uses now interface. > This allows us to make progress without disturbing the Clojure code base too > much. > > This has some performance implications that we do not fully understand yet > since we need a living Clojure implementation > to work with, something we are in the process of creating... what a catch 22 > :))) > We thought about spending time working on this aspect right now but we > prefer to wait for the first alpha release. > > As for the rest of the Clojure code, we are working on the classes > implementing vectors, hash maps, > to get them shared through terracotta. > > Our main challenge these days is putting together the terracotta > configuration of the internal classes of Clojure that need to be shared. > > We may hit issues that make some classes non portable. > These will require us to implement an alternative. We will use then a > slightly different approach, > we need only factories to allocate an alternate version or the "local" > implementation. > The Clojure code already uses interfaces to access the data objects so this > will be almost transparent in the code. > > We prefer to re implement an "distributed" implementation side by side with > the original one and easily switch between them > to compare behaviour and performance with the same code base. > > When we have a clearer understanding of how it performs we will look at how > to merge this in the code base > that will have changed in between. We may be able then to reduce the number > of alternate implementations > if more where created. > > The work is in progress, next week is a school break week here so the pace > will slow down a bit. > We wanted to start earlier on this (before XMas) but we had updates to put > in production , client caring to do, ... > and other mundane tasks to get the bread and butter on the table. > > Comments/suggestions are welcomed... > > Luc > > > On Fri, 2009-02-27 at 12:20 -0800, Paul Stadig wrote: > > I've recently done some experimentation with Clojure and Terracotta. > I've detailed my experience at: > > http://paul.stadig.name/2009/02/clojure-terracotta-yeah-baby.html > > and shared my code at: > > http://github.com/pjstadig/terraclojure/tree/master/ > > I'm the first to admit that I'm not an expert in Terracotta. This is > actually my first time working with it. > > I was able to setup a permanent store, and to run a couple of > transactions against some refs shared across multiple JVMs. I ran into > two snags. The first was that Keyword did not
Re: Waterfront 148 (was: Waterfront - The Clojure-based editor for Clojure)
> I'm not sure I understand. Are you referring to > UIManager.getSystemLookAndFeelClassName() ? > This is the L&F that Waterfront is using. If you don't get this L&F > then perhaps the call to setLookAndFeel() fails on your machine. I'll > add a piece of code to log the exception. > > -Itay It also has the ugly default swing L&F on my machine too. I'm using Linux / KDE. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: ANN: Preliminary Clojure Support in Buildr
As an aside, "gem install djspiewak-buildr" probably works again. I've merged Assaf's fixes, and GitHub *claims* to be building things correctly. So, I haven't tried it, but I can't think of a reason why it wouldn't work. Daniel On Feb 27, 2:39 pm, Christian Vest Hansen wrote: > On Fri, Feb 27, 2009 at 6:47 PM, Daniel Spiewak wrote: > > > Correction: > > > git clone git://github.com:djspiewak/buildr.git > > git clone git://github.com/djspiewak/buildr.git > > Excellent. Got it installed. > > > > > Daniel > > > On Feb 27, 11:44 am, Daniel Spiewak wrote: > >> I was able to repeat the problem. I suspect that the issue is the way > >> in which GitHub is building its gems. I think Assaf (the lead dev for > >> Buildr) has implemented a workaround in some of the more recent > >> commits, but I haven't been able to merge with his master so I really > >> couldn't say. > > >> For the moment, the solution is to just clone the git repository and > >> build using rake. If you were able to get djspiewak-buildr to install > >> (as you did), then you should be able to just run the following: > > >> sudo gem uninstall djspiewak-buildr > >> git clone g...@github.com:djspiewak/buildr.git > >> cd buildr > >> rake install > > >> Note that there is no need to run rake under sudo, the install task > >> will handle that for you. > > >> Daniel > > >> On Feb 26, 7:59 pm, Daniel Spiewak wrote: > > >> > Crud. I suspect this is something weird with the way that the GitHib > >> > gem server works. I'll try to repeat the problem on Ubuntu as soon as > >> > I get back to my computer. In the meantime, you could try these > >> > commands: > > >> > sudo gem uninstall djspiewak-buildr > >> > sudo gem install djspiewak-buildr > > >> > Daniel > > >> > On Feb 26, 3:59 pm, Christian Vest Hansen > >> > wrote: > > >> > > rowe:~$ buildr --version > >> > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > >> > > `gem_original_require': no such file to load -- buildr (LoadError) > >> > > from > >> > > /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in > >> > > `require' > >> > > from > >> > > /opt/local/lib/ruby/gems/1.8/gems/djspiewak-buildr-1.3.4/bin/buildr:18 > >> > > from /opt/local/bin/buildr:19:in `load' > >> > > from /opt/local/bin/buildr:19 > >> > > rowe:~$ gem --version > >> > > 1.3.1 > >> > > rowe:~$ > > >> > > On Thu, Feb 26, 2009 at 10:30 PM, Daniel Spiewak > >> > > wrote: > > >> > > > I'm not sure what the File not found thing is all about, but you > >> > > > should still be ok (crazy gems). Try the following: > > >> > > > buildr --version > > >> > > > Daniel > > >> > > > On Feb 26, 3:16 pm, Christian Vest Hansen > >> > > > wrote: > >> > > >> On Thu, Feb 26, 2009 at 6:17 PM, Daniel Spiewak > >> > > >> wrote: > > >> > > >> > Odd. Must be a problem with RubyForge. If you try again, does it > >> > > >> > work? > > >> > > >> I tried again at home and got quite a bit further. Maybe it was > >> > > >> just a > >> > > >> hiccup at rubyforge. > > >> > > >> However, I still see some questionable things in the output, and I > >> > > >> have yet to actually try it out (this is the first time I'm trying > >> > > >> out > >> > > >> buildr). Here in verbatim: > > >> > > >> rowe:~$ sudo gem install djspiewak-buildr > >> > > >> Building native extensions. This could take a while... > >> > > >> Successfully installed builder-2.1.2 > >> > > >> Successfully installed net-ssh-2.0.4 > >> > > >> Successfully installed net-sftp-2.0.1 > >> > > >> Successfully installed rubyzip-0.9.1 > >> > > >> Successfully installed highline-1.5.0 > >> > > >> Successfully installed rubyforge-1.0.1 > >> > > >> Successfully installed hoe-1.7.0 > >> > > >> Successfully installed rjb-1.1.6 > >> > > >> Successfully installed Antwrap-0.7.0 > >> > > >> Successfully installed rspec-1.1.4 > >> > > >> Successfully installed xml-simple-1.0.11 > >> > > >> Successfully installed archive-tar-minitar-0.5.2 > >> > > >> Successfully installed djspiewak-buildr-1.3.4 > >> > > >> 13 gems installed > >> > > >> Installing ri documentation for builder-2.1.2... > >> > > >> ERROR: While generating documentation for builder-2.1.2 > >> > > >> ... MESSAGE: Unhandled special: Special: type=17, text="" > >> > > >> ... RDOC args: --ri --op > >> > > >> /opt/local/lib/ruby/gems/1.8/doc/builder-2.1.2/ri --title Builder -- > >> > > >> Easy XML Building --main README --line-numbers --quiet lib CHANGES > >> > > >> Rakefile README doc/releases/builder-1.2.4.rdoc > >> > > >> doc/releases/builder-2.0.0.rdoc doc/releases/builder-2.1.1.rdoc > >> > > >> (continuing with the rest of the installation) > >> > > >> Installing ri documentation for net-ssh-2.0.4... > >> > > >> Installing ri documentation for net-sftp-2.0.1... > >> > > >> Installing ri documentation for highline-1.5.0... > >> > > >> Installing ri documentation for rubyforge-1.0.1... > >> > > >> Installing ri documentation for hoe-1.7.0... > >> >
Re: Waterfront - The Clojure-based editor for Clojure
On Feb 25, 6:02 pm, "Stephen C. Gilardi" wrote: > > - When using waterfront on Mac OS X, it appears that the control > characters intended to trigger menu selections (e.g. ^E) are being > intercepted before they reach the menus. In the specific case of ^E, > it is being interpreted by the text input field as "move to end of > line" which is a common meaning for it in Mac OS X. I suspect there is > a way to trigger menu items using the "command-key" on the Mac (while > still using the control key on Windows) and people using waterfront on > Mac OS X would benefit from a change to using that mechanism. Indeed. Instead of hard-coding modifier keys, you should use the Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(). This will return control for windows and META (or command) for Mac. Curtis --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
Having the ability to redefine a function once for all instances is something we really want... and you need name spaces to be shared for that to happen. We take the approach of sharing everything that seems to worth it, then we will see what we might need to keep private to each JVM. Sharing var roots and refs also is something we want so we can initiate STM transactions involving multiple JVMs. We have much to learn from a prototype and that is what we strive to achieve the immediate future. After this step, real fun will begin, right now were having only an appetizer... Luc On Fri, 2009-02-27 at 16:51 -0500, Paul Stadig wrote: > Yeah, after sharing clojure.lang.Keyword.table I tried to share > clojure.lang.Namespace.namespaces, but ran into a problem because > Namespace uses an AtomicReference for its mappings and aliases > members. I thought that not sharing namespaces would be a problem (and > maybe it still is I don't have as much practical experience with this > as you), but I wasn't sure it would be a problem. Looking up a var in > a namespace on different JVMs would find different vars, but since > they are thread local, then I'm not sure its an issue. Having all of > your refs shared without having to specify each specific ref would be > interesting, but since most of the stuff (functions, vars, etc.) are > immutable or thread local, then I'm not sure how much of an issue it > is. > > Obviously, if you were going to redefine some functions or something, > then you'd either have to do so on each JVM, or just restart all of > the clients. > > And as I said in my article, I didn't do any work with agents, so > maybe there's a lot missing from my part of the puzzle. > > > Paul > > On Fri, Feb 27, 2009 at 4:37 PM, Luc Prefontaine > wrote: > > We are trying to get Clojure shared over Terracotta, not just specific > > things but the whole Clojure object space > > (name spaces, root values, ) except stuff that needs to remain local > > (streams, ). > > > > We take an all or nothing approach here, we would to see many Clojure > > instances work as a single > > entity. > > > > We are facing a number of issues, one of them being the lack of support by > > Terracotta of AtomicReference. > > > > Terracotta has placed this class in the list of classes they will eventually > > support but has of 2.7.3 > > it's still not supported. > > > > The Sun AtomicReference does peeks and pokes in the heap using internal > > routines of the JVM (JNI). > > Clearly this cannot be done with multiple JVMs, different object heaps, > > > > Terracotta suggest using the oswego library but since Java 5 has been out, > > it's in maintenance mode only and > > integrating another library to the puzzle for that single purpose did not > > look to us as very efficient. > > > > So we created a SharedAtomicReference implementation that uses standard > > locks to control access to > > the value with the corresponding Terracotta configuration. > > > > We use a factory to decide at run time which implementation to use based on > > a system property. > > To preserve the Clojure code base, we implemented an AtomicReference > > interface and a delegate to > > the AtomicReference class. The Clojure code uses now interface. > > This allows us to make progress without disturbing the Clojure code base too > > much. > > > > This has some performance implications that we do not fully understand yet > > since we need a living Clojure implementation > > to work with, something we are in the process of creating... what a catch 22 > > :))) > > We thought about spending time working on this aspect right now but we > > prefer to wait for the first alpha release. > > > > As for the rest of the Clojure code, we are working on the classes > > implementing vectors, hash maps, > > to get them shared through terracotta. > > > > Our main challenge these days is putting together the terracotta > > configuration of the internal classes of Clojure that need to be shared. > > > > We may hit issues that make some classes non portable. > > These will require us to implement an alternative. We will use then a > > slightly different approach, > > we need only factories to allocate an alternate version or the "local" > > implementation. > > The Clojure code already uses interfaces to access the data objects so this > > will be almost transparent in the code. > > > > We prefer to re implement an "distributed" implementation side by side with > > the original one and easily switch between them > > to compare behaviour and performance with the same code base. > > > > When we have a clearer understanding of how it performs we will look at how > > to merge this in the code base > > that will have changed in between. We may be able then to reduce the number > > of alternate implementations > > if more where created. > > > > The work is in progress, next week is a school break week here so the pace > > will slow down a bit. > > We wanted to start
Re: The Application Context Pattern
It looks really nice. I have a question about those observers, though-- every time that a context-processing function is called, every observer is called one by one, no matter what the context-processing function was. This seems somewhat inefficient, more so than listeners that listen to only certain functions and are called when the listened function is activated. In your experience, is this not a big problem? Or am I missing something? On Feb 27, 1:05 am, Itay Maman wrote: > Some of the reaction for Waterfront was related to the Application > Context Pattern (ACP) - The pattern that allows most of Waterfront's > code to be purely functional. I'll try to explain the basics in this > post. Let me start with the motivation: the reason why FP is at odds > with GUI code. > > (Pure) Functional code has no side effects, which implies immutability > of state. There are no fields nor global variables that can be > assigned to. Thus, one function can affect the computation carried out > by another function only by the passing of parameters. Most GUI > systems are built around the notion of event handlers which are > invoked by a message processing loop. There is no chain of calls from > one event handler to another. > In particular, if handler "A" computed some new value it cannot pass > it on to handler "B" because the system will call "B" only after "A" > returns. That's the predicament. > > ACP overcomes this by capturing the applications current state in an > immutable map. All event handlers receive a single parameter which is > the "current" context and compute the "new" context. A typical handler > (henceforth: "context processing function") will carry out these > activities: (a) Examine the current context; (b) Perform some GUI > operations (setSize, setText, etc.); (c) Compute a new context based > on the current context and on information obtained from the GUI > (getText, etc.). The caller (henceforth: "dispatcher") takes the > returned context and will use it as the new current context, the next > time a context processing function is invoked. > > This means that when you register event handler with a Swing widget > the handler needs to to call the ACP dispatcher passing it a context > processing function. > > The net effect of this approach is that only the dispatcher has to > deal with mutable state. The context processors are functional: they > merely compute the new state from the current. > > application-context-pattern.clj (http://groups.google.com/group/ > clojure/web/application-context-pattern.clj) shows a concrete example. > It's about 140 LOC (ripped off from the real Waterfront codebase) > structured as follows: > Lines 1..40: General-purpose helpers. > Lines 40..90: The ACP infrastructure > Lines 90..140: A quick sample, built around ACP. > > The sample program opens a JFrame with two buttons: Input and Output. > A click on the input button will pop-up an input dialog box. A click > on the output button will pop-up a message box showing the last value > entered into the input box. There's also a JLabel showing the length > of the input, but let's ignore it for the moment. > > The entry point into the ACP world is the bootstrap function. It takes > two parameters: a context processing function and an initial context. > In the example, this is carried out at the bottom of the run-it > function: > > (defn run-it [] > (let [build-ui (fn [ctx] > (let [f (javax.swing.JFrame. "Frame") > b-in (javax.swing.JButton. "Input") > b-out (javax.swing.JButton. "Output")] > > (.addActionListener b-in (new-action-listener (fn [event] > ((ctx :dispatch) get-input > > (.addActionListener b-out (new-action-listener (fn [event] > ((ctx :dispatch) show-output > > (.setLayout f (java.awt.FlowLayout.)) > (doseq [x [b-in b-out]] > (.add f x) ) > > (doto f > (.setSize 500 300) > (.setDefaultCloseOperation javax.swing.JFrame/ > DISPOSE_ON_CLOSE) > (.setVisible true)) > > (assoc ctx :frame f) ))] > > (invoke-later #(bootstrap build-ui {})) )) > > invoke-later is a utility function that is mapped to SwingUtilities/ > invokeLater. > > Let's drill down into the build-ui function: It takes the current > context (ctx parameter). Then it creates the frame and the buttons. It > uses new-action-listener (another utility) to register an action > listener with the buttons. The first listener looks like this: > ((ctx :dispatch) get-input > > It uses (ctx :dispatch) to obtain the dispatcher from which ctx was > obtained, and evaluates it passing get-input as the context processing > function. The call to bootstrap initialized this dispatcher and added > the :dispatch mapping to the initial context. > > get-input looks like this: > (defn- get-input [ctx] > (let [reply (javax.swing.JOptionPane/showInputDialog nil "Type in > something")] > (assoc
Re: Synchronous watches
On Feb 27, 7:17 am, Rich Hickey wrote: > > > Are namespaces & global set of namespaces "watchable" things ? > > No they are not. Is there a deep reason for this? I'm not familiar with this part of Clojure but, if the functionality is possible, would you accept a patch for this? --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
On Feb 27, 2009, at 7:29 PM, Mark Addleman wrote: > > On Feb 27, 7:17 am, Rich Hickey wrote: >> >>> Are namespaces & global set of namespaces "watchable" things ? >> >> No they are not. > > Is there a deep reason for this? I'm not familiar with this part of > Clojure but, if the functionality is possible, would you accept a > patch for this? > There's no deep reason, but I want to hold off on pursuing this right now. I'm still thinking about the issues of people running in systems like OSGi and NetKernel, which may in the end need partitioning of the namespace stuff from the rest of Clojure, as well as the needs of those trying to use Terracotta. 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
(rest ())
Maybe it doesn't matter in practice, but does it seem odd to anyone else that (rest ()) returns () rather than nil? --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: (rest ())
On Feb 27, 2009, at 8:27 PM, Mark Engelberg wrote: Maybe it doesn't matter in practice, but does it seem odd to anyone else that (rest ()) returns () rather than nil? I think that's to be expected given the recent changes to how laziness works in Clojure. It's consistent with these docs: Clojure user=> (doc rest) - clojure.core/rest ([coll]) Returns a possibly empty seq of the items after the first. Calls seq on its argument. nil user=> (doc next) - clojure.core/next ([coll]) Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil. nil Were you thinking of what's now called "next" and used to be called "rest"? Why did you expect nil from rest in this case? --Steve smime.p7s Description: S/MIME cryptographic signature
Re: Clojure + Terracotta = Yeah, Baby!
On Feb 27, 6:54 pm, Luc Prefontaine wrote: > Having the ability to redefine a function once for all instances is > something we really want... > and you need name spaces to be shared for that to happen. > We take the approach of sharing everything that seems to worth it, then > we will see > what we might need to keep private to each JVM. > > Sharing var roots and refs also is something we want so we can initiate > STM transactions > involving multiple JVMs. > > We have much to learn from a prototype and that is what we strive to > achieve the immediate future. > After this step, real fun will begin, right now were having only an > appetizer... > > Luc > It would be great if you could mention the difficulties you face as you go, before you spend too much time on workarounds. I am interested in seeing Clojure on Terracotta and if there are things I can do easily to support this effort I will. Rich > > > On Fri, 2009-02-27 at 16:51 -0500, Paul Stadig wrote: > > Yeah, after sharing clojure.lang.Keyword.table I tried to share > > clojure.lang.Namespace.namespaces, but ran into a problem because > > Namespace uses an AtomicReference for its mappings and aliases > > members. I thought that not sharing namespaces would be a problem (and > > maybe it still is I don't have as much practical experience with this > > as you), but I wasn't sure it would be a problem. Looking up a var in > > a namespace on different JVMs would find different vars, but since > > they are thread local, then I'm not sure its an issue. Having all of > > your refs shared without having to specify each specific ref would be > > interesting, but since most of the stuff (functions, vars, etc.) are > > immutable or thread local, then I'm not sure how much of an issue it > > is. > > > Obviously, if you were going to redefine some functions or something, > > then you'd either have to do so on each JVM, or just restart all of > > the clients. > > > And as I said in my article, I didn't do any work with agents, so > > maybe there's a lot missing from my part of the puzzle. > > > Paul > > > On Fri, Feb 27, 2009 at 4:37 PM, Luc Prefontaine > > wrote: > > > We are trying to get Clojure shared over Terracotta, not just specific > > > things but the whole Clojure object space > > > (name spaces, root values, ) except stuff that needs to remain local > > > (streams, ). > > > > We take an all or nothing approach here, we would to see many Clojure > > > instances work as a single > > > entity. > > > > We are facing a number of issues, one of them being the lack of support by > > > Terracotta of AtomicReference. > > > > Terracotta has placed this class in the list of classes they will > > > eventually > > > support but has of 2.7.3 > > > it's still not supported. > > > > The Sun AtomicReference does peeks and pokes in the heap using internal > > > routines of the JVM (JNI). > > > Clearly this cannot be done with multiple JVMs, different object heaps, > > > > > > > Terracotta suggest using the oswego library but since Java 5 has been out, > > > it's in maintenance mode only and > > > integrating another library to the puzzle for that single purpose did not > > > look to us as very efficient. > > > > So we created a SharedAtomicReference implementation that uses standard > > > locks to control access to > > > the value with the corresponding Terracotta configuration. > > > > We use a factory to decide at run time which implementation to use based > > > on > > > a system property. > > > To preserve the Clojure code base, we implemented an AtomicReference > > > interface and a delegate to > > > the AtomicReference class. The Clojure code uses now interface. > > > This allows us to make progress without disturbing the Clojure code base > > > too > > > much. > > > > This has some performance implications that we do not fully understand yet > > > since we need a living Clojure implementation > > > to work with, something we are in the process of creating... what a catch > > > 22 > > > :))) > > > We thought about spending time working on this aspect right now but we > > > prefer to wait for the first alpha release. > > > > As for the rest of the Clojure code, we are working on the classes > > > implementing vectors, hash maps, > > > to get them shared through terracotta. > > > > Our main challenge these days is putting together the terracotta > > > configuration of the internal classes of Clojure that need to be shared. > > > > We may hit issues that make some classes non portable. > > > These will require us to implement an alternative. We will use then a > > > slightly different approach, > > > we need only factories to allocate an alternate version or the "local" > > > implementation. > > > The Clojure code already uses interfaces to access the data objects so > > > this > > > will be almost transparent in the code. > > > > We prefer to re implement an "distributed" implementation side by side > > > with > > > the original one
Re: Clojure + Terracotta = Yeah, Baby!
You're right Rich, We all have to agree on the means used to implement this in the Clojure runtime. Any code we throw right now has to be somewhat aligned with these decisions. The decision to hide the AtomicReference class was easy to take. It was an unavoidable obstacle. Any other issues from the Clojure run time will need more thinking and there might be other ways to do work around these issues. I can post an update each 2 weeks or so or on demand before we spit out code if we face an issue. Right now we are busy writing a tool in Clojure to generate the terracotta configuration from a set of classes. Finding each dependent class one by one is too slow. We always end up missing one. It will also spit out the locking section with all these member functions. This tool will speed us a lot in getting the prototype up. We will get the master pieces of the XML configuration. We can them removing unwanted classes from the configuration and tune the locking strategy as you test things. Luc On Fri, 2009-02-27 at 18:05 -0800, Rich Hickey wrote: > > > On Feb 27, 6:54 pm, Luc Prefontaine > wrote: > > Having the ability to redefine a function once for all instances is > > something we really want... > > and you need name spaces to be shared for that to happen. > > We take the approach of sharing everything that seems to worth it, then > > we will see > > what we might need to keep private to each JVM. > > > > Sharing var roots and refs also is something we want so we can initiate > > STM transactions > > involving multiple JVMs. > > > > We have much to learn from a prototype and that is what we strive to > > achieve the immediate future. > > After this step, real fun will begin, right now were having only an > > appetizer... > > > > Luc > > > > It would be great if you could mention the difficulties you face as > you go, before you spend too much time on workarounds. I am interested > in seeing Clojure on Terracotta and if there are things I can do > easily to support this effort I will. > > Rich > > > > > > > On Fri, 2009-02-27 at 16:51 -0500, Paul Stadig wrote: > > > Yeah, after sharing clojure.lang.Keyword.table I tried to share > > > clojure.lang.Namespace.namespaces, but ran into a problem because > > > Namespace uses an AtomicReference for its mappings and aliases > > > members. I thought that not sharing namespaces would be a problem (and > > > maybe it still is I don't have as much practical experience with this > > > as you), but I wasn't sure it would be a problem. Looking up a var in > > > a namespace on different JVMs would find different vars, but since > > > they are thread local, then I'm not sure its an issue. Having all of > > > your refs shared without having to specify each specific ref would be > > > interesting, but since most of the stuff (functions, vars, etc.) are > > > immutable or thread local, then I'm not sure how much of an issue it > > > is. > > > > > Obviously, if you were going to redefine some functions or something, > > > then you'd either have to do so on each JVM, or just restart all of > > > the clients. > > > > > And as I said in my article, I didn't do any work with agents, so > > > maybe there's a lot missing from my part of the puzzle. > > > > > Paul > > > > > On Fri, Feb 27, 2009 at 4:37 PM, Luc Prefontaine > > > wrote: > > > > We are trying to get Clojure shared over Terracotta, not just specific > > > > things but the whole Clojure object space > > > > (name spaces, root values, ) except stuff that needs to remain local > > > > (streams, ). > > > > > > We take an all or nothing approach here, we would to see many Clojure > > > > instances work as a single > > > > entity. > > > > > > We are facing a number of issues, one of them being the lack of support > > > > by > > > > Terracotta of AtomicReference. > > > > > > Terracotta has placed this class in the list of classes they will > > > > eventually > > > > support but has of 2.7.3 > > > > it's still not supported. > > > > > > The Sun AtomicReference does peeks and pokes in the heap using internal > > > > routines of the JVM (JNI). > > > > Clearly this cannot be done with multiple JVMs, different object heaps, > > > > > > > > > > Terracotta suggest using the oswego library but since Java 5 has been > > > > out, > > > > it's in maintenance mode only and > > > > integrating another library to the puzzle for that single purpose did > > > > not > > > > look to us as very efficient. > > > > > > So we created a SharedAtomicReference implementation that uses standard > > > > locks to control access to > > > > the value with the corresponding Terracotta configuration. > > > > > > We use a factory to decide at run time which implementation to use > > > > based on > > > > a system property. > > > > To preserve the Clojure code base, we implemented an AtomicReference > > > > interface and a delegate to > > > > the AtomicReference class. The Clojure code uses now interface. > > > > This allows us to
Re: (rest ())
> Were you thinking of what's now called "next" and used to be called "rest"? No. > > Why did you expect nil from rest in this case? I expect: (rest [1]) -> () (rest []) -> nil Starting with the new lazier branch, we have a concept of an empty sequence. So the rest of a singleton yields an empty sequence. But asking for the rest of an empty sequence is very different. Clojure should generate a different kind of value to let you know that you asked for the rest of something that doesn't really have a rest. Just as (first []) yields nil, so should (rest []), IMO. I can't offhand think of a way that the current behavior would break something, but it seems quite illogical to me to say that the rest of an empty sequence is the empty sequence. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Opinions on -> macro?
I think it's simpler just to have a consistent syntax, personally. Otherwise, why not python or haskell style syntax for the language? because code is data. So now there's a special case where the data is backwards. On Fri, Feb 27, 2009 at 1:49 PM, Meikel Brandmeyer wrote: > Hi, > > Am 27.02.2009 um 19:39 schrieb John D. Hume: > > As a Java/Ruby guy who is not used to reading inside out, I'm curious >> as to whether people who ARE accustomed to LISP find the -> macro >> distracting since it flops things around. Are there circumstances >> where you prefer it? >> > > I have a Scheme background and I like -> a lot. I would prefer it > always over > > (foo (bar (baz (frobnicate a-thing)) bla)). > > Eh? To which function belongs the bla argument? I think > > (-> a-thing frobnicate baz (bar bla) foo) > > is much clearer. > > Sincerely > Meikel > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Contributing
I have started looking into Issue 34 and I have some questions. Link: http://code.google.com/p/clojure/issues/detail?id=34&colspec=ID%20Type%20Status%20Priority%20Reporter%20Owner%20Summary Is the desired syntax to match the CL version? Should I create a separate reader for the read-only version or just use an if statement within the EvalReader? Joshua --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Observations about new lazy branch
I just finished porting my combinatorics code to the new lazy constructs, and I discovered some subtleties to using lazy-seq that were not at first apparent. To begin with, consider the two versions of map: The old way: (defn map ([f coll] (when (seq coll) (lazy-cons (f (first coll)) (map f (rest coll) The new way: (defn map ([f coll] (lazy-seq (when-let [s (seq coll)] (cons (f (first s)) (map f (rest s)) Let's imagine that you are using map on a collection for which it is very computation intensive to generate the rest, but trivial to generate the first. I believe that in this case, you'd get more desirable behavior from the old way than the new way. That's because the original lazy-cons kept the first and rest thunks separate. It would force the first to get the rest, but it would NOT force the rest to get at the first. So if you ask for the first, it wouldn't do all the rest-generating computation. However, the new version uses a delayed regular cons. So when you invoke the first of the sequence, both arguments of cons are evaluated, so (map f (rest s)) is called, and therefore (rest s) must be evaluated. If this is unclear, consider this: (defn a [] (do (println "a") nil)) (def s (lazy-seq (cons (a) (a (first s) If you type this into the REPL, you'll see that the rest gets evaluated when you ask for the first. To get the desired separation of first and rest evaluation with the new lazy-seq function, you'd actually need to do something like this: (def lazier-map (let [step (fn step [f coll] (when-let [s (seq coll)] (cons (f (first s)) (lazy-seq (step f (rest s))] (fn [f coll] (lazy-seq (step f coll) Basically, I've made a helper function which uses lazy-seq to delay the evaluation of the rest, and then wrapped the call to the helper function in a lazy-seq in order to delay evaluation of the very first item. As a challenge, try to similarly fix up the version of filter provided on the lazy page so that it fully separates the evaluation of first and rest, thus protecting you against unnecessary evaluation if rest is a slow operation on coll. I think you'll find that you end up with two levels of indirection, and it's extremely difficult to write it properly. Post your simplest solution here. Now in both these examples, you could argue that in all likelihood, rest will be a fast operation. But I chose map here because everyone knows the way we're supposed to write map, so it seemed like a good choice to illustrate my concerns without having to explain how the function works, etc. But this kind of problem does actually occur in practice. It appeared in several places in the code I ported, because my code tends to do most of the work within the arguments to the recursive call. I found it difficult to reason about where to place the calls to lazy-seq in order to achieve the separation I needed for evaluating the first and the rest. I think I pulled it off correctly, but I've got to say I'm not crazy about how, to do the "right thing", the code ends up looking quite obfuscated. In summary, the new version gives you the most power to place the delays where you want, but it's hard to get it right. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Contributing
On Feb 27, 2009, at 10:59 PM, Joshua wrote: Is the desired syntax to match the CL version? Following CL's lead by implementing a *read-eval* var as Stuart suggested looks like a good way to do this to me. Should I create a separate reader for the read-only version or just use an if statement within the EvalReader? A solution based on *read-eval* would use if statement. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: Observations about new lazy branch
If lazy-cons makes your life easier, I think you can still have something very much like it: (defmacro lazy-cons [x s] `(lazy-seq (cons ~x (lazy-seq ~s If you're interested in perf, you'd just have to write your code a bit carefully to avoid double lazy-seq'ing the rests: (defn map [f coll] (lazy-seq (old-map [f coll]))) where old-map is the old version of map (modified to cache the call to "seq"?). Does this make sense? -Jason P.S. thanks for updating combinatorics, I've been waiting for that. On Feb 27, 8:10 pm, Mark Engelberg wrote: > I just finished porting my combinatorics code to the new lazy > constructs, and I discovered some subtleties to using lazy-seq that > were not at first apparent. > > To begin with, consider the two versions of map: > The old way: > > (defn map > ([f coll] > (when (seq coll) > (lazy-cons (f (first coll)) (map f (rest coll) > > The new way: > > (defn map > ([f coll] > (lazy-seq > (when-let [s (seq coll)] > (cons (f (first s)) (map f (rest s)) > > Let's imagine that you are using map on a collection for which it is > very computation intensive to generate the rest, but trivial to > generate the first. > > I believe that in this case, you'd get more desirable behavior from > the old way than the new way. > > That's because the original lazy-cons kept the first and rest thunks > separate. It would force the first to get the rest, but it would NOT > force the rest to get at the first. So if you ask for the first, it > wouldn't do all the rest-generating computation. However, the new > version uses a delayed regular cons. So when you invoke the first of > the sequence, both arguments of cons are evaluated, so (map f (rest > s)) is called, and therefore (rest s) must be evaluated. > > If this is unclear, consider this: > (defn a [] (do (println "a") nil)) > (def s (lazy-seq (cons (a) (a > (first s) > > If you type this into the REPL, you'll see that the rest gets > evaluated when you ask for the first. > > To get the desired separation of first and rest evaluation with the > new lazy-seq function, you'd actually need to do something like this: > > (def lazier-map > (let [step (fn step [f coll] > (when-let [s (seq coll)] > (cons (f (first s)) (lazy-seq (step f (rest s))] > (fn [f coll] > (lazy-seq (step f coll) > > Basically, I've made a helper function which uses lazy-seq to delay > the evaluation of the rest, and then wrapped the call to the helper > function in a lazy-seq in order to delay evaluation of the very first > item. > > As a challenge, try to similarly fix up the version of filter provided > on the lazy page so that it fully separates the evaluation of first > and rest, thus protecting you against unnecessary evaluation if rest > is a slow operation on coll. I think you'll find that you end up with > two levels of indirection, and it's extremely difficult to write it > properly. Post your simplest solution here. > > Now in both these examples, you could argue that in all likelihood, > rest will be a fast operation. But I chose map here because everyone > knows the way we're supposed to write map, so it seemed like a good > choice to illustrate my concerns without having to explain how the > function works, etc. > > But this kind of problem does actually occur in practice. It appeared > in several places in the code I ported, because my code tends to do > most of the work within the arguments to the recursive call. I found > it difficult to reason about where to place the calls to lazy-seq in > order to achieve the separation I needed for evaluating the first and > the rest. I think I pulled it off correctly, but I've got to say I'm > not crazy about how, to do the "right thing", the code ends up looking > quite obfuscated. > > In summary, the new version gives you the most power to place the > delays where you want, but it's hard to get it right. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
Apologies for thread-hijackig but I thought I'd mention that one of the problems I've had using Clojure under OSGi was fixed with a minor patch (mentioned in my post at http://www.talios.com/clojure_running_successfully_under_osgi.htm ) which had to do with the assumption non jar:// classpath entries were File's. Mark ...and then Buffy staked Edward. The End. On Sat, Feb 28, 2009 at 2:25 PM, Rich Hickey wrote: > > now. I'm still thinking about the issues of people running in systems > like OSGi and NetKernel, which may in the end need partitioning of the > namespace stuff from the rest of Clojure, as well as the needs of > those trying to use Terracotta. > --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Observations about new lazy branch
On Fri, Feb 27, 2009 at 8:33 PM, Jason Wolfe wrote: > > If lazy-cons makes your life easier, I think you can still have > something very much like it: > > (defmacro lazy-cons [x s] > `(lazy-seq (cons ~x (lazy-seq ~s As you pointed out, in most contexts, this will double the number of lazy-seq calls, which will really hurt performance. > > If you're interested in perf, you'd just have to write your code a bit > carefully to avoid double lazy-seq'ing the rests: > > (defn map [f coll] > (lazy-seq > (old-map [f coll]))) > > where old-map is the old version of map (modified to cache the call to > "seq"?). Does this make sense? I'm not sure which old-map you mean here. If you mean the old lazy-cons version, using your above macro, this will have too many lazy-seq calls. --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Observations about new lazy branch
> I'm not sure which old-map you mean here. If you mean the old > lazy-cons version, using your above macro, this will have too many > lazy-seq calls. Yeah, you're right ... I managed to confuse myself. Off the top of my head I can't think of a nicer way to write lazier- map than what you've got. Hmmm... -Jason --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Contributing
On Sat, Feb 28, 2009 at 6:13 AM, Stephen C. Gilardi wrote: > > On Feb 27, 2009, at 10:59 PM, Joshua wrote: > >> Is the desired syntax to match the CL version? > > Following CL's lead by implementing a *read-eval* var as Stuart suggested > looks like a good way to do this to me. So, I suppose the "syntax" for this would be something like this: (binding [*read-eval* false] (read ...)) >> Should I create a separate reader for the read-only version or just >> use an if statement within the EvalReader? > > A solution based on *read-eval* would use if statement. -- Michael Wood --~--~-~--~~~---~--~~ You 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---