Cannot pass a generic type as an argument

3,179 views
Skip to first unread message

Thiện Mẫn Hoàng

unread,
Nov 20, 2013, 10:07:06 PM11/20/13
to mi...@dartlang.org
Let's say I have a method

dynamic decode(String text, Type type)

I tried to call it this way

var x = decode('[1,2,3]', List<int>) as List<int>;



However, the editor says
  • [warning] There is no such operator '<' in 'Type'
  • [error] Expected to find ')'
Any idea?

Justin Fagnani

unread,
Nov 20, 2013, 10:33:56 PM11/20/13
to General Dart Discussion
There's no literal syntax for types with generics. The best you can currently do is create an instance and get its runtimeType: new List<int>().runtimeType


--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.

dangli...@gmail.com

unread,
Nov 21, 2013, 12:52:18 AM11/21/13
to mi...@dartlang.org
>> There's no literal syntax for types with generics. The best you can currently do is create an instance and get its runtimeType: new List<int>().runtimeType

This is a very bad advice from you.
++++++++++++++++++++++++++
import 'dart:mirrors';

void main() {
  var list1 = new _List<int>();
  var list2 = new _OtherList<int>();
  print("runtime type 'list1' of _List<int>: ${list1.runtimeType}");
  print("runtime type 'list2' of _OtherList<int>: ${list1.runtimeType}");
  if(list1.runtimeType == list2.runtimeType) {
    print("They equal. We never cannot reflect on _List<int> in Dart?");
  }

  // reflect(AbstractClass<Foo>);
  print("How we can reflect on abstract classes?");
}

class _OtherList<T> implements _List<T> { 
}

class _List<T> {
  factory _List() {
    return new _OtherList<T>();
  }
}
++++++++++++++++++++++++++
Results:
runtime type of '_List<int> list1' is _OtherList<int>
runtime type of '_OtherList<int> list2' is _OtherList<int>
They equal. We never cannot reflect on _List<int> in Dart?
How we can reflect on abstract classes?
++++++++++++++++++++++++++

We assume that you are unsuccessful joke.

четверг, 21 ноября 2013 г., 9:33:56 UTC+6 пользователь Justin Fagnani написал:

dangli...@gmail.com

unread,
Nov 21, 2013, 12:55:06 AM11/21/13
to mi...@dartlang.org
Sorry, for typo.
print("runtime type of '_OtherList<int> list2' is ${list1.runtimeType}");
Must be
print("runtime type of '_OtherList<int> list2' is ${list2.runtimeType}");
But result the same.

Justin Fagnani

unread,
Nov 21, 2013, 1:36:46 AM11/21/13
to General Dart Discussion
You know mezoni, you actually have a valid point about this technique not working well with abstract classes with factory constructors. Too bad it's completely obscured by your being childish and disrespectful. I shouldn't even be gracing you with a response, but seriously, if you can't control yourself and act like an adult, please do us a favor and just leave this community.

 -Justin

dangli...@gmail.com

unread,
Nov 21, 2013, 3:02:38 AM11/21/13
to mi...@dartlang.org
>> Too bad it's completely obscured by your being childish and disrespectful.

To be honest, I did not mean to offend or hurt somehow.
I respect you, but I just said that you were given bad advice.
In your opinion, it is forbidden?

On a very simple example, I have demonstrated that you are wrong.
This is bad or forbidden?

I have given you as a person a bad grade in public place?

No. I do not raise the issue of your personal qualities.
I said that your advice are bad  because it is misleading.

What's wrong with this?
If people make mistakes follow your advice you will find that it is good?

In such a situation I'm saying it's impossible, but I'm not trying to sugarcoat reality to hide something.

Personally, I respect you and I respect so far although those are your words.

But I not understand for bad is from my side?

This is not a criticism. This is a fact.

Statement of facts is already banned in favor of something else?

On the one hand you say that I am right, and on the other hand you say that I am childish and disrespectful.

If I know that "about this technique not working well with abstract classes with factory constructors" this not means that other people also know about that.

I can assure you. I didn't know about it until reading your advice.
It is not possible to know about every thing.

I only carried out tests and realized that your advice is not working.

P.S.
And sorry for english language. May be problem in that?

четверг, 21 ноября 2013 г., 12:36:46 UTC+6 пользователь Justin Fagnani написал:

dangli...@gmail.com

unread,
Nov 21, 2013, 3:39:35 AM11/21/13
to mi...@dartlang.org
For "bad advice" I means in Russion "плохой совет".
Дать плохой совет. Термин «плохой», в данном контексте означает неподходящий.
Это не ругательство и даже не оскорбление.
Когда, не подумав, люди дают плохие советы, я так им и говорю "это плохой совет" и они со мной соглашаются, если я аргументировано доказываю им обратное.
О какой обиде может идти речь, если Вы не правы и Вас поправили на благо других людей, которые могу последовать Вашему совету.
Если, конечно, у вас не завышенное самомнение о том, что Вы правы абсолютно во всем, и поправить Вас равноценно нанесению Вам личного оскорбления.
Лично я не считаю это оскорблением, если считаю, что был не прав и, естественно, соглашаюсь с оппонентом, если он прав.
Тем не менее, если я чем-то оскорбил кого-то, я приношу свои извинения.  Чье либо  достоинство, я не имел ни малейшего желания оскорблять.

Единственное чего я не понял, это то, зачем необходимо было оскорблять меня лично, если я, в принципе, не делал того же самого по отношению  к своему оппоненту.
Может быть оппонент, таким образом, хотел получить сатисфакцию?


Günter Zöchbauer

unread,
Nov 21, 2013, 3:40:00 AM11/21/13
to mi...@dartlang.org
Danglingfeet,

I find your contribution to this group very valuable but you often have ways to express yourself that seem offending.
Sometimes I have the impression it's because your limited english skills (I also don't need to brag about mine too though).

"We assume that you are unsuccessful joke."

Sometimes it seems so harsh it's hard to imagine that it's not intentional.
Don't have the post at hand (the last I responded to).

The quoted statement above is IMHO redundant.
It doesn't add anything to solve the problem at hand and it suggests that someone
didn't have the best intentions and that's totally out of place at least in this group.

just my $0.2 

Günter

dangli...@gmail.com

unread,
Nov 21, 2013, 4:07:58 AM11/21/13
to mi...@dartlang.org
@Günter Zöchbauer

First, thanks for explantion.

Second.

"We assume that you are unsuccessful joke."

In Russion this is "Будем считать это неудачной шуткой."
In the sense that it is either bad advice or unsuccessful joke.

Unsuccessful joke is something that said but cannot be considered as said seriously.
I not found something seriously in this advice "you can currently do is create an instance and get its runtimeType: new List<int>().runtimeType".

Even this is the best what you can do this not means that this is serious answer to the question because this is not same and in some situations this can misleading.

"You not right here" are more appropriate here but I as I say "Sorry, for my English language".

This is not the bad thoughts but just the bad translation of my thoughts in English.
When I speak in Russian language I try to be delicate as far as possible, if I'm not irritated.
Here, I never do not get irritated and therefore have no reason to be rude or offend anyone.

I'm sorry, but Justin insulted me, but that's his choice. I do not want to insult him.

Günter Zöchbauer

