www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cyclic Dependencies

reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Hello all,

I began learning D a few months ago, and now I have a question about 
cyclic dependencies (and some random whining).

I come from a java background and have had no serious exposure to C++. 
In java, cyclic dependencies are legit to the best of my knowledge. I 
don't know about C++, thus I don't know about D.

When I first started learning D I decided that a good way to learn it 
would be by porting a popular java api (mind, I didn't say intelligent), 
which came complete with a few cyclic dependencies. At the moment, I'm 
using GDC, and it refuses to swallow cyclic dependencies. The compiler 
doesn't complain, but it throws a runtime exception. I can break the 
dependency loops and GDC will work just fine, but what I'm wondering is 
whether it is standard that the dependency hierarchy be acyclic, or is 
this some quirk of GDC, or is it more likely that there is something 
weird going on in my java-to-D translation.

Also, I would be trying to compile with DMD, but I have evidently 
managed to crash the compiler, and I don't know if it's DMD's fault or 
mine. It reports an Internal Error in e2ir.c at line 3904. (not being a 
C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much to me)
That was with DMD 1.037, Tango 0.997, and using dsss to build.

On an unrelated note, is this code supposed to be incorrect?

wchar[] w = (true)? "true":"false";

--> Error: cannot implicitly convert expression ("true") of type char[] 
to wchar[]

or should it be reported as a bug?
Dec 08 2008
next sibling parent Zarathustra <adam.chrapkowski gmail.com> writes:
Ellery Newcomer Wrote:

 Hello all,
 
 I began learning D a few months ago, and now I have a question about 
 cyclic dependencies (and some random whining).
 
 I come from a java background and have had no serious exposure to C++. 
 In java, cyclic dependencies are legit to the best of my knowledge. I 
 don't know about C++, thus I don't know about D.
 
 When I first started learning D I decided that a good way to learn it 
 would be by porting a popular java api (mind, I didn't say intelligent), 
 which came complete with a few cyclic dependencies. At the moment, I'm 
 using GDC, and it refuses to swallow cyclic dependencies. The compiler 
 doesn't complain, but it throws a runtime exception. I can break the 
 dependency loops and GDC will work just fine, but what I'm wondering is 
 whether it is standard that the dependency hierarchy be acyclic, or is 
 this some quirk of GDC, or is it more likely that there is something 
 weird going on in my java-to-D translation.
 
 Also, I would be trying to compile with DMD, but I have evidently 
 managed to crash the compiler, and I don't know if it's DMD's fault or 
 mine. It reports an Internal Error in e2ir.c at line 3904. (not being a 
 C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much to me)
 That was with DMD 1.037, Tango 0.997, and using dsss to build.
 
 On an unrelated note, is this code supposed to be incorrect?
 
 wchar[] w = (true)? "true":"false";
 
 --> Error: cannot implicitly convert expression ("true") of type char[] 
 to wchar[]
 
 or should it be reported as a bug?

just use: wchar[] w = (true)? "true"w:"false"w;
Dec 08 2008
prev sibling next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 09 Dec 2008 01:26:29 -0600, Ellery Newcomer wrote:


 
 wchar[] w = (true)? "true":"false";
 
 --> Error: cannot implicitly convert expression ("true") of type char[] 
 to wchar[]
 
 or should it be reported as a bug?

It is not a bug. A string literal such as "true" is a char[] type (UTF8), and the compiler will not implicitly convert UTF8 to UTF16 (wchar[]). You can tell the compiler that the string literal is meant to be UTF16 by added the suffix 'w' to the literal ... "true"w, and in that way no conversion is required. If for some reason you did want a run-time conversion then this should work ... wchar[] w = std.utf.toUTF16((true)? "true":"false"); -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 09 2008
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Derek Parnell wrote:
  > It is not a bug. A string literal such as "true" is a char[] type 
(UTF8),
 and the compiler will not implicitly convert UTF8 to UTF16 (wchar[]).

Which would then beg the obvious wchar[] w = "true";
Dec 09 2008
parent Ary Borenszweig <ary esperanto.org.ar> writes:
Jarrett Billingsley wrote:
 On Tue, Dec 9, 2008 at 12:00 PM, Ellery Newcomer
 <ellery-newcomer utulsa.edu> wrote:
 Derek Parnell wrote:
  > It is not a bug. A string literal such as "true" is a char[] type (UTF8),
 and the compiler will not implicitly convert UTF8 to UTF16 (wchar[]).

wchar[] w = "true";

It's a sort of special case. String literals are, by default, UTF-8. But if you use a string literal in a situation where it can only be UTF-16 or UTF-32, it's automatically converted. However if a string literal is used in a context where it can be multiple encodings, an error results: void foo(char[] s) {} void foo(wchar[] s) {} foo("hello") fails because string literals are implicitly convertible to both char[] and wchar[], so you have to append either a c or a w to the literal. As for why 'wchar[] s = true ? "true" : "false"' doesn't work, it's because the initializer expression is semantically analyzed before looking at the destination type. The type of the initializer is determined to be char[], which is not implicitly convertible to wchar[]. It can obviously be argued that since the operands of ?: are constant, the compiler _could_ figure out that they should be of type wchar[], but that would make the semantic analysis more complicated, and since appending 'w' to the strings is far easier, it probably won't change any time soon.

I think the compiler should be smarter. I understand that the compiler should be simple to allow other implementations to be done easily. But... I don't think that's true. A D compiler must already instantiate templates and do compile-time evaluation. Now tell me that's easy! :-P After all, how many compiler implementors could there be? And how many users of the language? The language should focus on making it very easy to program and to avoid this kinds of pitfalls.
Dec 09 2008
prev sibling next sibling parent reply torhu <no spam.invalid> writes:
Ellery Newcomer wrote:
 When I first started learning D I decided that a good way to learn it 
 would be by porting a popular java api (mind, I didn't say intelligent), 
 which came complete with a few cyclic dependencies. At the moment, I'm 
 using GDC, and it refuses to swallow cyclic dependencies. The compiler 
 doesn't complain, but it throws a runtime exception. I can break the 
 dependency loops and GDC will work just fine, but what I'm wondering is 
 whether it is standard that the dependency hierarchy be acyclic, or is 
 this some quirk of GDC, or is it more likely that there is something 
 weird going on in my java-to-D translation.
 

You can't use module constructors (static this) in modules that import each other.
Dec 09 2008
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
torhu wrote:
 
 You can't use module constructors (static this) in modules that import 
 each other.

So THAT'S why I couldn't replicate it :)
Dec 09 2008
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Ellery Newcomer wrote:

 Hello all,
 
 I began learning D a few months ago, and now I have a question about
 cyclic dependencies (and some random whining).
 
 I come from a java background and have had no serious exposure to C++.
 In java, cyclic dependencies are legit to the best of my knowledge.

Legit in the way that they usually work - something that IMO cause a lot of Java code to be badly designed (causing too tight coupling and difficulties with extending code).
 I
 don't know about C++, thus I don't know about D.
 
 When I first started learning D I decided that a good way to learn it
 would be by porting a popular java api (mind, I didn't say intelligent),
 which came complete with a few cyclic dependencies. At the moment, I'm
 using GDC, and it refuses to swallow cyclic dependencies. The compiler
 doesn't complain, but it throws a runtime exception. I can break the
 dependency loops and GDC will work just fine, but what I'm wondering is
 whether it is standard that the dependency hierarchy be acyclic, or is
 this some quirk of GDC, or is it more likely that there is something
 weird going on in my java-to-D translation.

No quirk, just good design sense. There are also some real cyclic issues in chicken-egg situations.
 Also, I would be trying to compile with DMD, but I have evidently
 managed to crash the compiler, and I don't know if it's DMD's fault or
 mine. It reports an Internal Error in e2ir.c at line 3904. (not being a
 C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much to me)
 That was with DMD 1.037, Tango 0.997, and using dsss to build.

Tango 0.99.7 doesn't support DMD 1.037 - either use DMD 1.033 or check out Tango trunk. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Dec 09 2008
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Lars Ivar Igesund wrote:
 
 Tango 0.99.7 doesn't support DMD 1.037 - either use DMD 1.033 or check out
Tango trunk.
 

Say what you will, I got it to work :) I also experienced the crash on 1.030, 1.033, and 1.035 variously on linux and windows, so 1.037 was just to see if it had been fixed by then. Just to be thorough.
Dec 09 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 09 Dec 2008 10:26:29 +0300, Ellery Newcomer
<ellery-newcomer utulsa.edu> wrote:

 Also, I would be trying to compile with DMD, but I have evidently  
 managed to crash the compiler, and I don't know if it's DMD's fault or  
 mine. It reports an Internal Error in e2ir.c at line 3904. (not being a  
 C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much to me)
 That was with DMD 1.037, Tango 0.997, and using dsss to build.

This is a bug for sure. Could you please post a code sample that causes this behavior (a small one, if possible)?
 On an unrelated note, is this code supposed to be incorrect?

 wchar[] w = (true)? "true":"false";

 --> Error: cannot implicitly convert expression ("true") of type char[]  
 to wchar[]

 or should it be reported as a bug?

Yes it is correct. You need to specify return type explicitly by making at least one of the arguments wide: wchar[] w = true ? "true"w : "false"; wchar[] w = true ? "true" : "false"w; wchar[] w = true ? "true"w : "false"w;
Dec 09 2008
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Ellery Newcomer" wrote
 Hello all,

 I began learning D a few months ago, and now I have a question about 
 cyclic dependencies (and some random whining).

 I come from a java background and have had no serious exposure to C++. In 
 java, cyclic dependencies are legit to the best of my knowledge. I don't 
 know about C++, thus I don't know about D.

 When I first started learning D I decided that a good way to learn it 
 would be by porting a popular java api (mind, I didn't say intelligent), 
 which came complete with a few cyclic dependencies. At the moment, I'm 
 using GDC, and it refuses to swallow cyclic dependencies. The compiler 
 doesn't complain, but it throws a runtime exception. I can break the 
 dependency loops and GDC will work just fine, but what I'm wondering is 
 whether it is standard that the dependency hierarchy be acyclic, or is 
 this some quirk of GDC, or is it more likely that there is something weird 
 going on in my java-to-D translation.

I'm not sure about this problem. I've not encountered it, but it sounds weird that it would cause a runtime error...
 Also, I would be trying to compile with DMD, but I have evidently managed 
 to crash the compiler, and I don't know if it's DMD's fault or mine. It 
 reports an Internal Error in e2ir.c at line 3904.

This is a bug in the compiler. Try to figure out what causes the bug (smallest example possible), and post it to digitalmars' bugzilla. These are very weird, sometimes hard to narrow down issues, but it helps the compiler writers to have a small test case to reproduce it.
 (not being a C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much 
 to me)

It's saying n2->Enumbytes should not be null, if it is, then throw throw an error.
 That was with DMD 1.037, Tango 0.997, and using dsss to build.

Hm... as far as I know, DMD 1.037 doesn't work with Tango 0.99.7. Did you recompile Tango? Or are you using precompiled libraries? If you are, you should match the compiler to what the libraries were built with. If you need to use 1.037, download the latest svn Tango trunk and compile it, or wait for the next release. There are many corrected issues due to compiler changes in the Tango source tree.
 On an unrelated note, is this code supposed to be incorrect?

 wchar[] w = (true)? "true":"false";

 --> Error: cannot implicitly convert expression ("true") of type char[] to 
 wchar[]

A string literal such as "true" is typed as char[]. You cannot assign a char[] to a wchar[] without a cast. Like Zarathustra said, a wchar[] string literal is written as "true"w. -Steve
Dec 09 2008
parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Dec 9, 2008 at 9:52 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 I'm not sure about this problem.  I've not encountered it, but it sounds
 weird that it would cause a runtime error...

It is weird. ====[a.d]==== module a; import b; static this(){} void main(){} ====[b.d]==== module b; import a; static this(){} ====[Command line]==== $ rebuild a $ ./a object.Exception: Cyclic dependency in module a $ If two modules circularly import each other and they both have static ctors - regardless of whether or not those ctors really are circularly dependent - you get an error at runtime. Why it can't determine this at compile time, I don't know. Why it's an error when there's obviously no cyclic dependency, I don't know. http://d.puremagic.com/issues/show_bug.cgi?id=2457
Dec 09 2008
prev sibling next sibling parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Dec 9, 2008 at 12:00 PM, Ellery Newcomer
<ellery-newcomer utulsa.edu> wrote:
 Derek Parnell wrote:
  > It is not a bug. A string literal such as "true" is a char[] type (UTF8),
 and the compiler will not implicitly convert UTF8 to UTF16 (wchar[]).

Which would then beg the obvious wchar[] w = "true";

It's a sort of special case. String literals are, by default, UTF-8. But if you use a string literal in a situation where it can only be UTF-16 or UTF-32, it's automatically converted. However if a string literal is used in a context where it can be multiple encodings, an error results: void foo(char[] s) {} void foo(wchar[] s) {} foo("hello") fails because string literals are implicitly convertible to both char[] and wchar[], so you have to append either a c or a w to the literal. As for why 'wchar[] s = true ? "true" : "false"' doesn't work, it's because the initializer expression is semantically analyzed before looking at the destination type. The type of the initializer is determined to be char[], which is not implicitly convertible to wchar[]. It can obviously be argued that since the operands of ?: are constant, the compiler _could_ figure out that they should be of type wchar[], but that would make the semantic analysis more complicated, and since appending 'w' to the strings is far easier, it probably won't change any time soon.
Dec 09 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jarrett Billingsley" wrote
 It can obviously be argued that since the operands of ?: are constant,
 the compiler _could_ figure out that they should be of type wchar[],
 but that would make the semantic analysis more complicated, and since
 appending 'w' to the strings is far easier, it probably won't change
 any time soon.

Looks like another job for Captain Polysemy!
Dec 09 2008
prev sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Ellery Newcomer wrote:
 Hello all,
 
 I began learning D a few months ago, and now I have a question about 
 cyclic dependencies (and some random whining).
 
 I come from a java background and have had no serious exposure to C++. 
 In java, cyclic dependencies are legit to the best of my knowledge. I 
 don't know about C++, thus I don't know about D.
 
 When I first started learning D I decided that a good way to learn it 
 would be by porting a popular java api (mind, I didn't say intelligent), 
 which came complete with a few cyclic dependencies. At the moment, I'm 
 using GDC, and it refuses to swallow cyclic dependencies. The compiler 
 doesn't complain, but it throws a runtime exception. I can break the 
 dependency loops and GDC will work just fine, but what I'm wondering is 
 whether it is standard that the dependency hierarchy be acyclic, or is 
 this some quirk of GDC, or is it more likely that there is something 
 weird going on in my java-to-D translation.
 
 Also, I would be trying to compile with DMD, but I have evidently 
 managed to crash the compiler, and I don't know if it's DMD's fault or 
 mine. It reports an Internal Error in e2ir.c at line 3904. (not being a 
 C++ guru, the line "assert(n2->Enumbytes);" doesn't mean much to me)
 That was with DMD 1.037, Tango 0.997, and using dsss to build.
 
 On an unrelated note, is this code supposed to be incorrect?
 
 wchar[] w = (true)? "true":"false";
 
 --> Error: cannot implicitly convert expression ("true") of type char[] 
 to wchar[]
 
 or should it be reported as a bug?

Today I completed a simple code analysis tool for D. There be 91 cyclic dependencies spread among 36 files in my project. Not as bad as I thought it would be.
Feb 16 2009