Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 17:19:11 UTC, Adam D. Ruppe wrote:
You could conceivably write a child class that wraps or 
converts. For example, perhaps:


class Serializer {
void serialize(Serializable s) {}
}

class ExtendedSerializer: Serializer {
override void serialize(Object o) {
super.serialize(reflectToSerializable(o));
}
}



But you can't do that in D either, or? (I am ok with it, having 
invariant parameters is an ok tradeoff).





Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 17:17:15 UTC, Meta wrote:
Which is still open, but Iain ran into stack corruption issues 
when compiling with the -m64 flag... and no further progress. 
So I guess it's just a matter of the bug not being fixed.


That's surprising. It could perhaps just use my pattern 
automatically and have a simpler implementation :)


Re: interfaces and contracts - new pattern

2019-12-03 Thread Meta via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 17:10:04 UTC, Meta wrote:

On Monday, 2 December 2019 at 20:30:49 UTC, Adam D. Ruppe wrote:
In short use `in(false)` when you `override` a function to 
inherit the contract, unless you explicitly want to expand the 
input - which you shouldn't do when implementing an interface!


Wrote about it in more details here:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_12_02.html

i think this is a pretty cool little discovery, thanks too for 
the folks on irc for chatting it through.


destroy if i missed anything lol


I thought this was a defect that was fixed a long time ago, 
where if the overriding function has no contract, it is 
implicitly given a "in (true)" contract, causing the contract 
of the overridden function to not be run. Am I mistaken as to 
what the defect was, or as to whether it was fixed, or both?


I think this is the defect in question:
https://issues.dlang.org/show_bug.cgi?id=6856

I see a PR in comment 35: https://github.com/dlang/dmd/pull/4200

But it was closed. However, Iain Buclaw created a successor to 
4200:

https://github.com/dlang/dmd/pull/7510

Which is still open, but Iain ran into stack corruption issues 
when compiling with the -m64 flag... and no further progress. So 
I guess it's just a matter of the bug not being fixed.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 17:10:04 UTC, Meta wrote:
Am I mistaken as to what the defect was, or as to whether it 
was fixed, or both?


I don't think they ever changed it - the code in the original 
link there shows the current behavior.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 16:03:18 UTC, Ola Fosheim Grøstad 
wrote:

But this doesn't work in D.


That's my point - it is unsound in the static type system and D 
correctly rejects it. Might work in a dynamic language, but not 
in static.


Yes, but when do you need to do it? So it is typesafe, but what 
would the use case be?


You could conceivably write a child class that wraps or converts. 
For example, perhaps:


class Serializer {
void serialize(Serializable s) {}
}

class ExtendedSerializer: Serializer {
override void serialize(Object o) {
super.serialize(reflectToSerializable(o));
}
}

I probably wouldn't do it that way... and I can't think of a time 
I actually used this myself which is why I had to make something 
up. But still, it conceivably makes sense.


I've got a feeling that one could do something interesting with 
such semantics that would make all this variance-stuff 
cleaner... somehow. But I haven't given it a lot of thought. 
Just a feeling. :)


Maybe, I haven't thought a lot of it.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Meta via Digitalmars-d-announce

On Monday, 2 December 2019 at 20:30:49 UTC, Adam D. Ruppe wrote:
In short use `in(false)` when you `override` a function to 
inherit the contract, unless you explicitly want to expand the 
input - which you shouldn't do when implementing an interface!


Wrote about it in more details here:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_12_02.html

i think this is a pretty cool little discovery, thanks too for 
the folks on irc for chatting it through.


destroy if i missed anything lol


I thought this was a defect that was fixed a long time ago, where 
if the overriding function has no contract, it is implicitly 
given a "in (true)" contract, causing the contract of the 
overridden function to not be run. Am I mistaken as to what the 
defect was, or as to whether it was fixed, or both?


Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 16:03:18 UTC, Ola Fosheim Grøstad 
wrote:
comes to virtual function parameters. Then again, I think 
overriding the implementation of the subclass is kinda ugly.


That made no sense, I meant superclass...



Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 15:25:19 UTC, Adam D. Ruppe wrote:
On the parameters side it is a little more confusing, but it 
still makes sense:


abstract class Generic {
void generic(Generic g);
}

class Specialized : Generic {
override void generic(Specialized g) {}
}


But this doesn't work in D.



There you can see the obvious problem:

Generic g = new Specialized();
Generic other = new SomethingElse();
g.generic(other); // uh oh, interface allows it but 
specialization doesn't


It could have resolved it by calling the Generic.generic(...) 
method then the Specialized.generic could have tested it... but 
it gets messy.


Makes more sense for a dynamic language, I guess.


class Specialized : Generic {
override void generic(Object g) {}
}

since Generic implicitly casts back to Object, it is clear 
anything from the interface can also go to the child, so you're 
fine.


Yes, but when do you need to do it? So it is typesafe, but what 
would the use case be?


It does make sense if you think about it, just it is weird if 
you don't.


Sure, but it seems to me that something is missing when it comes 
to virtual function parameters. Then again, I think overriding 
the implementation of the subclass is kinda ugly. Some languages 
(at least one),  force you to call the super class virtual method 
as a wrapper around the subclass virtual method specialization. 
So basically the superclass gets to "look at" and act on the 
parameters before the subclass does.


I've got a feeling that one could do something interesting with 
such semantics that would make all this variance-stuff cleaner... 
somehow. But I haven't given it a lot of thought. Just a feeling. 
:)




Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 15:26:10 UTC, Ola Fosheim Grøstad 
wrote:

Also the use of the term "covariant" here is confusing to me:


Yeah, to be honest, I forget what the terms mean, so I tend to 
avoid them. like my last email just talked about specialization 
and implicit casts which I think we all understand better anyway 
:)


Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 15:12:46 UTC, Ola Fosheim Grøstad 
wrote:
But I was thinking of contravariant/covariant parameters on 
virtual functions.


those too. I mostly use it with things like a clone method:

interface Cloneable {
Cloneable clone();
}

class MyClass : Cloneable {
override MyClass clone() { return new Myclass(); }
}


That is fairly intuitive for return values - MyClass is an 
instance of the interface so of course you should be able to 
return it! It just lets you specialize.



On the parameters side it is a little more confusing, but it 
still makes sense:


abstract class Generic {
void generic(Generic g);
}

class Specialized : Generic {
override void generic(Specialized g) {}
}


There you can see the obvious problem:

Generic g = new Specialized();
Generic other = new SomethingElse();
g.generic(other); // uh oh, interface allows it but 
specialization doesn't




But that's also why you can loosen.

class Specialized : Generic {
override void generic(Object g) {}
}

since Generic implicitly casts back to Object, it is clear 
anything from the interface can also go to the child, so you're 
fine.


And if you do call the `super.generic`, you get the explicit cast 
requirement which is OK, since it happens in the implementation's 
body.


And then contracts follow the same rules...


It does make sense if you think about it, just it is weird if you 
don't.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 15:12:46 UTC, Ola Fosheim Grøstad 
wrote:
On Tuesday, 3 December 2019 at 14:51:58 UTC, Adam D. Ruppe 
wrote:

Maybe, but it is pretty sound once you get to know it.


You mean contracts? Yes. But I was thinking of 
contravariant/covariant parameters on virtual functions. 
Doesn't work with overloading though, so D only has it on 
return types? Probably for the best. Perhaps.


Also the use of the term "covariant" here is confusing to me:

https://dlang.org/spec/function.html

My understanding is that covariant means that an enclosing type 
and the enclosed type have the same typing-relationship when 
specialized. Whereas contravariant means they are opposite. So 
you need two types for it to make sense. I.e. the schematic here:


https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Inheritance_in_object-oriented_languages

But it the documentation "covariant" is used to describe a simple 
subtyping-relationship on one type?


Anyway, the wording is confusing. I think it would be hard on 
newbies, even if it was correctly used.




Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 14:51:58 UTC, Adam D. Ruppe wrote:

Maybe, but it is pretty sound once you get to know it.


You mean contracts? Yes. But I was thinking of 
contravariant/covariant parameters on virtual functions. Doesn't 
work with overloading though, so D only has it on return types? 
Probably for the best. Perhaps.




Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 14:45:28 UTC, Ola Fosheim Grøstad 
wrote:
Maybe also test with D interfaces? I suppose they have the same 
behaviour as superclasses?


Yeah, I did that (there's a unittest in the blog source for it, 
that's what shows under the example section). It works nicely.


I just assumed a null contract in the parent was the same as 
in(true) and it isn't so ugh.


Anyway, I think most programmers struggle with 
covariant/contravariant parameters... I certainly have to stop 
up and ponder for a while to figure out the semantics when 
hitting such. So I tend to avoid it... :-P :-)


Maybe, but it is pretty sound once you get to know it.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 14:40:21 UTC, Adam D. Ruppe wrote:
h geeze I was so focused on inheriting the contract that I 
didn't even test if it didn't have one at all. So we need a


Maybe also test with D interfaces? I suppose they have the same 
behaviour as superclasses?


Anyway, I think most programmers struggle with 
covariant/contravariant parameters... I certainly have to stop up 
and ponder for a while to figure out the semantics when hitting 
such. So I tend to avoid it... :-P :-)






Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 14:24:15 UTC, Robert M. Münch 
wrote:

My point was, when the superclass doesn't has an in() contract:

Error: function contracts.Derived.test cannot have an in 
contract when overridden function contracts.Base.test does not 
have an in contract


h geeze I was so focused on inheriting the contract that I 
didn't even test if it didn't have one at all. So we need a 
language change anyway.


ugh.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 10:39:08 UTC, Robert M. Münch 
wrote:
In large scale projects this will become a big problem as you 
can't assume that every developer knows about all the contracts 
of a superclass.


Yes, like if you just want to constrain a signed int to be >=1. 
If you forget to add it in the subclass it suddenly takes 
negative ints with no warning...




Re: interfaces and contracts - new pattern

2019-12-03 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 3 December 2019 at 10:39:08 UTC, Robert M. Münch 
wrote:
In large scale projects this will become a big problem as you 
can't assume that every developer knows about all the contracts 
of a superclass.


That's the beauty of `override in(false)` - you don't have to 
know about the superclass. You can use it and it works in all 
cases.


Though that's also a possible argument for the language change.


Re: interfaces and contracts - new pattern

2019-12-03 Thread Robert M. Münch via Digitalmars-d-announce

On 2019-12-03 07:53:48 +, Ola Fosheim Grøstad said:


On Tuesday, 3 December 2019 at 02:57:13 UTC, Adam D. Ruppe wrote:

On Monday, 2 December 2019 at 22:31:08 UTC, Ola Fosheim Grøstad wrote:

Interesting, could be useful, but now you have to remember to add "in(false)".


Yeah, it is kinda tempting to propose a language change, where an 
override method does this by default if nothing else is specified. I 
think it would probably usually be the right thing to do, and then 
you'd opt into extending it all the way by doing `in(true)` instead.


Yes, I agree, if you forget to add a specification then it probably 
should have the same strictness as the superclass. That is what I would 
expect.


+1 having to add something explicit to get the superclass contract 
activated looks weired.


In large scale projects this will become a big problem as you can't 
assume that every developer knows about all the contracts of a 
superclass.


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: interfaces and contracts - new pattern

2019-12-02 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Tuesday, 3 December 2019 at 02:57:13 UTC, Adam D. Ruppe wrote:
On Monday, 2 December 2019 at 22:31:08 UTC, Ola Fosheim Grøstad 
wrote:
Interesting, could be useful, but now you have to remember to 
add "in(false)".


Yeah, it is kinda tempting to propose a language change, where 
an override method does this by default if nothing else is 
specified. I think it would probably usually be the right thing 
to do, and then you'd opt into extending it all the way by 
doing `in(true)` instead.


Yes, I agree, if you forget to add a specification then it 
probably should have the same strictness as the superclass. That 
is what I would expect.





Re: interfaces and contracts - new pattern

2019-12-02 Thread Adam D. Ruppe via Digitalmars-d-announce
On Monday, 2 December 2019 at 22:31:08 UTC, Ola Fosheim Grøstad 
wrote:
Interesting, could be useful, but now you have to remember to 
add "in(false)".


Yeah, it is kinda tempting to propose a language change, where an 
override method does this by default if nothing else is 
specified. I think it would probably usually be the right thing 
to do, and then you'd opt into extending it all the way by doing 
`in(true)` instead.


I wonder if this could somehow be wrapped up in a clean way 
using meta-programming so you always get the "in(false)"?


I don't think so, contracts are invisible to reflection right now 
(unless there's a trick I don't know). Maybe a language change is 
warranted though, I don't really know, especially since this 
thing is possible today.


Re: interfaces and contracts - new pattern

2019-12-02 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 2 December 2019 at 20:30:49 UTC, Adam D. Ruppe wrote:

Wrote about it in more details here:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_12_02.html

i think this is a pretty cool little discovery, thanks too for 
the folks on irc for chatting it through.


Interesting, could be useful, but now you have to remember to add 
"in(false)".


I wonder if this could somehow be wrapped up in a clean way using 
meta-programming so you always get the "in(false)"?




interfaces and contracts - new pattern

2019-12-02 Thread Adam D. Ruppe via Digitalmars-d-announce
In short use `in(false)` when you `override` a function to 
inherit the contract, unless you explicitly want to expand the 
input - which you shouldn't do when implementing an interface!


Wrote about it in more details here:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_12_02.html

i think this is a pretty cool little discovery, thanks too for 
the folks on irc for chatting it through.


destroy if i missed anything lol