Re: scoped classes and dependency inversion

2018-11-09 Thread Sjoerd Nijboer via Digitalmars-d-learn

On Friday, 9 November 2018 at 09:17:27 UTC, Alex wrote:

Is it this what you are looking for?
https://dlang.org/phobos/std_traits.html#Parameters
I've been looking over std.traits all day yesterday, how could 
I've missed that?
I'm so glad there are people in this forum that want to help out 
others like this. :)





Re: scoped classes and dependency inversion

2018-11-09 Thread Alex via Digitalmars-d-learn

On Friday, 9 November 2018 at 09:13:56 UTC, Sjoerd Nijboer wrote:
On Thursday, 8 November 2018 at 21:16:32 UTC, Sjoerd Nijboer 
wrote:
I tried tom make a lazyscoped!T but I'm stuck at creating a 
constructor and determining the arguments from the Type.


Unfortunately I can't find a way in D to get a list of 
arguments at compile time for a given function. Is this at all 
possible? It sounds like an easy case of introspection.


Is it this what you are looking for?
https://dlang.org/phobos/std_traits.html#Parameters



Re: scoped classes and dependency inversion

2018-11-09 Thread Sjoerd Nijboer via Digitalmars-d-learn
On Thursday, 8 November 2018 at 21:16:32 UTC, Sjoerd Nijboer 
wrote:
I tried tom make a lazyscoped!T but I'm stuck at creating a 
constructor and determining the arguments from the Type.


Unfortunately I can't find a way in D to get a list of arguments 
at compile time for a given function. Is this at all possible? It 
sounds like an easy case of introspection.


Re: scoped classes and dependency inversion

2018-11-08 Thread Sjoerd Nijboer via Digitalmars-d-learn
On Thursday, 8 November 2018 at 16:31:26 UTC, Neia Neutuladh 
wrote:
I believe what you need to do is pass a factory function into 
the constructor. This is a bit awkward.


Yep, but I want a "nice and descriptive syntax" for it.


Anyway, here's some code to make it work. It's kind of ugly.

---
import std.stdio;
import std.typecons;

void main()
{
auto bar = new Bar!Foo((ref f) { f = scoped!Foo(); });
}

class Bar(TFoo) if(is(TFoo : IFoo))
{
alias SFoo = typeof(scoped!TFoo());
SFoo _foo;
this(void delegate(ref SFoo) dg)
{
dg(_foo);
}
}

class Foo : IFoo
{
void baz(){}
}

interface IFoo
{
void baz();
}
---


I tried to get something more nice looking and I'm stuck on the 
following.
I tried tom make a lazyscoped!T but I'm stuck at creating a 
constructor and determining the arguments from the Type. If I 
could do that I could just forward a lazyscoped!T which would 
have my parameters encapsulated to an object and have that object 
instantiate it at its place.
Maybe not the smartest idea but I think it's a little more 
descriptive than using a factory lambda.


```
import std.typecons : scoped;

void main() {
auto initData = 42;
auto bar = new Bar!Foo(lazyscoped!(Foo)(initData));
}

class Bar(TFoo, TArgs...) if(is(TFoo : IFoo)) {
private typeof(scoped!TFoo())  _foo;

this(lazyscoped!TFoo foo) {
foo.construct(_foo);
}
}

class Foo : IFoo {
int orWhatTypeEver;
this(T)(T myParam) {
orWhatTypeEver = /*cast(int)*/myParam;
}
void baz(){}
}
interface IFoo{ void baz(); }

struct lazyscoped(T) {
import std.typecons : scoped;
	TArgs args; // somehow determine TArgs assumimg there is only 
one __ctor of type T.


this(TArgs args) {
static if(TArgs.length > 0)
this.args = args;
}

void construct(ref typeof(scoped!T()) scoped_t) {
scoped_t = scoped!T(args);
}
}```


Re: scoped classes and dependency inversion

2018-11-08 Thread Neia Neutuladh via Digitalmars-d-learn
On Thu, 08 Nov 2018 11:04:19 +, Sjoerd Nijboer wrote:
> I'm trying to invert the dependency from the classes `Bar -> Foo` to
> `Foo -> IFoo <- Bar` at compile time.
> 
> I do want `Foo's` to be embedded into `Bar`

These goals are a *little* at odds with each other; having a scoped!Foo 
puts significant constraints on how to build the object. But you know your 
needs a lot better than some generic advice.

I believe what you need to do is pass a factory function into the 
constructor. This is a bit awkward.

The really annoying part is that std.typecons doesn't have a named type 
for the scoped wrapper for a type. It's actively hostile to having scoped 
fields for no discernable reason. Filed https://issues.dlang.org/
show_bug.cgi?id=19379

Anyway, here's some code to make it work. It's kind of ugly.

---
import std.stdio;
import std.typecons;

void main()
{
auto bar = new Bar!Foo((ref f) { f = scoped!Foo(); });
}

class Bar(TFoo) if(is(TFoo : IFoo))
{
alias SFoo = typeof(scoped!TFoo());
SFoo _foo;
this(void delegate(ref SFoo) dg)
{
dg(_foo);
}
}

class Foo : IFoo
{
void baz(){}
}

interface IFoo
{
void baz();
}
---


Re: scoped classes and dependency inversion

2018-11-08 Thread Neia Neutuladh via Digitalmars-d-learn
On Thu, 08 Nov 2018 12:45:57 +, Alex wrote:
> Hmm... not sure, if I got your idea... Do you think about something like
> this?

The point is dependency inversion. The class shouldn't need to know how to 
build its dependencies; it should leave that to other code. The fact that 
you can use the default constructor to build a thing is more coupling than 
desired.


Re: scoped classes and dependency inversion

2018-11-08 Thread Alex via Digitalmars-d-learn
On Thursday, 8 November 2018 at 15:11:16 UTC, Sjoerd Nijboer 
wrote:
Except if you want to pass a parameter to TFoo it'll become a 
mess.

And I expecially don't want it to become messy.


I thought of this case... But passing the argument to TFoo 
directly while constructing Bar is messier, I think. With the 
solution above you could just:


´´´
import std.stdio;
import std.typecons;

void main()
{
auto initData = 42;
auto bar = new Bar!Foo(initData);
assert(bar._foo.orWhatTypeEver == initData);
}

class Bar(TFoo) if(is(TFoo : IFoo))
{
typeof(scoped!TFoo()) _foo;
this(T)(T fooParam) //if(__traits(compiles, new TFoo(T.init)))
{
_foo = scoped!TFoo(fooParam);
}
}

class Foo : IFoo
{
int orWhatTypeEver;
this(T)(T myParam)
{
orWhatTypeEver = /*cast(int)*/myParam;
}
void baz(){}
}
interface IFoo{ void baz(); }
´´´

In this case, Bar's constructor is not bound to any special type 
of input, letting Foo handle any input you want. Still, the 
solution is type safe.


And, maybe to calm my mind: Bar is the context of Foo, so it is 
allowed to see its inputs...


Re: scoped classes and dependency inversion

2018-11-08 Thread Sjoerd Nijboer via Digitalmars-d-learn

On Thursday, 8 November 2018 at 12:45:57 UTC, Alex wrote:
Hmm... not sure, if I got your idea... Do you think about 
something like this?



 **snip**


class Bar(TFoo) if(is(TFoo : IFoo))
{
typeof(scoped!TFoo()) _foo;
this()
{
_foo = scoped!TFoo();
}
}


Yes, pretty much.
Except if you want to pass a parameter to TFoo it'll become a 
mess.

And I expecially don't want it to become messy.


Re: scoped classes and dependency inversion

2018-11-08 Thread Alex via Digitalmars-d-learn
On Thursday, 8 November 2018 at 11:04:19 UTC, Sjoerd Nijboer 
wrote:
I'm trying to invert the dependency from the classes `Bar -> 
Foo` to `Foo -> IFoo <- Bar` at compile time.


I do want `Foo's` to be embedded into `Bar`

So silly me tried something like this:
[...]

So how can I delay the construction of scoped!Foo that it'll 
end up inside Bar?

If there is a more elegant solution I'm also interested.


Hmm... not sure, if I got your idea... Do you think about 
something like this?


´´´
import std.stdio;
import std.typecons;

void main()
{
auto bar = new Bar!Foo();
}

class Bar(TFoo) if(is(TFoo : IFoo))
{
typeof(scoped!TFoo()) _foo;
this()
{
_foo = scoped!TFoo();
}
}

class Foo : IFoo { void baz(){} }
interface IFoo{ void baz(); }
´´´




scoped classes and dependency inversion

2018-11-08 Thread Sjoerd Nijboer via Digitalmars-d-learn
I'm trying to invert the dependency from the classes `Bar -> Foo` 
to `Foo -> IFoo <- Bar` at compile time.


I do want `Foo's` to be embedded into `Bar`

So silly me tried something like this:
module main;

```import std.stdio;
import std.typecons;

void main()
{
auto bar = new Bar!(scoped!Foo());
}

class Bar (TFoo)
if(is(TFoo == IFoo))
{
scoped!TFoo _foo;
this(scoped!TFoo foo)
{
_foo = foo;
}
}

class Foo : IFoo
{
void baz(){}
}

interface IFoo
{
void baz();
}```

This fails to compile on line 8 since you can't move a scoped!Foo.
So how can I delay the construction of scoped!Foo that it'll end 
up inside Bar?

If there is a more elegant solution I'm also interested.