Jump to page: 1 2 3
Thread overview
Casting by assigning to the right ...
Apr 14, 2020
Manfred Nowak
Apr 14, 2020
Manfred Nowak
Apr 14, 2020
Manfred Nowak
Apr 15, 2020
12345swordy
Apr 14, 2020
Mathias LANG
Apr 14, 2020
Manfred Nowak
Apr 14, 2020
aliak
Apr 14, 2020
Manfred Nowak
Apr 15, 2020
aliak
Apr 15, 2020
Manfred Nowak
Apr 15, 2020
aliak
Apr 15, 2020
Manfred Nowak
Apr 15, 2020
Paul Backus
Apr 15, 2020
Manfred Nowak
Apr 15, 2020
H. S. Teoh
Apr 15, 2020
Manfred Nowak
Apr 14, 2020
Paul Backus
Apr 14, 2020
Manfred Nowak
Re: Result (was: Casting by assigning to the right ...)
Apr 15, 2020
Manfred Nowak
April 14, 2020
... is already builtin via properties.

After declaring
```
struct S{ int data;}
S s;
int i;
```

one often would like to implicitly cast the value of the structure by typing
```
i= s;
```

According to the logged changes ( https://digitalmars.com/d/2.0/changelog.html) a thought on this was published in 2008/03 for D2.012: `opImplicitCast', but not implemented since.

Therefore one still has to introduce an `opCast' into `S' and then write
```
i= cast( int)  s;
```

I do not like to always correctly examine the type of the variable I am assigning to ( `i' in this case) for using that type in the `cast()' and came up with the idea to no more assign to the left but to the right:
```
s.castTo =i;
```

Of course one has to define the property `castTo' within `S', but that has the signature
  `void castTo( ref int arg)'
which is as simple as the signature of `opCast'. A runnable example follows. What do you think?


```
struct S{
  string data;
  int opCast( T: int)(){
      import std.conv: to;
    return to!int( data);
  }
  void castTo( ref int arg){
    arg= cast( int)  this;
  }
}
void main(){
  auto s= S( "42");
  int i;
  s.castTo =i;
    import std.stdio;
  writeln( i);
}
```
April 14, 2020
On 4/14/20 1:56 AM, Manfred Nowak wrote:
> According to the logged changes ( https://digitalmars.com/d/2.0/changelog.html) a thought on this was published in 2008/03 for D2.012: `opImplicitCast', but not implemented since.

The feature was implemented in a way, it's called alias this:

struct S
{
  int i;
  alias i this;
}

auto s = S(5);

int i = s;

assert(i == 5);

Note that at this time, only one alias this is allowed per structure.

-Steve
April 14, 2020
On Tuesday, 14 April 2020 at 05:56:39 UTC, Manfred Nowak wrote:
> ... is already builtin via properties.
>
> After declaring
> ```
> struct S{ int data;}
> S s;
> int i;
> ```
>
> one often would like to implicitly cast the value of the structure by typing
> ```
> i= s;
> ```

There's two easy ways to accomplish this:
```
struct S
{
    int data_;

    version (OpAssign) ref S opAssign (int v) { this.data_ = v; return this; }
    version (AliasThis)
    {
        @property ref int data (int v) { this.data_ = v; return this.data_; }
        alias data this;
    }
}

void main ()
{
    S s;
    int i;
    s = i;
}
```

Which one you pick depends on your design. I would recommend the `OpAssign` version by default.
April 14, 2020
On Tuesday, 14 April 2020 at 06:10:33 UTC, Steven Schveighoffer wrote:
> Note that at this time, only one alias this is allowed per structure.

This restriction falls by the suggested scheme:

```
struct S{
  string data;
    import std.conv: to;
  void castTo( ref int arg){
    arg= to!int( data);
  }
  void castTo( ref string arg){
    arg= data;
  }
}
void main(){
  auto s= S( "42");

  int i;
  s.castTo =i;

  string str;
  s.castTo =str;

    import std.stdio;
  writeln( i, ":", str); // 42:42
}
```
April 14, 2020
On Tuesday, 14 April 2020 at 06:15:14 UTC, Mathias LANG wrote:
[...]
>       ref S opAssign (int v) { this.data_ = v; return this; }
[...]
>     s = i;

With `opAssign' the value of `i' is assigned to `this.data_', but that is not the intended direction. From `this.data_' to `i' is intended ... and for several more types of variables.

Please see my reply to Steven:
https://forum.dlang.org/post/qdzvuduycklkhjesnyei@forum.dlang.org
April 14, 2020
On 4/14/20 2:44 AM, Manfred Nowak wrote:
> On Tuesday, 14 April 2020 at 06:10:33 UTC, Steven Schveighoffer wrote:
>> Note that at this time, only one alias this is allowed per structure.
> 
> This restriction falls by the suggested scheme:
> 
> ```
> struct S{
>    string data;
>      import std.conv: to;
>    void castTo( ref int arg){
>      arg= to!int( data);
>    }
>    void castTo( ref string arg){
>      arg= data;
>    }
> }
> void main(){
>    auto s= S( "42");
> 
>    int i;
>    s.castTo =i;
> 
>    string str;
>    s.castTo =str;
> 
>      import std.stdio;
>    writeln( i, ":", str); // 42:42
> }
> ```

Yes, I was responding to the point talking about opImplicitCast. Instead of that, we got alias this.

Proposals have been started to add multiple alias this. I think many consider alias this in general to be a troublesome feature that could have been done better. I don't know what will happen with it.

I would recommend not using the = syntax to denote the opposite of what it normally means (that the rhs is being assigned). You are better off I think just calling it like a function:

s.castTo(i);
s.castTo(str);

Without knowing what castTo is supposed to do, if I saw s.castTo = i, I would not expect at all that i is going to change.

-Steve
April 14, 2020
On Tuesday, 14 April 2020 at 05:56:39 UTC, Manfred Nowak wrote:
> ... is already builtin via properties.
>
> After declaring
> ```
> struct S{ int data;}
> S s;
> int i;
> ```
>
> one often would like to implicitly cast the value of the structure by typing
> ```
> i= s;
> ```
>
> According to the logged changes ( https://digitalmars.com/d/2.0/changelog.html) a thought on this was published in 2008/03 for D2.012: `opImplicitCast', but not implemented since.
>
> Therefore one still has to introduce an `opCast' into `S' and then write
> ```
> i= cast( int)  s;
> ```
>
> I do not like to always correctly examine the type of the variable I am assigning to ( `i' in this case) for using that type in the `cast()' and came up with the idea to no more assign to the left but to the right:
> ```
> s.castTo =i;
> ```
>
> Of course one has to define the property `castTo' within `S', but that has the signature
>   `void castTo( ref int arg)'
> which is as simple as the signature of `opCast'. A runnable example follows. What do you think?
>
>
> ```
> struct S{
>   string data;
>   int opCast( T: int)(){
>       import std.conv: to;
>     return to!int( data);
>   }
>   void castTo( ref int arg){
>     arg= cast( int)  this;
>   }
> }
> void main(){
>   auto s= S( "42");
>   int i;
>   s.castTo =i;
>     import std.stdio;
>   writeln( i);
> }
> ```

Always a fan of generalizing patterns as long as they are readable! So I would agree with Steven that

s.castTo = i

would be a bit confusing to review. And:

s.castTo(i);

would also be confusing in that it sounds like it's casting s to i as in, turning s in to an i. But it's hard to know what that can actually mean.

Also, you can make it a generic free function if you want. I.e. turn this:

struct S {
  void castTo( ref int arg){
    arg= cast( int)  this;
  }
}

to:

void castTo(Source, Dest)(ref Source source, ref Dest dest) {
  dest = cast(Dest)source;
}

And now you can have your i on the left hand side and maybe name it something like castAssign and have code that reads like

i.castAssign(s); // cast and assign s
April 14, 2020
On Tuesday, 14 April 2020 at 05:56:39 UTC, Manfred Nowak wrote:
> ```
> i= cast( int)  s;
> ```
>
> I do not like to always correctly examine the type of the variable I am assigning to ( `i' in this case) for using that type in the `cast()' and came up with the idea to no more assign to the left but to the right:

You can avoid the need to look up the type by using `typeof`:

i = cast(typeof(i)) s;
April 14, 2020
On Tuesday, 14 April 2020 at 14:50:29 UTC, Paul Backus wrote:
> You can avoid the need to look up the type by using `typeof`:
>
> i = cast(typeof(i)) s;

Yes. But it is unnecessary bloat of about 15 chars. I would rather annotate my knowledge of implicit-cast-assigning by writing:
  `i:= s;'

April 14, 2020
On Tuesday, 14 April 2020 at 13:03:19 UTC, aliak wrote:
> Also, you can make it a generic free function if you want.
[...]
> i.castAssign(s); // cast and assign s

And because the pair of parenthesis can by exchanged by a `=', giving
  `i   .castAssign=   s;'
you just evaluated, that there is in addition to  {+, -, *, /, %, ^^, &, |, ^, <<, >>, >>>, ~} an additional bunch of ops for the op-assignment-operator giving the resulting form in regular language parlor:
  '.' ident '='

Allowing ident to be an empty string would even include `.=' to be recognized as an assignment operator. This is very close to the assignment operator in pascal `:='.

What is the better annotation of a coder knowing, that a cast is being executed under the hood: `._=' or `:='?

« First   ‹ Prev
1 2 3