July 11, 2012
>>> The trouble with segmented stacks are:
>>>
>>> 1. they have a significant runtime penalty
>> Why?
> Extra instructions generated for each function.
Every function? Why?

>>> 2. interfacing to C code becomes problematic
>> Isn't it possible to auto-commit new pages when C code needs it?
...
> There's no way to predict how much stack arbitrary C code will use.
Presumably one does not call arbitrary C code. Usually one knows what one might call in advance and can plan accordingly (and even if it is arbitrary, one at least knows *that* one is going to call C code and plan accordingly. Most C code doesn't allocate more than a few megabytes on the stack).
July 11, 2012
On 7/11/2012 11:00 AM, David Piepgrass wrote:
>> the logical bitwise operators have higher precedence. In C, x & 2 > 0 comes
>> out as x & (2 > 0), in Rust, it means (x & 2) > 0, which is more likely to be
>> what you expect (unless you are a C veteran).
> Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's
> against D philosophy to change the precedence w.r.t. C, but how about a
> compromise: give a warning or error for "x&2 > 0", with error message: "add
> parenthesis around x&2 to clarify your intention."

  bool test(int x) { return x & 2 > 0; }

gives:

  foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &
July 11, 2012
On 7/11/2012 9:45 AM, David Piepgrass wrote:
> I still type "reutrn" and "retrun" all the damn time!

I keep finding myself typing "redrum" !
July 11, 2012
On Wednesday, 11 July 2012 at 18:31:23 UTC, David Piepgrass wrote:
>>>> The trouble with segmented stacks are:
>>>>
>>>> 1. they have a significant runtime penalty
>>> Why?
>> Extra instructions generated for each function.
> Every function? Why?

Looks like I misunderstood what "Segmented stacks" are. From an LLVM page:

> Segmented stack allows stack space to be allocated incrementally than as a monolithic chunk (of some worst case size) at thread initialization. This is done by allocating stack blocks (henceforth called stacklets) and linking them into a doubly linked list. The function prologue is responsible for checking if the current stacklet has enough space for the function to execute; and if not, call into the libgcc runtime to allocate more stack space. Support for segmented stacks on x86 / Linux is currently being worked on.

I envision a rather different implementation for 32-bit code.

1. Reserve a normal stack with one 4K page committed + some known minimum amount of uncommitted memory, e.g. another 8 KB uncommitted with a guard page that the program can trap via OS facilities (signals, etc.)
2. When the stack overflows, move the stack to a new, much larger region of Virtual Memory. Much like languages that support compacting garbage collectors, the language / runtime environment must be designed to support this.
3. If one needs to call C code, one preallocates the maximum expected virtual memory needed, e.g. 32 MB.
July 11, 2012
>> Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's
>> against D philosophy to change the precedence w.r.t. C, but how about a
>> compromise: give a warning or error for "x&2 > 0", with error message: "add
>> parenthesis around x&2 to clarify your intention."
>
>   bool test(int x) { return x & 2 > 0; }
>
> gives:
>
>   foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &

Doh! You read my mind before I thought it :) I hadn't got around to bit fiddling in D yet.
July 11, 2012
Am Wed, 11 Jul 2012 19:09:26 +0200
schrieb Timon Gehr <timon.gehr@gmx.ch>:

