Re: Getting started - D meta-program question

2009-10-07 Thread downs
Justin Johansson wrote:
 Your code as below, using auto to declare a temporary var in an if statement, 
 ahh, nice,
 didn't know that.
 
  if (auto res = dg(current.data))
 return res;
 
 What other statement types can you generalized use of auto like this to?
 

Sadly, it's an if-specific syntax.

 Thank you for taking the time downs,
 
 -- Justin

Anytime.


Re: Getting started - D meta-program question

2009-10-04 Thread downs
Justin Johansson wrote:
 Daniel Keep Wrote:
 
 Justin Johansson wrote:
 There was mention** on the general discussion group that the D 
 foreach_reverse
 language construct could be replaced (emulated?) with a (D) meta-program.

 ** Even a novice programmer can write a meta-program to replace
 foreach_reverse without any runtime performance hit.


 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=97362
   
 As I'm less than a novice with the D meta-programming facilities (at this 
 stage of my journey into D),
 if someone would kindly show me the D meta-program solution to do this,
 I'd really appreciate the enlightenment.

 Thanks again.
 Short answer: you can't.

 Long answer: you can, provided you aren't trying to reverse an opApply,
 which is patently impossible.

 As for the meta-program, I would suspect whoever said that was talking
 about writing a templated type or function to handle it.  You would need
 to use template specialisation or static ifs to switch on what type
 you've been given to reverse.

 http://digitalmars.com/d/1.0/template.html

 http://digitalmars.com/d/1.0/version.html#staticif
 
 Thanks for your answer, Daniel.  I thought the original post was a bit of a 
 red herring but
 thought I'd ask about it anyway.  Good thing I did as you motivated me to 
 delve into the
 subject just after reading your reply.
 
 Just now I've written a bit of CS101 play around code (shown below) for 
 constructing a
 singly-linked list of numbers (Conslist idiom).  As the code seems to work, 
 it looks like
 I've cut my first teeth on D meta programming.
 
 I'm sure there's lots to learn though .. especially looking though some of 
 that std.functional
 stuff.
 
 If you have any comments / suggestions for improvement about this code, I'd 
 graciously accept the same.
 It's just a tutorial exercise for learning the D way of doing things.
 
 
 class List
 {
List next;
int data;
 
this( int data) {
   this.next = null;
   this.data = data;
}
 
static List opCall() {
   return cast(List) null;
}
 
static List opCall( int data) {
   return new List( data);
}
 
static List cons( int data, List list) {
   auto newList = List( data);
   newList.next = list;
   return newList;
}
 
int opApply( int delegate( ref int data) dg) {
   auto result = 0;
   auto list = this;
 
   while ( list !is null) {
  if ((result = dg( list.data)) != 0)
 break;
 
  list = list.next;
   }
 
   return result;
}
 
 }
 
 
 void printdata( int data) {
writef(  %d, data);
 }
 
 
 void print( List list) {
writef( ();
 
if (list !is null) {
   foreach ( x; list) {
  printdata( x);
   }
}
 
writef( ));
 }
 
 
 void println( List list) {
print( list);
writefln();
 }
 
 
 List list(A...)( A args) {
static if (A.length == 0) {
   return List();
}
 
else {
   return List.cons( args[0], list( args[1..$]));
}
 }
 
 
 void main() {
auto l0 = list();
println( l0);

auto l1 = list( 10);
println( l1);

auto l2 = list( 10, 20);
println( l2);

auto l3 = list( 10, 20, 30);
println( l3);

 }
 
 
 Outputs:
 
 ()
 ( 10)
 ( 10 20)
 ( 10 20 30)
 
 Thanks again, Justin
 

I really recommend using a struct. There's rarely need to subclass List nodes 
dynamically, and structs would allow you to define allocators externally, for 
instance, for implementing freelists.

Also, I generally think of a list node as a value, not an object :)

In that sense ..
module test;

import std.string;
struct List(T)
{
  List* next;
  T data;

  static List* opCall(T data, List* next) {
auto res = new List;
res.next = next;
res.data = data;
return res;
  }
  static List* opCall(T[] data...) {
if (!data.length) return null;
else if (data.length == 1) return opCall(data[0], null);
else return opCall(data[0], opCall(data[1..$]));
  }
  List* cons(T data) { return List(data, this); }

  int opApply( int delegate( ref int data) dg) {
auto current = this;

do {
  if (auto res = dg(current.data)) return res;
  current = current.next;
} while (current);

return 0;
  }
  string toString() {
string res = (;
bool first = true;
foreach (value; *this) {
  if (first) first = false;
  else res ~= , ;
  res ~= format(value);
}
return res ~ );
  }
}

void print(T)(T what) {
  if (!what) writefln((nil));
  else writefln(what.toString());
}

import std.stdio;
void main() {
  auto l0 = List!(int)();
  print(l0);

  auto l1 = List!(int)(10);
  print(l1);

  auto l2 = List!(int)(10, 20);
  print(l2);

  auto l3 = List!(int)(10, 20, 30);
  print(l3);
}

gentoo-pc ~ $ gdc test.d -o test_c -g  ./test_c
(nil)
(10)
(10, 20)
(10, 20, 30)


Re: Getting started - D meta-program question

2009-10-04 Thread Justin Johansson
downs Wrote:

 Justin Johansson wrote:
  Daniel Keep Wrote:
  
  Just now I've written a bit of CS101 play around code (shown below) for 
  constructing a
  singly-linked list of numbers (Conslist idiom).  As the code seems to work, 
  it looks like
  I've cut my first teeth on D meta programming.
  
  I'm sure there's lots to learn though .. especially looking though some of 
  that std.functional
  stuff.
  
  If you have any comments / suggestions for improvement about this code, I'd 
  graciously accept the same.
  It's just a tutorial exercise for learning the D way of doing things.
  
  
  class List
  {
 List next;
 int data;
  
 this( int data) {
this.next = null;
this.data = data;
 }
  
 static List opCall() {
return cast(List) null;
 }
  
 static List opCall( int data) {
return new List( data);
 }
  
 static List cons( int data, List list) {
auto newList = List( data);
newList.next = list;
return newList;
 }
  
 int opApply( int delegate( ref int data) dg) {
auto result = 0;
auto list = this;
  
while ( list !is null) {
   if ((result = dg( list.data)) != 0)
  break;
  
   list = list.next;
}
  
return result;
 }
  
  }
  
  
  void printdata( int data) {
 writef(  %d, data);
  }
  
  
  void print( List list) {
 writef( ();
  
 if (list !is null) {
foreach ( x; list) {
   printdata( x);
}
 }
  
 writef( ));
  }
  
  
  void println( List list) {
 print( list);
 writefln();
  }
  
  
  List list(A...)( A args) {
 static if (A.length == 0) {
return List();
 }
  
 else {
return List.cons( args[0], list( args[1..$]));
 }
  }
  
  
  void main() {
 auto l0 = list();
 println( l0);
 
 auto l1 = list( 10);
 println( l1);
 
 auto l2 = list( 10, 20);
 println( l2);
 
 auto l3 = list( 10, 20, 30);
 println( l3);
 
  }
  
  
  Outputs:
  
  ()
  ( 10)
  ( 10 20)
  ( 10 20 30)
  
  Thanks again, Justin
  
 
 I really recommend using a struct. There's rarely need to subclass List nodes 
 dynamically, and structs would allow you to define allocators externally, for 
 instance, for implementing freelists.
 
 Also, I generally think of a list node as a value, not an object :)
 
 In that sense ..
 module test;
 
 import std.string;
 struct List(T)
 {
   List* next;
   T data;
 
   static List* opCall(T data, List* next) {
 auto res = new List;
 res.next = next;
 res.data = data;
 return res;
   }
   static List* opCall(T[] data...) {
 if (!data.length) return null;
 else if (data.length == 1) return opCall(data[0], null);
 else return opCall(data[0], opCall(data[1..$]));
   }
   List* cons(T data) { return List(data, this); }
 
   int opApply( int delegate( ref int data) dg) {
 auto current = this;
 
 do {
   if (auto res = dg(current.data)) return res;
   current = current.next;
 } while (current);
 
 return 0;
   }
   string toString() {
 string res = (;
 bool first = true;
 foreach (value; *this) {
   if (first) first = false;
   else res ~= , ;
   res ~= format(value);
 }
 return res ~ );
   }
 }
 
 void print(T)(T what) {
   if (!what) writefln((nil));
   else writefln(what.toString());
 }
 
 import std.stdio;
 void main() {
   auto l0 = List!(int)();
   print(l0);
 
   auto l1 = List!(int)(10);
   print(l1);
 
   auto l2 = List!(int)(10, 20);
   print(l2);
 
   auto l3 = List!(int)(10, 20, 30);
   print(l3);
 }


Great, this question was well worth asking :-)

My code above was true to C style.

Your code as below, using auto to declare a temporary var in an if statement, 
ahh, nice,
didn't know that.

 if (auto res = dg(current.data))
return res;

What other statement types can you generalized use of auto like this to?

 I really recommend using a struct. There's rarely need to subclass List nodes 
 dynamically, and structs would allow you to define allocators externally, for 
 instance, for implementing freelists.

I think with the overhead of at least 8 bytes for a PODO, your suggestion 
certainly makes sense;
struct is a lot greener than class in this case, though going by some of the 
posts on the main discussion
list, you get the feeling that structs are frowned these days upon by some of 
the language pundits.

Thank you for taking the time downs,

-- Justin


Getting started - D meta-program question

2009-10-03 Thread Justin Johansson
There was mention** on the general discussion group that the D foreach_reverse
language construct could be replaced (emulated?) with a (D) meta-program.

** Even a novice programmer can write a meta-program to replace
foreach_reverse without any runtime performance hit.

   
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=97362
  
As I'm less than a novice with the D meta-programming facilities (at this stage 
of my journey into D),
if someone would kindly show me the D meta-program solution to do this,
I'd really appreciate the enlightenment.

Thanks again.




Re: Getting started - D meta-program question

2009-10-03 Thread Daniel Keep

Justin Johansson wrote:
 There was mention** on the general discussion group that the D foreach_reverse
 language construct could be replaced (emulated?) with a (D) meta-program.
 
 ** Even a novice programmer can write a meta-program to replace
 foreach_reverse without any runtime performance hit.
 

 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=97362
   
 As I'm less than a novice with the D meta-programming facilities (at this 
 stage of my journey into D),
 if someone would kindly show me the D meta-program solution to do this,
 I'd really appreciate the enlightenment.
 
 Thanks again.

Short answer: you can't.

Long answer: you can, provided you aren't trying to reverse an opApply,
which is patently impossible.

As for the meta-program, I would suspect whoever said that was talking
about writing a templated type or function to handle it.  You would need
to use template specialisation or static ifs to switch on what type
you've been given to reverse.

http://digitalmars.com/d/1.0/template.html

http://digitalmars.com/d/1.0/version.html#staticif