Re: template/mixin magic for to! auto inferring type from variable

2024-02-03 Thread kdevel via Digitalmars-d-learn

On Saturday, 3 February 2024 at 02:20:13 UTC, Paul Backus wrote:

On Friday, 2 February 2024 at 23:25:37 UTC, Chris Katko wrote:
The auto solution won't work for a struct however which I'm 
using:


```D
struct procTable{ //contains all the fields inside a file I'm 
parsing

   uint time;
   int priority;
   string name;
   // etc
   }
```


Maybe you can use `typeof` in that case?

```d
procTable pt;
pt.time = to!(typeof(pt.time))(data[1]);
// etc
```

...although I guess then you're repeating the field name, which 
isn't great either.


```d
struct ProcTable2 {
   uint time;
   int priority;
   string name;

   this (string [this.tupleof.length] initializers)
   {
  import std.conv;
  static foreach (i, field; this.tupleof)
 field = initializers [i].to!(typeof (field));
   }
}

unittest {
   string [3] initializers = ["100", "-5", "foobar"];
   auto pt2 = ProcTable2 (initializers);
   with (pt2) {
  assert(time == 100);
  assert(priority == -5);
  assert(name == "foobar");
   }
}
```


Re: template/mixin magic for to! auto inferring type from variable

2024-02-02 Thread Paul Backus via Digitalmars-d-learn

On Friday, 2 February 2024 at 23:25:37 UTC, Chris Katko wrote:
The auto solution won't work for a struct however which I'm 
using:


```D
struct procTable{ //contains all the fields inside a file I'm 
parsing

   uint time;
   int priority;
   string name;
   // etc
   }
```


Maybe you can use `typeof` in that case?

```d
procTable pt;
pt.time = to!(typeof(pt.time))(data[1]);
// etc
```

...although I guess then you're repeating the field name, which 
isn't great either.


You could avoid the repetition by wrapping the above pattern up 
in a helper function, though:


```d
void convertAssign(Dest, Value)(ref Dest dest, Value value)
{
import std.conv;
dest = to!Dest(value);
}

void main()
{
string[3] data = ["100", "-5", "foobar"];

uint time;
int priority;
string name;

time.convertAssign(data[0]);
priority.convertAssign(data[1]);
name.convertAssign(data[2]);

assert(time == 100);
assert(priority == -5);
assert(name == "foobar");
}
```


Re: template/mixin magic for to! auto inferring type from variable

2024-02-02 Thread Chris Katko via Digitalmars-d-learn

On Friday, 2 February 2024 at 21:01:53 UTC, Paul Backus wrote:


No, D only does bottom-up type inference, not top down.

If you want to avoid repeating the type, use `auto` on the left 
side:


```d
auto time = to!uint(data[1]);
auto priority = to!int(data[2]);
```


Okay thanks. It finally clicked what bottom-up/top-down type 
interference is.


The auto solution won't work for a struct however which I'm using:

```D
struct procTable{ //contains all the fields inside a file I'm 
parsing

   uint time;
   int priority;
   string name;
   // etc
   }
```



Re: template/mixin magic for to! auto inferring type from variable

2024-02-02 Thread Paul Backus via Digitalmars-d-learn

On Friday, 2 February 2024 at 07:43:09 UTC, Chris Katko wrote:

Is there some way to do:
```D
string[3] data; //strings from some file input, some are ints, 
uints, etc.


auto into!(T)(T value){return to!???(value); } // ???

uint time = into!(data[1]); // We already know this is uint
int priority = into!(data[2]);
```

instead of:
```D
uint time = to!uint(data[1]); // specifying type twice
int priority = to!int(data[2])
```


No, D only does bottom-up type inference, not top down.

If you want to avoid repeating the type, use `auto` on the left 
side:


```d
auto time = to!uint(data[1]);
auto priority = to!int(data[2]);
```


template/mixin magic for to! auto inferring type from variable

2024-02-01 Thread Chris Katko via Digitalmars-d-learn

Is there some way to do:
```D
string[3] data; //strings from some file input, some are ints, 
uints, etc.


auto into!(T)(T value){return to!???(value); } // ???

uint time = into!(data[1]); // We already know this is uint
int priority = into!(data[2]);
```

instead of:
```D
uint time = to!uint(data[1]); // specifying type twice
int priority = to!int(data[2])
```


Re: 'auto' keyword

2023-03-12 Thread Ali Çehreli via Digitalmars-d-learn

On 3/12/23 06:07, DLearner wrote:

> 1. As a shorthand to make the type of the variable being declared the
> same as the type on the right hand side of an initial assignment.

As Adam explained, D already has type inference without a special keyword.

However, some places where 'auto' (or 'const', etc.) appear is not only 
for "shorthand" but for necessity.


Some types cannot be spelled-out at all:

auto foo() {
struct S {}
return S();
}

void main() {
pragma(msg, typeof(foo()));
auto s = foo();
}

The name 'S' is available only inside 'foo', so code outside has no 
choice but to use 'auto' (or 'const', etc.)


Having said that, it is still possible to alias the returned type, which 
may be cumbersome in some cases because you may have to come up with a 
clean expression for attempting to call the function. In this case it's 
trivial because foo does not take any parameter:


alias T = typeof(foo());
T t;// <-- There: I did not need to use 'auto'

Ali



Re: 'auto' keyword

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

On Sunday, 12 March 2023 at 13:27:05 UTC, Adam D Ruppe wrote:

[...] *any* storage class will work for type inference. [...]


After heaving read [1] I immediately thought of this:

   void main ()
   {
  deprecated i = 3;
  i = 4;
   }
   $ dmd test.d
   test.d(4): Deprecation: variable `test.main.i` is deprecated

Does that make sense???

[1] https://issues.dlang.org/show_bug.cgi?id=7432
Issue 7432 - DMD allows variables to be declared as pure


Re: 'auto' keyword

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

On Sunday, 12 March 2023 at 15:31:07 UTC, Salih Dincer wrote:

Moreover, `auto ref` or `ref auto` is needed in functions.


That's because `ref` isn't part of the argument or return value's 
type, so it isn't covered by **type** inference. Instead, D has a 
totally separate feature for "`ref` inference".


Re: 'auto' keyword

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

On Sunday, 12 March 2023 at 13:07:58 UTC, DLearner wrote:
Is it correct that this _single_ keyword is used to indicate 
_two_ quite different things:


1. As a shorthand to make the type of the variable being 
declared the same as the type on the right hand side of an 
initial assignment.


The auto keyword is really helpful for shortening it.  But in at 
least 2 cases (one of which is interfaces) it should help the 
compiler.  For example, contrary to expected, it is dynamic array:


```d
auto arr = [ 1, 2, 3 ];
```

Moreover, `auto ref` or `ref auto` is needed in functions.

SDB@79


Re: 'auto' keyword

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

On Sunday, 12 March 2023 at 13:07:58 UTC, DLearner wrote:
Is it correct that this _single_ keyword is used to indicate 
_two_ quite different things:


No, it only actually does #2 in your thing. The type is optional 
meaning *any* storage class will work for type inference. `auto` 
is not special in variable declarations. (it can be special in 
other contexts though).


auto A = 5;
static A = 5;
const A = 5;

all the same.


'auto' keyword

2023-03-12 Thread DLearner via Digitalmars-d-learn
Is it correct that this _single_ keyword is used to indicate 
_two_ quite different things:


1. As a shorthand to make the type of the variable being declared 
the same as the type on the right hand side of an initial 
assignment.


Example: ```auto A = 5;``` makes A an int.

2. To indicate storage class of variable.

Example: ```auto int A;``` (I guess) makes A have automatic 
storage, ie contents lost when control goes out of scope, unlike 
static.


Best regards


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-26 Thread Kagamin via Digitalmars-d-learn
Looks like explicitly initialized variable in this case allocates 
array literal. Uninitialized variable is initialized with init 
pattern. This may be correct as uninitialized variable isn't 
guaranteed to hold a value most useful for you, it's only 
guaranteed to hold a defined value.


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-26 Thread Andrey Zherikov via Digitalmars-d-learn

On Wednesday, 26 October 2022 at 04:40:17 UTC, Salih Dincer wrote:
On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:
Does the second piece of code shows a bug or my expectation is 
not correct (and why if so)?


As a result, if this is a bug, Andrey has the right to report 
it.


Bug tracking system doesn't work with gmail emails so I'm not 
able to report.





Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Salih Dincer via Digitalmars-d-learn

On Wednesday, 26 October 2022 at 02:34:24 UTC, Ali Çehreli wrote:

On 10/25/22 19:25, Salih Dincer wrote:

> with static in main():

If 'static' makes a difference on your side as well, it is your 
turn to create a bug report. :) (Last time you discovered a 
bug, I was too quick to report it. :/)




On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:
Does the second piece of code shows a bug or my expectation is 
not correct (and why if so)?


As a result, if this is a bug, Andrey has the right to report it. 
Unlike what Andrey did, I haven't tried it with a nested struct.


There is also be in the heap or be in the stack issue...

SDB@79


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 19:25, Salih Dincer wrote:

> with static in main():

If 'static' makes a difference on your side as well, it is your turn to 
create a bug report. :) (Last time you discovered a bug, I was too quick 
to report it. :/)


Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Salih Dincer via Digitalmars-d-learn

On Wednesday, 26 October 2022 at 00:44:45 UTC, H. S. Teoh wrote:


If you'll excuse some ASCII art, here's the situation you have:

STACK  GLOBAL DATA
x[0] {
Y[] y; -+> [ Y.init ]
}   |
x[1] {  |
Y[] y; -'
}




Thanks for these detailed explanations, especially the ASCII art 

On Wednesday, 26 October 2022 at 00:58:33 UTC, Ali Çehreli wrote:

On 10/25/22 17:16, Salih Dincer wrote:
I tested: If you make X a 'static struct', then you see the 
same output.


It occurred to me too, to use a static struct.  I also tried the 
following example because it can work with static in main():


import std;

void main() {
  //static
  struct X
  {
static struct Y {
   //...
  }}

  static
  struct Bar {
string s;

string toString() {
  return s;
}
  }

  auto list = "sixtwoone".chunks(3);
   list.map!(c => c.to!string)
   .map!Bar.array.writeln; // [six, two, one]
   //...
}

Thank you...

@SDB79


Re: auto scope question?

2022-10-25 Thread WhatMeWorry via Digitalmars-d-learn



typeof(screen.output.findSplit("")) s;


Perfect. That was the "essence" of my question. But thanks to 
Ali, I don't have to use such esoteric syntax.  D is a wonderful 
language, but I seem to shoot myself in the foot :)


Re: auto scope question?

2022-10-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/25/22 6:07 PM, WhatMeWorry wrote:
I'm naturally getting a undefined identifier `s` error in the return.  
Is there some way to refactor my code?  I tried to declare s outside of 
the else brackets like:


auto screen = executeShell(cmdLine);
auto s;
...
{
     s = screen.output.findSplit("REG_SZ");
}

but that doesn't compile either.



string[] getPath(string cmdLine)
{
     auto screen = executeShell(cmdLine);

     if (screen.status != 0)
     {
     writeln(cmdLine, " failed");
     }
     else
     {
     writeln("screen.output = ", screen.output);
 auto s = screen.output.findSplit("REG_SZ");
     writeln("s[0] = ", s[0]);
     writeln("s[1] = ", s[1]);
     writeln("s[2] = ", s[2]);
     }
     return (s.split(';'));  // Error: undefined identifier `s`
}


As Ali mentioned, your logic is faulty -- you seem to write that the 
command failed, but then return something anyway.


Also, you are returning `string[]`, so just declaring `string[] s;` 
should be enough.


However, I did want to mention that if you do want to hoist a difficult 
to name type outside where it is declared with an auto, you can use 
`typeof`:


```d
typeof(screen.output.findSplit("")) s;
```

In this case, it's just `string[]`, but the idea here is you can name a 
type without naming it, by using `typeof` on the expression you would 
have called.


Hope this helps further your D knowledge ;)

-Steve


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 17:16, Salih Dincer wrote:

> Excuse me, but they still write in purple prose about dynamic
> array literature here!

I've heard positive things about D's arrays from people who use D in 
production. Especially slices...


> I've known D for more than 10 years, but the topic we're talking about
> still seems strange to me.

Your example makes it more complicated and potentially exposes a bug.

> The explanations given are not enough for
> me, I'm sorry.

There may be a number of different concepts to list but I don't think 
there is anything inherently complicated with these topics (again, your 
example is more complicated).


> Can anyone tell me what happens when I change the location of the
> structure?

What you mean is, you see different behaviour depending on struct X is 
nested or not. The difference is, nested structs carry a context 
pointer. This may be related to a bug for the different outputs that we see.


> So the X structure must be in the stack when it is in
> main(), and the following must be in the heap, right?

To nit-pick: The struct is just a definition. Not the struct but its 
objects can be on the stack or on the heap.


But yes, all objects you have are on the stack.

> //void main() {

So when you uncomment that line and comment-out the following main() 
line in the program, you see a different output.


I tested: If you make X a 'static struct', then you see the same output.

I think the difference is due to a bug.

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Oct 26, 2022 at 12:16:55AM +, Salih Dincer via Digitalmars-d-learn 
wrote:
[...]
> I've known D for more than 10 years, but the topic we're talking about
> still seems strange to me.  The explanations given are not enough for
> me, I'm sorry.
> 
> Can anyone tell me what happens when I change the location of the
> structure?  So the X structure must be in the stack when it is in
> main(), and the following must be in the heap, right?
> 
> ```d
> import std;
> 
> //void main() {
> 
>   struct X
>   {
> struct Y {
>   int i = 10;
>   alias i this;
> }
> Y[] y = [Y.init];

This declares y to be a slice of some memory somewhere (it can be either
the stack or the heap), and initializes it to point to a 1-element array
containing Y.init.

Here's an important quirk in D: whenever you initialize an aggregate
array member with a literal, ALL instances of the aggregate will point
to the *same* underlying array (see below).

If you want to avoid the confusing situation below, my recommendation is
that you initialize .y inside the ctor instead. Then it will be more
explicit what exactly is going on.


> string toString() {
>   return y.format!"%s";
> }
>   }
> 
> void main() {
> 
>   X[2] x;

This declares a static array of 2 elements, each of which is an X. Each
instance of X contains a member y that is a slice that points to the
array [Y.init].  Each instance of X sits on the stack; however, their
members y point somewhere else, in this case, to the array [Y.init].

And here's the important point: as mentioned above, [Y.init] here is the
SAME ARRAY that's being referred to by two different slices: x[0].y and
x[1].y.

If you'll excuse some ASCII art, here's the situation you have:

STACK  GLOBAL DATA
x[0] {
Y[] y; -+> [ Y.init ]
}   |
x[1] {  |
Y[] y; -'
}


>   x.writeln;   // [[10], [10]]
> 
>   x[0].y[0] = 0;   // [[0], [0]]

This line in essence says, "assign 0 to the first element of the array
in the slice y, in the first element of array x".  Since both x[0].y and
x[1].y point to the same underlying array, modifying it via x[0].y will
also cause x[1].y to see the change.

IOW, the revised ASCII art diagram now looks like this:

STACK  GLOBAL DATA
x[0] {
Y[] y; -+> [ 0 ]
}   |
x[1] {  |
Y[] y; -'
}

That is why x[0].y[0] == 0 and also x[1].y[0] == 0. This is because
x[0].y.ptr == x[1].y.ptr.


>   x.writeln;
> 
>   x[0].y.length++;

This line tries to increase the length of the array pointed to by
x[0].y. Since it was declared as a 1-element literal, which is allocated
in program global data area, there isn't room to expand it.  So at this
point, in order to honor the request to lengthen the array, druntime
will allocate a new array on the heap and copy the contents of the old
array over, then expand its length to 2.  The situation now looks like
this:

STACK  GLOBAL DATA   HEAP
x[0] {
Y[] y; > [ 0, 0 ]
}
x[1] {   
Y[] y; --> [ 0 ]
}

Key point: x[0].y and x[1].y now point to two different arrays, in two
different places. Changes in one will no longer reflect in the other.

The array [ 0 ] shown above is the same array that x[0].y *used* to
point to, but no longer does because druntime has made a copy of it in
the heap and updated x[0].y to point to the copy instead of the
original.  x[1].y, however, continues to point to the original array.


>   x[0].y[1] = 1;

This modifies the second element of x[0].y to 1. Situation now looks
like this:

STACK  GLOBAL DATA   HEAP
x[0] {
Y[] y; > [ 0, 1 ]
}
x[1] {   
Y[] y; --> [ 0 ]
}


>   x[1].y[0] = 2;

This modifies the first element of x[1].y to 2. Situation:

STACK  GLOBAL DATA   HEAP
x[0] {
Y[] y; > [ 0, 1 ]
}
x[1] {   
Y[] y; --> [ 2 ]
}


>   x.writeln;   // [[0, 1], [2]]

Which reflects the situation shown above.


T

-- 
Why ask rhetorical questions? -- JC


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Salih Dincer via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 20:36:28 UTC, matheus wrote:

On


int[] a = [1];
int[] b = a.dup;

assert([0] !is [0]); // different memory
```


This is interesting, I understand the point of "reference vs 
copy", and I'm OK with this design choice of, but I wonder in 
the case of newcomers if this is a case the generate more 
problem understanding this rules, like we are having here.


Matheus.


Huh, I do NOT understand and I DO agree with you!

Excuse me, but they still write in purple prose about 
dynamic array literature here!


I've known D for more than 10 years, but the topic we're talking 
about still seems strange to me.  The explanations given are not 
enough for me, I'm sorry.


Can anyone tell me what happens when I change the location of the 
structure?  So the X structure must be in the stack when it is in 
main(), and the following must be in the heap, right?


```d
import std;

//void main() {

  struct X
  {
struct Y {
  int i = 10;
  alias i this;
}
Y[] y = [Y.init];

string toString() {
  return y.format!"%s";
}
  }

void main() {

  X[2] x;
  x.writeln;   // [[10], [10]]

  x[0].y[0] = 0;   // [[0], [0]]
  x.writeln;

  x[0].y.length++;
  x[0].y[1] = 1;

  x[1].y[0] = 2;
  x.writeln;   // [[0, 1], [2]]

} /* Output of other state:
[[10], [10]]
[[0], [0]]
[[2, 1], [2]]
*/
```
SDB@79


Re: auto scope question?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 15:07, WhatMeWorry wrote:

> auto screen = executeShell(cmdLine);
> auto s;

That can't work because there is no information to infer the type of 
's'. Judging from the return type of getPath, perhaps it's string[]:


string[] s;

This is the question we should answer first: What should happen when 
executeShell fails?


a) It is an error; the program should not continue. Then we can use 
'enforce' (this is my way of coding):


string[] getPath(string cmdLine)
{
import std.exception : enforce;

    auto screen = executeShell(cmdLine);
enforce(screen.status == 0, format!"%s failed:\n%s"(cmdLine, 
screen.output));


writeln("screen.output = ", screen.output);
auto s = screen.output.findSplit("REG_SZ");
writeln("s[0] = ", s[0]);
writeln("s[1] = ", s[1]);
writeln("s[2] = ", s[2]);

return (s.split(';'));
}

b) It is not an error; getPath() should return empty array:

string[] getPath(string cmdLine)
{
string[] result;
auto screen = executeShell(cmdLine);

if (screen.status != 0)
{
writeln(cmdLine, " failed");
return null;  // <-- HERE (null converts to any array type)
}
else
{
// ...
// Now, 'return' is where 's' is defined:
return (s.split(';'));
}
}

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 13:36, matheus wrote:
> On Tuesday, 25 October 2022 at 20:12:25 UTC, Paul Backus wrote:

>> Static arrays are value types.

What that means is, when we say float[3], there are just 3 floats 
without any overhead.


>> Dynamic arrays are reference types.

That phrase can be confusing because we often use the terms "dynamic 
array" and "slice" interchangably.


I find the following simpler to understand (can still be confusing):

- Dynamic arrays are expandable arrays that are owned by the D runtime 
(the GC). Dynamic arrays don't have names.


- The names (symbols) that we see in source code are slices that are 
references to elements of arrays. Such arrays can be static or dynamic.


