applay for template function with sumtypes result?

2023-07-03 Thread kiriakov via Digitalmars-d-learn
Hi. I can't handle template. It all looks sad, build ok, test 
error.


```
struct ParsResult(T) { T[] _in; T[] _out; }
struct Err(T) { T[] x; }

struct Result(T) {
SumType!(ParsResult!T, Err!T) data;
alias data this;
this(Value)(Value value) { data = value; }  
}


Result!T applay(T)(Result!T function (T[]) pure fun, T[] x) pure 
{ return fun(x); }
ParsResult!char f (char[] x) pure { return 
ParsResult!char(x[1..$], x[2..$]); }


unittest
{
writeln(applay(,"String10".dup));
}
```

I got

Error: none of the overloads of template `mexception.pars` are 
callable using argument types `!()(ParsResult!char 
delegate(char[] x) pure nothrow @nogc @safe, char[])`
source/mexception.d(64,10):Candidate is: 
`pars(T)(Result!T function(T[]) pure fun, T[] x)`




Re: "macro" expansion to build switch case code

2023-07-03 Thread Paul via Digitalmars-d-learn
On Sunday, 2 July 2023 at 20:27:47 UTC, Steven Schveighoffer 
wrote:

On 7/2/23 1:02 PM, Paul wrote:

[...]


Use a static foreach:

```d
import std.traits; // for FieldNameTuple. there are other ways, 
but this is the most straightforward

switchlabel: // this is needed for break inside a static foreach
final switch(s) {
   static foreach(mem; FieldNameTuple!myS) {
 case mem ~ mem:
__traits(getMember, this, mem) += n;
break switchalbel;
   }
}
```

-Steve


Perfect.  Thanks Steve!


Re: Inheritance and arrays

2023-07-03 Thread Arafel via Digitalmars-d-learn

On 3/7/23 17:41, Steven Schveighoffer wrote:



If Java works, it means that Java either handles the conversion by 
making a copy, or by properly converting on element fetch/store based on 
type introspection. It also might use a different mechanism to point at 
interfaces.




As I mentioned in another reply, Java does it by adding a runtime check 
to the type at insertion. This is a performance hit, and I'm glad it's 
not done in D.


Also, I think I read in some other thread here that Java uses a single 
pointer for both objects and interfaces, but I think the biggest issue 
here is the covariance.


I find it most unexpected and confusing and, assuming it won't change 
anytime soon, I think it should at the very least be **clearly** 
documented. And the cast forbidden, since it can't possible work 
between classes and interfaces.


I want to answer to myself here: it was my knowledge of type theory that 
was lacking: TIL that even if two types are covariant, arrays of them 
needn't be, and usually aren't. So I was spoiled by Java ;-)


[In case somebody else is 
interested](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Arrays) 
(also just google it, there are tons of links on the subject).


On a final note, thanks to everybody who answered! For all its quirks, D 
is a great language that I enjoy using, and the community here is great, 
even if at times it could be a bit more optimistic :-)




Re: Inheritance and arrays

2023-07-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/3/23 7:37 AM, Arafel wrote:
That's very clearly an implementation detail leaking: the semantics of 
the language shouldn't depend on how interfaces and classes are 
implemented.


It's a semantic detail -- casting an array does *not* make a copy, and 
an array is not a complex object. It's just a block of data.


And so it only succeeds if the binary representation can properly be 
reinterpreted.


This is the same for all array types, not just class/interfaces:

```d
int i = 1;
long x = i; // ok
int[] a = [1];
long[] b = a; // error
```

If Java works, it means that Java either handles the conversion by 
making a copy, or by properly converting on element fetch/store based on 
type introspection. It also might use a different mechanism to point at 
interfaces.


You might want it to be similar, but there are tradeoffs. With D, 
though, there is always the possibility of getting what you want by 
adding a specialized type. Indeed, if you are just going to *read* the 
definition, a map would work:


```d
auto ii = cc.map!(function I(C c) => c);
I i = ii[0]; // ok
```

However, if you plan to write the definition as well, you need a more 
specialized type.


It's all doable, though.

I find it most unexpected and confusing and, assuming it won't change 
anytime soon, I think it should at the very least be **clearly** 
documented. And the cast forbidden, since it can't possible work between 
classes and interfaces.


It is documented:
https://dlang.org/spec/arrays.html#implicit-conversions

However, the interface conversion is not covered, and it's a bit 
nebulous as to what is specifically covered with classes/interface.


I think it could be improved.

Honestly, this severely limits the usefulness of interfaces, and for 
hierarchies of classes it might be much better to switch to abstract 
classes.


BTW, even for (abstract) classes you need a cast:


...



Shouldn't `ii = cc` work in this case?


I think this has been discussed in another part of the thread. But I did 
want to point out that an implicit cast to `const` base type array is 
possible (not for interfaces, since the binary representation is different).


-Steve


Re: Inheritance and arrays

2023-07-03 Thread Arafel via Digitalmars-d-learn

On 3/7/23 13:03, Rene Zwanenburg wrote:

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:
Is this a conscious design decision (if so, why?), or just a leak of 
some implementation detail, but that could eventually be made to work?


Besides the pointer adjustment problem mentioned by FeepingCreature, 
it's an unsound conversion even with just class inheritance. Consider:


```
class A {}
class B : A {}
class C : A {}

void main()
{
   auto bArr = [new B()];
   A[] aArr = bArr; // If this was allowed..
   aArr[0] = new C(); // This would be a problem, because bArray would 
now contain a C.

}
```


This is a really good point. I just checked out of curiosity what Java 
does (because it's allowed there).


TIL it throws [an 
exception](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayStoreException.html) 
at runtime, which I guess is not a viable strategy for D.


Although when using interfaces, if I cast the individual class instances 
to interfaces, it should work, right?


Because then I'm storing the pointers to the interfaces, not to the 
actual class, so the arrays are actually different, and not two slices 
of the same array:



```
import std;

interface I { }
class C : I { }

void main() {
C c = new C;
I i = c;

	assert (c is i); // OK, took me a while to notice that "is" is smart 
enough.
assert (cast (void *) c != cast (void *) i); // This is what we 
really care about.


C[] cc = [ c ];
I[] ii;
ii = cc.map!( a => cast (I)a ).array;

assert (ii[0] is c); // This can be unexpected, even if technically 
right!
assert (cast (void*) ii[0] != cast (void*) c); // Now this is what 
we need.

}
```


Re: Inheritance and arrays

2023-07-03 Thread Arafel via Digitalmars-d-learn
That's very clearly an implementation detail leaking: the semantics of 
the language shouldn't depend on how interfaces and classes are implemented.


So then I need to do something like:

```d
ii = cc.map!(a => cast (I) a).array;
```

(I just tested it and it works)

Any reason why it can't be done internally by the language?

I find it most unexpected and confusing and, assuming it won't change 
anytime soon, I think it should at the very least be **clearly** 
documented. And the cast forbidden, since it can't possible work between 
classes and interfaces.


Honestly, this severely limits the usefulness of interfaces, and for 
hierarchies of classes it might be much better to switch to abstract 
classes.


BTW, even for (abstract) classes you need a cast:

```d
import std;

abstract class I {
abstract void foo();
}
class C : I {
this(int i) {
this.i = i;
}
override void foo() {
writeln("In foo: ",i);
}
int i;
}

void main() {
I i;
C c = new C(1);
i = c; // Works

I[] ii;
C[] cc;
cc ~= c;
i.foo();
// ii = cc; // Doesn't work: Error: cannot implicitly convert 
expression `cc` of type `C[]` to `I[]`

ii = cast (I[]) cc; // Compiles, apparently works
//ii = cc.map!(a => cast(I) a).array;
ii[0].foo();
}
```

Shouldn't `ii = cc` work in this case?

On 3/7/23 12:06, FeepingCreature wrote:

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:

Hi!

I am a D user coming from java, rather than from C/C++ (although 
obviously also have some exposure to them), and thus apparently one of 
the few people here who likes OO (within reason, of course).


So while I appreciate the fact that D closely follows java's design, I 
wonder why there is no implicit inheritance for arrays (also the same 
applies to AAs):


```d
interface I {}
class C : I {}

void main() {
    I i;
    C c = null;
    i = c; // Works

    I[] ii;
    C[] cc = null;
    // ii = cc; // Doesn't work: Error: cannot implicitly convert 
expression `cc` of type `C[]` to `I[]`

    ii = cast (I[]) cc; // Works, but why do I need to cast?
}
```


The `cast` version "works", but will crash at runtime.

In D, as opposed to Java, a reference to an object has a *different 
pointer value* than a reference to the interface-typed version of that 
object. This is necessary for efficient compiled virtual method calls on 
the interface. But for the same reason, you cannot reinterpret an array 
of objects to an array of interfaces; even if you can implicitly convert 
each object to that interface, there's a difference between 
automatically rewriting a value and automatically rewriting every 
element of an array: one is O(1), the other is O(n) and incurs a GC 
allocation.




Re: Inheritance and arrays

2023-07-03 Thread Rene Zwanenburg via Digitalmars-d-learn

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:
Is this a conscious design decision (if so, why?), or just a 
leak of some implementation detail, but that could eventually 
be made to work?


Besides the pointer adjustment problem mentioned by 
FeepingCreature, it's an unsound conversion even with just class 
inheritance. Consider:


```
class A {}
class B : A {}
class C : A {}

void main()
{
  auto bArr = [new B()];
  A[] aArr = bArr; // If this was allowed..
  aArr[0] = new C(); // This would be a problem, because bArray 
would now contain a C.

}
```


Re: Inheritance and arrays

2023-07-03 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:

Hi!

I am a D user coming from java, rather than from C/C++ 
(although obviously also have some exposure to them), and thus 
apparently one of the few people here who likes OO (within 
reason, of course).


So while I appreciate the fact that D closely follows java's 
design, I wonder why there is no implicit inheritance for 
arrays (also the same applies to AAs):


```d
interface I {}
class C : I {}

void main() {
I i;
C c = null;
i = c; // Works

I[] ii;
C[] cc = null;
// ii = cc; // Doesn't work: Error: cannot implicitly 
convert expression `cc` of type `C[]` to `I[]`

ii = cast (I[]) cc; // Works, but why do I need to cast?
}
```


The `cast` version "works", but will crash at runtime.

In D, as opposed to Java, a reference to an object has a 
*different pointer value* than a reference to the interface-typed 
version of that object. This is necessary for efficient compiled 
virtual method calls on the interface. But for the same reason, 
you cannot reinterpret an array of objects to an array of 
interfaces; even if you can implicitly convert each object to 
that interface, there's a difference between automatically 
rewriting a value and automatically rewriting every element of an 
array: one is O(1), the other is O(n) and incurs a GC allocation.


Re: Inheritance and arrays

2023-07-03 Thread FeepingCreature via Digitalmars-d-learn

On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:

Hi!

I am a D user coming from java, rather than from C/C++ 
(although obviously also have some exposure to them), and thus 
apparently one of the few people here who likes OO (within 
reason, of course).


So while I appreciate the fact that D closely follows java's 
design, I wonder why there is no implicit inheritance for 
arrays (also the same applies to AAs):


...

Is this a conscious design decision (if so, why?), or just a 
leak of some implementation detail, but that could eventually 
be made to work?


See also this thread on implementation details: 
https://forum.dlang.org/post/bibtjiiwpiqzzfwgx...@forum.dlang.org


Inheritance and arrays

2023-07-03 Thread Arafel via Digitalmars-d-learn

Hi!

I am a D user coming from java, rather than from C/C++ (although 
obviously also have some exposure to them), and thus apparently one of 
the few people here who likes OO (within reason, of course).


So while I appreciate the fact that D closely follows java's design, I 
wonder why there is no implicit inheritance for arrays (also the same 
applies to AAs):


```d
interface I {}
class C : I {}

void main() {
I i;
C c = null;
i = c; // Works

I[] ii;
C[] cc = null;
// ii = cc; // Doesn't work: Error: cannot implicitly convert 
expression `cc` of type `C[]` to `I[]`

ii = cast (I[]) cc; // Works, but why do I need to cast?
}
```

The equivalent java code compiles without issue:

```java
interface I {}
class C implements I {}

public class MyClass {
public static void main(String args[]) {
I i;
C c = null;
i = c; // Works

I[] ii;
C[] cc = null;
ii = cc; // Also works
}
}
```

Is this a conscious design decision (if so, why?), or just a leak of 
some implementation detail, but that could eventually be made to work?