Re: struct initializer

2023-12-01 Thread Salih Dincer via Digitalmars-d-learn

Hi All,

I feel lonely, just as those who come from C++ find it strange, 
because I think it makes it difficult to read code.


On Friday, 1 December 2023 at 14:53:16 UTC, Paul Backus wrote:


Technically you don't *have* to repeat the type. You can write 
the return type as `auto`:


```d
auto fun() { return S(5, 2); }
```

Or you can use `typeof(return)`:

```d
SomeReallyLongReturnType fun()
{
return typeof(return)(5, 2);
}
```


Paul's example is very readable and short so it's nice. Moreover, 
when there are named parameters in D, what is the need for them. 
While there is so much convenience in D, getting stuck on a very 
simple option...


You decide:
```d
struct Point
{
  int x, y;

  auto opBinary(string  op : "-")(Point that)
  => Point(this.x - that.x, this.y - that.y);

  auto opBinary(string  op : "+")(Point that)
  => Point(this.x + that.x, this.y + that.y);

  auto opBinary(string  op : "*")(Point that)
  => Point(this.x * that.x, this.y * that.y);
  // Moreover, it was possible to do this trio
  // at once with mixin...
}

void main()
{
  auto upperRightCorner = Point(y:768);
  Point x =  { 10, 268  };

  import std.stdio : dout = writeln;

  dout(upperRightCorner - x);
  dots(a: upperRightCorner, b: x).dout;
}

alias dots = differenceOfTwoSquares;
auto differenceOfTwoSquares(Point a, Point b)
  => (a - b)*(a + b);

/*
 * dmd -run "namedParameters.d"
 * Point(-10, 500)
 * Point(-100, 518000)
 */
```
SDB@79


Re: struct initializer

2023-12-01 Thread bomat via Digitalmars-d-learn
I completely agree with the OP, and I want to illustrate this by 
another example which I find quite bizarre:


```
struct S { int a; int b; }
S[] s_list = new S[0];

// this works
S s = { a:1, b:2 };
s_list ~= s;

// this does not
s_list ~= { a:1, b:2 };
```

I'm a C++ programmer in my day job and the very first instinct 
I'd have is to replace the first version by the second to reduce 
verbosity and eliminate an unnecessary copy.


However, for some reason the compiler is not able to deduce the 
type in the second case, so I'm out of luck.


I'm glad to hear that, with a compiler update, I will at least be 
able to do

```
s_list ~= S( a:1, b:2 );
```
instead of
```
s_list ~= S( 1, 2 );
```
but it still seems very inconsistent.


Re: struct initializer

2023-12-01 Thread kdevel via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus wrote:

[...]
If you're using a new enough compiler, it even supports named
arguments:

S3 fun2() { return S3(b: 2, a: 5); }


Indeed. Seems to be in dmd since 2.103.0 (2.102.2 didn't support 
this syntax). Alas, the Change Log [1] remain silent about it.


```
commit 42609ae98e0f72a8d2154da50865bc5182c4b6b3
Author: Dennis https://dlang.org/changelog/2.103.0.html


Re: struct initializer

2023-12-01 Thread Paul Backus via Digitalmars-d-learn

On Friday, 1 December 2023 at 13:02:06 UTC, Dom DiSc wrote:

```d
S Fun(){ return { 5, 2 }; }
```

This IS an initialization and the type is known. Requiring the 
repetition of the type is also here annoying.


Technically you don't *have* to repeat the type. You can write 
the return type as `auto`:


```d
auto fun() { return S(5, 2); }
```

Or you can use `typeof(return)`:

```d
SomeReallyLongReturnType fun()
{
return typeof(return)(5, 2);
}
```


Re: struct initializer

2023-12-01 Thread zjh via Digitalmars-d-learn

On Friday, 1 December 2023 at 13:02:06 UTC, Dom DiSc wrote:


```d
S Fun(){ return { 5, 2 }; }
```

This IS an initialization and the type is known. Requiring the 
repetition of the type is also here annoying.


Right.
The `{}` initialization method in C++ is very useful,I like it 
very much.





Re: struct initializer

2023-12-01 Thread Adam D Ruppe via Digitalmars-d-learn

On Friday, 1 December 2023 at 13:02:06 UTC, Dom DiSc wrote:
Either allow it for all initializations, or get rid of it, like 
DIP 1031 suggested.


I thought the decision actually was made to just get rid of it.


Re: struct initializer

2023-12-01 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 30 November 2023 at 12:15:04 UTC, Dennis wrote:
The syntax was inherited from C. The 'special place' is called 
initialization, and it's special because the target type of the 
initializer is known in advance


This is no different from `S fun(){ return { 5, 2 }; }` It 
creates a new instance of a struct, and the type is known in 
advance (it's the return type). So it's not an expression. But 
this place of initialization is not allowed. Therefor I think 
calling  `S s = { 5, 2 };` 'special' is justified.




Re: struct initializer

2023-12-01 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 30 November 2023 at 14:10:35 UTC, zjh wrote:

On Wednesday, 29 November 2023 at 16:38:36 UTC, Dom DiSc wrote:

```d

struct S { int a; int b; }
S2 fun3() { return S2( 5, 2 ); }

```

Here,`S2( 5, 2 );` violeit `DRY` principle.


Yes. I think if we have the brackets form, it should be allowed 
here:


```d
S Fun(){ return { 5, 2 }; }
```

This IS an initialization and the type is known. Requiring the 
repetition of the type is also here annoying.
So it is not a syntax reserved for initialization, but only for 
initialization with equals operator. I think this is inconsequent.
Either allow it for all initializations, or get rid of it, like 
DIP 1031 suggested.




Re: struct initializer

2023-11-30 Thread zjh via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:38:36 UTC, Dom DiSc wrote:

```d

struct S { int a; int b; }
S2 fun3() { return S2( 5, 2 ); }

```

Here,`S2( 5, 2 );` violeit `DRY` principle.



Re: struct initializer

2023-11-30 Thread Dennis via Digitalmars-d-learn

On Thursday, 30 November 2023 at 07:21:29 UTC, Dom DiSc wrote:
So, why supporting the (somewhat strange looking) version with 
curly backets at all?
It only works in one special place, so is simply overhead to 
remember.
Again a superfluous way to do the same - but only under 
specific circumstances.


I think a syntax should work either always or never.


The syntax was inherited from C. The 'special place' is called 
initialization, and it's special because the target type of the 
initializer is known in advance, while normal expression 
assignments are analyzed bottom up. Since there is no 
`typeof({10, 10})`, struct initializers don't work as expressions.


C99 added Compound literals `(S){.a = 10, .b = 20}`, and with 
named arguments you can do the same in D: `S(a: 10, b:20)`, and 
since the type name is included, they do work as standalone 
expressions.


Walter tried to deprecate the old struct initializer syntax:
https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1031.md

But it got some resistance, since {} initializers still have an 
advantage when you want to define an array of structs, and don't 
want to repeat the (potentially long) struct name for every entry.


Also note that even when {} is removed, there are still other 
special cases with initialization, for example with arrays:


```D
void main()
{
short[] a = [3: 10]; // ok
a = [3: 10]; // cannot implicitly convert expression `[3:10]` 
of type `int[int]` to `short[]`

}
```


Re: struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus wrote:

You can use this syntax without an explicit constructor:

struct S3 { int a; int b; }

S3 fun() { return S3(5, 2); }

The language spec calls this a struct literal


Ok, so we have

```d
struct S { int a; int b; }

S s = S(5, 3); // works
s = S(6, 2); // works
S fun() { return S(5, 2); } // works
int fun2(S s2);
fun2(S(4,4)); // works
```

but

```d
struct S { int a; int b; }

