Jump to page: 1 2
Thread overview
Datatypes I miss
Dec 07, 2005
Fredrik Olsson
Dec 07, 2005
Tom
Dec 07, 2005
James Dunne
Dec 08, 2005
Fredrik Olsson
Dec 08, 2005
Don Clugston
Dec 08, 2005
BCS
Dec 09, 2005
Bruno Medeiros
Dec 09, 2005
Bruno Medeiros
Dec 13, 2005
Lionello Lunesu
Dec 09, 2005
BCS
Dec 09, 2005
David Medlock
Dec 09, 2005
Fredrik Olsson
Dec 10, 2005
James Dunne
Dec 10, 2005
David Medlock
Dec 14, 2005
Fredrik Olsson
Dec 10, 2005
Glen Perkins
December 07, 2005
Ranges and sets :).

This is me more or less having a fantasy. Ranges and sets are without competition the two data types I use the most. They make writing solid code so much easy, helps finding range errors while debugging and reduces code size in general.

Both fits quite nicely into existing functionality in D, as well as into the paradigm of making usable functionality part of the core language (as for complex numbers and strings). Ranges are semi there when slicing arrays, and sets can be emulates with associative arrays with somewhat awkward syntax.

Anyway, if my x-mas wish comes true then :);

RangeDeclaration:
	range [Identifier] [: RangeBaseType] [RangeBody]
RangeBaseType:
	IntegerType
RangeBody:
	RangeMember
RangeMember:
	AssignExpression .. AssignExpression

For example:
	range minute 0..59;  // Static range
	minute = 61;  // Exception if compiling with range checks

	range slice: uint; // Dynamic range;
	int[12] foo;
	slice = 2..foo.length-2;
	int[] bar = foo[slice];

Range properties would be
.min, .max, .length and naturally .sizeof

Constant ranges are written with the .. operator just as one writes slices now. One minor hitch here, as slicing for arrays has the upper bound not including and having the upper bound not including for proper ranges would be awkward. But then again I have more often tried using foo[$] to get the last element of an array and failed, then I have ever used foo[2..$] to get the last elements.

Naturally the operator in should be able to work with ranges so that one could do for example:
	if (mychar in 'a'..'z') { ... }
	while (somenumber in 1..42) { ... }

And then sets:

SetDeclaration:
	set [Identifier] SetBody
SetBaseType:
	IntegerType
SetBody:
	IntegerType
	EnumType
	RangeType
	{ SetMembers }
SetMembers
	SetMember [, SetMembers]
SetMember:
	AssignExpression
	RangeMember
	SetType		// To expand existing sets

For example:
	set alfa {'A'..'Z', 'a'..'z'};
	set alfanum { alfa, '0'-'9' };

	enum weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
	set weekdays weekday;
	weekdays freedays = [TUE..THU, SAT];
	if (selectedday in freedays) { ... }

I mean how many of us have not written:
	if (tolower(ch) >= 'a' && tolower(ch) <= 'z' &&
	    ch >= '0' && ch <= '9') { ... }
And even longer when writing for non English. This is much nicer:
	if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }
And a compiler can optimize easy to just test bits.
December 07, 2005
I don't know about set or about the syntax but the range idea is also something I had wished for so long. It's very common to use integers just in a specified range, it'd make code much more nicer. Also the string enum would be very nice (or maybe something more general). I don't think all this could be implemented from a day to another but who knows in some future :D

In article <dn6re3$ckq$1@digitaldaemon.com>, Fredrik Olsson says...
>
>Ranges and sets :).
>
>This is me more or less having a fantasy. Ranges and sets are without competition the two data types I use the most. They make writing solid code so much easy, helps finding range errors while debugging and reduces code size in general.
>
>Both fits quite nicely into existing functionality in D, as well as into the paradigm of making usable functionality part of the core language (as for complex numbers and strings). Ranges are semi there when slicing arrays, and sets can be emulates with associative arrays with somewhat awkward syntax.
>
>Anyway, if my x-mas wish comes true then :);
>
>RangeDeclaration:
>	range [Identifier] [: RangeBaseType] [RangeBody]
>RangeBaseType:
>	IntegerType
>RangeBody:
>	RangeMember
>RangeMember:
>	AssignExpression .. AssignExpression
>
>For example:
>	range minute 0..59;  // Static range
>	minute = 61;  // Exception if compiling with range checks
>
>	range slice: uint; // Dynamic range;
>	int[12] foo;
>	slice = 2..foo.length-2;
>	int[] bar = foo[slice];
>
>Range properties would be
>.min, .max, .length and naturally .sizeof
>
>Constant ranges are written with the .. operator just as one writes slices now. One minor hitch here, as slicing for arrays has the upper bound not including and having the upper bound not including for proper ranges would be awkward. But then again I have more often tried using foo[$] to get the last element of an array and failed, then I have ever used foo[2..$] to get the last elements.
>
>Naturally the operator in should be able to work with ranges so that one
>could do for example:
>	if (mychar in 'a'..'z') { ... }
>	while (somenumber in 1..42) { ... }
>
>And then sets:
>
>SetDeclaration:
>	set [Identifier] SetBody
>SetBaseType:
>	IntegerType
>SetBody:
>	IntegerType
>	EnumType
>	RangeType
>	{ SetMembers }
>SetMembers
>	SetMember [, SetMembers]
>SetMember:
>	AssignExpression
>	RangeMember
>	SetType		// To expand existing sets
>
>For example:
>	set alfa {'A'..'Z', 'a'..'z'};
>	set alfanum { alfa, '0'-'9' };
>
>	enum weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
>	set weekdays weekday;
>	weekdays freedays = [TUE..THU, SAT];
>	if (selectedday in freedays) { ... }
>
>I mean how many of us have not written:
>	if (tolower(ch) >= 'a' && tolower(ch) <= 'z' &&
>	    ch >= '0' && ch <= '9') { ... }
>And even longer when writing for non English. This is much nicer:
>	if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }
>And a compiler can optimize easy to just test bits.

Tom
December 07, 2005
Fredrik Olsson wrote:
> Ranges and sets :).
> 
> This is me more or less having a fantasy. Ranges and sets are without competition the two data types I use the most. They make writing solid code so much easy, helps finding range errors while debugging and reduces code size in general.
> 
> Both fits quite nicely into existing functionality in D, as well as into the paradigm of making usable functionality part of the core language (as for complex numbers and strings). Ranges are semi there when slicing arrays, and sets can be emulates with associative arrays with somewhat awkward syntax.
> 
> Anyway, if my x-mas wish comes true then :);
> 
> RangeDeclaration:
>     range [Identifier] [: RangeBaseType] [RangeBody]
> RangeBaseType:
>     IntegerType
> RangeBody:
>     RangeMember
> RangeMember:
>     AssignExpression .. AssignExpression
> 
> For example:
>     range minute 0..59;  // Static range
>     minute = 61;  // Exception if compiling with range checks
> 
>     range slice: uint; // Dynamic range;
>     int[12] foo;
>     slice = 2..foo.length-2;
>     int[] bar = foo[slice];
> 
> Range properties would be
> .min, .max, .length and naturally .sizeof
> 
> Constant ranges are written with the .. operator just as one writes slices now. One minor hitch here, as slicing for arrays has the upper bound not including and having the upper bound not including for proper ranges would be awkward. But then again I have more often tried using foo[$] to get the last element of an array and failed, then I have ever used foo[2..$] to get the last elements.
> 
> Naturally the operator in should be able to work with ranges so that one could do for example:
>     if (mychar in 'a'..'z') { ... }
>     while (somenumber in 1..42) { ... }
> 

Very nice.  Well thought out.

