January 13, 2022
On Thursday, 13 January 2022 at 17:57:58 UTC, bauss wrote:
> Basically what you said, as the sane thing is working with pure UTC and just offsetting it by the timezone and only actually accounting for timezone when you need to display the time to some user.

This is a common myth.

It works ok for times in the past, but it drops important information for times in the future.
January 14, 2022

On Thursday, 13 January 2022 at 00:59:49 UTC, Mike Parker wrote:

>

On Wed, Jan 12, 2022 at 08:26:17PM +0000, Dom DiSc via Digitalmars-d wrote:
[...]

>

By far the most classes will contain non-comparable values, because
there is only a few "completely ordered" things out there, and most of
them like simple numbers are already implemented.

This makes me question the wisdom of putting opCmp in the common base of
all classes. If only a small subset of classes will be comparable with
each other

This is a misunderstanding.
First of all, you don't compare classes, but objects (instances) of the same class.
And the majority of objects may well be comparable.
My argument was: Nearly every class will contain some (most times even only very few) objects that can not be compared to others. This means: The class is not completely ordered, but still partially ordered. And we need a value to express this non-comparability.
And comparison is very important in most classes, even if they are only partially ordered, so having a common interface for that (and I mean: identical in every class, so e.g. always returning the same type, namely the 4 float-values -1, 0, 1 and NaN) is very important.

January 14, 2022

On Friday, 14 January 2022 at 01:48:06 UTC, Dom DiSc wrote:

>

returning the same type, namely the 4 float-values -1, 0, 1 and NaN is very important.

And by the way, using float instead of int does no harm, as both are 32bit types so they waste the same memory to store two bit of information.
And if you don't need the NaN value because your class is totally ordered, simply don't use it. Just be glad that it's there, because most of the time you will learn later that your class is not as totally ordered as you thought at first glance.

January 14, 2022
On Friday, 14 January 2022 at 01:59:19 UTC, Dom DiSc wrote:
> you will learn later that your class is not as totally ordered as you thought at first glance.

enum PartialOrdering { Less, Equal, Greater, Indeterminate }
enum TotalOrdering { Less, Equal, Greater }
interface PartiallyOrdered { PartialOrdering cmp(PartiallyOrdered other); }
interface TotallyOrdered { TotalOrdering cmp(TotallyOrdered other); }
January 13, 2022
On Fri, Jan 14, 2022 at 01:48:06AM +0000, Dom DiSc via Digitalmars-d wrote: [...]
> > This makes me question the wisdom of putting opCmp in the common base of all classes.  If only a small subset of classes will be comparable with each other
> 
> This is a misunderstanding.
> First of all, you don't compare classes, but objects (instances) of
> the same class.
> And the majority of objects may well be comparable.
[...]

Majority? Hardly.  How should opCmp for std.stdio.File be defined?  What does it even mean for one File to be "less than" another?  What about a Socket?  What about a Widget or Window? What about a ServerConnection? What about an ObjectFactory?  What kind of order can be meaningfully imposed on objects of such classes?

In the universe of things one might want to define classes for, only a narrow subset are meaningfully (partially) orderable.  And among them, an even narrower subset is linearly-orderable (mostly just user-defined numerical types and number-like objects).  Even std.complex.Complex does not have any meaningful order (except for the very narrow case where the imaginary part is zero).

A base class should generally encapsulate functionality common to ALL subclasses.  If most classes are not meaningfully orderable (File, Socket, Widget, Connection, Factory, Complex), then why are we shoehorning opCmp into the base class of ALL classes?


T

-- 
Unix is my IDE. -- Justin Whear
January 14, 2022
On Friday, 14 January 2022 at 02:22:13 UTC, H. S. Teoh wrote:
> On Fri, Jan 14, 2022 at 01:48:06AM +0000, Dom DiSc via Digitalmars-d wrote: [...]
>> > This makes me question the wisdom of putting opCmp in the common base of all classes.  If only a small subset of classes will be comparable with each other
>> 
>> This is a misunderstanding.
>> First of all, you don't compare classes, but objects (instances) of
>> the same class.
>> And the majority of objects may well be comparable.
> [...]
>
> Majority? Hardly.  How should opCmp for std.stdio.File be defined?
Oh, come on. Every browser need to order files. Of course there are endless different orders (by size, by name, by date, ...) but there IS an order  - and one need to be applied if you want to show the user a list. How else can you create a list other than creating an order?!?

> What does it even mean for one File to be "less than" another?
It means it should be shown before the other one in a list.
And this also makes clear why this order is only partial, because maybe you have some filter. All files filtered out are non-comparable to ones within the list, because they are not shown, neither before nor after. And of course they are not equal.

>  What about a Socket?
Any kind of ID?

> What about a Widget or Window?
z-Order? - at least for windows that really matters.

> What about a ServerConnection?
Priority?

> What about an ObjectFactory?
Nah, maybe for something too generic order doesn't matter so much, but at least for the majority of your examples there were meaningful orders, don't you think?

January 14, 2022

On Monday, 10 January 2022 at 13:48:14 UTC, Mike Parker wrote:

>

This is the discussion thread for the first round of Community Review of DIP 1042, "ProtoObject":

https://github.com/dlang/DIPs/blob/2e6d428f42b879c0220ae6adb675164e3ce3803c/DIPs/DIP1042.md

One issue with this DIP that I haven't noticed anyone else raise yet is interface bloat. Each interface directly implemented by a class or any of its super classes adds size_t.sizeof to the instance size:

