Re: Today's clojure trick question
Sean Corfield writes: > On Wed, Aug 18, 2010 at 10:28 AM, Shantanu Kumar > wrote: >> Would suggest to consider this: >> >> (let [ x (true? (new java.lang.Boolean false)) ] (if x "trouble" >> "ok")) > > Ah, but that wouldn't work for a new Boolean set to true: > > (let [ x (true? (new java.lang.Boolean true)) ] (if x "ok" "trouble")) > > Expect "ok"? Nope, you'll get "trouble". How about something along these lines? (defmacro careful-if [test then else] `(let [result# ~test] (cond (nil? result#) ~else (identical? Boolean/FALSE result#) ~else (identical? Boolean/TRUE result#) ~then (instance? Boolean result#) (if (Boolean/valueOf result#) ~then ~else) :else ~then))) In the case of a "proper" boolean value I think you just get one more reference check than with normal "if"; you only hit reflection if both those reference checks fail. It satisfies the original author's challenge, anyway: (map #(careful-if %1 :truthy :falsey) [true false (new Boolean true) (new Boolean false)]) ;;; => (:truthy :falsey :truthy :falsey) I'll leave it to someone more skilled in Clojure than me to tell us what would be the impact of either using this as a replacement "if" or somehow embedding similar logic into the Java interop functions... -- Mark Shroyer http://markshroyer.com/contact/ -- You 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: Today's clojure trick question
I copy that. Thanks for the explanation. On Aug 18, 1:22 pm, Matt Fowles wrote: > Armando~ > > Libraries that target JRE 1.2 compatibility, will not call > `Boolean.valueOf(var)` internally. Instead they will call `new > Boolean(var)`. If they return those results to modern java code, it will > unbox correctly into either true or false and thus work as expected in > constructs of the form: > > if (old_library_call()) { > // handle true > > } else { > // handle false > } > > If clojure's `if` form does not correctly unbox Booleans in the same manner, > then that really should be viewed as a bug in Clojure. As these libraries > are not likely to change to using the newer `Boolean.valueOf()` since that > break compatibility. Yes, they could create their own static factory for > Booleans and call that instead, but I don't think consumers of the library > are going to want to figure out (the hard way) that they need to hack their > library to use it from Clojure. > > Matt > > On Wed, Aug 18, 2010 at 4:07 PM, Armando Blancas > wrote: > > > > > I don't see what the concern may be. Can you elaborate? > > > On Aug 18, 10:04 am, Matt Fowles wrote: > > > All~ > > > > Boolean.valueOf() was added in 1.4. While that seems ancient, some older > > > libraries use 'new Boolean()' because they maintain 1.2 compatibility. > > It > > > seems like Clojure should take more care when it unboxes Booleans... > > > > Matt > > > > On Wed, Aug 18, 2010 at 12:57 PM, Nicolas Oury > >wrote: > > > > > I am not an expert. Is it possible on some JDK to put a breakpoint on > > > > Boolean constructor and look at the stack? > > > > Or you can't put a breakpoint on standard library? > > > > > -- > > > > You 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-Hide quoted text - > > > > - Show quoted text - > > > -- > > You 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- Hide quoted text - > > - Show quoted text - -- You 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: Today's clojure trick question
Armando~ Libraries that target JRE 1.2 compatibility, will not call `Boolean.valueOf(var)` internally. Instead they will call `new Boolean(var)`. If they return those results to modern java code, it will unbox correctly into either true or false and thus work as expected in constructs of the form: if (old_library_call()) { // handle true } else { // handle false } If clojure's `if` form does not correctly unbox Booleans in the same manner, then that really should be viewed as a bug in Clojure. As these libraries are not likely to change to using the newer `Boolean.valueOf()` since that break compatibility. Yes, they could create their own static factory for Booleans and call that instead, but I don't think consumers of the library are going to want to figure out (the hard way) that they need to hack their library to use it from Clojure. Matt On Wed, Aug 18, 2010 at 4:07 PM, Armando Blancas wrote: > I don't see what the concern may be. Can you elaborate? > > On Aug 18, 10:04 am, Matt Fowles wrote: > > All~ > > > > Boolean.valueOf() was added in 1.4. While that seems ancient, some older > > libraries use 'new Boolean()' because they maintain 1.2 compatibility. > It > > seems like Clojure should take more care when it unboxes Booleans... > > > > Matt > > > > On Wed, Aug 18, 2010 at 12:57 PM, Nicolas Oury >wrote: > > > > > > > > > I am not an expert. Is it possible on some JDK to put a breakpoint on > > > Boolean constructor and look at the stack? > > > Or you can't put a breakpoint on standard library? > > > > > -- > > > You 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- Hide quoted text - > > > > - Show quoted text - > > -- > You 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: Today's clojure trick question
> However, if you do (let [x (java.lang.Boolean/getBoolean "false")] (if > x :trouble :ok)) you're fine, which obviously isn't helpful in your > situation. Boolean.getBoolean() is pretty evil, too. It was featured in one of Joshua Bloch's java puzzlers (which might have been borrowed from somewhere else, I don't know if it was originally his). Watch out, it might not do what you think it does. :) For instance: System.out.println(Boolean.getBoolean("false")); System.out.println(Boolean.getBoolean("true")); System.out.println(Boolean.getBoolean("fred")); will print false three times. Joe -- You 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: Today's clojure trick question
I don't see what the concern may be. Can you elaborate? On Aug 18, 10:04 am, Matt Fowles wrote: > All~ > > Boolean.valueOf() was added in 1.4. While that seems ancient, some older > libraries use 'new Boolean()' because they maintain 1.2 compatibility. It > seems like Clojure should take more care when it unboxes Booleans... > > Matt > > On Wed, Aug 18, 2010 at 12:57 PM, Nicolas Oury wrote: > > > > > I am not an expert. Is it possible on some JDK to put a breakpoint on > > Boolean constructor and look at the stack? > > Or you can't put a breakpoint on standard library? > > > -- > > You 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- Hide quoted text - > > - Show quoted text - -- You 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: Today's clojure trick question
All~ Boolean.valueOf() was added in 1.4. While that seems ancient, some older libraries use 'new Boolean()' because they maintain 1.2 compatibility. It seems like Clojure should take more care when it unboxes Booleans... Matt On Wed, Aug 18, 2010 at 12:57 PM, Nicolas Oury wrote: > I am not an expert. Is it possible on some JDK to put a breakpoint on > Boolean constructor and look at the stack? > Or you can't put a breakpoint on standard library? > > -- > You 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: Today's clojure trick question
On Wed, Aug 18, 2010 at 10:28 AM, Shantanu Kumar wrote: > Would suggest to consider this: > > (let [ x (true? (new java.lang.Boolean false)) ] (if x "trouble" > "ok")) Ah, but that wouldn't work for a new Boolean set to true: (let [ x (true? (new java.lang.Boolean true)) ] (if x "ok" "trouble")) Expect "ok"? Nope, you'll get "trouble". -- Sean A Corfield -- (904) 302-SEAN Railo Technologies, Inc. -- http://getrailo.com/ An Architect's View -- http://corfield.org/ "If you're not annoying somebody, you're not really alive." -- Margaret Atwood -- You 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: Today's clojure trick question
Would suggest to consider this: (let [ x (true? (new java.lang.Boolean false)) ] (if x "trouble" "ok")) Regards, Shantanu On Aug 18, 10:05 pm, Chas Emerick wrote: > No, you can put a breakpoint on any class, regardless of where it's > been loaded from. > > In this case, I'd suggest not relying on the line numbers shown in > source dumps. At least in my experience, line numbers in the standard > library source differ from what is shown at runtime. All three Java > IDEs allow you to set breakpoints on specific classes and methods, > irrespective of line number -- doing that will allow you to set the > right breakpoint, if the line number in Boolean(boolean) happens > to mismatch whichever source tree you have wired into the IDE. > > - Chas > > On Aug 18, 12:57 pm, Nicolas Oury wrote: > > > > > > > > > I am not an expert. Is it possible on some JDK to put a breakpoint on > > Boolean constructor and look at the stack? > > Or you can't put a breakpoint on standard library? -- You 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: Today's clojure trick question
No, you can put a breakpoint on any class, regardless of where it's been loaded from. In this case, I'd suggest not relying on the line numbers shown in source dumps. At least in my experience, line numbers in the standard library source differ from what is shown at runtime. All three Java IDEs allow you to set breakpoints on specific classes and methods, irrespective of line number -- doing that will allow you to set the right breakpoint, if the line number in Boolean(boolean) happens to mismatch whichever source tree you have wired into the IDE. - Chas On Aug 18, 12:57 pm, Nicolas Oury wrote: > I am not an expert. Is it possible on some JDK to put a breakpoint on > Boolean constructor and look at the stack? > Or you can't put a breakpoint on standard library? -- You 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: Today's clojure trick question
I am not an expert. Is it possible on some JDK to put a breakpoint on Boolean constructor and look at the stack? Or you can't put a breakpoint on standard library? -- You 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: Today's clojure trick question
On Wed, Aug 18, 2010 at 11:58 AM, Brian Hurt wrote: > For the record, no where in my code am I deliberately creating Boolean > objects. Why the hell would I write (new java.lang.Boolean false) when I > can just as easily write false? And I have looked through the code to see > if something stupid like that did sneak in, and didn't find anything. So > this means what is happening is the values are being boxed because of some > subtle interaction I haven't tracked down yet. Could it be something to do > with Java's serialization? Or maybe the way Clojure boxes boolean values? > I don't know. So unless you have some information on what I could be doing > wrong, simply going "don't do that" does not help. > > Brian > Boxing has nothing to do with it. (let [x ((fn [] false))] (if x "trouble" "ok")) ; "ok" Somewhere new Boolean values are being constructed. Are you using an external Java library that might be doing 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: Today's clojure trick question
On Wed, Aug 18, 2010 at 11:09 AM, Brian Hurt wrote: > Consider the following bit of code: > > (let [ x (new java.lang.Boolean false) ] (if x "trouble" "ok")) I consider the fact that Boolean has a public constructor a bug. It can only ever represent 2 values. However, if you do (let [x (java.lang.Boolean/getBoolean "false")] (if x :trouble :ok)) you're fine, which obviously isn't helpful in your situation. > As you might guess from the fact that I'm calling it's a trick question, the > above code returns "trouble", not "ok". From experimentation, it looks like > clojure's if takes the second branch if the value is nil or referentially > equal to java.lang.Boolean/FALSE. If you have a boolean object which is not > referentially equal to Boolean/FALSE, but still holds the value false, this > is treated as true by Clojure. > > The problem is, I'm not 100% sure if this is a bug or not. The problem is > nil-punning. The if statement can't rely on the test expression evaluating > to a boolean. Which means to make this work correctly, if statements would > have to do an instanceof test (to see if the object was a Boolean), then a > cast and a call to .booleanValue to get the boolean value. Which is way > more expensive than a quick nil test and referential equality test. > > This is, however, more than a little bit surprising and depressing. > Somewhere, in my 10K lines of clojure code, boolean values are getting boxed > in exactly that way. I've fixed the current problem (dropping in a call to > .booleanValue in the test), but having if statements that can fail makes me > paranoid. > > Brian > > -- > You 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 -- http://www.apgwoz.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: Today's clojure trick question
On Wed, Aug 18, 2010 at 11:34 AM, David Nolen wrote: > On Wed, Aug 18, 2010 at 11:09 AM, Brian Hurt wrote: > >> This is, however, more than a little bit surprising and depressing. >> Somewhere, in my 10K lines of clojure code, boolean values are getting boxed >> in exactly that way. I've fixed the current problem (dropping in a call to >> .booleanValue in the test), but having if statements that can fail makes me >> paranoid. >> >> Brian >> >> Somewhere in your code you are creating boolean values instead of just > using Clojure's true and false. Get rid of this code. > > > For the record, no where in my code am I deliberately creating Boolean objects. Why the hell would I write (new java.lang.Boolean false) when I can just as easily write false? And I have looked through the code to see if something stupid like that did sneak in, and didn't find anything. So this means what is happening is the values are being boxed because of some subtle interaction I haven't tracked down yet. Could it be something to do with Java's serialization? Or maybe the way Clojure boxes boolean values? I don't know. So unless you have some information on what I could be doing wrong, simply going "don't do that" does not help. Brian -- You 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: Today's clojure trick question
On Wed, Aug 18, 2010 at 11:09 AM, Brian Hurt wrote: > Consider the following bit of code: > > (let [ x (new java.lang.Boolean false) ] (if x "trouble" "ok")) The Javadoc for Boolean has something to say on this subject[1] as does the following excerpt from Fogus' book The Joy of Clojure: Don't create Boolean objects It is possible to create an object that looks a lot like, but is not actually, `false`. Java has left a little landmine for you here, so take a moment to look at it so that you can step past it gingerly and get on with your life: (def evil-false (Boolean. "false")) ; NEVER do this This creates a new instance of Boolean -- and that's already wrong! Since there are only two possible values of Boolean, an instance of each has already been made for you -- they're named `true` and `false`. But here you've gone and done it anyway, created a new instance of Boolean and stored it in a Var named `evil-false`. It looks like false: evil-false ;=> false Sometimes it even acts like false: (= false evil-false) ;=> true But once it gains your trust, it will show you just how wicked it is by acting like `true`: (if evil-false :truthy :falsey) ;=> :truthy Java's own documentation warns against the creation of this evil thing, and now you've been warned again. If you just want to parse a string, use Boolean's static method instead of its constructor. This is the right way: (if (Boolean/valueOf "false") :truthy :falsey) ;=> :falsey --Chouser http://joyofclojure.com/ 1: http://download-llnw.oracle.com/javase/1.5.0/docs/api/java/lang/Boolean.html#Boolean%28boolean%29 -- You 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: Today's clojure trick question
On Wed, Aug 18, 2010 at 11:09 AM, Brian Hurt wrote: > This is, however, more than a little bit surprising and depressing. > Somewhere, in my 10K lines of clojure code, boolean values are getting boxed > in exactly that way. I've fixed the current problem (dropping in a call to > .booleanValue in the test), but having if statements that can fail makes me > paranoid. > > Brian > > Somewhere in your code you are creating boolean values instead of just using Clojure's true and false. Get rid of this code. David -- You 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: Today's clojure trick question
(defmacro fat-if) On Wed, Aug 18, 2010 at 4:09 PM, Brian Hurt wrote: > Consider the following bit of code: > > (let [ x (new java.lang.Boolean false) ] (if x "trouble" "ok")) > > As you might guess from the fact that I'm calling it's a trick question, the > above code returns "trouble", not "ok". From experimentation, it looks like > clojure's if takes the second branch if the value is nil or referentially > equal to java.lang.Boolean/FALSE. If you have a boolean object which is not > referentially equal to Boolean/FALSE, but still holds the value false, this > is treated as true by Clojure. > > The problem is, I'm not 100% sure if this is a bug or not. The problem is > nil-punning. The if statement can't rely on the test expression evaluating > to a boolean. Which means to make this work correctly, if statements would > have to do an instanceof test (to see if the object was a Boolean), then a > cast and a call to .booleanValue to get the boolean value. Which is way > more expensive than a quick nil test and referential equality test. > > This is, however, more than a little bit surprising and depressing. > Somewhere, in my 10K lines of clojure code, boolean values are getting boxed > in exactly that way. I've fixed the current problem (dropping in a call to > .booleanValue in the test), but having if statements that can fail makes me > paranoid. > > Brian > > -- > You 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
Today's clojure trick question
Consider the following bit of code: (let [ x (new java.lang.Boolean false) ] (if x "trouble" "ok")) As you might guess from the fact that I'm calling it's a trick question, the above code returns "trouble", not "ok". From experimentation, it looks like clojure's if takes the second branch if the value is nil or referentially equal to java.lang.Boolean/FALSE. If you have a boolean object which is not referentially equal to Boolean/FALSE, but still holds the value false, this is treated as true by Clojure. The problem is, I'm not 100% sure if this is a bug or not. The problem is nil-punning. The if statement can't rely on the test expression evaluating to a boolean. Which means to make this work correctly, if statements would have to do an instanceof test (to see if the object was a Boolean), then a cast and a call to .booleanValue to get the boolean value. Which is way more expensive than a quick nil test and referential equality test. This is, however, more than a little bit surprising and depressing. Somewhere, in my 10K lines of clojure code, boolean values are getting boxed in exactly that way. I've fixed the current problem (dropping in a call to .booleanValue in the test), but having if statements that can fail makes me paranoid. Brian -- You 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