> And then sets:
> 
> SetDeclaration:
>     set [Identifier] SetBody
> SetBaseType:
>     IntegerType
> SetBody:
>     IntegerType
>     EnumType
>     RangeType
>     { SetMembers }
> SetMembers
>     SetMember [, SetMembers]
> SetMember:
>     AssignExpression
>     RangeMember
>     SetType        // To expand existing sets
> 
> For example:
>     set alfa {'A'..'Z', 'a'..'z'};
>     set alfanum { alfa, '0'-'9' };
> 
>     enum weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
>     set weekdays weekday;
>     weekdays freedays = [TUE..THU, SAT];
>     if (selectedday in freedays) { ... }
> 
> I mean how many of us have not written:
>     if (tolower(ch) >= 'a' && tolower(ch) <= 'z' &&
>         ch >= '0' && ch <= '9') { ... }
> And even longer when writing for non English. This is much nicer:
>     if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }
> And a compiler can optimize easy to just test bits.

The only potential problem I can see in this is a conflict with static array literal syntax.  Most notably your last line there:

if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }

You and I both know that you meant a set type for ['A'..'Z', '0'..'9'], but the compiler might think that ['A'..'Z', '0'..'9'] is a static array literal and will get confused on your use of ranges there.  And then what would happen if your ['A'..'Z', '0'..'9'] looked like a real array literal with no ranges in it, but you meant it as a set?  Silent bug. Something like ['I', 'V', 'X', 'C', 'L', 'M']?  Is that a char[6] or a set?

Hope that wasn't too obtuse.  I do like your idea though!
December 08, 2005
James Dunne skrev:
> Fredrik Olsson wrote:
>> Ranges and sets :).
<snip>
> The only potential problem I can see in this is a conflict with static array literal syntax.  Most notably your last line there:
> 
> if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }
> 
> You and I both know that you meant a set type for ['A'..'Z', '0'..'9'], but the compiler might think that ['A'..'Z', '0'..'9'] is a static array literal and will get confused on your use of ranges there.  And then what would happen if your ['A'..'Z', '0'..'9'] looked like a real array literal with no ranges in it, but you meant it as a set?  Silent bug. Something like ['I', 'V', 'X', 'C', 'L', 'M']?  Is that a char[6] or a set?
> 
> Hope that wasn't too obtuse.  I do like your idea though!

Yes, it is a quite huge problem I guess as well. I remember reading in several places Walter stating that static arrays have been on for "v2.0", simply because of the problem of getting the type bottom up. I think the same problem applies here.

And then using [] for both static arrays and static sets is a problem as well, as you say. Both for the programmer and definitely for the compiler. Unfortunately {} is already set aside for static structs, using () is not an option, and then we sort of ran out of parenthesis like character pairs :/. Perhaps <> can work.
if (ch in <'a'..'z'>) { ... }
Not too bad. But then again I think the syntax is the smallest obstacle :).
December 08, 2005
Fredrik Olsson wrote:
> Ranges and sets :).
> For example:
>     range minute 0..59;  // Static range
>     minute = 61;  // Exception if compiling with range checks
> 
>     range slice: uint; // Dynamic range;
>     int[12] foo;
>     slice = 2..foo.length-2;
>     int[] bar = foo[slice];
> 
> Range properties would be
> .min, .max, .length and naturally .sizeof

I think there are TWO things going on here.
(1) syntactic sugar for a built-in pair structure.
struct range {
 int max;
 int min;
};
This could be passed to opSlice. I don't see any need for it
to be restricted to integral types; real numbers would make sense, too.

Actually, this type would be almost identical to
auto myrange = [1, 5];
except that the syntax is
auto myrange = 1..5;

(2) ability to apply a class invariant to a built-in type. This could be allowing a contracts to be applied to a typedef.

>     range minute 0..59;  // Static range
>     minute = 61;  // Exception if compiling with range checks

is the same as something like:
      typedef int invariant { assert(this>=0 && this<=59); } Minute;
// this assertion is checked every time there's
// an assignment to a Minute variable.
     Minute minute;
     minute = 61;

But you could also have more complex invariants, such
     typedef int invariant{ assert(this&1==0); } OddInt;
to create an integer which must be odd.

Except for the redefinition of 'this', it seems to be a natural extension of class invariants.
December 08, 2005
In article <dn8vjc$17fo$1@digitaldaemon.com>, Don Clugston says...
>

..

>(2) ability to apply a class invariant to a built-in type. This could be allowing a contracts to be applied to a typedef.
>
> >     range minute 0..59;  // Static range
> >     minute = 61;  // Exception if compiling with range checks
>
>is the same as something like:
>       typedef int invariant { assert(this>=0 && this<=59); } Minute;
>// this assertion is checked every time there's
>// an assignment to a Minute variable.
>      Minute minute;
>      minute = 61;
>
>But you could also have more complex invariants, such
>      typedef int invariant{ assert(this&1==0); } OddInt;
>to create an integer which must be odd.
>
>Except for the redefinition of 'this', it seems to be a natural extension of class invariants.


Sweet! This would be great!


December 09, 2005
Fredrik Olsson wrote:

> Ranges and sets :).
> 
> This is me more or less having a fantasy. Ranges and sets are without competition the two data types I use the most. They make writing solid code so much easy, helps finding range errors while debugging and reduces code size in general.
> 
> Both fits quite nicely into existing functionality in D, as well as into the paradigm of making usable functionality part of the core language (as for complex numbers and strings). Ranges are semi there when slicing arrays, and sets can be emulates with associative arrays with somewhat awkward syntax.
> 
> Anyway, if my x-mas wish comes true then :);
> 
> RangeDeclaration:
>     range [Identifier] [: RangeBaseType] [RangeBody]
> RangeBaseType:
>     IntegerType
> RangeBody:
>     RangeMember
> RangeMember:
>     AssignExpression .. AssignExpression
> 
> For example:
>     range minute 0..59;  // Static range
>     minute = 61;  // Exception if compiling with range checks
> 
>     range slice: uint; // Dynamic range;
>     int[12] foo;
>     slice = 2..foo.length-2;
>     int[] bar = foo[slice];
> 
> Range properties would be
> .min, .max, .length and naturally .sizeof
> 
> Constant ranges are written with the .. operator just as one writes slices now. One minor hitch here, as slicing for arrays has the upper bound not including and having the upper bound not including for proper ranges would be awkward. But then again I have more often tried using foo[$] to get the last element of an array and failed, then I have ever used foo[2..$] to get the last elements.
> 
> Naturally the operator in should be able to work with ranges so that one could do for example:
>     if (mychar in 'a'..'z') { ... }
>     while (somenumber in 1..42) { ... }
> 
> And then sets:
> 
> SetDeclaration:
>     set [Identifier] SetBody
> SetBaseType:
>     IntegerType
> SetBody:
>     IntegerType
>     EnumType
>     RangeType
>     { SetMembers }
> SetMembers
>     SetMember [, SetMembers]
> SetMember:
>     AssignExpression
>     RangeMember
>     SetType        // To expand existing sets
> 
> For example:
>     set alfa {'A'..'Z', 'a'..'z'};
>     set alfanum { alfa, '0'-'9' };
> 
>     enum weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
>     set weekdays weekday;
>     weekdays freedays = [TUE..THU, SAT];
>     if (selectedday in freedays) { ... }
> 
> I mean how many of us have not written:
>     if (tolower(ch) >= 'a' && tolower(ch) <= 'z' &&
>         ch >= '0' && ch <= '9') { ... }
> And even longer when writing for non English. This is much nicer:
>     if (toupper(ch) in ['A'..'Z', '0'..'9']) { ... }
> And a compiler can optimize easy to just test bits.

Do you mean you miss them from Pascal?
Your examples match Pascal pretty closely:

type Weekday = ( MON, TUE, WED, THU, FRI, SAT, SUN );
     WeekdaySet = Set of Weekday;
     Charset = Set of Char;
     DayOfWeek : 1..7 ;

var  weekdays : WeekdaySet;
     characters : Charset;

This is no slight on you, but its amusing to see programmers wish for features available on a language developed in 1970.. hee hee.

(A Pascal fan)
-DavidM

December 09, 2005
Don Clugston wrote:
> Fredrik Olsson wrote:
> 
>> Ranges and sets :).
>> For example:
>>     range minute 0..59;  // Static range
>>     minute = 61;  // Exception if compiling with range checks
>>
>>     range slice: uint; // Dynamic range;
>>     int[12] foo;
>>     slice = 2..foo.length-2;
>>     int[] bar = foo[slice];
>>
>> Range properties would be
>> .min, .max, .length and naturally .sizeof
> 
> 
> I think there are TWO things going on here.
> (1) syntactic sugar for a built-in pair structure.
> struct range {
>  int max;
>  int min;
> };
> This could be passed to opSlice. I don't see any need for it
> to be restricted to integral types; real numbers would make sense, too.
> 
> Actually, this type would be almost identical to
> auto myrange = [1, 5];
> except that the syntax is
> auto myrange = 1..5;
> 
> (2) ability to apply a class invariant to a built-in type. This could be allowing a contracts to be applied to a typedef.
> 
>  >     range minute 0..59;  // Static range
>  >     minute = 61;  // Exception if compiling with range checks
> 
> is the same as something like:
>       typedef int invariant { assert(this>=0 && this<=59); } Minute;
> // this assertion is checked every time there's
> // an assignment to a Minute variable.
>      Minute minute;
>      minute = 61;
> 
> But you could also have more complex invariants, such
>      typedef int invariant{ assert(this&1==0); } OddInt;
> to create an integer which must be odd.
> 
> Except for the redefinition of 'this', it seems to be a natural extension of class invariants.

That invariant in the middle of the typedef declaration seems a bit out of place. What if typedefs had a body, where you could put many invariants, unittests (not sure about the usefulness of this one) and even methods!
Like:

  enum weekday_enum { MON, TUE, WED, THU, FRI, SAT, SUN };
  typedef weekday_enum weekday
  {
    invariant { assert(this >= MON && this <= SUN); }
    bool isWeekDay() { return (this >= MON && this <= FRI); }
    char[] toString() { ... // returns "Monday", "Tuesday", etc. }
  }

  ...

  weekday wday;
  wday = weekday.MON;
  writefln( wday.toString() );


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
December 09, 2005
Bruno Medeiros wrote:
> 
> That invariant in the middle of the typedef declaration seems a bit out of place. What if typedefs had a body, where you could put many invariants, unittests (not sure about the usefulness of this one) and even methods!
> Like:
> 
>   enum weekday_enum { MON, TUE, WED, THU, FRI, SAT, SUN };
>   typedef weekday_enum weekday
>   {
>     invariant { assert(this >= MON && this <= SUN); }
>     bool isWeekDay() { return (this >= MON && this <= FRI); }
>     char[] toString() { ... // returns "Monday", "Tuesday", etc. }
>   }
> 

And yes, the similarity to structs is something worth to note. Hum..

-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
December 09, 2005
David Medlock skrev:
> Fredrik Olsson wrote:
> 
>> Ranges and sets :).
<snip>
> This is no slight on you, but its amusing to see programmers wish for features available on a language developed in 1970.. hee hee.
> 
> (A Pascal fan)
> -DavidM
> 

No coincident at all :). I am a Pascal fan as well, and Lisp fan, and Ruby fan and sql fan, and etc. I am simply choose what I feel is the best tool for the task at hand. For the general case Pascal tended to be it, before I found D. So naturally I want D to fill the few gaps I miss from my former #1.

//Fredrik


« First   ‹ Prev
1 2