When we add an element to a slice that has no room (.capacity <= 
.length) then a fresh dynamic array is created from the copies of the 
elements of the slice.


> if this is a case the generate more problem understanding this rules,

I think all these array complexities are inherent. Other examples from 
two other languages that I know:


- In C, arrays that are members of user-defined types are value types. 
Arrays that are parameters are reference types (pointer to the first 
element). Confusing.


- In C++, std::vector is a value type, which would be copied if passed 
by value. So there came std::array, std::string_view, std::span, etc. to 
address value versus reference complexities.


I don't think D could do anything better with arrays. They seem to work 
pretty well and are among the favorite features of many D programmers.


Ali



auto scope question?

2022-10-25 Thread WhatMeWorry via Digitalmars-d-learn
I'm naturally getting a undefined identifier `s` error in the 
return.  Is there some way to refactor my code?  I tried to 
declare s outside of the else brackets like:


auto screen = executeShell(cmdLine);
auto s;
...
{
s = screen.output.findSplit("REG_SZ");
}

but that doesn't compile either.



string[] getPath(string cmdLine)
{
auto screen = executeShell(cmdLine);

if (screen.status != 0)
{
writeln(cmdLine, " failed");
}
else
{
writeln("screen.output = ", screen.output);   
auto s = screen.output.findSplit("REG_SZ");
writeln("s[0] = ", s[0]);
writeln("s[1] = ", s[1]);
writeln("s[2] = ", s[2]); 
}
return (s.split(';'));  // Error: undefined identifier `s`
}


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 20:27:18 UTC, Ali Çehreli wrote:

On 10/25/22 13:12, Paul Backus wrote:

> In order to create a copy of a static array

Although .dup works for static arrays as well, you meant 
"dynamic array" and everyones knows it. :)


Yes; thank you for the correction. :)


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread matheus via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 20:12:25 UTC, Paul Backus wrote:

On Tuesday, 25 October 2022 at 17:54:16 UTC, Salih Dincer wrote:

On Tuesday, 25 October 2022 at 17:18:35 UTC, Paul Backus wrote:
It's not a bug. They're pointing to the exact same instance 
of `A` in memory:


I don't understand?  So I don't understand why it causes 
problems with dynamic arrays!  So why is there nothing wrong 
with the static array in the example below?


Static arrays are value types. When you copy a static array, 
the copy's data is stored in a separate block of memory from 
the original:


```d
int[1] a = [1];
int[1] b = a;

assert([0] !is [0]); // different memory
```

Dynamic arrays are reference types. When you copy a dynamic 
array, both copies point to the same block of memory:


```d
int[] a = [1];
int[] b = a;

assert([0] is [0]); // same memory
```

In order to create a copy of a static array with its own block 
of memory, separate from the original, you have to use the 
built-in `.dup` method:


```d
int[] a = [1];
int[] b = a.dup;

assert([0] !is [0]); // different memory
```


This is interesting, I understand the point of "reference vs 
copy", and I'm OK with this design choice of, but I wonder in the 
case of newcomers if this is a case the generate more problem 
understanding this rules, like we are having here.


Matheus.


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 13:12, Paul Backus wrote:

> In order to create a copy of a static array

Although .dup works for static arrays as well, you meant "dynamic array" 
and everyones knows it. :)


> with its own block of
> memory, separate from the original, you have to use the built-in `.dup`
> method:
>
> ```d
> int[] a = [1];
> int[] b = a.dup;

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 17:54:16 UTC, Salih Dincer wrote:

On Tuesday, 25 October 2022 at 17:18:35 UTC, Paul Backus wrote:
It's not a bug. They're pointing to the exact same instance of 
`A` in memory:


I don't understand?  So I don't understand why it causes 
problems with dynamic arrays!  So why is there nothing wrong 
with the static array in the example below?


Static arrays are value types. When you copy a static array, the 
copy's data is stored in a separate block of memory from the 
original:


```d
int[1] a = [1];
int[1] b = a;

assert([0] !is [0]); // different memory
```

Dynamic arrays are reference types. When you copy a dynamic 
array, both copies point to the same block of memory:


```d
int[] a = [1];
int[] b = a;

assert([0] is [0]); // same memory
```

In order to create a copy of a static array with its own block of 
memory, separate from the original, you have to use the built-in 
`.dup` method:


```d
int[] a = [1];
int[] b = a.dup;

assert([0] !is [0]); // different memory
```


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 11:23, Steven Schveighoffer wrote:

>> Why do I say incorrect things like that? :)

> You were right actually.

As always! Now I'm confused. :o)

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/25/22 2:03 PM, Ali Çehreli wrote:

On 10/25/22 11:01, Ali Çehreli wrote:

 > static arrays don't have .ptr to point
 > to any member.

Why do I say incorrect things like that? :) Of course static arrays have 
.ptr as well but that always point to their own body of N elements. They 
own their elements... I move away from the keyboard now... :)


You were right actually. The `arr.ptr` is a shortcut for the address of 
the first element.


A dynamic array is equivalent to a struct with a `ptr` and `length` 
fields. A static array does not have fields, it's just the data itself. 
The properties are not real fields, but lowerings so they can be used 
like dynamic arrays.


-Steve


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 11:01, Ali Çehreli wrote:

> static arrays don't have .ptr to point
> to any member.

Why do I say incorrect things like that? :) Of course static arrays have 
.ptr as well but that always point to their own body of N elements. They 
own their elements... I move away from the keyboard now... :)


> Static arrays are "just elements side by side."

I still like that description though.

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 10:54, Salih Dincer wrote:

> So I don't understand why it causes problems with
> dynamic arrays!  So why is there nothing wrong with the static array in
> the example below?

The same rules as other uses of dynamic arrays...

>  //A[] a = [A.init];/*

In that case, there is a single instance of [A.init]. All A.a members 
point to it through their .ptr .length members.


>  A[1] a = [A.init];//*/

In that case, there is still a single instance of [A.init], which gets 
copied to each A.a member because static arrays don't have .ptr to point 
to any member. Static arrays are "just elements side by side."


In other words, there is no option but to copy to static arrays; they 
can't point to elements and they don't have any problem in this case.


Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Salih Dincer via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 17:18:35 UTC, Paul Backus wrote:
It's not a bug. They're pointing to the exact same instance of 
`A` in memory:


I don't understand?  So I don't understand why it causes problems 
with dynamic arrays!  So why is there nothing wrong with the 
static array in the example below?



```d
import std.stdio, std.format;
void main()
{
  struct B
  {
struct A {
  int i = 10;
}
//A[] a = [A.init];/*
A[1] a = [A.init];//*/

string toString() {
  return a[0].i.format!"%s";
}
  }

  B[2] b;
  b.writeln;  // [10, 10]

  b[0].a[0].i = 0;
  b.writeln;  // [0, 10]

  b[1].a[0].i = 1;
  b.writeln;  // [0, 1]
}
```


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 08:50, Andrey Zherikov wrote:

> I'd like to tune default ctor but structs can't have custom one.
> Adding a ctor with parameter seems a hack to me

There is static opCall, which may be seen as a hack as well. :) The 
following all print the same thing now:


import std.stdio;

struct A
{
int[] i;
}
struct B
{
A[] a = [A.init];

static B opCall()
{
return B.init;
}
}
void main()
{
    auto b1 = B.init;
b1.writeln;

B b2 = B();
b2.writeln;

B b3;
b3.writeln;
}

> This fails in run time

Not anymore with the above code.

Ali



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 16:52:48 UTC, Salih Dincer wrote:
On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:
Does the second piece of code shows a bug or my expectation is 
not correct (and why if so)?


This is a bug:

```d
void main()
{
  struct B
  {
struct A
{
  int i = 10;
}
A[] a = [A.init];
  }

  B[2] b;
  assert(b[0].a[0].i == 10);
  assert(b[1].a[0].i == 10);

  b[0].a[0].i = 1;
  assert(b[0].a[0].i == 1); // ok...
  assert(b[1].a[0].i == 1); // must be 10 !!!
}
```


It's not a bug. They're pointing to the exact same instance of 
`A` in memory:


```d
void main()
{
  struct B
  {
struct A
{
  int i = 10;
}
A[] a = [A.init];
  }

  B[2] b;
  assert(b[0].a.ptr is b[1].a.ptr);
}
```

As explained in [Adam's reply][1], what happens here is that 
there is a single, global `A[]` allocated at compile time, which 
is shared between all instances of `B.init`. It's the same as if 
you'd written


```d
struct B
{
struct A
{
int i = 10;
}
static A[] globalArray = [A.init];
A[] a = globalArray;
}
```

[1]: 
https://forum.dlang.org/post/yznhocajstphrozpn...@forum.dlang.org


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Salih Dincer via Digitalmars-d-learn
On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:
Does the second piece of code shows a bug or my expectation is 
not correct (and why if so)?


This is a bug:

```d
void main()
{
  struct B
  {
struct A
{
  int i = 10;
}
A[] a = [A.init];
  }

  B[2] b;
  assert(b[0].a[0].i == 10);
  assert(b[1].a[0].i == 10);

  b[0].a[0].i = 1;
  assert(b[0].a[0].i == 1); // ok...
  assert(b[1].a[0].i == 1); // must be 10 !!!
}
```

SDB@79


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Andrey Zherikov via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 14:53:50 UTC, Adam D Ruppe wrote:
On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:

A[] a = [A.init];


This is a problem - this is referring to a static array 
instance, shared across all copies of B. You almost certainly 
don't want this.


That B.a[0] is the *same object* across different 
default-constructed Bs... unless the optimizer hits it or 
something.


Is it a bad idea to trigger copy on write before modification of 
B.a so it behaves as below?

```d
B b1;
b1.a = b1.a.dup;   // copy on write
b1.a[0].i ~= '1';
b1.a ~= A.init;
b1.a[0].i ~= '2';
b1.a[1].i ~= '3';
b1.writeln;// B([A("12"), A("3")])

