Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #35750 > unrolled thread

Re: double == double

Started byEric Sosman <esosman@comcast-dot-net.invalid>
First post2016-10-12 09:39 -0400
Last post2016-10-20 15:01 +0200
Articles 7 on this page of 47 — 6 participants

Back to article view | Back to comp.lang.java.programmer

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-12 09:39 -0400
    Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-13 21:10 +0200
      Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-15 14:04 +0200
        Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 09:13 -0400
          Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 10:32 -0400
            Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 10:46 -0400
              Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-15 17:44 +0200
              Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 17:36 +0100
                Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 14:15 -0400
                  Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 19:41 +0100
              Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 20:39 -0400
        Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 10:41 -0400
          Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 23:09 +0100
            Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 18:28 -0400
              Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:13 +0100
                Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-16 08:37 -0400
                  Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 14:06 +0100
            Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 20:30 -0400
              Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:16 +0100
                Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:18 +0100
                Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 09:45 -0400
                  Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 14:51 +0100
                    Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 11:24 -0400
                      Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 16:43 +0100
                        Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 12:54 -0400
                          Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 18:37 +0100
                            Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 14:14 -0400
                              Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 22:19 +0100
                                Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 22:49 -0400
                                  Re: double == double a.laforgia@gmail.com - 2016-10-17 01:53 -0700
                                    Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 19:04 +0200
                                      Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 20:17 +0100
                                        Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 23:11 +0200
                                          Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 22:46 +0100
                                            Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-18 18:55 +0200
                                              Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-18 18:52 +0100
                                                Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-20 15:03 +0200
                                          True O-O [Was: double == double] Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-17 18:06 -0400
                                            Re: True O-O Patrick Roemer <sangamon@netcologne.de> - 2016-10-18 18:32 +0200
                                            Re: True O-O [Was: double == double] Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 22:09 -0400
                                    Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:58 -0400
                                  Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 18:58 +0200
                                    Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 20:32 +0100
                                      Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 23:21 +0200
                                      Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:38 -0400
                                    Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:47 -0400
                                      Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-20 15:01 +0200

Page 3 of 3 — ← Prev page 1 2 [3]


#35843

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-19 21:58 -0400
Message-ID<nu98bs$gjs$1@gioia.aioe.org>
In reply to#35796
On 10/17/2016 4:53 AM, a.laforgia@gmail.com wrote:
> On Monday, 17 October 2016 03:51:55 UTC+1, Arne Vajhøj  wrote:
>
> [...]
>> Having data and methods operating on the data separate is
>> very non-OO'ish in my book.
>
> That's a kind of purist approach that I find very little
 > pragmatic. Having methods that act on data is how OO is
> normally implemented.

Usually I am rather pragmatic.

But using a formatted string to as primary form for data
should bother more than purists.

> This:
>
>         double d1 = 3.4;
>         double d2 = 5.6;
>         double dMax = Math.max(d1, d2);
>
> is certainly better than this:
>
>     class PairOfDoubles {
>         double d1;
>         double d2;
>
>         public PairOfDoubles(double d1, double d2) {
>             this.d1 = d1;
>             this.d2 = d2;
>         }
>
>         public double max() {
>             return d1 >= d2 ? d1 : d2;
>         }
>     }
>

This example is not that close to the version number example.

The version number example has data with an internal structure
that the processing methods need to parse and format to work
with the data.

Consider a suggestion to instead of having a Circle and
Rectangle class then you used String's in formats:
   "C(x,y,r)"
   "R(x,y,w,h)"

Would anyone consider that good OOP? I doubt it!

Arne

[toc] | [prev] | [next] | [standalone]


#35801

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-10-17 18:58 +0200
Message-ID<nu2vv1$ikt$1@newsreader4.netcologne.de>
In reply to#35792
Responding to Arne Vajhøj:
> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>
>> [...]
>>> But that code is not using String as version
>>
>> Erm... how about this? :) I don't see how this is less OO-ish than the
>> previous one, but hey... okay!...:
>>
>>         List<String> versions = new ArrayList<String>();
>>
>>         versions.add("1.9.0-123");
>>         versions.add("1.10.0-123");
>>         versions.add("1.7.0-123");
>>         versions.add("1.7.0-123");
>>         versions.add("1.7.0-10");
>>         versions.add("1.7.0-9");
>>
>>         Collections.sort(versions, new VersionComparator());
>>
>> ...
>>
>> static class VersionComparator implements Comparator<String> {
> 
>>         public int compare(String version1, String version2) {
>>             try {
>>                 ParsedVersion pv1 = parse(version1);
>>                 ParsedVersion pv2 = parse(version2);
>>                 if (pv1.equals(pv2)) return 0;
>>                 if (pv1.lessThan(pv2)) return -1;
>>                 return 1;
>>             } catch (InvalidVersionException e) {
>>                 throw new IllegalArgumentException(e);
>>             }
>>         }
> 
> Having data and methods operating on the data separate is
> very non-OO'ish in my book.

I don't think this describes the actual problem well. There may be
perfectly good, OO-compatible reasons to separate comparison logic from
the domain class - after all, that's why Comparator exists. For example,
there may be occasions when one wants to compare only based on the major
(major + minor,...) version parts.

But this code defies a more general programming principle: Describe your
concepts as dedicated types and define operations for those types.
Passing an opaque string around to be interpreted as a version only
"when needed" feels fishy to me in any paradigm.

With this approach, one has to rely on variable names and comments to
know what the string is supposed to represent. It is inefficient,
because one is bound to re-parse on every comparison. And there's no
easy way of knowing whether a given variable holds a valid version
number or whether one has to be prepared for an exception upon
comparison. With a dedicated Version type, you parse once at whatever
boundary the string enters the system, and from then on you have a
guaranteed valid version with a "speaking" type that can be compared
efficiently and that can easily be extended with other version-specific
functionality in future, erm, versions.

Best regards,
Patrick

[toc] | [prev] | [next] | [standalone]


#35804

From4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid>
Date2016-10-17 20:32 +0100
Message-ID<nu38vj$pf6$2@dont-email.me>
In reply to#35801
On 17/10/2016 17:58, Patrick Roemer wrote:

[...]
> Passing an opaque string around to be interpreted as a version only
> "when needed" feels fishy to me in any paradigm.

I agree that having a 'Version' class (as shown in my first example) is 
generally better. However, I do not fully agree with not having opaque 
information, in general.

I believe that there has to be a certain "axiomatic" level with any data 
structure. If you have the following:

Double speed = 1.5;
Double height = 1.5;
Double size = 1.5;

it is perfectly legit to have:

String version = "10.10.10"
String name = "John"
String email = "john@somedomain.com"

I might not always want to have a class for speed, a class for height, a 
class for size, etc.. each with its own validation rules. Schools of 
thought, maybe :)

-- 
4ndre4

[toc] | [prev] | [next] | [standalone]


#35806

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-10-17 23:21 +0200
Message-ID<nu3fc6$uig$1@newsreader4.netcologne.de>
In reply to#35804
Responding to 4ndre4:
> On 17/10/2016 17:58, Patrick Roemer wrote:
> 
> [...]
>> Passing an opaque string around to be interpreted as a version only
>> "when needed" feels fishy to me in any paradigm.
> 
> I agree that having a 'Version' class (as shown in my first example) is 
> generally better. However, I do not fully agree with not having opaque 
> information, in general.

Fundamentalism is always bad. ;)

> I believe that there has to be a certain "axiomatic" level with any data 
> structure. If you have the following:
> 
> Double speed = 1.5;
> Double height = 1.5;
> Double size = 1.5;
> 
> it is perfectly legit to have:
> 
> String version = "10.10.10"
> String name = "John"
> String email = "john@somedomain.com"
> 
> I might not always want to have a class for speed, a class for height, a 
> class for size, etc.. each with its own validation rules. Schools of 
> thought, maybe :)

The limits of our language are the limits of our world. :)

