equality

2014-01-27 Thread Eric Le Goff
Newbie question :

user=> (= 42 42)
true
user=> (= 42 42.0)
false

I did not expect last result.

I understand that underlying classes are not the same
i.e
user=> (class 42)
java.lang.Long
user=> (class 42.0)
java.lang.Double


but anyway I'am surprised

Cheers


--
Eric

-- 
-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: equality

2014-01-27 Thread Dennis Haupt
one does not simply compare floating point numbers for equality


2014-01-27 Eric Le Goff 

> Newbie question :
>
> user=> (= 42 42)
> true
> user=> (= 42 42.0)
> false
>
> I did not expect last result.
>
> I understand that underlying classes are not the same
> i.e
> user=> (class 42)
> java.lang.Long
> user=> (class 42.0)
> java.lang.Double
>
>
> but anyway I'am surprised
>
> Cheers
>
>
> --
> Eric
>
>  --
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: equality

2014-01-27 Thread Jim - FooBar();

Use `==` instead:

user=> (== 42 42.0)
true
user=> (== 42 42M)
true

Jim


On 27/01/14 13:41, Dennis Haupt wrote:

one does not simply compare floating point numbers for equality


2014-01-27 Eric Le Goff mailto:eleg...@gmail.com>>

Newbie question :

user=> (= 42 42)
true
user=> (= 42 42.0)
false

I did not expect last result.

I understand that underlying classes are not the same
i.e
user=> (class 42)
java.lang.Long
user=> (class 42.0)
java.lang.Double


but anyway I'am surprised

Cheers


--
Eric

-- 
-- 
You received this message because you are subscribed to the Google

Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
<mailto: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
<mailto:clojure%2bunsubscr...@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 unsubscribe from this group and stop receiving emails from it,
send an email to clojure+unsubscr...@googlegroups.com
<mailto:clojure%2bunsubscr...@googlegroups.com>.
For more options, visit https://groups.google.com/groups/opt_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
---
You received this message because you are subscribed to the Google 
Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to clojure+unsubscr...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: equality

2014-01-27 Thread Andy Fingerhut
As Jim already mentioned, you can use == to compare numbers for equality,
but you must be cautious with equality for floating point numbers, as the
tiniest bit of roundoff error will cause = and == to be false for such
comparisons.

For =, there are effectively 3 'categories' of numeric values in Clojure,
each of which can be = to each other within a category, but between
categories values are never = to each other.

Category 1. integer values (including Java Byte, Short, Integer, Long,
BigInteger, and Clojure BigInt types) and ratio values (Clojure's Ratio
type)
Category 2. float and double values (Java Float and Double)
Category 3. BigDecimal

This is better than Java equals(), where Byte and Short are never equals()
to each other, etc.  Two numeric values must be the same Java class for
equals() to be true.

Why the 3 categories, you may wonder?  I didn't design it myself, but my
best guess is that in order to have a hash function (in this case Clojure's
hash, implemented as a Java method called hasheq()) that is consistent with
Clojure =, it is difficult to make such a hash function correct and fast if
there were not these 3 separate categories.

Andy


On Mon, Jan 27, 2014 at 5:39 AM, Eric Le Goff  wrote:

> Newbie question :
>
> user=> (= 42 42)
> true
> user=> (= 42 42.0)
> false
>
> I did not expect last result.
>
> I understand that underlying classes are not the same
> i.e
> user=> (class 42)
> java.lang.Long
> user=> (class 42.0)
> java.lang.Double
>
>
> but anyway I'am surprised
>
> Cheers
>
>
> --
> Eric
>
>  --
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: equality

2014-01-27 Thread Cedric Greevey
Seems to me that BigDecimal, being essentially a BigInteger numerator and a
power-of-ten denominator, could have been accommodated in Category 1 given
that Ratio could.


On Mon, Jan 27, 2014 at 10:26 AM, Andy Fingerhut
wrote:

> As Jim already mentioned, you can use == to compare numbers for equality,
> but you must be cautious with equality for floating point numbers, as the
> tiniest bit of roundoff error will cause = and == to be false for such
> comparisons.
>
> For =, there are effectively 3 'categories' of numeric values in Clojure,
> each of which can be = to each other within a category, but between
> categories values are never = to each other.
>
> Category 1. integer values (including Java Byte, Short, Integer, Long,
> BigInteger, and Clojure BigInt types) and ratio values (Clojure's Ratio
> type)
> Category 2. float and double values (Java Float and Double)
> Category 3. BigDecimal
>
> This is better than Java equals(), where Byte and Short are never equals()
> to each other, etc.  Two numeric values must be the same Java class for
> equals() to be true.
>
> Why the 3 categories, you may wonder?  I didn't design it myself, but my
> best guess is that in order to have a hash function (in this case Clojure's
> hash, implemented as a Java method called hasheq()) that is consistent with
> Clojure =, it is difficult to make such a hash function correct and fast if
> there were not these 3 separate categories.
>
> Andy
>
>
> On Mon, Jan 27, 2014 at 5:39 AM, Eric Le Goff  wrote:
>
>> Newbie question :
>>
>> user=> (= 42 42)
>> true
>> user=> (= 42 42.0)
>> false
>>
>> I did not expect last result.
>>
>> I understand that underlying classes are not the same
>> i.e
>> user=> (class 42)
>> java.lang.Long
>> user=> (class 42.0)
>> java.lang.Double
>>
>>
>> but anyway I'am surprised
>>
>> Cheers
>>
>>
>> --
>> Eric
>>
>>  --
>> --
>> You 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 unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/groups/opt_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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: equality

2014-01-28 Thread nuryoku san
for comparing floatingpoint-numbers esp. in testcode this is useful:  

(defn- square [n] 
  (* n n))

(defn close-to
  ([a b d] 
(< (square(- a b)) d))
  ([a b]
(close-to a b 0.01)))



-- 
-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


array equality

2010-01-11 Thread Stuart Halloway

clojure.core/= handles strings and seqs, but not arrays:

(apply = ["A" "A"])
=> true

(apply = (map #(.getBytes %) ["A" "A"]))
=> false

(apply = (map #(seq (.getBytes %)) ["A" "A"]))
=> true

I know how this happens, but not why. Is it a motivated design choice,  
or would a patch be welcome?


Stu

-- 
You 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

Testing equality

2010-04-28 Thread WoodHacker
Can someone explain to me why this doesn't work:

  (let [ p "Bill/"
  sep (System/getProperty "file.separator")
   ]

  (if (= (last p) sep)
  (println "found separator")
  (println "no separator")
  )

The (= (last p) sep) always returns false.   If I print them out
inside pipes they look like
| / | and | / | (white space on either side of the slash).

Is this some sort of bug?   Is there a better solution for finding a
file separator at the end of a line?

Bill




-- 
You 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


Set equality bug?

2015-01-22 Thread Immo Heikkinen
(= (float 0.5) (double 0.5))
=> true
(= #{(float 0.5)} #{(double 0.5)})
=> true
(= {:a (float 0.5)} {:a (double 0.5)})
=> true
(= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
=> false


Tested with both 1.6.0 and 1.7.0-alpha5.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Keyword equality check

2014-02-12 Thread Arkadiusz Komarzewski
Hi,

I wonder how is equality of keywords implemented in Clojure?

I have this piece of Java code executed in one classloader:
Keyword a = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");

Then, when I pass it to another part of my application (which uses another 
classloader) and do this:
Keyword b = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
assert a == b;

Assertion passes.
Why does it work? If I'm correct, keywords are interned, but since they 
were created in separate classloaders shouldn't that assert fail?

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Eval destroys equality

2011-05-05 Thread Dominikus
My observation is best distilled with the following definition of a
function in Clojure 1.2:

user=> (defn id [x] (list id x))
#'user/id

Interstingly, (id 7) and (eval (id 7)) result in different instances
of function id as the number after the '@' char unveils:

user=> (id 7)
(# 7)
user=> (eval (id 7))
(# 7)

Consequently, the following comparison leads to false:

user=> (= (id 7) (eval (id 7)))
false

Why is the instance relevant to '='? What is the precise semantics of
two values being equal in Clojure?

Dominikus

(Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
restrictive 'equal?' does not and returns #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: array equality

2010-01-11 Thread Laurent PETIT
Since arrays are not immutable, it's certainly wise to only consider
equality to be based on java object identity ? At least I remember
Rich mentioning this rationale, which sounds reasonable to me.

2010/1/11 Stuart Halloway :
> clojure.core/= handles strings and seqs, but not arrays:
>
> (apply = ["A" "A"])
> => true
>
> (apply = (map #(.getBytes %) ["A" "A"]))
> => false
>
> (apply = (map #(seq (.getBytes %)) ["A" "A"]))
> => true
>
> I know how this happens, but not why. Is it a motivated design choice, or
> would a patch be welcome?
>
> Stu
>
>
> --
> You 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: Testing equality

2010-04-28 Thread David Nolen
On Wed, Apr 28, 2010 at 9:30 AM, WoodHacker  wrote:

> Can someone explain to me why this doesn't work:
>
>  (let [ p "Bill/"
>  sep (System/getProperty "file.separator")
>   ]
>
>  (if (= (last p) sep)
>  (println "found separator")
>  (println "no separator")
>  )


(last p)

Will return a char, while

(System/geProperty "file.separator")

returns a string.

(= (str \/) "/") ; true

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: Testing equality

2010-04-28 Thread Teemu Antti-Poika


On Apr 28, 4:30 pm, WoodHacker  wrote:
> Can someone explain to me why this doesn't work:
>
>   (let [ p     "Bill/"
>           sep (System/getProperty "file.separator")
>            ]
>
>       (if (= (last p) sep)
>           (println "found separator")
>           (println "no separator")
>   )
>
> The (= (last p) sep) always returns false.   If I print them out
> inside pipes they look like
> | / | and | / | (white space on either side of the slash).
>
> Is this some sort of bug?   Is there a better solution for finding a
> file separator at the end of a line?

In the above p is a character /, and sep is a string of one char "/",
therefore they are not equal.

Maybe you should use String's endsWith?

(.endsWith "bill/" (System/getProperty "file.separator"))

-- 
You 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: Testing equality

2010-04-28 Thread Adrian Cuthbertson
(last p) returns a char \/
(first p) returns \B)

so, use (= (str (last p)) sep)

-Rgds, Adrian.

On Wed, Apr 28, 2010 at 3:30 PM, WoodHacker  wrote:
> Can someone explain to me why this doesn't work:
>
>  (let [ p     "Bill/"
>          sep (System/getProperty "file.separator")
>           ]
>
>      (if (= (last p) sep)
>          (println "found separator")
>          (println "no separator")
>  )
>
> The (= (last p) sep) always returns false.   If I print them out
> inside pipes they look like
> | / | and | / | (white space on either side of the slash).
>
> Is this some sort of bug?   Is there a better solution for finding a
> file separator at the end of a line?
>
> Bill
>
>
>
>
> --
> You 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: Testing equality

2010-04-28 Thread Mike DeLaurentis
Depending on what you're trying to do with paths, you may want to construct
File objects and then get the paths from them.  For example,

(let [home (File. "/Users/Bill")
bashrc (File . home ".bashrc")]
  (.getPath bashrc))

I think that tends to be less cumbersome than stringing path components
together directly.


On Wed, Apr 28, 2010 at 9:37 AM, Teemu Antti-Poika wrote:

>
>
> On Apr 28, 4:30 pm, WoodHacker  wrote:
> > Can someone explain to me why this doesn't work:
> >
> >   (let [ p "Bill/"
> >   sep (System/getProperty "file.separator")
> >]
> >
> >   (if (= (last p) sep)
> >   (println "found separator")
> >   (println "no separator")
> >   )
> >
> > The (= (last p) sep) always returns false.   If I print them out
> > inside pipes they look like
> > | / | and | / | (white space on either side of the slash).
> >
> > Is this some sort of bug?   Is there a better solution for finding a
> > file separator at the end of a line?
>
> In the above p is a character /, and sep is a string of one char "/",
> therefore they are not equal.
>
> Maybe you should use String's endsWith?
>
> (.endsWith "bill/" (System/getProperty "file.separator"))
>
> --
> You 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: Set equality bug?

2015-01-22 Thread Nicola Mometto

Looks like it's a bug in PersistentHashMap:
user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
false
user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
true

Immo Heikkinen writes:

> (= (float 0.5) (double 0.5))
> => true
> (= #{(float 0.5)} #{(double 0.5)})
> => true
> (= {:a (float 0.5)} {:a (double 0.5)})
> => true
> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
> => false
>
>
> Tested with both 1.6.0 and 1.7.0-alpha5.

--

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Nicola Mometto

Looking at the PHM impl, this looks like it's caused by (float 0.5) and
(double 0.5) hashing differently.

user=> (= (float 0.5) (double 0.5))
true
user=> (map hash [(float 0.5) (double 0.5)])
(1056964608 1071644672)

Nicola Mometto writes:

> Looks like it's a bug in PersistentHashMap:
> user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
> false
> user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
> true
>
> Immo Heikkinen writes:
>
>> (= (float 0.5) (double 0.5))
>> => true
>> (= #{(float 0.5)} #{(double 0.5)})
>> => true
>> (= {:a (float 0.5)} {:a (double 0.5)})
>> => true
>> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
>> => false
>>
>>
>> Tested with both 1.6.0 and 1.7.0-alpha5.

--

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Jozef Wagner
More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036

On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto  wrote:

>
> Looking at the PHM impl, this looks like it's caused by (float 0.5) and
> (double 0.5) hashing differently.
>
> user=> (= (float 0.5) (double 0.5))
> true
> user=> (map hash [(float 0.5) (double 0.5)])
> (1056964608 1071644672)
>
> Nicola Mometto writes:
>
> > Looks like it's a bug in PersistentHashMap:
> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
> > false
> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
> > true
> >
> > Immo Heikkinen writes:
> >
> >> (= (float 0.5) (double 0.5))
> >> => true
> >> (= #{(float 0.5)} #{(double 0.5)})
> >> => true
> >> (= {:a (float 0.5)} {:a (double 0.5)})
> >> => true
> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
> >> => false
> >>
> >>
> >> Tested with both 1.6.0 and 1.7.0-alpha5.
>
> --
>
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Nicola Mometto

Not sure if this is intended behaviour:
user=> (= (float 1.6) (double 1.6))
false
user=> (= (float 1.5) (double 1.5))
true

I.e. = (and ==) will return true when comparing floats with doubles IFF
the float's .doubleValue roundtrips to the same double it's comparing to.

user=> (.doubleValue (float 1.6))
1.60023841858
user=> (.doubleValue (float 1.5))
1.5

I'm not sure why floats are not handled specially in Numbers.java so
that hash/comparision is handled consistently with doubles (e.g. by
converting the floats to the fitting double via Double.parseDouble),
the current behaviour seems odd to me.

Jozef Wagner writes:

> More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
>
> On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto  wrote:
>
>>
>> Looking at the PHM impl, this looks like it's caused by (float 0.5) and
>> (double 0.5) hashing differently.
>>
>> user=> (= (float 0.5) (double 0.5))
>> true
>> user=> (map hash [(float 0.5) (double 0.5)])
>> (1056964608 1071644672)
>>
>> Nicola Mometto writes:
>>
>> > Looks like it's a bug in PersistentHashMap:
>> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
>> > false
>> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
>> > true
>> >
>> > Immo Heikkinen writes:
>> >
>> >> (= (float 0.5) (double 0.5))
>> >> => true
>> >> (= #{(float 0.5)} #{(double 0.5)})
>> >> => true
>> >> (= {:a (float 0.5)} {:a (double 0.5)})
>> >> => true
>> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
>> >> => false
>> >>
>> >>
>> >> Tested with both 1.6.0 and 1.7.0-alpha5.
>>
>> --
>>
>> --
>> You 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 unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>

--

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Andy Fingerhut
"It is out of scope for Clojure to fix this for Java types Float/Double"
 -- comments in CLJ-1036: http://dev.clojure.org/jira/browse/CLJ-1036

Andy

On Thu, Jan 22, 2015 at 5:53 AM, Nicola Mometto  wrote:

>
> Not sure if this is intended behaviour:
> user=> (= (float 1.6) (double 1.6))
> false
> user=> (= (float 1.5) (double 1.5))
> true
>
> I.e. = (and ==) will return true when comparing floats with doubles IFF
> the float's .doubleValue roundtrips to the same double it's comparing to.
>
> user=> (.doubleValue (float 1.6))
> 1.60023841858
> user=> (.doubleValue (float 1.5))
> 1.5
>
> I'm not sure why floats are not handled specially in Numbers.java so
> that hash/comparision is handled consistently with doubles (e.g. by
> converting the floats to the fitting double via Double.parseDouble),
> the current behaviour seems odd to me.
>
> Jozef Wagner writes:
>
> > More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
> >
> > On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto 
> wrote:
> >
> >>
> >> Looking at the PHM impl, this looks like it's caused by (float 0.5) and
> >> (double 0.5) hashing differently.
> >>
> >> user=> (= (float 0.5) (double 0.5))
> >> true
> >> user=> (map hash [(float 0.5) (double 0.5)])
> >> (1056964608 1071644672)
> >>
> >> Nicola Mometto writes:
> >>
> >> > Looks like it's a bug in PersistentHashMap:
> >> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
> >> > false
> >> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
> >> > true
> >> >
> >> > Immo Heikkinen writes:
> >> >
> >> >> (= (float 0.5) (double 0.5))
> >> >> => true
> >> >> (= #{(float 0.5)} #{(double 0.5)})
> >> >> => true
> >> >> (= {:a (float 0.5)} {:a (double 0.5)})
> >> >> => true
> >> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
> >> >> => false
> >> >>
> >> >>
> >> >> Tested with both 1.6.0 and 1.7.0-alpha5.
> >>
> >> --
> >>
> >> --
> >> You 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 unsubscribe from this group and stop receiving emails from it, send
> an
> >> email to clojure+unsubscr...@googlegroups.com.
> >> For more options, visit https://groups.google.com/d/optout.
> >>
>
> --
>
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Plínio Balduino
My one cent:

But I think (and it's just my humble opinion) is in the scope of Clojure
keep its consistency, am I right?

I mean, if doubles and floats are different, and they are, I think we
should always get equality test as false. Or always as true, if they're
nominally the same value.

Regards

Plínio

On Thu, Jan 22, 2015 at 12:18 PM, Andy Fingerhut 
wrote:

> "It is out of scope for Clojure to fix this for Java types Float/Double"
>  -- comments in CLJ-1036: http://dev.clojure.org/jira/browse/CLJ-1036
>
> Andy
>
> On Thu, Jan 22, 2015 at 5:53 AM, Nicola Mometto 
> wrote:
>
>>
>> Not sure if this is intended behaviour:
>> user=> (= (float 1.6) (double 1.6))
>> false
>> user=> (= (float 1.5) (double 1.5))
>> true
>>
>> I.e. = (and ==) will return true when comparing floats with doubles IFF
>> the float's .doubleValue roundtrips to the same double it's comparing to.
>>
>> user=> (.doubleValue (float 1.6))
>> 1.60023841858
>> user=> (.doubleValue (float 1.5))
>> 1.5
>>
>> I'm not sure why floats are not handled specially in Numbers.java so
>> that hash/comparision is handled consistently with doubles (e.g. by
>> converting the floats to the fitting double via Double.parseDouble),
>> the current behaviour seems odd to me.
>>
>> Jozef Wagner writes:
>>
>> > More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
>> >
>> > On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto 
>> wrote:
>> >
>> >>
>> >> Looking at the PHM impl, this looks like it's caused by (float 0.5) and
>> >> (double 0.5) hashing differently.
>> >>
>> >> user=> (= (float 0.5) (double 0.5))
>> >> true
>> >> user=> (map hash [(float 0.5) (double 0.5)])
>> >> (1056964608 1071644672)
>> >>
>> >> Nicola Mometto writes:
>> >>
>> >> > Looks like it's a bug in PersistentHashMap:
>> >> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
>> >> > false
>> >> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
>> >> > true
>> >> >
>> >> > Immo Heikkinen writes:
>> >> >
>> >> >> (= (float 0.5) (double 0.5))
>> >> >> => true
>> >> >> (= #{(float 0.5)} #{(double 0.5)})
>> >> >> => true
>> >> >> (= {:a (float 0.5)} {:a (double 0.5)})
>> >> >> => true
>> >> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
>> >> >> => false
>> >> >>
>> >> >>
>> >> >> Tested with both 1.6.0 and 1.7.0-alpha5.
>> >>
>> >> --
>> >>
>> >> --
>> >> You 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 unsubscribe from this group and stop receiving emails from it, send
>> an
>> >> email to clojure+unsubscr...@googlegroups.com.
>> >> For more options, visit https://groups.google.com/d/optout.
>> >>
>>
>> --
>>
>> --
>> You 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 unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit h

Re: Set equality bug?

2015-01-22 Thread Andy Fingerhut
On the side of positive recommendations to avoid problems like this, here
is some advice:

+ Don't mix floats and doubles in the same Clojure program.  Given that
Clojure uses double arithmetic by default, it is much easier to use doubles
everywhere than it is to try to use floats everywhere.

+ Don't use NaN in collections.  They aren't even equal to themselves, and
that inequality propagates to any collections they are in.

+ Don't use mutable collections as elements of Clojure's immutable
collections.  They are equal to each other in straightforward equality
tests, but are not consistent in their hashes are, much as float/double
values are not.  See http://dev.clojure.org/jira/browse/CLJ-1372 for one
example.

If you keep those things out of Clojure collections, I am not aware of any
other gotchas there.

Andy

On Thu, Jan 22, 2015 at 6:44 AM, Plínio Balduino 
wrote:

> My one cent:
>
> But I think (and it's just my humble opinion) is in the scope of Clojure
> keep its consistency, am I right?
>
> I mean, if doubles and floats are different, and they are, I think we
> should always get equality test as false. Or always as true, if they're
> nominally the same value.
>
> Regards
>
> Plínio
>
> On Thu, Jan 22, 2015 at 12:18 PM, Andy Fingerhut  > wrote:
>
>> "It is out of scope for Clojure to fix this for Java types Float/Double"
>>  -- comments in CLJ-1036: http://dev.clojure.org/jira/browse/CLJ-1036
>>
>> Andy
>>
>> On Thu, Jan 22, 2015 at 5:53 AM, Nicola Mometto 
>> wrote:
>>
>>>
>>> Not sure if this is intended behaviour:
>>> user=> (= (float 1.6) (double 1.6))
>>> false
>>> user=> (= (float 1.5) (double 1.5))
>>> true
>>>
>>> I.e. = (and ==) will return true when comparing floats with doubles IFF
>>> the float's .doubleValue roundtrips to the same double it's comparing to.
>>>
>>> user=> (.doubleValue (float 1.6))
>>> 1.60023841858
>>> user=> (.doubleValue (float 1.5))
>>> 1.5
>>>
>>> I'm not sure why floats are not handled specially in Numbers.java so
>>> that hash/comparision is handled consistently with doubles (e.g. by
>>> converting the floats to the fitting double via Double.parseDouble),
>>> the current behaviour seems odd to me.
>>>
>>> Jozef Wagner writes:
>>>
>>> > More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
>>> >
>>> > On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto 
>>> wrote:
>>> >
>>> >>
>>> >> Looking at the PHM impl, this looks like it's caused by (float 0.5)
>>> and
>>> >> (double 0.5) hashing differently.
>>> >>
>>> >> user=> (= (float 0.5) (double 0.5))
>>> >> true
>>> >> user=> (map hash [(float 0.5) (double 0.5)])
>>> >> (1056964608 1071644672)
>>> >>
>>> >> Nicola Mometto writes:
>>> >>
>>> >> > Looks like it's a bug in PersistentHashMap:
>>> >> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 0.5)})
>>> >> > false
>>> >> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
>>> >> > true
>>> >> >
>>> >> > Immo Heikkinen writes:
>>> >> >
>>> >> >> (= (float 0.5) (double 0.5))
>>> >> >> => true
>>> >> >> (= #{(float 0.5)} #{(double 0.5)})
>>> >> >> => true
>>> >> >> (= {:a (float 0.5)} {:a (double 0.5)})
>>> >> >> => true
>>> >> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
>>> >> >> => false
>>> >> >>
>>> >> >>
>>> >> >> Tested with both 1.6.0 and 1.7.0-alpha5.
>>> >>
>>> >> --
>>> >>
>>> >> --
>>> >> You 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://

Re: Set equality bug?

2015-01-22 Thread Luc Préfontaine
And how to you want to proceed knowing that floats and double can escape
elsewhere in your app and create the same chaotic effect like for example,
in some interop call to some obscure library ?

The best ... consistency here seems to reflect what's occurring underneath 
instead
of giving the false impression that everything is fine.

Floats and doubles do not have the same precision/representation and thus 
comparing
for equal values without explicit casting/truncating/rounding cannot be relied 
on.
These are JVM native types. Even Java folks ask this question about equality on 
a regular 
basis and its their language of choice :)

Have a look at IEE floating point representations that will give you an idea of 
the scope
of the problem.

In the past I used to deal with up to 4 different representations on the same 
hardware.
We would never mix them, we would convert them at the edge of our app or within
very narrow boundaries.

Even business apps in Cobol had issues with this, not all hardware supported 
packed
decimal operations, relying on some floating point representation better 
handled by
hardware was common with all the conversion problems related 
(rounding/truncating
in computations, ...). We could even choose the runtime float representation to
minimize errors in computations and take the best one given the app at hand.

Avoid mixing them. That's the only safe escape.

Luc P.

> My one cent:
> 
> But I think (and it's just my humble opinion) is in the scope of Clojure
> keep its consistency, am I right?
> 
> I mean, if doubles and floats are different, and they are, I think we
> should always get equality test as false. Or always as true, if they're
> nominally the same value.
> 
> Regards
> 
> Plínio
> 
> On Thu, Jan 22, 2015 at 12:18 PM, Andy Fingerhut 
> wrote:
> 
> > "It is out of scope for Clojure to fix this for Java types Float/Double"
> >  -- comments in CLJ-1036: http://dev.clojure.org/jira/browse/CLJ-1036
> >
> > Andy
> >
> > On Thu, Jan 22, 2015 at 5:53 AM, Nicola Mometto 
> > wrote:
> >
> >>
> >> Not sure if this is intended behaviour:
> >> user=> (= (float 1.6) (double 1.6))
> >> false
> >> user=> (= (float 1.5) (double 1.5))
> >> true
> >>
> >> I.e. = (and ==) will return true when comparing floats with doubles IFF
> >> the float's .doubleValue roundtrips to the same double it's comparing to.
> >>
> >> user=> (.doubleValue (float 1.6))
> >> 1.60023841858
> >> user=> (.doubleValue (float 1.5))
> >> 1.5
> >>
> >> I'm not sure why floats are not handled specially in Numbers.java so
> >> that hash/comparision is handled consistently with doubles (e.g. by
> >> converting the floats to the fitting double via Double.parseDouble),
> >> the current behaviour seems odd to me.
> >>
> >> Jozef Wagner writes:
> >>
> >> > More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
> >> >
> >> > On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto 
> >> wrote:
> >> >
> >> >>
> >> >> Looking at the PHM impl, this looks like it's caused by (float 0.5) and
> >> >> (double 0.5) hashing differently.
> >> >>
> >> >> user=> (= (float 0.5) (double 0.5))
> >> >> true
> >> >> user=> (map hash [(float 0.5) (double 0.5)])
> >> >> (1056964608 1071644672)
> >> >>
> >> >> Nicola Mometto writes:
> >> >>
> >> >> > Looks like it's a bug in PersistentHashMap:
> >> >> > user=> (contains? (hash-map {:a (float 0.5)} 1) {:a (double 05)})
> >> >> > false
> >> >> > user=> (contains? (array-map {:a (float 0.5)} 1) {:a (double 0.5)})
> >> >> > true
> >> >> >
> >> >> > Immo Heikkinen writes:
> >> >> >
> >> >> >> (= (float 0.5) (double 0.5))
> >> >> >> => true
> >> >> >> (= #{(float 0.5)} #{(double 0.5)})
> >> >> >> => true
> >> >> >> (= {:a (float 0.5)} {:a (double 0.5)})
> >> >> >> => true
> >> >> >> (= #{{:a (float 0.5)}} #{{:a (double 0.5)}})
> >> >> >> => false
> >> >> >>
> >> >> >>
> >> >> >> Tested with both 1.6.0 and 1.7.0-alpha5.
> >> >>
> >> >> --
> >> >>
> >> >> --
> >> &

Re: Set equality bug?

2015-01-22 Thread Jozef Wagner
As seen in CLJ-1372, this issue will probably cause some strong opinions. I
think this is an example of a leaky abstraction and the current approach is
to leave it as is, as there are some serious trade-offs and are there is no
rationale or real practical reason to fix this.

Current implementation for double and float hashes uses Java's hash
algorithm, which
uses IEEE 754 bit representation of floats, that is a fast native function
[1], but is different for doubles and floats. While Murmur3 does provide
hashing for integer numbers, there is no hash function for floating point
ones.

And note that there are big decimals too...

> (hash 1.5)
1073217536
> (hash 1.5M)
466
> (hash (float 1.5))
1069547520

[1]
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/a7dd84b9557c/src/share/classes/java/lang/Double.java#l761

Jozef


On Thu, Jan 22, 2015 at 4:36 PM, Luc Préfontaine <
lprefonta...@softaddicts.ca> wrote:

> And how to you want to proceed knowing that floats and double can escape
> elsewhere in your app and create the same chaotic effect like for example,
> in some interop call to some obscure library ?
>
> The best ... consistency here seems to reflect what's occurring underneath
> instead
> of giving the false impression that everything is fine.
>
> Floats and doubles do not have the same precision/representation and thus
> comparing
> for equal values without explicit casting/truncating/rounding cannot be
> relied on.
> These are JVM native types. Even Java folks ask this question about
> equality on a regular
> basis and its their language of choice :)
>
> Have a look at IEE floating point representations that will give you an
> idea of the scope
> of the problem.
>
> In the past I used to deal with up to 4 different representations on the
> same hardware.
> We would never mix them, we would convert them at the edge of our app or
> within
> very narrow boundaries.
>
> Even business apps in Cobol had issues with this, not all hardware
> supported packed
> decimal operations, relying on some floating point representation better
> handled by
> hardware was common with all the conversion problems related
> (rounding/truncating
> in computations, ...). We could even choose the runtime float
> representation to
> minimize errors in computations and take the best one given the app at
> hand.
>
> Avoid mixing them. That's the only safe escape.
>
> Luc P.
>
> > My one cent:
> >
> > But I think (and it's just my humble opinion) is in the scope of Clojure
> > keep its consistency, am I right?
> >
> > I mean, if doubles and floats are different, and they are, I think we
> > should always get equality test as false. Or always as true, if they're
> > nominally the same value.
> >
> > Regards
> >
> > Plínio
> >
> > On Thu, Jan 22, 2015 at 12:18 PM, Andy Fingerhut <
> andy.finger...@gmail.com>
> > wrote:
> >
> > > "It is out of scope for Clojure to fix this for Java types
> Float/Double"
> > >  -- comments in CLJ-1036: http://dev.clojure.org/jira/browse/CLJ-1036
> > >
> > > Andy
> > >
> > > On Thu, Jan 22, 2015 at 5:53 AM, Nicola Mometto 
> > > wrote:
> > >
> > >>
> > >> Not sure if this is intended behaviour:
> > >> user=> (= (float 1.6) (double 1.6))
> > >> false
> > >> user=> (= (float 1.5) (double 1.5))
> > >> true
> > >>
> > >> I.e. = (and ==) will return true when comparing floats with doubles
> IFF
> > >> the float's .doubleValue roundtrips to the same double it's comparing
> to.
> > >>
> > >> user=> (.doubleValue (float 1.6))
> > >> 1.60023841858
> > >> user=> (.doubleValue (float 1.5))
> > >> 1.5
> > >>
> > >> I'm not sure why floats are not handled specially in Numbers.java so
> > >> that hash/comparision is handled consistently with doubles (e.g. by
> > >> converting the floats to the fitting double via Double.parseDouble),
> > >> the current behaviour seems odd to me.
> > >>
> > >> Jozef Wagner writes:
> > >>
> > >> > More on this behavior http://dev.clojure.org/jira/browse/CLJ-1036
> > >> >
> > >> > On Thu, Jan 22, 2015 at 2:00 PM, Nicola Mometto <
> brobro...@gmail.com>
> > >> wrote:
> > >> >
> > >> >>
> > >> >> Looking at the PHM impl, this looks like it's caused by (float
> 0.5) and
> > >> >> (double 0.5) hashing d

Re: Set equality bug?

2015-01-22 Thread Fluid Dynamics
On Thursday, January 22, 2015 at 2:12:52 PM UTC-5, Jozef Wagner wrote:
>
> As seen in CLJ-1372, this issue will probably cause some strong opinions. 
> I think this is an example of a leaky abstraction and the current approach 
> is to leave it as is, as there are some serious trade-offs and are there is 
> no rationale or real practical reason to fix this.
>
> Current implementation for double and float hashes uses Java's hash 
> algorithm, which 
> uses IEEE 754 bit representation of floats, that is a fast native 
> function [1], but is different for doubles and floats. While Murmur3 does 
> provide hashing for integer numbers, there is no hash function for floating 
> point ones.
>
> And note that there are big decimals too...
>
> > (hash 1.5)
> 1073217536
> > (hash 1.5M)
> 466
> > (hash (float 1.5))
> 1069547520
>

Things that don't have the same hash shouldn't compare equal, at least so 
long as one avoids mutable java.util collections.

If floats and doubles can't generally have the same hashes (let alone 
floats and BigDecimals) then = should return false for any comparison of 
two different of these three types (and numerical code that wants to check 
for numerical equality across types, to the extent that ever makes sense 
with FP types, should 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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Andy Fingerhut
Part of what you wish were true is already true: Using = to compare a
double to a BigDecimal always returns false in Clojure, as does comparing a
float to a BigDecimal.

It is only (= float-value double-value) that can return true in Clojure,
even though hash does not guarantee the usual hash consistency property of
"(= a b) implies (= (hash a) (hash b))".  Hence my recommendation earlier
in the thread to avoid mixing floats and doubles in the same Clojure
program.

Andy

On Thu, Jan 22, 2015 at 2:04 PM, Fluid Dynamics  wrote:

> On Thursday, January 22, 2015 at 2:12:52 PM UTC-5, Jozef Wagner wrote:
>>
>> As seen in CLJ-1372, this issue will probably cause some strong opinions.
>> I think this is an example of a leaky abstraction and the current approach
>> is to leave it as is, as there are some serious trade-offs and are there is
>> no rationale or real practical reason to fix this.
>>
>> Current implementation for double and float hashes uses Java's hash
>> algorithm, which
>> uses IEEE 754 bit representation of floats, that is a fast native
>> function [1], but is different for doubles and floats. While Murmur3 does
>> provide hashing for integer numbers, there is no hash function for floating
>> point ones.
>>
>> And note that there are big decimals too...
>>
>> > (hash 1.5)
>> 1073217536
>> > (hash 1.5M)
>> 466
>> > (hash (float 1.5))
>> 1069547520
>>
>
> Things that don't have the same hash shouldn't compare equal, at least so
> long as one avoids mutable java.util collections.
>
> If floats and doubles can't generally have the same hashes (let alone
> floats and BigDecimals) then = should return false for any comparison of
> two different of these three types (and numerical code that wants to check
> for numerical equality across types, to the extent that ever makes sense
> with FP types, should 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-22 Thread Immo Heikkinen
I actually ran into this while comparing nested data structures from two
different sources and spent a good part of my day figuring out what's
happening. While it is a good advice to avoid mixing floats and doubles, it
is inevitable that Clojure users will get bitten by this once in a while
and hours will be wasted.

It is also very disturbing to realise that "(= a b)" doesn't always imply
"(= (hash a) (hash b))" or "(= #{a} #{b})" as you would think.

2015-01-23 0:18 GMT+02:00 Andy Fingerhut :

> Part of what you wish were true is already true: Using = to compare a
> double to a BigDecimal always returns false in Clojure, as does comparing a
> float to a BigDecimal.
>
> It is only (= float-value double-value) that can return true in Clojure,
> even though hash does not guarantee the usual hash consistency property of
> "(= a b) implies (= (hash a) (hash b))".  Hence my recommendation earlier
> in the thread to avoid mixing floats and doubles in the same Clojure
> program.
>
> Andy
>
> On Thu, Jan 22, 2015 at 2:04 PM, Fluid Dynamics 
> wrote:
>
>> On Thursday, January 22, 2015 at 2:12:52 PM UTC-5, Jozef Wagner wrote:
>>>
>>> As seen in CLJ-1372, this issue will probably cause some strong
>>> opinions. I think this is an example of a leaky abstraction and the current
>>> approach is to leave it as is, as there are some serious trade-offs and are
>>> there is no rationale or real practical reason to fix this.
>>>
>>> Current implementation for double and float hashes uses Java's hash
>>> algorithm, which
>>> uses IEEE 754 bit representation of floats, that is a fast native
>>> function [1], but is different for doubles and floats. While Murmur3 does
>>> provide hashing for integer numbers, there is no hash function for floating
>>> point ones.
>>>
>>> And note that there are big decimals too...
>>>
>>> > (hash 1.5)
>>> 1073217536
>>> > (hash 1.5M)
>>> 466
>>> > (hash (float 1.5))
>>> 1069547520
>>>
>>
>> Things that don't have the same hash shouldn't compare equal, at least so
>> long as one avoids mutable java.util collections.
>>
>> If floats and doubles can't generally have the same hashes (let alone
>> floats and BigDecimals) then = should return false for any comparison of
>> two different of these three types (and numerical code that wants to check
>> for numerical equality across types, to the extent that ever makes sense
>> with FP types, should 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
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>  --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Michael Gardner
On Jan 23, 2015, at 1:33 AM, Immo Heikkinen  wrote:
> 
> I actually ran into this while comparing nested data structures from two 
> different sources and spent a good part of my day figuring out what's 
> happening. While it is a good advice to avoid mixing floats and doubles, it 
> is inevitable that Clojure users will get bitten by this once in a while and 
> hours will be wasted.
> 
> It is also very disturbing to realise that "(= a b)" doesn't always imply "(= 
> (hash a) (hash b))" or "(= #{a} #{b})" as you would think.

(inc)

This is fundamentally broken behavior. Telling people to just learn to avoid it 
is not good, IMO. If the hashes must be unequal, then = should return false.

As for backwards compatibility, note that if such a change were made to =, it 
wouldn't affect anyone who was already following Andy's advice to avoid mixing 
doubles and floats. IOW, it should only affect those who are doing something 
you're not "supposed" to do 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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Luc Prefontaine
Agree, it's broken... in java...
Has it has been broken in the past in several architectures...

I understand your frustration but this is not something new. It's been a 
problem for at least 30 years.

It is kind of a basic programming issue:

- Never compare floats with different representations.

- Never mix different representations in computations

- Convert representations as early as possible to a common format

These are the rules to follow to avoid running into trouble.

Now if you think you can overcome this persistent (ah ! ah !) problem with some 
David Copperfield trick, fine.

But that's a trick nothing else. The problem will resurface in some form in 
another. Better cope with reality...

Luc P.


> On Jan 23, 2015, at 1:33 AM, Immo Heikkinen  wrote:
> > 
> > I actually ran into this while comparing nested data structures from two 
> > different sources and spent a good part of my day figuring out what's 
> > happening. While it is a good advice to avoid mixing floats and doubles, it 
> > is inevitable that Clojure users will get bitten by this once in a while 
> > and hours will be wasted.
> > 
> > It is also very disturbing to realise that "(= a b)" doesn't always imply 
> > "(= (hash a) (hash b))" or "(= #{a} #{b})" as you would think.
> 
> (inc)
> 
> This is fundamentally broken behavior. Telling people to just learn to avoid 
> it is not good, IMO. If the hashes must be unequal, then = should return 
> false.
> 
> As for backwards compatibility, note that if such a change were made to =, it 
> wouldn't affect anyone who was already following Andy's advice to avoid 
> mixing doubles and floats. IOW, it should only affect those who are doing 
> something you're not "supposed" to do 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
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> 
--
Luc Prefontaine sent by ibisMail!

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Mark Engelberg
On Fri, Jan 23, 2015 at 1:10 AM, Luc Prefontaine <
lprefonta...@softaddicts.ca> wrote:

> Agree, it's broken... in java...
>

I think it's more frustrating in Clojure than in Java, though, because in
Java you have those big, ugly type annotations on every single variable,
input and output, so there's really no question when you're working with a
mixture of floats and doubles.  In Clojure, it's much easier for this kind
of thing to slip into your program unnoticed.  Call a couple of external
libraries that produce floats or doubles -- Clojure will happily hide the
difference from you and then you get burned.

As I frequently find myself explaining to newcomers to Clojure, one of
Clojure's biggest weaknesses is that it goes to great pains to hide type
details (floats vs doubles, boxed vs unboxed, hash sets vs array sets,
etc.) and every once in a while it really matters -- a lot -- what the
types actually are and there aren't many tools for discovering the flow of
types through your code.

So I wouldn't necessarily go blaming this on Java.

Furthermore, I'm not so sure it is broken in Java:

=> (.equals (float 2) (double 2))
false

=> (.compareTo (float 2) (double 2))
ClassCastException Cannot cast java.lang.Double to java.lang.Float
java.lang.Class.cast (Class.java:3258)

So Java doesn't appear to transparently treat floats and doubles as equal
(which is consistent with the fact that Java's hashes of floats and doubles
can be different).

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Michael Gardner
If there's a technical reason why Clojure can't return false for all = 
comparisons between floats and doubles, I'd like to hear it. Otherwise, I don't 
see how your response is relevant.

> On Jan 23, 2015, at 3:10 AM, Luc Prefontaine  
> wrote:
> 
> Agree, it's broken... in java...
> Has it has been broken in the past in several architectures...
> 
> I understand your frustration but this is not something new. It's been a 
> problem for at least 30 years.
> 
> It is kind of a basic programming issue:
> 
> - Never compare floats with different representations.
> 
> - Never mix different representations in computations
> 
> - Convert representations as early as possible to a common format
> 
> These are the rules to follow to avoid running into trouble.
> 
> Now if you think you can overcome this persistent (ah ! ah !) problem with 
> some David Copperfield trick, fine.
> 
> But that's a trick nothing else. The problem will resurface in some form in 
> another. Better cope with reality...
> 
> Luc P.
> 
> 
>> On Jan 23, 2015, at 1:33 AM, Immo Heikkinen  wrote:
>>> 
>>> I actually ran into this while comparing nested data structures from two 
>>> different sources and spent a good part of my day figuring out what's 
>>> happening. While it is a good advice to avoid mixing floats and doubles, it 
>>> is inevitable that Clojure users will get bitten by this once in a while 
>>> and hours will be wasted.
>>> 
>>> It is also very disturbing to realise that "(= a b)" doesn't always imply 
>>> "(= (hash a) (hash b))" or "(= #{a} #{b})" as you would think.
>> 
>> (inc)
>> 
>> This is fundamentally broken behavior. Telling people to just learn to avoid 
>> it is not good, IMO. If the hashes must be unequal, then = should return 
>> false.
>> 
>> As for backwards compatibility, note that if such a change were made to =, 
>> it wouldn't affect anyone who was already following Andy's advice to avoid 
>> mixing doubles and floats. IOW, it should only affect those who are doing 
>> something you're not "supposed" to do 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
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>> 
> --
> Luc Prefontaine sent by ibisMail!
> 
> -- 
> You 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 unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Luc Préfontaine
Well if it breaks elsewhere than in your code because you mix representations 
and leak
them to some library in Java that you do not control I see my comments as 
absolutely relevant.

It's not technical, it's failsafe. But that might not be of any interest to 
your problem scope.
However it does interest me. Hiding odd behaviors when consistency can be 
guaranteed,
I have no problem with that. Here to me its very clear that there is no 
failsafe approach.

Clojure is hosted on a platform that does not provide the kind if consistency 
you want.
Anything you can build to hide this in Clojure is like building a tower on 
moving sand.

Mark has a valid point about type safety which helps a bit in Java but you can 
dig
with google and you will find people that got bitten in Java by float/double 
mixing
even with type 'safety'. So long for type systems, it cannot help you with 
values that
'look' the same superficially but are internally different.

For some values, floats and doubles are equal because their internal 
representations are the 
same. For many other values it's not working.

I suggest some readings;

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
http://floating-point-gui.de/errors/comparison/

Then maybe we can bring this thread to an end.


> If there's a technical reason why Clojure can't return false for all = 
> comparisons between floats and doubles, I'd like to hear it. Otherwise, I 
> don't see how your response is relevant.
> 
> > On Jan 23, 2015, at 3:10 AM, Luc Prefontaine  
> > wrote:
> > 
> > Agree, it's broken... in java...
> > Has it has been broken in the past in several architectures...
> > 
> > I understand your frustration but this is not something new. It's been a 
> > problem for at least 30 years.
> > 
> > It is kind of a basic programming issue:
> > 
> > - Never compare floats with different representations.
> > 
> > - Never mix different representations in computations
> > 
> > - Convert representations as early as possible to a common format
> > 
> > These are the rules to follow to avoid running into trouble.
> > 
> > Now if you think you can overcome this persistent (ah ! ah !) problem with 
> > some David Copperfield trick, fine.
> > 
> > But that's a trick nothing else. The problem will resurface in some form in 
> > another. Better cope with reality...
> > 
> > Luc P.
> > 
> > 
> >> On Jan 23, 2015, at 1:33 AM, Immo Heikkinen  
> >> wrote:
> >>> 
> >>> I actually ran into this while comparing nested data structures from two 
> >>> different sources and spent a good part of my day figuring out what's 
> >>> happening. While it is a good advice to avoid mixing floats and doubles, 
> >>> it is inevitable that Clojure users will get bitten by this once in a 
> >>> while and hours will be wasted.
> >>> 
> >>> It is also very disturbing to realise that "(= a b)" doesn't always imply 
> >>> "(= (hash a) (hash b))" or "(= #{a} #{b})" as you would think.
> >> 
> >> (inc)
> >> 
> >> This is fundamentally broken behavior. Telling people to just learn to 
> >> avoid it is not good, IMO. If the hashes must be unequal, then = should 
> >> return false.
> >> 
> >> As for backwards compatibility, note that if such a change were made to =, 
> >> it wouldn't affect anyone who was already following Andy's advice to avoid 
> >> mixing doubles and floats. IOW, it should only affect those who are doing 
> >> something you're not "supposed" to do 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
> >> --- 
> >> You received this message because you are subscribed to the Google Groups 
> >> "Clojure" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an 
> >> email to clojure+unsubscr...@googlegroups.com.
> >> For more options, visit https://groups.google.com/d/optout.
> >> 
> > --
> > Luc Prefontaine sent by ibisMail!
> > 
> > -- 
> > You 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 unsubscribe from this group and stop receiving emails from it, send an 
> > email to clojure+unsubscr...@googlegroups.com.
> > For more options, vi

Re: Set equality bug?

2015-01-23 Thread Luc Prefontaine

public class TestClass {
public static void equality () {
double dd = 3.5;  
float ff = 3.5f;
System.out.println(String.format("dd vs ff == %b", dd==ff)); 

double dd2 = 3.2;
float ff2 = 3.2f;
System.out.println(String.format("dd2 vs ff2 == %b", dd2==ff2));
}
}

REPL output:
=> (idem.core.TestClass/equality)
nil

Console output:

nREPL server started on port 38698 on host 127.0.0.1 - nrepl://127.0.0.1:38698
dd vs ff == true
dd2 vs ff2 == false

We are talking about values as primitive types, not boxed values as objects:

The equals method for class Object implements the most discriminating possible 
equivalence relation on objects; that is, for any non-null reference values x 
and y, this method returns true if and only if x and y refer to the same object 
(x == y has the value true). 

=> (class (float 3.2))
java.lang.Float
=> (class (double 3.2))
java.lang.Double

Oupse... :)

Luc P.


On Fri, 23 Jan 2015 01:31:31 -0800
Mark Engelberg  wrote:

> On Fri, Jan 23, 2015 at 1:10 AM, Luc Prefontaine <
> lprefonta...@softaddicts.ca> wrote:
> 
> > Agree, it's broken... in java...
> >
> 
> I think it's more frustrating in Clojure than in Java, though,
> because in Java you have those big, ugly type annotations on every
> single variable, input and output, so there's really no question when
> you're working with a mixture of floats and doubles.  In Clojure,
> it's much easier for this kind of thing to slip into your program
> unnoticed.  Call a couple of external libraries that produce floats
> or doubles -- Clojure will happily hide the difference from you and
> then you get burned.
> 
> As I frequently find myself explaining to newcomers to Clojure, one of
> Clojure's biggest weaknesses is that it goes to great pains to hide
> type details (floats vs doubles, boxed vs unboxed, hash sets vs array
> sets, etc.) and every once in a while it really matters -- a lot --
> what the types actually are and there aren't many tools for
> discovering the flow of types through your code.
> 
> So I wouldn't necessarily go blaming this on Java.
> 
> Furthermore, I'm not so sure it is broken in Java:
> 
> => (.equals (float 2) (double 2))
> false
> 
> => (.compareTo (float 2) (double 2))
> ClassCastException Cannot cast java.lang.Double to java.lang.Float
> java.lang.Class.cast (Class.java:3258)
> 
> So Java doesn't appear to transparently treat floats and doubles as
> equal (which is consistent with the fact that Java's hashes of floats
> and doubles can be different).
> 



-- 
Luc Préfontaine

SoftAddicts inc.
Québec, Canada
Mobil: (514) 993-0320
Fax: (514) 800-2017

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Michael Gardner
I'm sure we are all aware of the various issues with floating point math 
(particularly equality comparisons); however none of that is relevant to this 
discussion. The only issue here is an inconsistency between hashing and 
equality testing in Clojure.

My claim is that the property "any two objects can be equal only if their 
hashes are equal" is a fundamental one that should not be violated under any 
circumstances. Whether that means modifying Clojure's hashing algorithm or its 
implementation of = doesn't much matter to me, so long as that property is 
maintained.

> On Jan 23, 2015, at 5:06 AM, Luc Préfontaine  
> wrote:
> 
> Well if it breaks elsewhere than in your code because you mix representations 
> and leak
> them to some library in Java that you do not control I see my comments as 
> absolutely relevant.
> 
> It's not technical, it's failsafe. But that might not be of any interest to 
> your problem scope.
> However it does interest me. Hiding odd behaviors when consistency can be 
> guaranteed,
> I have no problem with that. Here to me its very clear that there is no 
> failsafe approach.
> 
> Clojure is hosted on a platform that does not provide the kind if consistency 
> you want.
> Anything you can build to hide this in Clojure is like building a tower on 
> moving sand.
> 
> Mark has a valid point about type safety which helps a bit in Java but you 
> can dig
> with google and you will find people that got bitten in Java by float/double 
> mixing
> even with type 'safety'. So long for type systems, it cannot help you with 
> values that
> 'look' the same superficially but are internally different.
> 
> For some values, floats and doubles are equal because their internal 
> representations are the 
> same. For many other values it's not working.
> 
> I suggest some readings;
> 
> http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
> http://floating-point-gui.de/errors/comparison/
> 
> Then maybe we can bring this thread to an end.
> 
> 
>> If there's a technical reason why Clojure can't return false for all = 
>> comparisons between floats and doubles, I'd like to hear it. Otherwise, I 
>> don't see how your response is relevant.
>> 
>>> On Jan 23, 2015, at 3:10 AM, Luc Prefontaine  
>>> wrote:
>>> 
>>> Agree, it's broken... in java...
>>> Has it has been broken in the past in several architectures...
>>> 
>>> I understand your frustration but this is not something new. It's been a 
>>> problem for at least 30 years.
>>> 
>>> It is kind of a basic programming issue:
>>> 
>>> - Never compare floats with different representations.
>>> 
>>> - Never mix different representations in computations
>>> 
>>> - Convert representations as early as possible to a common format
>>> 
>>> These are the rules to follow to avoid running into trouble.
>>> 
>>> Now if you think you can overcome this persistent (ah ! ah !) problem with 
>>> some David Copperfield trick, fine.
>>> 
>>> But that's a trick nothing else. The problem will resurface in some form in 
>>> another. Better cope with reality...
>>> 
>>> Luc P.
>>> 
>>> 
>>>> On Jan 23, 2015, at 1:33 AM, Immo Heikkinen  
>>>> wrote:
>>>>> 
>>>>> I actually ran into this while comparing nested data structures from two 
>>>>> different sources and spent a good part of my day figuring out what's 
>>>>> happening. While it is a good advice to avoid mixing floats and doubles, 
>>>>> it is inevitable that Clojure users will get bitten by this once in a 
>>>>> while and hours will be wasted.
>>>>> 
>>>>> It is also very disturbing to realise that "(= a b)" doesn't always imply 
>>>>> "(= (hash a) (hash b))" or "(= #{a} #{b})" as you would think.
>>>> 
>>>> (inc)
>>>> 
>>>> This is fundamentally broken behavior. Telling people to just learn to 
>>>> avoid it is not good, IMO. If the hashes must be unequal, then = should 
>>>> return false.
>>>> 
>>>> As for backwards compatibility, note that if such a change were made to =, 
>>>> it wouldn't affect anyone who was already following Andy's advice to avoid 
>>>> mixing doubles and floats. IOW, it should only affect those who are doing 
>>>> something you're not "supposed&

Re: Set equality bug?

2015-01-23 Thread Andy Fingerhut
Michael:

You can try creating a JIRA ticket suggesting that Clojure's = should
return false when comparing floats and doubles to each other.  I have no
idea if it would go anywhere, but alternative (2) trying to get hashes to
be equal between = float/doubles has been suggested and declined.  Without
some new convincing argument in favor of (2), it seems unlikely to change.

Another alternative might be an option to throw an exception if any floats
creep into Clojure territory from Java, if that boundary line is even
drawable.

Andy

On Fri, Jan 23, 2015 at 4:45 AM, Michael Gardner 
wrote:

> I'm sure we are all aware of the various issues with floating point math
> (particularly equality comparisons); however none of that is relevant to
> this discussion. The only issue here is an inconsistency between hashing
> and equality testing in Clojure.
>
> My claim is that the property "any two objects can be equal only if their
> hashes are equal" is a fundamental one that should not be violated under
> any circumstances. Whether that means modifying Clojure's hashing algorithm
> or its implementation of = doesn't much matter to me, so long as that
> property is maintained.
>
> > On Jan 23, 2015, at 5:06 AM, Luc Préfontaine <
> lprefonta...@softaddicts.ca> wrote:
> >
> > Well if it breaks elsewhere than in your code because you mix
> representations and leak
> > them to some library in Java that you do not control I see my comments
> as absolutely relevant.
> >
> > It's not technical, it's failsafe. But that might not be of any interest
> to your problem scope.
> > However it does interest me. Hiding odd behaviors when consistency can
> be guaranteed,
> > I have no problem with that. Here to me its very clear that there is no
> failsafe approach.
> >
> > Clojure is hosted on a platform that does not provide the kind if
> consistency you want.
> > Anything you can build to hide this in Clojure is like building a tower
> on moving sand.
> >
> > Mark has a valid point about type safety which helps a bit in Java but
> you can dig
> > with google and you will find people that got bitten in Java by
> float/double mixing
> > even with type 'safety'. So long for type systems, it cannot help you
> with values that
> > 'look' the same superficially but are internally different.
> >
> > For some values, floats and doubles are equal because their internal
> representations are the
> > same. For many other values it's not working.
> >
> > I suggest some readings;
> >
> > http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
> > http://floating-point-gui.de/errors/comparison/
> >
> > Then maybe we can bring this thread to an end.
> >
> >
> >> If there's a technical reason why Clojure can't return false for all =
> comparisons between floats and doubles, I'd like to hear it. Otherwise, I
> don't see how your response is relevant.
> >>
> >>> On Jan 23, 2015, at 3:10 AM, Luc Prefontaine <
> lprefonta...@softaddicts.ca> wrote:
> >>>
> >>> Agree, it's broken... in java...
> >>> Has it has been broken in the past in several architectures...
> >>>
> >>> I understand your frustration but this is not something new. It's been
> a problem for at least 30 years.
> >>>
> >>> It is kind of a basic programming issue:
> >>>
> >>> - Never compare floats with different representations.
> >>>
> >>> - Never mix different representations in computations
> >>>
> >>> - Convert representations as early as possible to a common format
> >>>
> >>> These are the rules to follow to avoid running into trouble.
> >>>
> >>> Now if you think you can overcome this persistent (ah ! ah !) problem
> with some David Copperfield trick, fine.
> >>>
> >>> But that's a trick nothing else. The problem will resurface in some
> form in another. Better cope with reality...
> >>>
> >>> Luc P.
> >>>
> >>>
> >>>> On Jan 23, 2015, at 1:33 AM, Immo Heikkinen 
> wrote:
> >>>>>
> >>>>> I actually ran into this while comparing nested data structures from
> two different sources and spent a good part of my day figuring out what's
> happening. While it is a good advice to avoid mixing floats and doubles, it
> is inevitable that Clojure users will get bitten by this once in a while
> and hours will be wasted.
> >>>>>
> &

Re: Set equality bug?

2015-01-23 Thread Michael Gardner
On Jan 23, 2015, at 8:23 AM, Andy Fingerhut  wrote:
> You can try creating a JIRA ticket suggesting that Clojure's = should return 
> false when comparing floats and doubles to each other.

CLJ-1649, for anyone interested.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Andy Fingerhut
Not sure which properties you prefer to be true in programming languages
you use.  Hash consistency is certainly nice, but if Clojure were changed
such that (= float-val double-val) were always false, and no other changes
were made, it would lead to this situation:

user=> (<= (float 1.5) (double 1.5))
true
user=> (>= (float 1.5) (double 1.5))
true
user=> (= (float 1.5) (double 1.5))
false

That certainly flies in the face of what most people learned in math class.

Andy

On Fri, Jan 23, 2015 at 9:29 AM, Michael Gardner 
wrote:

> On Jan 23, 2015, at 8:23 AM, Andy Fingerhut 
> wrote:
> > You can try creating a JIRA ticket suggesting that Clojure's = should
> return false when comparing floats and doubles to each other.
>
> CLJ-1649, for anyone interested.
>
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Michael Gardner
On Jan 23, 2015, at 11:51 AM, Andy Fingerhut  wrote:
> Hash consistency is certainly nice, but if Clojure were changed such that (= 
> float-val double-val) were always false, and no other changes were made, it 
> would lead to this situation:
> 
> user=> (<= (float 1.5) (double 1.5))
> true
> user=> (>= (float 1.5) (double 1.5))
> true
> user=> (= (float 1.5) (double 1.5))
> false

I'd argue you should be using == if you care about that particular property. 
And note that this can already happen with BigDecimals:

user=> (>= 10M 10)
true
user=> (<= 10M 10)
true
user=> (= 10M 10)
false

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Mark Engelberg
If the underlying argument is that it is horribly dangerous to mix floats
and doubles in your code, then maybe (<= (float 1.5) (double 1.5)) should
have the semantics of (.compareTo (float 1.5) (double 1.5)), i.e., throw an
error.

I'm not certain that's a good idea for Clojure, but it does seem like the
logical outcome of this line of thinking.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Luc Prefontaine
Danger vs flexibility.

< or > are safe. Should they throw an exception then ?

Compiler in some older typed languages would warn you about testing equality 
between two float numbers irrelevant of their types but would be silent about 
other operators.

Testing equality with floats is seldom used in the context of heavy 
computations. Testing against a range is often preferred.

Money related apps use specific types to deal with rounding/truncating.
This is why packed decimal was used  intensively. You would always end up with 
two decimals. W/o having to care for the intermediate computation steps too 
much.

Danger comes from ignorance.

What you with it afterward is another story :)

I would find it odd to see some operators throw such errors in a typeless 
language.

> If the underlying argument is that it is horribly dangerous to mix floats
> and doubles in your code, then maybe (<= (float 1.5) (double 1.5)) should
> have the semantics of (.compareTo (float 1.5) (double 1.5)), i.e., throw an
> error.
> 
> I'm not certain that's a good idea for Clojure, but it does seem like the
> logical outcome of this line of thinking.
> 
> -- 
> You 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 unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> 
--
Luc Prefontaine sent by ibisMail!

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Fluid Dynamics
On Friday, January 23, 2015 at 1:27:18 PM UTC-5, Luc wrote:
>
> Danger vs flexibility. 
>
> < or > are safe. Should they throw an exception then ? 
>
> Compiler in some older typed languages would warn you about testing 
> equality between two float numbers irrelevant of their types but would be 
> silent about other operators. 
>
> Testing equality with floats is seldom used in the context of heavy 
> computations. Testing against a range is often preferred. 
>

Often, but there can be exceptions. When floats appear as part of objects 
put in a set or used as map keys is one of them.

Not long ago I had something doing numeric work where calculations produced 
double values and certain runs of inputs would produce identical output, 
down to the last decimal place. Detecting such runs was as simple as using 
a map with double keys and checking whether it already had an entry for a 
value, then dispatching some other code based on the value found, as inputs 
that produced one value needed one sort of additional processing, and 
another value another sort.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Fluid Dynamics
And this is not a typeless language, it is a strongly dynamically typed 
language.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Set equality bug?

2015-01-23 Thread Luc Prefontaine
Obviously...

user=> (= (byte 1) (short 1) (long 1) 1)
true
user=> 

http://clojure.org/rationale

Language as platform vs. language + platform
- Old way - each language defines its own runtime
GC, bytecode, type system, libraries etc
- New way (JVM, .Net)
- Common runtime independent of language

Clojure 'type system' embraces the platform it runs on with the exception
of its own persistent data structures.

It's not the other way around.


On Fri, 23 Jan 2015 14:23:34 -0800 (PST)
Fluid Dynamics  wrote:

> And this is not a typeless language, it is a strongly dynamically
> typed language.
> 



-- 
Luc Préfontaine

SoftAddicts inc.
Québec, Canada
Mobil: (514) 993-0320
Fax: (514) 800-2017

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Keyword equality check

2014-02-12 Thread Jozef Wagner
Interning table uses keyword's symbol as a key, and the symbols are
compared by value. See
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L37


On Wed, Feb 12, 2014 at 5:23 PM, Arkadiusz Komarzewski <
akomarzew...@gmail.com> wrote:

> Hi,
>
> I wonder how is equality of keywords implemented in Clojure?
>
> I have this piece of Java code executed in one classloader:
> Keyword a = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
>
> Then, when I pass it to another part of my application (which uses another
> classloader) and do this:
> Keyword b = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
> assert a == b;
>
> Assertion passes.
> Why does it work? If I'm correct, keywords are interned, but since they
> were created in separate classloaders shouldn't that assert fail?
>
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Keyword equality check

2014-02-12 Thread Herwig Hochleitner
I'm willing to bet that both classloaders have the same clojure runtime in
a common base classloader.
i.e. that cl1.loadClass("clojure.lang.RT") ==
cl2.loadClass("clojure.lang.RT");

If the two clojure runtimes were distinct, the assert would indeed fail.
Also .equals return false and this assignment would fail: Keyword kw =
getKwFromDifferentClassloader();
This would work: Object kw = getKwFromDifferentClassloader();

See here:
http://stackoverflow.com/questions/5375349/class-instance-obtained-through-multiple-class-loader

For reference: This is a printout of the return value of nrepl/start-server
in a completely separated classloader, save for bootstrap classes in the
java library (an architecture that I use for my services)

{# #,
 # 4003,
 # #,
 # #,
 # nil,
 # #,
 # #}

Notice how the printer prints out the {} correctly, because it dispatches
on java.util.Map (a common base class from the bootstrap classloader), but
fails to recognize the Keywords of a different clojure runtime.
>From experiments, I can assure you that (not= :port #)
Similarly, assoc on this map would fail, because it's only recognized as a
j.u.Map, but not as a c.l.PersistentMap.

cheers


2014-02-12 17:45 GMT+01:00 Jozef Wagner :

> Interning table uses keyword's symbol as a key, and the symbols are
> compared by value. See
> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L37
>
>
> On Wed, Feb 12, 2014 at 5:23 PM, Arkadiusz Komarzewski <
> akomarzew...@gmail.com> wrote:
>
>> Hi,
>>
>> I wonder how is equality of keywords implemented in Clojure?
>>
>> I have this piece of Java code executed in one classloader:
>> Keyword a = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
>>
>> Then, when I pass it to another part of my application (which uses
>> another classloader) and do this:
>> Keyword b = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
>> assert a == b;
>>
>> Assertion passes.
>> Why does it work? If I'm correct, keywords are interned, but since they
>> were created in separate classloaders shouldn't that assert fail?
>>
>> --
>> You 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 unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/groups/opt_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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Keyword equality check

2014-02-12 Thread Alex Miller
I think it's a little more subtle than that.  Symbols are composed of a 
String name and a String namespace. When symbols are created they intern 
each of those Strings. Interned Strings are comparable by identity across 
the JVM. Symbol equals() compares name and namespace. Keyword extends from 
Symbol and calls into the Symbol interning and inherits the equals() 
implementation. 

As Jozef mentions, the Keyword intern table is held in a static map in 
Keyword and that would not be shared if you had multiple Clojure 
classloaders. However, I think the Keyword intern table is largely to avoid 
creating multiple instances of the same Keyword (as well as safely cleaning 
them up if no one is using them anymore). This is all irrelevant for the 
equality comparison in the original post.


On Wednesday, February 12, 2014 10:45:38 AM UTC-6, Jozef Wagner wrote:
>
> Interning table uses keyword's symbol as a key, and the symbols are 
> compared by value. See 
> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L37
>
>
> On Wed, Feb 12, 2014 at 5:23 PM, Arkadiusz Komarzewski <
> akomar...@gmail.com > wrote:
>
>> Hi,
>>
>> I wonder how is equality of keywords implemented in Clojure?
>>
>> I have this piece of Java code executed in one classloader:
>> Keyword a = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
>>
>> Then, when I pass it to another part of my application (which uses 
>> another classloader) and do this:
>> Keyword b = (Keyword) RT.var("clojure.core", "keyword").invoke("keyword");
>> assert a == b;
>>
>> Assertion passes.
>> Why does it work? If I'm correct, keywords are interned, but since they 
>> were created in separate classloaders shouldn't that assert fail?
>>  
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Keyword equality check

2014-02-12 Thread Alex Miller
Reading a little more closely, that's an identity comparison in Java, not 
an equals comparison in Clojure (who uses Java anyways? :). So I would 
retract my last statement. The question is really whether the two 
classloaders are deferring the load of the common class to a parent 
classloader that loads the same Keyword class. You can ask the Keyword 
classes you have for their classloader and then look through the parents to 
investigate that question.



On Wednesday, February 12, 2014 5:32:07 PM UTC-6, Alex Miller wrote:
>
> I think it's a little more subtle than that.  Symbols are composed of a 
> String name and a String namespace. When symbols are created they intern 
> each of those Strings. Interned Strings are comparable by identity across 
> the JVM. Symbol equals() compares name and namespace. Keyword extends from 
> Symbol and calls into the Symbol interning and inherits the equals() 
> implementation. 
>
> As Jozef mentions, the Keyword intern table is held in a static map in 
> Keyword and that would not be shared if you had multiple Clojure 
> classloaders. However, I think the Keyword intern table is largely to avoid 
> creating multiple instances of the same Keyword (as well as safely cleaning 
> them up if no one is using them anymore). This is all irrelevant for the 
> equality comparison in the original post.
>
>
> On Wednesday, February 12, 2014 10:45:38 AM UTC-6, Jozef Wagner wrote:
>>
>> Interning table uses keyword's symbol as a key, and the symbols are 
>> compared by value. See 
>> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L37
>>
>>
>> On Wed, Feb 12, 2014 at 5:23 PM, Arkadiusz Komarzewski <
>> akomar...@gmail.com> wrote:
>>
>>> Hi,
>>>
>>> I wonder how is equality of keywords implemented in Clojure?
>>>
>>> I have this piece of Java code executed in one classloader:
>>> Keyword a = (Keyword) RT.var("clojure.core", 
>>> "keyword").invoke("keyword");
>>>
>>> Then, when I pass it to another part of my application (which uses 
>>> another classloader) and do this:
>>> Keyword b = (Keyword) RT.var("clojure.core", 
>>> "keyword").invoke("keyword");
>>> assert a == b;
>>>
>>> Assertion passes.
>>> Why does it work? If I'm correct, keywords are interned, but since they 
>>> were created in separate classloaders shouldn't that assert fail?
>>>  
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Keyword equality check

2014-02-13 Thread Arkadiusz Komarzewski
Guys, thank you all for input.

I found that both keywords were (as you expected) loaded by same 
classloader (same parent was used in both). After fixing that the assert 
indeed fails.

Cheers!

On Thursday, 13 February 2014 00:41:12 UTC+1, Alex Miller wrote:
>
> Reading a little more closely, that's an identity comparison in Java, not 
> an equals comparison in Clojure (who uses Java anyways? :). So I would 
> retract my last statement. The question is really whether the two 
> classloaders are deferring the load of the common class to a parent 
> classloader that loads the same Keyword class. You can ask the Keyword 
> classes you have for their classloader and then look through the parents to 
> investigate that question.
>
>
>
> On Wednesday, February 12, 2014 5:32:07 PM UTC-6, Alex Miller wrote:
>>
>> I think it's a little more subtle than that.  Symbols are composed of a 
>> String name and a String namespace. When symbols are created they intern 
>> each of those Strings. Interned Strings are comparable by identity across 
>> the JVM. Symbol equals() compares name and namespace. Keyword extends from 
>> Symbol and calls into the Symbol interning and inherits the equals() 
>> implementation. 
>>
>> As Jozef mentions, the Keyword intern table is held in a static map in 
>> Keyword and that would not be shared if you had multiple Clojure 
>> classloaders. However, I think the Keyword intern table is largely to avoid 
>> creating multiple instances of the same Keyword (as well as safely cleaning 
>> them up if no one is using them anymore). This is all irrelevant for the 
>> equality comparison in the original post.
>>
>>
>> On Wednesday, February 12, 2014 10:45:38 AM UTC-6, Jozef Wagner wrote:
>>>
>>> Interning table uses keyword's symbol as a key, and the symbols are 
>>> compared by value. See 
>>> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L37
>>>
>>>
>>> On Wed, Feb 12, 2014 at 5:23 PM, Arkadiusz Komarzewski <
>>> akomar...@gmail.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> I wonder how is equality of keywords implemented in Clojure?
>>>>
>>>> I have this piece of Java code executed in one classloader:
>>>> Keyword a = (Keyword) RT.var("clojure.core", 
>>>> "keyword").invoke("keyword");
>>>>
>>>> Then, when I pass it to another part of my application (which uses 
>>>> another classloader) and do this:
>>>> Keyword b = (Keyword) RT.var("clojure.core", 
>>>> "keyword").invoke("keyword");
>>>> assert a == b;
>>>>
>>>> Assertion passes.
>>>> Why does it work? If I'm correct, keywords are interned, but since they 
>>>> were created in separate classloaders shouldn't that assert fail?
>>>>  
>>>> -- 
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>> To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to clojure+u...@googlegroups.com.
>>>> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Opinions on Equality Semantics

2013-04-08 Thread JvJ
This is just an idle curiosity up for discussion, but in Clojure, if (= a 
b) is true, then given some function f, it is not necessarily true that (= 
(f a) (f b))

For instance:

(defn check-eq
[f a b]
[(= a b)
(= (f a) (f b))])

(check-eq #(conj % 1) '(1 2 3) [1 2 3])
[true false]

Even though the behaviour of lists and vectors differs under specific 
functions, they still count as equal, but this statement "If a = b, then (f 
a) = (f b)" seems like it would be some sort of rule or axiom about 
functional programming.  What's the FP purists' view on 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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




equality and struct inheritance

2008-10-07 Thread Brian Doyle
I'm attempting to learn Clojure with a long history of OO and have some
questions.I've created a defstruct for a place type object like:

(defstruct place :id :name :street :city :state :zip)

I want to write a function that would take a list of places and remove
the duplicates.   Duplicates are defined by places having the same :id.
I created a 'place' namespace and attempted to create a function
called '=' that would only use the :id to compare two places, however,
I was not about to create such a function name.   Is there a preferred
function name for equality in this case?

Coming from an OO background and wanting a geocoded-place
struc is there a way to "inherit" from the place struct?   Something
like take all of the existing keys from the place struct and also add
:latitude & :longitude?

Thanks.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Eval destroys equality

2011-05-05 Thread Jonathan Fischer Friberg
= uses the clojure.lang.Util/equiv to compare two "things". The source of
this function is: [1]

static public boolean equiv(Object k1, Object k2){
if(k1 == k2)
return true;
if(k1 != null)
{
if(k1 instanceof Number && k2 instanceof Number)
return Numbers.equiv(k1, k2);
else if(k1 instanceof IPersistentCollection && k2 instanceof
IPersistentCollection)
return ((IPersistentCollection)k1).equiv(k2);
return k1.equals(k2);
}
return false;
}


Which says:
if k1 and k2 is the same instance (has the same id), return true
if k1 and k2 are numbers, compare them as numbers
if k1 and k2 are collections, compare them as collections
otherwise, use the function "equals" of the k1 object.

The equals function defines "intelligent" (proper) comparison of two
objects, and is defined by the programmer. If the equals function isn't
defined, it behaves like == [2]
The == function returns true if the "things" are of the same instance.

I think functions in clojure are defined in [3], but I'm not entirely sure.
As you can see, equals isn't implemented, and thus = will only compare
instance (id), as you have noticed.

Jonathan

[1] 
https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Util.java

[2] http://leepoint.net/notes-java/data/expressions/22compareobjects.html
[3]
https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/AFn.java

On Thu, May 5, 2011 at 3:04 PM, Dominikus 
wrote:
>
> My observation is best distilled with the following definition of a
> function in Clojure 1.2:
>
> user=> (defn id [x] (list id x))
> #'user/id
>
> Interstingly, (id 7) and (eval (id 7)) result in different instances
> of function id as the number after the '@' char unveils:
>
> user=> (id 7)
> (# 7)
> user=> (eval (id 7))
> (# 7)
>
> Consequently, the following comparison leads to false:
>
> user=> (= (id 7) (eval (id 7)))
> false
>
> Why is the instance relevant to '='? What is the precise semantics of
> two values being equal in Clojure?
>
> Dominikus
>
> (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
> restrictive 'equal?' does not and returns #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

-- 
You 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: Eval destroys equality

2011-05-05 Thread Armando Blancas
In 1.3 the function will (eval) to itself:

Clojure 1.3.0-alpha6
user=> (defn id [x] (list id x))
#'user/id
user=> (id 7)
(# 7)
user=> (eval (id 7))
(# 7)
user=> (= (id 7) (eval (id 7)))
true

On May 5, 6:04 am, Dominikus  wrote:
> My observation is best distilled with the following definition of a
> function in Clojure 1.2:
>
> user=> (defn id [x] (list id x))
> #'user/id
>
> Interstingly, (id 7) and (eval (id 7)) result in different instances
> of function id as the number after the '@' char unveils:
>
> user=> (id 7)
> (# 7)
> user=> (eval (id 7))
> (# 7)
>
> Consequently, the following comparison leads to false:
>
> user=> (= (id 7) (eval (id 7)))
> false
>
> Why is the instance relevant to '='? What is the precise semantics of
> two values being equal in Clojure?
>
> Dominikus
>
> (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
> restrictive 'equal?' does not and returns #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: Eval destroys equality

2011-05-05 Thread Dominikus Herzberg
Thanks a lot, Armando. Looks like I should switch to Clojure 1.3 asap.

Cheers,

Dominikus

2011/5/5 Armando Blancas :
> In 1.3 the function will (eval) to itself:
>
> Clojure 1.3.0-alpha6
> user=> (defn id [x] (list id x))
> #'user/id
> user=> (id 7)
> (# 7)
> user=> (eval (id 7))
> (# 7)
> user=> (= (id 7) (eval (id 7)))
> true
>
> On May 5, 6:04 am, Dominikus  wrote:
>> My observation is best distilled with the following definition of a
>> function in Clojure 1.2:
>>
>> user=> (defn id [x] (list id x))
>> #'user/id
>>
>> Interstingly, (id 7) and (eval (id 7)) result in different instances
>> of function id as the number after the '@' char unveils:
>>
>> user=> (id 7)
>> (# 7)
>> user=> (eval (id 7))
>> (# 7)
>>
>> Consequently, the following comparison leads to false:
>>
>> user=> (= (id 7) (eval (id 7)))
>> false
>>
>> Why is the instance relevant to '='? What is the precise semantics of
>> two values being equal in Clojure?
>>
>> Dominikus
>>
>> (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
>> restrictive 'equal?' does not and returns #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

-- 
You 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: Eval destroys equality

2011-05-05 Thread Dominikus
Thanks for the pointers to the implementation, Jonathan!

Unfortunately, I couldnt' find out yet, which part of the source code
in Clojure 1.3 is responsible for fixing the misbehavior in 1.2. The
parts you point to haven't changed in 1.3.

Cheers,

Dominikus

On May 5, 4:27 pm, Jonathan Fischer Friberg 
wrote:
> = uses the clojure.lang.Util/equiv to compare two "things". The source of
> this function is: [1]
>
> static public boolean equiv(Object k1, Object k2){
>         if(k1 == k2)
>                 return true;
>         if(k1 != null)
>                 {
>                 if(k1 instanceof Number && k2 instanceof Number)
>                         return Numbers.equiv(k1, k2);
>                 else if(k1 instanceof IPersistentCollection && k2 instanceof
> IPersistentCollection)
>                         return ((IPersistentCollection)k1).equiv(k2);
>                 return k1.equals(k2);
>                 }
>         return false;
>
> }
>
> Which says:
> if k1 and k2 is the same instance (has the same id), return true
> if k1 and k2 are numbers, compare them as numbers
> if k1 and k2 are collections, compare them as collections
> otherwise, use the function "equals" of the k1 object.
>
> The equals function defines "intelligent" (proper) comparison of two
> objects, and is defined by the programmer. If the equals function isn't
> defined, it behaves like == [2]
> The == function returns true if the "things" are of the same instance.
>
> I think functions in clojure are defined in [3], but I'm not entirely sure.
> As you can see, equals isn't implemented, and thus = will only compare
> instance (id), as you have noticed.
>
> Jonathan
>
> [1]https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
> 
> [2]http://leepoint.net/notes-java/data/expressions/22compareobjects.html
> [3]https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
>
> On Thu, May 5, 2011 at 3:04 PM, Dominikus 
> wrote:
>
>
>
>
>
>
>
>
>
> > My observation is best distilled with the following definition of a
> > function in Clojure 1.2:
>
> > user=> (defn id [x] (list id x))
> > #'user/id
>
> > Interstingly, (id 7) and (eval (id 7)) result in different instances
> > of function id as the number after the '@' char unveils:
>
> > user=> (id 7)
> > (# 7)
> > user=> (eval (id 7))
> > (# 7)
>
> > Consequently, the following comparison leads to false:
>
> > user=> (= (id 7) (eval (id 7)))
> > false
>
> > Why is the instance relevant to '='? What is the precise semantics of
> > two values being equal in Clojure?
>
> > Dominikus
>
> > (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
> > restrictive 'equal?' does not and returns #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

-- 
You 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: Eval destroys equality

2011-05-05 Thread Jonathan Fischer Friberg
I'm also interested in that.
I think it has to do with how clojure.lang.Compiler [1] works (since that is
what eval uses),
but since it is quite big, I don't know exactly what parts are important.

Jonathan

[1]
https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Compiler.java

On Thu, May 5, 2011 at 5:41 PM, Dominikus wrote:

> Thanks for the pointers to the implementation, Jonathan!
>
> Unfortunately, I couldnt' find out yet, which part of the source code
> in Clojure 1.3 is responsible for fixing the misbehavior in 1.2. The
> parts you point to haven't changed in 1.3.
>
> Cheers,
>
> Dominikus
>
> On May 5, 4:27 pm, Jonathan Fischer Friberg 
> wrote:
> > = uses the clojure.lang.Util/equiv to compare two "things". The source of
> > this function is: [1]
> >
> > static public boolean equiv(Object k1, Object k2){
> > if(k1 == k2)
> > return true;
> > if(k1 != null)
> > {
> > if(k1 instanceof Number && k2 instanceof Number)
> > return Numbers.equiv(k1, k2);
> > else if(k1 instanceof IPersistentCollection && k2
> instanceof
> > IPersistentCollection)
> > return ((IPersistentCollection)k1).equiv(k2);
> > return k1.equals(k2);
> > }
> > return false;
> >
> > }
> >
> > Which says:
> > if k1 and k2 is the same instance (has the same id), return true
> > if k1 and k2 are numbers, compare them as numbers
> > if k1 and k2 are collections, compare them as collections
> > otherwise, use the function "equals" of the k1 object.
> >
> > The equals function defines "intelligent" (proper) comparison of two
> > objects, and is defined by the programmer. If the equals function isn't
> > defined, it behaves like == [2]
> > The == function returns true if the "things" are of the same instance.
> >
> > I think functions in clojure are defined in [3], but I'm not entirely
> sure.
> > As you can see, equals isn't implemented, and thus = will only compare
> > instance (id), as you have noticed.
> >
> > Jonathan
> >
> > [1]
> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
> >  .>
> > [2]http://leepoint.net/notes-java/data/expressions/22compareobjects.html
> > [3]
> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
> >
> > On Thu, May 5, 2011 at 3:04 PM, Dominikus 
> > wrote:
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > > My observation is best distilled with the following definition of a
> > > function in Clojure 1.2:
> >
> > > user=> (defn id [x] (list id x))
> > > #'user/id
> >
> > > Interstingly, (id 7) and (eval (id 7)) result in different instances
> > > of function id as the number after the '@' char unveils:
> >
> > > user=> (id 7)
> > > (# 7)
> > > user=> (eval (id 7))
> > > (# 7)
> >
> > > Consequently, the following comparison leads to false:
> >
> > > user=> (= (id 7) (eval (id 7)))
> > > false
> >
> > > Why is the instance relevant to '='? What is the precise semantics of
> > > two values being equal in Clojure?
> >
> > > Dominikus
> >
> > > (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
> > > restrictive 'equal?' does not and returns #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
>
> --
> You 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: Eval destroys equality

2011-05-05 Thread Jonathan Fischer Friberg
It also seems that I have been linking to the wrong repo... :S
https://github.com/clojure/clojure
Should be the correct one.

On Thu, May 5, 2011 at 6:09 PM, Jonathan Fischer Friberg <
odysso...@gmail.com> wrote:

> I'm also interested in that.
> I think it has to do with how clojure.lang.Compiler [1] works (since that
> is what eval uses),
> but since it is quite big, I don't know exactly what parts are important.
>
> Jonathan
>
> [1]
> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Compiler.java
>
> On Thu, May 5, 2011 at 5:41 PM, Dominikus wrote:
>
>> Thanks for the pointers to the implementation, Jonathan!
>>
>> Unfortunately, I couldnt' find out yet, which part of the source code
>> in Clojure 1.3 is responsible for fixing the misbehavior in 1.2. The
>> parts you point to haven't changed in 1.3.
>>
>> Cheers,
>>
>> Dominikus
>>
>> On May 5, 4:27 pm, Jonathan Fischer Friberg 
>> wrote:
>> > = uses the clojure.lang.Util/equiv to compare two "things". The source
>> of
>> > this function is: [1]
>> >
>> > static public boolean equiv(Object k1, Object k2){
>> > if(k1 == k2)
>> > return true;
>> > if(k1 != null)
>> > {
>> > if(k1 instanceof Number && k2 instanceof Number)
>> > return Numbers.equiv(k1, k2);
>> > else if(k1 instanceof IPersistentCollection && k2
>> instanceof
>> > IPersistentCollection)
>> > return ((IPersistentCollection)k1).equiv(k2);
>> > return k1.equals(k2);
>> > }
>> > return false;
>> >
>> > }
>> >
>> > Which says:
>> > if k1 and k2 is the same instance (has the same id), return true
>> > if k1 and k2 are numbers, compare them as numbers
>> > if k1 and k2 are collections, compare them as collections
>> > otherwise, use the function "equals" of the k1 object.
>> >
>> > The equals function defines "intelligent" (proper) comparison of two
>> > objects, and is defined by the programmer. If the equals function isn't
>> > defined, it behaves like == [2]
>> > The == function returns true if the "things" are of the same instance.
>> >
>> > I think functions in clojure are defined in [3], but I'm not entirely
>> sure.
>> > As you can see, equals isn't implemented, and thus = will only compare
>> > instance (id), as you have noticed.
>> >
>> > Jonathan
>> >
>> > [1]
>> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
>> > <
>> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...>
>> > [2]
>> http://leepoint.net/notes-java/data/expressions/22compareobjects.html
>> > [3]
>> https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lan...
>> >
>> > On Thu, May 5, 2011 at 3:04 PM, Dominikus > >
>> > wrote:
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> > > My observation is best distilled with the following definition of a
>> > > function in Clojure 1.2:
>> >
>> > > user=> (defn id [x] (list id x))
>> > > #'user/id
>> >
>> > > Interstingly, (id 7) and (eval (id 7)) result in different instances
>> > > of function id as the number after the '@' char unveils:
>> >
>> > > user=> (id 7)
>> > > (# 7)
>> > > user=> (eval (id 7))
>> > > (# 7)
>> >
>> > > Consequently, the following comparison leads to false:
>> >
>> > > user=> (= (id 7) (eval (id 7)))
>> > > false
>> >
>> > > Why is the instance relevant to '='? What is the precise semantics of
>> > > two values being equal in Clojure?
>> >
>> > > Dominikus
>> >
>> > > (Remark: In Scheme, the use of 'eqv?' returns also #f, but the less
>> > > restrictive 'equal?' does not and returns #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
>>
>> --
>> You 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: Eval destroys equality

2011-05-05 Thread Ken Wesson
This is another case of function-object evaluation acting hinky, actually.

Specifically, (eval (id 7)) is evaluating a list of (id 7), not ('id
7). As near as I can figure out, rather than embed the function object
reference into the code OR complain, it is creating a new instance of
its class with newInstance, more or less in the manner I suggested in
another thread recently -- the failure with closures happening because
it doesn't check for closures and closures don't have a public
no-argument constructor, so need special handling (and preservation of
the arguments they were constructed with -- the closed-over values).

A longer-term fix might be to make instances of the function
superclass generated by (fn [foo] bar) (but not all IFns!) compare
equal if their exact classes are equal and, in the case that they are
closures, the closed-over values compare equal. This doesn't break the
expected semantics that functions that behave differently should
compare UNequal, but allows functions to be represented as constructor
calls to their classes and then reconstructed without breaking
equality.

In particular, we don't need to use eval to get hinky function
equality semantics already:

user=> (defn fn-maker1 [] (fn [] 3))
#'user/fn-maker1
user=> (= (fn-maker1) (fn-maker1))
false
user=> (defn fn-maker2 [x] (fn [] x))
#'user/fn-maker2
user=> (= (fn-maker2 3) (fn-maker2 3))
false
user=> (= (fn-maker2 3) (fn-maker2 4))
false
user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y)))
#'user/fn-maker3
user=> (= (fn-maker3 1 2) (fn-maker3 1 2))
false
user=> (= (fn-maker3 1 2) (fn-maker3 2 1))
false

Ideally, the results would be this instead:

user=> (defn fn-maker1 [] (fn [] 3))
#'user/fn-maker1
user=> (= (fn-maker1) (fn-maker1))
true ; conceptually identical functions
user=> (defn fn-maker2 [x] (fn [] x))
#'user/fn-maker2
user=> (= (fn-maker2 3) (fn-maker2 3))
true ; conceptually identical functions
user=> (= (fn-maker2 3) (fn-maker2 4))
false ; genuinely not the same
user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y)))
#'user/fn-maker3
user=> (= (fn-maker3 1 2) (fn-maker3 1 2))
true ; conceptually identical functions
user=> (= (fn-maker3 1 2) (fn-maker3 2 1))
false ; not the same:
user=> ((fn-maker3 1 2) 10)
12
user=> ((fn-maker3 2 1) 10)
21

Now, fn-maker3 could have produced (fn [z] (+ x y z)) in which the
roles of x and y are symmetrical, but I don't think it reasonable to
expect the compiler to detect every situation in which distinct
closed-over values give identically-behaved functions (in fact that's
probably equivalent to the halting problem) so I'd consider it
reasonable for it to consider closures unequal if they have distinct
sequences of closed-over values (and I say "sequences" here because as
fn-maker3 shows they aren't generally interchangeable; the constructor
for fn-maker3's closure's class will have some particular order it
takes them in and as sequences in that order they'd have to be equal
for two fn-maker3 results to be treated as equal here).

-- 
You 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: Eval destroys equality

2011-05-05 Thread Alan
(let [fnmaker4 (fn [coll] (fn [n] (nth coll n)))
  ints (range)]
  (= (fnmaker4 ints) (fnmaker4 ints)))

You want to make it impossible to compare functions that close over
infinite sequences? What is the point of being able to compare
functions if there are cases in which using the functions will
succeed, and the existing comparison strategy would not cause errors,
but your new proposal does?

Similarly, if you try to eval such a function, your proposed function-
eval semantics would, as I understand it, store its closed-over values
in a class constant somewhere. Then there's some secret place holding
onto the head of my lazy sequences for me? No thanks.

On May 5, 1:04 pm, Ken Wesson  wrote:
> This is another case of function-object evaluation acting hinky, actually.
>
> Specifically, (eval (id 7)) is evaluating a list of (id 7), not ('id
> 7). As near as I can figure out, rather than embed the function object
> reference into the code OR complain, it is creating a new instance of
> its class with newInstance, more or less in the manner I suggested in
> another thread recently -- the failure with closures happening because
> it doesn't check for closures and closures don't have a public
> no-argument constructor, so need special handling (and preservation of
> the arguments they were constructed with -- the closed-over values).
>
> A longer-term fix might be to make instances of the function
> superclass generated by (fn [foo] bar) (but not all IFns!) compare
> equal if their exact classes are equal and, in the case that they are
> closures, the closed-over values compare equal. This doesn't break the
> expected semantics that functions that behave differently should
> compare UNequal, but allows functions to be represented as constructor
> calls to their classes and then reconstructed without breaking
> equality.
>
> In particular, we don't need to use eval to get hinky function
> equality semantics already:
>
> user=> (defn fn-maker1 [] (fn [] 3))
> #'user/fn-maker1
> user=> (= (fn-maker1) (fn-maker1))
> false
> user=> (defn fn-maker2 [x] (fn [] x))
> #'user/fn-maker2
> user=> (= (fn-maker2 3) (fn-maker2 3))
> false
> user=> (= (fn-maker2 3) (fn-maker2 4))
> false
> user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y)))
> #'user/fn-maker3
> user=> (= (fn-maker3 1 2) (fn-maker3 1 2))
> false
> user=> (= (fn-maker3 1 2) (fn-maker3 2 1))
> false
>
> Ideally, the results would be this instead:
>
> user=> (defn fn-maker1 [] (fn [] 3))
> #'user/fn-maker1
> user=> (= (fn-maker1) (fn-maker1))
> true ; conceptually identical functions
> user=> (defn fn-maker2 [x] (fn [] x))
> #'user/fn-maker2
> user=> (= (fn-maker2 3) (fn-maker2 3))
> true ; conceptually identical functions
> user=> (= (fn-maker2 3) (fn-maker2 4))
> false ; genuinely not the same
> user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y)))
> #'user/fn-maker3
> user=> (= (fn-maker3 1 2) (fn-maker3 1 2))
> true ; conceptually identical functions
> user=> (= (fn-maker3 1 2) (fn-maker3 2 1))
> false ; not the same:
> user=> ((fn-maker3 1 2) 10)
> 12
> user=> ((fn-maker3 2 1) 10)
> 21
>
> Now, fn-maker3 could have produced (fn [z] (+ x y z)) in which the
> roles of x and y are symmetrical, but I don't think it reasonable to
> expect the compiler to detect every situation in which distinct
> closed-over values give identically-behaved functions (in fact that's
> probably equivalent to the halting problem) so I'd consider it
> reasonable for it to consider closures unequal if they have distinct
> sequences of closed-over values (and I say "sequences" here because as
> fn-maker3 shows they aren't generally interchangeable; the constructor
> for fn-maker3's closure's class will have some particular order it
> takes them in and as sequences in that order they'd have to be equal
> for two fn-maker3 results to be treated as equal here).

-- 
You 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: Eval destroys equality

2011-05-05 Thread Ken Wesson
On Thu, May 5, 2011 at 4:16 PM, Alan  wrote:
> (let [fnmaker4 (fn [coll] (fn [n] (nth coll n)))
>      ints (range)]
>  (= (fnmaker4 ints) (fnmaker4 ints)))
>
> You want to make it impossible to compare functions that close over
> infinite sequences? What is the point of being able to compare
> functions if there are cases in which using the functions will
> succeed, and the existing comparison strategy would not cause errors,
> but your new proposal does?

Hm, that is a problem. You'd need to compare not the sequences, but
their generator functions. :)

> Similarly, if you try to eval such a function, your proposed function-
> eval semantics would, as I understand it, store its closed-over values
> in a class constant somewhere. Then there's some secret place holding
> onto the head of my lazy sequences for me? No thanks.

Your fnmaker4 already holds onto the head of ints, above, so that this:

user=> (def q (fnmaker4 (iterate inc 0)))
#'user/q
user=> (q 119)
119
user=> (q 0)
0

can work properly.

Externalizing of lazy sequences that are potentially infinite does
present a complex issue, though. One option is to not allow it. (Right
now, I think it will actually try to write out an infinite sequence to
disk and eventually run out of filesystem space if you use prn or
something.) Another is to try to output not the sequence, but code
that will reconstruct the sequence, which means being able to
externalize the function references involved. :)

-- 
You 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: Eval destroys equality

2011-05-05 Thread Alan
On May 5, 1:28 pm, Ken Wesson  wrote:
> On Thu, May 5, 2011 at 4:16 PM, Alan  wrote:
> > (let [fnmaker4 (fn [coll] (fn [n] (nth coll n)))
> >      ints (range)]
> >  (= (fnmaker4 ints) (fnmaker4 ints)))
>
> > You want to make it impossible to compare functions that close over
> > infinite sequences? What is the point of being able to compare
> > functions if there are cases in which using the functions will
> > succeed, and the existing comparison strategy would not cause errors,
> > but your new proposal does?
>
> Hm, that is a problem. You'd need to compare not the sequences, but
> their generator functions. :)
>
> > Similarly, if you try to eval such a function, your proposed function-
> > eval semantics would, as I understand it, store its closed-over values
> > in a class constant somewhere. Then there's some secret place holding
> > onto the head of my lazy sequences for me? No thanks.
>
> Your fnmaker4 already holds onto the head of ints, above, so that this:
>
> user=> (def q (fnmaker4 (iterate inc 0)))
> #'user/q
> user=> (q 119)
> 119
> user=> (q 0)
> 0
>
> can work properly.

Right. But if I drop all references to the returned function after I'm
done with it, it gets GCed. If there's some class holding a reference
to it forever, it will never get cleaned up. For example, ((fnmaker4
(range)) 1e6) will (I think?) currently result in a million ints being
held in memory at once, as things are now. Those things will get
thrown away shortly thereafter, though. I'm not sure I fully
understand your proposal, but it seems to me like you might be making
these stick around permanently if I include the right mixture of eval,
quoting, and unquoting in that expression.

-- 
You 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: Eval destroys equality

2011-05-05 Thread Jonathan Fischer Friberg
I created a new datatype to solve this problem:
http://gist.github.com/958001
c-fn creates a comparable function;

(let [fnmaker4 (fn [coll] (c-fn [n] (nth coll n)))
  ints (range)]
 (= (fnmaker4 ints) (fnmaker4 ints)))
=> true


On Thu, May 5, 2011 at 10:41 PM, Alan  wrote:

> On May 5, 1:28 pm, Ken Wesson  wrote:
> > On Thu, May 5, 2011 at 4:16 PM, Alan  wrote:
> > > (let [fnmaker4 (fn [coll] (fn [n] (nth coll n)))
> > >  ints (range)]
> > >  (= (fnmaker4 ints) (fnmaker4 ints)))
> >
> > > You want to make it impossible to compare functions that close over
> > > infinite sequences? What is the point of being able to compare
> > > functions if there are cases in which using the functions will
> > > succeed, and the existing comparison strategy would not cause errors,
> > > but your new proposal does?
> >
> > Hm, that is a problem. You'd need to compare not the sequences, but
> > their generator functions. :)
> >
> > > Similarly, if you try to eval such a function, your proposed function-
> > > eval semantics would, as I understand it, store its closed-over values
> > > in a class constant somewhere. Then there's some secret place holding
> > > onto the head of my lazy sequences for me? No thanks.
> >
> > Your fnmaker4 already holds onto the head of ints, above, so that this:
> >
> > user=> (def q (fnmaker4 (iterate inc 0)))
> > #'user/q
> > user=> (q 119)
> > 119
> > user=> (q 0)
> > 0
> >
> > can work properly.
>
> Right. But if I drop all references to the returned function after I'm
> done with it, it gets GCed. If there's some class holding a reference
> to it forever, it will never get cleaned up. For example, ((fnmaker4
> (range)) 1e6) will (I think?) currently result in a million ints being
> held in memory at once, as things are now. Those things will get
> thrown away shortly thereafter, though. I'm not sure I fully
> understand your proposal, but it seems to me like you might be making
> these stick around permanently if I include the right mixture of eval,
> quoting, and unquoting in that expression.
>
> --
> You 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: Eval destroys equality

2011-05-05 Thread Jonathan Fischer Friberg
Although (as I just realized), it fails miserably with closures.

On Thu, May 5, 2011 at 11:38 PM, Jonathan Fischer Friberg <
odysso...@gmail.com> wrote:

> I created a new datatype to solve this problem:
> http://gist.github.com/958001
> c-fn creates a comparable function;
>
> (let [fnmaker4 (fn [coll] (c-fn [n] (nth coll n)))
>   ints (range)]
>  (= (fnmaker4 ints) (fnmaker4 ints)))
> => true
>
>
> On Thu, May 5, 2011 at 10:41 PM, Alan  wrote:
>
>> On May 5, 1:28 pm, Ken Wesson  wrote:
>> > On Thu, May 5, 2011 at 4:16 PM, Alan  wrote:
>> > > (let [fnmaker4 (fn [coll] (fn [n] (nth coll n)))
>> > >  ints (range)]
>> > >  (= (fnmaker4 ints) (fnmaker4 ints)))
>> >
>> > > You want to make it impossible to compare functions that close over
>> > > infinite sequences? What is the point of being able to compare
>> > > functions if there are cases in which using the functions will
>> > > succeed, and the existing comparison strategy would not cause errors,
>> > > but your new proposal does?
>> >
>> > Hm, that is a problem. You'd need to compare not the sequences, but
>> > their generator functions. :)
>> >
>> > > Similarly, if you try to eval such a function, your proposed function-
>> > > eval semantics would, as I understand it, store its closed-over values
>> > > in a class constant somewhere. Then there's some secret place holding
>> > > onto the head of my lazy sequences for me? No thanks.
>> >
>> > Your fnmaker4 already holds onto the head of ints, above, so that this:
>> >
>> > user=> (def q (fnmaker4 (iterate inc 0)))
>> > #'user/q
>> > user=> (q 119)
>> > 119
>> > user=> (q 0)
>> > 0
>> >
>> > can work properly.
>>
>> Right. But if I drop all references to the returned function after I'm
>> done with it, it gets GCed. If there's some class holding a reference
>> to it forever, it will never get cleaned up. For example, ((fnmaker4
>> (range)) 1e6) will (I think?) currently result in a million ints being
>> held in memory at once, as things are now. Those things will get
>> thrown away shortly thereafter, though. I'm not sure I fully
>> understand your proposal, but it seems to me like you might be making
>> these stick around permanently if I include the right mixture of eval,
>> quoting, and unquoting in that expression.
>>
>> --
>> You 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: Eval destroys equality

2011-05-05 Thread Ken Wesson
On Thu, May 5, 2011 at 4:41 PM, Alan  wrote:
> Right. But if I drop all references to the returned function after I'm
> done with it, it gets GCed. If there's some class holding a reference
> to it forever, it will never get cleaned up. For example, ((fnmaker4
> (range)) 1e6) will (I think?) currently result in a million ints being
> held in memory at once, as things are now. Those things will get
> thrown away shortly thereafter, though.

True. We only need to worry about those integers being held if we keep
a reference to it somewhere.

Under my externalizability proposal, the fnmaker4 instance would hold
a reference to that instance of (range) in its metadata, but it
already holds such a reference in an instance variable somewhere. If
the fnmaker4 instance becomes unreachable, the GC will collect it and
the (range) instance even with the metadata. Only if it's externalized
is there an issue.

Case 1 is not real "externalization" and is (eval `(some stuff
~the-fnmaker4-instance more stuff)) and suchlike. In that case there's
no real externalization required; eval can just embed a reference to
the fnmaker4 instance directly into the generated class. As long as
things are configured such that whole classes can be unloaded if no
longer in use, if the return value from eval is discarded and gets
eligible for GC, the (range) instance can still become GCable.

Case 2 is actual conversion of the closure into code that can recreate
it. The easy way to handle it is to disallow lazy seqs, or walk them
to some point and reject if over some length/byte limit, but that's
kind of icky.

Alternatively, we can have lazy seq externalization be done by
externalizing the unrealized seq -- that is, the fact of a lazy seq
with some particular generator function. That gives us another
function to externalize. Let's consider the output of

(map #(* x x) (range))

-- it turns out that this is a LazySeq object built ultimately around
delay and force. Somewhere in there is a fn that is closed over
(range) and #(* x x) and generates each successive element of the lazy
sequence. Externalizing that requires externalizing (range) and #(* x
x). The latter is trivial -- it's not even closed over anything. The
former is a specially-implemented lazy sequence instance and that
implementation can just externalize using print-dup as #=(range),
#=(range 3), #=(range 3 7), or the like.

The general pattern will be that lazy sequences amount to a special
kind of closure over, frequently, an input sequence, plus some other
values, often including more functions. The regress stops when it hits
something implemented the way range is, or an explicit use of the
lazy-seq macro, or similar. But the lazy-seq macro also just wraps
calls to a step function that is generally closed over something.

I'm fairly confident that it can, in principle, be done. Of course, it
won't always be doable -- a line-seq for example will not be
externalizable by the default means because eventually somewhere in
its guts is some function that has closed over a file handle.

-- 
You 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: Eval destroys equality

2011-05-06 Thread Andy Fingerhut
Caveat: The following fact may already be well known to those discussing this 
issue, and I may not be clear on the goal of this effort.

If the goal is to have functions compare as equal whenever they are equivalent 
in some sense, then that is an undecidable problem, even if the two functions 
are restricted to pure functions with no side effects and closed over no vars.  
The proof is nearly the same as that for the halting problem.

Of course, it is still decidable to get the correct answer for some restricted 
kinds of functions.  If that is what you are after, go for it.

Andy

On May 5, 2011, at 3:23 PM, Ken Wesson  wrote:

> On Thu, May 5, 2011 at 4:41 PM, Alan  wrote:
>> Right. But if I drop all references to the returned function after I'm
>> done with it, it gets GCed. If there's some class holding a reference
>> to it forever, it will never get cleaned up. For example, ((fnmaker4
>> (range)) 1e6) will (I think?) currently result in a million ints being
>> held in memory at once, as things are now. Those things will get
>> thrown away shortly thereafter, though.
> 
> True. We only need to worry about those integers being held if we keep
> a reference to it somewhere.
> 
> Under my externalizability proposal, the fnmaker4 instance would hold
> a reference to that instance of (range) in its metadata, but it
> already holds such a reference in an instance variable somewhere. If
> the fnmaker4 instance becomes unreachable, the GC will collect it and
> the (range) instance even with the metadata. Only if it's externalized
> is there an issue.
> 
> Case 1 is not real "externalization" and is (eval `(some stuff
> ~the-fnmaker4-instance more stuff)) and suchlike. In that case there's
> no real externalization required; eval can just embed a reference to
> the fnmaker4 instance directly into the generated class. As long as
> things are configured such that whole classes can be unloaded if no
> longer in use, if the return value from eval is discarded and gets
> eligible for GC, the (range) instance can still become GCable.
> 
> Case 2 is actual conversion of the closure into code that can recreate
> it. The easy way to handle it is to disallow lazy seqs, or walk them
> to some point and reject if over some length/byte limit, but that's
> kind of icky.
> 
> Alternatively, we can have lazy seq externalization be done by
> externalizing the unrealized seq -- that is, the fact of a lazy seq
> with some particular generator function. That gives us another
> function to externalize. Let's consider the output of
> 
> (map #(* x x) (range))
> 
> -- it turns out that this is a LazySeq object built ultimately around
> delay and force. Somewhere in there is a fn that is closed over
> (range) and #(* x x) and generates each successive element of the lazy
> sequence. Externalizing that requires externalizing (range) and #(* x
> x). The latter is trivial -- it's not even closed over anything. The
> former is a specially-implemented lazy sequence instance and that
> implementation can just externalize using print-dup as #=(range),
> #=(range 3), #=(range 3 7), or the like.
> 
> The general pattern will be that lazy sequences amount to a special
> kind of closure over, frequently, an input sequence, plus some other
> values, often including more functions. The regress stops when it hits
> something implemented the way range is, or an explicit use of the
> lazy-seq macro, or similar. But the lazy-seq macro also just wraps
> calls to a step function that is generally closed over something.
> 
> I'm fairly confident that it can, in principle, be done. Of course, it
> won't always be doable -- a line-seq for example will not be
> externalizable by the default means because eventually somewhere in
> its guts is some function that has closed over a file handle.
> 
> -- 
> You 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: Eval destroys equality

2011-05-06 Thread Adam Burry
On May 6, 3:10 pm, Andy Fingerhut  wrote:
> Caveat: The following fact may already be well known to those discussing this 
> issue, and I may not be clear on the goal of this effort.
>
> If the goal is to have functions compare as equal whenever they are 
> equivalent in some sense, then that is an undecidable problem, even if the 
> two functions are restricted to pure functions with no side effects and 
> closed over no vars.  The proof is nearly the same as that for the halting 
> problem.
>
> Of course, it is still decidable to get the correct answer for some 
> restricted kinds of functions.  If that is what you are after, go for it.

I don't think anyone expects quick sort to compare equal to bubble
sort or anything like that. I think the issue is to get two functions
with the same textual representation to compare equal.

Adam

-- 
You 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: Eval destroys equality

2011-05-06 Thread Dominikus
On May 6, 8:39 pm, Adam Burry  wrote:
> On May 6, 3:10 pm, Andy Fingerhut  wrote:
>
> > Caveat: The following fact may already be well known to those discussing 
> > this issue, and I may not be clear on the goal of this effort.
>
> > If the goal is to have functions compare as equal whenever they are 
> > equivalent in some sense, then that is an undecidable problem, even if the 
> > two functions are restricted to pure functions with no side effects and 
> > closed over no vars.  The proof is nearly the same as that for the halting 
> > problem.
>
> > Of course, it is still decidable to get the correct answer for some 
> > restricted kinds of functions.  If that is what you are after, go for it.
>
> I don't think anyone expects quick sort to compare equal to bubble
> sort or anything like that. I think the issue is to get two functions
> with the same textual representation to compare equal.
>
> Adam

Right, Adam. As Armando pointed out, Clojure 1.3 at least doesn't fail
in the case I brought up. I would be very interested to learn what has
changed in the Clojure 1.3 source code (compared to 1.2) to achieve
this.

Dominikus

-- 
You 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


Equality comparison in 1.3

2011-10-01 Thread Chris Perkins
I am trying to upgrade some code to 1.3, and I'm not sure how to do the 
equivalent of a 1.2-style equality comparison.

user> (= {:foo 23} {:foo 23.0})
false

This used to be true.  I see that = is now documented to compare same-type 
numbers only, but == can be used for 1.2-compatible comparisons. However:

user> (== {:foo 23} {:foo 23.0})
; Evaluation aborted.

== only seems to work on numbers.

How can I upgrade code that expects 1.2-compatible equality comparisons? Or 
do I need to change my expectations of what is considered equal in clojure?


- Chris


-- 
You 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

defrecord and map equality?

2010-07-29 Thread Ryan Twitchell
Hi all,

I noticed (with a very recent git pull) the following asymmetric
behavior regarding = and records:

(defrecord my-record [a])

(def r (new my-record 1))
(def s (new my-record 1))

(= r s);; true
(= s r);; true
(= r {:a 1})   ;; false
(= {:a 1} r)   ;; true

Is this intentional? (I hope not)

Also, what prompted this was my trying to do the following.  In
general, what kind of behavior should we expect to see when mixing
records and other map types?

(replace {{:a 1} (new my-record 2)} [(new my-record 1)])

Currently this produces [#:user.my-record{:a 1}], where I was hoping
to get [#:user.my-record{:a 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


equality of primitive values

2010-08-03 Thread Nicolas Oury
Dear all,

I am still fighting with a profiler and primitive hints.

It seems I cannot manage to have a direct equality check of the
primitive. My profiler tells me it goes through clojure.lang.Numbers
eq.
What is the best way to test equality of unboxed primitive?
(The two primitive are of the same primitive type)

Best regards,

Nicolas.

-- 
You 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


non-equality (=) of records nuance

2014-03-18 Thread Greg D
Greetings,

I'm confused by the failure of 2 record instances to compare as equal, only 
when generated by a protocol method and having extra fields.

The code below shows this, with uninformative REPL responses snipped. The 
attached file has similar code as a clojure.test.

Would somebody please help me understand the underlying mechanism. I'll 
need to develop a workaround to avoid confounding library users.

Thanks, Greg

user=> ;;; Set up protocol and records
user=> (defprotocol FooBar (clone [this]) (switch [this]))
user=> (defrecord Foo [])
user=> (defrecord Bar [])
user=> (extend-type Foo FooBar (clone [this] (map->Foo this)) (switch 
[this] (map->Bar this)))
user=> (extend-type Bar FooBar (clone [this] (map->Bar this)) (switch 
[this] (map->Foo this)))

user=> ;;; Create 4 (.equal) instances of Bar, no fields; all works as 
expected
user=> (def foo0 (->Foo))
user=> (def bar0 (->Bar))
user=> (def bar1 (->Bar))
user=> (def bar-switch-foo0 (switch foo0))
user=> (def bar-clone-bar0 (clone bar0))
user=> bar0
#user.Bar{}
user=> bar1
#user.Bar{}
user=> bar-switch-foo0
#user.Bar{}
user=> bar-clone-bar0
#user.Bar{}
user=> (= bar0 bar1); gets expected true
true
user=> (= bar0 bar-switch-foo0) ; gets expected true
true
user=> (= bar0 bar-clone-bar0)  ; gets expected true
true

user=> ;;; Create 4 (.equal) instances of Bar with an added field; 
unexpected results
user=> (def x-foo0 (map->Foo {:field "xtra"}))
user=> (def x-bar0 (map->Bar {:field "xtra"}))
user=> (def x-bar1 (map->Bar {:field "xtra"}))
user=> (def bar-switch-x-foo0 (switch x-foo0))
user=> (def bar-clone-x-bar0 (clone x-bar0))
user=> x-bar0
#user.Bar{:field "xtra"}
user=> x-bar1
#user.Bar{:field "xtra"}
user=> bar-switch-x-foo0
#user.Bar{:field "xtra"}
user=> bar-clone-x-bar0
#user.Bar{:field "xtra"}
user=> (= x-bar0 x-bar1); gets expected true
true
user=> (= x-bar0 bar-switch-x-foo0) ; gets UNEXPECTED
false
user=> (= x-bar0 bar-clone-x-bar0)  ; gets UNEXPECTED
false
user=> (= bar-switch-x-foo0 bar-clone-x-bar0)   ; gets UNEXPECTED
false
user=> (.equals x-bar0 bar-switch-x-foo0)   ; .equals is true
true
user=> (.equals x-bar0 bar-clone-x-bar0); .equals is true
true
user=> (.equals bar-switch-x-foo0 bar-clone-x-bar0) ; .equals is true
true

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


record_instance_equality_test.clj
Description: Binary data


non-equality (=) of records nuance

2014-03-18 Thread Alex Miller
What Clojure version are you 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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


defrecord, equality, hashing, and performance

2015-06-11 Thread Mars0i
I think that the following is all correct, but I could be wrong about 
something.

The datatypes page at clojure.org <http://clojure.org/datatypes> says: 
"defrecord provides ... value-based equality and hashCode", while deftype 
does not.   So
(defrecord Rec [x])
(= (Rec. 42) (Rec. 42)) ;=> true
but
(deftype Typ [x])
(= (Typ. 42) (Typ. 42)) ;=> false.
This also means, as I understand it, that data structures that use 
hashing--maps and sets, for example--hash on value for records, but on 
identity for types.  I believe that the same is true when Java hashtables 
compare records, or compare types, although I haven't carefully tested this.

It makes sense that the primary, most fully functional user-definable 
datatypes in Clojure should use value-based equality; that's fully in the 
spirit of a functional language, and is very convenient in many contexts, 
and hashing should follow the equality semantics of the datatypes.  You can 
always use identical? if you want to test records for identity rather than 
equality.

However, you can't tell maps and sets to use identity for records, afaik.  
This makes records undesirable if you only care about identity, and need to 
use a data structure that uses hashing, and care about performance, because 
value-based hashing is presumably a lot slower than identity-based hashing 
(which is what my experiments seem to show).

On the other hand, records are obviously way, way, more convenient than 
types in many contexts because the functionality provided by deftype is so 
bare-bones.  It really bothers me that I have to choose between speed and 
using convenient, idiomatic functionality (defrecord) that is one of 
several significant reasons that I love Clojure.  (This is in an 
application in which value-based equality would *never* be what I wanted 
for my datatypes.)

Should there be an alternative?  Either a way to define e.g. a special kind 
of set that uses identity rather than value for records, or a way to make 
records use identity for equality, or another datatype that's just like 
defrecord but ..., or a way to get more functionality with deftype, or 
...?  (I don't think that Clojure should include every option or 
functionality that someone thinks might be convenient in some context.  
Another reason that I love Clojure is that it *doesn't* do that, but 
instead provides limited, well-thought out options that allow a lot of 
flexibility.)

In an earlier thread 
<https://groups.google.com/forum/#!topic/clojure/EdjnSxRkOPk>, Stephen Yi 
pointed out that although you're allowed to override some Object methods in 
defrecord, you can't override Object.equals and Object.hashCode.  It isn't 
documented, but the compiler throws an exception if you try it.  That makes 
quite a bit of sense, since changing the meaning of equality for a datatype 
would be an easy way to introduce confusing bugs.  On the other hand, if 
you do override Object.equals and Object.hashCode for defrecord, you 
probably know that you're doing something weird, and that you'd better take 
precautions, if necessary, to avoid later confusion.

-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Question about equality in HashMaps

2015-09-11 Thread Erlis Vidal
(def a (apply merge-with + (map #(hash-map %1 1) "aaaur")))
(def b {"a" 3, "r" 1, "u" 1})

 (= a b)  ; why false
 (.equals a b)

 (type a)
 (type b)

 (identity a)
 (identity b)

from http://web.clojurerepl.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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Equality comparison in 1.3

2013-02-03 Thread greybird
Yes, the Clojure 1.3 doc is wrong.  As a new Clojure user, I was pretty 
confused for a while.

But after reading this thread I still don't understand why the map behavior 
(where 3 and 3.0 are considered different map keys) wasn't considered 
incorrect, rather than the = behavior.

http://clojure.org/data_structures has this general statement:

   - Contagion
   BigInts and floating point types are "contagious" across operations. 
   That is, any integer operation involving a BigInt will result in a BigInt, 
   and any operation involving a double or float will result in a double.

Since this does seem to apply to < and >, why wouldn't = fall into the same 
category, and therefore why wouldn't it be the map behavior that was 
considered incorrect?  Said differently, what is the rationale for the map 
behavior?

--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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-08 Thread Ben Wolfson
On Mon, Apr 8, 2013 at 4:02 PM, JvJ  wrote:

>
> Even though the behaviour of lists and vectors differs under specific
> functions, they still count as equal, but this statement "If a = b, then (f
> a) = (f b)" seems like it would be some sort of rule or axiom about
> functional programming.  What's the FP purists' view on this?
>

You don't even need different types for this:

user> (deftype Perverse? [a b]
   Object
   (equals [this other] (= a (.a other
user.Perverse?
user> (defn f [^Perverse? p]
   (Perverse?. (.b p) (.a p)))
#'user/f
user> (= (->Perverse? 1 2) (->Perverse? 1 4))
true
user> (= (f (->Perverse? 1 2)) (f (->Perverse? 1 4)))
false
user>

-- 
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks, which
may be sweet, aromatic, fermented or spirit-based. ... Family and social
life also offer numerous other occasions to consume drinks for pleasure."
[Larousse, "Drink" entry]

-- 
-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-08 Thread Andy Fingerhut
I think the general pattern here is equality being a function of _part_ of
the value, but not all of it.  For Clojure's = on lists/sequences/vectors,
it is based upon the sequence of values, but not whether it is a list,
sequence, or vector.  For Perverse?'s equals it is quite explicit in its
definition which part it is ignoring.  The functions f being considered
have behavior that explicitly depends upon parts of the value that equality
is ignoring.  Clojure's = on collections also ignores metadata, by design,
and yet functions can return values that depend upon the metadata.

This certainly does lead to as many cases as you care to dream up where (=
a b) but not (= (f a) (f b)).  I believe  Haskell lets you define your own
equality for new types, so there is nothing unique to Clojure here.

Regarding whether it is a good or bad idea for Clojure to define (= '(1 2
3) [1 2 3]), it is often very useful, and lets you write (= s1 s2) instead
of (= (seq s1) (seq s2)) in many places.  I have no objections to it.

What the FP purist's point of view is on that question I don't know.  I'd
guess that a Haskell programmer would frown on defining equality for a new
type in a way that exposes this behavior.  I didn't have much luck from a
few minutes of Google searches, but did find the discussion linked below.
Someone points out how certain Haskell functions are frowned upon because
they cause certain theorems about program transformation to no longer
apply, that would otherwise be true in the absence of those functions.
Such program transformations can be used to help optimize code generated by
compilers.

http://stackoverflow.com/questions/12687392/why-is-seq-bad

Andy



On Mon, Apr 8, 2013 at 4:16 PM, Ben Wolfson  wrote:

> On Mon, Apr 8, 2013 at 4:02 PM, JvJ  wrote:
>
>>
>> Even though the behaviour of lists and vectors differs under specific
>> functions, they still count as equal, but this statement "If a = b, then (f
>> a) = (f b)" seems like it would be some sort of rule or axiom about
>> functional programming.  What's the FP purists' view on this?
>>
>
> You don't even need different types for this:
>
> user> (deftype Perverse? [a b]
>Object
>(equals [this other] (= a (.a other
> user.Perverse?
> user> (defn f [^Perverse? p]
>(Perverse?. (.b p) (.a p)))
> #'user/f
> user> (= (->Perverse? 1 2) (->Perverse? 1 4))
> true
> user> (= (f (->Perverse? 1 2)) (f (->Perverse? 1 4)))
> false
> user>
>
> --
> Ben Wolfson
> "Human kind has used its intelligence to vary the flavour of drinks, which
> may be sweet, aromatic, fermented or spirit-based. ... Family and social
> life also offer numerous other occasions to consume drinks for pleasure."
> [Larousse, "Drink" entry]
>
>  --
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-08 Thread Phil Hagelberg

JvJ writes:

> Even though the behaviour of lists and vectors differs under specific 
> functions, they still count as equal, but this statement "If a = b, then (f 
> a) = (f b)" seems like it would be some sort of rule or axiom about 
> functional programming.  What's the FP purists' view on this?

Baker's "Equal Rights for Functional Objects" is the best overview of
equality semantics I've ever read:

http://home.pipeline.com/~hbaker1/ObjectIdentity.html

> Two objects are "operationally equivalent" if and only if there is no
> way that they can be distinguished, using ... primitives other than
> [equality primitives]. It is guaranteed that objects maintain their
> operational identity despite being named by variables or fetched from or
> stored into data structures.

Clojure is inspired by it, but cheats in a number of places. The
most obvious being the way that seqs and vectors can be considered
equal. This could be considered cutting corners in order to make
laziness less onerous to deal with. IIRC there are a few other places
where Clojure deviates from this definition of operational equivalence
around defrecord and deftype, but since I don't use those features the
details escape me at the moment.

-Phil

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-08 Thread Philip Potter
One reason for being slightly "impure" here is for greater java
interoperability. Clojure gets much of its equality semantics for
collections from java.lang.List and java.lang.Set, which define equality to
depend only on collection contents and not on concrete type. By having
equality semantics which match up, you can pass a clojure vector, list, or
seq to a library expecting a j.l.List.

(it's a little more complicated than this; clojure defines its own equality
semantics which broadly matches java collection semantics using the
.equiv() method. It differs only in which numeric types it considers equal.
The clojure = function calls .equiv if present, and .equals otherwise. But
broadly clojure's equality matches java collection equality.)
On Apr 9, 2013 12:02 AM, "JvJ"  wrote:

> This is just an idle curiosity up for discussion, but in Clojure, if (= a
> b) is true, then given some function f, it is not necessarily true that (=
> (f a) (f b))
>
> For instance:
>
> (defn check-eq
> [f a b]
> [(= a b)
> (= (f a) (f b))])
>
> (check-eq #(conj % 1) '(1 2 3) [1 2 3])
> [true false]
>
> Even though the behaviour of lists and vectors differs under specific
> functions, they still count as equal, but this statement "If a = b, then (f
> a) = (f b)" seems like it would be some sort of rule or axiom about
> functional programming.  What's the FP purists' view on 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-09 Thread Tassilo Horn
JvJ  writes:

> This is just an idle curiosity up for discussion, but in Clojure, if
> (= a b) is true, then given some function f, it is not necessarily
> true that (= (f a) (f b))

I think this axiom isn't true in any language.  Take `str` / toString()
as an example.  If that statement was true, then equal objects would
need to have equal string representations.  Then you either couldn't
have 1 and 1.0 be equal, or you would need to print all numbers as
floats.  An even better counter example are sets versus sorted sets.

Bye,
Tassilo

-- 
-- 
You 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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Opinions on Equality Semantics

2013-04-09 Thread Gary Verhaegen
Since Clojure is not a pure language, you cannot even expect (a == a) ==>
((f a) == (f a)), so I do not think it is a stretch to break that theorem
for b != a.

Most importantly, Clojure's notion of equality is centered around the
notion of simple data, irrespective of the specific type of object you have
built to encapsulate it.


On 9 April 2013 11:00, Tassilo Horn  wrote:

> JvJ  writes:
>
> > This is just an idle curiosity up for discussion, but in Clojure, if
> > (= a b) is true, then given some function f, it is not necessarily
> > true that (= (f a) (f b))
>
> I think this axiom isn't true in any language.  Take `str` / toString()
> as an example.  If that statement was true, then equal objects would
> need to have equal string representations.  Then you either couldn't
> have 1 and 1.0 be equal, or you would need to print all numbers as
> floats.  An even better counter example are sets versus sorted sets.
>
> Bye,
> Tassilo
>
> --
> --
> You 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: equality and struct inheritance

2008-10-07 Thread Stuart Halloway

Hi Brian,

(1) What does it mean to be equal on id and not equal on the other  
fields? If two fields claim the same id but a different name, how  
would you know which one to keep?

(2) Given some answer to #1, why not store the structs in a map under  
id?

(3) For the geocoded place struct, I would be tempted to just create a  
separate defstruct. Nothing in Clojure prevents the two different  
kinds of structures from being substituted for one another. You could  
look into make-hierarchy, etc. plus defmulti if you find that you need  
inheritance-like behavior for method dispatch.

Stuart

> I'm attempting to learn Clojure with a long history of OO and have  
> some
> questions.I've created a defstruct for a place type object like:
>
> (defstruct place :id :name :street :city :state :zip)
>
> I want to write a function that would take a list of places and remove
> the duplicates.   Duplicates are defined by places having the  
> same :id.
> I created a 'place' namespace and attempted to create a function
> called '=' that would only use the :id to compare two places, however,
> I was not about to create such a function name.   Is there a preferred
> function name for equality in this case?
>
> Coming from an OO background and wanting a geocoded-place
> struc is there a way to "inherit" from the place struct?   Something
> like take all of the existing keys from the place struct and also add
> :latitude & :longitude?
>
> Thanks.
>
>
>
>
>
> >


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: equality and struct inheritance

2008-10-07 Thread Brian Doyle
On Tue, Oct 7, 2008 at 2:32 PM, Stuart Halloway
<[EMAIL PROTECTED]>wrote:

>
> Hi Brian,
>
> (1) What does it mean to be equal on id and not equal on the other
> fields? If two fields claim the same id but a different name, how
> would you know which one to keep?


I guess it could depend on the situation and you may not care about
the other fields at all, only on the id.   I'm used to Java/Ruby
when you define an equals and hashcode method that determines
equality which very well may be a subset of the total attributes on an
object.

(2) Given some answer to #1, why not store the structs in a map under
> id?


I could, but does this mean that I couldn't store the place objects in a set
to dedup the places?   It would appear that a struct uses all of the
attributes
of the map to determine equality.  I was hoping I could overwrite equality
for a given struct.


>
>
> (3) For the geocoded place struct, I would be tempted to just create a
> separate defstruct. Nothing in Clojure prevents the two different
> kinds of structures from being substituted for one another. You could
> look into make-hierarchy, etc. plus defmulti if you find that you need
> inheritance-like behavior for method dispatch.


Yes, I was just being somewhat lazy with this.  If I define 10 attributes
for a given struct and wanted to use all of those plus 3 more in a new
struct I didn't want to have to write out those original 10 attributes
again.

Thanks.




>
>
> Stuart
>
> > I'm attempting to learn Clojure with a long history of OO and have
> > some
> > questions.I've created a defstruct for a place type object like:
> >
> > (defstruct place :id :name :street :city :state :zip)
> >
> > I want to write a function that would take a list of places and remove
> > the duplicates.   Duplicates are defined by places having the
> > same :id.
> > I created a 'place' namespace and attempted to create a function
> > called '=' that would only use the :id to compare two places, however,
> > I was not about to create such a function name.   Is there a preferred
> > function name for equality in this case?
> >
> > Coming from an OO background and wanting a geocoded-place
> > struc is there a way to "inherit" from the place struct?   Something
> > like take all of the existing keys from the place struct and also add
> > :latitude & :longitude?
> >
> > Thanks.
> >
> >
> >
> >
> >
> > >
>
>
> >
>

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: equality and struct inheritance

2008-10-07 Thread Meikel Brandmeyer

Hello,

Am 07.10.2008 um 23:32 schrieb Brian Doyle:

Yes, I was just being somewhat lazy with this.  If I define 10  
attributes

for a given struct and wanted to use all of those plus 3 more in a new
struct I didn't want to have to write out those original 10  
attributes again.


I'm not sure, that understand what you mean, but you can assign
arbitrary additional keys to structs.

(defstruct foo :a)
(def m (struct foo 5))
; => {:a 5}
(def x (assoc m :b 7))
; => {:a 5 :b 7}
(def y (assoc m :c 1))
; => {:a 5 :c 1}

However you loose the key sharing for this additional keys. Only the
struct keys are shared between the maps.

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: equality and struct inheritance

2008-10-07 Thread Stephen Parker

On 7 Oct 2008, at 21:00, Brian Doyle wrote:

> [...] I've created a defstruct for a place type object like:
>
> (defstruct place :id :name :street :city :state :zip)
>
> I want to write a function that would take a list of places and remove
> the duplicates.   Duplicates are defined by places having the  
> same :id.

How about something like this (based on "distinct" in boot.clj):

(defn hashed-distinct
   "Returns a lazy sequence of the elements of coll with duplicates  
removed after elements first 'hashed' by hashfn"
   [coll hashfn]
 (let [step (fn step [[f & r :as xs] seen]
(when xs
  (if (seen (hashfn f))
   (recur r seen)
   (lazy-cons f (step r (conj seen (hashfn f)))]
   (step (seq coll) #{})))

(defstruct place :id :name :street :city :state :zip)

(defn distinct-places [places]
   (hashed-distinct places #(:id %1)))

So the "hashing" or "distinction extracting" function is passed into  
the duplicate removing function.  It seems odd to me to define an  
equality such as this as being the property of the object.  If the  
object has externally visible attributes that differ then to define =  
to say that it is the same can only be a source of confusion surely.

stephen
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Bug? Strange set equality (r1075)

2008-10-19 Thread Achim Passen

Hi,

user> (= #{1 4} #{2 3})
true

it's not, is it?

Kind regards,
achim




-- 
http://rauschabstand.twoday.net


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



compare doubles for equality fn

2012-10-26 Thread Michael
Can someone recommend a library that contains a function comparing doubles 
for equality?

This clojure cookbook has a section on comparing floating-point numbers.

http://www.gettingclojure.com/cookbook:numbers

This blog post makes me want to find an implementation by someone who has 
more experience in these matters. Thanks.

http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

There is no silver bullet. You have to choose wisely.

   - If you are comparing against zero, then relative epsilons and ULPs 
   based comparisons are usually meaningless. You’ll need to use an absolute 
   epsilon, whose value might be some small multiple of FLT_EPSILON and the 
   inputs to your calculation. Maybe.
   - If you are comparing against a non-zero number then relative epsilons 
   or ULPs based comparisons are probably what you want. You’ll probably want 
   some small multiple of FLT_EPSILON for your relative epsilon, or some small 
   number of ULPs. An absolute epsilon could be used if you knew exactly what 
   number you were comparing against.
   - If you are comparing two arbitrary numbers that could be zero or 
   non-zero then you need the kitchen sink. Good luck and God speed.

-- 
You 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: Equality comparison in 1.3

2011-10-01 Thread Daniel
user=> (= 23.0 23)
false
user=> (= 23 23)
true


"compares numbers and collections in a type-independent manner"

This kind of breakage was probably to be expected with the numerics
changes in 1.3.  I am also interested in this.


On Oct 1, 4:34 pm, Chris Perkins  wrote:
> I am trying to upgrade some code to 1.3, and I'm not sure how to do the
> equivalent of a 1.2-style equality comparison.
>
> user> (= {:foo 23} {:foo 23.0})
> false
>
> This used to be true.  I see that = is now documented to compare same-type
> numbers only, but == can be used for 1.2-compatible comparisons. However:
>
> user> (== {:foo 23} {:foo 23.0})
> ; Evaluation aborted.
>
> == only seems to work on numbers.
>
> How can I upgrade code that expects 1.2-compatible equality comparisons? Or
> do I need to change my expectations of what is considered equal in clojure?
>
> - Chris

-- 
You 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: Equality comparison in 1.3

2011-10-01 Thread Sean Corfield
On Sat, Oct 1, 2011 at 9:52 PM, Daniel  wrote:
> user=> (= 23.0 23)
> false

With every language I've ever worked in, I've always been told that
comparing floating point numbers for equality is a bad idea so I'm
actually glad to see that the above comparison is false...
-- 
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/
Railo Technologies, Inc. -- http://www.getrailo.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Stuart Halloway
> user=> (= 23.0 23)
> false
> user=> (= 23 23)
> true

This is the correct behavior. If the doc string is confusing, please propose 
alternate language.

Stu

Stuart Halloway
Clojure/core
http://clojure.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: Equality comparison in 1.3

2011-10-02 Thread Chris Perkins
Stuart,

The documentation is clear (to me) about comparing numbers directly - that 
part is fine. My question was about whether there is an equivalent of the 
new == comparison that works on containers with floating-point numbers 
inside.

I had guessed that == would recursively compare the contents with "loosely 
typed" comparison, so that, for example (== [23] [23.0]) would be true, but 
it does not.

Is there an equality comparison that does this? I couldn't find any mention 
of one in the numerics docs, but maybe missed it.


thanks,

- Chris

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Stuart Halloway
> Stuart,
> 
> The documentation is clear (to me) about comparing numbers directly - that 
> part is fine. My question was about whether there is an equivalent of the new 
> == comparison that works on containers with floating-point numbers inside.
> 
> I had guessed that == would recursively compare the contents with "loosely 
> typed" comparison, so that, for example (== [23] [23.0]) would be true, but 
> it does not.
> 
> Is there an equality comparison that does this? I couldn't find any mention 
> of one in the numerics docs, but maybe missed it.

Gotcha. No, there isn't. I don't think doing this kind of comparison is a good 
idea, but I have been wrong before.  If you need it, either a proposal on the 
wiki [1] or an incubator patch [2] would be fine.

In this case, [2] is probably better. Getting things in incubator is *much* 
easier than getting things in Clojure. This should be where we start to feel 
the benefit of modular contrib.

[1] http://dev.clojure.org/display/design/Release.Next+Planning
[2] http://dev.clojure.org/jira/browse/CINCU

Stuart Halloway
Clojure/core
http://clojure.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: Equality comparison in 1.3

2011-10-02 Thread Chris Perkins
Follow-up question: Can someone explain the rationale behind the change to = 
semantics between integers and floating-point numbers?  I have read the 
design page (
http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics), but all 
it seems to have is this somewhat cryptic description:

"It compares values in a type-independent manner, but not between floating 
points and integer types. This allows numbers to be used as map keys with 
correct semantics."

I have been playing with floating-point map-keys in 1.2, trying to find some 
behavior that seems like incorrect semantics, but I haven't found anything 
odd. What sort of incorrect semantics is this change trying to correct?

- Chris

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Luc Prefontaine
user=> (def m  { 3.0 :a 3 :b})
#'user/a
user=> a
{3.0 :a, 3 :b}
user=> (get m 3.0 )
:a
user=> (get m 3 )
:b
user=> 

if 3.0 and 3 were to be considered equals, you could not represent the above 
map,
the second entry would squash the first.

Now if we want to allow such maps, then we cannot consider 3.0 and 3 to be 
equal else where,
it's a matter of consistency.

Luc P.


On Sun, 2 Oct 2011 12:29:01 -0700 (PDT)
Chris Perkins  wrote:

> Follow-up question: Can someone explain the rationale behind the
> change to = semantics between integers and floating-point numbers?  I
> have read the design page (
> http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics),
> but all it seems to have is this somewhat cryptic description:
> 
> "It compares values in a type-independent manner, but not between
> floating points and integer types. This allows numbers to be used as
> map keys with correct semantics."
> 
> I have been playing with floating-point map-keys in 1.2, trying to
> find some behavior that seems like incorrect semantics, but I haven't
> found anything odd. What sort of incorrect semantics is this change
> trying to correct?
> 
> - Chris
> 



-- 
Luc P.


The rabid Muppet

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Daniel
Right.  I didn't see this earlier (http://dev.clojure.org/display/doc/
Documentation+for+1.3+Numerics).  We're all on the same page now.  (=

> If the doc string is confusing, please propose alternate language.

Updating the '=' docstring to match that page sounds appropriate ie
adding "...,but not between floating points and integer types."


This kind of change in equality semantics seems prone to cause really
sinister bugs in old 1.2 programs not well unit tested, so I've got a
general concern that there's no easy upgrade (like an =' (prime)) for
old programs that may have relied on this documented functionality.

On Oct 2, 7:58 am, Stuart Halloway  wrote:
> > user=> (= 23.0 23)
> > false
> > user=> (= 23 23)
> > true
>
> This is the correct behavior. If the doc string is confusing, please propose 
> alternate language.
>
> Stu
>
> Stuart Halloway
> Clojure/corehttp://clojure.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: Equality comparison in 1.3

2011-10-02 Thread Chris Perkins
Luc,

I think you are mistaken.

user=> (clojure-version)
"1.2.1"
user=> (def m {3.0 :a 3 :b})
#'user/m
user=> (get m 3.0)
:a
user=> (get m 3)
:b
user=> (= 3 3.0)
true
user=> 

Do you have another example?

- Chris

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Daniel
I think he's saying that it boiled down to consistency ie it's
inconsistent to allow maps where 3 != 3.0, but make 3 = 3.0 fit
clojure equality semantics.  I don't know if that's satisfying, but
it's fair.

On Oct 2, 3:31 pm, Chris Perkins  wrote:
> Luc,
>
> I think you are mistaken.
>
> user=> (clojure-version)
> "1.2.1"
> user=> (def m {3.0 :a 3 :b})
> #'user/m
> user=> (get m 3.0)
> :a
> user=> (get m 3)
> :b
> user=> (= 3 3.0)
> true
> user=>
>
> Do you have another example?
>
> - Chris

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Luc Prefontaine
What I meant is that (= 3 3.0) is the erroneous behavior.

Either it's equal every where (including as keys in maps) or not.

You cannot have both semantics coexists. It's all or nothing.

Look at this the other way around (1.2):

user=>  {3 :a 3 :b}
java.lang.IllegalArgumentException: Duplicate key: 3
user=> (= 3.0 3)
true
user=> {3.0 :a 3 :b} 
{3.0 :a, 3 :b}

This is non sense, if 3.0 and 3 are to be equal, then the last map should also 
fail
with a duplicate entry.

It's an inconsistent behavior.


On Sun, 2 Oct 2011 13:31:40 -0700 (PDT)
Chris Perkins  wrote:

> Luc,
> 
> I think you are mistaken.
> 
> user=> (clojure-version)
> "1.2.1"
> user=> (def m {3.0 :a 3 :b})
> #'user/m
> user=> (get m 3.0)
> :a
> user=> (get m 3)
> :b
> user=> (= 3 3.0)
> true
> user=> 
> 
> Do you have another example?
> 
> - Chris
> 



-- 
Luc P.


The rabid Muppet

-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Chris Perkins
Ok, I follow you now.  That makes sense.  Sort-of :)

On the other hand, it's only inconsistent if you consider clojure's = to map 
to java's .equals method, but it does not:

user=> (clojure-version)
"1.2.1"
user=> (= 3 3.0)
true
user=> (.equals 3 3.0)
false

So it doesn't really violate the contract for java's Map, which tells us 
that if a.equals(b), then they must have the same hash, and so a and b 
cannot both be keys. If you think of clojure's = as a looser sort of 
equivalence, then it's not a problem. I think.

In any case, the 1.3 behavior does feel weird in sometimes:

user> (def i 3)
#'user/i
user> (def j 3.0)
#'user/j
user> (< i j)
false
user> (> i j)
false
user> (= i j)
false

OK, that kind-of freaks me out...  :)

- Chris


-- 
You 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: Equality comparison in 1.3

2011-10-02 Thread Luc Prefontaine
In practice, in most languages, it's uncertain to test for equality between 
floating point values.
This is mainly a side effect of internal representations.

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

It's probably safer to keep things that way. Ints (or longs) are not floating 
point values.
The same issues could arise if we allow cross type equality tests, especially 
with computed values,
giving a false impression of a defined behavior.

If you have nearly equal values between an int (or long) and a floating point 
value, where do round up ?
Is it fine to round up the decimals or dropping them because they are "not 
significant" ?
For whom ? How often does a floating point value end up with no decimals 
following a computation ?

The above is a can of worms especially in heavy computation algorithms.

If Clojure stays on the most accepted side of the fence, then all the semantic 
issues that do not respect
this must change.

I would rather see something like this in the code:

(= 3 (long 3.8))

or even better

(= 3 (trunc 3.8))

Which clearly states what we want to test.

Luc P.

On Sun, 2 Oct 2011 14:03:47 -0700 (PDT)
Chris Perkins  wrote:

> Ok, I follow you now.  That makes sense.  Sort-of :)
> 
> On the other hand, it's only inconsistent if you consider clojure's =
> to map to java's .equals method, but it does not:
> 
> user=> (clojure-version)
> "1.2.1"
> user=> (= 3 3.0)
> true
> user=> (.equals 3 3.0)
> false
> 
> So it doesn't really violate the contract for java's Map, which tells
> us that if a.equals(b), then they must have the same hash, and so a
> and b cannot both be keys. If you think of clojure's = as a looser
> sort of equivalence, then it's not a problem. I think.
> 
> In any case, the 1.3 behavior does feel weird in sometimes:
> 
> user> (def i 3)
> #'user/i
> user> (def j 3.0)
> #'user/j
> user> (< i j)
> false
> user> (> i j)
> false
> user> (= i j)
> false
> 
> OK, that kind-of freaks me out...  :)
> 
> - Chris
> 
> 



-- 
Luc P.


The rabid Muppet

-- 
You 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


  1   2   >