| Thread overview | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 18, 2011 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Attachments:
| 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrew Pennebaker | 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Graham Fawcett Attachments:
| 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrew Pennebaker | 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrew Pennebaker | 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Graham Fawcett Attachments:
| 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Attachments:
| 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: How do you use templates in D? | ||||
|---|---|---|---|---|
| ||||
Attachments:
| 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
>
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply