Re: using enums as key in associative array

2011-03-08 Thread Jonathan M Davis
On Tuesday, March 08, 2011 07:40:08 spir wrote:
> On 03/08/2011 03:48 PM, Jonathan M Davis wrote:
> > I really don't understand your problem with module constructors. They're
> > fantastic.
> 
> I may be wrong, but I think this point of view is a "where I can from"
> statement. C's char* are fantastic when you have never used a PL with
> builtin strings. There are languages in which you don't need to list twice
> everything just to have them available at import time.
> 
> // data definition
> X foo;
> Y bar;
> Z baz;
> ...
> static this {
> foo = ...;
> bar = ...;
> baz = ...;
> ...
> }

In one case, you're declaring a variable. In another, you're giving it a value. 
They're two _very_ different things. In one case, you're telling the compiler 
that a particular variable exists. In the other, you're giving it a value.

Generally, it is ideal to give a variable its initial value (and final value if 
it's not mutable) when you declare it, and there's no question that CTFE is 
currently not as good as we'd like in that regard. However, there are plenty of 
cases where it makes no sense to give a variable its initial value at compile 
time. So, given that D requires that _all_ module variables, class/struct 
variables, and member variables which are directly initialized have that value 
known at compile time, you have to do it separately to do it runtime. Also, 
there are plenty of cases where there are dependcies between variables such 
that 
you need to actually give them values within a function rather than statically. 
Constructors do a beautiful job of dealing with this problem.

The main alternative is to allow you to set module, class/struct,  and member 
variables directly at runtime. Languages such as C++ and Java do this, and it 
causes a host of problems. The order of initialization isn't necessarily 
defined. 
It's possible to end up using variables before they're actually initialized. 
Compilation is slower because of all of the interdependencies, whereas in D 
it's 
possible to parallelize a lot of what the compiler does with declarations, 
because they're not interdependent like they are in C++ or Java. Not to 
mention, 
if you want to be able to initialize them in a manner which requires you to 
essentially have a function rather than set them directly, then you _need_ 
something like a constructor to initialize them. Also, you don't get compile 
time evaluation of variables in languages like C/C++ and Java like you do in D, 
so _every_ variable is initialized at runtime. The occasional irritation with 
the current implementation problems of CTFE is _well_ worth the gain in compile 
time evaluation.

D uses a model similar to C/C++ and Java, but it improves on it _considerably_ 
by doing things the way it does. The order of initialization in D is _well-
defined_ and not bug-prone. It also lends itself to efficient compilation. 
Granted, 
until CTFE is able to do anything in SafeD (as its intended to do eventually), 
there are going to be irritating restrictions with regards to what we can and 
can't initialize directly using CTFE, but that's an implementation detail which 
will improve. D's design in this regard is excellent.

- Jonathan M Davis


Re: using enums as key in associative array

2011-03-08 Thread Wilfried Kirschenmann
>>
>> I really don't understand your problem with module constructors. They're
>> fantastic.
>
> I may be wrong, but I think this point of view is a "where I can from"
> statement. C's char* are fantastic when you have never used a PL with
> builtin strings. There are languages in which you don't need to list twice
> everything just to have them available at import time.
>
> // data definition
> X foo;
> Y bar;
> Z baz;
> ...
> static this {
>   foo = ...;
>   bar = ...;
>   baz = ...;
>   ...
> }
>

The question is : what are in the dots :
static this {
// get information from environment
...
// load information from a module configuration file
...
// make some complex computation
...

// initialize data in any order
baz = ...;
bar = ...;
foo = functionOf(baz, bar);
}

This way, you have made independent the initialization of a module
from the initialization of the user's application.

However, I agree to the fact that for statically known value (such as
my first example), this far from optimal.

Wilfried


Re: using enums as key in associative array

2011-03-08 Thread spir

On 03/08/2011 03:48 PM, Jonathan M Davis wrote:

I really don't understand your problem with module constructors. They're
fantastic.


I may be wrong, but I think this point of view is a "where I can from" 
statement. C's char* are fantastic when you have never used a PL with builtin 
strings. There are languages in which you don't need to list twice everything 
just to have them available at import time.


// data definition
X foo;
Y bar;
Z baz;
...
static this {
   foo = ...;
   bar = ...;
   baz = ...;
   ...
}

Denis
--
_
vita es estrany
spir.wikidot.com



Re: using enums as key in associative array

2011-03-08 Thread Jonathan M Davis
On Tuesday 08 March 2011 04:54:45 spir wrote:
> On 03/08/2011 09:26 AM, Wilfried Kirschenmann wrote:
> >>> enum deviceType {cpu, gpu}
> >>> auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];
> >> 
> >> The way to get what you want to work in this case is to use a module
> >> constructor. So, you'd do something like this:
> >> 
> >> string[deviceType] execDeviceSuffix;
> >> 
> >> static this()
> >> {
> >> 
> >> execDeviceSuffix[deviceType.cpu] = "cpu";
> >> execDeviceSuffix[deviceType.gpu] = "gpu";
> >> 
> >> }
> >> 
> >> The module constructor will be run before main does, so execDeviceSuffix
> >> will be properly filled in by then.
> > 
> > I didn't get to the point where module constructors are introduced in
> > Andrei's book yet. I really like this idea !
> > I found a similar workaround which used an useless class so that I
> > could use the static constructor but this is even better !
> 
> This is a very nice feature, yes. But I personly see it as a workaround for
> the limitation that dmd, apparently, is not able to correctly evaluate
> many kinds of assignment expressions. And it's ugly when one has hordes of
> definitions -- the module is (mainly) a piece of data description: all
> symbols must first be declared /outside/, then redefined /inside/ static
> this(). Else, D would be a great data-definition language, in addition to
> its other qualities, thank to its literals for everything (and conversely
> its standard to!string for everything, which needs improvements). Think a
> static Lua.

??? It's for stuff that has to be defined at runtime. There's plenty of stuff 
that 
_has_ to be done at runtime and could _never_ be done at compile time no matter 
how great the language is. For instance, what if you want to have a variable 
with the time that the program started running? You certainly couldn't do that 
at compile time. Sure, there are things that you'd ideally be able to set with 
CTFE and currenly can't, but it's not like a better CTFE would negate the need 
for static constructors.

And honestly, in other cases, such as when you have to use a module constructor 
because of interdependencies between variables when initializing them and 
they're mutable, the fact that you can't do that at compile time is 
_fantastic_. 
In other programming languages, you run into problems because of the order of 
evaluation of the declarations of such variables. D makes them it so the order 
truly doesn't matter, because when it does, you have to use a module 
constructor. That's _huge_.

I really don't understand your problem with module constructors. They're 
fantastic.

- Jonathan M Davis


Re: using enums as key in associative array

2011-03-08 Thread spir

On 03/08/2011 09:26 AM, Wilfried Kirschenmann wrote:

enum deviceType {cpu, gpu}
auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];



The way to get what you want to work in this case is to use a module
constructor. So, you'd do something like this:

string[deviceType] execDeviceSuffix;

static this()
{
execDeviceSuffix[deviceType.cpu] = "cpu";
execDeviceSuffix[deviceType.gpu] = "gpu";
}

The module constructor will be run before main does, so execDeviceSuffix will be
properly filled in by then.


I didn't get to the point where module constructors are introduced in
Andrei's book yet. I really like this idea !
I found a similar workaround which used an useless class so that I
could use the static constructor but this is even better !


This is a very nice feature, yes. But I personly see it as a workaround for the 
limitation that dmd, apparently, is not able to correctly evaluate many kinds 
of assignment expressions. And it's ugly when one has hordes of definitions -- 
the module is (mainly) a piece of data description: all symbols must first be 
declared /outside/, then redefined /inside/ static this(). Else, D would be a 
great data-definition language, in addition to its other qualities, thank to 
its literals for everything (and conversely its standard to!string for 
everything, which needs improvements). Think a static Lua.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: using enums as key in associative array

2011-03-08 Thread Wilfried Kirschenmann
>> enum deviceType {cpu, gpu}
>> auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];

> The way to get what you want to work in this case is to use a module
> constructor. So, you'd do something like this:
>
> string[deviceType] execDeviceSuffix;
>
> static this()
> {
>        execDeviceSuffix[deviceType.cpu] = "cpu";
>        execDeviceSuffix[deviceType.gpu] = "gpu";
> }
>
> The module constructor will be run before main does, so execDeviceSuffix will 
> be
> properly filled in by then.

I didn't get to the point where module constructors are introduced in
Andrei's book yet. I really like this idea !
I found a similar workaround which used an useless class so that I
could use the static constructor but this is even better !


Re: using enums as key in associative array

2011-03-07 Thread Ali Çehreli

