Re: dmd 2.049 bug with take and SList?

2010-10-14 Thread Lars T. Kyllingstad
On Thu, 14 Oct 2010 06:54:17 +, Lars T. Kyllingstad wrote:

> On Wed, 13 Oct 2010 18:06:15 +, Lars T. Kyllingstad wrote:
> 
>> On Wed, 13 Oct 2010 16:46:09 +, Nick Treleaven wrote:
>> 
>>> Hi,
>>> I'm new to D2 ranges but have been following D for some time. I'm
>>> posting here because I want to check if I'm doing anything wrong
>>> before filing a bug.
>>> 
>>> The code below is a test case I made after hitting the problem in real
>>> code. Basically the pyramid recursive function should print out: [1,
>>> 2, 3]
>>> [1, 2]
>>> [1]
>>> 
>>> This works fine when calling with an int[] range, but calling with
>>> SList!int seems to make the compiler hang, eating up memory.
>>> 
>>> Should I file a bug?
>>> 
>>> 
>>> import std.stdio;
>>> import std.range;
>>> import std.container;
>>> 
>>> void pyramid(Range)(Range items)
>>> {
>>> if (items.empty)
>>> return;
>>> writeln(items);
>>> auto len = walkLength(items);
>>> auto r = take(items, len - 1);
>>> pyramid(r);
>>> }
>>> 
>>> void main()
>>> {
>>> /* array version is fine */
>>> int[] arr = [1, 2, 3];
>>> pyramid(arr[]);
>>> 
>>> SList!int list = [1, 2, 3];
>>> pyramid(list[]);/* infinite loop with dmd 2.049 */
>>> }
>> 
>> 
>> You are creating an infinite recursion of templates.  For an array the
>> return type of take() is the same array type.  For other ranges, the
>> return type of take() is Take!Range.  So when you instantiate pyramid!
>> Range, it instantiates pyramid!(Take!Range), and then
>> pyramid!(Take!(Take! Range)), and so on ad infinitum.
>> 
>> A solution could be to make take!(Take!Range)() just return another
>> Take! Range.  I can look into that, but you should file a bug report on
>> it so it's not forgotten.
>> 
>> -Lars
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=5052

Fixed.
http://www.dsource.org/projects/phobos/changeset/2102


writing

2010-10-14 Thread spir
Hello,

write and writeln just write; writef and writefln first format: seems clear. 
But the latter do not work properly with D strings, and the former do not work 
without format. Is there a practical way to just write anything to the terminal 
(without caring of its type)?

Is there some rationale about this?
Would it be possible to automatically add \0 to D strings passed to 
write/writeln (can a programmer define a custom func doing this before 
delegating to builtin funcs, or is it necessarily a job for the compiler?)?
And/or what about having writef/writefln use "%s" as default format (when the 
first arg is not a string)?

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: writing

2010-10-14 Thread Lars T. Kyllingstad
On Thu, 14 Oct 2010 09:58:36 +0200, spir wrote:

> Hello,
> 
> write and writeln just write; writef and writefln first format: seems
> clear. But the latter do not work properly with D strings, and the
> former do not work without format. Is there a practical way to just
> write anything to the terminal (without caring of its type)?
> 
> Is there some rationale about this?
> Would it be possible to automatically add \0 to D strings passed to
> write/writeln (can a programmer define a custom func doing this before
> delegating to builtin funcs, or is it necessarily a job for the
> compiler?)? And/or what about having writef/writefln use "%s" as default
> format (when the first arg is not a string)?


I don't understand what you mean.  This works just fine:

  import std.stdio;

  void main()
  {
  string s = "Hello world!";
  writeln(s);
  }

If I'm misunderstanding you, please explain, or perhaps give a code 
example.

-Lars


Re: What sorts of things cause cyclic dependencies?

2010-10-14 Thread bearophile
Jonathan M Davis:

> Well, just knowing that it involves module constructors is definitely useful, 
> though the error message really needs to be improved. Thanks.

You may file a bug report, with an example, asking for a better error message 
(with a better wording), or a much better error message (that lists the cycle 
too).

Bye,
bearophile


Re: GC interpreting integer values as pointers

2010-10-14 Thread Steven Schveighoffer

On Sat, 09 Oct 2010 15:51:37 -0400, Ivo Kasiuk  wrote:


Hi!

In my D programs I am having problems with objects not getting finalised
although there is no reference anymore. It turned out that this is
caused by integers which happen to have values corresponding to pointers
into the heap. So I wrote a test program to check the GC behaviour
concerning integer values:



[snip]


So in most but not all situations the integer value keeps the object
from getting finalised. This observation corresponds to the effects I
saw in my programs.

I find this rather unfortunate. Is this known, documented behaviour? In
a typical program there are such integer values all over the place. How
should such values be stored to avoid unwanted interaction with the GC?


Yes, D's garbage collector is a conservative garbage collector.  One which  
doesn't have this problem is called a precise garbage collector.


There are two problems here.  First, D has unions, so it is impossible for  
the GC to determine if a union contains an integer or a pointer.


Second problem is the granularity of scanning.  A memory block is scanned  
as if every n bits (n being your architecture) is a pointer, or there are  
no pointers.  This is determined by a bit associated with the block (the  
NO_SCAN bit).


If you allocate a memory block that contains at least one pointer, then  
all the words in the memory block are considered to be pointers by the  
GC.  There is a (continually updated) patch which allows the GC to be  
semi-precise.  That is, the type information of the memory block will be  
linked to it.  This will allow precise scanning except for unions.  Once  
this is integrated, the false pointer problem will be much less prevalent.


-Steve


Re: dmd 2.049 bug with take and SList?

2010-10-14 Thread Nick Treleaven
On Thu, 14 Oct 2010 07:18:48 +, Lars T. Kyllingstad wrote:

>>> You are creating an infinite recursion of templates.  For an array the
>>> return type of take() is the same array type.  For other ranges, the
>>> return type of take() is Take!Range.  So when you instantiate pyramid!
>>> Range, it instantiates pyramid!(Take!Range), and then
>>> pyramid!(Take!(Take! Range)), and so on ad infinitum.

OK, makes sense.

>>> A solution could be to make take!(Take!Range)() just return another
>>> Take! Range.  I can look into that, but you should file a bug report
>>> on it so it's not forgotten.
>>> 
>>> -Lars
>> 
>> http://d.puremagic.com/issues/show_bug.cgi?id=5052
> 
> Fixed.
> http://www.dsource.org/projects/phobos/changeset/2102

Thanks!


Re: mutable reference to const object

2010-10-14 Thread Steven Schveighoffer
On Tue, 12 Oct 2010 18:54:49 -0400, Jonathan M Davis   
wrote:



On Tuesday, October 12, 2010 15:27:41 Jesse Phillips wrote:

Jonathan M Davis Wrote:
> Unfortunately, at this point, tail const has pretty much been decided  
to

> be too difficult implement and/or too difficult to do cleanly, so it's
> not in D and likely never will be. If it's mentioned in the online  
docs,

> the docs need to be updated. It's been a long time since there was any
> kind of tail const in D.
>
> - Jonathan M Davis

What I have heard is that it can't be done syntactically for  
references. As

Denis shows you can do it with points (and arrays) but not object
references.

There are many syntax suggestion threads so I suggest search for them
before bring it up again.


Yes, you can do it with pointers, but not with references, and it causes
problems for stuff like ranges. There have been several discussions on  
it over
time, and Walter has pretty much said that it's not a feature that's  
going to
happen. He spent too much time on it before without success to want to  
try at it

again.


If someone were to do the work, and the syntax was bearable, it might be  
considered.  I think Walter no longer wants to accept any ideas without  
proof that they will work -- he's already worked enough on trying to  
implement tail-const.


I personally think tail const is going to be a very important feature that  
will not be solvable via the library.  Tail-const ranges are going to be  
very important when it comes to things like collections.


-Steve


Re: What sorts of things cause cyclic dependencies?

2010-10-14 Thread Steven Schveighoffer
On Thu, 14 Oct 2010 02:31:23 -0400, Jonathan M Davis   
wrote:



On Wednesday 13 October 2010 23:03:05 Lars T. Kyllingstad wrote:

On Thu, 14 Oct 2010 05:53:51 +, Lars T. Kyllingstad wrote:
> On Wed, 13 Oct 2010 21:25:15 -0700, Jonathan M Davis wrote:
>> Okay. in the code that I'm working on at the moment, I get an  
exception

>> saying that a cyclic dependency was detected but no information
>> whatsoever as to where it is or what it means. I haven't been able to
>> find much information on them other than some discussions of making  
it
>> so that the compiler detects them at compile time. I have yet to  
figure
>> out _what_ it is that is causes such errors. Could someone clue me  
in?
>> It's really hard to track down a bug when the error only tells you  
that

>> there's a bug and doesn't say anything about where it happens, and I
>> have no clue what sort of things can be cyclically dependent.
>
> Say you have two modules, a and b.  Both have static constructors,  
and a

>
> imports b:
>   // a.d
>   module a;
>   import b;
>   static this() { ... }
>
>   // b.d
>   module b;
>   static this() { ... }
>
> The language is then defined so that b's constructor is run before  
a's,

> since a depends on b.  But what happens if b imports a as well?  There
> is no way to determine which constructor to run first, so the runtime
> throws a "cyclic dependency" exception.

I should mention that this can happen with larger cycles as well, i.e.  
"a

imports b, b imports c, c imports ..., ... imports a".  This can make
some cyclic dependencies very hard to track down.

There was a discussion about this on the Phobos mailing list a few  
months

ago:

  http://lists.puremagic.com/pipermail/phobos/2010-June/thread.html#949

-Lars


Well, just knowing that it involves module constructors is definitely  
useful,

though the error message really needs to be improved. Thanks.


I had mostly implemented a cyclic dependency improvement that actually  
printed the cycle.  However, I never committed it because I found there  
was a huge hole in the algorithm that needed to be addressed.  Essentially  
certain cycles are allowed (even today).


I think it can be done with an O(n^2) space and an O(n) algorithm, but I  
need to work on it.


BTW, there is a bug report for this problem:  
http://d.puremagic.com/issues/show_bug.cgi?id=4384


-Steve


How to use tango's FileScan correctly?

2010-10-14 Thread qwesx
Hello!

I'm trying out some things in D (with tango) and tried to build a *very* 
primitive indexing program. One function requires to run through a 
directory (without recursion) and get me all the files/folders in there.

So after reading the documentation I found that tango.io.FileScan 
basically does what I need. It's just that I can't get it to work. All 
examples there use some filter, but I don't need one. And the other stuff 
I tried (and which compiled) gives me either a wrong number of files in 
my debug output, or none at all.

Here's (part of) my code:

FileScan scan = new FileScan();
// only one of those was used at a time, the others are commented
// dir is a char[] with an existing (absolute) directory:
scan(dir, "*");
scan(dir, ".*");
scan(dir, "*.*");
scan(dir, "");
scan = scan.sweep(dir, false);


FilePath[] myFolders = scan.folders();
FilePath[] myFiles = scan.files();
char[][] err = scan.errors();
Stdout("found folders: ")(myFolders.length)("\n")();
Stdout("found files  : ")(myFiles.length)("\n")();
Stdout("errors:\n")();
foreach (char[] e; err)
  Stdout(e)("\n")();


The result was always:

found folders: 0
found files  : 0
errors:
% _

I think I'm doing something very wrong here. And it's possibly because I 
don't understand the documentation.

Can you help me get this to work?



Regards
qwesx


Re: Am I doing this right? (File byChunk)

2010-10-14 Thread Andrej Mitrovic
 I'll be sure to check it out once I get my phone line back (forgot to
pay the bills..). I'm currently on expensive wireless (Why is wireless
so expensive anyway? What's so special about radiowaves that were
invented half a century ago?..)

Thanks for the heads up!

On 9/14/10, Jonathan M Davis  wrote:
> gmx.com seems to deal with mailing list e-mails correctly (by actually
> putting
> the ones you sent to the list in your inbox when they come from the list),
> and
> it has free imap and lots of disk space just like gmail (not to mention that
> it
> uses proper folders instead of labels), so I've switched over to it. It's
> much
> more pleasant to deal with (at least when using it from an e-mail client;
> whether the user interface for the site itself is better is more debatable).
> And
> switching e-mail addresses gives me a chance to reduce the spam that I get.
> :)
>
> - Jonathan M Davis
>


Re: GC interpreting integer values as pointers

2010-10-14 Thread bearophile
Steven Schveighoffer:

> There are two problems here.  First, D has unions, so it is impossible for  
> the GC to determine if a union contains an integer or a pointer.

D has unions, and sometimes normal C-style unions are useful. But in many 
situations when you have a union you also keep a tag that represents the type, 
so in many of those situations you may use the tagged union of Phobos, 
std.variant.Algebraic (if the Phobos implementation is good enough, currently 
unfinished and not good enough yet) and the D GC may be aware and read and use 
the tag of an Algebraic union to know at runtime what's the type. This improves 
the GC precision a little.

Bye,
bearophile


Passing multidimensional D arrays to C (sorry if duplicate)

2010-10-14 Thread Andrej Mitrovic
I don't have a minimal working example right now so I'll just have to show you 
the client code and the C function prototype. I have a C++ DLL with a C 
interface for some of its functions and I am dynamically loading it in my D 
application. Here's some code with the usual DLL loading bits left out:

alias extern(C) void function(float** inputs) ProcessProc;
// Some code that loads the DLL, calls Windows' GetProcAddress.. and now we 
have a function pointer processFunc:
ProcessProc processFunc;

I have no trouble passing single pointer parameters to C functions, and even 
callback functions. But I haven't figured out an elegant way of passing 
multidimensional arrays to functions expecting pointers to pointers. I've tried 
forcing a 2-dimensional array with a cast, or even changing the function 
pointer signature to *fake* that it takes a 2-dimensional array and not a 
ptr-2-ptr, but that doesn't work properly as the C code ends up working only 
partially and I get back an access violation. 

So my calling code looks like the following. Disregard that I'm using GC's 
malloc and not std.c.stdlib.malloc for now please :) :

float[][] _inputs;
float** inputs;

enum numInputs = 4;
enum kBlockSize = 512;

_inputs = new float[][](numInputs, kBlockSize);

// we would now fill the inputs with some random data

inputs = cast(float**)GC.malloc((float*).sizeof * numInputs);

foreach (index; 0 .. numInputs)
{
inputs[index] = _inputs[index].ptr;
}

// some loop that runs for a number of cycles, im using while true just for 
demonstration
while (true)
{
processFunc(inputs);
}

I don't want to leave you in the dark, so let me explain. I'm using the popular 
VST plugin standard, which is used for digital audio plugin effects. The loaded 
DLL can be any DLL file that conforms to this standard and has a certain number 
and type of functions ready to be called from the client code. 

Basically how it's used is: I send a pointer to a number of buffers to the 
DLL's processing function, and the effect does some processing on the data and 
writes it back to the buffers.

If it's necessary I'll try to write a simplified C DLL and calling code to show 
what's wrong.

P.S. (for those in the know) I have a fully working Host example that can load 
VST instruments/effects, check their capabilities, do some processing, and load 
their GUI (if they have one). I have not ported any VST classes used to build 
the VST instruments yet.

P.P.S. I also have a working ASIO Host, however it's only a wrapper around the 
C++ classes. I'm currently having huge issues with COM, and I'm not yet sure if 
there's a bug in DMD or in my implementation.

P.P.P.S. Hopefully I'll be able to provide a clean implementation of both VST 
and ASIO, and after the necessary registration at Steinberg I'll create a 
repository for the projects. Wish me luck. :>


[import,module] got biting again :(

2010-10-14 Thread %u
Yay, free access to a!

I searched for this bug in the bug-reports..
Why are there so many basic import bugs?

--
module main;
import b;

void main(){
  a.write();
}
--
module a;
import std.stdio;

void write(){
  writefln("a");
}
--
module b;
import a; //also with static
--


Re: How to use tango's FileScan correctly?

2010-10-14 Thread Moritz Warning
I suspect there is a bug.
You could use FilePath.toList() as an alternative for now.

foreach(path; FilePath(".").toList())
{
  if(path.isFolder)
folder_counter++;
  else
file_counter++;
}

On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote:

> Hello!
> 
> I'm trying out some things in D (with tango) and tried to build a *very*
> primitive indexing program. One function requires to run through a
> directory (without recursion) and get me all the files/folders in there.
> 
> So after reading the documentation I found that tango.io.FileScan
> basically does what I need. It's just that I can't get it to work. All
> examples there use some filter, but I don't need one. And the other
> stuff I tried (and which compiled) gives me either a wrong number of
> files in my debug output, or none at all.
> 
> Here's (part of) my code:
> 
> FileScan scan = new FileScan();
> // only one of those was used at a time, the others are commented // dir
> is a char[] with an existing (absolute) directory: scan(dir, "*");
> scan(dir, ".*");
> scan(dir, "*.*");
> scan(dir, "");
> scan = scan.sweep(dir, false);
> 
> 
> FilePath[] myFolders = scan.folders(); FilePath[] myFiles =
> scan.files();
> char[][] err = scan.errors();
> Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files
>  : ")(myFiles.length)("\n")(); Stdout("errors:\n")();
> foreach (char[] e; err)
>   Stdout(e)("\n")();
> 
> 
> The result was always:
> 
> found folders: 0
> found files  : 0
> errors:
> % _
> 
> I think I'm doing something very wrong here. And it's possibly because I
> don't understand the documentation.
> 
> Can you help me get this to work?
> 
> 
> 
> Regards
> qwesx



Re: Passing multidimensional D arrays to C (sorry if duplicate)

2010-10-14 Thread bearophile
Andrej Mitrovic:

> But I haven't figured out an elegant way of passing multidimensional arrays 
> to functions expecting pointers to pointers.

In D there are no nD dynamic arrays.
nD arrays in D may be fixed-sized. The fixed-sized ones are just a contiguous 
sequence of values (so their rows may be not aligned to 16 bytes).
The dynamic arrays may contain other dynamic arrays, so a 2D dynamic array is a 
2-word struct that points to an array of 2-word structs, each of them points to 
an array of the items (so if the row lengths are all the same you are wasting 
memory).
There are few different ways to allocate 2D arrays in C, if your C function 
expects a pointer to pointers, then it wants an array of pointers to the row, 
so the D structure is not fit, you need to build an array of pointers:

void main() {
enum int side = 10;
alias int T;
auto m = new T[][](side, side);
auto m2 = new T*[side];
foreach (i, ref p; m2)
p = m[i].ptr;
// now you may read m2.ptr from C
}

Bye,
bearophile


Re: [import,module] got biting again :(

2010-10-14 Thread bearophile
%u:

> Why are there so many basic import bugs?

Module system bugs are among the most voted in Bugzilla. True modules are 
absent in C/C++, so maybe Walter thinks assuring their semantics is correct is 
not so important compared to other kinds of bugs, or maybe such bugs are hard 
to fix, I don't know.

Bye,
bearophile


Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread Andrej Mitrovic
I'm not sure if this is a legitimate bug or one of my brainfarts.

I know that if I'm using a foreach loop with a char array as a reusable 
datatype I definitely have to create a copy if I want to store it to a string.

But this code is a little more subtle, check it out (This is Windows only 
because it uses the registry, sorry):

module mymodule;

import std.stdio : writeln, write;
import std.windows.registry;

void main()
{
Key HKLM = Registry.localMachine;
Key SFW = HKLM.getKey("software");

string[] names;

foreach (Key key; SFW.keys())
{
string name = key.name();
// string name = key.name().idup; // workaround for the issue
names ~= name;
}

writeln("results:");
foreach (name; names)
{
write(name, ", ");
}
}

The results are quite unexpected. The strings get overwritten with each other, 
and in my case the results are similar to this:

Sun Microsystems, Sun Micros, Sun , Sun Micr, Sun, Sun Mic,...

And it goes like that for a hundred or so values, then switches to the next 
name and writes more garbage like that.

If I use .idup, the problem goes away. What I don't understand is why assigning 
a string to a string isn't safe in this case? They're both immutable, so I was 
expecting the contents of the strings never to change. 

If it's not a bug, it certainly is a subtle issue. The original foreach loop 
was quite big, and it took some time to figure out the problem. Are we *always* 
supossed to be using .idup in a foreach loop? Of course, the Key key variable 
is reused in the foreach loop, so I guess this has something to do with the 
results.


Overloading Generic and non-generic functions

2010-10-14 Thread Andrej Mitrovic
AFAIK the following should be allowed, but it's not (v2.048):

void test(uint) {  }

void test(T)(T value) { }

void main()
{
test(42);
test("hello");
}

These end up conflicting with each other. From what I've read in TDPL we should 
be able to overload generic and nongeneric functions, there's an example in the 
book similar to this one, but it doesn't work. Has this been filed as a bug 
already?


Order of interface implementations affects code

2010-10-14 Thread Andrej Mitrovic
Should the order in which you implement interfaces have an effect in your code? 
It seems to be that way when you have two functions with the same name in the 
different interfaces. Here's an example:

import std.stdio : writeln;

interface Foo
{
final void run() { writeln("foo"); } 
}

interface Bar
{
final void run() { writeln("bar"); } 
}

class One : Foo, Bar
{
}

class Two : Bar, Foo
{
}

void main()
{
with (new One)
{
run();  // writes foo
}

with (new Two)
{
run();  // writes bar
}
}

Bug? Or legitimate working code?


Re: How to use tango's FileScan correctly?

2010-10-14 Thread Moritz Warning
Here is the bug report (patch proposal included):

http://dsource.org/projects/tango/ticket/2003

On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote:

> Hello!
> 
> I'm trying out some things in D (with tango) and tried to build a *very*
> primitive indexing program. One function requires to run through a
> directory (without recursion) and get me all the files/folders in there.
> 
> So after reading the documentation I found that tango.io.FileScan
> basically does what I need. It's just that I can't get it to work. All
> examples there use some filter, but I don't need one. And the other
> stuff I tried (and which compiled) gives me either a wrong number of
> files in my debug output, or none at all.
> 
> Here's (part of) my code:
> 
> FileScan scan = new FileScan();
> // only one of those was used at a time, the others are commented // dir
> is a char[] with an existing (absolute) directory: scan(dir, "*");
> scan(dir, ".*");
> scan(dir, "*.*");
> scan(dir, "");
> scan = scan.sweep(dir, false);
> 
> 
> FilePath[] myFolders = scan.folders(); FilePath[] myFiles =
> scan.files();
> char[][] err = scan.errors();
> Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files
>  : ")(myFiles.length)("\n")(); Stdout("errors:\n")();
> foreach (char[] e; err)
>   Stdout(e)("\n")();
> 
> 
> The result was always:
> 
> found folders: 0
> found files  : 0
> errors:
> % _
> 
> I think I'm doing something very wrong here. And it's possibly because I
> don't understand the documentation.
> 
> Can you help me get this to work?
> 
> 
> 
> Regards
> qwesx



Re: Order of interface implementations affects code

2010-10-14 Thread Jonathan M Davis
On Thursday, October 14, 2010 10:14:25 Andrej Mitrovic wrote:
> Should the order in which you implement interfaces have an effect in your
> code? It seems to be that way when you have two functions with the same
> name in the different interfaces. Here's an example:
> 
> import std.stdio : writeln;
> 
> interface Foo
> {
> final void run() { writeln("foo"); }
> }
> 
> interface Bar
> {
> final void run() { writeln("bar"); }
> }
> 
> class One : Foo, Bar
> {
> }
> 
> class Two : Bar, Foo
> {
> }
> 
> void main()
> {
> with (new One)
> {
> run();  // writes foo
> }
> 
> with (new Two)
> {
> run();  // writes bar
> }
> }
> 
> Bug? Or legitimate working code?

I'd have to pull out my copy of TDPL, but IIRC, it should not be legal to call 
run() directly because it's ambiguous. Assuming that dmd was working correctly 
on this issue, it wouldn't let this code compile. I believe that you'd have to 
do something like Foo.run() and Bar.run() to call run(). I'd have to check TDPL 
to be completely sure of the syntax though.

- Jonathan M Davis


Re: What sorts of things cause cyclic dependencies?

2010-10-14 Thread spir
On Thu, 14 Oct 2010 06:03:05 + (UTC)
"Lars T. Kyllingstad"  wrote:

> On Thu, 14 Oct 2010 05:53:51 +, Lars T. Kyllingstad wrote:
> 
> > On Wed, 13 Oct 2010 21:25:15 -0700, Jonathan M Davis wrote:
> > 
> >> Okay. in the code that I'm working on at the moment, I get an exception
> >> saying that a cyclic dependency was detected but no information
> >> whatsoever as to where it is or what it means. I haven't been able to
> >> find much information on them other than some discussions of making it
> >> so that the compiler detects them at compile time. I have yet to figure
> >> out _what_ it is that is causes such errors. Could someone clue me in?
> >> It's really hard to track down a bug when the error only tells you that
> >> there's a bug and doesn't say anything about where it happens, and I
> >> have no clue what sort of things can be cyclically dependent.
> > 
> > 
> > Say you have two modules, a and b.  Both have static constructors, and a
> > imports b:
> > 
> >   // a.d
> >   module a;
> >   import b;
> >   static this() { ... }
> > 
> >   // b.d
> >   module b;
> >   static this() { ... }
> > 
> > The language is then defined so that b's constructor is run before a's,
> > since a depends on b.  But what happens if b imports a as well?  There
> > is no way to determine which constructor to run first, so the runtime
> > throws a "cyclic dependency" exception.
> 
> 
> I should mention that this can happen with larger cycles as well, i.e. "a 
> imports b, b imports c, c imports ..., ... imports a".  This can make 
> some cyclic dependencies very hard to track down.
> 
> There was a discussion about this on the Phobos mailing list a few months 
> ago:
> 
>   http://lists.puremagic.com/pipermail/phobos/2010-June/thread.html#949
> 
> -Lars


I'm totally new to D, but have some real-life experience with circular imports. 
A typical case is with unit testing. Say you design a parsing lib, with (among 
others) a module defining Pattern types and another for (parse tree) Nodes, 
wich are thee results of successful pattern matches.
To test Patterns, no issue, since it already imports Nodes for normal process. 
But testing Nodes introduces a circular dependance, only for testing, because 
the ordinary way to produce a node, and thus to be able to test its 
functionality, is to create a Pattern and run its match method against source 
text.
2 solutions I know of:
* create fake Pattern types inside the Nodes module, just for testing
* export Nodes' test routines into a third module that imports both Patterns 
and Nodes, but is not import.
That's probably why many libraries have loads of separated test* unittest 
modules. But I prefere to have tests locally written in the module itself 
(which well seems to be the intention of D's testing features).

Some static languages (eg freepascal) allow mutual dependance as long as at 
least one module (M1) uses imported elements of the other (M2) on the 
implementation side only (not in the interface). This allows the compiler 
initially constructing the interface of M1 (without any mention of M2), to be 
imported by M2. Then, M2 can be fully constructed, and imported into M1 for the 
needs of its implementation only.


Denis 
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: Overloading Generic and non-generic functions

2010-10-14 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


AFAIK the following should be allowed, but it's not (v2.048):

void test(uint) {  }

void test(T)(T value) { }

void main()
{
test(42);
test("hello");
}

These end up conflicting with each other. From what I've read in TDPL we  
should be able to overload generic and nongeneric functions, there's an  
example in the book similar to this one, but it doesn't work. Has this  
been filed as a bug already?


http://d.puremagic.com/issues/show_bug.cgi?id=2972

--
Simen


Re: GC interpreting integer values as pointers

2010-10-14 Thread Steven Schveighoffer
On Thu, 14 Oct 2010 12:39:33 -0400, bearophile   
wrote:



Steven Schveighoffer:

There are two problems here.  First, D has unions, so it is impossible  
for

the GC to determine if a union contains an integer or a pointer.


D has unions, and sometimes normal C-style unions are useful. But in  
many situations when you have a union you also keep a tag that  
represents the type, so in many of those situations you may use the  
tagged union of Phobos, std.variant.Algebraic (if the Phobos  
implementation is good enough, currently unfinished and not good enough  
yet) and the D GC may be aware and read and use the tag of an Algebraic  
union to know at runtime what's the type. This improves the GC precision  
a little.


Unions are rare enough that I think this may not be worth doing.  But yes,  
it could be had.


-Steve


Re: GC interpreting integer values as pointers

2010-10-14 Thread Ivo Kasiuk
> On Sat, 09 Oct 2010 15:51:37 -0400, Ivo Kasiuk  wrote:
> 
> > Hi!
> >
> > In my D programs I am having problems with objects not getting finalised
> > although there is no reference anymore. It turned out that this is
> > caused by integers which happen to have values corresponding to pointers
> > into the heap. So I wrote a test program to check the GC behaviour
> > concerning integer values:
> >
> 
> [snip]
> 
> > So in most but not all situations the integer value keeps the object
> > from getting finalised. This observation corresponds to the effects I
> > saw in my programs.
> >
> > I find this rather unfortunate. Is this known, documented behaviour? In
> > a typical program there are such integer values all over the place. How
> > should such values be stored to avoid unwanted interaction with the GC?
> 
> Yes, D's garbage collector is a conservative garbage collector.  One which  
> doesn't have this problem is called a precise garbage collector.
> 
> There are two problems here.  First, D has unions, so it is impossible for  
> the GC to determine if a union contains an integer or a pointer.
> 
> Second problem is the granularity of scanning.  A memory block is scanned  
> as if every n bits (n being your architecture) is a pointer, or there are  
> no pointers.  This is determined by a bit associated with the block (the  
> NO_SCAN bit).
> 
> If you allocate a memory block that contains at least one pointer, then  
> all the words in the memory block are considered to be pointers by the  
> GC.  There is a (continually updated) patch which allows the GC to be  
> semi-precise.  That is, the type information of the memory block will be  
> linked to it.  This will allow precise scanning except for unions.  Once  
> this is integrated, the false pointer problem will be much less prevalent.
> 
> -Steve

Thanks! This absolutely makes sense. It is basically a trade-off between
precision and efficiency of the GC.
Slowly, I am learning all the little details of D's garbage collection.
It is more complicated than it seems at first, but understanding it
better greatly helps to write better programs in terms of memory
management.

There is one case though that I am still not sure about: associative
arrays. It seems that keys as well as values in AAs are scanned for
pointers even if both are integer types. How can I tell the GC that I do
not want them to be scanned? I know about the NO_SCAN flag but what
memory region should it be applied to in this case?

BTW: considering the "conservative" scanning, the implementation of
Object.toHash() is somewhat interesting:

hash_t toHash()
{
  // BUG: this prevents a compacting GC from working, needs to be fixed
  return cast(hash_t)cast(void*)this;
}

So an object's hash value will keep the GC from freeing the object, if
that value is scanned. But as the comment indicates, this implementation
needs to be changed anyway (I am eager to see the result). A compacting
GC probably gives rise to some whole new problems.

Ivo




Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread Steven Schveighoffer

On Thu, 14 Oct 2010 13:01:36 -0400, Andrej Mitrovic  wrote:


I'm not sure if this is a legitimate bug or one of my brainfarts.

I know that if I'm using a foreach loop with a char array as a reusable  
datatype I definitely have to create a copy if I want to store it to a  
string.


But this code is a little more subtle, check it out (This is Windows  
only because it uses the registry, sorry):


module mymodule;

import std.stdio : writeln, write;
import std.windows.registry;

void main()
{
Key HKLM = Registry.localMachine;
Key SFW = HKLM.getKey("software");

string[] names;

foreach (Key key; SFW.keys())
{
string name = key.name();
// string name = key.name().idup; // workaround for the issue
names ~= name;
}

writeln("results:");
foreach (name; names)
{
write(name, ", ");
}
}

The results are quite unexpected. The strings get overwritten with each  
other, and in my case the results are similar to this:


Sun Microsystems, Sun Micros, Sun , Sun Micr, Sun, Sun Mic,...

And it goes like that for a hundred or so values, then switches to the  
next name and writes more garbage like that.


If I use .idup, the problem goes away. What I don't understand is why  
assigning a string to a string isn't safe in this case? They're both  
immutable, so I was expecting the contents of the strings never to  
change.


If it's not a bug, it certainly is a subtle issue. The original foreach  
loop was quite big, and it took some time to figure out the problem. Are  
we *always* supossed to be using .idup in a foreach loop? Of course, the  
Key key variable is reused in the foreach loop, so I guess this has  
something to do with the results.


I'm not familiar with std.windows.registry, but there are two things here.

First, unequivocally, this is a bug.  If key.name is returning an  
immutable(char)[], and later on that value is being overwritten, this is a  
violation of the type system (immutable data must never change again).


Second, I think the bug may not be that it's violating immutability, but  
rather that it's typed key.name as string.  It could probably be  
const(char)[].  Essentially, I think from the behavior described that the  
foreach loop is reusing the name buffer for each iteration of the loop.   
This is probably to save extra heap allocations in case you don't use them  
after the foreach loop is over.  I think your workaround is the correct  
way to deal with it.


This is a common problem in defining an opApply loop which streams data --  
do you make things safe or efficient?  The only reasonable solution IMO is  
to make them efficient, because safety can be had by duping the data.


-Steve


Re: GC interpreting integer values as pointers

2010-10-14 Thread Steven Schveighoffer

On Thu, 14 Oct 2010 13:35:13 -0400, Ivo Kasiuk  wrote:


There is one case though that I am still not sure about: associative
arrays. It seems that keys as well as values in AAs are scanned for
pointers even if both are integer types. How can I tell the GC that I do
not want them to be scanned? I know about the NO_SCAN flag but what
memory region should it be applied to in this case?


This is a common problem.  I am not intimately familiar with AAs, but it  
may have something to do with the fact that it's not a templated type.   
That means the runtime is responsible for allocating AA nodes.


I think at the moment there is no way to do this.  I also think there is  
likely a bug report to this effect, and that others may have implemented  
better AAs to fix the issue.  Try searching the bug database for AA and  
NO_SCAN.


-Steve


Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread bearophile
Steven Schveighoffer:

> This is a common problem in defining an opApply loop which streams data --  
> do you make things safe or efficient?  The only reasonable solution IMO is  
> to make them efficient, because safety can be had by duping the data.

The only reasonable solution is to make it safe, and then allow the unsafe and 
more efficient behaviour only on explicit request. This follows D philosophy 
and in practice it's the only design that allows you to write programs that 
actually work, instead of being just a nest for bugs.

Bye,
bearophile


Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread Andrej Mitrovic
So do I file this as a bug? The current behavior is way too subtle
imo, at least the compiler could issue a warning if this behavior is
intended.

On 10/14/10, bearophile  wrote:
> Steven Schveighoffer:
>
>> This is a common problem in defining an opApply loop which streams data --
>>
>> do you make things safe or efficient?  The only reasonable solution IMO is
>>
>> to make them efficient, because safety can be had by duping the data.
>
> The only reasonable solution is to make it safe, and then allow the unsafe
> and more efficient behaviour only on explicit request. This follows D
> philosophy and in practice it's the only design that allows you to write
> programs that actually work, instead of being just a nest for bugs.
>
> Bye,
> bearophile
>


Re: writing

2010-10-14 Thread spir
On Thu, 14 Oct 2010 08:05:09 + (UTC)
"Lars T. Kyllingstad"  wrote:

> On Thu, 14 Oct 2010 09:58:36 +0200, spir wrote:
> 
> > Hello,
> > 
> > write and writeln just write; writef and writefln first format: seems
> > clear. But the latter do not work properly with D strings, and the
> > former do not work without format. Is there a practical way to just
> > write anything to the terminal (without caring of its type)?
> > 
> > Is there some rationale about this?
> > Would it be possible to automatically add \0 to D strings passed to
> > write/writeln (can a programmer define a custom func doing this before
> > delegating to builtin funcs, or is it necessarily a job for the
> > compiler?)? And/or what about having writef/writefln use "%s" as default
> > format (when the first arg is not a string)?
> 
> 
> I don't understand what you mean.  This works just fine:
> 
>   import std.stdio;
> 
>   void main()
>   {
>   string s = "Hello world!";
>   writeln(s);
>   }
> 
> If I'm misunderstanding you, please explain, or perhaps give a code 
> example.
> 
> -Lars

Sorry, seems I just mistake the various C & D ways of coping with strings (too 
many forms of char arrays and functions that deal with them). I'll just stick 
with D funcs.

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: Order of interface implementations affects code

2010-10-14 Thread bearophile
Jonathan M Davis:

> I believe that you'd have to 
> do something like Foo.run() and Bar.run() to call run(). I'd have to check 
> TDPL 
> to be completely sure of the syntax though.

I think that's a compiler bug, regardless what the TDPL-Bible says :-)

Bye,
bearophile


Re: How to use tango's FileScan correctly?

2010-10-14 Thread Moritz Warning
Ok,

as I've found out, FileScan is only for locating a set of files.
the preferred way is to use the virtual file system (VFS):

http://dsource.org/projects/tango/wiki/ChapterVFS

Examples:
http://www.dsource.org/projects/tango/wiki/VfsZipAndLinesExample
http://dsource.org/projects/tango/browser/trunk/doc/example/vfs/vfscan.d
http://dsource.org/projects/tango/browser/trunk/doc/example/vfs

But I think FilePath.toList()
is enough for your plans.


On Thu, 14 Oct 2010 15:31:47 +, qwesx wrote:

> Hello!
> 
> I'm trying out some things in D (with tango) and tried to build a *very*
> primitive indexing program. One function requires to run through a
> directory (without recursion) and get me all the files/folders in there.
> 
> So after reading the documentation I found that tango.io.FileScan
> basically does what I need. It's just that I can't get it to work. All
> examples there use some filter, but I don't need one. And the other
> stuff I tried (and which compiled) gives me either a wrong number of
> files in my debug output, or none at all.
> 
> Here's (part of) my code:
> 
> FileScan scan = new FileScan();
> // only one of those was used at a time, the others are commented // dir
> is a char[] with an existing (absolute) directory: scan(dir, "*");
> scan(dir, ".*");
> scan(dir, "*.*");
> scan(dir, "");
> scan = scan.sweep(dir, false);
> 
> 
> FilePath[] myFolders = scan.folders(); FilePath[] myFiles =
> scan.files();
> char[][] err = scan.errors();
> Stdout("found folders: ")(myFolders.length)("\n")(); Stdout("found files
>  : ")(myFiles.length)("\n")(); Stdout("errors:\n")();
> foreach (char[] e; err)
>   Stdout(e)("\n")();
> 
> 
> The result was always:
> 
> found folders: 0
> found files  : 0
> errors:
> % _
> 
> I think I'm doing something very wrong here. And it's possibly because I
> don't understand the documentation.
> 
> Can you help me get this to work?
> 
> 
> 
> Regards
> qwesx



Re: How to use tango's FileScan correctly?

2010-10-14 Thread qwesx
On Thu, 14 Oct 2010 18:07:20 +, Moritz Warning wrote:

> Ok,
> 
> as I've found out, FileScan is only for locating a set of files. the
> preferred way is to use the virtual file system (VFS):
> 
> http://dsource.org/projects/tango/wiki/ChapterVFS
> 
> Examples:
> http://www.dsource.org/projects/tango/wiki/VfsZipAndLinesExample
> http://dsource.org/projects/tango/browser/trunk/doc/example/vfs/vfscan.d
> http://dsource.org/projects/tango/browser/trunk/doc/example/vfs
> 
> But I think FilePath.toList()
> is enough for your plans.


I'll take a look at it.
Thank all three of you, I got it working with toList()
:-)


Regards
qwesx



Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread Steven Schveighoffer
On Thu, 14 Oct 2010 13:49:13 -0400, bearophile   
wrote:



Steven Schveighoffer:

This is a common problem in defining an opApply loop which streams data  
--
do you make things safe or efficient?  The only reasonable solution IMO  
is

to make them efficient, because safety can be had by duping the data.


The only reasonable solution is to make it safe, and then allow the  
unsafe and more efficient behaviour only on explicit request. This  
follows D philosophy and in practice it's the only design that allows  
you to write programs that actually work, instead of being just a nest  
for bugs.


How do you request in a foreach loop that it doesn't dup?

That's why I think the only one which allows both is the by default unsafe  
version.


Note also, by "unsafe" we just mean surprising :)  It's still safe in  
terms of memory safety.



On Thu, 14 Oct 2010 13:55:38 -0400, Andrej Mitrovic  
 wrote:



So do I file this as a bug? The current behavior is way too subtle
imo, at least the compiler could issue a warning if this behavior is
intended.


Well, at the very least, this violates immutability.  You can file a bug  
based on those grounds alone.


Whether the foreach loop should auto-dup for you is another question, I  
think it's fine to require you to dup each key's name if you plan on using  
it later, but this should be in the documentation.


-Steve


Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread bearophile
Steven Schveighoffer:

> How do you request in a foreach loop that it doesn't dup?

There are several ways to do this. You may add a boolean value in the 
struct/class template, that switches the safe/unsafe behaviour (defaults to 
safe), or you may let the basic opApply to dup, plus you add another method 
with a name that warns against its non-copying behaviour that doesn't dup. In 
my dlibs1 I have used the first solution for the lazy 
xpermutations/xcombinations.


> Whether the foreach loop should auto-dup for you is another question, I  
> think it's fine to require you to dup each key's name if you plan on using  
> it later, but this should be in the documentation.

D Zen follows another design philosophy, documentation is not enough, people 
forget things.


> Note also, by "unsafe" we just mean surprising :)  It's still safe in  
> terms of memory safety.

"Safe" has many different meanings. Something that on default acts in a 
bug-prone way is not "safe".

Bye,
bearophile


Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread Jonathan M Davis
On Thursday 14 October 2010 12:20:06 bearophile wrote:
> Steven Schveighoffer:
> > How do you request in a foreach loop that it doesn't dup?
> 
> There are several ways to do this. You may add a boolean value in the
> struct/class template, that switches the safe/unsafe behaviour (defaults
> to safe), or you may let the basic opApply to dup, plus you add another
> method with a name that warns against its non-copying behaviour that
> doesn't dup. In my dlibs1 I have used the first solution for the lazy
> xpermutations/xcombinations.
> 
> > Whether the foreach loop should auto-dup for you is another question, I
> > think it's fine to require you to dup each key's name if you plan on
> > using it later, but this should be in the documentation.
> 
> D Zen follows another design philosophy, documentation is not enough,
> people forget things.
> 
> > Note also, by "unsafe" we just mean surprising :)  It's still safe in
> > terms of memory safety.
> 
> "Safe" has many different meanings. Something that on default acts in a
> bug-prone way is not "safe".
> 
> Bye,
> bearophile

