www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9112] New: Uniform default construction

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112

           Summary: Uniform default construction
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: k.hara.pg gmail.com


--- Comment #0 from Kenji Hara <k.hara.pg gmail.com> 2012-12-03 20:06:08 PST ---
Related: http://d.puremagic.com/issues/show_bug.cgi?id=8752

Built-in .init property is useful, but it is sometimes unsafe, and many people
might confuse the default initializer and construction.

- Default initializer represents pre-constructing object state.
  Users can access to it by using built-in `.init` property.

- Default construction is a default operation which constructing an object
  completely.
  * For built-in types (int, double, pointers, arrays) and class types,
    default construction does nothing. Because, after initializing by
    default initializer, the object is already completely constructed.
  * For struct types, it is same in basic. After initialized by S.init,
    the object is completely constructed. Except:
    + If S is a nested struct, default construction should fill
      its frame pointer. So default construction is valid only in
     the function where S is defined.
    + If S is a struct which has ` disable this();`, default construction
      is disabled explicitly. So default construction is never occur.
      Instead, users should call explicitly defined user-defined
      constructor which has arguments.

Well, for struct types, default construction has an explicit syntax S().
But, built-in types does not have that. It is inconsistent.

So I'd like to propose new syntax to reduce such concept confusion.

int n = int();    // same as int.init
int n = int(10);  // same as cast(int)10;

From the meta-programming view, we can represent default construction of value
types by T().

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 03 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs eml.cc


--- Comment #1 from bearophile_hugs eml.cc 2012-12-05 17:31:48 PST ---
This is useful in generic code:
int n = int(10);

So we use:
reduce!q{a + b}(T(0), items)

Instead of:
reduce!q{a + b}(cast(T)0, items)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg gmx.com


--- Comment #2 from Jonathan M Davis <jmdavisProg gmx.com> 2012-12-05 18:12:49
PST ---
What I really want to be able to do is stuff like

auto i = new int(5);
auto j = new immutable(int)(7);

Right now, you have to do nonsense like

auto i = new int;
*i = 5;

auto temp = new int;
*temp = 7;
auto j = cast(immutable(int)*)temp;