unread,
Nov 21, 2013, 5:34:32 AM11/21/13
to mi...@dartlang.org
What I learned about how to behave in online communities (I'm all but an expert here)

- people don't know you, they can't see your facial expression if you try to be ironical, they don't hear your voice
- there are many many trolls in forums that just want to make themselves important and make others feel bad
- it's very hard to find places online where it's fun to contribute because of the previous point
- people are very sensitive because when they found a community with great people like this one, they are eager to keep it that way
- there are people with many many different skills and skill levels, some are rookies some are experts, some are rookies in one group and experts in another. There's no need to make any assumptions or accusations about a person if someone is wrong.
- there may be communities where the above points might not apply, where it's welcome to be cynical or ironical.
- If you'r not absolutely sure what the accepted behaviour is, be as polite as possible and keep with factual arguments.
- When you have given valuable contributions for a while and people know you better it's much less sensitive.
- Save jokes for later when people know you better. It requires very good language skills (writer and reader) to get jokes right. If you don't have them be especially careful.

You can find a lot about this in the web. That's just to get you started ;-)

You seem smart and skilled and I assume that this is very much appreciated by everyone here.

Cheers
Günter

Jos Hirth

unread,
Nov 21, 2013, 6:19:41 AM11/21/13
to mi...@dartlang.org
How many "targets" do you intend to support?

Anyhow, there is a problem with that function's signature. It doesn't tell me how to use that function since there are so many types and I don't know which ones are actually supported.

Secondly, the return value is dynamic, which means I won't get the tooling/checks.

So, if you only intend to support, say, int and double lists, I'd just provide 2 functions for these 2 cases.

Or you could pass a destination list as second parameter instead of a type.

var x = decodeInto('[1,2,3]', new List<int>()) as List<int>;

Something like that, perhaps.

Peter Ahé

unread,
Nov 21, 2013, 6:50:36 AM11/21/13
to General Dart Discussion
import 'dart:mirrors';

class TypeArgument<T> {
Type get type => T;
}

decode(String text, Type type) {
return reflectType(type).newInstance(const Symbol(''), []).reflectee;
}

main() {
var result = decode("..", new TypeArgument<List<int>>().type) as List<int>;
result as List<String>; // This line must throw if we created the
right type (and it does).

Peter Ahé

unread,
Nov 21, 2013, 6:55:31 AM11/21/13
to General Dart Discussion
Or:

import 'dart:mirrors';

Type type(List l) => reflect(l).type.typeArguments.single.reflectedType;

decode(String text, Type type) {
return reflectType(type).newInstance(const Symbol(''), []).reflectee;
}

main() {
var result = decode("..", type(<List<int>>[])) as List<int>;

Jos Hirth

unread,
Nov 21, 2013, 9:23:50 AM11/21/13
to mi...@dartlang.org
Heh. Cool that that works.

However, is there any point in doing that? The effect is the same as just passing a list, the function is more difficult to use, and it also uses reflection, which adds a small performance hit and which also increases the size of the generated JS file.

I mean, it's really neat that you can actually do this kind of thing, but does it make any sense in this case?

Alex Tatumizer

unread,
Nov 21, 2013, 9:52:09 AM11/21/13
to mi...@dartlang.org
@mezoni: there's a sure way to criticize someone's idea or solution without offending  the opponent.
Suppose person P suggests solution S which you have issues with.
Forget about person P.  Better assume that S submitted itself all by itself.
Argue with S, not with P.
E.g., you could say: "One problem with the above solution is that in the following scenario ... its doesn't work as expected, instead printing this and that, etc."

It's clear and short and to the point.

Based on one of the above posts, your Russian is, in a sense, too good for automatic translation. One wrong word inserted by google translate - and all subtlety is gone, and it sounds as personal attack.
This forum is not a literary contest, you won't get Booker prize for it - you can write terse comments with no emotions whatsoever - it will only be better this way.

My native language is Russian, too, and I am also prone to using literary patterns, and made similar mistakes for a long time, but now I am trying (maybe not always succeed)  to implement simple principles: 
1. criticize idea, not a person,
2. even while criticizing the idea, have respect for it.
3. what can be said in 2 lines, should be said in 2 lines, not 22.

Do you agree?




Peter Ahé

unread,
Nov 21, 2013, 10:10:42 AM11/21/13
to General Dart Discussion
On Thu, Nov 21, 2013 at 3:23 PM, Jos Hirth <google...@kaioa.com> wrote:
> Heh. Cool that that works.
>
> However, is there any point in doing that?

I certainly wouldn't accept it in a code review. I only did it to
preempt complaints that "new TypeArgument<List<int>>().type" is too
many characters to type ;-)

Cheers,
Peter

Jos Hirth

unread,
Nov 21, 2013, 10:38:18 AM11/21/13
to mi...@dartlang.org
Thanks for the confirmation, Peter. I was afraid I was overlooking something. ;)

dangli...@gmail.com

unread,
Nov 21, 2013, 10:58:28 AM11/21/13
to mi...@dartlang.org
>> Do you agree?

What you're saying I know, and this have a common sense.
And if you want that I said my opinion then my answer is "I agree with you".

I doing so in most cases. What you said is called prioritizing problems.
Arrives question (problem) "What is more problematic (what must be more prioritized) in this problem?".
Question, answers, the applicability of solutions, possible problems, the intention of the opponents and so on.

Your prioritization of the most simple, but it does not allow you to build the discussion because it offers ignore opponents.
The given by you relationship of discussion can be called "one-to-many".
But I also like "many-to-many" and, of course, "one-to-one".

In the real life I have a good sense of humor and I am also a humorist. But on the English language, it looks like rude man.
I apologize to man which have name Justin Fagnani.

четверг, 21 ноября 2013 г., 20:52:09 UTC+6 пользователь Alex Tatumizer написал:

Thiện Mẫn Hoàng

unread,
Nov 21, 2013, 10:07:12 PM11/21/13
to
I'm not satisfied with the current JSON in dart:convert or json_object library. So, what I'm actually doing is to create a mirror based JSON library, which has two methods

/**
 * Decodes the JSON string [text].
 *
 * [instance] is used to retrieve the type of the decoded object. An instance
 * is required rather than a [Type] since passing a generic type as an argument
 * is not allowed.
 *
 * Example:
 *
 * class Person {
 *   String name;
 *   String email;
 * }
 *
 * Person p = decode('{ "name": "kin", "email": "a@b.c" }', new Person());
 * print(p.name);
 *
 * List<int> list = decode('[1,2,3]', <int>[]);
 */

decode
(String text, [instance]);


/**
 * Encodes [object] as a JSON string.
 *
 * Example:
 *
 * class Person {
 *   Person(this.name, this.email);
 *   String name;
 *   String email;
 * }
 *
 * var p = new Person('kin', 'a@b.c');
 * print(encode(p));
 */

String encode(object);


I have successfully implemented these two methods. Below is a test case.

import 'jsonx.dart';


class Person {
 
String name;
 
String email;
 
List<int> cards;
}


main
() {
 
var p = new Person()
     
..email = '1@2.3'
     
..name = 'kin'
     
..cards = [1, 2, 3, 4];


 
var s = encode(p);
 
print(s); // print {"name":"kin","email":"1@2.3","cards":[1,2,3,4]}


 
Person pp = decode(s, p);
 
print(pp.name); // print kin. Auto completion works.


 
var ss = encode(pp);
 
print(ss); // print {"name":"kin","email":"1@2.3","cards":[1,2,3,4]}


 
List<String> list = decode('["green", "yellow", "orange"]', <String>[]);
 
print(list[1]); // print yellow
}


I must use an instance to get the type since runtimeType doesn't work for generics. Not sure if this is a bug.

  var t = <Person>[].runtimeType;
 
print(t); // print List<Person>

 
var cm = reflectClass(t);
 
print(cm.typeArguments); // expect [Person] but print []!

Thiện Mẫn Hoàng

unread,
Nov 21, 2013, 10:35:43 PM11/21/13
to
I just found out that reflectType() should be used instead of reflectClass() to get type arguments of generics. It just works!

The new method declarations are

/**
 * Decodes the JSON string [text] given the optional type [type].
 *
 * Since Dart doesn't allow passing a generic type as an argument, one must
 * create an instance of that generic type and pass the instance's 'runtimeType'
 * as the value of [type].
 *
 * If [type] is omitted, this method is equivalent to JSON.decode() in dart:convert
 * library.
 *
 * Example:
 *
 * class Person {
 *   String name;
 *   String email;
 * }
 *
 * Person p = decode('{ "name": "Man", "email": "a@b.c" }', Person);
 * print(p.name);
 *
 * List<int> list = decode('[1,2,3]', <int>[].runtimeType);
 */

decode(String text, [Type type]);



/**
 * Encodes [object] as a JSON string.
 *
 * Example:
 *
 * class Person {
 *   Person(this.name, this.email);
 *   String name;
 *   String email;
 * }
 *
 * var p = new Person('kin', 'a@b.c');
 * print(encode(p));
 */

String encode(object);

Thiện Mẫn Hoàng

unread,
Nov 22, 2013, 11:22:29 AM11/22/13
to mi...@dartlang.org
I just published the library at http://pub.dartlang.org/packages/jsonx.

dangli...@gmail.com

unread,
Nov 22, 2013, 12:14:08 PM11/22/13
to mi...@dartlang.org
I understand why this not possible (currently) in Dart to use this.

Look at example.

class Foo<T, E> {}

var type = Foo;

For type expression "Foo" compiler generates generic type "Foo<dynamic, dymanic>". This is default behavior of compiler.

Next look at this example.

var type = Foo<String, int>;
Or even
var type = typeof(Foo<String, int>);

Why compiler cannot evaluate this type expression with given type arguments?
The answer is obvious.
But as a small add-on I'll explain how it works in MS NET Framework.

In C# "Foo<String, int>" means that we need 'Foo' type with two arguments "String" and "int".
Is this problematic for C# compiler? No.
Not problematic because in C# types that generated by compiler have the same implementation as the runtime types.
This is because reflection in C# built in virtual machine and the same types available at compile time and at runtime.

C# compiler generates for you reflection type "Foo<String, int>" even this type never be instantiated.
In this case you can reflect information about this "surrogate" type.
This type just an instance of "Foo<T, E>" with given arguments.

Now go back to Dart.

Dart compiler knows nothing about reflection and in this case he was not able to create instance of "Foo<T, E>" with given arguments because it never know about "dart:mirrors".

Also I don't know the how in "dart:mirrors" create "custom" type reflection with specified type arguments.

var type = reflection.reflectCustomType(Foo, [String, int]);

I hope it's at least will help in the understanding of this issue.

And aslo I assume that this is bad advice "create an instance and get its runtimeType: new List<int>().runtimeType".
I not reccomend it use for this issue.

This missing feature can considered as the best solution.
var type = reflection.reflectCustomType(Foo, [String, int]);

Maybe the developers will realize that even it is an imperfect way, but it is at least a solution.

And I would advise such masters as "fagnani" not throw out their emotions in the form of an insult without understanding the situation.
At least being a well-mannered man (which I have no doubt) you could ask explained to me in front of you.
But it seems I'm not alone here who can to be rude.

Peter Ahé

unread,
Nov 27, 2013, 3:02:26 PM11/27/13
to General Dart Discussion
The reason why the Dart language doesn't support type literals like
Foo<String, int> is because they're slightly annoying to parse, and
because we didn't have a need for them until we added reflectType to
dart:mirrors.

It has absolutely nothing to do with not having access to reflection.
There is no difference in what kind of data the compiler needs to
store to a type literal like "Foo<String, int>" compared to what it
must store to support something like "new TypeArgument<Foo<String,
int>>()". This is demonstrated by my TypeArgument above.

I assume that we'll add type literals with type arguments in a future
version of Dart.

Cheers,
Peter

dangli...@gmail.com

unread,
Nov 28, 2013, 1:11:59 AM11/28/13
to mi...@dartlang.org
@Peter von der Ahé
Not want to argue with you. Oh, my bad knowledge of English.

Just sample code.

1. Scenario when the type has no arguments. "List" is type literal.

a. Compilation
// var type = core_patch.runtimeTypes[const Symbol("dart.core.List")]
var type = List;

b. VM runtime
// core_patch.runtimeTypes[const const Symbol("dart.core.List")] = core_patch.runtimeTypes[const const Symbol("dart.core.List")]
new List().runtimeType == List // must be true

2. Scenario when type has arguments. "List<String, int>" is type literal.

a. Compilation
// var type = core_patch.runtimeTypes[const Symbol("dart.core.List<dart.core.String, dart.core.int>")]
var type = typeof(List<String, int>);

b. VM runtime
// var type = runtimeTypes[const const Symbol("dart.core.List<dart.core.String, dart.core.int>")]
var type = typeof(List<String, int>);
// runtimeTypes[const Symbol("dart.core.List<dart.core.String, dart.core.int>")] = runtimeTypes[const Symbol("dart.core.List<dart.core.String, dart.core.int>")]
new List<String, int>().runtimeType == typeof(List<String, int>) // must be true

P.S.

The "reflectType" can reflect only types without arguments because it just a method invocation and thus it cannot take as the parameter type with an arguments because this code cannot be compiled.

reflectType(Foo<String, int>); // Won't compile

The "typeof" operator is a language construction and it intended to work with type literals.

typeof: 'typeof' '(' typeLiteral ')'

No parsing problem (annoying) to parse "typeof" operator.

Waht is "new TypeArgument<Foo<String, int>>()" I not understand.

Peter Ahé

unread,
Nov 28, 2013, 1:17:12 PM11/28/13
to General Dart Discussion
In my previous examples I included this class:

class TypeArgument<T> {
Type get type => T;
}

This class can be used to implement the typeof language feature you suggest:

var type = typeof(List<String, int>);
// Equivalent to: type = new TypeArgument<List<String, int>>().type;

This illustrates that both dart2js and the VM already implement most
of the features needed to support type literals with arguments, except
for the syntax.

Cheers,
Peter

dangli...@gmail.com

unread,
Nov 28, 2013, 1:55:59 PM11/28/13
to mi...@dartlang.org
>> type = new TypeArgument<List<String, int>>().type;

Is this possible?

class Type implements TypeOf {
}

class TypeOf<T> {
  factory TypeOf() {
    return T;
  }
}


var type = new TypeOf<List<int>>(); // returns "List<int>" type

Peter Ahé

unread,
Nov 29, 2013, 5:17:55 AM11/29/13
to General Dart Discussion
I thought of that as well. But it doesn't work in checked mode because
we require that a factory returns a *subtype* of the class' type. In
other words, we require that Type is a subtype of TypeOf, but it
isn't.

Cheers,
Peter

john smith

unread,
Nov 29, 2013, 5:28:27 AM11/29/13
to mi...@dartlang.org
>> In other words, we require that Type is a subtype of TypeOf, but it isn't.

But I propose make this modification in core.

class Type implements TypeOf {
}

Also adding this in core.


class TypeOf<T> {
  factory TypeOf() {
    return T;
  }
}

No breaking change, no language enhancements.
Just improve class "Type" and it will be works fine.


var type = new TypeOf<List<int>>();

Also class "TypeOf" has no members and so no problems can be found here for the implementing this in  "Type".

Peter Ahé

unread,
Nov 29, 2013, 5:38:37 AM11/29/13
to General Dart Discussion
I misread your example, it could work.

But I would prefer to extend the syntax.

I don't like having Type implementing TypeOf.

Cheers,
Peter

john smith

unread,
Nov 29, 2013, 5:57:18 AM11/29/13
to mi...@dartlang.org
>> But I would prefer to extend the syntax.

I am too but this is a long (but correct) process.

Paul Brauner

unread,
Dec 22, 2014, 1:54:42 PM12/22/14
to mi...@dartlang.org
Hello,

is there an bug associated to this issue? I've stumbled upon it too and I'd like to star it.

Paul

On Fri Nov 29 2013 at 11:57:24 AM john smith <shlyp...@gmail.com> wrote:
>> But I would prefer to extend the syntax.

I am too but this is a long (but correct) process.

--
Reply all
Reply to author
Forward
0 new messages