module app;

import std.stdio : writeln;

interface Stringify { }
interface Hash { }
interface Ordered { }
interface Equals { }

class D : Stringify, Hash, Ordered, Equals { }

void main() {
    writeln("Object instance size: ", __traits(classInstanceSize, Object));
    writeln("D instance size: ", __traits(classInstanceSize, D));
}

Output:

Object instance size: 16
D instance size: 48

We care enough about minimizing instance size to fret about 8 bytes wasted on an unused mutex, but then burden all new-style classes that need full compatibility with the standard library with up to 32 bytes of interface implementations. This does not seem like an improvement to me.

Single method interfaces are an anti-pattern for lightweight classes, given how D implements interfaces.

January 13, 2022
On Fri, Jan 14, 2022 at 03:04:28AM +0000, Dom DiSc via Digitalmars-d wrote:
> On Friday, 14 January 2022 at 02:22:13 UTC, H. S. Teoh wrote:
[...]
> > Majority? Hardly.  How should opCmp for std.stdio.File be defined?
>
> Oh, come on. Every browser need to order files. Of course there are endless different orders (by size, by name, by date, ...) but there IS an order  - and one need to be applied if you want to show the user a list. How else can you create a list other than creating an order?!?

A File does not have an inherent order; an *directory entry* may have one of several possible orders imposed upon it.  You create a list by defining an external ordering (by name, by date, by size, etc.). The file itself is not inherently orderable, and therefore the ordering does not belong in the class.


> > What does it even mean for one File to be "less than" another?
>
> It means it should be shown before the other one in a list.

Yes, it means "less than" **according to some externally-defined order**. The ordering is external to the file, and not inherent to it. This is why there are multiple possible orders.  Which of them should File.opCmp use?


> And this also makes clear why this order is only partial, because maybe you have some filter. All files filtered out are non-comparable to ones within the list, because they are not shown, neither before nor after. And of course they are not equal.

Your mention of "filter" makes it clear that the order does not belong in the File class; it belongs in another object that represents an entry in a list of files. A filter is something you use to impose an order on a collection of unordered objects; it's not something inherent to the object itself. Therefore, std.stdio.File should not have an .opCmp defined for it.


> >  What about a Socket?
> Any kind of ID?

Again, that's imposing an external order to something that inherently doesn't have one. You can sort a list of sockets by last access time, connection speed, lexicographic IP address, etc., but these are external orders imposed upon the Socket, not an inherent order.


> > What about a Widget or Window?
> z-Order? - at least for windows that really matters.

Also an external order.


> > What about a ServerConnection?
> Priority?

Ditto.


> > What about an ObjectFactory?
> Nah, maybe for something too generic order doesn't matter so much, but at least for the majority of your examples there were meaningful orders, don't you think?

No, they are not inherently orderable, the orderings you mentions are external orders imposed on them.  An external order should be defined by an external predicate that compares two objects (this is why std.algorithm.sort takes a predicate, btw), not in the .opCmp which defines an *inherent* order.  You can order complex numbers by magnitude, for example, but that does not mean they are inherently orderable.


T

-- 
If creativity is stifled by rigid discipline, then it is not true creativity.
January 14, 2022
On Friday, 14 January 2022 at 03:41:49 UTC, H. S. Teoh wrote:

> No, they are not inherently orderable, the orderings you mentions are external orders imposed on them.
Nothing is inherently ordered. The order is always some new property given to the object in question. Numbers are nothing then a (unordered) set plus an order given to them (an axiom on its own). The order is never "inherent" and there are always endless different ways to assign an order to a set of objects.
The important part is: it is mostly useful to do so (assigning a specific order to a set of objects), thereby making from a set an ordered set.
And especially on computers a set always need at least some "default" order (e.g. address), otherwise you cannot access its elements.
But I agree that it is useful to have a way to assign some predicate to a class by which its instances should be ordered (at least if you don't like the default order: the memory address where it is stored), but that need not be a member function, so I omitted it.
January 14, 2022

On Friday, 14 January 2022 at 03:38:28 UTC, tsbockman wrote:

>

On Monday, 10 January 2022 at 13:48:14 UTC, Mike Parker wrote:

>

This is the discussion thread for the first round of Community Review of DIP 1042, "ProtoObject":

https://github.com/dlang/DIPs/blob/2e6d428f42b879c0220ae6adb675164e3ce3803c/DIPs/DIP1042.md

One issue with this DIP that I haven't noticed anyone else raise yet is interface bloat. Each interface directly implemented by a class or any of its super classes adds size_t.sizeof to the instance size:

module app;

import std.stdio : writeln;

interface Stringify { }
interface Hash { }
interface Ordered { }
interface Equals { }

class D : Stringify, Hash, Ordered, Equals { }

void main() {
    writeln("Object instance size: ", __traits(classInstanceSize, Object));
    writeln("D instance size: ", __traits(classInstanceSize, D));
}

Output:

Object instance size: 16
D instance size: 48

We care enough about minimizing instance size to fret about 8 bytes wasted on an unused mutex, but then burden all new-style classes that need full compatibility with the standard library with up to 32 bytes of interface implementations. This does not seem like an improvement to me.

Single method interfaces are an anti-pattern for lightweight classes, given how D implements interfaces.

This is a very important point because in general that could bloat your memory by A LOT. In your example the bloat is 3 times as much. So I'n going to guess this DIP in reality will add maybe 2-3 times as much bloat when implemented with functionality within those interfaces etc.

That's just terrible.