Pointers to primitive types are just plain ugly to initialize, especially when
const and immutable come into play.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #3 from bearophile_hugs eml.cc 2012-12-05 18:50:12 PST ---
(In reply to comment #2)
 What I really want to be able to do is stuff like
 
 auto i = new int(5);

Just curious, in what cases do you need that? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #4 from Jonathan M Davis <jmdavisProg gmx.com> 2012-12-05 19:04:49
PST ---
 Just curious, in what cases do you need that?

Any time that you want create a pointer to an int - or a float or a bool or any of the primitive types. Right now, you're forced to do two-part initialization instead of initializing it to a value other than init when constructing it, which is particularly bad when const or immutable is involved. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #5 from bearophile_hugs eml.cc 2012-12-05 19:37:13 PST ---
(In reply to comment #4)

 Any time that you want create a pointer to an int - or a float or a bool or any
 of the primitive types.

This doesn't answer my question. In what cases do you want this? I think I have never needed this: auto i = new int(5); -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #6 from Jonathan M Davis <jmdavisProg gmx.com> 2012-12-05 21:42:28
PST ---
Personally, I've used it so that an integer could be null in cases where I
needed to distinguish between having a specific value and having no value at
all, but there are plenty of other uses for it. Have you honestly never needed
a pointer to an int? It's needed less than some other things to be sure, but
there are times when it is needed, and constructing such pointers is horrible
with how things stand. It also makes constructing them generically very
difficult, which is precisely what Kenji is bringing up in this enhancement
request. It's just that he's talking about them when they're on the stack, and
I'm pointing out that it would also be valuable to do the same with the heap.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #7 from bearophile_hugs eml.cc 2012-12-06 04:37:51 PST ---
(In reply to comment #6)
 Personally, I've used it so that an integer could be null in cases where I
 needed to distinguish between having a specific value and having no value at
 all,

In D std.typecons.Nullable!int is often better than a heap-allocated int.
 Have you honestly never needed a pointer to an int?

Not that I remember. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 06 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Uniform default             |Uniform construction for
                   |construction                |built-in types


--- Comment #8 from Kenji Hara <k.hara.pg gmail.com> 2012-12-06 16:55:04 PST ---
I agree with Jonathan. `new immutable int(1)` is also necessary, otherwise we
cannot initialize heap-allocated value without type-system hacking (by using
cast). I think it is one of hole in current const type system.

Therefore, for all built-in types, both stack allocating syntax (T() and T(v))
and heap allocating syntax (new T() and new T(v)) should be supported. I
changed the summary. 

But, true uniform construction cannot be implemented currently, because array
construction has some special cases.
I've opened a new issue for uniform array construction.
Issue 9120 - Uniform construction for array types

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 06 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com


--- Comment #9 from monarchdodra gmail.com 2012-12-06 22:30:28 PST ---
(In reply to comment #1)
 This is useful in generic code:
 int n = int(10);

EXTREMELY useful. Just the other day, I was writing a unittest to cover appender with as many types as possible, and wanted to write something along the lines of: //---- foreach (SS; TypeTuple!(int, S0, S1, S2, S3, S4, S5, S6, S7)) { foreach (S; TypeTuple!(SS, const(SS), immutable(SS))) { auto app1 = appender!(S[])(); foreach(i; 0 .. 0x20000) app1.put(S(i)); // HERE //---- Long story short: "int" didn't make it into the final test... (In reply to comment #2)
 What I really want to be able to do is stuff like
 
 auto i = new int(5);
 auto j = new immutable(int)(7);
 
 Right now, you have to do nonsense like
 
 auto i = new int;
 *i = 5;

You always have the auto j = [cast(immutable int)5].ptr; "Trick". But that's still ugly as sin, and I'm not sure what you are actually paying for when doing this. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 06 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull


--- Comment #10 from Kenji Hara <k.hara.pg gmail.com> 2012-12-07 07:54:45 PST
---
https://github.com/D-Programming-Language/dmd/pull/1356

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich gmail.com


--- Comment #11 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2012-12-07
10:39:02 PST ---
(In reply to comment #0)
 So I'd like to propose new syntax to reduce such concept confusion.
 
 int n = int(10);  // same as cast(int)10;

So we're introducing C++-style casts into D? This means you can no longer search for 'cast' and expect to find all the unsafe casts in your code. I'm very much against this, and if I remember right Walter was also against this.
 From the meta-programming view, we can represent default construction of value
 types by T().

We can also use a library template to do it without introducing new syntax. If orthogonality is needed because of metaprogramming then why not just implement a template in Phobos? We really don't need 10 ways of doing the same thing with a different syntax.. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #12 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2012-12-07
10:41:09 PST ---
(In reply to comment #9)
 (In reply to comment #1)
 This is useful in generic code:
 int n = int(10);

EXTREMELY useful. Just the other day, I was writing a unittest to cover appender with as many types as possible, and wanted to write something along the lines of: app1.put(S(i)); // HERE

There: app1.put(DefInit!S(i)); No need to introduce new syntax because of a small issue like that. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #13 from monarchdodra gmail.com 2012-12-07 10:55:13 PST ---
(In reply to comment #11)
 (In reply to comment #0)
 So I'd like to propose new syntax to reduce such concept confusion.
 
 int n = int(10);  // same as cast(int)10;

So we're introducing C++-style casts into D? This means you can no longer search for 'cast' and expect to find all the unsafe casts in your code. I'm very much against this, and if I remember right Walter was also against this.

AFAIK, it's not exactly the same thing, as int(10) would be only a constructor, so would not downcast. Writing: //---- void foo(long k) { int n = int(k); } //---- Would fail to compile the same way as: //---- void foo(long k) { int n = k; } //---- would. You'd need to use: //---- void foo(long k) { int n = int(cast(int)k); } //---- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #14 from Jonathan M Davis <jmdavisProg gmx.com> 2012-12-07 10:57:47
PST ---
 So we're introducing C++-style casts into D? This means you can no longer
 search for 'cast' and expect to find all the unsafe casts in your code. I'm
 very much against this, and if I remember right Walter was also against this.

I'd actually argue for making it so that no explict casting is involved. It could be restricted to cases where T var = literal; and T var = T(literal); would be identical. So, stuff like ubyte(12345) would be illegal whereas cast(ubyte)12345 would be legal. It then looks like a C++ cast but isn't. It solves the problem with generic code without causing any issues you get with casts.
 We can also use a library template to do it without introducing new syntax. If
 orthogonality is needed because of metaprogramming then why not just implement
 a template in Phobos?

I tried that. Andrei rejected it, and it's not worth my time to fight him over it. Not to mention, I've always thought that auto i = new int(7); auto j = new immutable(int)(5); should be legal and think that having to do something like makeNew!int(7) is a bit of a hack anyway, since it's specifically working around a deficiency in the language.
 We really don't need 10 ways of doing the same thing with a different syntax..

The whole point of this is to try and make things more consistent, not less. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #15 from Jonathan M Davis <jmdavisProg gmx.com> 2012-12-07 10:59:34
PST ---
 AFAIK, it's not exactly the same thing, as int(10) would be only a
 constructor, so would not downcast.

I agree, but if you look at Kenji's proposal, he specifically says that there's a cast involved (which I'd missed when I read it the first time). So, Andrej's complaint is completely valid given Kenji's initial proposal. But if you fix it so that no cast is involved, then I think that it's fine. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #16 from monarchdodra gmail.com 2012-12-07 12:20:03 PST ---
(In reply to comment #15)
 AFAIK, it's not exactly the same thing, as int(10) would be only a
 constructor, so would not downcast.

I agree, but if you look at Kenji's proposal, he specifically says that there's a cast involved (which I'd missed when I read it the first time). So, Andrej's complaint is completely valid given Kenji's initial proposal. But if you fix it so that no cast is involved, then I think that it's fine.

I'm just wondering if that's *actually* what's going on, or if Kenji just accidentally miss-commented it that way. I don't know how to read compiler code, so I wouldn't know what he actually did. It'd be nice if he did deliver a fail_compile checking this. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #17 from bearophile_hugs eml.cc 2012-12-07 14:33:35 PST ---
The pull request was closed hours ago:
https://github.com/D-Programming-Language/dmd/pull/1356

Do you know where are the comments that have made Hara close it?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #18 from Kenji Hara <k.hara.pg gmail.com> 2012-12-11 05:01:27 PST
---
(In reply to comment #16)
 (In reply to comment #15)
 AFAIK, it's not exactly the same thing, as int(10) would be only a
 constructor, so would not downcast.

I agree, but if you look at Kenji's proposal, he specifically says that there's a cast involved (which I'd missed when I read it the first time). So, Andrej's complaint is completely valid given Kenji's initial proposal. But if you fix it so that no cast is involved, then I think that it's fine.

I'm just wondering if that's *actually* what's going on, or if Kenji just accidentally miss-commented it that way. I don't know how to read compiler code, so I wouldn't know what he actually did. It'd be nice if he did deliver a fail_compile checking this.

You pointed out is correct. At first, I had considered that int(10) should be translated to cast(int)10. But, while implementing pull, I had discovered the incorrect cast would occur much easily. So now, the posted pull doesn't implement int(10) as a cast, and the syntax accepts only a value which implicitly convertible to int. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 11 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #19 from Kenji Hara <k.hara.pg gmail.com> 2012-12-11 05:03:33 PST
---
(In reply to comment #17)
 The pull request was closed hours ago:
 https://github.com/D-Programming-Language/dmd/pull/1356
 
 Do you know where are the comments that have made Hara close it?

Sorry, I had temporarily closed it so auto tester result had been broken in 64bit platforms. After fixing test cases, I reopened that. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 11 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #20 from yebblies <yebblies gmail.com> 2013-01-13 18:17:38 EST ---
*** Issue 5347 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 12 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112



--- Comment #21 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-01-13
07:08:11 PST ---
I just think there's a good chance that the feature could bite us in generic
code and leave us spending a lot of time debugging.

Here's a somewhat contrived example:

float sqr(int val)
{
    return val * val;
}

template Call(T...)
{
    auto Call(int arg)
    {
        alias T[0] Func;
        return Func(arg);
    }
}

template GetFunc()
{
    alias int GetFunc;
}

void main()
{
    alias Call!(GetFunc!()) square;
    square(2);  // actually calls int(2)
}

test.d(13): Error: function expected before (), not int of type int

With the pull this becomes valid code.

Maybe it's obvious in this case, but when you combine tuples, mixins, etc, it
could be hard to notice what's wrong. The way I see it, the more the line
between functions and types becomes blurred the harder it can be to track bugs.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 13 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9112


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei erdani.com


--- Comment #22 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-02-04
18:06:46 PST ---
*** Issue 2600 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 04 2013