The "safe" that Walter and Andrei are almost always concerned with is memory 
safety. That doesn't mean that other types of safety aren't important, but it 
does mean that that's the sort of safety that dmd and Phobos is generally 
concerned about.

- Jonathan M Davis


Re: Foreach and string to string assignment (maybe a bug..)

2010-10-14 Thread bearophile
Jonathan M Davis:

> The "safe" that Walter and Andrei are almost always concerned with is memory 
> safety.

Please help me help Walter understand that for a modern system language memory 
safety isn't the only safety worth having :-)

Bye,
bearophile


about pointer syntax

2010-10-14 Thread spir
Hello,

As a way to start learning D by practicing, I'm trying to implement a symbol 
table as linked list: see prototype code of the structs below. (Hints about 
good D coding welcome :-)

2 little questions about pointers:
1. To please the compiler, I had to wrap dereferencing in parens, like in 
"(*symbol).name". Is this just normal (for disambiguation)?
2. Just noticed the compiler accepts "symbol.name", while symbol is a pointer: 
is there implicit dereferencing of pointers to structs? If yes, does this also 
apply to pointers to arrays (for information, this what Oberon does).

And a note: had forgotten to add an empty main(), just for compiling: the 
linker produced a rather big amount of error text without any hint to the 
actual issue. Maybe dmd could cope with that before calling gcc?

Finally: the reference is rather harsh for me, esp there are very few example 
(I have few practice of C, and none of C++); the bits of tutorials I found are 
too light or just started (toc points to empty pages). Is there anywhere online 
a kind of D programming guide, even not polished or possibly unfinished (I know 
about the book; maybe I'll order it, but in meantime...).

Thank you,
Denis

== code ==
struct Symbol {
string name  = "" ;
int element  = 0 ;
Symbol* next = null ;
}
struct List {
Symbol* first = null ;
int element(string name) {
Symbol* symbol = this.first ;
while (symbol) {
if ((*symbol).name ==  name) {return (*symbol).element ;} ;
symbol = (*symbol).next ;
}
return 0 ;
}
}
==

-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: about pointer syntax

2010-10-14 Thread bearophile
spir:

> As a way to start learning D by practicing, I'm trying to implement a symbol 
> table as linked list: see prototype code of the structs below. (Hints about 
> good D coding welcome :-)

I have modified your code a little:

struct Symbol {
string name;
int element;
Symbol* next;

this(string n, int e, Symbol* s=null) {
name = n;
element = e;
next = s;
}
}

struct List {
Symbol* first;

int element(string name) {
for (auto symbol = this.first; symbol != null; symbol = symbol.next)
if (symbol.name == name)
return symbol.element;
return 0;
}
}

void main() {
auto l = List(new Symbol("baz", 3, new Symbol("bar", 2, new Symbol("foo", 
1;
assert(l.element("bar") == 2);
}

- There's no need to initialize int to 0, string to "", pointers to null, etc, 
the compiler does it for you on default. Each type has a default init value 
(for floating point values it uses a NaN).
- Generally don't put a space before the ending semicolon.
- Four spaces indent and no space before the "*" of the pointer, as you have 
done, is OK.
- Using a while loop as you have done is OK, I have used a for loop just to 
show a shorter alternative.
- It's generally better to put one or two blank lines before structs, 
functions, etc
- (*symbol).name is written symbol.name in D.
- After an { generally a \n is used, there's no need to use the ; after the }
- using 0 as error return value is sometimes OK, but also keep in mind that 
exceptions are present.
- while(symbol) is acceptable, but some people prefer to put an explicit 
comparison to make the code more readable.
- sometimes using "auto" helps.
- In D linked lists are doable, but much less used, think about using a dynamic 
array, or even in this case an associative array:

void main() {
auto aa = ["foo": 1, "bar": 2, "baz": 3];
assert(aa["bar"] == 2);
}


> 1. To please the compiler, I had to wrap dereferencing in parens, like in 
> "(*symbol).name". Is this just normal (for disambiguation)?
> 2. Just noticed the compiler accepts "symbol.name", while symbol is a 
> pointer: is there implicit dereferencing of pointers to structs? If yes, does 
> this also apply to pointers to arrays (for information, this what Oberon 
> does).

Generally the field dereferencing doesn't require the "(*symbol).name", in D 
you use "symbol.name".
Pointers to arrays are possible, but quite uncommon in D.


> And a note: had forgotten to add an empty main(), just for compiling: the 
> linker produced a rather big amount of error text without any hint to the 
> actual issue. Maybe dmd could cope with that before calling gcc?

I agree, I have bug report 4680 open on something similar:
http://d.puremagic.com/issues/show_bug.cgi?id=4680


> Finally: the reference is rather harsh for me, esp there are very few example 
> (I have few practice of C, and none of C++); the bits of tutorials I found 
> are too light or just started (toc points to empty pages). Is there anywhere 
> online a kind of D programming guide, even not polished or possibly 
> unfinished (I know about the book; maybe I'll order it, but in meantime...).

The D2 documentation isn't abundant yet :-)

Bye,
bearophile


Re: Order of interface implementations affects code

2010-10-14 Thread Stewart Gordon

On 14/10/2010 18:14, Andrej Mitrovic wrote:

Should the order in which you implement interfaces have an effect in
your code?


No.


It seems to be that way when you have two functions with
thesame name in the different interfaces.



If they are normal interface functions, then if they have the same 
signature then they should resolve to the same function in any class 
that implements both.  If they have the same parameters but different 
return types, or are final functions with the same signature, the 
compiler should reject any class that implements both.


If one's final and the other isn't ... I guess I just don't know what's 
meant to happen.


Stewart.


Any usable parsers for D2 around?

2010-10-14 Thread Andrej Mitrovic
Hey,

I've been looking for a D2 parser.. there seems to be a few D1 lexers, parsers, 
and even some minimal semantic analysis tools but I can't find much of anything 
for D2. Perhaps Goldie will be D2 compatible some day soon. :)

There's a "CodeAnalyzer" lexer/parser with some minimal semantics, but it's D1 
only and kind of dead for some years. The Poseidon author added some D2 support 
for it in his editor, so I have kept an eye on that. But interfacing with D1 
code from D2 is kind of complicated, and I need to use it from D2. (I guess I 
could get away with writing a DLL with a simple interface for D2 or 
something..).

I had a visit on the prowiki site and most of the parser projects there are 
either D1-only or dead. So is there anything usable for D2? Specifically I need 
these tools for use with an editor/IDE, which is something I'm working on for 
fun atm. But working on a parser is probably a ton of work, + the whole thing 
screams NIH to me. Luckily enough I don't have to reinvent a GUI and an editing 
control, there's DFL and Scintilla which are pretty awesome for my needs. 

Maybe I should take a look at how Descent/DDT and VisualD do their parsing.. :)


Re: about pointer syntax

2010-10-14 Thread spir
On Thu, 14 Oct 2010 17:16:23 -0400
bearophile  wrote:

> spir:
> 
> > As a way to start learning D by practicing, I'm trying to implement a 
> > symbol table as linked list: see prototype code of the structs below. 
> > (Hints about good D coding welcome :-)
> 
> I have modified your code a little:
> 
> struct Symbol {
> string name;
> int element;
> Symbol* next;
> 
> this(string n, int e, Symbol* s=null) {
> name = n;
> element = e;
> next = s;
> }
> }
> 
> struct List {
> Symbol* first;
> 
> int element(string name) {
> for (auto symbol = this.first; symbol != null; symbol = symbol.next)
> if (symbol.name == name)
> return symbol.element;
> return 0;
> }
> }
> 
> void main() {
> auto l = List(new Symbol("baz", 3, new Symbol("bar", 2, new Symbol("foo", 
> 1;
> assert(l.element("bar") == 2);
> }

Thank you very much! That's exactly what I need to learn good practice, even 
more with comments below. (Hope you don't mind if I send other bits of code to 
be improved that way?)

> - There's no need to initialize int to 0, string to "", pointers to null, 
> etc, the compiler does it for you on default. Each type has a default init 
> value (for floating point values it uses a NaN).

Right. I think at keeping explicit defaults like "int element = 0" for 
documentation. It means "that's precisely what I want as default value", as 
opposed to just the language's "init". (So, for Symbol fields, I would only 
write element & next defaults explicitely, since name has no meaningful 
default: it must be provided.)

> - Generally don't put a space before the ending semicolon.
> - Four spaces indent and no space before the "*" of the pointer, as you have 
> done, is OK.
> - It's generally better to put one or two blank lines before structs, 
> functions, etc

(About ';', I like to separate actual code from grammatical separators, which 
are just noise to my eyes. If I ever write a lib for public use, I'll follow 
such styling guidelines ;-)

> - Using a while loop as you have done is OK, I have used a for loop just to 
> show a shorter alternative.

Thanks, as I said I'm not used to PLs of the C family. Wouldn't have ever 
thought that the "stepping" statement of a for loop can be something else as 
incrementation.

> - (*symbol).name is written symbol.name in D.

Very good.

> - After an { generally a \n is used, there's no need to use the ; after the }

Right.

> - using 0 as error return value is sometimes OK, but also keep in mind that 
> exceptions are present.

;-) Was just a placeholder before I decide how to cope with "finding failure".

> - while(symbol) is acceptable, but some people prefer to put an explicit 
> comparison to make the code more readable.

Right, guess you mean while(symbol != null)?

> - sometimes using "auto" helps.

I need to explore this further (what's the actual purpose of "auto").

> - In D linked lists are doable, but much less used, think about using a 
> dynamic array, or even in this case an associative array:
>
> void main() {
> auto aa = ["foo": 1, "bar": 2, "baz": 3];
> assert(aa["bar"] == 2);
> }

Yes, it was just an exercise. For curiosity, I intend to benchmark lists vs 
sequential arrays vs associative arrays, for various element counts.
(Did that already in another language (freepascal), to know what kind of data 
structures were suited for symbol tables representing the content of 
record-like objects, which number of entries is typically small since 
hand-written by the programmer: sophisticated structures like associative 
arrays and tries started to perform better than plain sequences for counts >> 
100.)

> > 1. To please the compiler, I had to wrap dereferencing in parens, like in 
> > "(*symbol).name". Is this just normal (for disambiguation)?
> > 2. Just noticed the compiler accepts "symbol.name", while symbol is a 
> > pointer: is there implicit dereferencing of pointers to structs? If yes, 
> > does this also apply to pointers to arrays (for information, this what 
> > Oberon does).
> 
> Generally the field dereferencing doesn't require the "(*symbol).name", in D 
> you use "symbol.name".
> Pointers to arrays are possible, but quite uncommon in D.

Sure, there are builtin dynamic arrays :-)
I'll check whether manually pointed arrays also silently dereferencing (on 
element access, on attribute access)?

> > And a note: had forgotten to add an empty main(), just for compiling: the 
> > linker produced a rather big amount of error text without any hint to the 
> > actual issue. Maybe dmd could cope with that before calling gcc?
> 
> I agree, I have bug report 4680 open on something similar:
> http://d.puremagic.com/issues/show_bug.cgi?id=4680

Good.

> > Finally: the reference is rather harsh for me, esp there are very few 
> > example (I have few practice of C, and none of C++); the bits of tutorials 
> > I found are too light or just started (toc p

Re: about pointer syntax

2010-10-14 Thread Andrej Mitrovic
On 10/14/10, bearophile  wrote:

> Generally the field dereferencing doesn't require the "(*symbol).name", in D
> you use "symbol.name".
> Pointers to arrays are possible, but quite uncommon in D.

I'm not sure, but I think function pointers (the C syntax ones, not
variables declared with function/delegate) still need parenthesis for
dereferencing? IIRC I was getting back some weird errors a few days
ago when I was trying it out. I might be wrong though..


Re: about pointer syntax

2010-10-14 Thread bearophile
spir:

> (Hope you don't mind if I send other bits of code to be improved that way?)

Feel free to show them, if I am busy other people may give you an answer. The 
worst that may happen is that no one answers you.


> Right. I think at keeping explicit defaults like "int element = 0" for 
> documentation.

Not putting a value, unless it's different from the standard initializator, is 
a very common idiom in D. It's easy to remember the inits: zero, empty string, 
NaN, null, invalid Unicode chars.


> If I ever write a lib for public use, I'll follow such styling guidelines ;-)

The D style:
http://www.digitalmars.com/d/2.0/dstyle.html


> Wouldn't have ever thought that the "stepping" statement of a for loop can be 
> something else as incrementation.

This is a kind of incrementation:
symbol = symbol.next;

In C-derived languages this line of code:
symbol = symbol + 5;
May be written:
symbol += 5;

In the same way you may think of this (this is not D syntax):
symbol .= next;
As a compact version of:
symbol = symbol.next;


> Right, guess you mean while(symbol != null)?

Right. But some people don't like that.


> I need to explore this further (what's the actual purpose of "auto").

It just asks the compiler to use the default type, it performs a bit of local 
type inferencing.


> For curiosity, I intend to benchmark lists vs sequential arrays vs 
> associative arrays, for various element counts.

Good, it's a way to understand the language better. In the lists vs dynamic 
array I suggest you to also take a look at the produced (dis)assembly.


> to know what kind of data structures were suited for symbol tables 
> representing the content of record-like objects, which number of entries is 
> typically small since hand-written by the programmer: sophisticated 
> structures like associative arrays and tries started to perform better than 
> plain sequences for counts >> 100.)<

D dynamic arrays are not bad, but they are not very efficient, so a sequential 
scan in a small array of integer numbers is faster than an hash search.

You may also try a "perfect hash", for your purpose. Around you may find C code 
(that's easy to translate to D) to create a perfect hash out of a sequence of 
strings.

A binary search in an array of strings-int pairs is an easy option too.

If your symbol are names are short you may also put your string+int pairs in a 
single flat data structure (even keeping a fixed length for each one of them), 
to increase CPU cache locality a bit, something like:

struct Pair { char[10] name; int element; }
Pair[20] data;

In C/C++/D languages usually there are *many* complicated ways to speed up code 
:-) You generally want to use them only in the spots where the profiler tells 
you you need performance. The profiler is used with the DMD -profile switch.

It's also good if you learn D to start using unittests and design by contract 
from the beginning. They help a lot avoid bugs. And the more hairy (pointers, 
etc) your code is, the more useful they are.

Bye,
bearophile


Re: about pointer syntax

2010-10-14 Thread bearophile
> D dynamic arrays are not bad, but they are not very efficient,

I meant associative array, sorry.


broken link: http://d-programming-language.org/phobos/phobos.html

2010-10-14 Thread Gianluigi Rubino
Is it just me or there's a broken link to the library reference in the
official site ? I'm currently using the doc shipped with DMD, but I
found this broken link and I thought it's worth to signal.

Best
Gianluigi


Re: broken link: http://d-programming-language.org/phobos/phobos.html

2010-10-14 Thread Jonathan M Davis
On Thursday, October 14, 2010 16:12:40 Gianluigi Rubino wrote:
> Is it just me or there's a broken link to the library reference in the
> official site ? I'm currently using the doc shipped with DMD, but I
> found this broken link and I thought it's worth to signal.
> 
> Best
> Gianluigi

It's probably there because at some point that will be the correct link, but d-
programming-language.org hasn't been completed yet, so the link doesn't work.

- Jonathan M Davis


Re: Any usable parsers for D2 around?

2010-10-14 Thread Denis Koroskin

On Fri, 15 Oct 2010 02:47:28 +0400, Andrej Mitrovic  wrote:


Hey,

I've been looking for a D2 parser.. there seems to be a few D1 lexers,  
parsers, and even some minimal semantic analysis tools but I can't find  
much of anything for D2. Perhaps Goldie will be D2 compatible some day  
soon. :)


There's a "CodeAnalyzer" lexer/parser with some minimal semantics, but  
it's D1 only and kind of dead for some years. The Poseidon author added  
some D2 support for it in his editor, so I have kept an eye on that. But  
interfacing with D1 code from D2 is kind of complicated, and I need to  
use it from D2. (I guess I could get away with writing a DLL with a  
simple interface for D2 or something..).


I had a visit on the prowiki site and most of the parser projects there  
are either D1-only or dead. So is there anything usable for D2?  
Specifically I need these tools for use with an editor/IDE, which is  
something I'm working on for fun atm. But working on a parser is  
probably a ton of work, + the whole thing screams NIH to me. Luckily  
enough I don't have to reinvent a GUI and an editing control, there's  
DFL and Scintilla which are pretty awesome for my needs.


Maybe I should take a look at how Descent/DDT and VisualD do their  
parsing.. :)


You can try using ddmd (dsource.org/projects/ddmd).