www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how does isInputRange(T) actually work?

reply "kevin" <sudo pt-get.com> writes:
enum bool isInputRange = is(typeof(
     (inout int = 0)
     {
         R r = R.init;     // can define a range object
         if (r.empty) {}   // can test for empty
         r.popFront();     // can invoke popFront()
         auto h = r.front; // can get the front of the range
     }));


... is the current implementation in Phobos. But I can't seem to 
understand this syntax. What is (inout int = 0)? Why can a block 
follow it?

My guess is that this is declaring some sort of function and 
testing if it is syntactically valid, but this is still strange 
to me.
Apr 21 2015
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
     (inout int = 0)
     {
         R r = R.init;     // can define a range object
         if (r.empty) {}   // can test for empty
         r.popFront();     // can invoke popFront()
         auto h = r.front; // can get the front of the range
     }));


 ... is the current implementation in Phobos. But I can't seem 
 to understand this syntax. What is (inout int = 0)? Why can a 
 block follow it?

 My guess is that this is declaring some sort of function and 
 testing if it is syntactically valid, but this is still strange 
 to me.
It's defining a lambda function and checking that it is *semantically* valid. No idea what the `(inout int = 0)` is there for, I would have thought it would be fine without it.
Apr 21 2015
next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Tuesday, 21 April 2015 at 19:11:43 UTC, John Colvin wrote:
 On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
    (inout int = 0)
    {
        R r = R.init;     // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range
    }));


 ... is the current implementation in Phobos. But I can't seem 
 to understand this syntax. What is (inout int = 0)? Why can a 
 block follow it?

 My guess is that this is declaring some sort of function and 
 testing if it is syntactically valid, but this is still 
 strange to me.
It's defining a lambda function and checking that it is *semantically* valid. No idea what the `(inout int = 0)` is there for, I would have thought it would be fine without it.
`inout int = 0` is just `inout int n = 0` without the variable name, which is just `inout int n` with a default argument of 0.
Apr 21 2015
parent reply "kevin" <sudo pt-get.com> writes:
On Tuesday, 21 April 2015 at 19:13:34 UTC, Meta wrote:
 On Tuesday, 21 April 2015 at 19:11:43 UTC, John Colvin wrote:
 On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
   (inout int = 0)
   {
       R r = R.init;     // can define a range object
       if (r.empty) {}   // can test for empty
       r.popFront();     // can invoke popFront()
       auto h = r.front; // can get the front of the range
   }));


 ... is the current implementation in Phobos. But I can't seem 
 to understand this syntax. What is (inout int = 0)? Why can a 
 block follow it?

 My guess is that this is declaring some sort of function and 
 testing if it is syntactically valid, but this is still 
 strange to me.
It's defining a lambda function and checking that it is *semantically* valid. No idea what the `(inout int = 0)` is there for, I would have thought it would be fine without it.
`inout int = 0` is just `inout int n = 0` without the variable name, which is just `inout int n` with a default argument of 0.
Thanks for your responses. Don't lambdas need a => token? Also, what is the purpose of typeof? I would have expected a simple is() to work just fine.
Apr 21 2015
parent reply "anonymous" <anonymous example.com> writes:
On Tuesday, 21 April 2015 at 19:17:56 UTC, kevin wrote:
 On Tuesday, 21 April 2015 at 19:13:34 UTC, Meta wrote:
 On Tuesday, 21 April 2015 at 19:11:43 UTC, John Colvin wrote:
 On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
  (inout int = 0)
  {
      R r = R.init;     // can define a range object
      if (r.empty) {}   // can test for empty
      r.popFront();     // can invoke popFront()
      auto h = r.front; // can get the front of the range
  }));
[...]
 Don't lambdas need a => token?
No, D has two variants of function/delegate literal or lambda syntax: 1) with "=>": parameters => expression Some examples: (int a) => a + 2 a => a + 2 (a, b) => a + b () => 2 2) with braces: (parameters) {statements} Same examples as above: (int a) {return a + 2;} (a) {return a + 2;} (a, b) {return a + b;} {return 2;} As you can see, a lot is optional there. In the spec: http://dlang.org/expression.html#FunctionLiteral
 Also, what is the purpose of typeof? I would have expected a 
 simple is() to work just fine.
(In this most simple form,) `is` evaluates to true if the argument is a valid type. A function/delegate literal isn't a type. If you passed the lambda expression itself to `is`, the result would always be false. As it is, the result is true when the lambda expression compiles (so it has a valid type). More about the IsExpression: http://dlang.org/expression.html#IsExpression
Apr 21 2015
parent reply "kevin" <sudo pt-get.com> writes:
On Tuesday, 21 April 2015 at 19:42:42 UTC, anonymous wrote:
 On Tuesday, 21 April 2015 at 19:17:56 UTC, kevin wrote:
 On Tuesday, 21 April 2015 at 19:13:34 UTC, Meta wrote:
 On Tuesday, 21 April 2015 at 19:11:43 UTC, John Colvin wrote:
 On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
 (inout int = 0)
 {
     R r = R.init;     // can define a range object
     if (r.empty) {}   // can test for empty
     r.popFront();     // can invoke popFront()
     auto h = r.front; // can get the front of the range
 }));
[...] Also, what is the purpose of typeof? I would have expected a simple is() to work just fine.
(In this most simple form,) `is` evaluates to true if the argument is a valid type. A function/delegate literal isn't a type. If you passed the lambda expression itself to `is`, the result would always be false. As it is, the result is true when the lambda expression compiles (so it has a valid type). More about the IsExpression: http://dlang.org/expression.html#IsExpression
That makes sense. It seems to me that D has very... special but effective syntax. I'm having a hard time remembering all the keywords and expression forms (especially of IsExpression) but it's definitely a vast improvement over C++'s half baked pile of whatever. Thanks for the help, everyone.
Apr 22 2015
parent reply "Meta" <jared771 gmail.com> writes:
 That makes sense. It seems to me that D has very... special but 
 effective syntax. I'm having a hard time remembering all the 
 keywords and expression forms (especially of IsExpression) but 
 it's definitely a vast improvement over C++'s half baked pile 
 of whatever. Thanks for the help, everyone.
The `is` expression is complicated and has a bunch of different usage syntax, but it's like one of those little multitools. Complicated to figure out how to use, but extremely flexible and able to do a lot of cool things.
Apr 22 2015
parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Wednesday, 22 April 2015 at 21:22:43 UTC, Meta wrote:
 That makes sense. It seems to me that D has very... special 
 but effective syntax. I'm having a hard time remembering all 
 the keywords and expression forms (especially of IsExpression) 
 but it's definitely a vast improvement over C++'s half baked 
 pile of whatever. Thanks for the help, everyone.
The `is` expression is complicated and has a bunch of different usage syntax, but it's like one of those little multitools. Complicated to figure out how to use, but extremely flexible and able to do a lot of cool things.
Yeah, the `is` expression is one of my favorite D features. import std.container; template Substitute (T, U) { static if (is (T == F!V, alias F, V)) alias Substitute = F!U; } alias List = SList!int; static assert (is (Substitute!(List, char) == SList!char)); It's the little things.
Apr 22 2015
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/21/15 3:11 PM, John Colvin wrote:
 On Tuesday, 21 April 2015 at 19:06:39 UTC, kevin wrote:
 enum bool isInputRange = is(typeof(
     (inout int = 0)
     {
         R r = R.init;     // can define a range object
         if (r.empty) {}   // can test for empty
         r.popFront();     // can invoke popFront()
         auto h = r.front; // can get the front of the range
     }));


 ... is the current implementation in Phobos. But I can't seem to
 understand this syntax. What is (inout int = 0)? Why can a block
 follow it?

 My guess is that this is declaring some sort of function and testing
 if it is syntactically valid, but this is still strange to me.
It's defining a lambda function and checking that it is *semantically* valid. No idea what the `(inout int = 0)` is there for, I would have thought it would be fine without it.
inout has a rule that you can't declare a type of inout as a local variable unless there is an inout parameter/return. I'm not sure if this rule still exists (it causes weird shit like the above to be required). I know some inout rules that I devised have been relaxed for the benefit of generic function sanity. The inout int = 0 gives the lambda an inout parameter, in case you are doing isInputRange!(inout(int)[]), then you can validly declare a range of type R inside your function. Alternatively, you could have the lambda take an R as a parameter. Or fix the semantics so that inout local variable acts like immutable inside a non-inout function. -Steve
Apr 21 2015
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/21/2015 12:06 PM, kevin wrote:
 enum bool isInputRange = is(typeof(
      (inout int = 0)
      {
          R r = R.init;     // can define a range object
          if (r.empty) {}   // can test for empty
          r.popFront();     // can invoke popFront()
          auto h = r.front; // can get the front of the range
      }));


 ... is the current implementation in Phobos. But I can't seem to
 understand this syntax. What is (inout int = 0)? Why can a block follow it?

 My guess is that this is declaring some sort of function and testing if
 it is syntactically valid, but this is still strange to me.
I try to explain that syntax here: http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.named%20template%20constraint Ali
Apr 21 2015