July 09, 2017
Following is the code for a more generalized Fibonacci range.

Questions:

1. How do I get only the value of the Nth (i.e. N = 25) element in an idiomatic way?

2. Can I set constraints in the range so that user gets warning if he asks for Nth element greater than a limit, say N> 30; or if the actually range value at N is greater than datatype limit (e.g. max long)? Maybe this should be done outside of the range, i.e. do check before accessing the range?

    #!/usr/bin/env rdmd
    import std.stdio : writeln;
    long multifactor = 4;
    int elemth = 25;

    struct FibonacciRange
    {
      long first = 1;
      long second = 1;

      bool empty() const @property
      {
       // how to stop at n = 30?
        return false;
      }

      void popFront()
      {
        long tmp = 0;
        tmp = first*multifactor + second;
        first = second;
        second = tmp;
      }

      long front() const @property
      {
        return first;
      }
    }

    void main()
    {
        import std.range : take;
        import std.array : array;

        FibonacciRange fib;

        auto fib10 = take(fib, elemth);
        long[] the10Fibs = array(fib10);
    }

July 10, 2017
On 07/09/2017 11:51 PM, biocyberman wrote:
> Following is the code for a more generalized Fibonacci range.
> 
> Questions:
> 
> 1. How do I get only the value of the Nth (i.e. N = 25) element in an idiomatic way?

As you've only got an input range, you have to popFront the 24 values that come before. You can use std.range.drop:

----
import std.range : drop;
auto twentyfifth = fib.drop(24).front;
----

But if you're not sure that the range actually has 25 elements, you should check `empty`, of course:

----
import std.range : popFrontN;
fib.popFrontN(24); /* or fib = fib.drop(24); */
if (!fib.empty)
{
    auto twentyfifth = fib.front;
}
----

> 2. Can I set constraints in the range so that user gets warning if he asks for Nth element greater than a limit, say N> 30;

You can keep track of N in FibonacciRange and when it hits 30 you throw an exception or print a message or just set `empty` to true.

You can't make it a compilation warning/error as far as I can tell.

> or if the actually range value at N is greater than datatype limit (e.g. max long)?

You can use std.experimental.checkedint to detect it at run time:

----
private bool _empty = false;
bool empty() const @property { return _empty; }

void popFront()
{
    import std.experimental.checkedint : checked, Throw;
    long tmp = 0;
    try tmp = (checked!Throw(first)*multifactor + second).get;
    catch (Throw.CheckFailure e) _empty = true;
    first = second;
    second = tmp;
}
----

(There may be a smarter way than making the operation throw an exception and catching that.)