www.digitalmars.com         C & C++   DMDScript  

D - Random comments/suggestions/bugs

reply Andy Friesen <andy ikagames.com> writes:
I happened upon this language just yesterday.  I think I'm in love. :>

First, the bad news.  This little snippet can crash the compiler:

	alias void delegate() SimpleDelegate;
	SimpleDelegate[] funcarray;
	....
	funcarray[]();

The error message is:

	Assertion failure: '!ident' on line 1812 in file 'mtype.c'

I'm not sure whether it should be legal D or not, but it probably 
shouldn't crash the compiler in either case. :)

Second up, there's no explicit scope operator like C++ has, so there's 
no way to call a global function from within a class that has a method 
by the same name.  The most obvious example is the toString function in 
the string module.  Copying C++ is an unappealing option, since D's only 
scope operator is a period, which would be a tad ambigious, not to 
mention ugly.

Lastly, a few tiny suggestions.  How about coroutines?  They have a way 
of reducing the complexity of state machines.  Python implements 
coroutines as iterators, which you can use in a for statement.

Templates that accept a variable number of arguments would be nice too, 
though the syntax might start to get weird at that point. (arrays of types?)

Anyway, thanks for finally letting me stop bouncing between begging for 
C++'s power, and C#'s simplicity. ;)

  -- Andy Friesen
Dec 29 2002
parent reply Burton Radons <loth users.sourceforge.net> writes:
Andy Friesen wrote:
 I happened upon this language just yesterday.  I think I'm in love. :>
 
 First, the bad news.  This little snippet can crash the compiler:
 
     alias void delegate() SimpleDelegate;
     SimpleDelegate[] funcarray;
     ....
     funcarray[]();
 
 The error message is:
 
     Assertion failure: '!ident' on line 1812 in file 'mtype.c'
 
 I'm not sure whether it should be legal D or not, but it probably 
 shouldn't crash the compiler in either case. :)

Hm. On the one hand, I do a lot of dispatching to lists of delegates; on the other hand, there's no speed benefit in the compiler optimising it for us, and the return from the operation isn't clear (a list of the return value, as with map?).
 Second up, there's no explicit scope operator like C++ has, so there's 
 no way to call a global function from within a class that has a method 
 by the same name.  The most obvious example is the toString function in 
 the string module.  Copying C++ is an unappealing option, since D's only 
 scope operator is a period, which would be a tad ambigious, not to 
 mention ugly.

Use the module name you used to import: import string; ... string.toStringz (xxx); If the symbol exists in this module, alias it into something more explicit in the global scope or import your own module and use that name.
 Lastly, a few tiny suggestions.  How about coroutines?  They have a way 
 of reducing the complexity of state machines.  Python implements 
 coroutines as iterators, which you can use in a for statement.

You'll need to be more explicit about what they are, how you think they'd work in a D context, what they'd be capable of.
Dec 29 2002
parent reply Andy Friesen <andy ikagames.com> writes:
Burton Radons wrote:
 Andy Friesen wrote:
 
 I happened upon this language just yesterday.  I think I'm in love. :>

 First, the bad news.  This little snippet can crash the compiler:

     alias void delegate() SimpleDelegate;
     SimpleDelegate[] funcarray;
     ....
     funcarray[]();

 The error message is:

     Assertion failure: '!ident' on line 1812 in file 'mtype.c'

 I'm not sure whether it should be legal D or not, but it probably 
 shouldn't crash the compiler in either case. :)

Hm. On the one hand, I do a lot of dispatching to lists of delegates; on the other hand, there's no speed benefit in the compiler optimising it for us, and the return from the operation isn't clear (a list of the return value, as with map?).
 Second up, there's no explicit scope operator like C++ has, so there's 
 no way to call a global function from within a class that has a method 
 by the same name.  The most obvious example is the toString function 
 in the string module.  Copying C++ is an unappealing option, since D's 
 only scope operator is a period, which would be a tad ambigious, not 
 to mention ugly.

Use the module name you used to import: import string; ... string.toStringz (xxx); If the symbol exists in this module, alias it into something more explicit in the global scope or import your own module and use that name.
 Lastly, a few tiny suggestions.  How about coroutines?  They have a 
 way of reducing the complexity of state machines.  Python implements 
 coroutines as iterators, which you can use in a for statement.

You'll need to be more explicit about what they are, how you think they'd work in a D context, what they'd be capable of.

At the core, a coroutine is basically a function that stores its state somewhere other than the stack so that one can later "resume" the function after it returns. for (int i=0; i<10; i++) return i; // won't work, but it'd be nice A better explanation, and an inventive C implementation can be found at http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html To paraphrase, it's sometimes useful to have two functions that jump back and forth, instead of having one strictly call the other. Writing one of the functions as a state machine is one way to solve this problem. Coroutines are a better way. :) (it's also easy to use them for quick n' dirty cooperative threading) As for how they could work in D, I think Python has the right idea. "somewhere other than the stack" would be an iterator object. (one with a method to fetch the next value) Internally, local variables are stored within the iterator itself. A StopIteration exception is raised when the coroutine function has completed whatever it's doing. This (rather bizzare) Python function produces the fibonacci sequence, for example: def fib(): a = 0 b = 1 while True: yield b c = a + b a = b b = c The actual function returns an iterator, which one would hold onto, calling its next() method when desired. f = fib() i = 0 try: while i < 10: print f.next() i += 1 except StopIteration: pass # do nothing This particular coroutine goes on forever, so the exception handling in this example is extraneous. It's left in for clarity. The trickiest part of doing this in D is the iterator itself. One way is to have a "special" template interface for iterators. coroutine int fib() { int a = 0; int b = 1; int c = b; while (true) { yield b; c = a + b; a = b; b = c; } } instance Iterator(int) IntIter; IntIter.Iterator f = fib(); try { for (int i=0; i < 10; i++) printf("%i\n", f.next()); } catch (StopIteration) { } I think an Iterator.atend() method would be better than throwing an exception, as exceptions imply some kind of error condition, which isn't really the case. "return" could be used instead of "yield", but it may be better to distinguish the two. On a slightly related note, iterators could be provided for arrays and such as well, allowing a foreach() construct to be added to the language easily. The downsides are pretty obvious -- having a "magical" template interface built into the language, and the compiler complexity imposed by having some locals on the stack, and other locals stored in an iterator. whew! -- Andy Friesen
Dec 29 2002
parent Mark Evans <Mark_member pathlink.com> writes:
P.S.  You can go back several months and read my posts here about the Icon
language, which supports coroutines natively.  They have their uses.

http://www.cs.arizona.edu/icon/
http://unicon.sourceforge.net/index.html

Mark

 At the core, a coroutine is basically a function that stores its state 
 somewhere other than the stack so that one can later "resume" the 
 function after it returns.

Dec 29 2002