Understand typeof trick

anonymous via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Dec 25 06:55:04 PST 2015


On 25.12.2015 13:10, Joakim Brännström wrote:
> In http://forum.dlang.org/post/ojawnpggfaxevqpmrdww@forum.dlang.org Adam
> uses findSkip as an example and especially points out the "D idiom with
> is/typeof".
>
> I'm not quite sure I understand it correctly. Please correct me if I
> have misunderstood anything regarding the idiom.
>
> findSkip: http://dlang.org/phobos/std_algorithm_searching.html#.findSkip
> bool findSkip
>    (alias pred = "a == b", R1, R2)
>    (ref R1 haystack, R2 needle)
>      if (isForwardRange!R1 &&
>          isForwardRange!R2 &&
>          is(                        [C]
>             typeof(                 [B]
>                    binaryFun!pred(  [A]
>                                   haystack.front, needle.front))));
>
> [A]
> Nothing special. findSkip's pred is passed on to binaryFun. binaryFun's
> constraints thus apply to findSkip's pred.
> See http://dlang.org/phobos/std_functional.html#.binaryFun

Yup, and then the resulting function is called with arguments 
`haystack.front, needle.front`. The template instantiation, and the 
function call can fail compilation (more precisely: semantic analysis). 
In that case, A is marked as being "broken".

> [B]
> Evaluates to the function type "constructed" by binaryFun.

Almost. It evaluates to the type of the expression. The expression is a 
function call, so typeof evaluates to the return type of the generated 
function.

If A has been marked broken, then B does not become a proper type, and 
it's marked "broken" as well.

> [C]
> The is expression is true if A->B is valid "code".

It's true if the argument, i.e. B, is a proper type. In particular, B 
must not be marked "broken".

If B is "broken", then C is false. Any error messages that would usually 
be printed for the broken A/B are suppressed.

> It is used to convert any compiler errors to "false" (thus the
> constraint wouldn't be fulfilled).

Yes, but be aware that this only works on semantic errors, not on syntax 
errors.

For example, `is(foo())` and `is(typeof(foo(); bar();))` don't give you 
false, but they error out in the syntax checking phase.

That second one leads us to the longest form of the is-typeof idiom: 
`is(typeof({foo(); bar();}))`. Wrapping the code in a delegate so that 
it's an expression, which can be passed to typeof.

> Question:
> I guess that binaryFun is used in the implementation of findSkip.

Yeah, the constraint wouldn't make sense otherwise.

> The reason for using this type of idiom is to avoid "compilation errors"
> to occur in the implementation when pred/R1/R2 is "funky". It "confuses"
> the user.
> The idiom is thus used to move errors to the call site?
> "D idiom: constraint error at call site"?

I think Adam meant just the is(typeof(...)) thing itself, regardless of 
where it appears.

Constraints are used to reject bad instantiations early on, yes. They're 
also used to distinguish different template "overloads".


More information about the Digitalmars-d-learn mailing list