Tuesday, November 27, 2012

No Function.apply, but Wins Still to Be Had

‹prev | My Chain | next›

I prettied up the Dart web server code in my Dart Comics sample app quite a bit recently. As pretty as it is, I have been lamenting the lack of a splat operator or an apply method for functions to make things even prettier. It turns out that there is, in fact, a Function.apply, so let's see if that will help.

The first thing that I notice is that it is a static method, so something like this is probably not going to work:
import 'dart:io';

main() {
  HttpServer app = new HttpServer();

  app.addRequestHandler.apply([Public.matcher, Public.handler]);

  // ...
  app.listen('127.0.0.1', 8000);
}
And indeed that does fail when I try to start up my server:
➜  dart-comics git:(app.dart) ✗ dart app.dart
Unhandled exception:
NoSuchMethodError : method not found: 'apply'
Receiver: Closure: (dynamic, (dynamic, HttpRequest) => bool, (dynamic, HttpRequest, HttpResponse) => void) => dynamic from Function 'addRequestHandler':.
Arguments: [GrowableObjectArray]
#0      Object._noSuchMethod (dart:core-patch:1260:3)
#1      Object.noSuchMethod (dart:core-patch:1263:25)
#2      main (file:///home/chris/repos/dart-comics/app.dart:9:30)
I am unsure if the static version of Function.apply will retain the object context (e.g. this), but there is one way to find out. So I convert that broken apply() to a full Function.apply():
main() {
  HttpServer app = new HttpServer();

  Function.apply(app.addRequestHandler, [Public.matcher, Public.handler]);

  // ...
  app.listen('127.0.0.1', 8000);
}
But, when I try again, I get:
➜  dart-comics git:(app.dart) ✗ dart app.dart
Unhandled exception:
UnimplementedError: Function.apply not implemented
#0      Function.apply (dart:core-patch:721:5)
#1      main (file:///home/chris/repos/dart-comics/app.dart:9:17)
Dang it! It's still just a tease. Oh well, at least it is on the radar.

So I switch to fixing a small bug in my sample app. OK, maybe not that small. It turns out that my scheme to grab the next available ID does not work:
class Comics {
  static Dirty db = new Dirty('dart_comics.db');
  // ...
  static post(req, res) {
    var input = new StringInputStream(req.inputStream);
    // ...
    input.onClosed = () {
      var graphic_novel = JSON.parse(post_data);
      graphic_novel['id'] = db.length + 1;
    };
  }
}
The problem here is that if I delete the first record in the database then db.length + 1 now refers to the last record in the DB, not the next available ID.

The way that I got around this in the node.js version of the application was to make use of node-dirty-uuid. In Dart, I am going to give dart-uuid a try. Since this is Dart and since dart-uuid is available in Dart Pub, trying this out is a simple matter of adding dart-uuid to my application's pubspec dependencies:
name: Dart Comics
dependencies:
  dirty: any
  uuid: any
After a simple pub install, I am ready to go.

And it turns out to be as simple as importing dart-uuid, instantiating a UUID object, and using it:
import 'package:uuid/uuid.dart';
class Comics {
  static Uuid uuid = new Uuid();
  static Dirty db = new Dirty('dart_comics.db');
  // ...
  static post(req, res) {
    var input = new StringInputStream(req.inputStream);
    // ...
    input.onClosed = () {
      var graphic_novel = JSON.parse(post_data);
      graphic_novel['id'] = uuid.v1();
    };
  }
}
With that, my problem is solved.


Day #582

No comments:

Post a Comment