April 28, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tomas Lindquist Olsen | On Tue, 28 Apr 2009 22:13:50 +0400, Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> wrote:
> On Tue, Apr 28, 2009 at 6:07 PM, MLT <none@anon.com> wrote:
>> 2. char[] vs. int[]
>> I think it is strange that
>> char[] x = "1234" ;
>> x[0] = '4' ;
>>
>> Produces a run time error, but
>> int[] x = [1,2,3,4] ;
>> x[0] = 4 ;
>> Doesn't. I think that they both should, or both shouldn't - to be
>> consistent (and it would be better if they both didn't). Best would be
>> again, to allow the programmer to specify where the array (or other
>> stuff) should be stored.
>>
>
> It pretty much boils down to this (mostly said in other replies)
>
> * string literals are special, they are allocated in a static data segment, readonly if the platform allows it.
>
> * arrayliterals as non-static expressions are always heap allocated. even when there's absolute no need for it... (see http://d.puremagic.com/issues/show_bug.cgi?id=2356 )
>
> -Tomas
Someone ought to post a feature request to make arrayliterals immutable by default (D2 only, I don't think this change will go to D1 anyway) and don't heap-allocate them every time they're used:
int[] x1 = [1,2,3,4]; // error: can't assign immutable(int)[] to int[]
int[] x2 = [1,2,3,4].dup; // okay, allocates
int[4] x3 = [1,2,3,4]; // okay, doesn't allocate
foreach (int i; [1,2,3,4]) { // okay, doesn't allocate
// ...
}
| |||
April 28, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin | Denis Koroskin wrote: > On Tue, 28 Apr 2009 22:13:50 +0400, Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> wrote: > >> On Tue, Apr 28, 2009 at 6:07 PM, MLT <none@anon.com> wrote: >>> 2. char[] vs. int[] >>> I think it is strange that >>> char[] x = "1234" ; >>> x[0] = '4' ; >>> >>> Produces a run time error, but >>> int[] x = [1,2,3,4] ; >>> x[0] = 4 ; >>> Doesn't. I think that they both should, or both shouldn't - to be consistent (and it would be better if they both didn't). Best would be again, to allow the programmer to specify where the array (or other stuff) should be stored. >>> >> It pretty much boils down to this (mostly said in other replies) >> >> * string literals are special, they are allocated in a static data >> segment, readonly if the platform allows it. >> >> * arrayliterals as non-static expressions are always heap allocated. >> even when there's absolute no need for it... (see >> http://d.puremagic.com/issues/show_bug.cgi?id=2356 ) >> >> -Tomas > > Someone ought to post a feature request to make arrayliterals immutable by default (D2 only, I don't think this change will go to D1 anyway) and don't heap-allocate them every time they're used: > > int[] x1 = [1,2,3,4]; // error: can't assign immutable(int)[] to int[] Why not auto-allocate? Writing that .dup all the time is going to be annoying. Just implicitly convert it from immutable to mutable by copying. > int[] x2 = [1,2,3,4].dup; // okay, allocates > > int[4] x3 = [1,2,3,4]; // okay, doesn't allocate > > foreach (int i; [1,2,3,4]) { // okay, doesn't allocate > // ... > } | |||
April 28, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to grauzone | On Tue, 28 Apr 2009 22:50:28 +0400, grauzone <none@example.net> wrote:
>> I belive it could be implemented as a library type, using Scope(T) template:
>
> I don't like that approach to replace random language features by templates at all. And in this case, you really have to ask WHY?
>
> It's nice that it's possible, but there are some reasons that speak
> against this approach:
> 1. it's harder to understand in general (even if the language definition
> becomes smaller)
> 2. error messages turn into an incomprehensible mess
> 3. puts more stress on the compiler and it gets slower (you will
> understand when you have to _wait_ for your project to finish
> compilation, even if you use the superfast dmd)
>
>> class Foo
>> {
>> Scope!(Bar) _bar;
>> }
>
> Would typeof(_bar) == Bar?
>
No way! But Scope!(Bar) would be implicitly castable to Bar (just not vice-versa):
Bar b = _bar; // allowed
_bar = b; // disallowed
In fact, I don't like scope as it is:
scope Foo foo = ...; // is foo scope allocated or not? It depends:
scope Foo foo = new Foo(); // scope-allocated
Foo getFoo() { return new Foo(); }
scope Foo foo = getFoo(); // ????
In last example, DMD may inline and make it scope-allocated, but may not inline and make it heap-allocated.
Scope!(Foo) foo = ...;
gives you better control over allocation. For example,
Scope!(Foo) foo = getFoo();
won't even compile.
| |||
April 28, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu: > Could you please give a little more detail? My experience with Scala is near zero, I have written and compiled only small programs, like the ones from the Shootout and the ones of the first tutorial. Scala isn't a language as simple as they say, its type system is quite complex and powerful, so Scala isn't easy to learn if you want to use it well. You can use monads in Scala too, in a decent enough way: http://www.scala-lang.org/node/46 To give you a small answer, in Scala all types are used in a quite uniform way. This is useful. Even integers have a methods (as in Ruby, but Scala is statically compiled). You can add "methods" to all integers: object extendBuiltins extends Application { def fact(n: Int): BigInt = if (n == 0) 1 else fact(n-1) * n class Factorizer(n: Int) { def ! = fact(n) } implicit def int2fact(n: Int) = new Factorizer(n) println(10!) } Removing most of the distinction from built-in types and values and user-defined ones has some advantages. alias this of D2 is a little step in that direction. Like the idea of having first-class types. Once you have first-class types, with run-time-function-evaluation you may not need templates anymore. You have just functions that act on types that run at runtime too. The space of all possible computer languages is huge. > And speaking of Scala, after having watched a presentation, I was left with the impression that traits are nothing but classes with parameterized base. [...] > Is that correct? I don't know, I am sorry. I may be able to answer your question after reading the Scala docs, but you may do that yourself, and probably more efficiently, because you are smarter. Bye, bearophile | |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin |
Denis Koroskin wrote:
> ...
Scope stack-allocating is an optimisation. It doesn't guarantee it because that it's the point of scope.
Given that you're hung-up about stack allocation, I can't imagine how you'd implement scope as a template. Hell, I can't imagine how you'd implement Scope as a template for *any* of its behaviours.
class Foo
{
Scope!(Bar) _bar;
}
How do you guarantee deterministic destruction when it's inside a non-deterministic construct?
-- Daniel
| |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | On Wed, 29 Apr 2009 06:09:49 +0400, Daniel Keep <daniel.keep.lists@gmail.com> wrote: > > > Denis Koroskin wrote: >> ... > > Scope stack-allocating is an optimisation. It doesn't guarantee it > because that it's the point of scope. > > Given that you're hung-up about stack allocation, I can't imagine how > you'd implement scope as a template. Hell, I can't imagine how you'd > implement Scope as a template for *any* of its behaviours. > > class Foo > { > Scope!(Bar) _bar; > } > > How do you guarantee deterministic destruction when it's inside a > non-deterministic construct? > > -- Daniel Is that a challenge? import std.stdio; class Foo { this(int i, int j, int k) { writeln("Foo.this(): ", i, j, k); } ~this() { writeln("Foo.~this()"); } } struct Scope(T) { this(Args...)(Args args) { _data[] = T.classinfo.init[]; // shouldn't be needed __get.__ctor(args); } ~this() { __get.__dtor(); } alias __get this; T __get() { return cast(T)_data.ptr; } static assert(is(T == class)); private byte[__traits(classInstanceSize, T)] _data; //private byte[__traits(classInstanceSize, T)] _data = T.classinfo.init; // bug: doesn't work } void main() { auto foo = Scope!(Foo)(1, 2, 3); } One more bug-o-feature is that Scope.ctor is not called when args set is empty: auto foo = Scope!(Foo)(); // no Scope.__ctor is called and thus underlying Foo instance is left uninitialized. I never understood a rationale behind this "feature". I believe it's a hole. | |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin | Here is another example:
import std.stdio;
import Scope;
class Foo
{
this(int i, int j, int k) {
writeln("Foo.this(): ", i, j, k);
}
~this() {
writeln("Foo.~this()");
}
}
class Bar
{
this(int i, int j, int k)
{
writeln("Bar.this(): ", i, j, k);
foo = Scope!(Foo)(i, j, k);
}
~this()
{
writeln("Bar.~this()");
}
Scope!(Foo) foo;
}
// Just for comparison - note that they are almost the same
class NoScopeBar
{
this(int i, int j, int k)
{
writeln("NoScopeBar.this()");
foo = new Foo(i, j, k);
}
~this()
{
writeln("NoScopeBar.~this()");
}
Foo foo;
}
void main()
{
auto bar = Scope!(Bar)(1, 2, 3);
}
Expected output:
Bar.this(): 123
Foo.this(): 123
Bar.~this()
Foo.~this()
Output:
Bar.this(): 123
Foo.this(): 123
Bar.~this()
It is a DMD bug: calling an object's dtor should call dtors on all its fields.
| |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin | On Wed, 29 Apr 2009 13:06:18 +0400, Denis Koroskin <2korden@gmail.com> wrote: > It is a DMD bug: calling an object's dtor should call dtors on all its fields. This could be temporarily worked around by little template magic: foreach(field; filterFields(__traits(allMembers,T))) { field.dtor(); } | |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to grauzone | grauzone wrote: > Denis Koroskin wrote: >> On Tue, 28 Apr 2009 22:13:50 +0400, Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> wrote: >> >>> On Tue, Apr 28, 2009 at 6:07 PM, MLT <none@anon.com> wrote: >>>> 2. char[] vs. int[] >>>> I think it is strange that >>>> char[] x = "1234" ; >>>> x[0] = '4' ; >>>> >>>> Produces a run time error, but >>>> int[] x = [1,2,3,4] ; >>>> x[0] = 4 ; >>>> Doesn't. I think that they both should, or both shouldn't - to be consistent (and it would be better if they both didn't). Best would be again, to allow the programmer to specify where the array (or other stuff) should be stored. >>>> >>> It pretty much boils down to this (mostly said in other replies) >>> >>> * string literals are special, they are allocated in a static data >>> segment, readonly if the platform allows it. >>> >>> * arrayliterals as non-static expressions are always heap allocated. >>> even when there's absolute no need for it... (see >>> http://d.puremagic.com/issues/show_bug.cgi?id=2356 ) >>> >>> -Tomas >> >> Someone ought to post a feature request to make arrayliterals immutable by default (D2 only, I don't think this change will go to D1 anyway) and don't heap-allocate them every time they're used: Definitely. They should go into the initialized data segment. >> >> int[] x1 = [1,2,3,4]; // error: can't assign immutable(int)[] to int[] > > Why not auto-allocate? Writing that .dup all the time is going to be annoying. Just implicitly convert it from immutable to mutable by copying. I think it's pretty unlikely that you'd want to do that. It's far more likely that it's a bug, and you meant it to be an immutable(int)[]. Except in the case where the array is empty. (Likewise, it'd be nice if char [] s=""; were legal in D2. Since a mutable "" string has nothing that can be changed anyway, "" can be treated in the same way that 'null' is). > >> int[] x2 = [1,2,3,4].dup; // okay, allocates >> >> int[4] x3 = [1,2,3,4]; // okay, doesn't allocate >> >> foreach (int i; [1,2,3,4]) { // okay, doesn't allocate >> // ... >> } | |||
April 29, 2009 Re: struct vs. class, int vs. char. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don | Don wrote:
> (Likewise, it'd be nice if char [] s=""; were legal in D2. Since a mutable "" string has nothing that can be changed anyway, "" can be treated in the same way that 'null' is).
There was a huge discussion about null strings a few years ago. (Probably it was before Andrei, and possibly before your time.)
IIRC, most of the discussion was about detecting the "nullness" of a string, and what we should define the Null string to be, there were a few good thoughts around the subject in general.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply