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