Most languages, including Java, simply don't allow the introduction of
cheap, ad hoc derived data types. If there were a way to declare a
Distance type derived from double that inherits the full double algebra
and incurs no runtime (Un-)Boxing overhead and minimal coding overhead,
there'd be every reason to do so. This is a limitation of our tools, not
a conceptually unreasonable thing.

Your argument holds as long as the overhead of a dedicated type
outweighs its benefits. If you never take an email address apart and
only use it as a string, by all means stick with String as the type. But
in the Version case everything, even performance considerations
(re-parsing!), seems to speak for the dedicated type.

Best regards,
Patrick

[toc] | [prev] | [next] | [standalone]


#35838

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-19 21:38 -0400
Message-ID<nu9776$far$1@gioia.aioe.org>
In reply to#35804
On 10/17/2016 3:32 PM, 4ndre4 wrote:
> On 17/10/2016 17:58, Patrick Roemer wrote:
>
> [...]
>> Passing an opaque string around to be interpreted as a version only
>> "when needed" feels fishy to me in any paradigm.
>
> I agree that having a 'Version' class (as shown in my first example) is
> generally better. However, I do not fully agree with not having opaque
> information, in general.
>
> I believe that there has to be a certain "axiomatic" level with any data
> structure. If you have the following:
>
> Double speed = 1.5;
> Double height = 1.5;
> Double size = 1.5;
>
> it is perfectly legit to have:
>
> String version = "10.10.10"
> String name = "John"
> String email = "john@somedomain.com"
>
> I might not always want to have a class for speed, a class for height, a
> class for size, etc.. each with its own validation rules. Schools of
> thought, maybe :)

There is a big difference between the two examples.

In the double example most of the required semantics exist
in the Double type.

In the version example significant logic about how to actually process
the format has to be added elsewhere.

Arne

[toc] | [prev] | [next] | [standalone]


