Is there an expiring map in dart ? I'm looking for something similar to PassiveExpiringMap in Apache common.
Thanks in advance.
There doesn't seem to be a package for this. However, in case anyone is just looking for a quick snippet to lazily copy and paste like I did, here's a start you can taylor to your needs:
class ExpiringMap {
final Map<dynamic, dynamic> _map = {};
Object operator [](Object key) => _map[key];
void operator []=(Object key, Object value) {
_map[key] = value;
Future.delayed(Duration(minutes: 1), () => _map.remove(key));
}
}
Related
So i need to run some code that needs to get some data later.
I imagine it like:
voin runWithContext(void Function () fn, dynamic context) {
// ... magic
fn();
}
And later in the call stack of fn()
void otherFn() {
dynamic context = getContext();
}
If functions are not async we could just store the context as global variable, but the main requirement to support dart:async
I was looking into dart:mirrors and stacktrace but i can't find no way to bind some data.
You can do this with Zones.
Zones, and their "zone variables" are the canonical way to create a context that is preserved throughout an asynchronous computation).
Since you want single global function to access the context, it will have to be untyped (or typed at the one type that you need, but not generally reusable). That would me me want to reconsider the design, but if it works for you, I'd do it as:
import "dart:async";
/// Container for a mutable value.
class _Context {
dynamic value;
}
final _Context _rootContext = _Context();
R runWithNewContext<R>(R Function() body) =>
runZoned(body, zoneValues: {
#_context: _Context()..value = context,
});
dynamic get context => (Zone.current[#_context] ?? _rootContext).value;
set context(dynamic value) {
(Zone.current[#_context] ?? _rootContext).value = value;
}
If you don't need the mutability, you can simplify things a little, but not much.
The typed and unmodifable alternative is something like
class _Box { // Distinguishable from `null`, even if value is `null`
final Object? value;
_Box(this.value);
}
class ZoneStorage<T> {
final _Box _initialValue;
ZoneStorage(T initialValue) : _initialValue = _Box(initialValue);
R update<R>(T newValue, R Function() body) =>
runZoned(body, zoneValues: {this: _Box(newValue)});
T get value =>
(Zone.current[this] as _Box? ?? _initialValue).value as T;
}
That allows you to create multiple independent zone stores, like:
var zs1 = ZoneStorage<int>(1);
var zs2 = ZoneStorage<String>("yup");
zs1.update(42, () {
print(zs1.value);
print(zs2.value);
});
zs2.update("yup yup yup", () {
print(zs1.value);
print(zs2.value);
});
So the thing that is need is https://api.dart.dev/stable/2.17.3/dart-async/Zone-class.html
Hope that answer will help someone else
I'm new to dart. I'm trying to covert my Holiday class to Map to be used in my calendar. I tried using Map.fromIterable but it only convert it to <String, dynamic>?
class Occasion {
final List<Holiday> holidays;
Map<DateTime, List> toMap() {
var map = Map.fromIterable(holidays,
key: (e) => DateFormat('y-M-d').format(DateTime.parse(e.date)),
value: (e) => e.name);
print(map);
}
}
class Holiday {
final String date;
final String name;
Holiday({
this.date,
this.name,
});
factory Holiday.fromJson(Map<String, dynamic> parsedJson) {
return Holiday(date: parsedJson['date'], name: parsedJson['name']);
}
}
There are two things:
First: The type parameters of your returned map aren't right for the values you produce in fromIterable. You say it should be List, but in value: ... you are only producing a single String.
Secondly, as I said in my comment you need to help out the dart compiler here a little bit. The compiler isn't very smart. It doesn't see that you are only producing Strings in value. You need to tell him that.
To be fair. This might not be the problem of the compiler, but an overuse of the dynamic type in the collections library.
Map<String, String> toMap() {
var map = Map<String, String>.fromIterable(holidays,
key: (e) => e.date,
value: (e) => e.name );
return map;
}
Just remember: be precise with your types. If you run into type errors start putting additional type information everywhere you can. If you feel it's to cluttered after that, try removing them one spot at a time and see where it leads you.
I am having a heck of a time with list transformations in Dart. Since the bulk of my experience is with Typescript I will provide a working example in TS and then my solution in Dart.
Typescript with type safety from response to creation of Coin object.
type Entry = {
spark: Record<string, Spark>;
};
type Spark = {
t: number;
p: number;
};
const coin = (entry: Entry): Coin => ({
sparkline: Object.values(entry.spark)
.sort((a, b) => a.t - b.t)
.map(spark => spark.p)
});
type Coin = {
sparkline: number[];
};
Dart with fragile types, confusing string transform, and no way to tell the compiler what's inside this map.
Coin.fromEntry(MapEntry<String, Map> e)
: this.sparkline = List<num>.from((List<Map>.from(e.value['spark'].values)
..sort((a, b) => a['t'].compareTo(b['t'])))
.map((spark) => spark['p'].toDouble())
.toList());
Is there a way to do list transformations that are type safe from response to Coin object that are easier to read?
Here is another way to translate the typescript code.
class Entry {
Map<String, Spark> spark;
}
class Spark {
int t;
double p;
}
class Coin {
List<double> sparkline;
Coin.fromEntry(Entry entry)
: sparkline = (entry.spark.values.toList()
..sort((a, b) => a.t.compareTo(b.t)))
.map((spark) => spark.p)
.toList() {}
}
If the Spark is coming into your program as a JSON object/dictionary, I would recommend creating a separate de-serialization method. This way, instead of working with dynamic values all over the place, you are able to leverage the type system when operating on Spark values.
I'm wondering if it's possible to filter logs by properties of passed arguments to a specific function. To be more specific, here's where I'm starting:
_dispatcher.getLogs(callsTo("dispatchEvent", new isInstanceOf<PinEvent>()));
I'd like to further filter this by PinEvent.property = "something"
In pseudo-code, I guess it'd look like this:
_dispatcher.getLogs(callsTo("dispatchEvent", new isInstanceOf<PinEvent>("property":"something")));
Any ideas? I know I can loop through the entire log list, but that seems dirty, and I would think there'd be a better way.
Thanks :-)
You can write your own matcher and use it instead of isInstanceOf
or derive from isInstanceOf and extend this matcher with the missing functionality.
I don't know of a matcher that does this out of the box (but I must admit that I didn't yet work very much with them).
While waiting for responses I whipped this up real quick. It's probably not perfect, but it does allow you to combine an isInstanceOf with this matcher using allOf. ex:
allOf(new isInstanceOf<MyThing>(), new ContainsProperty("property", "propertyValue"));
And here's the Matcher:
class ContainsProperty extends Matcher {
final String _name;
final dynamic _value;
const ContainsProperty(String name, dynamic value):this._name = name, this._value = value;
bool matches(obj, Map matchState) {
try {
InstanceMirror objMirror = reflect(obj);
InstanceMirror propMirror = objMirror.getField(new Symbol(_name));
return propMirror.reflectee == _value;
} catch (e) {
return false;
}
}
Description describe(Description description) {
description.add("contains property \"${_name}\" with value \"${_value}\"");
}
}
I need to "fetch" the methods in a Dart Class.
How can I do this?
And I want to be able to call the methods.
May I see an example?
Here's an easy copy-pasteable code sample:
import 'dart:mirrors';
import 'dart:io';
main() {
var im = reflect(new File('test')); // Retrieve the InstanceMirror of some class instance.
im.type.methods.values.forEach((MethodMirror method) => print(method.simpleName));
}
Output is:
existsSync
_delete
exists
directory
_getDecodedLines
readAsTextSync
readAsBytesSync
readAsLinesSync
_directory
throwIfError
lastModifiedSync
readAsLines
open
_ensureFileService
deleteSync
delete
_exists
length
openInputStream
create
_create
readAsText
_openStdioSync
openOutputStream
_fullPath
_lastModified
fullPathSync
readAsBytes
lastModified
_openStdio
_open
openSync
lengthSync
directorySync
fullPath
createSync
_lengthFromName
Here is a basic example:
(Note: You will want to have a (very) up to date version of the SDK for this, this was done in Dart Editor version 0.2.1_r14167, Dart SDK version 0.2.1.2_r14167 Nov 2, 2012)
My most sincere Thanks to Gilad of the Google Dart Team for providing this example!
#import('dart:mirrors');
class MyClass {
String _test;
String get test => _test;
set test(String paramVal) => _test = paramVal;
void my_method() {
}
void print_test(){
print("test string is: ${_test}");
}
MyClass(String test) {
_test = test;
}
}
main() {
MyClass myClass = new MyClass("Make my day, PUNK.");
myClass.print_test();
//ClassMirror myClassMirror = reflect(myClass).type;
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
Map<String, MethodMirror> map = MyClassMirror.methods;
print("map = ${map}");
map.values.forEach( (MethodMirror mm){
myClassInstanceMirror.invoke(mm.simpleName,[]);
});
}
Concerning Reflection I have just written a couple of "Helper Functions" for fetching a LIST of the method names (not a Map) and invoking the method... all I can say for sure is that it works right now. There are likely technical reasons for not doing it this way - but in my case this does not run in a complex environment. However, I do think they nicely mask over a lot of details that not everybody is going to want to deal with.
Here's a functioning demonstration with and without the Helper functions:
#import('dart:mirrors');
class MyClass {
String _test;
String get test => _test;
set test(String paramVal) => _test = paramVal;
void my_method1(){print("in method1");}
void my_method2(){print("in method2");}
void print_test(){
print("test string is: ${_test}");
}
MyClass(String test) {
_test = test;
}
}
//Helper Methods
InstanceMirror hMr;
List REFLECT_methods(Object myClass) {hMr=reflect(myClass);return(hMr.type.methods.values);}
REFLECT_invoke(MethodMirror mm){hMr.invoke(mm.simpleName, []);}
main() {
MyClass myClass = new MyClass("Make my day, PUNK.");
print("\n=======Using Raw Reflection================");
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
Map<String, MethodMirror> map1 = MyClassMirror.methods;
map1.values.forEach( (MethodMirror mm){
myClassInstanceMirror.invoke(mm.simpleName,[]);
});
print("\n==========Using Helper functions=============");
List list2 = REFLECT_methods(myClass);
list2.forEach((method){
REFLECT_invoke(method);
});
}