Skip to content

Conversation

andralex
Copy link
Member

http://d.puremagic.com/issues/show_bug.cgi?id=5359

I recall Kenji introduced the variadics. What was the intent here?

@andralex
Copy link
Member Author

cc @9rnsr

@ghost
Copy link

ghost commented Feb 25, 2013

What was the intent here?

To allow both types and names to be passed to the template. alias doesn't permit types, template type parameter doesn't permit a name, but a tuple permits both.

@andralex
Copy link
Member Author

Yah, but that doesn't explain the bug.

@ghost
Copy link

ghost commented Feb 25, 2013

Yeah it should have only accepted types to begin with.

@ghost
Copy link

ghost commented Feb 25, 2013

I honestly don't know now whether it should be fixed to allow expressions like isSomeFunction does or just allow types only. Most of the other traits allow both and then do magic internally to get a type out of an expression.

@9rnsr
Copy link
Contributor

9rnsr commented Feb 25, 2013

@andralex : A variadics parameter with if (T.length == 1) means that the template can accept any kind of language entities (type, symbol, and value).

Most of std.traits templates (e.g. FunctionTypeOf, fullyQualifiedName) have used it with the intention, so it looks to me that isDelegate implementation has a problem.

I think that most of std.traits templates should work for both type and symbol. In the view of library user, they works as like "generic predicate for language entities", and in library implementation, the behaviors for both kinds can be distinguished.
In the most case of D meta-programming, the responsibility to distinguish symbols and types belongs to the library user (because heterogeneous tuple elements cannot have a kind of meta type to do it, at least in current D). So, a name that has two behaviors for types and symbols will reduce redundancy. e.g. isDelegateType/isDelegateSymbol VS isDelegate.

@andralex
Copy link
Member Author

@9rnsr: got it. I'd change the name of isDelegate to isDelegateType but I think now we must live with it. If we add now isDelegateSymbol or isDelegateObject that's a slippery slope - we'll need to add such traits for /everything/. For example we have isIntegral, so for consistency we'd need to add isIntegralValue. And so on...

So I'd say let's stick with types in traits.

@mihails-strasuns
Copy link

I don't get why you want to stick with types in traits. There is no rational reason to prohibit symbols. Also this implementation works (I used that approach for fullyQualifiedName):

template isDelegate(T...)
    if (T.length == 1)
{
    static if (is(T[0]))
        enum bool isDelegate = is(T[0] == delegate);
    else
        enum bool isDelegate = is(typeof(T[0]) == delegate);
}

@andralex
Copy link
Member Author

I don't get why you want to stick with types in traits.

I said it: to avoid duplication everywhere.

@mihails-strasuns
Copy link

@andralex That is hardly an excuse for standard library. Imagine new comer who meets a limitation in generic code that makes no sense (delegates can be both types and symbols after all, we call all of them "delegates") - he may conclude that either language is not powerful enough to do it, or library implementors are bad, and I believe neither of those has place. Code duplication is an issue to solve, not a reason to avoid allowing meaningful interfaces,

Better to discuss what can be done to avoid code duplication so this can be "done right". Obvious way can be to generate wrapper boilerplate via mixin, but that feels a bit dirty. Another approach that comes to my mind is to allow types as a parameters to typeof so that is(typeof(T) == T).

@andralex
Copy link
Member Author

@Dicebot: wasn't an excuse. There are traits of types and traits of values. Being a delegate is a trait of a type. I think that's the correct design. No need to change anything.

@mihails-strasuns
Copy link

@andralex

int delegate(int) dg; // dg is a delegate to a function

(c) http://dlang.org/type.html#Delegates

If official docs call symbols delegates, it is natural from user to expect from std library to match them.

@andralex
Copy link
Member Author

I understand. But then consider:

int x; // x is an int

This is just colloquial description for the fact that x has type int. If we took that all too literally we'd need to redo isIntegral and isNumeric etc. to work with both x and typeof(x). I find that unnecessary.

@mihails-strasuns
Copy link

@andralex
And I really expected from them to work for both. Well, until noticed this pull request / issue.

I can understand your desire to keep things minimal (and it is your decision to make for sure) but than documentation needs to be tightened and official position stated explicitly somewhere easy to notice. After all, it is an only official documentation about the language and the lib, every single point of ambiguity there should be considered as a bug. This is one of the reasons comparison with C++ standard docs style keeps popping up.

@ghost
Copy link

ghost commented Feb 26, 2013

We should be consistent with the rest of the relevant traits: isSomeFunction, isFunctionPointer, isCallable, isAbstractFunction, isFinalFunction, etc, which all work on types and expressions. In the future we should only allow types, but it would be very annoying to have the single exception of isDelegate not working with expressions.

@andralex
Copy link
Member Author

I am now sorry I allowed those to go through.

@ghost
Copy link

ghost commented Feb 26, 2013

I am now sorry I allowed those to go through.

I agree.

We could separate them into those which take a Type and ones which take an alias, and add a deprecation stage for the alias ones?

@ghost
Copy link

ghost commented Mar 8, 2013

I'm taking over this one.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants