March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Wed, Mar 27, 2013 at 05:04:48PM +0100, bearophile wrote: [...] > >- When casting a value to an enum, there's no checking that the value actually is a valid enum value. Don't think I ever found a solution on how to check whether the value after casting is a valid enum value, it hasn't been a pressing issue. > > cast() is a sharp unsafe tool. In Bugzilla I have a request to use > to!() to perform that safely. [...] It already does that on latest git phobos: enum A { abc=100, def=200 } A a; a = to!A(150); // throws runtime exception T -- All problems are easy in retrospect. |
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Wed, Mar 27, 2013 at 12:52:25PM -0400, Nick Sabalausky wrote: > On Wed, 27 Mar 2013 16:34:19 +0100 > "Vidar Wahlberg" <vidar.wahlberg@gmail.com> wrote: [...] > > - While the "auto"-keyword often is great, it can lead to difficulties, especially when used as the return type of a function, such as "auto foo() { return bar; }". Sometimes you may wish to store the result of a function/method call as a global variable/class member, but when the function/method returns "auto" it's not apparent what the data type may be. While you may be able to find out what "bar" is by digging in the source code, > > Here's the trick I like to use: > > // Some var with unknown type > auto var = ...; > pragma(msg, "var: " ~ typeof(var).stringof); > > That will print something like this at compile-time: > > var: int > > Unfortunately (or fortunately, depending on your point of view), it ignores all convenience aliases and will always give you the *full* original concrete static type, instead of any prettied-up aliases for it, but it does work and gets the job done. What's wrong with using typeof? auto var = ...; typeof(var) anotherVar; ... anotherVar = var; [...] > > - When casting a value to an enum, there's no checking that the value actually is a valid enum value. Don't think I ever found a solution on how to check whether the value after casting is a valid enum value, it hasn't been a pressing issue. > > > > Honestly, I hate that, too. The problem is that enum is (unfortunately) intended to do double-duty as a bitfield so you can do something like this: > > enum Options > { > FeatureA = 0b0000_0001; > FeatureB = 0b0000_0010; > FeatureC = 0b0000_0100; > FeatureD = 0b0000_1000; > // etc... > } > > // Use features A and C > auto myOptions = Options.FeatureA | Options.FeatureC; > > That possibility means that D *can't* check for validity as you suggest. As a compromise for now, I'd just use std.conv.to for when I want enum values checked. In any case, using casts should be avoided in D unless there's no other way around it. Casting is a @system-level operation, and most application code shouldn't be using it. > I'm convinced that scenario *should* be considered an entirely separate thing because cramming it together with regular enumerations creates conflicting goals with the two usages of "enum", and forces unfortunate design compromises with both. [...] Yeah, I find using enums for bitfields a bit ugly. I mean, I love using bitfields too (don't know if this is because of my C/C++ background tending toward premature optimization) but conflating them with enums that supposedly should have unique values is IMO a language smell. (And don't get me started on enums being manifest constants instead of "real" enums... I still find that jarring.) T -- Marketing: the art of convincing people to pay for what they didn't need before which you can't deliver after. |
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 03/27/2013 05:04 PM, deadalnix wrote: > On Wednesday, 27 March 2013 at 15:34:20 UTC, Vidar Wahlberg wrote: >> ... > >> - While the "auto"-keyword often is great, it can lead to >> difficulties, especially when used as the return type of a function, >> such as "auto foo() { return bar; }". Sometimes you may wish to store >> the result of a function/method call as a global variable/class >> member, but when the function/method returns "auto" it's not apparent >> what the data type may be. While you may be able to find out what >> "bar" is by digging in the source code, it can still be difficult to >> find. One example is to save the result of "std.regex.match()" as a >> member in a class. For me the solution was to "import std.traits", >> create a function "auto matchText(string text) { return match(text, >> myRegex); }" and define the class member as "ReturnType!matchText >> matchResult;" (do also note that function & member must come in the >> right order for this to compile). This was all but obvious to a novice >> D coder as myself, the solution was suggested to me in the IRC channel. >> > > Yes, I have to say that it is a pain sometime. Additionally, it have > some rough edges you may want to know : > - Function that never return are inferred void. I would have preferred > typeof(null) as void lead to many static and repetitive code for nothing > when doing metaprograming. I strongly disagree. What would be an example of the problems you are apparently experiencing? > - Type inference handle very poorly recursion. It should simply > exclude the recursion when doing type inference as it won't change the > return type. The error message can be very opaque. The cases that are allowed would need to be specified more rigorously. > - In some cases, you have to add explicit casts when implicit would > have been enough in theory (but the type inference mechanism is confused). > > ... > >> - "Foo foo = new Foo();" for global variables/class members. Now you >> must "Foo foo; static this() { foo = new Foo(); }". > > Yes, as it imply an heap allocation. It is an harder problem that it > seems as all thoses object could reference themselves. Just serialize the CTFE object graph into the static data segment. |
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Wednesday, 27 March 2013 at 16:52:27 UTC, Nick Sabalausky wrote:
> Honestly, I hate that, too. The problem is that enum is (unfortunately)
> intended to do double-duty as a bitfield so you can do something like
> this:
>
> enum Options
> {
> FeatureA = 0b0000_0001;
> FeatureB = 0b0000_0010;
> FeatureC = 0b0000_0100;
> FeatureD = 0b0000_1000;
> // etc...
> }
>
> // Use features A and C
> auto myOptions = Options.FeatureA | Options.FeatureC;
>
> That possibility means that D *can't* check for validity as you suggest.
>
It can. myOptions is an int here, as Options would decay to its base type.
|
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Wednesday, 27 March 2013 at 17:23:01 UTC, Timon Gehr wrote: > On 03/27/2013 05:04 PM, deadalnix wrote: >> On Wednesday, 27 March 2013 at 15:34:20 UTC, Vidar Wahlberg >>> ... >>> - "Foo foo = new Foo();" for global variables/class members. Now you >>> must "Foo foo; static this() { foo = new Foo(); }". >> >> Yes, as it imply an heap allocation. It is an harder problem that it >> seems as all thoses object could reference themselves. > > Just serialize the CTFE object graph into the static data segment. I believe that's what this pull aims to do: https://github.com/D-Programming-Language/dmd/pull/1724 |
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Wed, 27 Mar 2013 13:32:06 -0400, deadalnix <deadalnix@gmail.com> wrote:
> On Wednesday, 27 March 2013 at 16:52:27 UTC, Nick Sabalausky wrote:
>> Honestly, I hate that, too. The problem is that enum is (unfortunately)
>> intended to do double-duty as a bitfield so you can do something like
>> this:
>>
>> enum Options
>> {
>> FeatureA = 0b0000_0001;
>> FeatureB = 0b0000_0010;
>> FeatureC = 0b0000_0100;
>> FeatureD = 0b0000_1000;
>> // etc...
>> }
>>
>> // Use features A and C
>> auto myOptions = Options.FeatureA | Options.FeatureC;
>>
>> That possibility means that D *can't* check for validity as you suggest.
>>
>
> It can. myOptions is an int here, as Options would decay to its base type.
No, it's not. try it. I thought as you did too until recently.
And before you go checking, it's not a bug, it's functioning per the spec.
-Steve
|
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Wednesday, 27 March 2013 at 17:23:01 UTC, Timon Gehr wrote: > I strongly disagree. What would be an example of the problems you are apparently experiencing? > T foo(alias fallback)() { // Do some processing return the result. If an error occurs use fallback mechanism. } Reasonable thing to do as fallback is to try another method workaround the error, throw, whatever. The problem is that the fallback type inference makes it painful to work with, especially if fallback is a template itself. For instance, in SDC, you can parse ambiguous things as follow : parseTypeOrExpression!((parsed) { static if(is(typeof(parsed) : Expression)) { // Do something } else { throw SomeException(); } })(tokenRange); This is bound to fail. When a function never return, it make no sens to force a type on it and the magic subtype typeof(null) should be used (as typeof(null) can cast to anything, it is valid to call the function in any condition). |
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wednesday, 27 March 2013 at 17:36:46 UTC, Steven Schveighoffer wrote:
> On Wed, 27 Mar 2013 13:32:06 -0400, deadalnix <deadalnix@gmail.com> wrote:
>
>> On Wednesday, 27 March 2013 at 16:52:27 UTC, Nick Sabalausky wrote:
>>> Honestly, I hate that, too. The problem is that enum is (unfortunately)
>>> intended to do double-duty as a bitfield so you can do something like
>>> this:
>>>
>>> enum Options
>>> {
>>> FeatureA = 0b0000_0001;
>>> FeatureB = 0b0000_0010;
>>> FeatureC = 0b0000_0100;
>>> FeatureD = 0b0000_1000;
>>> // etc...
>>> }
>>>
>>> // Use features A and C
>>> auto myOptions = Options.FeatureA | Options.FeatureC;
>>>
>>> That possibility means that D *can't* check for validity as you suggest.
>>>
>>
>> It can. myOptions is an int here, as Options would decay to its base type.
>
> No, it's not. try it. I thought as you did too until recently.
>
I knew the bug existed, but I thought it would be solved now. If it is how the spec specify it, then it is a spec bug and a compiler bug.
|
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Wed, 27 Mar 2013 18:32:06 +0100
"deadalnix" <deadalnix@gmail.com> wrote:
> On Wednesday, 27 March 2013 at 16:52:27 UTC, Nick Sabalausky wrote:
> > Honestly, I hate that, too. The problem is that enum is
> > (unfortunately)
> > intended to do double-duty as a bitfield so you can do
> > something like
> > this:
> >
> > enum Options
> > {
> > FeatureA = 0b0000_0001;
> > FeatureB = 0b0000_0010;
> > FeatureC = 0b0000_0100;
> > FeatureD = 0b0000_1000;
> > // etc...
> > }
> >
> > // Use features A and C
> > auto myOptions = Options.FeatureA | Options.FeatureC;
> >
> > That possibility means that D *can't* check for validity as you suggest.
> >
>
> It can. myOptions is an int here, as Options would decay to its base type.
Options myOptions = Options.FeatureA | Options.FeatureC;
|
March 27, 2013 Re: My thoughts & experiences with D so far, as a novice D coder | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | Nick Sabalausky:
> enum Options
> {
> FeatureA = 0b0000_0001;
> FeatureB = 0b0000_0010;
> FeatureC = 0b0000_0100;
> FeatureD = 0b0000_1000;
> // etc...
> }
>
> // Use features A and C
> auto myOptions = Options.FeatureA | Options.FeatureC;
>
> That possibility means that D *can't* check for validity as you suggest.
>
> I'm convinced that scenario *should* be considered an entirely separate
> thing because cramming it together with regular enumerations creates
> conflicting goals with the two usages of "enum", and forces unfortunate
> design compromises with both.
This was discussed in past. A library code BitFlags similar to struct bitfields is probably able to solve most of this problem in a mostly type safe way. If you want a built-in solution, with a @bitflags, you will have to wait longer.
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation