March 27, 2013
On 03/27/2013 07:20 PM, Andrei Alexandrescu wrote:
> On 3/27/13 1:23 PM, Timon Gehr wrote:
>>> - 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.
>
> Ideally such function should return a "none" type, the bottom of the
> hierarchy lattice. We don't have such, so returning typeof(null) (which
> we do have) is the next best choice as it's just above bottom.
>
> Andrei

Maybe it is one next best choice. It is still a horrible choice.

It's not any more just above bottom than the following type:

struct JustAboveBottom{ }

We should either go with the real thing or do nothing about it.
March 28, 2013
On Wednesday, 27 March 2013 at 18:20:49 UTC, Andrei Alexandrescu wrote:
> On 3/27/13 1:23 PM, Timon Gehr wrote:
>>> - 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.
>
> Ideally such function should return a "none" type, the bottom of the hierarchy lattice. We don't have such, so returning typeof(null) (which we do have) is the next best choice as it's just above bottom.
>

I thought that typeof(null) was that bottom type. What is the difference ?

Anyway, void isn't the right choice here and is a pain to work with.
March 28, 2013
On 2013-03-27 16:34, Vidar Wahlberg wrote:

> - I find myself in a world of pain when I want to share data more
> complex than the basic data types (int, char, byte, etc) across threads.
> Seemingly the magic trick is to "cast(shared) foo" (or
> "cast(immutable)") when passing objects/references to another thread,
> then "cast(Foo)" back on the receiving end (as most classes/structs in
> the standard library refuse to let you call any methods when the object
> is shared). The examples in the source and TDPL are fairly limited on
> the issue, it mostly covers only those basic data types.

Try message passing and serialize the data you want to send.

Message passing: http://dlang.org/phobos/std_concurrency.html
Serialization: https://github.com/jacob-carlborg/orange

-- 
/Jacob Carlborg
March 28, 2013
On 03/27/2013 12:08 PM, Steven Schveighoffer wrote:
> On Wed, 27 Mar 2013 11:34:19 -0400, Vidar Wahlberg
> <vidar.wahlberg@gmail.com> 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.
>
> Typically, one uses std.conv.to to safely convert one value into
> another. Cast should be avoided unless absolutely necessary.
>
> I just tested it, it works on enum *strings*, but not enum *values*
>
> For example:
>
> import std.conv;
>
> enum X {
> i, j, k
> }
>
> void main()
> {
> X x = to!X("i"); // works!
> x = to!X(1); // fails!
> }


> I think to should be able to do this, but I'm not a good enough guru
> with templates and compile-time type info to know if it's possible.
> Anyone know if this is possible? If so, I think it should be added.
>
> -Steve

It also works on values....


enum A
{
    B,
    C,
    D,
}
int w;

import std.conv;
import std.stdio;

void main()
{
   auto t = w.to!A.B;

   writeln(t);
}
March 28, 2013
On 03/27/2013 03:47 PM, Steven Schveighoffer wrote:
> On Wed, 27 Mar 2013 14:09:07 -0400, Nick Sabalausky
> <SeeWebsiteToContactMe@semitwist.com> wrote:
>
>> On Wed, 27 Mar 2013 14:07:27 -0400
>> Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote:
>>
>>> On Wed, 27 Mar 2013 13:08:19 -0400
>>> >
>>> > I just tested it, it works on enum *strings*, but not enum *values*
>>> >
>>> > For example:
>>> >
>>> > import std.conv;
>>> >
>>> > enum X {
>>> > i, j, k
>>> > }
>>> >
>>> > void main()
>>> > {
>>> > X x = to!X("i"); // works!
>>> > x = to!X(1); // fails!
>>> > }
>>> >
>>>
>>> Works for me on 2.063 Win. Keep in mind:
>>>
>>> assert(cast(int)X.i == 0);
>>> assert(cast(int)X.j == 1);
>>>
>>
>> I meant of course 2.062
>>
>
> Hah, I have not yet downloaded 2.062. It did not work in 2.061, not sure
> if that was a bug or it's a new feature.
>
> anyway, that is good to know!
>
> -Steve

It worked for me in 2.061, as that's what I'm currently on.


Waiting to build the release that I hear might have shared objects!
March 28, 2013
On 03/28/2013 04:18 AM, deadalnix wrote:
> On Wednesday, 27 March 2013 at 18:20:49 UTC, Andrei Alexandrescu wrote:
>> On 3/27/13 1:23 PM, Timon Gehr wrote:
>>>> - 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.
>>
>> Ideally such function should return a "none" type, the bottom of the
>> hierarchy lattice. We don't have such, so returning typeof(null)
>> (which we do have) is the next best choice as it's just above bottom.
>>
>
> I thought that typeof(null) was that bottom type. What is the difference ?
>

There is a huge difference.

 - typeof(null) is a subtype of all _class, interface and pointer_
   types because they all _include_ its value, null.

 - bottom is a subtype of _all_ types, because there is _no_ value of
   type bottom.

> Anyway, void isn't the right choice here and is a pain to work with.

typeof(null) would be worse.
March 28, 2013
On Thursday, 28 March 2013 at 10:34:35 UTC, Timon Gehr wrote:
> On 03/28/2013 04:18 AM, deadalnix wrote:
>> On Wednesday, 27 March 2013 at 18:20:49 UTC, Andrei Alexandrescu wrote:
>>> On 3/27/13 1:23 PM, Timon Gehr wrote:
>>>>> - 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.
>>>
>>> Ideally such function should return a "none" type, the bottom of the
>>> hierarchy lattice. We don't have such, so returning typeof(null)
>>> (which we do have) is the next best choice as it's just above bottom.
>>>
>>
>> I thought that typeof(null) was that bottom type. What is the difference ?
>>
>
> There is a huge difference.
>
>  - typeof(null) is a subtype of all _class, interface and pointer_
>    types because they all _include_ its value, null.
>
>  - bottom is a subtype of _all_ types, because there is _no_ value of
>    type bottom.
>

OK I see the difference.

>> Anyway, void isn't the right choice here and is a pain to work with.
>
> typeof(null) would be worse.

I don't see how it is worse.
March 28, 2013
On Wednesday, 27 March 2013 at 16:04:49 UTC, bearophile wrote:
> Vidar Wahlberg:
[cut]
>> That static arrays are value types while dynamic arrays are reference types may not be obvious for those with primarily Java background.
>
> Java has a semantics more limited compared to a system language as D/Rust. This is not easy to avoid.

Especially when keeping the poor C/C++ syntax for declaration instead of Pascal-style declaration syntax where you *name* the kind of array you're using!

*Sigh* and some still think that syntax doesn't matter..

renoX
March 28, 2013
To follow up with some new woes I'm currently struggling with:
I'm storing some various values in an ubyte array. I discovered that it's probably std.bitmanip I wish to use in order to "convert" i.e. an int to 4 bytes (although I went first to std.conv looking for this feature).
So I have "ubyte[] buffer;", and my second thought is that the "append" method (http://dlang.org/phobos/std_bitmanip.html#.append) is what I want to append values to my ubyte-array (my first thought was something like "buffer ~= to!ubyte[](42);", although then I forgot about endianness). In the example in the documentation it does say "auto buffer = appender!(const ubyte[])();", with no explanation as of what "appender" is (I later learned that this is from std.array), but just looking a bit up I see that the "write" method explained just above use "ubyte[] buffer; buffer.write!ubyte(42);", so I assumed that I could use ubyte[] myself instead of this "appender" which I thought was some legacy code.
So I write some simple test code:
 import std.bitmanip, std.stdio;
 void main() {
  ubyte[] buffer;
  buffer.append!ubyte(42);
 }
Run it through rdmd, and get: "core.exception.AssertError@/usr/include/d/std/array.d(591): Attempting to fetch the front of an empty array of ubyte".
Just to see what happens I set the size of the buffer ("buffer.length = 1;") before appending and run it again. Now it runs, but instead of appending it behaves like write(), which was not exactly what I wanted.

At this time I google for this "appender" used in the example and learn that it comes from std.array, so I import std.array and try again using "auto buffer = appender!(ubyte[])();", and surely enough, now it does append correctly to the buffer. Great, I have a solution, so I go back to my project and implement it like I implemented it in my test code, but when I compile my project after this addition I get a new cryptic error message: "Error: __overloadset isn't a template".
After digging a bit I realized that it's because in my project I also import std.file, apparently there are some collisions between std.bitmanip and std.file. Again it's solvable, but it's yet another fight with the language/standard library. I would also assume that it's not that uncommon for a module that use std.bitmanip to also use std.file, meaning that this error potentially may occur often.

A bit on the side: It seems to me as importing std.bitmanip somehow adds new properties to my array (".read()" and ".write()", for example). Not necessarily a bad thing, more of "I've not seen this before, I was expecting that I were to concatenate the bytes from the conversion to my buffer using ~".
March 28, 2013
On Thu, Mar 28, 2013 at 09:24:49PM +0100, Vidar Wahlberg wrote:
> To follow up with some new woes I'm currently struggling with: I'm storing some various values in an ubyte array. I discovered that it's probably std.bitmanip I wish to use in order to "convert" i.e.  an int to 4 bytes (although I went first to std.conv looking for this feature).
[...]

There are several ways to convert an int into 4 bytes:

1) Use a union:

	static assert(int.sizeof==4);
	ubyte[4] intToUbytes(int x) {
		union U {
			int i;
			ubyte[4] b;
		}
		U u;
		u.i = x;
		return u.b;
	}

2) Use bit operators:

	ubyte[4] intToUbytes(int x) {
		ubyte[4] bytes;

		// Note: this assumes little-endian. For big-endian,
		// reverse the order below.
		bytes[0] = x & 0xFF;
		bytes[1] = (x >> 8) & 0xFF;
		bytes[2] = (x >> 16) & 0xFF;
		bytes[3] = (x >> 24) & 0xFF;

		return bytes;
	}

3) Use a pointer cast (warning: un-@safe):

	ubyte[4] intToUbytes(int x) @system {
		ubyte[4] b;
		ubyte* ptr = cast(ubyte*)&x;
		b[0] = *ptr++;
		b[1] = *ptr++;
		b[2] = *ptr++;
		b[3] = *ptr;

		return b;
	}

4) Reinterpret a pointer (warning: un-@safe):

	ubyte[4] intToUbytes(int x) @system {
		return *cast(ubyte[4]*)&x;
	}

I'm sure there are several other ways to do it.

You don't need to use appender unless you're doing a lot of conversions in one go.


--T