S s = { 5, 3 }; // works
s = { 6, 2 }; // doesn't work
S fun() { return { 5, 2 }; } // doesn't work
int fun2(S s2);
fun2(S(4,4)); // doesn't work
```

So, why supporting the (somewhat strange looking) version with 
curly backets at all?
It only works in one special place, so is simply overhead to 
remember.
Again a superfluous way to do the same - but only under specific 
circumstances.


I think a syntax should work either always or never.


Re: struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

Sorry, I meant

```d
fun2({4, 4}); // doesn't work
```




Re: struct initializer

2023-11-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 17:23:04 UTC, Antonio wrote:
On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus 
wrote:

... it even supports named arguments:


- Witch version of DMD supports named arguments?  Is it an 
experimental compiler option?


I don't know what the earliest version is that supports it, but I 
know the example I posted works in 2.105. It doesn't require any 
compiler options.


Named arguments are still a work in progress, and there are some 
situations where they aren't available (for example, I don't 
think they work for templates yet). With struct literals, though, 
you shouldn't have any problems using them.


Re: struct initializer

2023-11-29 Thread Antonio via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus wrote:

... it even supports named arguments:


- Witch version of DMD supports named arguments?  Is it an 
experimental compiler option?







Re: struct initializer

2023-11-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:38:36 UTC, Dom DiSc wrote:

```d
struct S2 { int a; int b; this(int c, int d) { a=c; b=d; } }

S2 fun3() { return S2( 5, 2 ); } // works but requires explicit 
constructor

```


You can use this syntax without an explicit constructor:

struct S3 { int a; int b; }

S3 fun() { return S3(5, 2); }

The language spec calls this a [struct literal][1]. If you're 
using a new enough compiler, it even supports named arguments:


S3 fun2() { return S3(b: 2, a: 5); }

[1]: https://dlang.org/spec/struct.html#struct-literal


struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

```d
struct S { int a; int b; }

S s = { 5, 2 }; // works fine

S fun() { return { 5, 2 }; } // doesn't work :-(

S fun2() { S s = { 5, 2 }; return s; } // works but is ugly

struct S2 { int a; int b; this(int c, int d) { a=c; b=d; } }

S2 fun3() { return S2( 5, 2 ); } // works but requires explicit 
constructor

```

Is there a reason why the short form is not possible?
It's clearly an initialization of a new instance of a struct, and 
the requested type is unambigous (the return type of the 
function).


Re: Struct initializer in UDA

2020-09-27 Thread realhet via Digitalmars-d-learn

On Sunday, 27 September 2020 at 11:59:49 UTC, Anonymouse wrote:

On Sunday, 27 September 2020 at 10:17:39 UTC, realhet wrote:
On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse 
wrote:

On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote:


That looks the closes to the python named parameters or the 
struct initializer.


For my use case this opDispatch trick seems to be more flexible 
than the named-parameters thing:


@(FieldProps().range(-360, 360).format("%.2f").caption("Turret 
rotation").unit("deg")) float alpha = 0;


for example if I use the name: "logRange" it can also set the 
isLogarithmic flag as a side effect to true inside the FieldProps 
struct. Just by choosing a slightly different name.


With this idealized format it would be not possible:
@FieldProps{ range: {-360, 360}, format:"%.2f", caption:"Turret 
rotation", unit:"deg"} float alpha = 0;


The more work inside the struct is not a problem, because I'm 
willing to use it from 1000 places. Also __traits(allMembers) can 
help.


Thank you!


Re: Struct initializer in UDA

2020-09-27 Thread Anonymouse via Digitalmars-d-learn

On Sunday, 27 September 2020 at 10:17:39 UTC, realhet wrote:
On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse 
wrote:

On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote:
The closest I can get is @(S.init.c(9).f(42)) with use of 
opDispatch, which is easier to read but still ugly.


All I can get is that the
- an identifier of a member is stronger than the opDispatch. -> 
Error: function expected before (), not S(0, 0).c of type int
- and if I prefix it with '_' it ruins toString. -> Error: no 
property toString for type onlineapp.S



import std.stdio, std.range, std.algorithm, std.traits, 
std.meta, std.conv, std.string, std.uni, std.meta, 
std.functional, std.exception;


struct S{
int a, b;

auto opDispatch(string name, T)(T value)
if(name.startsWith("_"))
{
mixin(name[1..$], "= value;");
return this;
}
}

void main(){
S.init._a(5).writeln;
}


Now I'm more confused, as the compiler completely ignores the 
if(name.startsWith("_")) constraint o.O


It works if you specialise opDispatch to take an int parameter 
instead of a type T. It smells like a bug but I don't know enough 
to say.


I used two opDispatches to be able to avoid having to use _a and 
_b, and std.algorithm.comparison.among to constrain them.


struct S{
private int _a, _b;

auto opDispatch(string name)(int value)
if (name.among("a", "b"))
{
mixin("_", name, "= value;");
return this;
}

auto opDispatch(string name)()
if (name.among("a", "b"))
{
mixin("return _", name, ";");
}
}

void main(){
S.init.a(123).b(456).writeln;
S().b(456).a(123).writeln;  // Alternative syntax, may not 
work if opCall is defined

}

It's brittle in that you have to update and sync the two 
among("a", "b") constraints every time you add or remove a field, 
but I can't seem to get the names by introspection without it 
endlessly recursing over opDispatch again.


Re: Struct initializer in UDA

2020-09-27 Thread realhet via Digitalmars-d-learn

On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse wrote:

On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote:
The closest I can get is @(S.init.c(9).f(42)) with use of 
opDispatch, which is easier to read but still ugly.


All I can get is that the
- an identifier of a member is stronger than the opDispatch. -> 
Error: function expected before (), not S(0, 0).c of type int
- and if I prefix it with '_' it ruins toString. -> Error: no 
property toString for type onlineapp.S



import std.stdio, std.range, std.algorithm, std.traits, std.meta, 
std.conv, std.string, std.uni, std.meta, std.functional, 
std.exception;


struct S{
int a, b;

auto opDispatch(string name, T)(T value)
if(name.startsWith("_"))
{
mixin(name[1..$], "= value;");
return this;
}
}

void main(){
S.init._a(5).writeln;
}


Now I'm more confused, as the compiler completely ignores the 
if(name.startsWith("_")) constraint o.O


Re: Struct initializer in UDA

2020-09-26 Thread Anonymouse via Digitalmars-d-learn

On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote:

Hi,

  struct S{int a, b, c=9, d, e, f;}

Is there a way or a trick to declare an UDA by using a nice 
struct initializer?


It would be nice to be able to use the form:

  @S{f:42} int a;  //or something similar to this.

instead of this longer and error-prone way:

  @S(0, 0, 0, 9, 0, 42) int a;


I don't think you can currently, no, but I'd be happy to be 
proven wrong.


The closest I can get is @(S.init.c(9).f(42)) with use of 
opDispatch, which is easier to read but still ugly.


Struct initializer in UDA

2020-09-26 Thread realhet via Digitalmars-d-learn

Hi,

  struct S{int a, b, c=9, d, e, f;}

Is there a way or a trick to declare an UDA by using a nice 
struct initializer?


It would be nice to be able to use the form:

  @S{f:42} int a;  //or something similar to this.

instead of this longer and error-prone way:

  @S(0, 0, 0, 9, 0, 42) int a;


Re: Why does struct initializer works for arrays but not for associative arrays?

2018-03-14 Thread Andre Pany via Digitalmars-d-learn
On Wednesday, 14 March 2018 at 15:17:54 UTC, Jonathan M Davis 
wrote:
On Wednesday, March 14, 2018 13:36:51 Andre Pany via 
Digitalmars-d-learn wrote:

[...]


Well, I think that you have two issues here:

1. Struct literals work in only a few, specific circumstances. 
Why, I don't know, but IIRC, someone was writing a DIP to fix 
that, and that may or may not fix this case. So, as I 
understand it, it's not all that hard to run into places where 
they don't work (I confess that I never use them, because I 
don't like them any more than I like the fact that struct 
constructors are implicitly declared if you don't declare them, 
which has caused me bugs when changing the members fo a struct; 
both are misfeatures IMHO, though obviously not everyone agrees 
on that point).


2. In general in D, the type of an expression is not inferred 
based on where it's used. There are a few exceptions where 
literals are involved, but in general, if you have something 
like


A a = expression;

expression has to evaluate correct on its own without taking A 
into account. The fact that something like


Bar b = {s: "str"};

compiles is actually a bit of an oddity in D's semantics in 
that respect. So, the fact that it works at all is a bit of a 
special case, and clearly, they didn't get everything. My guess 
is that the problem is that the dynamic array literal needs a 
type, but the compiler is not set up to figure out what type 
that is based on the fact that it's being used in a struct 
literal.


- Jonathan M Davis


Thanks for the information. As it works fine for dynamic arrays 
and the coding
in the compiler seems identical for arrays and associative arrays 
I really

wonder why it not work.

Although I really anticipate the DIP, this can be solved as bug 
fix.
The chances to solve this a bug fix are much higher than getting 
the DIP implemented

in near future (unfortunately).

Kind regards
André



Re: Why does struct initializer works for arrays but not for associative arrays?

2018-03-14 Thread Seb via Digitalmars-d-learn
On Wednesday, 14 March 2018 at 15:17:54 UTC, Jonathan M Davis 
wrote:
On Wednesday, March 14, 2018 13:36:51 Andre Pany via 
Digitalmars-d-learn wrote:

[...]


Well, I think that you have two issues here:

1. Struct literals work in only a few, specific circumstances. 
Why, I don't know, but IIRC, someone was writing a DIP to fix 
that, and that may or may not fix this case.


For reference, that's the DIP: 
https://github.com/dlang/DIPs/pull/71


Re: Why does struct initializer works for arrays but not for associative arrays?

2018-03-14 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, March 14, 2018 13:36:51 Andre Pany via Digitalmars-d-learn 
wrote:
> Hi,
>
> I do not understand why struct initializer works for arrays but
> not for
> associative arrays:
>
> struct Bar
> {
>  string s;
> }
>
> struct Foo
> {
>  Bar[string] asso;
>  Bar[] arr;
> }
>
> void main()
> {
>  Foo foo = {
>  arr: [{s: "123"}],
>  asso: ["0": {s: "123"}] // does not work
>  };
> }
>
> The coding for both types of arrays looks very similiar:
> https://github.com/dlang/dmd/blob/9ed779a7d68d2ac489338cc4758c10d0cb169b39
> /src/dmd/initsem.d#L634
>
> I cannot spot the difference.
>
> Kind regards
> André

Well, I think that you have two issues here:

1. Struct literals work in only a few, specific circumstances. Why, I don't
know, but IIRC, someone was writing a DIP to fix that, and that may or may
not fix this case. So, as I understand it, it's not all that hard to run
into places where they don't work (I confess that I never use them, because
I don't like them any more than I like the fact that struct constructors are
implicitly declared if you don't declare them, which has caused me bugs when
changing the members fo a struct; both are misfeatures IMHO, though
obviously not everyone agrees on that point).

2. In general in D, the type of an expression is not inferred based on where
it's used. There are a few exceptions where literals are involved, but in
general, if you have something like

A a = expression;

expression has to evaluate correct on its own without taking A into account.
The fact that something like

Bar b = {s: "str"};

compiles is actually a bit of an oddity in D's semantics in that respect.
So, the fact that it works at all is a bit of a special case, and clearly,
they didn't get everything. My guess is that the problem is that the dynamic
array literal needs a type, but the compiler is not set up to figure out
what type that is based on the fact that it's being used in a struct
literal.

- Jonathan M Davis




Re: Why does struct initializer works for arrays but not for associative arrays?

2018-03-14 Thread Uknown via Digitalmars-d-learn

On Wednesday, 14 March 2018 at 13:36:51 UTC, Andre Pany wrote:

Hi,

I do not understand why struct initializer works for arrays but 
not for

associative arrays:

struct Bar
{
string s;
}

struct Foo
{
Bar[string] asso;
Bar[] arr;
}

void main()
{
Foo foo = {
arr: [{s: "123"}],
asso: ["0": {s: "123"}] // does not work
};
}

The coding for both types of arrays looks very similiar:
https://github.com/dlang/dmd/blob/9ed779a7d68d2ac489338cc4758c10d0cb169b39/src/dmd/initsem.d#L634

I cannot spot the difference.

Kind regards
André


This might just be a bug. Changing the initializer to an explicit 
call to Bar constructor compiles just fine


https://run.dlang.io/is/nuuolx

Even just doing

Foo foo = {
arr: [{s: "123"}],
asso: ["0": {"123"}] // does not work
};


Why does struct initializer works for arrays but not for associative arrays?

2018-03-14 Thread Andre Pany via Digitalmars-d-learn

Hi,

I do not understand why struct initializer works for arrays but 
not for

associative arrays:

struct Bar
{
string s;
}

struct Foo
{
Bar[string] asso;
Bar[] arr;
}

void main()
{
Foo foo = {
arr: [{s: "123"}],
asso: ["0": {s: "123"}] // does not work
};
}

The coding for both types of arrays looks very similiar:
https://github.com/dlang/dmd/blob/9ed779a7d68d2ac489338cc4758c10d0cb169b39/src/dmd/initsem.d#L634

I cannot spot the difference.

Kind regards
André


Re: alias this and struct initializer

2017-05-18 Thread Andre Pany via Digitalmars-d-learn

On Thursday, 18 May 2017 at 12:56:09 UTC, Adam D. Ruppe wrote:

On Thursday, 18 May 2017 at 08:40:39 UTC, Andre Pany wrote:

[...]


Nope, case 2 is assigning to an already constructed object and 
case 3 is constructing a new one.


[...]


Thanks for the explanation, that makes perfectly sense.

Kind regards
André


Re: alias this and struct initializer

2017-05-18 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 18 May 2017 at 08:40:39 UTC, Andre Pany wrote:

I think as case 2 is working case 3 should work also.


Nope, case 2 is assigning to an already constructed object and 
case 3 is constructing a new one.


alias this is NEVER used in construction. It can only apply after 
the object already exists, just like subclasses vs interfaces. 
Once the object exists, you can assign a subclass to an 
interface, but you can't do


SubClass obj = new Interface();

in theory, the compiler could see the left hand side and know it 
is supposed to be SubClass, but it doesn't - you need to 
construct the class explicitly.


Same with alias this, it allows implicit conversion TO the type 
and assignment of the member through the existing variable (the 
existing variable must already be valid, it is already 
constructed, so it is no different than assigning any other 
public member), but not implicit conversion FROM the type since 
the new struct may have other members that need to be initialized 
too.


alias this and struct initializer

2017-05-18 Thread Andre Pany via Digitalmars-d-learn

Hi,

I have some issues with struct initializer and alias this.
In following example 1 and 2 is working but there is a syntax
error for 3. I think as case 2 is working case 3 should work also.
For me case 3 is looking much nicer than case 1.
What do you think?

void main()
{
// Working
Request request1 = {
definitions: {[
Definition("A", "B")
]}
};

// Working
Request request2;
request2.definitions = [Definition()];

	// cannot implicitly convert expression ([Definition("A", "B")]) 
of type Definition[] to Definitions

Request request3 = {
definitions: [
Definition("A", "B")
]
};
}

struct Request
{
Definitions definitions;
}

struct Definitions
{
private Definition[] _arr;
alias values this;
@property Definition[] values(){return _arr;}
@property void values(Definition[] values){_arr = values;}
}

struct Definition
{
string attributeName;
string attributeType;
}

Kind regards
André