#35839

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-19 21:47 -0400
Message-ID<nu97n6$fs1$1@gioia.aioe.org>
In reply to#35801
On 10/17/2016 12:58 PM, Patrick Roemer wrote:
> Responding to Arne Vajhøj:
>> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>>
>>> [...]
>>>> But that code is not using String as version
>>>
>>> Erm... how about this? :) I don't see how this is less OO-ish than the
>>> previous one, but hey... okay!...:
>>>
>>>         List<String> versions = new ArrayList<String>();
>>>
>>>         versions.add("1.9.0-123");
>>>         versions.add("1.10.0-123");
>>>         versions.add("1.7.0-123");
>>>         versions.add("1.7.0-123");
>>>         versions.add("1.7.0-10");
>>>         versions.add("1.7.0-9");
>>>
>>>         Collections.sort(versions, new VersionComparator());
>>>
>>> ...
>>>
>>> static class VersionComparator implements Comparator<String> {
>>
>>>         public int compare(String version1, String version2) {
>>>             try {
>>>                 ParsedVersion pv1 = parse(version1);
>>>                 ParsedVersion pv2 = parse(version2);
>>>                 if (pv1.equals(pv2)) return 0;
>>>                 if (pv1.lessThan(pv2)) return -1;
>>>                 return 1;
>>>             } catch (InvalidVersionException e) {
>>>                 throw new IllegalArgumentException(e);
>>>             }
>>>         }
>>
>> Having data and methods operating on the data separate is
>> very non-OO'ish in my book.
>
> I don't think this describes the actual problem well. There may be
> perfectly good, OO-compatible reasons to separate comparison logic from
> the domain class - after all, that's why Comparator exists. For example,
> there may be occasions when one wants to compare only based on the major
> (major + minor,...) version parts.

The problem is not so much with the Comparator.

As you say then it is perfectly valid to have an external
Comparator that matches the logic in the code doing the sort
(or whatever).

The problem is with the parse code that is very much tied to the
internal structure of the String.

Having that parse code in many different places will be a
maintenance nightmare.

And if the ParsedVersion and the parse code is made public
and reused then we have the Version class back and there
is little reason to use the String format except for
input and output.

> But this code defies a more general programming principle: Describe your
> concepts as dedicated types and define operations for those types.
> Passing an opaque string around to be interpreted as a version only
> "when needed" feels fishy to me in any paradigm.

That is very aligned with OOP.

But yes - you could do something sort of similar procedural even
though it may start to be more like OOP in a non-OO language then.

Arne

[toc] | [prev] | [next] | [standalone]


#35849

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-10-20 15:01 +0200
Message-ID<nuaf6r$eop$1@newsreader4.netcologne.de>
In reply to#35839
Responding to Arne Vajhøj:
> On 10/17/2016 12:58 PM, Patrick Roemer wrote:
>> Responding to Arne Vajhøj:
>>> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>>>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>>>
>>>> [...]
>>>>> But that code is not using String as version
>>>>
>>>> Erm... how about this? :) I don't see how this is less OO-ish than the
>>>> previous one, but hey... okay!...:
>>>>
>>>>         List<String> versions = new ArrayList<String>();
>>>>
>>>>         versions.add("1.9.0-123");
>>>>         versions.add("1.10.0-123");
>>>>         versions.add("1.7.0-123");
>>>>         versions.add("1.7.0-123");
>>>>         versions.add("1.7.0-10");
>>>>         versions.add("1.7.0-9");
>>>>
>>>>         Collections.sort(versions, new VersionComparator());
>>>>
>>>> ...
>>>>
>>>> static class VersionComparator implements Comparator<String> {
>>>
>>>>         public int compare(String version1, String version2) {
>>>>             try {
>>>>                 ParsedVersion pv1 = parse(version1);
>>>>                 ParsedVersion pv2 = parse(version2);
>>>>                 if (pv1.equals(pv2)) return 0;
>>>>                 if (pv1.lessThan(pv2)) return -1;
>>>>                 return 1;
>>>>             } catch (InvalidVersionException e) {
>>>>                 throw new IllegalArgumentException(e);
>>>>             }
>>>>         }
>>>
>>> Having data and methods operating on the data separate is
>>> very non-OO'ish in my book.
>>
>> I don't think this describes the actual problem well. There may be
>> perfectly good, OO-compatible reasons to separate comparison logic from
>> the domain class - after all, that's why Comparator exists. For example,
>> there may be occasions when one wants to compare only based on the major
>> (major + minor,...) version parts.
> 
> The problem is not so much with the Comparator.
> 
> As you say then it is perfectly valid to have an external
> Comparator that matches the logic in the code doing the sort
> (or whatever).
> 
> The problem is with the parse code that is very much tied to the
> internal structure of the String.
> 
> Having that parse code in many different places will be a
> maintenance nightmare.
>
> And if the ParsedVersion and the parse code is made public
> and reused then we have the Version class back and there
> is little reason to use the String format except for
> input and output.

Agreed. But I wouldn't necessarily want to have the parse code in the
Version class, either. There may be different string formats from
different sources ("1.2.3.4" vs "1.2.3-004"), or there may even be other
representations than strings I want to convert from. Having just a plain
Version(int, int, int, int) constructor and offloading parsing to
dedicated classes might be a reasonable choice, and it'd still be in
line with OO principles. The main problem with the given code isn't
having methods and data separate, it's not having a Version type, and
that's not an OO specific problem.

>> But this code defies a more general programming principle: Describe your
>> concepts as dedicated types and define operations for those types.
>> Passing an opaque string around to be interpreted as a version only
>> "when needed" feels fishy to me in any paradigm.
> 
> That is very aligned with OOP.
> 
> But yes - you could do something sort of similar procedural even
> though it may start to be more like OOP in a non-OO language then.

In proper procedural, you'd have a Version record type and procedures
acting upon it. In proper functional you'd have a Version data type and
functions acting upon it. That's an overarching principle, nothing
specific to OO.

Here's a functional semantic version library, for example:

https://hackage.haskell.org/package/semver-0.3.3.1/docs/Data-SemVer.html

Using a String as a version representation would be as silly there as
anywhere else. And if you suggested to the Haskell guys that they were
emulating OO, they'd laugh you out of the room.

Best regards,
Patrick

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.java.programmer


csiph-web