B b2;
b2.writeln;// B([A("")])
```


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Andrey Zherikov via Digitalmars-d-learn

On Tuesday, 25 October 2022 at 14:53:50 UTC, Adam D Ruppe wrote:
But just don't do this. Only basic values and immutable strings 
are good to initialize this way. With the array or class 
objects, you're liable to get some shared thing.


If you change this to be initialized in a constructor (which 
will require an argument in D) or factory function, you'll get 
far more consistent behavior as each instance will have its own 
array.


I'd like to tune default ctor but structs can't have custom one.
Adding a ctor with parameter seems a hack to me - and compiler 
still allows default construction even when default ctor is 
disabled:


```d
struct A
{
int[] i;
}
struct B
{
A[] a;
@disable this();
this(bool)
{
A[] a = [A.init];
}
}
void main()
{
auto b1 = B.init;
b1.a[0].i ~= 1;
b1.a ~= A.init;
b1.a[0].i ~= 11;
b1.a[1].i ~= 12;
b1.writeln;

auto b2 = B.init;
b2.writeln;
}
```
This fails in run time, not compile time:
```
core.exception.ArrayIndexError@onlineapp.d(19): index [0] is out 
of bounds for array of length 0


??:? _d_arraybounds_indexp [0x55b558b8ec55]
./onlineapp.d:19 _Dmain [0x55b558b6bd5f]
```

As for why B() and B.init are different here... i don't know, 
probably some subtly of the compiler's implementation.


Actually `auto b = B.init;` behaves the same way as `auto b = 
B();` but they don't do the same as `B b;`


Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 07:53, Adam D Ruppe wrote:
> On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov wrote:
>> A[] a = [A.init];
>
> This is a problem - this is referring to a static array instance, shared
> across all copies of B. You almost certainly don't want this.

Agreed. It should be fine when the elements are immutable as I've 
experimented with recently[1]:


struct Xml {
string beg;
string end = "/>";  // Shared by all instances;
// no allocation for some objects.
// ...
}

> As for why B() and B.init are different here... i don't know, probably
> some subtly of the compiler's implementation.

I think it's a bug.

Ali

[1] https://youtu.be/0JL9uT_XGZE?t=4260s



Re: Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Adam D Ruppe via Digitalmars-d-learn
On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov 
wrote:

A[] a = [A.init];


This is a problem - this is referring to a static array instance, 
shared across all copies of B. You almost certainly don't want 
this.


That B.a[0] is the *same object* across different 
default-constructed Bs... unless the optimizer hits it or 
something.


But just don't do this. Only basic values and immutable strings 
are good to initialize this way. With the array or class objects, 
you're liable to get some shared thing.


If you change this to be initialized in a constructor (which will 
require an argument in D) or factory function, you'll get far 
more consistent behavior as each instance will have its own array.


As for why B() and B.init are different here... i don't know, 
probably some subtly of the compiler's implementation.


Is "auto t=T();" not the same as "T t;"?

2022-10-25 Thread Andrey Zherikov via Digitalmars-d-learn

I have the following types (simplified version of my code):
```d
struct A
{
int[] i;
}
struct B
{
A[] a = [A.init];
}
```

This code:
```d
auto b1 = B.init;
b1.a[0].i ~= 1;
b1.a ~= A.init;
b1.a[0].i ~= 11;
b1.a[1].i ~= 12;
b1.writeln;

auto b2 = B();
b2.writeln;
```
prints this as expected:
```
B([A([1, 11]), A([12])])
B([A([])])
```

But this code:
```d
B b1;  // auto b1 = B.init;
b1.a[0].i ~= 1;
b1.a ~= A.init;
b1.a[0].i ~= 11;
b1.a[1].i ~= 12;
b1.writeln;

B b2; // auto b2 = B();
b2.writeln;
```
prints this which is not expected:
```
B([A([1, 11]), A([12])])
B([A([1])])
```

Does the second piece of code shows a bug or my expectation is 
not correct (and why if so)?


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-10 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Tuesday, 9 November 2021 at 19:30:20 UTC, tchaloupka wrote:

On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote:

Bug or feature? :)


I've reported it in 
https://issues.dlang.org/show_bug.cgi?id=22498.


It doesn't copy. It just destructs the same object twice... Ouch.

Change the destructor to `~this() { printf("~this(%d)\n", n); n = 
12; }` and you'll see.


I have been looking at LDC's IR of this. `unwrap` takes a lvalue, 
but the compiler puts the object from `gen` on main's stack and 
gives a pointer to unwrap instead. `unwrap` is now the sole owner 
of the object, and calls the destructor before returning a ref to 
one of its fields.


I haven't figured out the interplay of features and optimizations 
here, but it looks like a leak. I would have expected @safe to 
catch this.


As you said in the bug, NVRO solves it (not sure why). As well as 
not passing a lvalue into `unwrap` in the first place.


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-09 Thread tchaloupka via Digitalmars-d-learn

On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote:

Bug or feature? :)


I've reported it in 
https://issues.dlang.org/show_bug.cgi?id=22498.


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-08 Thread tchaloupka via Digitalmars-d-learn

On Tuesday, 9 November 2021 at 02:43:55 UTC, jfondren wrote:

On Tuesday, 9 November 2021 at 02:41:18 UTC, jfondren wrote:
The expectation is probably that `f.move` set `f` to 
`Foo.init`, but the docs say:


Posted too fast. Foo qualifies with its @disable:

```d
struct A { int x; }
struct B { int x; @disable this(this); }

unittest {
import core.lifetime : move;
auto a = A(5);
auto b = B(5);
a.move;
b.move;
assert(a == A(5));
assert(b == B(0));
}
```


Yes it should qualify so it should be cleaned out when moved.
When I change:

```D
auto ref unwrap(EX)(auto ref EX res) {
printf("unwrap()\n");
return res.get();
}
```

I get:

```
~this(0)
~this(0)
~this(0)
unwrap()
~this(42)
~this(0)
~this(42)
```

So the destructor isn't called from `gen()` -> there is 
[NRVO](https://dlang.org/glossary.html#nrvo) in play.


Also `pragma(msg, __traits(isRef, res));` prints false in unwrap 
in this case (which is expected), but how it gets there as a 
value when it's not moved and instead copied even though it has 
disabled copy constructor?

`isCopyable!(Value!Foo)` returns false as expected too.


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-08 Thread jfondren via Digitalmars-d-learn

On Tuesday, 9 November 2021 at 02:41:18 UTC, jfondren wrote:
The expectation is probably that `f.move` set `f` to 
`Foo.init`, but the docs say:


Posted too fast. Foo qualifies with its @disable:

```d
struct A { int x; }
struct B { int x; @disable this(this); }

unittest {
import core.lifetime : move;
auto a = A(5);
auto b = B(5);
a.move;
b.move;
assert(a == A(5));
assert(b == B(0));
}
```


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-08 Thread jfondren via Digitalmars-d-learn
On Tuesday, 9 November 2021 at 02:19:28 UTC, Stanislav Blinov 
wrote:

On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote:


```
auto gen() {
Foo f;   // <--- this one
f.n = 42;
return value(f.move());
}

void main() {
Foo f;
f = gen().unwrap.move;
}
```
~this(0)
~this(0)
~this(0)
~this(42) <- this is a copy (that shouldn't exist) being 
destroyed

~this(0)
~this(42)



Is it a copy? I think the first destructor call is one of `f` 
in `gen` (marked by the comment above)


The expectation is probably that `f.move` set `f` to `Foo.init`, 
but the docs say:


"If T is a struct with a destructor or postblit defined, source 
is reset to its .init value after it is moved into target, 
otherwise it is left unchanged."


```d
struct A { int x; }
struct B { int x; this(this) { } }

unittest {
import core.lifetime : move;
auto a = A(5);
auto b = B(5);
a.move;
b.move;
assert(a == A(5));
assert(b == B(0));
}
```


Re: auto ref function parameter causes that non copyable struct is copied?

2021-11-08 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote:


```
auto gen() {
Foo f;   // <--- this one
f.n = 42;
return value(f.move());
}

void main() {
Foo f;
f = gen().unwrap.move;
}
```
~this(0)
~this(0)
~this(0)
~this(42) <- this is a copy (that shouldn't exist) being 
destroyed

~this(0)
~this(42)



Is it a copy? I think the first destructor call is one of `f` in 
`gen` (marked by the comment above)


auto ref function parameter causes that non copyable struct is copied?

2021-11-08 Thread tchaloupka via Digitalmars-d-learn

Lets have this code:

```D
import core.lifetime : forward;
import core.stdc.stdio;
import std.algorithm : move;

struct Value(T) {
private T storage;

this()(auto ref T val) {
storage = forward!val;
}

ref inout(T) get() inout {
return storage;
}
}

Value!T value(T)(auto ref T val) {
return Value!T(forward!val);
}

auto ref unwrap(EX)(auto ref EX res) {
return res.get();
}

struct Foo {
int n;
@disable this(this);
~this() { printf("~this(%d)\n", n); }
}

auto gen() {
Foo f;
f.n = 42;
return value(f.move());
}

void main() {
Foo f;
f = gen().unwrap.move;
}
```

As I understand it unwrap in `f = gen().unwrap.move` can't be 
called by ref (as gen() returns rvalue) so it would force the 
`Value` to be copied but as it holds non copyable struct, it 
can't be and so it should end up with a compiler error.


But the code outputs:
```
~this(0)
~this(0)
~this(0)
~this(42) <- this is a copy (that shouldn't exist) being destroyed
~this(0)
~this(42)
```

This could cause unwanted resource cleanup on a seemingly non 
copyable structs.

Bug or feature? :)


Re: Return values from auto function

2020-11-07 Thread Piotr Mitana via Digitalmars-d-learn

On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov wrote:


struct Result(T)
{
struct Success
{
static if(!is(T == void))
{
T value;
}
}
struct Failure
{
string error;
}

Algebraic!(Success, Failure) result;

this(Success value)
{
result = value;
}
this(Failure value)
{
result = value;
}
}
auto success(T)(T value)
{
return Result!T(Result!T.Success(value));
}
auto failure(string error)
{
return Result!void(Result!void.Failure(error));
}

auto f(int i)
{
return i > 0 ? success(i) : failure("err text"); // Error: 
incompatible types for (success(i)) : (failure("err text")): 
Result!int and Result!void

}


I'd go with:

struct Result(T)
{
Nullable!string error;

static if(!is(T == void))
{
T value;

static Result!T success(T value)
{
return Result!T(Nullable!string.init, value);
}

static Result!T failure(string error)
{
return Result!T(nullable(error), T.init);
}
}

else
{
static Result!T success()
{
return Result!T(Nullable!string.init);
}

static Result!T failure(string error)
{
return Result!T(nullable(error));
}
}

bool isSuccess()
{
return error.isNull();
}
}

// Demo
Result!int intFun(int i)
{
return i > 0 ? Result!int.success(i) : Result!int.failure("Be 
positive!");

}

Result!void voidFun(int i)
{
return i > 0 ? Result!void.success() : 
Result!void.failure("Be positive!");

}

void main()
{
auto intFunRes = intFun(5);

if(intFunRes.isSuccess)
writefln("Result: %d", intFunRes.value);
else
writefln("ERROR: %s", intFunRes.error.get);
}

Does this satisfy your needs?


Re: Return values from auto function

2020-11-07 Thread Jesse Phillips via Digitalmars-d-learn

On Saturday, 7 November 2020 at 15:49:13 UTC, James Blachly wrote:


```
return i > 0 ? cast(Result) Success!int(i) : cast(Result) 
Failure("Sorry");

```



I don't know about the SumType but I would expect you could use a 
construction instead of cast.


import std;
alias Result = Algebraic!(int, string) ;
void main()
{
    auto x = true? Result("fish") : Result(6);

}


Re: Return values from auto function

2020-11-07 Thread Patrick Schluter via Digitalmars-d-learn

On Saturday, 7 November 2020 at 15:49:13 UTC, James Blachly wrote:


```
retval = i > 0 ? Success!int(i) : Failure("Sorry");
```

casting each to `Result` compiles, but is verbose:

```
return i > 0 ? cast(Result) Success!int(i) : cast(Result) 
Failure("Sorry");

```

** Could someone more knowledgeable than me explain why 
implicit conversion does not happen with the ternary op, but 
works fine with if/else? Presumably, it is because the op 
returns a single type and implicit conversion is performed 
after computing the expression's return type? If this somehow 
worked, it would make the SumType package much more ergonomic **


It's just that tenary requires the same type in both branches. It 
was already so in C.



return i > 0 ? (retval = Success!int(i)) : (retval = 
Failure("Sorry"));


should work


Re: Return values from auto function

2020-11-07 Thread James Blachly via Digitalmars-d-learn

On 11/6/20 5:51 AM, Andrey Zherikov wrote:
I have auto function 'f' that might return either an error (with some 
text) or a result (with some value). The problem is that the type of the 
error is not the same as the type of result so compilation fails.



...
How can I make the original code compilable without templatizing 
`failure` function?


Paul Backus has already replied to you so I am surprised he did not plug 
is own package "SumType". Maybe it is modesty? This seems like an ideal 
time to use this.


All of that being said, I tried to solve this for you using Paul's 
SumType package and myself was initially stymied by the fact that the 
implicit conversion of a `Success(T)` or `Failure` type did not work 
within the ternary op expression*. I rewrote it with if/else which works 
great and is only slightly more verbose than with ternary op.


```D
alias Result = SumType!(Success!int, Failure);

auto f(int i)
{
Result retval;
if (i > 0)
retval = Success!int(i);
else
retval = Failure("Sorry!");
return retval;
}
```

the above relies on suitable definition of `Success(T)` and `Failure` 
structs, obviously.


* This fails due to different types within the same expression:

```
retval = i > 0 ? Success!int(i) : Failure("Sorry");
```

casting each to `Result` compiles, but is verbose:

```
return i > 0 ? cast(Result) Success!int(i) : cast(Result) 
Failure("Sorry");

```

** Could someone more knowledgeable than me explain why implicit 
conversion does not happen with the ternary op, but works fine with 
if/else? Presumably, it is because the op returns a single type and 
implicit conversion is performed after computing the expression's return 
type? If this somehow worked, it would make the SumType package much 
more ergonomic **


Re: Return values from auto function

2020-11-07 Thread Andrey Zherikov via Digitalmars-d-learn
On Saturday, 7 November 2020 at 01:50:15 UTC, Jesse Phillips 
wrote:
On Friday, 6 November 2020 at 15:06:18 UTC, Andrey Zherikov 
wrote:
On Friday, 6 November 2020 at 14:58:40 UTC, Jesse Phillips 
wrote:
On Friday, 6 November 2020 at 14:20:40 UTC, Andrey Zherikov 
wrote:
This issue seems hit the inability to implicitly convert 
custom types. May be it makes more sense to ask in a 
separate thread.


The return type must be the same for all execution paths.

Result!void is a different type from Result!int. You aren't 
passing a 'Result' because that doesn't exist as a type.


To clarify my statement:
Yes, Result!void and Result!int are different types but I 
couldn't find a way to implicitly convert one to another.


I'm curious what your semantics would be.

# Result!void => Result!int

How does the type know it can convert to int, or string, or Foo?

What does it mean for a void to be an int?

# Result!int => Result!void

If you have something, what does it mean to go to not having 
that something. Would you really want to implicitly lose that 
something?


Ideally error type shouldn't depend on what type the operation 
returns but language has a limitation that function must return 
single type.


Technically Failure struct can be moved out from Result(T) but 
the issue remains the same: how to convert Failure to Result!T 
for any T.


Re: Return values from auto function

2020-11-06 Thread Jesse Phillips via Digitalmars-d-learn

On Friday, 6 November 2020 at 15:06:18 UTC, Andrey Zherikov wrote:
On Friday, 6 November 2020 at 14:58:40 UTC, Jesse Phillips 
wrote:
On Friday, 6 November 2020 at 14:20:40 UTC, Andrey Zherikov 
wrote:
This issue seems hit the inability to implicitly convert 
custom types. May be it makes more sense to ask in a separate 
thread.


The return type must be the same for all execution paths.

Result!void is a different type from Result!int. You aren't 
passing a 'Result' because that doesn't exist as a type.


To clarify my statement:
Yes, Result!void and Result!int are different types but I 
couldn't find a way to implicitly convert one to another.


Putting aside D not providing implicit conversion to custom types.

I'm curious what your semantics would be.

# Result!void => Result!int

How does the type know it can convert to int, or string, or Foo?

What does it mean for a void to be an int?

# Result!int => Result!void

If you have something, what does it mean to go to not having that 
something. Would you really want to implicitly lose that 
something?




Re: Return values from auto function

2020-11-06 Thread Jesse Phillips via Digitalmars-d-learn
On Friday, 6 November 2020 at 20:05:36 UTC, Ferhat Kurtulmuş 
wrote:
On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov 
wrote:
I have auto function 'f' that might return either an error 
(with some text) or a result (with some value). The problem is 
that the type of the error is not the same as the type of 
result so compilation fails.


[...]


Sounds like Andrei's "Expected". Here is an implementation for 
d. https://github.com/tchaloupka/expected


Hmmm, I wonder how that is different from the idea of 'option'


Re: Return values from auto function

2020-11-06 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov wrote:
I have auto function 'f' that might return either an error 
(with some text) or a result (with some value). The problem is 
that the type of the error is not the same as the type of 
result so compilation fails.


[...]


Sounds like Andrei's "Expected". Here is an implementation for d. 
https://github.com/tchaloupka/expected


Re: Return values from auto function

2020-11-06 Thread Mike Parker via Digitalmars-d-learn

On Friday, 6 November 2020 at 15:06:18 UTC, Andrey Zherikov wrote:


To clarify my statement:
Yes, Result!void and Result!int are different types but I 
couldn't find a way to implicitly convert one to another.


You can't. Structs do not implicitly convert to each other, 
templated or otherwise.


Re: Return values from auto function

2020-11-06 Thread Andrey Zherikov via Digitalmars-d-learn

On Friday, 6 November 2020 at 14:58:40 UTC, Jesse Phillips wrote:
On Friday, 6 November 2020 at 14:20:40 UTC, Andrey Zherikov 
wrote:
This issue seems hit the inability to implicitly convert 
custom types. May be it makes more sense to ask in a separate 
thread.


The return type must be the same for all execution paths.

Result!void is a different type from Result!int. You aren't 
passing a 'Result' because that doesn't exist as a type.


To clarify my statement:
Yes, Result!void and Result!int are different types but I 
couldn't find a way to implicitly convert one to another.


Re: Return values from auto function

2020-11-06 Thread Jesse Phillips via Digitalmars-d-learn

On Friday, 6 November 2020 at 14:20:40 UTC, Andrey Zherikov wrote:

On Friday, 6 November 2020 at 12:03:01 UTC, Paul Backus wrote:
You can't. Both return values have to have the same type, 
which means the failure function has to be able to return more 
than one type, which means it has to be a template.


This issue seems hit the inability to implicitly convert custom 
types. May be it makes more sense to ask in a separate thread.


The return type must be the same for all execution paths.

Result!void is a different type from Result!int. You aren't 
passing a 'Result' because that doesn't exist as a type.


Hopefully one of these captures a misunderstanding.


Re: Return values from auto function

2020-11-06 Thread Andrey Zherikov via Digitalmars-d-learn

On Friday, 6 November 2020 at 12:03:01 UTC, Paul Backus wrote:
You can't. Both return values have to have the same type, which 
means the failure function has to be able to return more than 
one type, which means it has to be a template.


This issue seems hit the inability to implicitly convert custom 
types. May be it makes more sense to ask in a separate thread.


Re: Return values from auto function

2020-11-06 Thread Andrey Zherikov via Digitalmars-d-learn

On Friday, 6 November 2020 at 13:59:58 UTC, gbram wrote:

On Friday, 6 November 2020 at 12:03:01 UTC, Paul Backus wrote:
On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov 
wrote:


How can I make the original code compilable without 
templatizing `failure` function?


You can't. Both return values have to have the same type, 
which means the failure function has to be able to return more 
than one type, which means it has to be a template.


Being pedantic, he can, by templatising 'f' instead.


Could you share how?


Re: Return values from auto function

2020-11-06 Thread gbram via Digitalmars-d-learn

On Friday, 6 November 2020 at 12:03:01 UTC, Paul Backus wrote:
On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov 
wrote:


How can I make the original code compilable without 
templatizing `failure` function?


You can't. Both return values have to have the same type, which 
means the failure function has to be able to return more than 
one type, which means it has to be a template.


Being pedantic, he can, by templatising 'f' instead.


Re: Return values from auto function

2020-11-06 Thread Paul Backus via Digitalmars-d-learn

On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov wrote:
I can make it work if I add a type to `failure` function but 
this remove brevity in usage:

-
auto failure(T)(string error)
{
return Result!T(Result!T.Failure(error));
}
auto f(int i)
{
return i > 0 ? success(i) : failure!int("err text"); // 
no error

}
-

How can I make the original code compilable without 
templatizing `failure` function?


You can't. Both return values have to have the same type, which 
means the failure function has to be able to return more than one 
type, which means it has to be a template.


Return values from auto function

2020-11-06 Thread Andrey Zherikov via Digitalmars-d-learn
I have auto function 'f' that might return either an error (with 
some text) or a result (with some value). The problem is that the 
type of the error is not the same as the type of result so 
compilation fails.


Here is my code:
--
struct Result(T)
{
struct Success
{
static if(!is(T == void))
{
T value;
}
}
struct Failure
{
string error;
}

Algebraic!(Success, Failure) result;

this(Success value)
{
result = value;
}
this(Failure value)
{
result = value;
}
}
auto success(T)(T value)
{
return Result!T(Result!T.Success(value));
}
auto failure(string error)
{
return Result!void(Result!void.Failure(error));
}

auto f(int i)
{
return i > 0 ? success(i) : failure("err text"); // Error: 
incompatible types for (success(i)) : (failure("err text")): 
Result!int and Result!void

}
-

I can make it work if I add a type to `failure` function but this 
remove brevity in usage:

-
auto failure(T)(string error)
{
return Result!T(Result!T.Failure(error));
}
auto f(int i)
{
return i > 0 ? success(i) : failure!int("err text"); // 
no error

}
-

How can I make the original code compilable without templatizing 
`failure` function?




Re: How auto convert Variant to required function arguments?

2020-10-09 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 9 October 2020 at 16:10:03 UTC, Ferhat Kurtulmuş wrote:
On Friday, 9 October 2020 at 15:49:31 UTC, Ferhat Kurtulmuş 
wrote:

On Friday, 9 October 2020 at 00:19:20 UTC, Marcone wrote:

How auto convert Variant to required function arguments?



import std.variant;
import std.stdio;

Variant a;

int mul2(Variant b){
    int c = *b.peek!(int);
    return 2*c;
}

int mul3(int b){
return 3*b;
}

void main()
{
    a = 5;
    writeln(mul2(a));

Variant b = 3;
writeln(mul3(*b.peek!int));
}
Uh, probably this is not what you want. I found this thread: 
https://forum.dlang.org/thread/ebylgcrslkelgrvnt...@forum.dlang.org


You man need to use Algebraic.


may*


Re: How auto convert Variant to required function arguments?

2020-10-09 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 9 October 2020 at 15:49:31 UTC, Ferhat Kurtulmuş wrote:

On Friday, 9 October 2020 at 00:19:20 UTC, Marcone wrote:

How auto convert Variant to required function arguments?



import std.variant;
import std.stdio;

Variant a;

int mul2(Variant b){
    int c = *b.peek!(int);
    return 2*c;
}

int mul3(int b){
return 3*b;
}

void main()
{
    a = 5;
    writeln(mul2(a));

Variant b = 3;
writeln(mul3(*b.peek!int));
}
Uh, probably this is not what you want. I found this thread: 
https://forum.dlang.org/thread/ebylgcrslkelgrvnt...@forum.dlang.org


You man need to use Algebraic.




Re: How auto convert Variant to required function arguments?

2020-10-09 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 9 October 2020 at 00:19:20 UTC, Marcone wrote:

How auto convert Variant to required function arguments?



import std.variant;
import std.stdio;

Variant a;

int mul2(Variant b){
    int c = *b.peek!(int);
    return 2*c;
}

int mul3(int b){
return 3*b;
}

void main()
{
    a = 5;
    writeln(mul2(a));

Variant b = 3;
writeln(mul3(*b.peek!int));
}



How auto convert Variant to required function arguments?

2020-10-08 Thread Marcone via Digitalmars-d-learn

How auto convert Variant to required function arguments?


Re: Annotating SortedRange.empty const: Best way to auto-deduce annotations?

2020-09-02 Thread SimonN via Digitalmars-d-learn
On Wednesday, 2 September 2020 at 21:40:59 UTC, Steven 
Schveighoffer wrote:
What they can do is template the `this` parameter. Then if the 
underlying range supports calling that way, it will work, 
otherwise it won't.


using `template this` should be compatible with the existing 
code I would think.


Thanks! I've never looked much into template this -- at first 
glance, it offers what inout already offers -- but it sounds like 
the right tool for the job. (inout would straightaway disallow 
calls to mutable methods.)


https://dlang.org/spec/template.html#template_this_parameter

I'll experiment with it!

-- Simon


Re: Annotating SortedRange.empty const: Best way to auto-deduce annotations?

2020-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/20 5:23 PM, SimonN wrote:

Hi,

About this issue in Phobos:
https://issues.dlang.org/show_bug.cgi?id=21216
SortedRange.empty should be const, .front should be inout

Just adding const/inout to SortedRange's methods won't be enough; if we 
add const/inout here, then many other Phobos ranges need to become 
const/inout-correct to keep the tests passing. Before I dive deeper into 
annotating their methods, I would like to verify my assumptions on how 
template function attribute deduction works:


1) I know that templated functions deduce their own attributes on 
instantiation. But front()/empty() are non-templated methods within the 
templated struct SortedRange. Will attribute deduction happen here?


mutability attributes are not deducted for templates.

wrapping ranges such as SortedRange can't really specify const or inout 
on their methods via introspection of the underlying range. What they 
can do is template the `this` parameter. Then if the underlying range 
supports calling that way, it will work, otherwise it won't.


using `template this` should be compatible with the existing code I 
would think.


-Steve


Annotating SortedRange.empty const: Best way to auto-deduce annotations?

2020-09-02 Thread SimonN via Digitalmars-d-learn

Hi,

About this issue in Phobos:
https://issues.dlang.org/show_bug.cgi?id=21216
SortedRange.empty should be const, .front should be inout

Just adding const/inout to SortedRange's methods won't be enough; 
if we add const/inout here, then many other Phobos ranges need to 
become const/inout-correct to keep the tests passing. Before I 
dive deeper into annotating their methods, I would like to verify 
my assumptions on how template function attribute deduction works:


1) I know that templated functions deduce their own attributes on 
instantiation. But front()/empty() are non-templated methods 
within the templated struct SortedRange. Will attribute deduction 
happen here?


2) Is it sensible/possible to force attribute deduction by 
declaring empty() in SortedRange as a zero-argument template? 
I.e.:

@property bool empty()() { return this._input.empty; }

3) Should I rather annotate the non-templated 
SortedRange.empty/.front manually? But with what, then? empty() 
should probably be const, but it's never @nogc if annotated 
manually, even if the wrapped range offers empty() @nogc.


-- Simon


Re: safety and auto vectorization

2020-08-04 Thread Andy Balba via Digitalmars-d-learn
On Monday, 3 August 2020 at 19:42:51 UTC, Steven Schveighoffer 
wrote:

On 8/3/20 3:22 PM, Bruce Carneal wrote:


Thanks Steve (and Chad).  Summary: underspecified, varying 
behavior across versions, buggy.


Steve, what's the best way for me to report this?  Are spec 
issues lumped in with the other bugzilla reports?


Yep. You can file under dlang.org with the spec keyword.

Although this looks like it's not exactly a spec issue. I'd 
start it as a dmd bug (I don't know the exact interaction with 
the compiler and the library). It might also be a druntime bug.


-Steve


FWIW   ..using gdc Debian 8.3.0-6,   dst[]= generates a range 
error

auto a = [1, 2, 3];
auto b = [4, 5, 6];
int[] dst = new int[4]; // note the extra element
dst[] = a[] + b[];
writeln(dst[3]);


Re: safety and auto vectorization

2020-08-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/3/20 3:22 PM, Bruce Carneal wrote:


Thanks Steve (and Chad).  Summary: underspecified, varying behavior 
across versions, buggy.


Steve, what's the best way for me to report this?  Are spec issues 
lumped in with the other bugzilla reports?


Yep. You can file under dlang.org with the spec keyword.

Although this looks like it's not exactly a spec issue. I'd start it as 
a dmd bug (I don't know the exact interaction with the compiler and the 
library). It might also be a druntime bug.


-Steve


Re: safety and auto vectorization

2020-08-03 Thread Bruce Carneal via Digitalmars-d-learn
On Monday, 3 August 2020 at 18:55:36 UTC, Steven Schveighoffer 
wrote:

On 8/2/20 1:31 PM, Bruce Carneal wrote:

import std;

void f0(int[] a, int[] b, int[] dst) @safe {
     dst[] = a[] + b[];
}


[snip of auto-vectorization example]


I was surprised that f0 ran just fine with a.length and 
b.length geq dst.length.  Is that a bug or a feature?




First, I think this is a bug. A regression in fact. As of 2.077 
this works, and before it did not. There is nothing in the spec 
that says the behavior is defined for this case.


Second, it's more than just that. This also runs currently:

void main()
{
auto a = [1, 2, 3];
auto b = [4, 5, 6];
int[] dst = new int[4]; // note the extra element
dst[] = a[] + b[];
writeln(dst[3]);
}

Prior to 2.077, this fails with array length problems.

After that it prints (at the moment): 402653184

If I up the size to 5, it fails with a range violation. I 
strongly suspect some off-by-one errors, but this looks unsafe.


-Steve


Thanks Steve (and Chad).  Summary: underspecified, varying 
behavior across versions, buggy.


Steve, what's the best way for me to report this?  Are spec 
issues lumped in with the other bugzilla reports?









Re: safety and auto vectorization

2020-08-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/2/20 1:31 PM, Bruce Carneal wrote:

import std;

void f0(int[] a, int[] b, int[] dst) @safe {
     dst[] = a[] + b[];
}

void f1(int[] a, int[] b, int[] dst) @trusted {
     const minLen = min(a.length, b.length, dst.length);
     dst[0..minLen] = a[0..minLen] + b[0..minLen];
     assert(dst.length == minLen);
}

I was surprised that f0 ran just fine with a.length and b.length geq 
dst.length.  Is that a bug or a feature?


Assuming it's a feature, are f0 and f1 morally equivalent?  I ask 
because f1 auto-vectorizes in ldc while f0 does not.  Not sure why.  As 
a guess I'd say that the front end doesn't hoist bounds checks in f0 or 
at least doesn't convey the info to the back end in a comprehensible 
fashion.  Non-guesses welcome.


First, I think this is a bug. A regression in fact. As of 2.077 this 
works, and before it did not. There is nothing in the spec that says the 
behavior is defined for this case.


Second, it's more than just that. This also runs currently:

void main()
{
auto a = [1, 2, 3];
auto b = [4, 5, 6];
int[] dst = new int[4]; // note the extra element
dst[] = a[] + b[];
writeln(dst[3]);
}

Prior to 2.077, this fails with array length problems.

After that it prints (at the moment): 402653184

If I up the size to 5, it fails with a range violation. I strongly 
suspect some off-by-one errors, but this looks unsafe.


-Steve


Re: safety and auto vectorization

2020-08-03 Thread Chad Joan via Digitalmars-d-learn

On Sunday, 2 August 2020 at 17:31:45 UTC, Bruce Carneal wrote:

import std;

void f0(int[] a, int[] b, int[] dst) @safe {
dst[] = a[] + b[];
}

void f1(int[] a, int[] b, int[] dst) @trusted {
const minLen = min(a.length, b.length, dst.length);
dst[0..minLen] = a[0..minLen] + b[0..minLen];
assert(dst.length == minLen);
}

I was surprised that f0 ran just fine with a.length and 
b.length geq dst.length.  Is that a bug or a feature?


Assuming it's a feature, are f0 and f1 morally equivalent?  I 
ask because f1 auto-vectorizes in ldc while f0 does not.  Not 
sure why.  As a guess I'd say that the front end doesn't hoist 
bounds checks in f0 or at least doesn't convey the info to the 
back end in a comprehensible fashion.  Non-guesses welcome.


I don't know what's going on auto-vectorization-wise, but to 
address the behavioral issues, the next thing I would do if I 
were in your shoes is something like this:


import std.stdio;
int[100]  a, b, dst;
a[]   = 2;
b[]   = 3;
dst[] = 42;
f0(a[0..$], b[0..$], dst[0..50]); // Notice: dst is a smaller 
slice.

writefln("dst[49] == %d", dst[49]); // Should be 5.
writefln("dst[50] == %d", dst[50]); // 42 or 5?

On my machine (Linux 64-bit DMD v2.093.0) it prints this:
dst[49] == 5
dst[50] == 42

Which suggests that it is doing the minimum-length calculation, 
as the dst[] values outside of the lesser-sized slice were 
untouched.


This was DMD, so it's going to be worth trying on your compiler 
to see what you get.


safety and auto vectorization

2020-08-02 Thread Bruce Carneal via Digitalmars-d-learn

import std;

void f0(int[] a, int[] b, int[] dst) @safe {
dst[] = a[] + b[];
}

void f1(int[] a, int[] b, int[] dst) @trusted {
const minLen = min(a.length, b.length, dst.length);
dst[0..minLen] = a[0..minLen] + b[0..minLen];
assert(dst.length == minLen);
}

I was surprised that f0 ran just fine with a.length and b.length 
geq dst.length.  Is that a bug or a feature?


Assuming it's a feature, are f0 and f1 morally equivalent?  I ask 
because f1 auto-vectorizes in ldc while f0 does not.  Not sure 
why.  As a guess I'd say that the front end doesn't hoist bounds 
checks in f0 or at least doesn't convey the info to the back end 
in a comprehensible fashion.  Non-guesses welcome.







Re: Finding out ref-ness of the return of an auto ref function

2020-06-13 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 13 June 2020 at 09:13:36 UTC, Arafel wrote:

If, however, you're wrapping a function template, however, you 
won't know until you actually instantiate it, which is 
basically going back to Paul Backus' solution. So the compiler 
doesn't always have all the information :)


Well, the compiler can know `typeof (return)`, so at that point 
and under the same circumstances it has know (and thus it could 
expose) the ref-ness.


And it does, for functions, via the aforementioned trait. It 
can't for templates until those templates are instantiated, which 
you can only do correctly by actually forwarding arguments to it 
(because a function template may have auto ref parameters).


Steven's issue report doesn't account for templates, nor 
overloading, and correctly testing the latter would pretty much 
require you to match argument types and ref-ness by hand anyway 
(yuck).


Re: Finding out ref-ness of the return of an auto ref function

2020-06-13 Thread Arafel via Digitalmars-d-learn

On 12/6/20 20:34, Stanislav Blinov wrote:

On Friday, 12 June 2020 at 17:50:43 UTC, Arafel wrote:

All in all, I still think something like `__traits(isRef,return)` 
would still be worth adding! After all the compiler already has all 
the information, so it's just about exposing it. I'm trying to think 
of a library solution, but I find it very hard to express "the 
hypothetical result of calling the current function with the current 
parameters in the current context".


A.


If you're wrapping a function you can use a 'getFunctionAttributes' 
trait [1], which would contain a "ref" if that function returns ref.


If, however, you're wrapping a function template, however, you won't 
know until you actually instantiate it, which is basically going back to 
Paul Backus' solution. So the compiler doesn't always have all the 
information :)


[1] https://dlang.org/spec/traits.html#getFunctionAttributes


Well, the compiler can know `typeof (return)`, so at that point and 
under the same circumstances it has know (and thus it could expose) the 
ref-ness.


Also there could be a better and more straightforward way of checking if 
an expression would be an l-value... it seems it's not the first time it 
has appeared:


https://issues.dlang.org/show_bug.cgi?id=15634

The forum thread linked in the bug report is also quite interesting.


Re: Finding out ref-ness of the return of an auto ref function

2020-06-12 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 12 June 2020 at 17:50:43 UTC, Arafel wrote:

All in all, I still think something like 
`__traits(isRef,return)` would still be worth adding! After all 
the compiler already has all the information, so it's just 
about exposing it. I'm trying to think of a library solution, 
but I find it very hard to express "the hypothetical result of 
calling the current function with the current parameters in the 
current context".


A.


If you're wrapping a function you can use a 
'getFunctionAttributes' trait [1], which would contain a "ref" if 
that function returns ref.


If, however, you're wrapping a function template, however, you 
won't know until you actually instantiate it, which is basically 
going back to Paul Backus' solution. So the compiler doesn't 
always have all the information :)


[1] https://dlang.org/spec/traits.html#getFunctionAttributes


Re: Finding out ref-ness of the return of an auto ref function

2020-06-12 Thread Arafel via Digitalmars-d-learn

On 12/6/20 18:15, Paul Backus wrote:


I think I have something that works:

ref int foo();
int bar();

enum isLvalue(string expr) = q{
     __traits(compiles, (auto ref x) {
     static assert(__traits(isRef, x));
     }(} ~ expr ~ q{))
};

pragma(msg, mixin(isLvalue!"foo()")); // true
pragma(msg, mixin(isLvalue!"bar()")); // false

Basically, you can pass the result of the function call to a function 
with an `auto ref` parameter and check whether that parameter is 
inferred as ref or not.


Thanks a lot!

I have to say, it works, it's really, really clever... but it's also 
ugly as hell, and feels like a kludge. I had already tried something 
similar with an identity function, but I couldn't make it 
compile-time... I was missing the "compiles"+"static assert" trick.


Also, it can become quite hard to check from within the function 
itself... in my case it's more or less doable because it's basically a 
forwarding, so I'm essentially doing a simple mixin, but in a more 
complex case (with perhaps even static ifs and whatever) I can see it 
becoming essentially unmanageable.


All in all, I still think something like `__traits(isRef,return)` would 
still be worth adding! After all the compiler already has all the 
information, so it's just about exposing it. I'm trying to think of a 
library solution, but I find it very hard to express "the hypothetical 
result of calling the current function with the current parameters in 
the current context".


A.


Re: Finding out ref-ness of the return of an auto ref function

2020-06-12 Thread Paul Backus via Digitalmars-d-learn

On Friday, 12 June 2020 at 14:56:41 UTC, Arafel wrote:

Hi all,

I'm hitting a problem that it's making crazy... is there any 
way to find out if the return of an `auto ref` function is 
actually ref or not?


So, according to the documentation [1] it depends on the return 
expressions... however in my case I'm implementing `opDispatch` 
in a wrapper type (and trying to carry over the ref-ness), so I 
don't know how can I check it.


Now, the whole point of this wrapper is to act differently 
based on whether the return is a reference or not (it already 
checks for `hasIndirections`, which btw doesn't help here 
either).


I've tried to use `__traits(isRef, ??? ) but I haven't been 
able to find out how to use it, it seems to be meant for 
parameters. Perhaps it would make sense to have something like 
`traits(isRef, return)`?


Also I have tried making two different overloads, with and 
without ref, but it didn't work either...


A.


[1]: https://dlang.org/spec/function.html#auto-ref-functions


I think I have something that works:

ref int foo();
int bar();

enum isLvalue(string expr) = q{
__traits(compiles, (auto ref x) {
static assert(__traits(isRef, x));
}(} ~ expr ~ q{))
};

pragma(msg, mixin(isLvalue!"foo()")); // true
pragma(msg, mixin(isLvalue!"bar()")); // false

Basically, you can pass the result of the function call to a 
function with an `auto ref` parameter and check whether that 
parameter is inferred as ref or not.


Finding out ref-ness of the return of an auto ref function

2020-06-12 Thread Arafel via Digitalmars-d-learn

Hi all,

I'm hitting a problem that it's making crazy... is there any way to find 
out if the return of an `auto ref` function is actually ref or not?


So, according to the documentation [1] it depends on the return 
expressions... however in my case I'm implementing `opDispatch` in a 
wrapper type (and trying to carry over the ref-ness), so I don't know 
how can I check it.


Now, the whole point of this wrapper is to act differently based on 
whether the return is a reference or not (it already checks for 
`hasIndirections`, which btw doesn't help here either).


I've tried to use `__traits(isRef, ??? ) but I haven't been able to find 
out how to use it, it seems to be meant for parameters. Perhaps it would 
make sense to have something like `traits(isRef, return)`?


Also I have tried making two different overloads, with and without ref, 
but it didn't work either...


A.


[1]: https://dlang.org/spec/function.html#auto-ref-functions


Re: I want Sublime 3 D auto import !

2020-06-04 Thread Виталий Фадеев via Digitalmars-d-learn

On Thursday, 4 June 2020 at 04:48:22 UTC, bauss wrote:

On Wednesday, 3 June 2020 at 11:54:57 UTC, Виталий Фадеев wrote:

On Tuesday, 2 June 2020 at 20:08:09 UTC, bauss wrote:
What happens if you have the same symbol in multiple modules? 
Ex. two libraries that implement symbols with same name.


Is there a way to be selective?


I want it too! :)


Updated:
- implemented simple way to be selective !




Re: I want Sublime 3 D auto import !

2020-06-03 Thread bauss via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 11:54:57 UTC, Виталий Фадеев wrote:

On Tuesday, 2 June 2020 at 20:08:09 UTC, bauss wrote:
What happens if you have the same symbol in multiple modules? 
Ex. two libraries that implement symbols with same name.




First module will inserted.


Is there a way to be selective?


I want it too! :)


