Why is this basic Dart mirror usage not working - dart

I've got the following code in a console application:
import 'dart:mirrors';
void main() {
final foo = Foo();
final mirror = reflect(foo);
final instanceMirror = mirror.invoke(#test, []);
print(instanceMirror);
}
class Foo {
int get test {return 42;}
}
When I run it I get an exception:
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: Class 'int' has no instance method 'call'.
Receiver: 42
Tried calling: call())
If I set a breakpoint on test then it is hit before the exception, so it's definitely invoking the property.
Why is an exception being thrown?
UPDATE: ultimately what I am trying to achieve is to grab the values of all properties in an object. Per #mezoni's answer, it seems I need to treat properties as fields rather than methods (the opposite of C#, incidentally). However, it's still not entirely clear why or how to enumerate all fields. The best I've gotten is this:
import 'dart:mirrors';
void main() {
final foo = Foo();
final mirror = reflect(foo);
for (var k in mirror.type.instanceMembers.keys) {
final i = mirror.type.instanceMembers[k];
if (i.isGetter && i.simpleName != #hashCode && i.simpleName != #runtimeType) {
final instanceMirror = mirror.getField(i.simpleName);
print("${MirrorSystem.getName(i.simpleName)}: ${instanceMirror.reflectee}");
}
}
}
class Foo {
int get someOther {
return 42;
}
int get test {
return someOther + 13;
}
}

