Re: Duplicated keys in maps
On Sun, Oct 11, 2009 at 8:55 PM, Angel Java Lopez ajlopez2...@gmail.comwrote: Hi people! I just discovered that maps support duplicated keys: user= {:a 1 :b 2 :a 3} {:a 1, :b 2, :a 3} It was not clear to me, from documentation. I presumed that maps are like dictionaries. What is the rationale behind this behaviour? I doubt there is one. I suspect it's a bug. = (assoc {:a 1 :b 2} :a 3) {:a 3, :b 2} = (type {:a 1 :b 2 :a 3}) clojure.lang.PersistentArrayMap = (type (assoc {:a 1 :b 2} :a 3)) clojure.lang.PersistentArrayMap Looks like there's a constructor that breaks the PersistentArrayMap (and Map) contract and is used when building one from a literal. Associng the key-value pairs one by one into an empty map is probably the only way to fix it. Detecting duplicate keys in map literals at read time is NOT enough: =(def x :a) = (def y :b) = (def z :c) = {x 1 y 2 z 3} {:a 1, :b 2, :c 3} = (def z :a) = {x 1 y 2 z 3} {:a 1, :b 2, :a 3} Runtime-variable keys can be duplicates without it being evident at read time, or even predictable at all (equivalent to the halting problem). There are only two behaviors that seem reasonable here, duplicate keys produce a runtime exception or duplicate keys quietly overwrite earlier ones. The latter is achieved by the an array literal is a shorthand for (assoc (assoc (assoc ... (assoc {} k1 v1) ... k2 v2) k3 v3) k4 v4) semantics, whether implemented that way or in some more-efficient way (transients? special constructor?) and both have situations where they might be desirable. I'd argue for the former, it throws an exception, on the basis that explicit associng (or (reduce conj {} [[k1 v1] [k2 v2] [k3 v3]]) or (hash-map k1 v1 k2 v2 k3 v3)) can be used to achieve the latter effect where desired, and most usually duplicate keys would represent an error. Duplicate keys detected at read time (same keyword, quoted symbol/form, string or numeric literal, or var) could of course be reported as errors at the compilation stage. = (reduce conj {} [[:a 1] [:b 2] [:c 3]]) {:c 3, :b 2, :a 1} = (reduce conj {} [[:a 1] [:b 2] [:a 3]]) {:b 2, :a 3} = (reduce conj {} [[x 1] [y 2] [z 3]]) {:b 2, :a 3} = (hash-map x 1 y 2 z 3) {:a 3, :b 2} --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Is there a standard function transforming a map's vals
On Sun, Oct 11, 2009 at 3:17 PM, Daniel Werner daniel.d.wer...@googlemail.com wrote: On Oct 11, 6:02 am, samppi rbysam...@gmail.com wrote: Oops, you're right; I was thinking about something else. And I have another mistake in my function too—I meant: (defn transform-map [f a-map] (into {} (map #(vector (key %) (f (val %))) a-map))) It's unfortunate that it's not in any standard library yet. I've used this function in every single Clojure program that I've written. Ah, well. Konrad Hinsen's generic functor multimethod seems to do exactly what you want: user= (use 'clojure.contrib.generic.functor) nil user= (fmap inc {:a 4, :b 3}) {:a 5, :b 4} Actually it is not limited to maps: user= (fmap inc [4 3]) [5 4] It's just too easy to miss beautiful and useful gems like this in the depths of clojure.contrib. Agreed. That's why I may create a kind of mind map of that library (and throw in clojure.core) that can find functions by, well, function. So all the stuff for manipulating maps can be found, or all the stuff for file I/O, etc. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agents for managing threads
Here is a quickie library for abstracting this: (defn make-actor [f period-in-ms initial-state] (agent (into [f period-in-ms false] initial-state))) (defmacro actor Creates and returns a new, initially-sleeping actor with the specified period, initial parameter values, and code to execute. [period-in-ms initial-bindings body] `(let [p# ~period-in-ms] (make-actor (fn [~@(take-nth 2 initial-bindings)] ~...@body) p# ~@(take-nth 2 (rest initial-bindings) (defn- actor-act [state] (when (nth state 2) (apply (first state) (drop 3 state)) (Thread/sleep (second state)) (send-off *agent* actor-act)) state) (defn- actor-start [state] (send-off *agent* actor-act) (into [(first state) (second state) true] (drop 3 state))) (defn- actor-stop [state] (into [(first state) (second state) false] (drop 3 state))) (defn- actor-change-state [state new-state] (into [(first state) (second state) (nth state 2)] new-state)) (defn start-actor Wakes up an actor -- starts it periodically executing its body. [actor] (send-off actor actor-start)) (defn stop-actor Puts an actor to sleep again. [actor] (send-off actor actor-stop)) (defn change-actor-state Changes an actor's parameter list. [actor new-state] (send-off actor actor-change-state new-state)) Test at the REPL with these: = (def y (actor 1000 [x 1 y 1] (println (+ (* x 10) y = (start-actor y) 11 should start repeating to stdout. = (change-actor-state y 2 2) It should stop repeating 11 and start repeating 22. = (stop-actor y) Output should halt. (start-actor y) Output should resume. (stop-actor y) Output should halt. (change-actor-state y 4 7) No immediate effect. (start-actor y) Output should resume, but printing 47 instead of 22. (stop-actor y) Output should stop. Note that the (actor ...) macro resembles a fn form in use (though destructuring won't work). In the body, the parameters can be referred to by name to use them. When it is called, it is with an ordered list of values to bind to those parameters. The (change-actor-state ...) function is followed by the actor and then such a parameter list, so in the example above since x was the first parameter (change-actor-state y 4 7) binds 4 to x on subsequent executions of the actor body. Under the hood, it's exactly as described: the actor body is wrapped in a fn with those parameter names and the actor is invoked periodically with an argument list, which is replaced by change-actor-state. The actor itself is an agent wrapping a vector with the function, period, awake flag, and current parameters. Trivial additions: creating a (defactor name ...) macro that functions like (def name (actor ...)); adding a change-actor-period function. More interesting, but fairly easy: have the function take one extra parameter, the previous invocation's return value, and specify an initial value for it in (actor ...). This enables the function to maintain a mutable cell of sorts. Nontrivial: add destructuring. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agents for managing threads
On Sat, Oct 10, 2009 at 5:52 PM, Raoul Duke rao...@gmail.com wrote: The actor itself is an agent wrapping a vector with the function, period, awake flag, and current parameters. will actors actually do the queued function w/in a reasonable timeframe? i don't think there are any guarantees of it so if one is hoping to get really nicely periodic behaviour... just curious because i'd thought of using agents for periodic stuff, too. In practice, they seem to. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Another defmult VS defn query
On Thu, Oct 8, 2009 at 10:25 AM, Robert Stehwien rstehw...@gmail.comwrote: (defn mv2 [from to] (let [f (if (= (class from) File) from (File. from)) t (if (= (class to) File) from (File. to))] (println transformed to File))) ITYM t (if (= (class to) File) to (File. to))] for that third line. I have a function as-file I would use for this: (defn as-file [file-or-name] (if (instance? file-or-name java.io.File) file-or-name (File. file-or-name))) Then the above simplifies to: (let [f (as-file from) t (as-tile to)] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: What does this error mean?
On Thu, Oct 8, 2009 at 11:09 AM, Mark Tomko mjt0...@gmail.com wrote: Can you give some more context? The pesky thing about that particular error is that there IS no more context; it fingers no specific line of code, function definition, or whatever as culprit. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agents for managing threads
On Thu, Oct 8, 2009 at 1:06 PM, Laurent PETIT laurent.pe...@gmail.comwrote: So I don't think you need this message-queue at all (or maybe I haven't understood what it is or I'm mislead by its name), send directly your order to the agent as what you want to change in its state. You might be able to do better than that, and dispense entirely with the separate polling thread. Break the state involved in the polling into a variable and a constant part. Constant might be a pocket on a socket on a port, variable a polling/non-polling flag and some other stuff. Wrap the latter in a structure such as a list or a map and stuff it in an agent. Create some functions that close over the former, some to change the agent state and one to do the polling. The polling one should check the are-we-polling flag of the state, return the state if we're not polling, and otherwise poll, sleep however-long, and (send-off *agent* poll), then return the state. The one to turn on polling also needs to end with (send-off *agent* poll) and then return the modified version of the state (with the we're-polling flag assoc'd true). The effect of all this should be: If the agent is told to start polling, it gets enqueued with a poll send-off, and immediately after the last send returns and sets the new agent state, the poll function is then executed. Every however long this repeats. If a state change is sent to a polling agent, it probably arrives during the poll function's sleep. This state change message is thus queued by the agent ahead of the poll message it sends itself at the end of the sleep. So the state change is done next, then the poll, and for that poll the state change should be in effect. If the state change included stop-polling, then since the poll function checks the we're-polling flag and aborts if we're not polling, that next poll is a no-op; in particular, the agent does not send itself another poll message, and will be completely quiescent until sent a start-polling message. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agents for managing threads
On Thu, Oct 8, 2009 at 7:49 PM, John Harrop jharrop...@gmail.com wrote: You might be able to do better than that, and dispense entirely with the separate polling thread. Confirmed: (def x (agent {:polling false :message foo})) (defn poll [m] (when (:polling m) (prn (:message m)) (Thread/sleep 1000) (send-off *agent* poll)) m) (defn set-message [m mess] (assoc m :message mess)) (defn start [m] (send-off *agent* poll) (assoc m :polling true)) (defn stop [m] (assoc m :polling false)) (send-off x start) The message foo should start repeating in the standard-output monitor window of your IDE. (send-off x set-message bar) The message bar should start repeating in the standard-output monitor window of your IDE, in place of foo. (send-off x stop) The output should stop, and look like this: foo foo foo foo bar bar bar with possibly different numbers of repetitions. Seems to indicate that this strategy works beautifully for a periodically-repeating behavior that accepts state-change messages, including start and stop signals. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: immutable defs?
On Tue, Oct 6, 2009 at 9:14 PM, Stephen C. Gilardi squee...@mac.com wrote: `(do (set-validator! (defvar ~name ~init) #{~init}) (var ~name))) Cute hack. Won't work if init is false or nil, though, unless the validator does not trigger on the initial assignment of the value. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: On
On Sun, Oct 4, 2009 at 4:41 PM, samppi rbysam...@gmail.com wrote: I want to do this: (defn a ...) (cache a) ; or (cache #'a) or (cache 'a); it doesn't matter to me ...instead of this: (def a (memoize (fn ...))) That way, it separates the concern of what a does from the optimization I'm doing on it. Now, I'm kind of stuck; how should I do it? (defn cache Replaces the function that the given variable refers to with a memoizing version of it. [fn-var] (??? fn-var (memoize @fn-var))) Why not use a macro? (defmacro cache Replaces the function that the given variable refers to with a memoizing version of it. [fn-var-name] `(def ~fn-var-name (memoize ~fn-var-name))) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: apply for macros?
On Mon, Oct 5, 2009 at 2:38 PM, Meikel Brandmeyer m...@kotka.de wrote: Hi, Am 05.10.2009 um 19:29 schrieb cody koeninger: Here we have the smell! You cannot define functions with a function. You have to use a macro! I am not clear on what you mean by this. From a user's point of view, what is the difference between defining a function, and interning a var with a fn object as its value? user (defn define-function [name] (intern *ns* name (fn [] (str called a generated function: name #'user/define-function user (some-function) ; Evaluation aborted. user (define-function 'some-function) #'user/some-function user (some-function) called a generated function: some-function Or is your point just that #'fn is a macro? I stand corrected. I'd argue that you can define a function within a function, but that interning a var within a function is a smell, and doing it with a constant, rather than argument-supplied or computed, name, in a function or in a macro, is a stench (e.g. (defn foo [x y z] (defn bar ... ))) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Agent send-off: ~20k/s
On Mon, Oct 5, 2009 at 11:51 AM, MarkSwanson mark.swanson...@gmail.comwrote: On Oct 5, 2:45 am, ngocdaothanh ngocdaoth...@gmail.com wrote: I think it is not spawn about 20K agents / second, it is 20K message passings / second. The number is about that of Erlang. As Clojure uses a thread pool for agents I agree 'spawn' was the wrong word. Thanks for the correction. Some confusion here may also be from the subject line. It mentions send-off, which actually can spawn unlimited numbers of new threads. Regular send doesn't, using a fixed thread pool instead. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: apply for macros?
On Sat, Oct 3, 2009 at 6:50 PM, b2m b2monl...@googlemail.com wrote: What macros do y'all have that you want to apply things to? (defn init-funs [name levels] (do (apply-macro create-department-struct name levels) (apply-macro create-process-department name levels) nil)) A call like (init-funs company1 level1 level2) will result in (defstruct company1-department :name :head :level1 :level2) and so on. So I need macros for the benefit of individual strucs and functions for every company, and I need something like apply to pass parameters from the inital function to the macros. This is working by using (eval (apply-macro... as described in a previous posting in this thread. It would be nice to have a solution without eval. But maybe my attempt of writing code that writes code is too enthusiastic. Not really. But since you're automating generation of deffoos (in this example, defstructs) you can, and should, use macros all the way down. I.e. init-funs can, and should, be a macro above and it can then just be: (defmacro init-funs [name levels] `(do (create-department-struct ~name ~...@levels) (create-process-department ~name ~...@levels) nil)) or similarly as the case may be. If you need to be creating these things dynamically, with information only available at runtime, defstruct is probably the wrong tool for the job, or the only struct member should be :name, and the levels at least should just be ordinary map keys (not struct keys); then you can dispense with init-funs entirely, and replace the call currently used to get a new instance of the struct with a call that given a name, figures out the appropriate levels (from a name to level-name-list hashmap you maintain at runtime) and initializes a structmap with the :name struct-key set appropriately and also empty lists for each level-name key appropriate for that name. Or something like that. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: apply for macros?
In the specific cases of and and or, I made utility functions that do non-short-circuiting and and or for use with apply and a stream of boolean data. (Not sure which implementation is more efficient though: a version that returns its argument with one argument, punts to the appropriate macro with two, and uses recur with more than two; a version similar to that that uses reduce with more than two; or a higher-level (every? identity args) / (some? identity args). The latter are clearly more elegant, but speed is a concern with something that might be used often.) What macros do y'all have that you want to apply things to? Most likely what you need is to make a version that's a function, if you can live without some deferred/selective evaluation of arguments type feature (like the short-circuiting of and). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Problem using shell-out in Windows command prompt
On Thu, Oct 1, 2009 at 1:39 PM, Nick Day nicke...@gmail.com wrote: Hey, I've just been trying to run a couple of simple commands using shell- out (e.g. (sh dir)) in a repl in Windows command prompt, but am running up against errors of the type java.io.IOException: Cannot run program dir: CreateProcess error=2, The system cannot find the file specified (NO_SOURCE_FILE:16) Shell built-in commands. If you're directly launching an external process from the JVM, there's no dir executable to find. You need to invoke it in the command interpreter instead of directly. I'm unsure how to do that. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Citing clojure
On Thu, Oct 1, 2009 at 3:42 PM, Dragan Djuric draga...@gmail.com wrote: I usualy cite Rich's conference paper and Stuart's book. @conference{hickey2008clojure, title={{The Clojure programming language}}, author={Hickey, R.}, booktitle={Proceedings of the 2008 symposium on Dynamic languages}, year={2008}, organization={ACM New York, NY, USA} } Eeeuw. What a non-Lispy syntax. What is that, anyway? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: server-socket on exit event
On Thu, Oct 1, 2009 at 4:02 PM, Roger Gilliar ro...@gilliar.de wrote: Am 01.10.2009 um 21:28 schrieb ngocdaothanh: Roger, your code is not event based. What do you mean by not event based ? He means he wants automatic notification if a connection is dropped. I'm not sure TCP/IP has a native facility for that. What most chat type programs, multiplayer games, and suchlike do is send a periodic ping from server to each connected client, which as part of the chat protocol the client is supposed to acknowledge. If a client stops responding for more than a few ping-intervals, it's assumed to have disconnected or otherwise become unreachable. This method has the advantage of being entirely under the control of the application layer, and the further advantage of also working with UDP (which is crucial in the multiplayer games case at least). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: ClojureCLR installation?
On Tue, Sep 29, 2009 at 7:21 PM, David Miller dmiller2...@gmail.com wrote: Mono: - One BigDecimal implementation away from getting serious about this. Why doesn't Mono have a BigDecimal analogue? It shouldn't, in principle, be difficult to create an open-source-friendly implementation backed by GMP. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: how to understand macro in clojure?
On Mon, Sep 28, 2009 at 5:23 AM, Jarkko Oranen chous...@gmail.com wrote: What happens is, when you call (mfloat + 1 2) the macro evaluates ('+ (float 1) (float 2)), ie. it calls the *symbol* + with parameters 1.0 and 2.0. Symbols, when used as functions, look themselves up in whatever associative thing you give them as the first parameter, OR return the second parameter in case of lookup failure. So, ('+ 1.0 2.0) evaluates to 2.0, which is the macro expansion. and as 2.0 evaluated is 2.0, it is the actual result. Very sneaky. Why is invoking a symbol returning the second argument even when the first is not an associative thing at all? It should probably return the second argument (defaulting to nil) on not-found but not on genuine errors. A ClassCastException java.lang.Float cannot be cast to clojure.core.IAssoc (or whatever) would have been more informative in this case. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mocking?
On Mon, Sep 28, 2009 at 9:20 AM, Laurent PETIT laurent.pe...@gmail.comwrote: 2009/9/28 C. Florian Ebeling florian.ebel...@gmail.com In Java I'd just have an interface with two implementations, and bootstrap the tests with a different implementation, in clojure I guess I'd do something like: (in-ns `some.thing) (defn foo [] nil) or something? That would consitute a root binding because of the 'defn, but you need a dynamic rebinding. This is what you can use: (binding [existing-function (fn [a b] ...)] ;; your tests here ) But as soon as your application becomes smart enough to do things in parallel (e.g. create and send an e-mail in a separate thread), just using dynamic binding in tests may not be enough, still the binding will not be seen by default by other threads. Does fixtures get around that? Perhaps by saving the root binding, redef'ing it, and later restoring 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Mocking?
On Sun, Sep 27, 2009 at 8:06 PM, Stuart Sierra the.stuart.sie...@gmail.comwrote: On Sep 27, 12:55 am, Mark Derricutt m...@talios.com wrote: How are people handling mocking/stubbing in clojure? Google finds me some old posts about a called? function/macro as part of test-is which looks like it'd do what I need but I can't seem to find any trace of it under clojure/clojure-contrib trunk. clojure.contrib.test-is (now clojure.test) has a fixtures feature. It doesn't do mocking itself, but provides a mechanism for temporarily rebinding vars in your tests. Isn't (binding [foo bar] ...) already such a mechanism? Or does the fixtures feature let you specify such a binding for a whole group of tests obviating the need to repeat the binding form in multiple test functions, and perhaps let mutable state carry forward through multiple tests instead of being rebound (and thus reset) after each one? (And why does the gmail interface seem designed to encourage users to top-post?) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros, namespaces, and lexical scope
On Fri, Sep 25, 2009 at 4:49 PM, Constantine Vetoshev gepar...@gmail.comwrote: (let [f1 #(inc %)] (defmacro m1 [x] `(~f1 ~x))) (m1 12) = No message. [Thrown class java.lang.ExceptionInInitializerError] The equivalent works in Common Lisp (Allegro CL and SBCL): (let ((f1 (lambda (y) (1+ y (defmacro m1 (x) `(funcall ,f1 ,x))) (m1 12) = 13 Thoughts on either of these brain teasers? I don't think you can use things like defmacro in a let. Macros are used at macroexpansion time and I don't think a let's bindings will exist yet. So you probably need something like (defmacro m1 [x] (let [f1 #(inc %)] `(~f1 ~x))) instead. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros, namespaces, and lexical scope
On Fri, Sep 25, 2009 at 8:48 PM, Constantine Vetoshev gepar...@gmail.comwrote: On Sep 25, 6:02 pm, John Harrop jharrop...@gmail.com wrote: I don't think you can use things like defmacro in a let. This works: (let [y 10] (defmacro m1 [] `(list ~y))) (m1) = (10) Well, that's weirdly inconsistent. It shouldn't work just *some* of the time. Either it should work, or it shouldn't work. According to the language semantics, it should work if let bindings wrapping def forms are in effect during any side effects of the def form, and should fail otherwise. Anyone knowledgeable about clojure internals have any idea why it would work sometimes, but only sometimes? Did you get a detail message or stack trace from the exception you saw? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: trouble running clojure.test
On Wed, Sep 23, 2009 at 12:29 PM, MarkSwanson mark.swanson...@gmail.comwrote: Environment: vimclojure-2.1.2. clojure from git as of a few days ago. Running the tests in a plain REPL from the command line worked perfectly! -=* THANKS GUYS !!! *=- I wasn't expecting this at all. I thought the REPL in vimclojure actually supported stdout because this works: (def a abc) #'user/a a abc (println a) abc nil I have noticed that mouse paste operations into the vimclojure repl fail (the pasted text is truncated after a certain number of characters). These seem to be indications that stdin/stdout is not handled perfectly by vimclojure... I'm not surprised. In fact I am surprised that mouse paste operations work at all in an editor that legacy. I've noticed that us NetBeans users have an environment that just works, including mousing and pasting into the REPL as well as stdout displaying correctly, while a quarter of the list traffic here deals with problems configuring either emacs or vim, or quirky post-configuration behavior from same. :) Modern IDEs for the win? But assuming you'd rather not change environments, I'd suggest not using whatever crummy mouse and clipboard support has been retrofitted onto vim and instead use your terminal emulator's paste that will present the pasted text to vim as if it were being typed into vim. That should work however long the pasted text is, unless the terminal emulator paste is equally broken, which if it's xterm it shouldn't be, and otherwise you should probably use xterm. :) (No flames please. The above is offered as observations and a possible workaround in the spirit of suggesting possible fixes so the O.P. can get on with actually developing whatever they're developing with a minimum of fuss and distractions.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Getting REPL transcript
On Wed, Sep 23, 2009 at 1:05 PM, Fogus mefo...@gmail.com wrote: If you're running it with JLine, then the transcript is usually stored in ~/.jline-clojure.lang.Repl.history Actually, that suggests a more general point: that we can have programmatic access to the REPL's backlog if we modify the REPL process's Java code somewhat. A simple example would be to make a repl.class that would provide an interactive stdin/stdout repl but log everything to a ./repl.log file or whatever. This could be used to obtain a text file with the interaction history afterward, to massage, cut and paste from, etc. to one's heart's content in a text editor. Even on MS-DOS, if anyone still uses such a dinosaur. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: question regarding agents
On Wed, Sep 23, 2009 at 4:18 PM, Roger Gilliar ro...@gilliar.de wrote: I have the following code: (defn handle-client [in out] (binding [ *in* (reader in) ] (with-connection db (let [outstream (agent (writer out))] (loop [] (let [xml (read-input)] (if xml (do (send-answers (parse outstream (makestr xml))) (recur)) (info disconnected The problem is, that it doesn't work to assign an agent to the outstream. If I do, the content of the agent (the outstream in this case) is set to nil after it is passed to send-answers and all send- answers does is to store the agent in a struct. Why that ? Wrapping a mutable thing like an output stream in an agent seems dubious to me. Then you don't dereference it -- you pass the agent itself to parse as its first argument, rather than the stream it wraps. That might not have been what you intended. Try just dropping the (agent ...) around (writer out). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Catching from Eval
On Wed, Sep 23, 2009 at 6:42 PM, Phil Hagelberg p...@hagelb.org wrote: What's going on here? The exception is being transformed. Eval and just about anything using closures -- just about any delayed evaluation, in other words -- wraps exceptions in RuntimeException for some reason. Even if they already were RuntimeExceptions (and InterruptedException isn't). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Namespace/class visibility in eval
On Tue, Sep 22, 2009 at 6:46 PM, Eric Tschetter eched...@gmail.com wrote: If I do just curl 'http://localhost:43034/1.0/cloj' -H 'content-type: application/clojure' -d '(json-str {:howdy [hi 1 2 3]})' I get this exception java.lang.Exception: Unable to resolve symbol: json-str in this context (NO_SOURCE_FILE:0) Looks like only clojure.core is imported as far as read/eval is concerned. Something like this curl -v 'http://localhost:43034/1.0/cloj' -H 'content-type: application/clojure' -d (require 'clojure.contrib.json.write) (json-str {:howdy [\hi\ 1 2 3]}) Doesn't work because I'm only read/eval'ing one thing. Wrap the require and json-str in a do. Or, modify your original code so that what read operates on includes this require. Something like: (defroutes evallerificator (POST /1.0/cloj (eval (list `do `(require (quote clojure.contrib.json.write)) (read (PushbackReader. (InputStreamReader. (request :body))) (GET / (html [:h1 Hello World])) (ANY * (page-not-found))) or, if that doesn't work (it proves to be read that does symbol resolution), (defroutes evallerificator (POST /1.0/cloj (eval (read-str (str (do (require 'clojure.contrib.json.write) (slurp (PushbackReader. (InputStreamReader. (request :body ) (GET / (html [:h1 Hello World])) (ANY * (page-not-found))) (untested!) But, this looks like a gaping security hole. You're taking an HTTP POST request body and eval'ing it. Someone will, sooner or later, try typing (delete all the secret files) into the web form and clicking Send. Or worse, something that will actually delete something or grant privilege. Sending (doall (iterate inc 1)) will crash the server with OOME after a lengthy 100%-cpu-use hang while it fills memory with consecutive Integer objects, for a cheap and easy DoS attack. And so forth. The last example shows that even vetting the incoming string for I/O is not enough protection. (And the incoming string could sneak I/O in in numerous ways; a lengthy computation could assemble a dynamic string equal to with-open or InputStream and another equal to a file path (/etc/passwd anyone?) and combine them. It might use symbol or read, then eval. Blocking eval just makes them resort to cobbling together classnames and method names from obfuscated fragments and then invoking Java reflection, e.g. Class/forName. Maybe if you blocked every Java reflection-related class name as well as read, eval, and the Clojure I/O forms -- but even then someone can request an infinite seq be doall'd or similarly to cause some amount of trouble, even if deleting files or creating a privileged account on the server machine is placed out of their reach.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Q: why doesn't this script terminate
On Mon, Sep 21, 2009 at 2:22 PM, Richard Newman holyg...@gmail.com wrote: But this script doesn't terminate. I have to press ctr-c to end this script. It seems that there a still some threads active. why ? http://www.mail-archive.com/clojure@googlegroups.com/msg13865.html Your response was longer than (shutdown-agents) would have been. Furthermore, in my experience almost no-one likes posts consisting solely of a blind URL. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: problem with threading and sql lib
On Sat, Sep 19, 2009 at 1:07 AM, Roger Gilliar ro...@gilliar.de wrote: Hi, re you opening something, using it to return a lazy sequence, and then closing it before consuming the sequence? No. I started with just opening the database connection in the handler function. You mention threading in the subject and you have a (binding [...] ...) form. Are you starting a thread, or communicating with one, or using pmap, future, an agent, or etc. inside the binding, and expecting the binding to affect the code that runs in the thread/map/future/agent? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: problem with threading and sql lib
Nothing leaps out at me as a likely cause of a dropped message. OTOH, the loop/recur at the end is probably better changed to a doseq. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Anyone care to defend/comment some points in this presentation
On Fri, Sep 18, 2009 at 8:34 AM, Mark Volkmann r.mark.volkm...@gmail.comwrote: On Thu, Sep 17, 2009 at 5:22 PM, John Harrop jharrop...@gmail.com wrote: On Thu, Sep 17, 2009 at 3:06 PM, Mark Volkmann r.mark.volkm...@gmail.com wrote: On Thu, Sep 17, 2009 at 1:43 PM, z5h bolusm...@gmail.com wrote: Specifically some problems encountered in Clojure's STM and bytecode generation. http://www.azulsystems.com/events/javaone_2009/session/2009_J1_JVMLang.pdf (Slide's 8 and 20-21) Slide 20 - Should say Nothing mutable by default and One kind of mutable, Refs, guarded by STM There are three more kinds of mutable: atoms, agents, and mutable Java objects. Of those, the latter are to be avoided where possible though, and only agents are also guarded by STM in any manner. Agents are not guarded by STM. It is Refs that can only be modified in a transaction. There is a connection between Agents and STM though. If you send an action to an Agent within a transaction, it won't actually be sent until changes to Refs in the transaction have been committed. That is what I meant by in any manner; that there's some interaction with STM. In the case of agents there's no guarding outside of a transaction context, whereas refs cannot be modified outside of a transaction so are guarded all the time in some sense. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: problem with threading and sql lib
On Fri, Sep 18, 2009 at 1:32 PM, rogergl ro...@gilliar.de wrote: The problem is that the above code only works if I establish a connection outside the handle-client function. Otherwise the first reply to my client gets lost. Has anyone an explanation for this ? Are you opening something, using it to return a lazy sequence, and then closing it before consuming the 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: OutOfMemoryError with loop/recur
On Fri, Sep 18, 2009 at 4:39 PM, Tassilo Horn tass...@member.fsf.orgwrote: Although that doesn't really help, the normal `reduce' doesn't do better. (reduce + (take 100 (iterate inc 1))) ; works (reduce + (take 1000 (iterate inc 1))) ; OutOfMemoryError Are you sure? I'd expect that with (def integers (iterate inc 1)) (reduce + (take 1000 integers)) but not with what you wrote. If it does happen with exactly what you wrote then clojure.core/reduce is holding onto the head, or you had a funny substitute reduce in whatever namespace you evaluated those in. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Silly Convention Question
On Fri, Sep 18, 2009 at 4:45 PM, CuppoJava patrickli_2...@hotmail.comwrote: Hi, After I shot myself in the foot again this morning by naming one of my variables cond and then wondering why Clojure was complaining about a simple cond form, I thought why don't we have capitalization conventions that differ between variables and functions? Everything in Clojure is lowercase. Are people too opposed to variable names beginning with an upper case character? In Java, names that begin with upper case characters denote classes, but class names are much less often to be seen in Clojure. Thoughts? A decent IDE will alert you with syntax highlighting (NetBeans w/ enclojure does, in particular). It is a bit of a bother that many commonly desirable short-and-meaningful variable names would shadow clojure.core names or special forms: fn, map, seq, vec, key, value, and plenty more. I find myself often using names like f, m, s, k, and v, or similarly. Sometimes a more meaningful name still is possible, generally in higher level code; accounts-map for instance. In lower level code though, you may have say a function that does some kind of reduction over a map with a particular key. This function is agnostic to whatever higher purpose the map may serve; it's called by, rather than part of, the business logic. So what do you call its parameters? I wind up with f, m, and k; it's that or something like the-fn, the-map, and the-key and that seems verbose. This arises with any function that performs a generic transformation of data agnostic as to that data's business-logic purpose. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: OutOfMemoryError with loop/recur
On Fri, Sep 18, 2009 at 3:52 PM, Patrik Fredriksson patri...@gmail.comwrote: Hi! Could someone please help me understand why the following causes a java.lang.OutOfMemoryError: Java heap space for large n:s (10 works fine, 100 does not). (def integers (iterate inc 1)) (defn limited-reduce [fn coll n] (loop [c coll i n result 0] (if (zero? i) result (recur (rest c) (dec i) (fn result (first c)) (limited-reduce + integers 10) Many thanks! With (def integers (iterate inc 1)) you're holding on to the head of the sequence. Try it with (defn integers [] (iterate inc 1)) and (limited-reduce + (integers) 100) and the OOME should not occur. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Ensure and STM: find the bug...
On Thu, Sep 17, 2009 at 11:04 AM, Mark Volkmann r.mark.volkm...@gmail.comwrote: On Thu, Sep 17, 2009 at 9:57 AM, Chouser chou...@gmail.com wrote: On Thu, Sep 17, 2009 at 12:28 AM, Krukow karl.kru...@gmail.com wrote: Final question. The docs say that 'ensure' permits more concurrency than promoting the ref to a write. Is there a quick/simple way of explaining how? (Or do I need to go to the source :-) If you have multiple transactions ensuring the same var but no transactions changing it, all those transactions can proceed simultaneously. If they all did dummy writes instead of ensure, they could only proceed in order. Ah ... I think I misunderstood an important part of the question. I wasn't assuming that all the concurrent transactions were going to use ensure or a dummy write on the same Ref. So the key is that multiple transactions can successfully ensure the same Ref, but multiple transactions cannot successfully write the same Ref. Not with ref-set! or alter!, but maybe with commute identity? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Ensure and STM: find the bug...
Don't commutes commute with one another, but not with other writes? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Redefining Special Forms
On Thu, Sep 17, 2009 at 2:49 PM, Stuart Sierra the.stuart.sie...@gmail.comwrote: On Sep 17, 12:40 pm, Gorsal s...@tewebs.com wrote: Oh. And just as a quick other question, do global bindings affect threads which are started in the same ns? I think threads inherit the bindings in effect when they are created. http://clojure.org/vars strongly implies otherwise; that they see the root bindings except while a (binding [foo bar] (baz)) form is executing in the same thread. Having heritable bindings could be useful, though. Yet wouldn't work for cases like pmap. Best might be to just use atoms when you want non-thread-local dynamic bindings: (untested) (def multiplier (atom 3)) (defn magnify [x] (* multiplier x)) (defmacro with-atom-value [[at v] body] `(let [a# ~at x# (deref a#)] (reset! a# ~v) (try ~...@body (finally (reset! a# x#) ... (with-atom-value [multiplier 4] (pmap magnify some-seq)) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Redefining Special Forms
On Thu, Sep 17, 2009 at 6:15 PM, Gorsal s...@tewebs.com wrote: Or maybe i could simply push to the global var and in addition to the value use a unique gensymed id. Then once the local binding was done it would pop until it sees its gensymed id. That would work in the situation that a local binding failed to pop its own binding. That might work... Why not just use an atom, if you want it globally, or a single global var and binding, if you want thread-local values. If you want it changed globally but put back after, save the value and use try ... finally to ensure it gets put back. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: minor grievance with arithmetic on characters
On Tue, Sep 8, 2009 at 8:18 PM, Timothy Pratley timothyprat...@gmail.comwrote: Hi Steve, I find the -1, 0, 1 result more useful, but am also wary it hides some useful information. My preference would be to have the doc-string changed to what you proposed and keep the neg/pos behaviour of .compareTo in place. To get -1, 0, 1 requires a 'sign' operator which is handy to have as a separate function - might be a candidate for contrib? (defn sign Returns 1 if x is positive, -1 if x is negative, else 0 [x] (cond (pos? x) 1, (neg? x) -1, :else 0)) (defn sign Returns 1 if x is positive, -1 if x is negative, else 0 [x] (compare x 0)) If that doesn't work, then compare on numbers is likely to fail for widely-separated numbers due to integer underflow or overflow if the Java compareTo being called does so; compareTo is defined in interface Comparable as returning a Java int, which has 32 bit range; there's a reason it's recommended to implement compareTo using or , ==, ?:, and the literal values -1, 0, and 1. The char comparison using subtraction is safe since all differences between 16-bit numbers fit in an int, but this is not true for int, long, or bignum comparison by subtracting and then narrowing to int. For the native Java Integer, Long, and BigInteger types this is highly unlikely to be the case. I'm hoping Clojure's Ratio class's compareTo is also safe. This is assuming the Clojure compare function on numbers works by coercing them along the graph Byte-(Short,Character)-Int-Long-BigInteger-Ratio-BigDecimal, Float-Double-BigDecimal and then using compareTo, as seems likely. (I don't currently have my REPL or the source code handy to check.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: dynamic :use
Or, you can go the opposite way and write a macro that expands into the appropriate ns form. This will work if the information you need from *db-adapter* is there by macroexpansion time. A macro that does a similar job to ns, but adds conditional features to the ns DSL, can wrap and generalize what Chouser suggests and will work if *db-adapter*'s information isn't available until runtime. The macro would allow something like what you originally tried to do, with your-ns replacing ns, and expand in that case into code like Chouser suggested. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: best way to make use of association lists
On Mon, Sep 7, 2009 at 5:19 PM, Conrad drc...@gmail.com wrote: Alternatively, I suppose it would be possible to create a new type of map that performs better than an alist but can return items in the order they were added to the list, if desired Or use an existing type: the java.util.LinkedHashMap. The downside is, it's a mutable Java Map and not a Clojure map. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Tight loop performance
Besides using just aset, try using unchecked-inc instead of 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Tight loop performance
Try unchecked-inc and try wrapping the function body in (let [words (int words)] ... ). I don't know why aset is still reflecting when all of the arguments are type-hinted, but the above changes might speed up some other bits of the code. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Filter Causing StackOverflowError?
On Wed, Sep 2, 2009 at 1:02 PM, tmountain tinymount...@gmail.com wrote: Hi all - I've recently encouraged a friend to start learning Clojure, and he has written some basic Markov chaining code as a learning exercise. His code works fine with small sets of input data, but larger inputs have been causing a StackOverflowError. I've taken a look at the code and suspect that the error may be caused by recurrent calls to filter occupying increasing amounts of stack space due to filter leaving closed-over locals hanging around. That being said, this is only a suspicion, I'm still learning the language myself, so I could be totally wrong. Wrapping the filter calls in doall seems to prevent the problem from happening, but performance is abysmal in that case. The problem is laziness: you have a loop/recur that layers on successive filters. Then when you go to realize an element, it calls filter, which calls filter, which calls filter ... however deep. Unfortunately, if you apply successive lazy operations to a seq in a loop/recur you sort of lose tail optimization because of this, and there doesn't seem to be a way to make lazy operations that call other lazy operations tail-optimized. At least, not yet. At least for now you will probably have to doall the seq every so many iterations to avoid the stack overflow. If doing it every iteration kills performance, you might try doing it every Nth for some value of N that's reasonably large, but small enough to avoid the overflow. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Two possible additions: non-reflective classobject calls support for map-conj on arrays
On Tue, Sep 1, 2009 at 10:40 AM, Rich Hickey richhic...@gmail.com wrote: On Mon, Aug 31, 2009 at 10:55 AM, Krukowkarl.kru...@gmail.com wrote: I have two minor minor suggestions for Clojure changes. 1) Consider this function: user (set! *warn-on-reflection* true) true user (defn reader-from-classpath [s] (- (.getResourceAsStream java.lang.String s) (java.io.InputStreamReader.) (java.io.BufferedReader.))) Reflection warning, NO_SOURCE_PATH:2 - call to getResourceAsStream can't be resolved. #'user/reader-from-classpath In general, I think every call of form (.instanceMember Classname args*) will generate such a warning since it expands to, e.g., user (macroexpand ' (.getResourceAsStream java.lang.String s)) (. (clojure.core/identity java.lang.String) getResourceAsStream s) user #1 is fine idea. I've implemented the hinting in the compiler where that expansion takes place. (commit e45046da8f) Why is there a call to identity at all? Why not just (. java.lang.String getResourceAsStream s)? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: vs. Python
On Mon, Aug 31, 2009 at 5:15 PM, Brian Hurt bhur...@gmail.com wrote: If I recall correctly (and correct me if I'm wrong), Python uses a reference counting garbage collector. Which means as soon as the reference to the object goes away, the object gets collected and the handle closed. Most JVMs use some form of mark sweep algorithm, which means it may be some time before the object gets collected (and the resource freed). This is especially the case in a generational GC system, where long-lived objects get collected much less frequently. So, for long-running programs, it's possible to pile up uncollected resources to the point where you run out of the resource, simply because unused objects haven't been collected yet. This suggests that when low-level JVM functions that try to get a file handle, socket, or what-not from the OS fail they should invoke the garbage collector in a full stop-the-world collection and then retry, just as the memory allocator already does, and throw the IOException only if they still fail afterward. (These resources tend to have finalizers, so the GC should be run twice back-to-back to collect them, or even repeatedly until no garbage was collected.) Then most cases of this would cause the occasional very slow file handle acquisition instead of a crash or other error. Generally, when you open a file descriptor, you should always make sure it's gets closed when you're done with it. But I do agree with this. Finalizers and gc of objects holding native resources are a safety net; it's better not to fall into it even when it's there. You might not die but the judges will be holding up placards reading 0.0, 0.1, 0.0, 1.2, 0.3 or some such after your performance. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: vs. Python
On Mon, Aug 31, 2009 at 5:04 PM, Brian Hurt bhur...@gmail.com wrote: On Sun, Aug 30, 2009 at 9:31 AM, Jason Baker amnorv...@gmail.com wrote: On Aug 30, 2:24 am, Dan Fichter daniel.fich...@gmail.com wrote: The Clojure version is more concise and radically safer but a little more conceptually packed. Is it worth your trouble? Being primarily a Python programmer, I can say that the first thing my co-workers would say is that Clojure isn't as readable as Python is. Any language you are familiar and comfortable with is going to seem much more readable and much more intuitive than a language you are unfamiliar with. Even similarity to English presupposes a familiarity with and comfort with English- something most people on this planet don't have. A native English speaker would find a programming language whose syntax was based on, say, Mandarin or Swahili, very unintuitive. The point here is that arguing in favor of a new language on the basis of intuitiveness and readability is a losing argument. That may depend on the audience. If the audience is a bunch of Python programmers, similarities to Python may be quite relevant and not comprise a losing argument. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: A complete documentation (downloadable)
On Mon, Aug 31, 2009 at 3:45 PM, freddi301 gobi...@gmail.com wrote: are there a complete clojure documentation ? There's the documentation at clojure.org; you could spider it with wget, though with some sites you need to spoof the user-agent and/or hack wget to disable retrieving robots.txt to do that. (Ethical, IMO, if your intent is to save hammering that server for bandwidth in the future by having a local copy.) There's also the (doc foo) form at the repl. All the API documentation is there. Unfortunately, *only* the API documentation is there; it would be nice if, at the very least, (doc a-special-form-name) provided a brief synopsis instead of just the web site's URL, for the convenience of having more of it in one place and zero task-switches away from your open project windows, and also more information findable via find-doc. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure/EPL and the GPL
On Sun, Aug 30, 2009 at 7:57 AM, Jan Rychter j...@rychter.com wrote: Tassilo Horn tass...@member.fsf.org writes: [...] BTW: What's the reason that Clojure is licensed under the EPL and the contrib stuff under CPL? Since clojure is not really eclipse-related, I don't see a good rationale. IMHO, the Lesser GPL would be a much better fit. Then you can use clojure also in commercial apps (I guess that was the rationale behind EPL), but still you can use it in projects with any other free-software license, may it be EPL, GPL or whatever... The GPL and LGPL are very restrictive licenses. While most people only focus on the source code availability issue, the real show-stopper for most commercial usage is the anti-patent clause that exists in both the GPL and LGPL. This clause is a potential landmine, even though little attention is paid to it. It exists in the same form in both the GPL and LGPL. Version 3 only, and according to http://news.cnet.com/FSF-rebuts-anti-GPL-3-claims/2100-7344_3-6119987.html The Linux programmers also expressed concern that a new patent provision in the draft GPL 3 poses risks to corporations' patent portfolios--a concern shared by Hewlett-Packard. The foundation said that interpretation is incorrect. The GPL 3 simply says that if someone has a patent covering XYZ, and distributes a GPL-covered program to do XYZ, he can't sue the program's subsequent users, redistributors and improvers for doing XYZ with their own versions of that program, the foundation said. This has no effect on other patents which that program does not implement. Which means it only affects software patents (which have just been rendered invalid by in re Bilski anyway) and only to the extent of indemnifying users and distributors of a GPL-covered program from infringement claims arising from the use and distribution of that code. If they, say, infringed an HP patent on print head design making a laser printer they'd not be covered; HP could still sue. It no more affects a company's important patents than any version affects a company's important copyrights. It just stops them extending same to the GPL'd code and making it effectively proprietary. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Why am I getting this performance result from Clojure CLR's LispReader?
On Sun, Aug 30, 2009 at 10:40 AM, Jason Baker amnorv...@gmail.com wrote: I've written a test that does this: public void ReadFile(TextReader infile) { using (var text_reader = new PushbackTextReader(infile)) { LispReader.read(text_reader, false, null, true); } } ...in a loop. I'm running this operation a specified number of times and then getting an average runtime. The thing is, if I run this more times, the average time goes down. Is something getting cached and/or memoized somewhere, or is this just a bad way to test performance? (And FYI, the TextReader that's getting passed in is a StringReader so I can eliminate I/O time from the results) Given that last, I/O buffering and OS disk caching seem doubtful. JIT perhaps. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: assoc-in-by
On Sun, Aug 30, 2009 at 4:14 PM, kyle smith the1physic...@gmail.com wrote: I wrote this based on assoc-in. If anyone thinks this should be in core or contrib, feel free to use it. (defn assoc-in-by 'Updates' a value in a nested associative structure, where ks is a sequence of keys and (f v) is the new value and returns a new nested structure. If any levels do not exist, hash-maps will be created. [m [k ks] f] (if ks (assoc m k (assoc-in-by (get m k) ks f)) (assoc m k (f (get m k) Nifty and seems to work. Here's a little demo: user= (assoc-in-by nil [:a :b :c] #(if (nil? %) 1 (inc %))) {:a {:b {:c 1}}} user= (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %))) {:a {:b {:c 2}}} user= (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %))) {:a {:b {:c 3}}} user= (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %))) {:a {:b {:c 4}}} which has a counter incrementing. And it's swap! and alter!-compatible: (swap! foo assoc-in-by [:a :b :c] #(bar % baz)) Maybe a version that takes more args? (defn assoc-in-by 'Updates' a value in a nested associative structure, where ks is a sequence of keys and (f v) is the new value and returns a new nested structure. If any levels do not exist, hash-maps will be created. ([m [k ks] f] (if ks (assoc m k (assoc-in-by (get m k) ks f)) (assoc m k (f (get m k) ([m [k ks] f args] (if ks (assoc m k (assoc-in-by (get m k) ks f args)) (assoc m k (apply f (get m k) args) which simplifies the swap! example to: (swap! foo assoc-in-by [:a :b :c] bar baz) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure/EPL and the GPL
This is a problem. The GPL is a very popular open source license. If a language does not permit developers to use the GPL, that language may be severely reducing the number of developers willing to adopt it. It would be desirable for clojure.lang and clojure.core to use a modified license, something perhaps describable as EPL with classpath exception, that expressly allows linking with GPL code (with classpath exception or similar to avoid violating the GPL instead). Alternatively, dual-licensing lang and core under both the GPL and the EPL would be possible. Thanks to the contributor agreements, it wouldn't be necessary to track down all the contributors and get their individual permission for this, unless the agreements had reciprocal clauses limiting how Rich could relicense the code base. (I haven't seen them, so wouldn't know.) Regardless, this problem bears thinking about and perhaps eventually doing something about. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure/EPL and the GPL
On Sat, Aug 29, 2009 at 12:00 PM, Rich Hickey richhic...@gmail.com wrote: This has been discussed as nauseam before: http://groups.google.com/group/clojure/browse_frm/thread/6e99caafcf2bbedf/b5519cc219a5baeb Nothing has changed, so let's give it a rest, please. This may be a tempest in a tea-pot, at least where GPLv3 is concerned: http://www.gnu.org/licenses/quick-guide-gplv3.html Both versions of the GPL require you to provide all the source necessary to build the software, including supporting libraries, compilation scripts, and so on. They also draw the line at System Libraries: you're not required to provide the source for certain core components of the operating system, such as the C library. GPLv3 has adjusted the definition of System Library to include software that may not come directly with the operating system, but that all users of the software can reasonably be expected to have. For example, it now also includes the standard libraries of common programming languages such as Python and Ruby. If the software is written in Clojure, then clojure.jar is something that all users of the software can reasonably be expected to have, is it not? That means clojure.jar can be combined with GPLv3 code, if I'm not mistaken, since doing so apparently doesn't violate the GPLv3 or the EPL. It even apparently allows combining with GPLv2 or any later version in that anyone redistributing it can (but must) use GPLv3 or later. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Java STM
On Fri, Aug 28, 2009 at 4:45 AM, peter veentjer alarmnum...@gmail.comwrote: Clojure's STM is part of a holistic language design where people will normally be programming with immutable persistent composite data structures. Getting a consistent view of such a data structure doesn't require a transaction at all, so that is much faster than other strategies. When 'changing' a data structure, you read it from the ref once and then structural changes do not involve the STM or refs. Store it back in the ref when done. Thus the granularity of transactions is coarse and the number of ref interactions involved small. These are not things you'll see when timing pounding an integer in a transactional ref in a tight loop, but matter greatly in practice, IMO. I partly agree. One of my design guidelines is that one should not have to pay for what is not being used. One of the things I'm focussing on is making the transaction as fast as possible for any length. I'm working on a system that advices the creation of a transaction with the maximum number of attached objects. I have a transaction optimised for a single attachment (5+M transactions/ second on a single core), for a small number of attachments (so using an array to store attached items to reduce object creation) and one for a large number of attachments (so using an expensive hashmap). The later one also is going to get a parallel commit (so obtaining locks/checking for isolation problems.. and doing the write) to make effective use of the cores and speed up the commit of larger transactions. For a single attachment Clojure has atoms and agents instead of an optimized specialization of refs and dosync. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Lazy Exceptions
On Fri, Aug 28, 2009 at 8:50 AM, Rich Hickey richhic...@gmail.com wrote: On Thu, Aug 27, 2009 at 8:10 PM, Tim Snydertsnyder...@gmail.com wrote: Well, I can see that LazySeq does indeed catch and wrap all Exceptions in a RuntimeException. I also think I can work around it, but I'd like to know why this was done? Was it necessary given the checked vs. unchecked exception system of Java? Yes. What about declaring IFn.invoke() as throws Exception? Or did you think that would make calling Clojure from Java too painful? Or was there some other reason? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Order of keys within a map?
On Thu, Aug 27, 2009 at 3:35 PM, Howard Lewis Ship hls...@gmail.com wrote: Is the order of keys in a map predictable? I have some tests I'm concerned about, where the keys and values in a map are converted to a string (ultimately, a URL, as query parameters) and the order will affect the output string. I could sort the keys, but then I'm changing my code to support the test in a somewhat non-trivial way. Literally: when iterating over the key/value pairs, the order seems to be the order in which the key/values are defined in the map. Is this true? The order of keys in a map is basically undefined. In practice, for small maps it tends to be insertion order and for maps with more than eight keys, in order of the keys' hashCode() values (as Java objects). But this behavior should probably not be relied on. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: we offer cheap sport shoes men's shoe(www.salegood8.com) casual shoe fashion shoe
On Tue, Aug 25, 2009 at 11:42 AM, Chouser chou...@gmail.com wrote: On Tue, Aug 25, 2009 at 10:36 AM, John Harropjharrop...@gmail.com wrote: What the hell? The group actually gets a steady stream of spam, but it usually gets deleted instead of being sent to everyone. On this one I accidentally clicked the wrong button. Sorry about that. I'd have thought you'd have set up an automatic filter for the shoe spammer. The messages should after all be very easy to identify with automation. There are plenty of people on an auto-accept list; this one, at least, seems to cry out for an auto-reject list. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: On the reader macro #=
On Wed, Aug 26, 2009 at 1:13 PM, John Harrop jharrop...@gmail.com wrote: This is important to know about for security reasons, also. Specifically, if you are receiving Clojure data structures in text form over the network, and don't set *read-eval* to false, you're vulnerable to a Clojure injection attack. Someone could send you (+ 5 #=(System/exit 0)) as a denial-of-service attack, just for starters. Interesting result from testing this: user= (read-string (System/exit 0)) (System/exit 0) user= (read-string #=(System/exit 0)) ClassNotFoundException: System user= (read-string #=(java.lang.System/exit 0)) REPL is disconnected. Strange that java.lang is not apparently imported in whatever environment the EvalReader uses. Doesn't stop it being a security hole if accessible over the network though. :) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: On the reader macro #=
This is important to know about for security reasons, also. Specifically, if you are receiving Clojure data structures in text form over the network, and don't set *read-eval* to false, you're vulnerable to a Clojure injection attack. Someone could send you (+ 5 #=(System/exit 0)) as a denial-of-service attack, just for starters. I doubt there's a way to make it safe. There's probably no way to force those expressions to run in an applet sanbox, at least without massive kludging. You'd have to vet the strings first, using some non-Clojure-reader parser. Easier to use the Clojure reader and then walk the resulting data structures looking for, say, special sentinel keywords that should be substituted with other things, or that flag something about the following item (say, that it should be converted to a SortedMap). For storing stuff locally the EvalReader should be safe, unless your program runs with elevated privileges compared to the user who runs it (unix setuid or equivalent). In that event though there's a possibility of it being exploited for local privilege escalation. Arbitrary Clojure and Java code could be submitted to be run at the higher privilege level. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: we offer cheap sport shoes men's shoe(www.salegood8.com) casual shoe fashion shoe
What the hell? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Generation of random sequences
On Tue, Aug 25, 2009 at 10:42 AM, Fogus mefo...@gmail.com wrote: A quick and dirty way would be to use a map as your intermediate storage with your generated numbers as keys and some constant as their assoc'd value. Once you've populated said map with the proper number of entries (keeping track of clashes along the way) then get a sequence using `(seq (.keySet myMap))`. Why not just use a HashSet rather than a SortedSet to begin with? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Arity count
On Wed, Aug 19, 2009 at 10:03 AM, Achim Passen achim.pas...@gmail.comwrote: Beware! This snippet relies on unexposed details of clojure's current implementation. It might stop working tomorrow, so it's definitely not intended for production use, but it might help with debbuging/exploring. Meanwhile, for declared functions this works: (map #(if (contains? (set %) ') [:more (- (count %) 2)] (count %)) (:arglists ^#'foo)) giving results like: (0 2 5 [:more 7]) (in this case for (defn foo ([] nil) ([glorb fuzzle] nil) ([x y z w u] x) ([a b c d e f g more] more))) Add this: (defn accepts-arity [arities arity] (or (contains? (set arities) arity) (and (vector? (last arities)) (= arity (second (last arities)) and you can check if the function accepts a particular arity. (This expects arities in the format output by my map expression. In particular, a list of numerical arities and possibly a [:more n] entry, which must be a vector and must be the last item in the list if present, and n must be the number of required parameters for the more overload.) Wrap it all up with two macros: (defmacro fn-arities [fn-name] `(map (fn [x#] (if (contains? (set x#) ') [:more (- (count x#) 2)] (count x#))) (:arglists ^#'~fn-name))) (defmacro fn-accepts-arity [fn-name arity] `(accepts-arity (fn-arities ~fn-name) ~arity)) user= (fn-accepts-arity foo 8) true user= (fn-accepts-arity foo 6) false user= (fn-accepts-arity reduce 2) true user= (fn-accepts-arity reduce 3) true user= (fn-accepts-arity reduce 4) false user= (fn-arities map) (2 3 4 [:more 4]) Works for macros, too: user= (fn-arities fn-arities) (1) user= (fn-arities fn-accepts-arity) (2) But, as noted, only works with a name of a declared fn or macro: user= (fn-arities #(+ 3 %)) #CompilerException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:110) (One thing odd about that: user= (class '#(+ 3 %)) clojure.lang.PersistentList not Cons. Hmm.) It also doesn't work with local, named functions, either using let or using letfn, even if (fn name [args] body) is used and not (fn [args] body): user= (let [x (fn [a] (+ 3 a))] (fn-arities x)) #CompilerException java.lang.Exception: Unable to resolve var: x in this context (NO_SOURCE_FILE:117) user= (let [x (fn x [a] (+ 3 a))] (fn-arities x)) #CompilerException java.lang.Exception: Unable to resolve var: x in this context (NO_SOURCE_FILE:118) user= (letfn [(x [a] (+ 3 a))] (fn-arities x)) #CompilerException java.lang.Exception: Unable to resolve var: x in this context (NO_SOURCE_FILE:119) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Can dosync transaction result computation be parallelized over multiple threads?
(def *dosync-counts* (atom {}) (defn avg-in [map key val] (let [[avg cnt] (get map key [0 0])] (assoc map key [(/ (+ (* avg cnt) val) (inc cnt)) (inc cnt)]))) (defmacro logged-dosync [ body] `(let [count# (atom 0)] (dosync (swap! count# inc) ~...@body) (swap! *dosync-counts* avg-in (quote ~body) (deref count# (defn crude-print-dosync-log [] (doseq [[code [avg cnt]] @*dosync-counts*] (println code) (println avg retries on average over cnt total transaction(s)) (println))) These tools should suffice to simply discover how many retries some transaction is taking on average. For more complex dosync profiling you'd probably need hooks deeper into Clojure's STM, particularly for logging what ref value changed to cause a retry or similarly. (A cleverer macro might parse the body for ensures, commutes, and the like, and bookend the body with code to record the at-start-of-transaction values of the involved refs and code to compare these against the out-transaction values just before commit, getting the latter using (future (deref foo)) or some similar method that will see the out-transaction values, and note any that had changed. So hooks deeper into STM might not be necessary after all, at least for some simple tests of why a retry might have happened. Having code that can introspect on code and write code seems to allow for some serious kung-fu!) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: New string utilities library ready
On Thu, Aug 20, 2009 at 12:45 AM, samppi rbysam...@gmail.com wrote: For me, I'd like it if the core functions had the data as the first argument, but have a special function—I can't come up with a better name than partial-2—so that (partial-2 function opt1 opt2 opt3) is equivalent to (fn [data] (function data opt1 opt2 opt3)). That way, I could do things like (map (partial-2 s/split #\n 30) vector-of-strs) without breaking . Is there something wrong with (map #(s/split % #\n 30) vector-of-strs)? The #(...) lambda read-macro seems to me to obviate most needs for partial and partial-2. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Idiom for array slicing
On Mon, Aug 17, 2009 at 11:35 PM, Mark Triggs mark.h.tri...@gmail.comwrote: Thanks all. So combining a few suggested ideas: (defn slice Return the items in coll at index positions keys. (slice [0 4 6] \abcdefg\) = (\\a \\e \\g) [keys coll] (let [max-idx (apply max keys) keyset (set keys)] (map second (filter (fn [[idx _]] (keyset idx)) (take-while (fn [[idx _]] (= idx max-idx)) (indexed coll)) This version has the advantage of working on infinite sequences and not hanging onto the head. This works as expected: (slice [200 201] (repeatedly #(int-array 102400))) without blowing up the stack or throwing OutOfMemory (on my JVM). So does the very simple (defn slice [indices coll] (map #(nth coll %) indices)) though that doesn't use keys rather than position with maps. (defn slice [indices coll] (map #(get coll %) indices)) does, but works for maps and vectors but not lists. It does work for strings. (defn slice [indices coll] (map #(get (indexed coll) %) indices)) should if (indexed coll) has the semantics it seems it should from what you've posted, but the indexed function is apparently bleeding-edge because my copy of clojure 1.0 doesn't have anything by that name in it. (defn slice [coll indices] (map #(nth coll %) indices)) has the same argument syntax as suggested originally by Mark. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: what's the appropriate way to process inner nested list (or vector) in clojure?
On Sun, Aug 16, 2009 at 1:30 AM, botgerry botge...@gmail.com wrote: Hello,all new to functional programming, I have one nested dynamic vecter just like this: (def a [[1 2 3 4] [ok 89 22] [25 78 99] ...]] it has to support ops: 1* add new item,it's easy: eg. (conj a [metoo oops] ) 2* insert one element into inner vector based that vector's content,eg i have to append 50 in inner vectors which includes 99. the result is [[1 2 3 4] [ok 89 22] [25 78 99 50]...] 3* merge inner vectors in a , eg. if there are same elements in inner vectors , they should be merged and delete same elements. [[1 2 3 4] [ ok 89 22] [ 5 6 7 2 ]...] - [[1 2 3 4 5 6 7] [ok 89 22]] If you are implementing a disjoint set forest, it might be better to use a map from values to sets, where the lookup-set-given-value operation is a simple map lookup, adding a new one-element set is just (assoc map object #{object}), and merging two sets is almost as simple: (let [new-set (into set-1 set-2)] (reduce #(assoc %1 %2 new-set) map new-set)) evaluates to the new forest map. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: clojure success story ... hopefully :-)
On Fri, Aug 14, 2009 at 7:18 PM, bradford cross bradford.n.cr...@gmail.comwrote: Hi Chad, yep, that was me. We do hope to open source some stuff soon. First will probably be our wrappers for cascading/hadoop and s3. Next might be some core language extensions which might be good in contrib or some other lib. If we release any basic stats or machine learning stuff we may try to merge into incanter if it seems like a fit but haven't had time to check out incanter as I'd like. Very interesting. Are you using (binding [*read-eval* false] ...) when reading Clojure data structures out of strings obtained over your distributed node network? If you're not it's possible you have a security hole that could be exploited by a hostile node masquerading as a legitimate one. (Though likely an attacker would have to penetrate your firewall and get loose in your LAN, gaining privileges on at least one of your machines, to exploit it.) Specifically, a #=() form in the stream would otherwise allow a sort of injection attack. If you use the Clojure reader on other untrusted data, such as fragments of web pages (to parse numbers, say), the same applies: without that binding for those reads, you may be vulnerable in a similar manner. If data from web forms, vulnerable in a very similar manner to SQL injection. Security becomes especially important if you figure to do big parallel reductions on office PC spare cycles instead of dedicated hardware. Those PCs might vary in how sensitive the information on them is, and in how trustworthy their users are. You don't want a newly-hired clerk in sales sending crafted network packets that give him privileges on the desktop computer of the CFO or among the RD department's boxes. The latter lets him sell industrial espionage data to the highest bidder, likely a competitor; the former, possibly do some insider trading or suchlike (and when the SEC shows up to investigate some suspicious trades, they'll be looking at your CFO, as he was the one nominally privy to the inside info). So a breach could cause anything from embarrassment (porn popups during board meeting Powerpoint presentations; intentional pranks) to competitive or legal trouble. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Can Clojure be as fast as Java?
On Wed, Aug 12, 2009 at 5:25 AM, Piyush Ranjan piyush...@gmail.com wrote: This is a troll question. I have seen similar questions posted on other forums about languages like ruby, CL, Haskell, Prolog, C, C++, fortran, bigloo(?) etc by the same poster. Hmm. fft1976 = WrexSoul? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure Code Style
On Thu, Aug 13, 2009 at 12:34 AM, Richard Newman holyg...@gmail.com wrote: This is the difference between 'conventional' and point-free style, by the way. Many people view point-free as being somehow more elegant, and I'm generally inclined to agree... apart from in cases like your example, where a ton of partials need to be added. What is point-free, exactly? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: core.clj: 'into' definition
On Tue, Aug 11, 2009 at 6:39 AM, Krukow karl.kru...@gmail.com wrote: I was browsing through core when I noticed something I didn't understand in 'into' (from core.clj): ;redef into with batch support (defn into Returns a new coll consisting of to-coll with all of the items of from-coll conjoined. [to from] (if (instance? clojure.lang.IEditableCollection to) (#(loop [ret (transient to) items (seq from)] (if items (recur (conj! ret (first items)) (next items)) (persistent! ret (#(loop [ret to items (seq from)] (if items (recur (conj ret (first items)) (next items)) ret) I am wondering about the construct #(loop ...). As far as I can see you might as well just use (loop). I.e., (defn into2 Returns a new coll consisting of to-coll with all of the items of from-coll conjoined. [to from] (if (instance? clojure.lang.IEditableCollection to) (loop [ret (transient to) items (seq from)] (if items (recur (conj! ret (first items)) (next items)) (persistent! ret))) (loop [ret to items (seq from)] (if items (recur (conj ret (first items)) (next items)) ret I suspect that I am missing some point. Could someone clarify? I don't know. Perhaps at this point during bootstrap loop doesn't create recur points and so the anonymous lambdas are necessary? But then recur would rebind the (nonexistent) lambda parameters I'd have thought. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: binary serialization
On Mon, Aug 10, 2009 at 10:57 PM, Kyle R. Burton kyle.bur...@gmail.comwrote: On Mon, Aug 10, 2009 at 10:42 PM, Kyle R. Burtonkyle.bur...@gmail.com wrote:Sorry, forgot to offer up the inverse of freeze, thaw: (defn thaw [bytes] (with-open [bais (java.io.ByteArrayInputStream. bytes) ois (java.io.ObjectInputStream. bais)] (.readObject ois))) Regards, Kyle Which in turn gives us this, otherwise sorely lacking from the Java standard library, but much less useful to us Clojurians who tend to mainly use immutable objects: (defn deep-copy [obj] (thaw (freeze obj))) (Object.clone() does a shallow copy and typically isn't as widely available as Serializable.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: binary serialization
On Tue, Aug 11, 2009 at 12:17 AM, fft1976 fft1...@gmail.com wrote: I don't know JVM too well, but I think no efficient user-level solution is possible. Why? To take care of substructure sharing, you need to remember a set of shareable values that have already been serialized, and do reference equality comparisons when new new substructures are serialized. This comparison and a set implementation can easily be done with pointers (because you have ), but there are no pointers in the JVM, and no reference inequality, so you must use linear seeks, making the time complexity of serialization quadratic, where in C/C++ it could be O(N log N) Reference equality is available in the JVM (instructions if_acmpeq and if_acmpne), in Java (operators == and !=), and in Clojure (predicate identical?). Furthermore, though on pointers isn't, so a tree-map of already serialized structures to themselves also isn't, Java provides System.identityHashCode() and IdentityHashMap. These use a hash that respects reference equality. So one in fact can implement one's own serialization that is O(n) using O(1) hashmap lookups (and using reflection, and not working if SecurityManager won't let you setAccessible private fields and the like, so not in an unsigned applet). (Another use for reference equality is to see if Double.valueOf() is caching, something that arose as an issue in another thread. On my system, Sun JVM 1.6.0_13 -server and Clojure 1.0.0, it apparently is not: user= (identical? 2.0 2.0) false If this comes out to true then it's caching. Integer.valueOf() is caching on my system, but only for small integers: user= (identical? 1 1) true user= (identical? 5 5) true user= (identical? 50 50) true user= (identical? 500 500) false user= (identical? 255 255) false user= (identical? 127 127) true user= (identical? 128 128) false The threshold seems to be at values that will fit in one byte. [Remember the literals get boxed when passed to a function like identical? that isn't inlined. And identical? isn't inlined: user= (meta (var identical?)) {:ns #Namespace clojure.core, :name identical?, :doc Tests if 2 arguments are the same object, :arglists ([x y])} whereas two-argument + is: user= (meta (var +)) {:ns #Namespace clojure.core, :name +, :file clojure/core.clj, :line 549, :arglists ([] [x] [x y] [x y more]), :inline-arities #{2}, :inline #core$fn__3329 clojure.core$fn__3...@d337d3, :doc Returns the sum of nums. (+) returns 0.} You can also use ^#'identical? and ^#'+ but I like my Clojure looking like Lisp, not like perl. :)]) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
On Fri, Aug 7, 2009 at 8:14 PM, John Harrop jharrop...@gmail.com wrote: Your core loop seems to be: (loop [zr (double 0.0) zi (double 0.0) zr2 (double 0.0) zi2 (double 0.0) iterations-remaining iterations-remaining] (if (and (not (neg? iterations-remaining)) ( (+ zr2 zi2) limit-square)) (let [new-zi (double (+ (* (* f2 zr) zi) pi)) new-zr (double (+ (- zr2 zi2) pr)) new-zr2 (double (* new-zr new-zr)) new-zi2 (double (* new-zi new-zi))] (recur new-zr new-zi new-zr2 new-zi2 (dec iterations-remaining))) What I suggest is (loop [zr (double 0.0) zi (double 0.0) i (int (inc iterations-remaining))] (let [zr2 (* zr zr) zi2 (* zi zi)] (if (and (not (= 0 i)) ( (+ zr2 zi2 limit-square))) (recur (+ (- zr2 zi2) pr) (+ (* (* f2 zr) zi) pi) (unchecked-inc i)) (whatever... * Same calculations * Less items in recur rebind * Counter is also primitive (untested, may need slight tweakage) I've got some interesting new benchmark results here. user= (time (let [m (int 1) b (double 4.0) x0 (double -0.2) y0 (double 0.1) t (double 2.0)] (loop [x (double 0.0) y (double 0.0) i (int 0)] (if ( i m) (let [x2 (* x x) y2 (* y y)] (if ( (+ x2 y2) b) (recur (+ (- x2 y2) x0) (+ (* t (* x y)) y0) (unchecked-inc i)) i)) i Elapsed time: 875.36796 msecs 1 A very straightforward version, and 875.36796ms/1 = 8.7536796ns. This is on a 2.5GHz machine, so that's only about 22 native instructions per iteration. The theoretical minimum is over 1/2 of that: Four fmuls Three fadds and an fsub A floating point comparison An integer add and an integer comparison A branch back to the start of the loop So we're within a factor of 2 of *native* code speeds (nevermind Java) here. user= (time (let [m (int 1) b (double 4.0) x0 (double -0.2) y0 (double 0.1) t (double 2.0)] (loop [x (double 0.0) y (double 0.0) i m] (if ( i 0) (let [x2 (* x x) y2 (* y y)] (if ( (+ x2 y2) b) (recur (+ (- x2 y2) x0) (+ (* t (* x y)) y0) (unchecked-dec i)) i)) i Elapsed time: 3418.8542 msecs 0 Shockingly, reversing the count-up to a count-down and not changing anything else at all makes things much, MUCH worse, about four times slower. user= (time (let [m (int 1) b (double 4.0) x0 (double -0.2) y0 (double 0.1) t (double 2.0)] (loop [x (double 0.0) y (double 0.0) i m] (if (zero? i) i (let [x2 (* x x) y2 (* y y)] (if ( (+ x2 y2) b) (recur (+ (- x2 y2) x0) (+ (* t (* x y)) y0) (unchecked-dec i)) i)) Elapsed time: 874.9564 msecs 0 The original, at-least-half-of-C speed again. It seems like and zero? are as fast as each other and much slower on primitive ints. user= ^#' {:ns #Namespace clojure.core, :name , :file clojure/core.clj, :line 589, :arglists ([x] [x y] [x y more]), :inline-arities #{2}, :inline #core$fn__3363 clojure.core$fn__3...@b655a, :doc Returns non-nil if nums are in monotonically increasing order,\n otherwise false.} user= ^#'zero? {:ns #Namespace clojure.core, :name zero?, :file clojure/core.clj, :line 742, :arglists ([x]), :inline #core$fn__3485 clojure.core$fn__3...@7787a5, :tag java.lang.Boolean, :doc Returns true if num is zero, else false} user= ^#' {:ns #Namespace clojure.core, :name , :file clojure/core.clj, :line 617, :arglists ([x] [x y] [x y more]), :inline-arities #{2}, :inline #core$fn__3379 clojure.core$fn__3...@51e67c, :doc Returns non-nil if nums are in monotonically decreasing order,\n otherwise false.} It isn't that isn't inlined, either. I think the inline implemenation #core$fn__3379 clojure.core$fn__3...@51e67c of needs to be investigated for why it is apparently vastly slower than that of . In the meantime, I'm not sure why Andy's code is still 3x slower than Java, while mine runs at more than half the speed of native C. Perhaps it's a difference in our JVMs or hardware. I'm using 1.6.0u13 -server on a 2.5GHz Intel CPU. If Andy's using a different JVM, not using -server, or using a CPU with fewer registers (to run as fast as it does my loop must be running entirely in CPU registers -- there's not enough slack time between the 5ns minimum to execute the calculations at 2.5GHz and the 9ns actual time to make a round trip to my 7ns RAM -- but on another CPU arch with fewer registers the loop might not fit in the registers. The bigger difference between C and Clojure on Andy's system could then result if the JIT is making it less register-efficient (using say one or two more) than hand-tuned assembly or a good C optimizer, and this is making the difference
Re: How to create structure with a seq of keys
On Sun, Aug 9, 2009 at 8:55 PM, David Nolen dnolen.li...@gmail.com wrote: Sounds like you want apply: (apply fn args) Indeed. Since create-struct (not create-structure!) is a function, this should work. It wouldn't work with a macro, though. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Commenting Code (Was: Re: Clojure as a First Language)
On Sun, Aug 9, 2009 at 12:47 PM, Lauri Pesonen lauri.peso...@iki.fi wrote: 2009/8/8 Luc Prefontaine lprefonta...@softaddicts.ca: I totally agree no comments is not good at all but JavaDoc style comments in Clojure ? I pray you all, please stay away of it : I was quite taken by this scheme style guide recently: http://mumble.net/~campbell/scheme/style.txt While I don't agree with all the points in it, and some advice is not Clojure compatible (e.g. do not use square brackets and the CL-specific block comments), I think that the guide gave me a to think about. It would be nice if Enclojure's auto-indent implemented the style guide (with suitable Clojure modificagtions). The current indent behavior for vectors, sets, and maps is appropriate. The current indent behavior for lists is just to indent two levels deeper for every unclosed open parenthesis. Better might be to indent two levels deeper for (oper foo bar body) where oper is either a special form with body code as the last parameter or a macro with an foo final parameter; but for unquoted (foo bar baz) align with the first operand, or with the operator if the first operand is not on the same line as the operator, and for quoted '(foo bar baz) similar to [], {}, and #{} because it's data rather than an operator and operands. Backquote expressions should be indented as if unquoted though, because they are probably code to be output by a macro (or, less commonly, fed to eval): `(foo bar ~baz) I suppose I should join the enclojure google group, if there is one, and cross-post this to 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
On Sun, Aug 9, 2009 at 3:06 AM, Andy Fingerhut andy_finger...@alum.wustl.edu wrote: I did two runs for each version, with the only difference between them being replacing the (zero? i) expression in function 'dot' with a different expression, as indicated below. (zero? i) is a clear winner in reducing run time. That's very surprising. Were you using -server in the vm options? It seems to me that (= 0 i) for a primitive int i ought to be very fast, compared to a Java method call that presumably takes a Number (and so would box the int). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
On Fri, Aug 7, 2009 at 9:19 PM, Andy Fingerhut andy_finger...@alum.wustl.edu wrote: What I suggest is (loop [zr (double 0.0) zi (double 0.0) i (int (inc iterations-remaining))] (let [zr2 (* zr zr) zi2 (* zi zi)] (if (and (not (= 0 i)) ( (+ zr2 zi2 limit-square))) (recur (+ (- zr2 zi2) pr) (+ (* (* f2 zr) zi) pi) (unchecked-inc i)) (whatever... * Same calculations * Less items in recur rebind * Counter is also primitive (untested, may need slight tweakage) Needed unchecked-dec in place of unchecked-inc, and I used (zero? i) instead of (= 0 i) (not sure if that makes much difference), and the results are much better -- the time went down to a little less than half of what it was before. Try (= 0 i) or whatever. Since zero? is a function it's probably boxing the integer, unless it's a definline rather than a defn. http://github.com/jafingerhut/clojure-benchmarks/blob/fe10ef25ec17b77dd03f6d1ccff4f35273764f3b/RESULTS Why post a link to a blank web page? Thanks! Andy You're welcome. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Durable transactions in practice?
On Sat, Aug 8, 2009 at 2:50 AM, cody koeninger c...@koeninger.org wrote: Assuming people aren't patching clojure ala dave griffith's external transactions patch in the group files, what are people doing in practice to durably store the state of refs? Storing within a transaction and somehow ensuring your store operation is idempotent (not to mention reversible)? Sending off an agent from a transaction and not worrying about race conditions? Forgoing the use of STM in favor of locks + try / catch? I'm not so much asking about what particular store (RDBMS, prn to a file, whatever) is being used, as I am curious what kind of coordination is being used. In one current project, I have a macro (transaction body) and some functions that create a weakly ACID file-transaction concept. A function transaction-file is called to convert a file object into the file to actually write, which will come back as a temp file if inside a transaction, and add that temp file to a list the transaction maintains. The transaction macro wraps the body with a bit of preamble code that sets up an atom used to build this list (and whose non-nil state informs the transaction-file function) and a post-amble that renames the original files, renames the temp files over them, and then deletes the original files. The post-amble is NOT in a finally block, so if an exception is thrown, the files are NOT replaced. A cleanup thread periodically kills temporary files that are too old. This is entirely orthogonal to clojure's dosync. Strengths: * Changes to several files can be done atomically, at least as far as the one Clojure thread is concerned. * Barring the unlikely event of something going wrong during the final renamings, changes to files either happen or don't happen. * The old version is never destroyed until the new version is safely in place with the old name. So if something does go pear-shaped, manual recovery is possible by a knowledgeable user. Weaknesses: * Separately changing the same file twice in a single transaction won't work. It would be nice to have a persistence framework in Clojure that was part of the core and provided some degree of ACID-like safety, with some sort of dosync-like wrapper, perhaps around arbitrary file operations, perhaps only around some system for serializing and deserializing Clojure objects. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
On Sat, Aug 8, 2009 at 5:23 AM, Mark Engelberg mark.engelb...@gmail.comwrote: On Fri, Aug 7, 2009 at 5:14 PM, John Harropjharrop...@gmail.com wrote: (if (and (not (= 0 i)) ( (+ zr2 zi2 limit-square))) I believe that (zero? i) is faster than (= 0 i). On primitive ints? Have you tested 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
On Thu, Aug 6, 2009 at 6:57 PM, Andy Fingerhut andy_finger...@alum.wustl.edu wrote: You are correct. I've updated that file: http://github.com/jafingerhut/clojure-benchmarks/blob/bb9755bdeeccae84a9b09fbf34e45f6d45d4b627/RESULTS Could you post the Mandelbrot code you use? Because I know for a fact that Clojure can do FP calcs as fast as native C code, given the -server vm and a loop/recur with unboxed doubles, and my understanding of Mandelbrot is that it's just FP calcs. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure performance tests and clojure a little slower than Java
Your core loop seems to be: (loop [zr (double 0.0) zi (double 0.0) zr2 (double 0.0) zi2 (double 0.0) iterations-remaining iterations-remaining] (if (and (not (neg? iterations-remaining)) ( (+ zr2 zi2) limit-square)) (let [new-zi (double (+ (* (* f2 zr) zi) pi)) new-zr (double (+ (- zr2 zi2) pr)) new-zr2 (double (* new-zr new-zr)) new-zi2 (double (* new-zi new-zi))] (recur new-zr new-zi new-zr2 new-zi2 (dec iterations-remaining))) What I suggest is (loop [zr (double 0.0) zi (double 0.0) i (int (inc iterations-remaining))] (let [zr2 (* zr zr) zi2 (* zi zi)] (if (and (not (= 0 i)) ( (+ zr2 zi2 limit-square))) (recur (+ (- zr2 zi2) pr) (+ (* (* f2 zr) zi) pi) (unchecked-inc i)) (whatever... * Same calculations * Less items in recur rebind * Counter is also primitive (untested, may need slight tweakage) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Transient Data Structures
On Tue, Aug 4, 2009 at 5:50 PM, Rich Hickey richhic...@gmail.com wrote: On Aug 4, 4:31 pm, John Harrop jharrop...@gmail.com wrote: What about things like: (persistent! (reduce (fn [x [i v]] (assoc! x i v)) (transient (vec (repeat 0 (reduce max (map first coll-of-index-val-pairs) coll-of-index-val-pairs)) Yes, that's completely fine intended usage, as the return value of the reducing fn becomes an argument to the next call. which is just the transientification of Nice word - transientification. Thanks. Of course, this makes me think of ways to possibly speed up other operations. For example: (defn vmap* [fun vect] (let [c (count vect)] (loop [out (transient []) i 0] (if (= i c) out (recur (conj! out (fun (nth vect i))) (inc i)) (defn vmap [fun vect] (persistent! (vmap* fun vect))) Vector in, vector out, conj'd up using a transient. And, of course: (defn vpmap [fun vect] (loop [out (vmap* #(future (fun %)) vect) i (dec (count vect))] (let [o2 (assoc! out i @(nth out i))] (if (zero? i) (persistent! o2) (recur o2 (dec i) Note that this last manipulates a transient vector in a single thread, though other threads (from the agent pool) calculate a bunch of futures that are stored in it. The transient vector of futures is generated using the vmap* from above, and then the futures are replaced with their values in-place by the loop in vpmap, before this persistentizes and returns that vector. The future-dereferencing loop works backwards from the end of the vector in case zero? is a quicker test than a general equality test. This is likely on hardware that implements an equality test as a subtraction followed by a zero test, because it eliminates the subtraction. On the other hand, hardware with a 1-cycle equality test of 32-bit ints is plausible, as is hardware that optimizes forward traversal of vectors, so I can't vouch for that being an optimization. The first loop has to go forward to conj up the output vector without reversing it, though. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Reflection warning: reference to field getClass can't be resolved.
On Tue, Aug 4, 2009 at 7:46 PM, Vagif Verdi vagif.ve...@gmail.com wrote: When reflection warning is on, i get 2 warnings on every my file: reference to field getClass can't be resolved. That one is very weird, because getClass is a method of java.lang.Object. It should always be possible to resolve that one without reflection. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Miscellanea prompted by a comp.lang.lisp post about Clojure
I just saw someone post a bunch of Clojure code to comp.lang.lisp one function from which was: (defn partition-with [pred coll] (loop [in coll curr [] out []] (if (empty? in) (conj out curr) (let [obj (first in)] (if (pred obj) (recur (rest in) [] (conj out curr)) (recur (rest in) (conj curr obj) out)) This looks like it might be generally useful (and the CLL poster thought so too); it splits a collection at items determined by the predicate, producing a vector of vectors of items not matching the predicate: user= (partition-with odd? [3 4 8 7 9 2 4 6]) [[] [4 8] [] [2 4 6]] (The empty collections are from before 3 and between 7 and 9, from the look of it. user= (remove empty? (partition-with odd? [3 4 8 7 9 2 4 6])) ([4 8] [2 4 6]) gives what you might want instead, in some situations.) The same CLL poster noticed that conj with two maps for arguments seems to duplicate the functionality of merge. I've just tested this and it seems to be true, even with key duplications: user= (merge {:key2 2 :key3 3} {:key1 1 :key4 4 :key3 7} ) {:key4 4, :key1 1, :key2 2, :key3 7} user= (conj {:key2 2 :key3 3} {:key1 1 :key4 4 :key3 7} ) {:key4 4, :key1 1, :key2 2, :key3 7} This makes merge appear redundant. Further experimentation shows that there isn't even a type-safety reason to prefer merge. It doesn't throw on vectors. In fact: user= (merge [1 2 3] 4) [1 2 3 4] user= (merge '(1 2 3) 4) (4 1 2 3) user= (merge #{1 2 3} 8) #{1 2 3 8} user= (merge #{1 2 3} 3) #{1 2 3} user= (merge #{1 2 3} #{4 3}) #{1 2 3 #{3 4}} user= (conj #{1 2 3} #{4 3}) #{1 2 3 #{3 4}} so merge appears to be strictly synonymous with conj. Curiouser and curiouser... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Minor macro help
Very clever, Meikel. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Memfn: what does it mean?
On Tue, Aug 4, 2009 at 2:22 AM, Meikel Brandmeyer m...@kotka.de wrote: Hi, On Aug 3, 10:10 pm, John Harrop jharrop...@gmail.com wrote: (defn and-ns A non-short-circuiting \and\ usable in reduce etc. ([] true) ([a] a) ([a b] (and a b)) ([a b more] (reduce and-ns (and a b) more))) Don't think to complicated. (reduce #(and %1 %2) coll) This should do the trick, no? It's still non-short-circuiting, though. That will do the trick, but it's kind of ugly compared to just having a symbol for the first argument to reduce. I think memfn is some relict like .., which pre-dates some of the nice additions to clojure. #(.foo %1 %2 fixed-arg %3) What, you mean it predates the #(...) read-macro? I wouldn't know; I only started using Clojure when version 1.0 became available. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie question on using Java Libraries
On Mon, Aug 3, 2009 at 4:16 AM, Adie adit...@gmail.com wrote: Good Afternoon folks, I am a newbie to Clojure, coming from CL, with very little Java background. I am trying to use the 'javax.persistence' libraries, but i just cant seem to import it properly for e.g (import '(javax.persistence Persistence) gives a java.lang.ClassNotFoundException: javax.persistence.Persistence (NO_SOURCE_FILE:0) error I don't see a javax.persistence package listed at http://java.sun.com/javase/6/docs/api/ so it apparently doesn't come with the JDK. You probably need (and probably already have) a jar for it (probably one of those JSR jars, given the package name). You also need (and probably don't have) the jar on the classpath. If you're using Eclipse or Netbeans, edit the project to add a library, then when prompted browse to that jar. Close and restart your REPL if you had it open, so that the change takes effect. Then try executing the code again and it should work if the jar is present and was added to the project libraries. If you're using emacs, then may God have mercy on your soul. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Memfn: what does it mean?
On Mon, Aug 3, 2009 at 8:53 AM, Mike DeLaurentis delauren...@gmail.comwrote: I believe it stands for member function. From the doc string: Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn. Interestingly, it's just a very simple macro to automate wrapping the method call in an anonymous lambda: user= (macroexpand-1 '(memfn add x y)) (clojure.core/fn [target__4193__auto__ x y] (. target__4193__auto__ (add x y))) That is, basically (fn [object x y] (.add object x y)). I'd guessed as much even before trying the above macroexpand-1 line. It was the obvious way to implement it with no magic required. (I think you'll find that most of the magic in Clojure is ClassLoader voodoo quite far under the hood, and that a lot of seemingly fancy features are simply implemented as fairly basic macros. The .add type of method call, however, does seem to be some sort of serious mojo. (doc .add) throws an exception rather than recognizing it as a special form or similarly, though you also get strange errors if you try to use .add as a variable name.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Memfn: what does it mean?
On Mon, Aug 3, 2009 at 3:45 PM, Richard Newman holyg...@gmail.com wrote: user= (macroexpand-1 '(memfn add x y)) (clojure.core/fn [target__4193__auto__ x y] (. target__4193__auto__ (add x y))) That is, basically (fn [object x y] (.add object x y)). .add is macroexpanded into the more general dot form, as shown in the memfn expansion. user= (read-string (.foo bar)) (.foo bar) user= (macroexpand-1 *1) (. bar foo) So, it treats .foo in form-initial position as a macro, though not elsewhere (so (doc .foo) does not produce Macro. and other data). Plain . is reported as a Special Form by doc. It is definitely interesting sometimes to poke at the guts of Clojure in the REPL. :) One apparent deficiency brought to light by all of this: since memfn is a macro, it's not itself composable. Other macros where I've found this to occasionally be a problem are and and or (where I wanted to do something like (reduce and (map pred? coll))) but it's easy enough to make function versions of all of them: (defn and-ns A non-short-circuiting \and\ usable in reduce etc. ([] true) ([a] a) ([a b] (and a b)) ([a b more] (reduce and-ns (and a b) more))) (defn or-ns A non-short-circuiting \or\ usable in reduce etc. ([] false) ([a] a) ([a b] (or a b)) ([a b more] (reduce or-ns (or a b) more))) (defn make-memfn Given a quoted method name and a quoted vector of argument names, returns a function that can be composed and that takes a target object plus the named arguments and invokes the named method on that target with those arguments. [name arg-vec] (eval `(fn [target# ~...@arg-vec] (. target# (~name ~...@arg-vec) Of course, the first two don't short-circuit like their macro counterparts, and the latter needs its arguments quoted. The latter generates: user= (make-memfn 'add '[x y]) (clojure.core/fn [target__15__auto__ x y] (. target__15__auto__ (add x y))) (obtained by dropping the eval from make-memfn, so it just returned the backquoted expression; compare with memfn above). Of course you're probably doing some serious voodoo if you are generating memfns on the fly from run-time-determined names and argument vectors. Metaprogramming, or making some kind of Java-object inspector, or whatever. The function versions of and and or are much more generally useful, since reductions over maps of predicates arise from time to time in more ordinary situations. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Minor macro help
On Mon, Aug 3, 2009 at 5:43 PM, samppi rbysam...@gmail.com wrote: I'm getting stuck because a-map always gets passed into my-macro as a symbol. (defmacro my-macro [a-map forms] ; Naive implementation `(binding ~(vec (process-a-map a-map)) ~...@forms)) Try (defmacro my-macro [a-map forms] ; Naive implementation `(binding ~(vec (process-a-map ~a-map)) ~...@forms)) If you want something included not as a symbol, precede it with a ~ (does the same thing , does in common lisp). You already have ~...@forms which just does the same thing, except that if forms is a list it is appended to the list it's in rather than inserted as a single item. If bar = (+ 2 3): `(foo bar) = (foo bar) `(foo ~bar) = (foo (+ 2 3)) `(foo ~...@bar) = (foo + 2 3) Takes some getting used to, but once you master Lisp macros, it's Katie bar the door. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Transient Data Structures
On Mon, Aug 3, 2009 at 7:27 PM, CuppoJava patrickli_2...@hotmail.comwrote: Hi Rich, This is a very useful addition thanks. I personally find the O(1) transformation to and back most useful. I have a question about capturing the return values of conj! and assoc!. in this code: (let [v (transient []) v2 (conj! v 0)]) v2 is the captured return value from conj!, which you're supposed to use for future operations. But what does v point to now? The site says: Note in particular that transients are not designed to be bashed in-place. You must capture and use the return value in the next call. So v is not safe to use. Probably either using it throws an exception or else it points to a node in the implementation of v2, but not necessarily the correct head or root node, so that using it will have questionable effects. (Common Lisp has similar cases. Let l be a list, s the results of calling sort on l, and examine l. It's likely to now be a tail of, but not the entirety of, s, because it points to the same cons it always did and sort moved that cons so it isn't the head of the list any more, while returning the head cons. This doesn't happen with Clojure's sort because Clojure's sort doesn't mutate; in Clojure, l stays pointing to the unsorted list and s points to a sorted version. But these new transient mutators may behave more like Common Lisp's sequence mutators in this regard. Rich?) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Minor macro help
On Mon, Aug 3, 2009 at 8:01 PM, CuppoJava patrickli_2...@hotmail.comwrote: You can use eval to retrieve the value of a-map when the macro is expanded. (let [value (eval a-map)] `(binding ~(vec (process-a-map value)) ~...@forms)) I've programmed some substantial programs now in Clojure though, and I've never had to use this. Perhaps there is another way to achieve what you want? As a rule of thumb that I use, using a macro should only look like a syntax extension. There shouldn't be any dependance on the values of any of the arguments. Eh, I hadn't noticed that; he's using process-a-map already in a ~ expression. That's the sort of thing more usually done in a helper function: (defn binding-from-map [a-map forms] `(binding ~(vec (process-a-map a-map)) ~...@forms))) Then call from a macro: (defmacro foo [map body] (binding-from-map map body)) (foo {:a 1} (fn1 arg1) (fn2 arg2 arg3)) If you really want to call the eventual macro with a non-literal map, though, then you'll need it to eval that argument as Patrick says. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Idiomatic parsing of objects from several lines of a text file
On Thu, Jul 30, 2009 at 9:37 PM, Richard Newman holyg...@gmail.com wrote: I suppose in Clojure we could use a real arrow character, with UTF-8 available in symbol names... I don't know about you, but I personally prefer to only use symbols that I can actually type. Copying and pasting from Character Map kind of interrupts flow, if you know what I mean? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Bug? Definline arguments multiply evaluated.
user= (definline addsq [a b] `(+ (* ~a ~a) (* ~b ~b))) #'hxr.clj.util/addsq user= (addsq (do (println a evaluated) 1) 1) a evaluated a evaluated 2 --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Parallel garbage collection worthwhile?
On Wed, Jul 29, 2009 at 2:59 AM, Daniel Lyons fus...@storytotell.orgwrote: Probably it would help to try and implement a lazy list of the Fibonacci sequence before looking at that code, and then maybe try some other mathematical sequences that are a little easier to construct too. Using the super-lazy-seq macro Wrexsoul posted a month or so ago, that's dead easy: (super-lazy-seq [a 0 b 1] (next-item b b (+ a b))) On the other hand, (defn fibs [] (cons 1 (cons 1 (lazy-seq (map + (fibs) (rest (fibs))) (def fibs (memoize fibs)) works and is done with map rather than a looping-like construct. (Without the memoize, the latter is exponential in time; with it, though, all generated terms are retained in memory. This could be scoped, by using (binding [fibs (memoize fibs)] (take n fibs)) or whatever whenever you needed to do something with (part of) fibs, and returning something. Downside: binding doesn't work well with lazy seqs. It's actually probably easier to use the first version efficiently in a pure-functional way, even if its less pure-functional inside. On the other hand, I'm a bit suspicious of that macro. It seems to work for common cases, but I suspect it will not work properly if you shadow one of its loop bindings with a let in the loop body, as I think it doesn't care if it's the same var so long as it has the same name when it wraps the loop vars in a deref. (map second (iterate (fn [[a b]] [b (+ a b)]) [0 1])) seems to work though and avoids the memory problems of the memoized function, the exponential tendencies of the un-memoized function, AND the super-lazy-seq macro (and even the lazy-seq macro). Interestingly, it works identically to the super-lazy-seq macro in that both start with a pair of [a = 0, b = 1] and transform it according to [a - b, b - (+ a b)]. In fact, there's a general correspondence between (map #(nth % n) (iterate (fn [[a b c ... z]] [exprs]) [a0 b0 c0 ... z0])) and (super-lazy-seq [a a0 b b0 c c0 ... z z0] (next-item an exprs)) and I suspect the map/iterate versions to be more efficient since they avoid atoms. (On the other hand, if the sequence is generated in a non-functional way, such as from network I/O, super-lazy-seq seems to me to be a better fit as long as you avoid shadowing any of its loop bindings internally.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: a denilling macro
On Mon, Jul 27, 2009 at 8:33 PM, nchubrich nicholas.chubr...@gmail.comwrote: Anyway I'd appreciate any critiques of the implementation; whether it's a useful thing or not; if there are more idiomatic ways of doing the same thing; and, if yes-no to the aforetwo, where's the best place to add this functionality? Well, it won't actually work properly at run-time, and won't work with a multiple-expression body. Try: (defmacro i-let [bindings body] (assert-args i-let (vector? bindings) a vector for its bindings (= 0 (mod (count bindings) 3)) forms by three in binding vector) (if (empty? bindings) `(let ~bindings ~body) `(let [nom# ~(bindings 0) attempted-val# ~(bindings 1) nil-val# ~(bindings 2)] (if (nil? attempted-val#) (let [~nom# ~nil-val#] (i-let ~(vec (drop 3 bindings)) ~...@body)) (let [~nom# ~attempted-val#] (i-let ~(vec (drop 3 bindings)) ~...@body)) though I'm somewhat dubious about it producing trees of nested lets instead of a single let, with many copies of the body, too; why not (defmacro i-let [bindings body] (assert-args i-let (vector? bindings) a vector for its bindings (= 0 (mod (count bindings) 3)) forms by three in binding vector) `(let ~(vec (reduce concat (map #(list (first %) `(let [x# ~(second %)] (if (nil? x#) ~(second (rest %)) x#))) (partition 3 bindings ~...@body)) Input: (i-let [x (foo) 0 y (:key strct) (:key default-map)] (swap! foo bar baz) (inc x)) Output: (let [x (let [x__1034__auto__ (foo)] (if (nil? x__1034__auto__) 0 x__1034__auto__)) y (let [x__1034__auto__ (:key strct)] (if (nil? x__1034__auto__) (:key default-map) x__1034__auto__))] (swap! foo bar baz) (inc x)) Note that this just automates what you said you were too lazy to do, write an if for every binding. This is generally how best to do macros: make them generate the same code you'd otherwise write manually. :) (You can test it yourself using macroexpand-1 if you want to.) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbish question. Does anyone have any example code for playing a wav sound file?
On Mon, Jul 27, 2009 at 9:00 PM, Rayne disciplera...@gmail.com wrote: I've googled around, and found several ways to do this in Java, but I've not been successful in translating the less-complex examples. I'm wondering, how would an experienced Clojurian go about doing this in Clojure? On my system, the following works even for mp3 files and other compressed ones, if the appropriate JavaSound plugins are installed. It should work for plain wavs with a bare-bones Java 6/Clojure install. It blocks, so you might want to invoke it in a separate thread/via an Agent in actual practice. (It might also be instructive as an example of Java interop involving things like byte buffers.) (defn play Plays an audio file. Blocks until playback is complete. [file] (let [f (if (instance? java.io.File file) file (java.io.File. file))] (with-open [aif (javax.sound.sampled.AudioSystem/getAudioInputStream f) ais (javax.sound.sampled.AudioSystem/getAudioInputStream javax.sound.sampled.AudioFormat$Encoding/PCM_SIGNED aif)] (let [af (.getFormat ais)] (with-open [line (javax.sound.sampled.AudioSystem/getSourceDataLine af)] (.open line af) (let [bufsize (.getBufferSize line) buf (into-array Byte/TYPE (repeat bufsize (byte 0)))] (.start line) (loop [] (let [br (.read ais buf 0 bufsize)] (if-not (= -1 br) (do (.write line buf 0 br) (recur)) (doto line (.drain) (.stop))) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: gen-class bytecode for method implementation
On Mon, Jul 27, 2009 at 3:37 PM, Mark Addleman mark_addle...@bigfoot.comwrote: I have written some Clojure code to implement java.lang.CharSequence that is constructed with a length and an ISeq of strings. I need this because I want to pass the resulting CharSequence into Java's regex library. I got the thing working (thanks to the docs and some good examples that I found in the discussion group) and I'm trying to optimize it now. I'm willing to accept the Clojure code being ~2x slower than the Java equivalent, but the best I can do is 10x slower. The code is below. After examining the resulting bytecode, it looks to me that the problem is that the Clojure compiler dispatches every method to an IFn that is bound as part of the class initialization. It's a cool idea that probably saved implementation effort but I'm pretty sure all the boxing/unboxing of primitives is what's killing the performance. My question is: Can someone come up with a better way of implementing this to avoid the performance problems? The only way to avoid boxing and unboxing of primitives is to avoid passing them as arguments or returning them. It *may* work if you declare the functions inline that need to do so, but you may need to rewrite it in a less functional style using loop/recur. Clojure is capable of the speed you want, though; indeed, even of the speed of hand-tuned assembly, when done 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---