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