Jump to page: 1 2
Thread overview
Re: How do you use templates in D?
Oct 18, 2011
Andrew Pennebaker
Oct 18, 2011
Graham Fawcett
Oct 18, 2011
Andrew Pennebaker
Oct 18, 2011
bearophile
Oct 19, 2011
Martin Nowak
Oct 19, 2011
bearophile
Oct 19, 2011
Marco Leise
Oct 19, 2011
Andrew Pennebaker
Oct 19, 2011
Andrew Pennebaker
Oct 19, 2011
Martin Nowak
Oct 19, 2011
Andrew Pennebaker
Oct 18, 2011
Graham Fawcett
Oct 18, 2011
Andrew Pennebaker
Oct 18, 2011
Andrew Pennebaker
Oct 18, 2011
Andrej Mitrovic
October 18, 2011
ntrel2<http://www.reddit.com/r/d_language/comments/lghzs/how_do_you_use_templates_in_d/>has the answer:

char genChar() {
 return cast(char) uniform(0, 128);
}

T[] genArray(T)(T function() gen) {
 int len = uniform(0, 100);
T[] arr = [];

for(int i = 0; i < len; i++) {
 arr ~= gen();
}

return arr;
}

string genString() {
 return genArray(&genChar).idup;
}

Now I'm curious: How can I pass and accept a collection of lambdas? The lambdas will each have different, arbitrary returns types. And how do I call a function using a collection of values, something like Lisp's (apply f args) ?

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Tue, Oct 18, 2011 at 1:56 PM, Andrew Pennebaker < andrew.pennebaker@gmail.com> wrote:

> I'm writing a function called genArray that accepts a function gen and returns a random array populated by calling gen(). genString builds on this by returning genArray(&genChar). But my type signatures are wrong.
>
> In dashcheck.d:
>
> char genChar() {
>     return cast(char) uniform(0, 128);
> }
>
> T[] genArray(T function() gen) {
>     int len = uniform(0, 100);
>     T[] arr = [];
>
>     for(int i = 0; i < len; i++) {
>         arr ~= gen();
>     }
>
>     return arr;
> }
>
> string genString() {
>     return genArray(&genChar);
> }
>
> Trace:
>
> dashcheck.d(17): Error: undefined identifier T
> dashcheck.d(17): Error: T is used as a type
> dashcheck.d(17): Error: undefined identifier T
> dashcheck.d(17): Error: T is used as a type
>
> Full code at GitHub <https://github.com/mcandre/dashcheck>
>
> Cheers,
>
> Andrew Pennebaker
> www.yellosoft.us
>


October 18, 2011
On Tue, 18 Oct 2011 14:28:59 -0400, Andrew Pennebaker wrote:


> Now I'm curious: How can I pass and accept a collection of lambdas? The lambdas will each have different, arbitrary returns types. And how do I call a function using a collection of values, something like Lisp's (apply f args) ?

Can you give an example of how such a thing would be used? Collection of lambdas, I understand; but what would you expect the return type to be?

Graham
October 18, 2011
You could pass arbitrary functions like so:

auto genArray(T...)(T dgs)
    if (allSatisfy!(isSomeFunction, T))
{
}

and call it:

genArray({ return cast(char) uniform(0, 128); },
              { return cast(int) uniform(0, 128); });

I'm not sure what you would want to do with lambdas with arbitrary return types though. I'll leave someone else to answer Lispy things.
October 18, 2011
I'm writing a D port of
QuickCheck<http://www.yellosoft.us/articles/2011/10/13/port-all-the-quickchecks>,
a unit test framework that works by testing properties. A property is a
function that accepts input values and returns a boolean, e.g. isEven(int
i).

The QuickCheck API's most important function is forAll, which should accept a property and a collection of generators. E.g., isEven takes a single integer, so the generators required are { genInt }. (I don't know the syntax for a collection of differently-typed functions.)

The call would look like:

forAll(isEven, { genInt });

And the output would be something like:

*** Failed!
57

Because 57, a random number returned by genInt(), when passed to isEven(),
results in false.

Writing our own generator, we can test whether all even integers are indeed even.

int genEven() {
   int i = genInt();

   if (i % 2 != 0) {
      i++;
   }

   return i;
}

forAll(isEven, { genEven });

Sample output:

+++ OK, passed 100 tests.

Recap:

forAll() accepts a property of type bool function(void), and a collection of generator functions, of types *arbitrary_type* function(void). forAll calls the generator functions, storing the values in another collection, and passing the values to the property. If the property returns false, the values are printed to the screen.

For a working C version of forAll, see qc <https://github.com/mcandre/qc>. It uses a nasty void* trick, but I'd prefer not to resort to hacks in D if possible.

The D version will be called dashcheck<https://github.com/mcandre/dashcheck> .

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Tue, Oct 18, 2011 at 2:55 PM, Graham Fawcett <fawcett@uwindsor.ca> wrote:

> On Tue, 18 Oct 2011 14:28:59 -0400, Andrew Pennebaker wrote:
>
>
> > Now I'm curious: How can I pass and accept a collection of lambdas? The lambdas will each have different, arbitrary returns types. And how do I call a function using a collection of values, something like Lisp's (apply f args) ?
>
> Can you give an example of how such a thing would be used? Collection of lambdas, I understand; but what would you expect the return type to be?
>
> Graham
>