And what about keyboard shortcut?


A specially for you !

Sublime 3 / Preferences / Key bindings:
[
{ "keys": ["alt+a"], "command": "dlang_auto_import" },
]


Thanks, that's great!


Re: I want Sublime 3 D auto import !

2020-06-03 Thread Виталий Фадеев via Digitalmars-d-learn

On Tuesday, 2 June 2020 at 20:08:09 UTC, bauss wrote:
What happens if you have the same symbol in multiple modules? 
Ex. two libraries that implement symbols with same name.




First module will inserted.


Is there a way to be selective?


I want it too! :)


And what about keyboard shortcut?


A specially for you !

Sublime 3 / Preferences / Key bindings:
[
{ "keys": ["alt+a"], "command": "dlang_auto_import" },
]


Re: I want Sublime 3 D auto import !

2020-06-03 Thread aberba via Digitalmars-d-learn

On Monday, 1 June 2020 at 17:28:16 UTC, Johannes Loher wrote:

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:

[...]


Demanding stuff usually doesn't work in this community. The 
usual answer is something like this: If you care about this, 
implement it yourself or pay somebody to do it.


Depends on how you interpret it.


Re: I want Sublime 3 D auto import !

2020-06-02 Thread bauss via Digitalmars-d-learn

On Tuesday, 2 June 2020 at 06:00:10 UTC, Виталий Фадеев wrote:

