Dart: How to convert variable identifier names to strings only for variables of a certain type - dart

Using Dart here.
As the above title suggests, I have a class (shown below) that has three bool instance variables. What I want to do is create a function that inspects the identifier names of these instance variables and prints each of them out in a string. The .declarations getter that comes with the ClassMirror class ALMOST does this, except it also gives me the name of the Constructor and any other methods I have in the class. This is no good. So really what I want is a way to filter by type (i.e., only give me the boolean identifiers as strings.) Any way to do this?
class BooleanHolder {
bool isMarried = false;
bool isBoard2 = false;
bool isBoard3 = false;
List<bool> boolCollection;
BooleanHolder() {
}
void boolsToStrings() {
ClassMirror cm = reflectClass(BooleanHolder);
Map<Symbol, DeclarationMirror> map = cm.declarations;
for (DeclarationMirror dm in map.values) {
print(MirrorSystem.getName(dm.simpleName));
}
}
}
OUTPUT IS:
isMarried
isBoard2
isBoard3
boolsToStrings
BooleanHolder

Sample code.
import "dart:mirrors";
void main() {
var type = reflectType(Foo);
var found = filter(type, [reflectType(bool), reflectType(int)]);
for(var element in found) {
var name = MirrorSystem.getName(element.simpleName);
print(name);
}
}
List<VariableMirror> filter(TypeMirror owner, List<TypeMirror> types) {
var result = new List<VariableMirror>();
if (owner is ClassMirror) {
for (var declaration in owner.declarations.values) {
if (declaration is VariableMirror) {
var declaredType = declaration.type;
for (var type in types) {
if (declaredType.isSubtypeOf(type)) {
result.add(declaration);
}
}
}
}
}
return result;
}
class Foo {
bool bool1 = true;
bool bool2;
int int1;
int int2;
String string1;
String string2;
}
Output:
bool1
bool2
int1
int2

Related

How to convert a GLib.Value of type GStrv (string[]) to a GLib.Variant

In the following example one class property is of type Gstrv.
With ObjectClass.list_properties() one can query the Paramspec of all properties, and with get_property() all properties can be requested as GLib.Value. How would I access the Value of type GStrv and convert it to a GLib.Variant?
My GLib version is slightly outdated, so I do not have the GLib.Value.to_variant() function available yet :( .
public class Foo: GLib.Object {
public GLib.HashTable<string, int32> bar;
public Foo() {
bar = new GLib.HashTable<string, int32>(str_hash, str_equal);
}
public string[] bar_keys { owned get { return bar.get_keys_as_array(); } }
}
int main() {
var foo = new Foo();
Type type = foo.get_type();
ObjectClass ocl = (ObjectClass) type.class_ref ();
foreach (ParamSpec spec in ocl.list_properties ()) {
print ("%s\n", spec.get_name ());
Value property_value = Value(spec.value_type);
print ("%s\n", property_value.type_name ());
foo.get_property(spec.name, ref property_value);
// next: convert GLib.Value -> GLib.Variant :(
}
foo.bar.set("baz", 42);
return 0;
}
Output:
bar-keys
GStrv
Using GLib.Value.get_boxed() seems to be working.
Example:
// compile simply with: valac valacode.vala
public class Foo: GLib.Object {
public GLib.HashTable<string, int32> bar;
public Foo() {
bar = new GLib.HashTable<string, int32>(str_hash, str_equal);
}
public string[] bar_keys { owned get { return bar.get_keys_as_array(); } }
}
public Variant first_gstrv_property_as_variant(Object obj)
{
Type class_type = obj.get_type();
ObjectClass ocl = (ObjectClass) class_type.class_ref ();
foreach (ParamSpec spec in ocl.list_properties ()) {
print ("%s\n", spec.get_name ());
Value property_value = Value(spec.value_type);
print ("%s\n", property_value.type_name ());
obj.get_property(spec.name, ref property_value);
// next: convert GLib.Value -> GLib.Variant
if(property_value.type_name () == "GStrv") {
return new GLib.Variant.strv((string[])property_value.get_boxed());
}
}
return new GLib.Variant("s", "No property of type GStrv found");
}
int main() {
var foo = new Foo();
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
foo.bar.set("baz", 42);
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
foo.bar.set("zot", 3);
print("%s\n", first_gstrv_property_as_variant(foo).print(true));
return 0;
}
Output:
bar-keys
GStrv
#as []
bar-keys
GStrv
['baz']
bar-keys
GStrv
['baz', 'zot']
In the generated c-code this looks as follows:
_tmp18_ = g_value_get_boxed (&property_value);
_tmp19_ = g_variant_new_strv ((gchar**) _tmp18_, -1);
Passing -1 as length to g_variant_new_strv() means the string array is considered as null terminated. Inside g_variant_new_strv() the g_strv_length() function is used to determine the length.
Hopefully it will be useful to someone else someday. :-)

dart, how to define a class so it can be used as a class attribute?

I've seen in polymer.dart they have:
class CustomTag {
final String tagName;
const CustomTag(this.tagName);
}
but how does that interact with the rest of the code? from just the code above I can't see how using #CustomTag('my-tag') actually does anything but creates a CustomTag which is then garbage collected since nothing is referencing it.
To answer the question in the title; these are called Annotations; they are simply const constructors.
To answer the second question; these are usually used for tooling (eg. #deprecated) or rewriting via a Transformer. You can access them at runtime using mirrors, but that's probably not practical/advisable for a production web app that gets converted to JavaScript.
Here's some sample code taken from this answer
import "dart:mirrors";
void main() {
var object = new Class1();
var classMirror = reflectClass(object.runtimeType);
// Retrieve 'HelloMetadata' for 'object'
HelloMetadata hello = getAnnotation(classMirror, HelloMetadata);
print("'HelloMetadata' for object: $hello");
// Retrieve 'Goodbye' for 'object.method'
var methodMirror = (reflect(object.method) as ClosureMirror).function;
Goodbye goodbye = getAnnotation(methodMirror, Goodbye);
print("'Goodbye' for object: $goodbye");
// Retrieve all 'Goodbye' for 'object.method'
List<Goodbye> goodbyes = getAnnotations(methodMirror, Goodbye);
print("'Goodbye's for object.method': $goodbyes");
// Retrieve all metadata for 'object.method'
List all = getAnnotations(methodMirror);
print("'Metadata for object.method': $all");
}
Object getAnnotation(DeclarationMirror declaration, Type annotation) {
for (var instance in declaration.metadata) {
if (instance.hasReflectee) {
var reflectee = instance.reflectee;
if (reflectee.runtimeType == annotation) {
return reflectee;
}
}
}
return null;
}
List getAnnotations(DeclarationMirror declaration, [Type annotation]) {
var result = [];
for (var instance in declaration.metadata) {
if (instance.hasReflectee) {
var reflectee = instance.reflectee;
if (annotation == null) {
result.add(reflectee);
} else if (reflectee.runtimeType == annotation) {
result.add(reflectee);
}
}
}
return result;
}
#HelloMetadata("Class1")
class Class1 {
#HelloMetadata("method")
#Goodbye("method")
#Goodbye("Class1")
void method() {
}
}
class HelloMetadata {
final String text;
const HelloMetadata(this.text);
String toString() => "Hello '$text'";
}
class Goodbye {
final String text;
const Goodbye(this.text);
String toString() => "Goodbye '$text'";
}
Output:
'HelloMetadata' for object: Hello 'Class1'
'Goodbye' for object: Goodbye 'method'
'Goodbye's for object.method': [Goodbye 'method', Goodbye 'Class1']
'Metadata for object.method': [Hello 'method', Goodbye 'method', Goodbye 'Class1']

How to implement call caching (Memoization)

I want to implement call cache(memoization) in non-intrusive way with the metadata annotations.
Hopefully, it will work like this:
class A{
#Cached
foo(msg) {
return msg;
}
}
void main() {
#Cached
var foo = ()=>"hello";
}
Can it be achieved with only dart:mirrors ?
I wrote a whole blog post on this topic a while ago. It's too long to copy here, so here's the link:
http://dartery.blogspot.com/2012/09/memoizing-functions-in-dart.html
The upshot is that you can write higher-order memoizing functions, but they're limited in generality by Dart's lack of flexible args functions. Also, if you want to use dynamic programming with recursive functions, you need to write your function with memoization in mind - it needs to take itself as an argument, so you can pass in the memoized version.
My current solution allows:
class B {
#CachedCallName(#cachedBaz)
baz() => print("first call to baz");
}
class A extends B with CacheableCalls {
#CachedCallName(#foo)
_foo(msg) {
print("first call with: $msg");
return msg + msg;
}
}
void main() {
A a = new A();
print(a.foo(21));
print(a.foo(21));
a.cachedBaz();
print(a.foo(22));
a.cachedBaz();
}
Output:
first call with: 21
42
42
first call to baz
first call with: 22
44
Flaws:
- can't cache methods with their actual names.
- can extend collection view but can't cache existing operators like operator []
- can't cache functions.
Full source:
#MirrorsUsed(metaTargets: CachedCallName)
import 'dart:mirrors';
class CachedCallName {
final Symbol name;
const CachedCallName(this.name);
}
#proxy
class CacheableCalls {
Map _cache = new Map();
dynamic _chacheInvoke(InstanceMirror thisMirror, Symbol
methodName, Invocation invocation) {
String key = "$methodName${invocation.positionalArguments}"
"${invocation.namedArguments}";
if (_cache.containsKey(key)) {
return _cache[key];
} else {
InstanceMirror resultMirror = thisMirror.invoke(methodName,
invocation.positionalArguments, invocation.namedArguments);
_cache[key] = resultMirror.reflectee;
return resultMirror.reflectee;
}
}
dynamic noSuchMethod(Invocation invocation) {
bool isFound = false;
var result;
Symbol called = invocation.memberName;
InstanceMirror instanceMirror = reflect(this);
ClassMirror classMirror = instanceMirror.type;
classMirror.instanceMembers.forEach((Symbol name, MethodMirror mm) {
mm.metadata.forEach((InstanceMirror im) {
if (im.reflectee is CachedCallName) {
if (im.reflectee.name == called) {
isFound = true;
result = _chacheInvoke(instanceMirror, name, invocation);
}
}
});
});
if (isFound) {
return result;
} else {
throw new NoSuchMethodError(this, called,
invocation.positionalArguments, invocation.namedArguments);
}
}
}
class B {
#CachedCallName(#cachedBaz)
baz() => print("first call to baz");
}
class A extends B with CacheableCalls {
#CachedCallName(#foo)
_foo(msg) {
print("first call with: $msg");
return msg + msg;
}
}
void main() {
A a = new A();
print(a.foo(21));
print(a.foo(21));
a.cachedBaz();
print(a.foo(22));
a.cachedBaz();
}

What can i do with a stored type?

Dart allows variables of types: Type type = SomeType; But for what purpose?
For example, foo bar baz are misapplications:
class A {
Type type = List;
foo() => new type();
type bar() {
return new List();
}
type baz = new List();
}
void main() {
Type type = String;
var str = "Hello Dart";
print(type == str.runtimeType);//true
print(str is String);//true
print(str is type); //type error.
}
I think this one is pretty neat:
void main() {
foo(Type t) {
switch (t){
case int: return 5;
case List: return [1,2,3]; // This one gets me every time :(
case String: return "Hello Dart!";
default: return "default";
}}
print(foo(10.runtimeType)); //5
print(foo([2,4,6].runtimeType)); //default
print(foo("lalala".runtimeType)); //Hello Dart!
print(foo(foo.runtimeType)); //default
}
Is its sole purpose to be the return type for methods like runtimeType and type matching ?
I don't think you can use it for generics. There you need type literals. But you can use it for reflection.
Just one simple example:
import 'dart:mirrors' as mirr;
class A {
String s;
A(this.s);
#override
String toString() => s;
}
void main() {
Type type = A;
var str = "Hello Dart";
mirr.ClassMirror cm = mirr.reflectType(type);
var s = cm.newInstance(new Symbol(''), [str]).reflectee;
print(s);
}
You could also create a Map with registered factories for different types to avoid the need for reflection.
(not tested)
class A {
String s;
int a = 0;
int b = 0;
int c = 0;
A(this.s);
A.extended(this.s, this.a, this.b, this.c);
#override
String toString() => '${super.toString()}: $s, $a, $b, $c';
}
void main(args) {
Type t = A;
registerType(t, (List args) => new A.extended(args[0], args[1], args[2], args[3]));
...
var a = getInstance(t, ['hallo', 1, 2, 3]);
}
Map<Type,Function> _factories = {};
void registerType(Type t, Function factory) {
_factories[t] = factory;
}
void getNewInstance(Type t, List args) {
return _factories[t](args);
}

List of Class Objects operation in Dart

Have an issue in the below chunk of code.
class Events
{
// some member variables
}
class SVList
{
String name;
int contentLen;
List<Events> listEvents;
SVList()
{
this.name = "";
this.contentLen = 0;
this.listEvents = new List<Events>();
}
}
class GList
{
List<SVList> listSVList;
GList(int Num)
{
this.listSVList = new List<SvList>(num);
}
}
function f1 ()
{
//array of class objects
GList gList = new GList(num);
}
Not able to find "listEvents" member after GList constructor is called. Am I missing anything here.
Referencing glist.listSVList[index] --> do not find member variable 'listEvents'. Any pointers appreciated.
To elaborate , no member variable with 'glist.listSVList[index].listEvents' is found.
you have a typo here:
this.listSVList = new List<SvList>(num); // <== SVList not SvList
function seems wrong here
function f1 () { ... }
in this case you use function as a return type
another typo:
GList(int Num) // <== Num (uppercase)
{
this.listSVList = new List<SvList>(num); // <== num (lowercase)
}
this code worked:
class Events {
// some member variables
}
class SVList {
String name;
int contentLen;
List<Events> listEvents;
SVList() {
this.name = "";
this.contentLen = 0;
this.listEvents = new List<Events>();
}
}
class GList {
List<SVList> listSVList;
GList(int num) {
this.listSVList = new List<SVList>(num);
}
}
main() {
//array of class objects
GList gList = new GList(5);
gList.listSVList[0] = new SVList();
gList.listSVList[0].listEvents.add(new Events());
print(gList.listSVList[0].listEvents.length);
}
What editor are you using?
DartEditor showed all errors immediately after I pasted your code.
Lists in Dart can now be stated as
List<Object> array = []

Resources