Please try this code:
import 'dart:mirrors';
void main() {
final foo = Foo();
final mirror = reflect(foo);
final instanceMirror = mirror.getField(#test);
print(instanceMirror.reflectee);
}
class Foo {
int get test {
return 42;
}
}

Related

How to implement generic class spezialization in Dart

In Dart we can use generic classes [class]. We can also specialize those classes [class]. However at runtime the specialization is not used. (In C++ this is called template programming)
Example: The following code will result in the output
Hallo world
How are you
class MyClass<T> {
foo( print('Hallo world'); );
}
class MyClassInt implements MyClass<int> {
#override
foo( print('How are you'); );
}
main() {
MyClass<int> a = Myclass<int>();
MyClassInt b = MyClassInt();
a.foo();
b.foo();
}
How can the specialization (here type [int]) be done, that it is called at runtime, i.e.
main() {
MyClass<int> a = Myclass<int>();
a.foo();
}
should result in the outcome "How are you".
As mentioned by jamesdlin, Dart does not support specialization. But you can do something like this to make the illusion:
class MyClass<T> {
factory MyClass() {
if (T == int) {
return MyClassInt() as MyClass<T>;
} else {
return MyClass._();
}
}
// Hidden real constructor for MyClass
MyClass._();
void foo() {
print('Hallo world');
}
}
class MyClassInt implements MyClass<int> {
#override
void foo() {
print('How are you');
}
}
void main() {
final a = MyClass<int>();
final b = MyClassInt();
final c = MyClass<String>();
a.foo(); // How are you
b.foo(); // How are you
c.foo(); // Hallo world
}

Why does this use of callable class now work?

I am trying to get callable classes to work in dart, but I have ran into a few issues. First thing I realized is that a normal function
myFunc() {
return 'myFunc';
}
Function.apply(myFunc,null);
is not working as a callable.
Then I realized that if I do
final myFunc = () => 'myFunc';
Function.apply(myFunc,null);
this works.
So now I am trying it out with classes
class Cars {
call(Map<Symbol,dynamic> args) {
return "ride";
}
const Cars();
}
final cars = Cars();
final jobs = {cars.hashCode :cars};
void main() {
int code = cars.hashCode;
print(Function.apply(jobs[code],null));
}
but in DartPad I get the following error
Uncaught exception:
NoSuchMethodError: method not found: 'call'
Receiver: Closure 'call$1' of Instance of 'Cars'
Arguments: []
are there some restrictions on the call method? Or how it works with Function.apply() that I am not finding in the docs?
Thanks.
Your first example works fine for me, but your program needs an entry point:
myFunc() {
return 'myFunc';
}
void main() {
print(Function.apply(myFunc, null));
}
In your class example, your call method requires a Map, but you're passing null. There is no call method with zero arguments, hence the method not found: 'call' error.
One way to fix it is by adding an empty Map to the parameter list in Function.apply:
class Cars {
call(Map<Symbol,dynamic> args) {
return "ride";
}
const Cars();
}
final cars = Cars();
final jobs = {cars.hashCode :cars};
void main() {
int code = cars.hashCode;
print(Function.apply(jobs[code], [Map<Symbol,dynamic>()]));
}
It's worth noting that you can call any method on a class with any number of arguments:
class Car {
go(int speed, int wheels) {
print('$speed mph, $wheels wheels');
}
}
void main() {
var car = Car();
Function.apply(car.go, [50, 4]);
}

Error in Iteration example in A Tour of the Dart Libraries

Problem
How can I implement the example of Iteration in A Tour of the Dart Libraries?
I understood that it is a code that must be supplemented, but how do I supplement it?
A Tour of the Dart Libraries
class Process {
// Represents a process...
}
class ProcessIterator implements Iterator<Process> {
#override
Process get current => ...
#override
bool moveNext() => ...
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
#override
final Iterator<Process> iterator = ProcessIterator();
}
void main() {
// Iterable objects can be used with for-in.
for (var process in Processes()) {
// Do something with the process.
}
}
Development Environment
Dart 2
DartPad
Tried → Error
I read and executed the document on my own, but the following error occurred.
class ProcessIterator implements Iterator<Process> {
#override
Process get current => new Process();
#override
bool moveNext() => false;
}
-> Error: 'IterableBase' expects 0 type arguments.
Best regards,
Two things.
1) Process is not available on the web, so your DartPad example won't work.
2) IterableBase is in dart:collection. Don't forget to import that.
This code seems to work for me:
import 'dart:collection';
class ProcessIterator implements Iterator<int> {
#override
int get current => 0;
#override
bool moveNext() => false;
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<int> {
#override
final Iterator<int> iterator = ProcessIterator();
}
main() {
for (var thing in Processes()) {
print(thing);
}
}
Keep in mind, it's often MUCH easier to use sync* for custom iterators.
Iterable<int> _myProcesses() sync* {
yield 1;
yield 2;
yield 3;
}
main() {
for (var thing in _myProcesses()) {
print(thing);
}
}
Refer to #Kevin 's answer and rewrite the code below.
Code
import 'dart:collection';
class Process {
var foo = 'foo';
}
class ProcessIterator implements Iterator<Process> {
int i = 0;
#override
Process get current => new Process();
#override
bool moveNext() {
if(i++ < 5) {
return true;
} else {
return false;
}
}
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
#override
final Iterator<Process> iterator = ProcessIterator();
}
void main() {
// Iterable objects can be used with for-in.
for (var process in Processes()) {
print(process.foo);
}
}
Console
foo
foo
foo
foo
foo

How to do lazy evaluation in Dart?

Is there a native (language supported) lazy evaluation syntax? Something like lazy val in Scala.
I've gone through the docs, and could not find anything. There is only a chapter about "lazily loading a library", but it's not what I am asking.
Based on this research I incline to believe (please correct me if I'm wrong) that currently there is no such thing. But maybe you know of any plans or feature requests which will provide the functionality? Or maybe it was considered and rejected by the Dart team?
If indeed there is no native support for this, then what is the best practice (best syntax) for implementing lazy evaluation? An example would be appreciated.
Edit:
The benefits of the feature that I am looking for are mostly the same as in implementation in other languages: Scala's lazy val or C#'s Lazy<T> or Hack's __Memorize attribute:
concise syntax
delayed computation until the value is needed
cache the result (the by-need laziness)
don't break pure functional paradigm (explanation below)
A simple example:
class Fibonacci {
final int n;
int _res = null;
int get result {
if (null == _res) {
_res = _compute(this.n);
}
return _res;
}
Fibonacci(this.n);
int _compute(n) {
// ...
}
}
main(List<String> args) async {
print(new Fibonacci(5).result);
print(new Fibonacci(9).result);
}
The getter is very verbose and has a repetitive code. Moreover I can't make the constructor const because the caching variable _res has to be computed on demand. I imagine that if I had a Scala-like lazy feature then I would also have language support for having a constant constructor. That's thanks to the fact, that the lazy evaluated _res is referentially transparent, and would not be in the way.
class Fibonacci {
final int n;
int lazy result => _compute(this.n);
const Fibonacci(this.n); // notice the `const`
int _compute(n) {
// ...
}
}
main(List<String> args) async {
// now these makes more sense:
print(const Fibonacci(5).result);
print(const Fibonacci(9).result);
}
Update 2021
Lazy initialization is now part of dart from the release 2.12.
Simply add late modifier to the variable declaration
late MyClass obj = MyClass();
And this object will be initialized only when it is first used.
From the docs:
Dart 2.12 added the late modifier, which has two use cases:
Declaring a non-nullable variable that’s initialized after its
declaration.
Lazily initializing a variable.
Checkout the example here:
https://dartpad.dev/?id=50f143391193a2d0b8dc74a5b85e79e3&null_safety=true
class A {
String text = "Hello";
A() {
print("Lazily initialized");
}
sayHello() {
print(text);
}
}
class Runner {
late A a = A();
run() async {
await Future.delayed(Duration(seconds: 3));
print("First message");
a.sayHello();
}
}
Here class A will be initialized only after "First message" has been displayed.
update2
From #lrn s comment - using an Expando for caching makes it work with const:
class Lazy<T> {
static final _cache = new Expando();
final Function _func;
const Lazy(this._func);
T call() {
var result = _cache[this];
if (identical(this, result)) return null;
if (result != null) return result;
result = _func();
_cache[this] = (result == null) ? this : result;
return result;
}
}
defaultFunc() {
print("Default Function Called");
return 42;
}
main([args, function = const Lazy(defaultFunc)]) {
print(function());
print(function());
}
Try it in DartPad
update
A reusable Lazy<T> could look like below in Dart but that also doesn't work with const and can't be used in field initializers if the calculation needs to refer instance members (this.xxx).
void main() {
var sc = new SomeClass();
print('new');
print(sc.v);
}
class SomeClass {
var _v = new Lazy<int>(() {
print('x');
return 10;
});
int get v => _v();
}
class Lazy<T> {
final Function _func;
bool _isEvaluated = false;
Lazy(this._func);
T _value;
T call() {
if(!_isEvaluated) {
if(_func != null) {
_value = _func();
}
_isEvaluated = true;
}
return _value;
}
}
Try it in DartPad
original
Dart version of http://matt.might.net/articles/implementing-laziness/ using a closure to lazy evaluate:
void main() {
var x = () {
print ("foo");
return 10;
}();
print("bar");
print(x);
// will print foo, then bar then 10.
print('===');
// But, the following Scala program:
x = () {
print("foo");
return 10;
};
print ("bar");
print (x());
// will print bar, then foo, then 10, since it delays the computation of x until it’s actually needed.
}
Try it in DartPad
Update
int _val;
int get val => _val ??= 9;
Thanks #Nightscape
Old
I think this little snippet might help you...
int _val;
int get val => _val ?? _val = 9;

Creating an instance of a generic type in DART

I was wondering if is possible to create an instance of a generic type in Dart. In other languages like Java you could work around this using reflection, but I'm not sure if this is possible in Dart.
I have this class:
class GenericController <T extends RequestHandler> {
void processRequest() {
T t = new T(); // ERROR
}
}
I tried mezonis approach with the Activator and it works. But it is an expensive approach as it uses mirrors, which requires you to use "mirrorsUsed" if you don't want to have a 2-4MB js file.
This morning I had the idea to use a generic typedef as generator and thus get rid of reflection:
You define a method type like this: (Add params if necessary)
typedef S ItemCreator<S>();
or even better:
typedef ItemCreator<S> = S Function();
Then in the class that needs to create the new instances:
class PagedListData<T>{
...
ItemCreator<T> creator;
PagedListData(ItemCreator<T> this.creator) {
}
void performMagic() {
T item = creator();
...
}
}
Then you can instantiate the PagedList like this:
PagedListData<UserListItem> users
= new PagedListData<UserListItem>(()=> new UserListItem());
You don't lose the advantage of using generic because at declaration time you need to provide the target class anyway, so defining the creator method doesn't hurt.
You can use similar code:
import "dart:mirrors";
void main() {
var controller = new GenericController<Foo>();
controller.processRequest();
}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T();
T t = Activator.createInstance(T);
t.tellAboutHimself();
}
}
class Foo extends RequestHandler {
void tellAboutHimself() {
print("Hello, I am 'Foo'");
}
}
abstract class RequestHandler {
void tellAboutHimself();
}
class Activator {
static createInstance(Type type, [Symbol constructor, List
arguments, Map<Symbol, dynamic> namedArguments]) {
if (type == null) {
throw new ArgumentError("type: $type");
}
if (constructor == null) {
constructor = const Symbol("");
}
if (arguments == null) {
arguments = const [];
}
var typeMirror = reflectType(type);
if (typeMirror is ClassMirror) {
return typeMirror.newInstance(constructor, arguments,
namedArguments).reflectee;
} else {
throw new ArgumentError("Cannot create the instance of the type '$type'.");
}
}
}
I don't know if this is still useful to anyone. But I have found an easy workaround. In the function you want to initialize the type T, pass an extra argument of type T Function(). This function should return an instance of T. Now whenever you want to create object of T, call the function.
class foo<T> {
void foo(T Function() creator) {
final t = creator();
// use t
}
}
P.S. inspired by Patrick's answer
2022 answer
Just came across this problem and found out that although instantiating using T() is still not possible, you can get the constructor of an object easier with SomeClass.new in dart>=2.15.
So what you could do is:
class MyClass<T> {
final T Function() creator;
MyClass(this.creator);
T getGenericInstance() {
return creator();
}
}
and when using it:
final myClass = MyClass<SomeOtherClass>(SomeOtherClass.new)
Nothing different but looks cleaner imo.
Here's my work around for this sad limitation
class RequestHandler {
static final _constructors = {
RequestHandler: () => RequestHandler(),
RequestHandler2: () => RequestHandler2(),
};
static RequestHandler create(Type type) {
return _constructors[type]();
}
}
class RequestHandler2 extends RequestHandler {}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T(); // ERROR
T t = RequestHandler.create(T);
}
}
test() {
final controller = GenericController<RequestHandler2>();
controller.processRequest();
}
Sorry but as far as I know, a type parameter cannot be used to name a constructor in an instance creation expression in Dart.
Working with FLutter
typedef S ItemCreator<S>();
mixin SharedExtension<T> {
T getSPData(ItemCreator<T> creator) async {
return creator();
}
}
Abc a = sharedObj.getSPData(()=> Abc());
P.S. inspired by Patrick
simple like that.
import 'dart:mirrors';
void main(List<String> args) {
final a = A<B>();
final b1 = a.getInstance();
final b2 = a.getInstance();
print('${b1.value}|${b1.text}|${b1.hashCode}');
print('${b2.value}|${b2.text}|${b2.hashCode}');
}
class A<T extends B> {
static int count = 0;
T getInstance() {
return reflectClass(T).newInstance(
Symbol(''),
['Text ${++count}'],
{Symbol('value'): count},
).reflectee;
}
}
class B {
final int value;
final String text;
B(this.text, {required this.value});
}
Inspired by Patrick's answer, this is the factory I ended up with.
class ServiceFactory<T> {
static final Map<Type, dynamic> _cache = <String, dynamic>{};
static T getInstance<T>(T Function() creator) {
String typeName = T.toString();
return _cache.putIfAbsent(typeName, () => creator());
}
}
Then I would use it like this.
final authClient = ServiceFactory.getInstance<AuthenticationClient>(() => AuthenticationClient());
Warning: Erik made a very good point in the comment below that the same type name can exist in multiple packages and that will cause issues. As much as I dislike to force the user to pass in a string key (that way it's the consumer's responsibility to ensuring the uniqueness of the type name), that might be the only way.

Resources