October 18, 2011
Andrew Pennebaker:

> The D version will be called dashcheck<https://github.com/mcandre/dashcheck>

QuickCheck is one of the good things of Haskell.

I have raised the topic few times: http://www.digitalmars.com/d/archives/digitalmars/D/QuickCheck-like_in_Phobos_131256.html http://www.digitalmars.com/d/archives/digitalmars/D/Re_Unit_Testing_for_D_._72154.html

I remember someone has already written one or two D versions of QuickCheck-like (probably D1), but it didn't get a lot of interest in the D newsgroups. One of them:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=73949

Bye,
bearophile
October 18, 2011
On Tue, 18 Oct 2011 15:06:21 -0400, Andrew Pennebaker wrote:

> Recap:
> 
> forAll() accepts a property of type bool function(void), and a collection of generator functions, of types *arbitrary_type* function(void). forAll calls the generator functions, storing the values in another collection, and passing the values to the property. If the property returns false, the values are printed to the screen.

A variadic forAll seems doable, e.g.

  forAll!isEven(&my_ints, &my_floats, &my_ulongs);

The types are not *entirely* arbitrary, right? Each has a return type Tn, constrained such that "isEven!Tn" must be a valid instance of the isEven template. so "forAll!isEven(&ints, &floats, &bananas)" would be invalid, assuming there's no legal "isEven!Banana" instance.

It would look something like this (here with arrays, instead of lambdas):

import std.stdio;

bool isEven(T)(T v) {
  return v % 2 == 0;
}

bool forAll(alias Pred, T...)(T seqs) {
  bool result = true;
  foreach(sequence; seqs) {
    foreach(elem; sequence)
      result &= Pred(elem);
  }
  return result;
}

void main() {
  writeln(forAll!isEven([22, 22], [23L, 22L]));
  writeln(forAll!isEven([2,4], [6.0,8.0], [10L,12L]));
}

Graham

October 18, 2011
bearophile, Awesome! I'll take a look at the old D ports to see how they did it.

Çehreli, thanks much! Another D user suggested the same fixes at StackOverflow, so my project is making progress.

Fawcett, you've got the right idea :) The difference between your example code and QuickCheck is that your example looks more like assert statements, and QuickCheck's forAll() generates the assertions dynamically, by the hundreds. The API has you specifying only the property to be tested, and the generators for its input types. You're definitely on the right track.

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Tue, Oct 18, 2011 at 3:48 PM, Graham Fawcett <fawcett@uwindsor.ca> wrote:

> On Tue, 18 Oct 2011 15:06:21 -0400, Andrew Pennebaker wrote:
>
> > Recap:
> >
> > forAll() accepts a property of type bool function(void), and a collection of generator functions, of types *arbitrary_type* function(void). forAll calls the generator functions, storing the values in another collection, and passing the values to the property. If the property returns false, the values are printed to the screen.
>
> A variadic forAll seems doable, e.g.
>
>  forAll!isEven(&my_ints, &my_floats, &my_ulongs);
>
> The types are not *entirely* arbitrary, right? Each has a return type Tn, constrained such that "isEven!Tn" must be a valid instance of the isEven template. so "forAll!isEven(&ints, &floats, &bananas)" would be invalid, assuming there's no legal "isEven!Banana" instance.
>
> It would look something like this (here with arrays, instead of lambdas):
>
> import std.stdio;
>
> bool isEven(T)(T v) {
>  return v % 2 == 0;
> }
>
> bool forAll(alias Pred, T...)(T seqs) {
>  bool result = true;
>  foreach(sequence; seqs) {
>    foreach(elem; sequence)
>      result &= Pred(elem);
>  }
>  return result;
> }
>
> void main() {
>  writeln(forAll!isEven([22, 22], [23L, 22L]));
>  writeln(forAll!isEven([2,4], [6.0,8.0], [10L,12L]));
> }
>
> Graham
>
>


October 18, 2011
bearophile: Aw shucks, every single link to the old D ports is broken. Even Fawzi took down his RTest project. I'll message him to ask that he reupload it.

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Tue, Oct 18, 2011 at 4:06 PM, Andrew Pennebaker < andrew.pennebaker@gmail.com> wrote:

