April 23, 2009
Daniel Keep wrote:
> 
> Andrei Alexandrescu wrote:
>> Joel C. Salomon wrote:
>>> Just as (1) & (2) point to a way to remove the “magic” of built-in
>>> arrays & hash-tables, so too might (5) & (6) point to a way of replacing
>>> the “new T(args)” syntax with something cleaner?  Not that
>>> “new!(T)(args)” looks nicer than the current syntax, but is it perhaps a
>>> better fit with the rest of the language?
>> I agree. new sucks.
>>
>> Andrei
> 
> Oh I don't know, I rather like being able to allocate stuff on the heap.
>  I mean, if I didn't, the poor heap would probably be very lonely.
> 
> Poor, poor oft-maligned heap; all because he's a bit slower than stack
> allocation and needs to be cleaned up after.  He's trying to help, you know!
> 
> Joking aside, what do you have in mind?  Every solution I come up with
> ends up being more or less the same (except with the 'new' keyword in a
> different place) or worse.

I don't know. Here's what we need:

1. Create one heap object of type T with creation arguments args. Currently: new T(args), except when T is a variable-sized array in which case syntax is new T[arg] (only one arg allowed). It is next to impossible to create one heap object of fixed-size array type.

2. Create one array T[] of size s and initialize its elements from a range or generator function. Currently possible via a function that internally uses GC calls.

3. Create one array T[] of a size s and do not initialize content. Currently possible by calling GC functions. Probably not really needed because it's not that safe anyway.



Andrei
April 24, 2009

Andrei Alexandrescu wrote:
> Daniel Keep wrote:
>>
>> Andrei Alexandrescu wrote:
>>> Joel C. Salomon wrote:
>>>> Just as (1) & (2) point to a way to remove the “magic” of built-in
>>>> arrays & hash-tables, so too might (5) & (6) point to a way of
>>>> replacing
>>>> the “new T(args)” syntax with something cleaner?  Not that
>>>> “new!(T)(args)” looks nicer than the current syntax, but is it
>>>> perhaps a
>>>> better fit with the rest of the language?
>>> I agree. new sucks.
>>>
>>> Andrei
>>
>> Oh I don't know, I rather like being able to allocate stuff on the heap.
>>  I mean, if I didn't, the poor heap would probably be very lonely.
>>
>> Poor, poor oft-maligned heap; all because he's a bit slower than stack allocation and needs to be cleaned up after.  He's trying to help, you know!
>>
>> Joking aside, what do you have in mind?  Every solution I come up with ends up being more or less the same (except with the 'new' keyword in a different place) or worse.
> 
> I don't know. Here's what we need:
> 
> 1. Create one heap object of type T with creation arguments args. Currently: new T(args), except when T is a variable-sized array in which case syntax is new T[arg] (only one arg allowed). It is next to impossible to create one heap object of fixed-size array type.

Actually,

> new T[](size);

This works just fine.  I do think that (new T[n]) should be of type
T[n], not T[].

> 2. Create one array T[] of size s and initialize its elements from a range or generator function. Currently possible via a function that internally uses GC calls.
>
> 3. Create one array T[] of a size s and do not initialize content. Currently possible by calling GC functions. Probably not really needed because it's not that safe anyway.
> 
> Andrei

Perhaps have these overloads for object.Array!(T)...

> new T[](size_t, T)
> new T[](size_t, S) if isInputRange!(S)

As for the uninitialised case, I don't think it's that important, either.

<dreaming>

That said...

Assuming I'm allowed to make language changes, I'd be tempted to make void a valid type for variables and arguments, and also make it double as an expression.  That is, void is a literal of type void with value void, the ONLY valid value for voids.  Then, you could have:

> auto a = new T[](n, void);

I've always been annoyed that you can't have void variables or arguments; it always seems to complicate my beautiful generic code :'(

> ReturnTypeOf!(Fn) wrap(alias Fn)(ParameterTypeTuple!(Fn) args)
> {
>     logf("> ",Fn.stringof,args);
>     auto result = Fn(args);
>     logf("< ",Fn.stringof,args);
> }

That works only so long as Fn doesn't return a void.  And before anyone suggests it, this trick:

> return Fn(args);

only works in trivial cases; it doesn't help if you need to be able to DO something after the function call.

</dreaming>

  -- Daniel
April 24, 2009
Andrei Alexandrescu schrieb:
> dennis luehring wrote:
>> Andrei Alexandrescu schrieb:
>>> 1. Put array definitions in object.d. Have the compiler rewrite "T[]" ->
>>> ".Array!(T)" and "[ a, b, c ]" -> ".Array!(typeof(a))(a, b, c)". I think
>>> superdan suggested that when he wasn't busy cursing :o).
>>>
>>> 2. Do the similar thing for associative arrays.
>>>
>>> 3. Have two object.d at hand: one is "normal" and uses garbage
>>> collection, the other (call it object_nogc.d) has an entirely different
>>> definition for arrays, hashes, and Object.
>> 
>> question about debug code speed:
>> 
>> a far as i understand it now is the code-speed of (assoc) arrays independent from the debug-code-generator because of the buildinness
>> 
>> i ask because i hate the speed of std::vectors/maps at debug-time
>> especially when it comes to large datasets - my major slowdown in prototype development comes then from the awfully slow stl containers - does D suffer from this - or will it, when you add this extension?
> 
> I think we'll be in better shape than debug stl because ranges are inherently cheaper to check. But only testing will tell.

not only iterating is awfully slow - also the pushing of data

(i can clearly say that my simple stl container based volume simulation
is nearly not debugable because of the amount of data needed to get into an debugable state) - so im working only with release versions - and start to convert my (c++)modules into relaseable c-interfaced dlls
(just to be able to debug the main-code) - and this situation is an absolut prototyping no-go

please: always test if your extensions to containers do not harm the "debugging" speed - the stl is best example of killing this part of prototype-test-programm-cycle







April 24, 2009
dennis luehring schrieb:
> Andrei Alexandrescu schrieb:
>> dennis luehring wrote:
>>> Andrei Alexandrescu schrieb:
>>>> 1. Put array definitions in object.d. Have the compiler rewrite "T[]" ->
>>>> ".Array!(T)" and "[ a, b, c ]" -> ".Array!(typeof(a))(a, b, c)". I think
>>>> superdan suggested that when he wasn't busy cursing :o).
>>>>
>>>> 2. Do the similar thing for associative arrays.
>>>>
>>>> 3. Have two object.d at hand: one is "normal" and uses garbage
>>>> collection, the other (call it object_nogc.d) has an entirely different
>>>> definition for arrays, hashes, and Object.
>>> 
>>> question about debug code speed:
>>> 
>>> a far as i understand it now is the code-speed of (assoc) arrays independent from the debug-code-generator because of the buildinness
>>> 
>>> i ask because i hate the speed of std::vectors/maps at debug-time
>>> especially when it comes to large datasets - my major slowdown in prototype development comes then from the awfully slow stl containers - does D suffer from this - or will it, when you add this extension?
>> 
>> I think we'll be in better shape than debug stl because ranges are inherently cheaper to check. But only testing will tell.
> 
> not only iterating is awfully slow - also the pushing of data
> 
> (i can clearly say that my simple stl container based volume simulation
> is nearly not debugable because of the amount of data needed to get into an debugable state) - so im working only with release versions - and start to convert my (c++)modules into relaseable c-interfaced dlls
> (just to be able to debug the main-code) - and this situation is an absolut prototyping no-go
> 
> please: always test if your extensions to containers do not harm the "debugging" speed - the stl is best example of killing this part of prototype-test-programm-cycle

does that also mean that strings are getting template based?

what amount of debug-code will produce this? like with the stl (or boost) - zillion megabytes for 9 lines of code? and i can throw away my debugger (if D will get a good one)

im always shocked when looking at the stl/boost based assembler code in debug releases - does D generate less code?


April 24, 2009
Sean Kelly Wrote:

> I've always been careful to say that array and
> AA operations will leak if linked against this lib.

You can remove leaking operations from druntime and leaking application won't link.
April 24, 2009
Andrei Alexandrescu Wrote:

> 1. Create one heap object of type T with creation arguments args. Currently: new T(args), except when T is a variable-sized array in which case syntax is new T[arg] (only one arg allowed). It is next to impossible to create one heap object of fixed-size array type.

You can create it. new T[arg] does just that. You can't *use* it.
T[5]* arr=something;
arr[3]; //wrong
(*arr)[3]; //ok

And as it was said, current new syntax allows arguments for array new.
April 24, 2009
On Fri, 24 Apr 2009 08:47:49 +0400, Daniel Keep <daniel.keep.lists@gmail.com> wrote:

>
>
> Andrei Alexandrescu wrote:
>> Daniel Keep wrote:
>>>
>>> Andrei Alexandrescu wrote:
>>>> Joel C. Salomon wrote:
>>>>> Just as (1) & (2) point to a way to remove the “magic” of built-in
>>>>> arrays & hash-tables, so too might (5) & (6) point to a way of
>>>>> replacing
>>>>> the “new T(args)” syntax with something cleaner?  Not that
>>>>> “new!(T)(args)” looks nicer than the current syntax, but is it
>>>>> perhaps a
>>>>> better fit with the rest of the language?
>>>> I agree. new sucks.
>>>>
>>>> Andrei
>>>
>>> Oh I don't know, I rather like being able to allocate stuff on the heap.
>>>  I mean, if I didn't, the poor heap would probably be very lonely.
>>>
>>> Poor, poor oft-maligned heap; all because he's a bit slower than stack
>>> allocation and needs to be cleaned up after.  He's trying to help, you
>>> know!
>>>
>>> Joking aside, what do you have in mind?  Every solution I come up with
>>> ends up being more or less the same (except with the 'new' keyword in a
>>> different place) or worse.
>>
>> I don't know. Here's what we need:
>>
>> 1. Create one heap object of type T with creation arguments args.
>> Currently: new T(args), except when T is a variable-sized array in which
>> case syntax is new T[arg] (only one arg allowed). It is next to
>> impossible to create one heap object of fixed-size array type.
>
> Actually,
>
>> new T[](size);
>
> This works just fine.  I do think that (new T[n]) should be of type
> T[n], not T[].
>
>> 2. Create one array T[] of size s and initialize its elements from a
>> range or generator function. Currently possible via a function that
>> internally uses GC calls.
>>
>> 3. Create one array T[] of a size s and do not initialize content.
>> Currently possible by calling GC functions. Probably not really needed
>> because it's not that safe anyway.
>>
>> Andrei
>
> Perhaps have these overloads for object.Array!(T)...
>
>> new T[](size_t, T)
>> new T[](size_t, S) if isInputRange!(S)
>

I agree these overloads belong to Array.

> As for the uninitialised case, I don't think it's that important, either.
>
> <dreaming>
>
> That said...
>
> Assuming I'm allowed to make language changes, I'd be tempted to make
> void a valid type for variables and arguments, and also make it double
> as an expression.  That is, void is a literal of type void with value
> void, the ONLY valid value for voids.  Then, you could have:
>
>> auto a = new T[](n, void);
>

This is a nice idea!

> I've always been annoyed that you can't have void variables or
> arguments; it always seems to complicate my beautiful generic code :'(
>
>> ReturnTypeOf!(Fn) wrap(alias Fn)(ParameterTypeTuple!(Fn) args)
>> {
>>     logf("> ",Fn.stringof,args);
>>     auto result = Fn(args);
>>     logf("< ",Fn.stringof,args);
      return result;
>> }
>
> That works only so long as Fn doesn't return a void.  And before anyone
> suggests it, this trick:
>
>> return Fn(args);
>
> only works in trivial cases; it doesn't help if you need to be able to
> DO something after the function call.
>
> </dreaming>
>
>   -- Daniel

Yes, I've hit the same issue a lot of times, although scope(exit)/scope(success) usually helps.

April 24, 2009
Andrei Alexandrescu Wrote:
> 1. Put array definitions in object.d. Have the compiler rewrite "T[]" ->
> ".Array!(T)" and "[ a, b, c ]" -> ".Array!(typeof(a))(a, b, c)". I think
> superdan suggested that when he wasn't busy cursing :o).

While I'd support such a rewriting of builtin arrays and associative arrays, it comes at a cost: one template instantiation per contained type, which will lead to more code and TypeInfo / ClassInfo initializers than the current implementation requires.

Can you come up with a solution that can seamlessly switch between RTTI based containers and templated containers?

April 24, 2009
Andrei Alexandrescu wrote:
> There shouldn't be any harm in using Array or AssocArray directly.

How about __Array or something? I already have a struct Array!()
April 24, 2009
Christian Kamm wrote:
> Andrei Alexandrescu Wrote:
>> 1. Put array definitions in object.d. Have the compiler rewrite "T[]" ->
>> ".Array!(T)" and "[ a, b, c ]" -> ".Array!(typeof(a))(a, b, c)". I think
>> superdan suggested that when he wasn't busy cursing :o).
> 
> While I'd support such a rewriting of builtin arrays and associative arrays,
> it comes at a cost: one template instantiation per contained type, which will lead to more code and TypeInfo / ClassInfo initializers than the current
> implementation requires.
> 
> Can you come up with a solution that can seamlessly switch between RTTI
> based containers and templated containers?

Good question. I don't know how the typeinfo could go away, but right now we're in that boat already - each T[] has its own typeinfo. Implementation-wise, there are techniques to reduce code bloating.

Andrei