www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Some questions

reply bearophile <bearophileHUGS mailas.com> writes:
Hello, more than one month ago I have started learning D (dmd V.1.015 and
successive ones) on Windows, and I like it a lot. I know various languages,
among them there is Python. In this my first post on digitalmars newsgroups I'd
like to ask few things about some problems I have found that I hope you can
explain/solve to/for me.
I have some suggestions too for D, but I'll probably post them in one or two
posts on digitalmars.D. (In my posts I use 2 spaces indent to reduce line
length, hopefully the web interface will keep them).


1a/1b) I am developing a package of some modules (using the really useful
"bud") each one of them contains some unittests. I'd like a way to just ignore
the main() function eventually present inside imported modules (or maybe to
allow importing and using it as modulename.main()). So they can be used both as
main modules and imported modules (Python allows something similar, using a
different syntax). Related: if I have many modules, I don't want to unittest
them all all the time, I'd like to unittest only the main module I am
developing in that moment. Maybe you can suggests me ways to solve those two
problems in a good way with no changes to the D language :-) (I currently
comment out the main() of all the modules I am not developing at that moment,
and I wait for the unittests of all the modules, but those aren't good
solutions).

----------------------------

2) Do you know why the following isin2() doesn't work?

class Gen {
  int stop;
  this(int instop) { stop = instop; }
  int opApply(int delegate(ref int) dg) {
    int result;
    for (int i = 0; i < stop; i++) {
      result = dg(i);
      if (result) break;
    }
    return 0;
  }
}
bool isin1(Gen items, int el) {
  bool result = false;
  foreach(el2; items)
    if (el == el2) {
      result = true;
      break;
    }
  return result;
}
bool isin2(Gen items, int el) {
  foreach(el2; items)
    if (el == el2)
      return true;
  return false;
}
void main() {
  assert(isin1(new Gen(10), 5) );
  assert(!isin1(new Gen(10), 20) );
  assert(isin2(new Gen(10), 5) );
  assert(!isin2(new Gen(10), 20) );
}

-------------------

3) Probably the last assert has to be true, is this a little bug of std.boxer?

import std.boxer;
int arraycmp(Ty)(Ty[] a1, Ty[] a2) {
  if (a1.length < a2.length) {
    foreach(i, field; a1) {
      if (field < a2[i]) return -1;
      else
        if (field > a2[i]) return 1;
    }
    return -1;
  } else {
    foreach(i, field; a2) {
      if (field < a1[i]) return 1;
      else
        if (field > a1[i]) return -1;
    }
    return (a1.length==a2.length)?0:1;
  }
}
void main() {
  float[] a1 = [1.0, 6.0];
  float[] a2 = [1.0, 35.0];
  assert( arraycmp(a1, a2) == -1 );
  assert( a1 < a2 );
  Box[] b1 = [box("aa"), box(6.0)];
  Box[] b2 = [box("aa"), box(35.0)];
  assert( arraycmp(b1, b2) == - 1 );
  assert( b1 < b2 ); // Error
}

-----------------------

4) This code:
foreach (k, v; ["ab":12])
    putr(k, ' ', v);

Gives me this error:
Error: cannot have out or ref parameter of type char[2u]
Is this a bug of DMD, or some limitation I have to know about?

----------------------------

5) Is this a bug of the function overload system? If the static if is set to
false it gives an error, the only difference is in the order of the definitions
of the overloard alternative() function:

import std.stdio;

int fun(TyElem)(TyElem[] arr) {
    return arr.length;
}

static if (true) { // change this
    alias fun!(char) alternative;
    int alternative(int[] arr) {
        return arr[0];
    }
} else {
    int alternative(int[] arr) {
        return arr[0];
    }
    alias fun!(char) alternative;
}

void caller(TyOp)(TyOp op, char[] s) {
    writefln( op(s) );
}

void main() {
    caller(&alternative, "abc"); // prints 3
}