On Monday, 1 June 2020 at 18:55:03 UTC, Paul Backus wrote:

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:


I do it!

https://github.com/vitalfadeev/SublimeDlangAutoImport


What happens if you have the same symbol in multiple modules? Ex. 
two libraries that implement symbols with same name.


Is there a way to be selective? And what about keyboard shortcut?


Re: I want Sublime 3 D auto import !

2020-06-02 Thread welkam via Digitalmars-d-learn

On Tuesday, 2 June 2020 at 06:00:10 UTC, Виталий Фадеев wrote:

On Monday, 1 June 2020 at 18:55:03 UTC, Paul Backus wrote:

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:


I do it!

https://github.com/vitalfadeev/SublimeDlangAutoImport


Cool. I dont use classe but I see how this kind of functionality 
might be useful for other symbols.


Re: I want Sublime 3 D auto import !

2020-06-02 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 2 June 2020 at 06:00:10 UTC, Виталий Фадеев wrote:

On Monday, 1 June 2020 at 18:55:03 UTC, Paul Backus wrote:

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:


I do it!

https://github.com/vitalfadeev/SublimeDlangAutoImport


Great! You should make a post about it in the Announce forum, so 
that other Sublime Text users will see it.


Re: I want Sublime 3 D auto import !

2020-06-02 Thread Виталий Фадеев via Digitalmars-d-learn