> bearophile, Awesome! I'll take a look at the old D ports to see how they did it.
>
> Çehreli, thanks much! Another D user suggested the same fixes at StackOverflow, so my project is making progress.
>
> Fawcett, you've got the right idea :) The difference between your example code and QuickCheck is that your example looks more like assert statements, and QuickCheck's forAll() generates the assertions dynamically, by the hundreds. The API has you specifying only the property to be tested, and the generators for its input types. You're definitely on the right track.
>
> Cheers,
>
> Andrew Pennebaker
> www.yellosoft.us
>
> On Tue, Oct 18, 2011 at 3:48 PM, Graham Fawcett <fawcett@uwindsor.ca>wrote:
>
>> On Tue, 18 Oct 2011 15:06:21 -0400, Andrew Pennebaker wrote:
>>
>> > Recap:
>> >
>> > forAll() accepts a property of type bool function(void), and a collection of generator functions, of types *arbitrary_type* function(void). forAll calls the generator functions, storing the values in another collection, and passing the values to the property. If the property returns false, the values are printed to the screen.
>>
>> A variadic forAll seems doable, e.g.
>>
>>  forAll!isEven(&my_ints, &my_floats, &my_ulongs);
>>
>> The types are not *entirely* arbitrary, right? Each has a return type Tn, constrained such that "isEven!Tn" must be a valid instance of the isEven template. so "forAll!isEven(&ints, &floats, &bananas)" would be invalid, assuming there's no legal "isEven!Banana" instance.
>>
>> It would look something like this (here with arrays, instead of lambdas):
>>
>> import std.stdio;
>>
>> bool isEven(T)(T v) {
>>  return v % 2 == 0;
>> }
>>
>> bool forAll(alias Pred, T...)(T seqs) {
>>  bool result = true;
>>  foreach(sequence; seqs) {
>>    foreach(elem; sequence)
>>      result &= Pred(elem);
>>  }
>>  return result;
>> }
>>
>> void main() {
>>  writeln(forAll!isEven([22, 22], [23L, 22L]));
>>  writeln(forAll!isEven([2,4], [6.0,8.0], [10L,12L]));
>> }
>>
>> Graham
>>
>>
>


October 19, 2011
On Tue, 18 Oct 2011 21:17:56 +0200, bearophile <bearophileHUGS@lycos.com> wrote:

> Andrew Pennebaker:
>
>> The D version will be called dashcheck<https://github.com/mcandre/dashcheck>
>
> QuickCheck is one of the good things of Haskell.
>
> I have raised the topic few times:
> http://www.digitalmars.com/d/archives/digitalmars/D/QuickCheck-like_in_Phobos_131256.html
> http://www.digitalmars.com/d/archives/digitalmars/D/Re_Unit_Testing_for_D_._72154.html
>
> I remember someone has already written one or two D versions of QuickCheck-like (probably D1), but it didn't get a lot of interest in the D newsgroups. One of them:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=73949
>
> Bye,
> bearophile

I wrote a pretty complete port of Haskell's Quickcheck some month ago.
https://github.com/dawgfoto/qcheck
The main function quickcheck takes the testee as first template parameter
and a bunch of policies. It will use getArbitraryTuple to construct the parameters
of the testee. It should be able to construct a random instance of any type out of the box,
but you can also pass generators with the policies and they will be used instead.
There is also a Policy RandomizeMembers which will set aggregate members to random values
after construction.
The testee might return a boolean result or an enum QCheckResult which has a third entry
QCheckResult.Reject.

martin
October 19, 2011
Novak: Very cool. Can qcheck automatically figure out a way to generate the arbitrary data types needed as input for the property/testee? Or did I read that wrong?

Cheers,

Andrew Pennebaker
www.yellosoft.us

On Tue, Oct 18, 2011 at 11:14 PM, Martin Nowak <dawg@dawgfoto.de> wrote:

> On Tue, 18 Oct 2011 21:17:56 +0200, bearophile <bearophileHUGS@lycos.com> wrote:
>
>  Andrew Pennebaker:
>>
>>  The D version will be called dashcheck<https://github.com/**
>>> mcandre/dashcheck <https://github.com/mcandre/dashcheck>>
>>>
>>
>> QuickCheck is one of the good things of Haskell.
>>
>> I have raised the topic few times:
>> http://www.digitalmars.com/d/**archives/digitalmars/D/**
>> QuickCheck-like_in_Phobos_**131256.html<http://www.digitalmars.com/d/archives/digitalmars/D/QuickCheck-like_in_Phobos_131256.html>
>> http://www.digitalmars.com/d/**archives/digitalmars/D/Re_**
>> Unit_Testing_for_D_._72154.**html<http://www.digitalmars.com/d/archives/digitalmars/D/Re_Unit_Testing_for_D_._72154.html>
>>
>> I remember someone has already written one or two D versions of
>> QuickCheck-like (probably D1), but it didn't get a lot of interest in the D
>> newsgroups. One of them:
>> http://www.digitalmars.com/**webnews/newsgroups.php?art_**
>> group=digitalmars.D&article_**id=73949<http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=73949>
>>
>> Bye,
>> bearophile
>>
>
> I wrote a pretty complete port of Haskell's Quickcheck some month ago.
> https://github.com/dawgfoto/**qcheck <https://github.com/dawgfoto/qcheck>
> The main function quickcheck takes the testee as first template parameter
> and a bunch of policies. It will use getArbitraryTuple to construct the
> parameters
> of the testee. It should be able to construct a random instance of any type
> out of the box,
> but you can also pass generators with the policies and they will be used
> instead.
> There is also a Policy RandomizeMembers which will set aggregate members to
> random values
> after construction.
> The testee might return a boolean result or an enum QCheckResult which has
> a third entry
> QCheckResult.Reject.
>
> martin
>


« First   ‹ Prev
1 2