Allowing arbitrary types for a function's argument and return type

John Colvin via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Oct 22 07:36:49 PDT 2015


On Thursday, 22 October 2015 at 13:53:33 UTC, pineapple wrote:
> I'm just starting to hammer D's very pleasant syntax into my 
> head. After "Hello world", the first thing I do when learning 
> any language is to write a simple program which generates and 
> outputs the Collatz sequence for an arbitrary number. (I also 
> like to golf it.) This is what I wrote in D:
>
> import std.stdio;void main(){int i;readf(" 
> %d",&i);while(i>1){writeln(i=i%2?i*3+1:i/2);}}
>
> Any ways I could shorten it further?
>
> Anyway, then I thought I should try something that was less of 
> a mess, too, and wrote this:
>
> import std.concurrency;
> Generator!int sequence(int i){
>     return new Generator!int({
>         yield(i);
>         while(i > 1){
>             yield(i = (i % 2) ? (i * 3 + 1) : (i >> 1));
>         }
>     });
> }
>
> Which can be used like so:
>
> import std.stdio;
> void main(){
>     foreach(i; sequence(11)){
>         writeln(i);
>     }
> }
>
> And now I'd like to make one more improvement, but this I 
> haven't been able to figure out. What if I wanted the argument 
> and output types to be longs instead of ints? Or some other, 
> arbitrary discrete numeric type? Is there any template-like 
> syntax I can use here instead of just copypasting for each 
> numeric type I can think of? I've been spoiled by the likes of 
> Python to be thinking in this duck-typing way.
>
> Thanks!

Using ranges instead of threads or fibers, slightly 
over-engineered to show off features:

import std.traits : isIntegral;

auto collatzStep(T)(T i)
if(isIntegral!T)
{
     return (i % 2) ? (i * 3 + 1) : (i >> 1);
}

auto collatz(T)(T a)
if(isIntegral!T)
{
     import std.range : recurrence;
     import std.algorithm : until, OpenRight;
     return a.recurrence!((a, n) => collatzStep(a[n-1]))
             .until!(n => n == 1)(OpenRight.no);
}

unittest
{
     import std.algorithm : equal;
     import std.range : only;
     assert(collatz(6L).equal(only(6, 3, 10, 5, 16, 8, 4, 2, 1)));
}


More information about the Digitalmars-d-learn mailing list