> On 07/11/2012 06:45 PM, David Piepgrass wrote:
> > ...
> > These benefits (except 3) all exist for "function" as well as "fn", but
> > while many languages use "fun", requiring "function" for all functions
> > is almost unheard of (at least I haven't heard of it), why? It's too
> > damn long! We write functions constantly, we don't want to type
> > "function" constantly.
> 
> You could have a look at JavaScript.

... and Pascal/Delphi, which has no 'void' return, but distinguishes between a 'procedure' and a 'function' with exactly those long keywords. Even better: When you declare a class, you have to use the long keywords in both the class declaration and the method implementation. Then again it also has 'begin' and 'end' instead of { and }. Masochists...

-- 
Marco

July 11, 2012
>   bool test(int x) { return x & 2 > 0; }
>
> gives:
>
>   foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &

That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.
July 11, 2012
On 7/11/2012 11:54 AM, David Piepgrass wrote:
> That reminds me, I was so happy the first two times I got an undefined symbol
> error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL,
> don't tell me how it works... it's magic, right? I love a good error message.

I added a spelling checker to the undefined identifier code, using the variables in scope as the dictionary. It's a fun little nicety.

July 11, 2012
Am Wed, 11 Jul 2012 20:24:34 +0200
schrieb "bearophile" <bearophileHUGS@lycos.com>:

> Marco Leise:
> 
> > Yes, this is the single most important Rust feature to me when typing. I've just had too many cases of mass-casts to ubyte or short where a suffix to the literal would only have cost one or two letters. 255ub = byte, 32000s = short
> 
> I am writing a lot of D2 code, but in my code the need of explicit short or byte literals is very uncommon. That's why those Rust suffixes seem overkill to me. Do you want to show us some of your use cases?
> 
> Bye,
> bearophile

As an optional feature, I think it is nice to have them when you need them. They are not a feature that has any downside I can think of, as we already have some other suffixes and the maintenance cost is practically zero.

Here are some examples:

DMD:

   (test42.d), array type inference:
   const short[] ct = cast(short[]) [cast(byte)1, 1];
=> const short[] ct = cast(short[]) [1b, 1];

Phobos:

   (boxer.d):
   assert (box(1) == box(cast(byte)1));
=> assert (box(1) == box(1b));

   (algorithm.d):
   assert(b == [ cast(ubyte) 0, cast(ubyte)2, cast(ubyte)1, cast(ubyte)6, cast(ubyte)5], text(b));
=> assert(b == [ 0ub, 2ub, 1ub, 6ub, 5ub], text(b));

   (variant.d):
   a = cast(short) 5;
=> a = 5s;

   (gregorian.d):
   julianbegin = julianDay(tuple(cast(ushort)ymd._0, cast(ushort)1, cast(ushort)1))
=> julianbegin = julianDay(tuple(cast(ushort)ymd._0, 1us, 1us))

   (string.d):
   assert(isNumeric(cast(byte)0x57) == false); // 'W'
=> assert(isNumeric(0x57b) == false); // 'W'

GtkD:

   (Color.d and several other occurences):
   _black = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0);
=> _black = new Color(0ub,0ub,0ub);

ScintillaD:

   (SciTEWin.d):
   SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, cast(ushort)-1));
=> SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, -1us));

QtD:

   (Atomic.d):
   return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0;
=> return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, 0ub) ? 1 : 0;

My code:

   write a literal (byte) number to a 'take anything' output stream:
   ostr.write(cast(ubyte) 0);
=> ostr.write(0ub);

   from a unittest for Unicode sequences:
   loadCycle(cast(char[]) [cast(ubyte) 0b11000111, cast(ubyte) 0b00111111]);
=> loadCycle(cast(char[]) [0b11000111ub, 0b00111111ub]);


I thought there were more cases in my code, but it seems like often the casts were required because some intermediate result of 16-bit calculations is extended to 32-bits by the language (where the CPU can perform arithmetics faster). So I looked at the other projects I checked out and it seems like casts to byte or short are not frequent, but most projects need them once in a while.

-- 
Marco

July 11, 2012
On Wednesday, 11 July 2012 at 18:53:31 UTC, Marco Leise wrote:
> Am Wed, 11 Jul 2012 19:09:26 +0200
> schrieb Timon Gehr <timon.gehr@gmx.ch>:
>
>> On 07/11/2012 06:45 PM, David Piepgrass wrote:
>> > ...
>> > These benefits (except 3) all exist for "function" as well as "fn", but
>> > while many languages use "fun", requiring "function" for all functions
>> > is almost unheard of (at least I haven't heard of it), why? It's too
>> > damn long! We write functions constantly, we don't want to type
>> > "function" constantly.
>> 
>> You could have a look at JavaScript.
>
> ... and Pascal/Delphi, which has no 'void' return, but distinguishes between a 'procedure' and a 'function' with exactly those long keywords. Even better: When you declare a class, you have to use the long keywords in both the class declaration and the method implementation. Then again it also has 'begin' and 'end' instead of { and }. Masochists...

I was a very happy Turbo Pascal and Delphi developer, until I switched full time to C and C++.