While working through my dart-dirty local data store yesterday, I realized that I was making a key-value store in Dart without making use of Dart's key-value class, the HashMap. There are a number of abstract methods in HashMap that need implementing a base classes. Let's see how many I can get done tonight.
First up, I declare my
Dirty
class as implementing HashMap
:#library('dart_dirty'); #import('dart:io'); #import('dart:json'); class Dirty implements HashMap<String, Object> { // ... }I do not necessarily need to restrict myself to
String
keys in a HashMap—anything that is hashable would do—but since I am serializing them as JSON, I do need the string.After declaring that my class implements the abstract
HashMap
, I expect that my tests would fail if run in type-checked mode. Instead, they all continue to pass:➜ dart-dirty git:(master) ✗ dart --checked test/dirty_test.dart unittest-suite-wait-for-done PASS: new DBs creates a new DB PASS: writing can write a record to the DB PASS: reading can read a record from the DB PASS: reading can read a record from the DB stored on the filesystem All 4 tests passed.I suppose this makes sense—or at least I can rationalize this behavior. Type checking is simply ensuring that the types being passed conform to what is declared. If I want a whole lot of complaining about not implementing the abstract class properly, I need to turn to the
dart_analyzer
tool:➜ dart-dirty git:(master) ✗ dart_analyzer lib/dirty.dart file:/home/chris/repos/dart-dirty/lib/dirty.dart:6: Concrete class Dirty has unimplemented member(s) # From Map: Collection<String> keys Collection<Object> values int length bool isEmpty bool containsValue(Object) bool containsKey(String) Object [](String) void []=(String, Object) Object putIfAbsent(String, () -> Object) Object remove(String) void clear() void forEach((String, Object) -> void) 5: 6: class Dirty implements HashMap<String, Object> { ~~~~~Ahhhh, that's the stuff.
The two that I am most keen to define are the setter and getter operator. So far, I have been following the node-dirty convention of making
set()
and get()
methods. That's just wrong in Dart.So I update my test for retrieving records to use the new syntax:
test("can read a record from the DB", () {
var db = new Dirty('test/test.db');
db.set('everything', {'answer': 42});
expect(
db['everything'],
equals({'answer': 42})
);
});
I can make that test pass by replacing the get
method:class Dirty { // ... dynamic get(String key) => _docs[key]; // ... }With the appropriate operator definition:
class Dirty { // ... Object operator[](String key) => _docs[key]; // ... }Similarly, instead of setting values in the DB with a
set()
method:db.set('everything', {'answer': 42});I now want to use the Darty
[]=
operator:db['everything'] = {'answer': 42};To make that happen, I remove the
set()
method:class Dirty { // ... void set(String key, value) { _docs[key] = value; // ... } // ... }And replace it with a
[]=
operator:class Dirty { // ... void operator []=(String key, Object value) { _keys.add(key); // ... } // ... }After updating my tests to use the new syntax, I again have all four tests passing:
➜ dart-dirty git:(master) ✗ dart --checked test/dirty_test.dart unittest-suite-wait-for-done PASS: new DBs creates a new DB PASS: writing can write a record to the DB PASS: reading can read a record from the DB PASS: reading can read a record from the DB stored on the filesystem All 4 tests passed.As for the bulk of the remaining not-implemented abstract methods of
HashMap
, I can define most by delegating to the method of the same name on the internal _docs
variable:class Dirty { // ... int length => _docs.length; bool isEmpty => _docs.isEmpty; Collection<String> keys => _keys; Collection<Object> values => _docs.values; bool containsValue(Object v) => _docs.containsValue(v); bool containsKey(String k) => _docs.containsKey(k); // Object putIfAbsent(String, () -> Object) // Object remove(String) // void clear() void forEach(cb) => _docs.forEach(cb); // ... }Unfortunately, I seem to be running an older version of the Dart SDK because I now get syntax errors when I run my tests:
➜ dart-dirty git:(master) ✗ dart --checked test/dirty_test.dart 'package:dart_dirty/dirty.dart': Error: line 33 pos 14: unexpected token '=>' int length => _docs.length; ^ 'file:///home/chris/repos/dart-dirty/test/dirty_test.dart': Error: line 2 pos 1: library handler failed #import('package:dart_dirty/dirty.dart'); ^If I add empty parentheses to the
length
method definition, then my tests again compile and pass, but this is not correct Dart behavior. In the most recent Dart, the empty parentheses on Dart properties should be omitted.Satisfied with my progress, I call it a night here. I will install the latest SDK and get started on the destructive HashMap methods tomorrow.
Day #574
No comments:
Post a Comment