Re: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
One answer to my question would be to force Clojure to throw an exception if querying a non-existant property on the data-structure...is that possible? For example, in the following snippet, (t {:c 10}) would fail. I assume a macro-or-something? Clojure> (defn t [a] (print (str (:b a #'sandbox5950/t Clojure> (t {:b 10}) 10nil Clojure> (t {:c 10}) nil Clojure> -- You 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: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
> One answer to my question would be to force Clojure to throw an exception if > querying a non-existant property on the data-structure...is that possible? > For example, in the following snippet, (t {:c 10}) would fail. I assume a > macro-or-something? > > Clojure> (defn t [a] (print (str (:b a > #'sandbox5950/t > Clojure> (t {:b 10}) > 10nil > Clojure> (t {:c 10}) > nil > Clojure> You should take a look at Clojure's pre-conditions for a possible solution. Here is a blog post that explains their usage - http://blog.fogus.me/2009/12/21/clojures-pre-and-post/ Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
Hi, Baishampayan beat me to it. But to elaborate more: You have to expose each contract up the function chain. Say it looks like this: (defn calculate-insurance [& items] {:pre [(every? #(contains? % :cost-replace-with-new) items)]} ...) Then funcE and funcD have to check this also. funcC doesn't because it adds said key to the data structure. If you change funcC to not add it, you'll also have to change funcC's contract. So you'd find the error in the call to funcD in funcC which is the first possible place to spot it (in case the change of contract was missed). If you'd change the contracts of the complete function chain, you'd spot it immediatelly in funcA. This is similar to changing the type of the items from Insurable to WrappedInsurableAdapter or such. There are things which bubble up. If you'd want something more akin classes and interfaces, you could use defrecord with (partial satisfies? PInsurable). Sincerely Meikel /me is waiting for David and Ambrose coming up with contract checker written in core.logic. -- You 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: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
Thanks both - DBC is one answer - yes. Very nice - I hadn't realised this was there. So this is the issue - funcD and funcE shouldn't know about the contract because they have no requirement for :cost-replace-with-new - they are simply wrappers for logging and performance monitoring for example. This means that funcC's post constructor should check for the output and func-calculate-insurance should assert it in the pre condition. I guess the navigational issue (who else is affected by the change in this func) can be done using keywords to search. I assumed a protocol should still return null rather than throw an exception? This definitely feels like the right solution - so essentially the reason this isn't an issue in statically typed languages is because the compiler enforces DBC where the contract *is* the type of the method signatures. I should have realised that and written a three line question originally ;) -- You 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: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
As I understand the problem in your example, you do have a definition for what an Insurable is, but it's implicit: there's no way to check whether an object is insurable and thus no way to check which parts of the code break when the notion of being Insurable changes. Luckily Clojure provides us with the tools needed to make the definition explicit. In your Java example you used an interface to define what an Insurable is. In Clojure you can do the same with a protocol: (defprotocol Insurable (cost-to-replace-with-new [insurable])) (def insurable? (partial satisfies? Insurable)) Whenever you expect to receive an insurable, you can use a precondition to make this assumption explicit, like BG and Meikel suggested: (defn calculate-insurance [& insurables] {:pre [(every? insurable? insurables)]} ...) Note that the Insurable objects are completely abstract; we don't know or care what kind of data structure are used to implement them. This means that we can't build valid Insurables by accident, like you did in your example by calling FuncA to FuncE, but that's a *good* thing, because data structures built like that are very brittle, as you noted. To wrap up the example, here are a two very different implementations of Insurable. Note how everything is modeled in terms of domain concepts instead of "maps with keys :x, :y and :z". We manipulate the data structures with completely normal Clojure code, but keep the knowledge of those data structures in one place only instead of spreading it all over the codebase. This makes the code much more robust and amenable to change. (defn make-simple-insurable [cost] {:post [(insurable? %)]} (reify Insurable (cost-to-replace-with-new [_] cost))) (defrecord CompositeInsurable [parts] Insurable (cost-to-replace-with-new [composite-insurable] (->> (:parts composite-insurable) (map cost-to-replace-with-new) (reduce + (defn make-composite-insurable [& parts] {:pre [(every? insurable? parts)] :post [(insurable? %)]} (CompositeInsurable. parts)) -- Timo -- You 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: (OTP slightly) - ensuring assumptions about structure of function arguments in dynamic languages
This is very helpful. I think my false assumption was that structural contracts weren't enforced, even with protocols. Your example is very helpful. On 30 January 2012 11:43, Timo Mihaljov wrote: > As I understand the problem in your example, you do have a definition > for what an Insurable is, but it's implicit: there's no way to check > whether an object is insurable and thus no way to check which parts of > the code break when the notion of being Insurable changes. Luckily > Clojure provides us with the tools needed to make the definition > explicit. > > In your Java example you used an interface to define what an Insurable > is. In Clojure you can do the same with a protocol: > >(defprotocol Insurable > (cost-to-replace-with-new [insurable])) > >(def insurable? (partial satisfies? Insurable)) > > Whenever you expect to receive an insurable, you can use a > precondition to make this assumption explicit, like BG and Meikel > suggested: > >(defn calculate-insurance [& insurables] > {:pre [(every? insurable? insurables)]} > ...) > > Note that the Insurable objects are completely abstract; we don't know > or care what kind of data structure are used to implement them. This > means that we can't build valid Insurables by accident, like you did > in your example by calling FuncA to FuncE, but that's a *good* thing, > because data structures built like that are very brittle, as you > noted. > > To wrap up the example, here are a two very different implementations > of Insurable. Note how everything is modeled in terms of domain > concepts instead of "maps with keys :x, :y and :z". We manipulate the > data structures with completely normal Clojure code, but keep the > knowledge of those data structures in one place only instead of > spreading it all over the codebase. This makes the code much more > robust and amenable to change. > >(defn make-simple-insurable [cost] > {:post [(insurable? %)]} > (reify Insurable >(cost-to-replace-with-new [_] > cost))) > >(defrecord CompositeInsurable [parts] > Insurable > (cost-to-replace-with-new [composite-insurable] >(->> (:parts composite-insurable) > (map cost-to-replace-with-new) > (reduce + > >(defn make-composite-insurable [& parts] > {:pre [(every? insurable? parts)] > :post [(insurable? %)]} > (CompositeInsurable. parts)) > > -- > Timo > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Exchange value between refs
Hi, I want to change state of two refs, exchanging between them. Currently this is what I do: (dosync (let [a (first @v) b (second @v)] (alter a assoc :color (:color @b)) (alter b assoc :color (:color @a I wonder if there's a better approach, maybe one single function does this. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: Exchange value between refs
Actually this is wrong, I bind the value of the :color of a first, before I alter b -- You 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: Exchange value between refs
Hi, a simple let does the trick, no? (dosync (let [av @a bv @b] (alter a assoc :color (:color bv)) (alter b assoc :color (:color av Sincerely Meikel -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exchange value between refs
Yes, that's what I've been doing What I want to know is if there's a single function that does this exchange between refs. -- You 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: Exchange value between refs
Hi, (defn exchange! [a b & {:keys [getter setter] {getter identity setter (fn [_ v] v)}}] (let [av @a bv @b] (alter a setter (getter bv)) (alter b setter (getter av (defn exchange-color! [a b] (exchange! a b :getter :color :setter #(assoc %1 :color %2))) (exchange-color! a b) Something like that? Sincerely Meikel -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exchange value between refs
yes, that works! thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exchange value between refs
Hi again, or more like this: (defn exchange! [a b & {:keys [f] {f (fn [_ v] v)}}] (let [av @a bv @b] (alter a f bv) (alter b f av))) (defn exchange-color! [a b] (exchange! a b :f #(assoc %1 :color (:color %2 (exchange-color! a b) Sincerely Meikel -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exchange value between refs
Here's a bit more of playing around at the repl. clojure.core=> a b # # clojure.core=> (for [[x y] [[a @b] [b @a]]] (swap! x assoc :color (:color y))) ({:color :red} {:color :blu}) clojure.core=> a b # # clojure.core=> (for [[x y] [[a @b] [b @a]]] (swap! x merge y)) ({:color :blu} {:color :red}) clojure.core=> a b # # clojure.core=> (map #(swap! %1 merge %2) [a b] [@b @a]) ({:color :red} {:color :blu}) clojure.core=> a b # # clojure.core=> (map #(swap! %1 assoc :color (:color %2)) [a b] [@b @a]) ({:color :blu} {:color :red}) clojure.core=> a b # # note, map & for are lazy, so you'll need a (doall) or something else to force evaluation (I think). Or, you could just use doseq clojure.core=> a b # # clojure.core=> (doseq [[x y] [[a @b] [b @a]]] (swap! x assoc :color (:color y))) nil clojure.core=> a b # # clojure.core=> (doseq [[x y] [[a @b] [b @a]]] (swap! x merge y)) nil clojure.core=> a b # # Cheers, Jay On Mon, Jan 30, 2012 at 8:07 AM, Meikel Brandmeyer (kotarak) wrote: > Hi again, > > or more like this: > > (defn exchange! > [a b & {:keys [f] {f (fn [_ v] v)}}] > > (let [av @a bv @b] > (alter a f bv) > (alter b f av))) > > (defn exchange-color! > [a b] > (exchange! a b :f #(assoc %1 :color (:color %2 > > (exchange-color! a b) > > > Sincerely > Meikel > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You 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: Literate programming in emacs - any experience?
On Sat, 2012-01-28 at 10:04 -0500, daly wrote: > On Sat, 2012-01-28 at 06:51 -0800, Folcon wrote: > > Hi Tim, > > > > > > Personally if you have done or would be interested in doing a quick > > vid cast of how you progress through your workflow, I think that would > > be very interesting. > > Sort of "extreme pair programming with everybody"? :-) > There is no such thing as a simple job but I'll see what I can do. > A watchable video takes time to compose. I am composing the notes for this video and I realized I have a piece of programming information about myself that you probably do not have about yourself. Years ago I wrote a program (Archive) to allow users of a time shared mainframe to back up programs to magnetic tape. This was a single person project. As an experiment I copied every input at the keyboard and every output of every command. I also kept a journal of everything I did, why I did it, and what failed. The key result was that I discovered what I call my personal "irreducible error rate". If I do 100 things I will make 3 errors. This was independent of the task. So typing 100 characters has 3 wrong letters which were mostly caught while typing. Writing 100 lines of code had 3 errors somewhere. Composing email introduces 3 errors per 100 lines of code. Most of the errors were trivial (spelling), some were syntax (missing delimiter), some were semantic (wrong action), some were design (wrong solution). As a result of this measurement I have formed habits to look for the 3 mistakes I know exist. For example, I am writing a book of Axiom graphics images (a "gallery"). I have written 679 equations so far, which are going to create the images. I know there are at least 21 uncaught errors lurking in those equations. So before I attempt to generate the images I will examine them in detail with an eye toward finding what I know is there. Literate programming is both a source of errors and a help. It is a source of errors because I have more typing to do and will generate bad latex and meaningless sentences, as well as the "standard" coding errors. So in some sense I have added to the number of errors I WILL introduce. But the tools, like the compiler, tex and spellcheck will at least warn me of these failures. However, literate programming helps because I am explaining what I am doing to myself as well as others. This really reduces the "big", "costly" errors, those in the design and implementation. There are no tools to help so I have to create a discipline that will highlight these errors as soon as possible. I KNOW my intrinsic error rate. What is yours? What discipline can you apply to your work to find your errors? I'm not sure how to get this important piece of self-knowledge into the video so I thought I'm mention it here. Tim Daly -- You 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: Exchange value between refs
Nice! I liked the use of *merge* , it seems even more semantic! -- You 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: got trouble when combine use condition-map and doc-string
It works now, thank you, Jonas. -- You 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
optimizations for serving binary with ring
I'm dynamically generating images for a website and I'm hosting the content using ring. Currently I use moustache for routing, where I have a handler that returns a response map and the response map contains a bytearrayinputstream. Currently I wrap the handler that makes the image file with memoize/memo-lru. I thought this would give me the performance improvement I needed, but its still noticeably slow to load a large batch of images (12 images, each 5kb each can take a few seconds, even if its the same set of images being returned). I was expecting the performance to be nearly instant since I'm hosting the website on my local machine. The operation seems to be CPU bound since the CPU usage is high for that moment while the data is transferring, and since the binary data is stored in memory (and when cached the binary data should already be in the image format which is very small, computation of the images should be nil). Are there any tips to improve performance? Is there a better InputStream type to use? -- You 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: optimizations for serving binary with ring
Hmm I seemed to have figured it out. Calling memo-lru on the handler was not a good idea since there are elements that change with each request, therefore all calls were a cache miss. Also I, I can't wrap memo-lru on a function that outputs a bytearrayinputstream since that object has state. I needed to wrap a function that returned a byte-array. Best all. -- You 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