On Monday, 1 June 2020 at 18:55:03 UTC, Paul Backus wrote:

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:


I do it!

https://github.com/vitalfadeev/SublimeDlangAutoImport



Re: I want Sublime 3 D auto import !

2020-06-01 Thread Paul Backus via Digitalmars-d-learn

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:

I want Sublime D auto import !

When typing code like this:


class Uno : IStylable
{
//
}


I want will be auto added "import IStylable" at begin of file. 
Like this:



import ui.istylable : IStylable;

class Uno : IStylable
{
//
}


1. I want for plugin will scan all files in project, and grep 
for "module ".

2. Then "module " replaced to "import ".
3. Then "import " inserted in text. At top. After line 
"module ..." if it exist, else just at top.

4. Check for "module " not exists before insert.


Your best bet for getting IDE-like features like this is probably 
to use serve-d [1] together with a language server client plugin 
for your editor [2].


[1] https://github.com/Pure-D/serve-d
[2] https://github.com/sublimelsp/LSP


Re: I want Sublime 3 D auto import !

2020-06-01 Thread Johannes Loher via Digitalmars-d-learn

On Monday, 1 June 2020 at 16:18:44 UTC, Виталий Фадеев wrote:

I want Sublime D auto import !

When typing code like this:


class Uno : IStylable
{
//
}


I want will be auto added "import IStylable" at begin of file. 
Like this:



import ui.istylable : IStylable;

class Uno : IStylable
{
//
}


1. I want for plugin will scan all files in project, and grep 
for "module ".

2. Then "module " replaced to "import ".
3. Then "import " inserted in text. At top. After line 
"module ..." if it exist, else just at top.

4. Check for "module " not exists before insert.


Demanding stuff usually doesn't work in this community. The usual 
answer is something like this: If you care about this, implement 
it yourself or pay somebody to do it.




I want Sublime 3 D auto import !

2020-06-01 Thread Виталий Фадеев via Digitalmars-d-learn

I want Sublime D auto import !

When typing code like this:


class Uno : IStylable
{
//
}


I want will be auto added "import IStylable" at begin of file. 
Like this:



import ui.istylable : IStylable;

class Uno : IStylable
{
//
}


1. I want for plugin will scan all files in project, and grep for 
"module ".

2. Then "module " replaced to "import ".
3. Then "import " inserted in text. At top. After line 
"module ..." if it exist, else just at top.

4. Check for "module " not exists before insert.




Re: Is there a way to tell if an auto ref parameter is by ref or by value?

2020-05-10 Thread NaN via Digitalmars-d-learn

On Sunday, 10 May 2020 at 01:15:58 UTC, Anonymouse wrote:

On Sunday, 10 May 2020 at 00:33:07 UTC, NaN wrote:

Ie something like..


auto Foo(T)(auto ref T x)
{
static if (isByRef(x))
{
}
else
{
}
}


__traits(isRef, x)


Thanks :)


Re: Is there a way to tell if an auto ref parameter is by ref or by value?

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

On Sunday, 10 May 2020 at 00:33:07 UTC, NaN wrote:

Ie something like..


auto Foo(T)(auto ref T x)
{
static if (isByRef(x))
{
}
else
{
}
}


__traits(isRef, x)


Is there a way to tell if an auto ref parameter is by ref or by value?

2020-05-09 Thread NaN via Digitalmars-d-learn

Ie something like..


auto Foo(T)(auto ref T x)
{
static if (isByRef(x))
{
}
else
{
}
}


Re: How make DMD auto link imported modules?

2020-04-21 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 21 April 2020 at 21:36:57 UTC, Marcone wrote:
When I create a module, for exemple mymodule.d and import im my 
main program using "import mymodule" I need add mymodule.d in 
DMD command line manually. How can make it automatic?


dmd -i


How make DMD auto link imported modules?

2020-04-21 Thread Marcone via Digitalmars-d-learn
When I create a module, for exemple mymodule.d and import im my 
main program using "import mymodule" I need add mymodule.d in DMD 
command line manually. How can make it automatic?


Re: auto vectorization notes

2020-03-28 Thread Bruce Carneal via Digitalmars-d-learn

On Saturday, 28 March 2020 at 18:01:37 UTC, Crayo List wrote:

On Saturday, 28 March 2020 at 06:56:14 UTC, Bruce Carneal wrote:

On Saturday, 28 March 2020 at 05:21:14 UTC, Crayo List wrote:

On Monday, 23 March 2020 at 18:52:16 UTC, Bruce Carneal wrote:

[snip]
Explicit SIMD code, ispc or other, isn't as readable or 
composable or vanilla portable but it certainly is performance 
predictable.


This is not true! The idea of ispc is to write portable code 
that will
vectorize predictably based on the target CPU. The object 
file/binary is not portable,

if that is what you meant.
Also, I find it readable.



There are many waypoints on the readability <==> performance 
axis.  If ispc works for you along that axis, great!


I find SIMT code readability better than SIMD but a little 
worse than auto-vectorizable kernels.  Hugely better 
performance though for less effort than SIMD if your platform 
supports it.


Again I don't think this is true. Unless I am misunderstanding 
you, SIMT and SIMD
are not mutually exclusive and if you need performance then you 
must use both.
Also based on the workload and processor SIMD may be much more 
effective than SIMT.j


SIMD might become part of the solution under the hood for a 
number of reasons including: ease of deployment, programmer 
familiarity, PCIe xfer overheads, kernel launch overhead, memory 
subsystem suitability, existing code base issues, ...


SIMT works for me in high throughput situations where it's hard 
to "take a log" on the problem.  SIMD, in auto-vectorizable or 
more explicit form, works in others.


Combinations can be useful but most of the work I've come in 
contact with splits pretty clearly along the memory bandwidth 
divide (SIMT on one side, SIMD/CPU on the other).  Others need a 
plus-up in arithmetic horsepower.  The more extreme the 
requirements, the more attractive SIMT appears. (hence my 
excitement about dcompute possibly expanding the dlang 
performance envelope with much less cognitive load than 
CUDA/OpenCL/SycL/...)


On the readability front, I find per-lane programming, even with 
the current thread-divergence caveats, to be easier to reason 
about wrt correctness and performance predictability than other 
approaches.  Apparently your mileage does vary.


When you have chosen SIMD, whether ispc or other, over SIMT what 
drove the decision?  Performance?  Ease of programming to reach a 
target speed?



















  1   2   3   4   5   6   7   >