On 03/07/2011 11:16 AM, Jonathan M Davis wrote:
> On Monday, March 07, 2011 07:22:47 Wilfried Kirschenmann wrote:

>> enum deviceType {cpu, gpu}
>> auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];

[...]

>> This won't compile and give the error:
>> Error: non-constant expression
>> [cast(deviceType)0:".cpu",cast(deviceType)1:".gpu"]

[...]

> The way to get what you want to work in this case is to use a module
> constructor. So, you'd do something like this:
>
> string[deviceType] execDeviceSuffix;
>
> static this()
> {
>execDeviceSuffix[deviceType.cpu] = "cpu";
>execDeviceSuffix[deviceType.gpu] = "gpu";
> }

This works too:

static this()
{
execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];
}

Ali



Re: using enums as key in associative array

2011-03-07 Thread Jonathan M Davis
On Monday, March 07, 2011 07:22:47 Wilfried Kirschenmann wrote:
> Hi,
> 
> I'm a beginner in D; I have just begun the book from Andrei.
> 
> I would like to know how to statically declare an associative array whose
> key are enums.
> 
> example :
> #!../dmd2/linux/bin/rdmd
> 
> import std.stdio, std.string;
> 
> enum deviceType {cpu, gpu}
> auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];
> 
> void main(){
>   foreach(deviceSuffix; execDeviceSuffix.values) writeln(deviceSuffix);
> }
> 
> 
> This won't compile and give the error:
> Error: non-constant expression
> [cast(deviceType)0:".cpu",cast(deviceType)1:".gpu"]
> 
> I have two questions :
> 1) Why are there casts in the error message ?
> Are the enums always substituted by with their base type ?

You can use an enum where it's base type is required without any kind of casts. 
You do have to cast going the other way though. I'm quite sure why the cast is 
shown, but I believe that the compiler just replaces the enum variable with its 
value everywhere that it's used, and when printing enum variables, you get 
their 
value, which in this case would be indistinguishable from 0 in the case of 
deviceType.cpu. So, what's _probably_ happening is that it's replacing the enum 
variable with its value as well as a cast to the enum type (just like you would 
have to do if you used 0 directly).

> 2) where is the non constant part in this expression ?
> Both the deviceType enum and the strings are constant.
> 
> Thank you for your help !

I believe that the problem is that it doesn't consider the associative array to 
be constant. Not everything with associative arrays works with CTFE (compile 
time function evaluation) yet. I believe that if you use an associative array 
in 
a function used at compile time but the associative array isn't assigned to a 
global variable or anything which would stick around beyond compile time, it 
works, but it doesn't work if you try and keep the associative array beyond 
compile time (as you're obviously trying to do here). Most things that involve 
memory allocation on the heap fail at compile time (arrays are about the only 
exception, I believe, and I think that even they fail at times). Eventually, it 
is hoped that CTFE will reach the point that anything in SafeD will be valid, 
but it's not there yet. For the moment, you tend to need to try and use CTFE 
the 
way you'd want to and then fall back to setting the values at runtime where you 
can't.

The way to get what you want to work in this case is to use a module 
constructor. So, you'd do something like this:

string[deviceType] execDeviceSuffix;

static this()
{
execDeviceSuffix[deviceType.cpu] = "cpu";
execDeviceSuffix[deviceType.gpu] = "gpu";
}

The module constructor will be run before main does, so execDeviceSuffix will 
be 
properly filled in by then.

- Jonathan M Davis


using enums as key in associative array

2011-03-07 Thread Wilfried Kirschenmann
Hi,

I'm a beginner in D; I have just begun the book from Andrei.

I would like to know how to statically declare an associative array whose
key are enums.

example :
#!../dmd2/linux/bin/rdmd

import std.stdio, std.string;

enum deviceType {cpu, gpu}
auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];

void main(){
  foreach(deviceSuffix; execDeviceSuffix.values) writeln(deviceSuffix);
}


This won't compile and give the error:
Error: non-constant expression
[cast(deviceType)0:".cpu",cast(deviceType)1:".gpu"]

I have two questions :
1) Why are there casts in the error message ?
Are the enums always substituted by with their base type ?

2) where is the non constant part in this expression ?
Both the deviceType enum and the strings are constant.

Thank you for your help !

-
Cordialement,
Wilfried Kirschenmann

"An expert is a person who has made all the mistakes that can be made in a
very narrow field."*
*Niels Bohr - *Danish physicist (1885 - 1962)*