Bye and thank you,
bearophile
Aug 01 2007
next sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
bearophile wrote:
 2) Do you know why the following isin2() doesn't work?

 class Gen {
   int stop;
   this(int instop) { stop = instop; }
   int opApply(int delegate(ref int) dg) {
     int result;
     for (int i = 0; i < stop; i++) {
       result = dg(i);
       if (result) break;
     }
     return 0;
   }
 }
 bool isin1(Gen items, int el) {
   bool result = false;
   foreach(el2; items)
     if (el == el2) {
       result = true;
       break;
     }
   return result;
 }
 bool isin2(Gen items, int el) {
   foreach(el2; items)
     if (el == el2)
       return true;
   return false;
 }
 void main() {
   assert(isin1(new Gen(10), 5) );
   assert(!isin1(new Gen(10), 20) );
   assert(isin2(new Gen(10), 5) );
   assert(!isin2(new Gen(10), 20) );
 }

You're returning 0, instead of result, in opApply.
 4) This code:
 foreach (k, v; ["ab":12])
     putr(k, ' ', v);

 Gives me this error:
 Error: cannot have out or ref parameter of type char[2u]
 Is this a bug of DMD, or some limitation I have to know about?

"ab" is of type char[2]. If you want a char[] (and you do), write "ab"[] or the more verbose cast(char[])"ab". putr evidently takes its third parameter as inout/out/ref, but you can't do that with static arrays, as the error message says. You need to pass a dynamic array instead.
 5) Is this a bug of the function overload system? If the static if is set to
 false it gives an error, the only difference is in the order of the
 definitions of the overloard alternative() function:

 import std.stdio;

 int fun(TyElem)(TyElem[] arr) {
     return arr.length;
 }

 static if (true) { // change this
     alias fun!(char) alternative;
     int alternative(int[] arr) {
         return arr[0];
     }
 } else {
     int alternative(int[] arr) {
         return arr[0];
     }
     alias fun!(char) alternative;
 }

 void caller(TyOp)(TyOp op, char[] s) {
     writefln( op(s) );
 }

 void main() {
     caller(&alternative, "abc"); // prints 3
 }

It's a bug, probably 810: http://d.puremagic.com/issues/show_bug.cgi?id=810 -- Remove ".doesnotlike.spam" from the mail address.
Aug 01 2007
parent bearophile <bearophileHUGS mailas.com> writes:
Thank you Bill Baxter, your suggestions regarding unittests look a bit better
than what I am doing now. But I think I'll keep commenting out the main (using
a static if(0){}).

D developers may be interested to know how Python (and ShedSkin) solve the
problem with main() I was talking about:

if __name__ == '__main__':
  ...

The *main* module compile has __name__ = "__main__", so what the stuff inside
that 'if' doesn't become executed if the module is being imported. I agree that
Python syntax is ugly (there are people that are pushing for its change) but it
actually solves the problem I was talking about.

Hugs,
bearophile
Aug 03 2007
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
bearophile wrote:
 1a/1b) I am developing a package of some modules (using the really
 useful "bud") each one of them contains some unittests. I'd like a way
 to just ignore the main() function eventually present inside imported
 modules (or maybe to allow importing and using it as modulename.main()).
 So they can be used both as main modules and imported modules (Python
 allows something similar, using a different syntax). 

Not a great solution, but can put main() inside a version block in each file like: version(MAIN) { void main() { //... } } Then when you compile, pass -version=MAIN to the compiler for the one file you want to be main. Related: if I have
 many modules, I don't want to unittest them all all the time, I'd like
 to unittest only the main module I am developing in that moment. Maybe
 you can suggests me ways to solve those two problems in a good way with
 no changes to the D language :-) (I currently comment out the main() of
 all the modules I am not developing at that moment, and I wait for the
 unittests of all the modules, but those aren't good solutions).

Probably 'version' is again your only hope. Maybe you can have a version for each module, like TEST_{MODULENAME}, and then one that does everything: TEST_ALL. I haven't used version much but you should be able to do something like this in each module: ----mymodule.d---- module mymodule; version(TEST_ALL) { version = TEST_MYMODULE; } version(TEST_MYMODULE) { unittest { ... } } ---------- And as for main(), I find it useful to have a dummy module with nothing but an empty main to compile in when doing unit tests of a library. Like: ----testmain.d---- module testmain; void main() {} ----------- Just throw that file into the mix when you want to do unit testing of some files that don't have their own main() already. It's kinda silly to have to do that. D should really be smart enough to know that if I'm asking for -unittest, then I'm going to want a main. --bb
Aug 01 2007