Fibonacci with ranges

Jonathan M Davis jmdavisProg at gmx.com
Sat Mar 12 01:56:14 PST 2011


On Saturday 12 March 2011 01:33:34 Russel Winder wrote:
> On Fri, 2011-03-11 at 18:46 -0500, Jesse Phillips wrote:
> > Without testing: foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0UL,
> > 1UL), 50))
> > 
> > teo Wrote:
> > > Just curious: How can I get ulong here?
> > > 
> > > foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0, 1), 50))
> > > {
> > > 
> > > 	writeln(f);
> > > 
> > > }
> 
> Interestingly, or not, the code:
> 
> long declarative ( immutable long n ) {
>   return take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , n ) ;
> }
> 
> results in the return statement delivering:
> 
> rdmd --main -unittest fibonacci_d2.d
> fibonacci_d2.d(15): Error: template std.range.take(R) if
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) &&
> !is(Unqual!(R) T == Take!(T))) does not match any function template
> declaration fibonacci_d2.d(15): Error: template std.range.take(R) if
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) &&
> !is(Unqual!(R) T == Take!(T))) cannot deduce template function from
> argument types !()(Recurrence!(fun,long,2u),immutable(long))
> 
> which seems deeply impenetrable for mere mortals.

LOL. Maybe I've been dealing with template code for too long, because that seems 
perfectly clear to me. Though I can certainly understand why it wouldn't be. 
Incidentally, isSafelySlicable will be going away (essentially it's checking 
that the range isn't some type of char[] or wchar[], and Andrei's just going to 
make it so that isSliceable is false for them).

All that template constraint is checking for is that the range is an input range 
which can't be sliced and isn't already a range returned from take. If a range 
_is_ sliceable, then take just returns the same range type.

However, I don't think that constraint is necessarily all that useful in this 
case. It's just that it's the first version of the template, so that's the way 
that gets displayed when the compiler can't instantiate any of the versions of 
the template with the given arguments.

What's happening is that the parameter that you're passing n to for recurrence 
is size_t. And on 32-bit systems, size_t is uint, so passing n - which is long - 
to recurrence would be a narrowing conversion, which requires a cast. The 
correct thing to do would be make n a size_t. The other thing that you'd need to 
do is change declarative to return auto, since take returns a range, _not_ a 
long.

In any case, it _would_ be nice if the compiler gave a more informative message 
about _why_ the template failed to instantiate - especially since it's _not_ the 
template constraint which is the problem - but unfortunately, the compiler just 
isn't that smart about template instantiation errors.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list