Archives For December

Closures

December 28, 2007 — 3 Comments

There is alot of debate going on between the CICE and BGGA proposals for Java closure support.

I thought I would try to experiment with the different proposals and compare to languages I am using right now. I picked something simple to try out, like summing an array of integers:

Also check out good closures, bad closures.

Actionscript 3

Assume you have a reduce function, for example:

public function reduce(array:Array, f:Function, index:int = 0):* {
  if (index == array.length - 1) return array[index];
  return f(array[index], reduce(array, f, index + 1));
}

Then the syntax is:

var array:Array = [ 1, 2, 3 ];
reduce(array, function(x1:Number, x2:Number):Number { return x1 + x2; });

Ruby

Sorry I have to.

array = [ 1, 2, 3 ];
array.inject { |sum, n| sum + n }

or with Symbol#to_proc:

array = [ 1, 2, 3 ];
array.inject(&:+)

Java (CICE)

Assume you have a “Reducer” interface (and Collections#reduce):

interface Reducer {
  T reduce(T t1, T t2);
}
List = Arrays.asList([ 1, 2, 3 ]);
Integer sum = Collections.reduce(list, Reducer(Integer x1, Integer x2) {
  return x1 + x2;
});

I think this is right, help? So you might have to declare new interfaces if the API doesn’t have them. It would probably have common ones though.

Java (BGGA)

Assume you have Collections#reduce:

List = Arrays.asList([ 1, 2, 3 ]);
Integer sum = Collections.reduce(list, { Integer x, Integer y => x+y });

The other powerful thing with the BGGA proposal is the control invocations, like:

Lock lock = new Lock();

Lock.withLock(lock) {
  doSomething();
}

// Automatically close stream when done
with(FileInputStream f : exp) {
  doSomething();
}

Like in Ruby:

mutex = Mutex.new
mutex.synchronize do
  doSomething
end

File.open("foo.txt", "w") do |file|
  doSomething
end

Since I’ve been doing Ruby lately, I know which Java proposal I prefer. The CICE doesn’t address the problem that within an anonymous inner instance return, and this and any anonymous instance methods are scoped to that anonymous instance and not the enclosing method.

I guess CICE is more about reducing the verbosity of the anonymous instance declaration and allowing mutability on public variables, and its not a real closure in the strict definition. I know people refer to anonymous inner classes as the poor man’s closure, but I don’t really think of it as a closure, I think of it as, you know, an anonymous inner class.

Flush

December 27, 2007 — 3 Comments

So I decided to try to overcome the Leopard File.upload() bug by rolling my own http client: as3httpclientlib which even supports https with the TLS (Socket) support from as3crypto (which is great). The HTTP protocol is pretty simple and I figured it would be a good way to learn the internals and look smart reading ancient RFC‘s. All you need is a Socket class and nice, flash api has one at flash.net.Socket

I got everything major working like GET, PUT and POST with multipart/form-data and reading chunked encoding and all that stuff. Not too hard since there are open source http libraries for every major language. I looked at ruby Net::HTTP (stole some regex’s) and Apache Httpclient (stole your multipart boundary).

I got to the point where I was testing uploading larger files, like in:

var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://mybucket.s3.amazonaws.com/big.mp3");
var testFile:File = new File("app:/test/assets/big.mp3");
client.upload(uri, testFile);

It turns out that when you call _socket.flush() (in HttpSocket) it doesn’t actually block, which you might expect. After thinking on it, this isn’t totally shocking since the whole threading model behind actionscript, you don’t really ever block (like there is no such thing as a modal dialog in flash). The problem is without blocking or an event to notify of a flush, the socket just gets filled with the request body all at once (all 800MB’s or whatever file size).

It turns out other people ran into this as well. If you look at (FlexFTP) source, the UploadInv.as file, you will see block of code commented out and replaced by a setInterval(.. , 300). Nice. I guess that upload is capped at ~12kb/sec.

Any of the links in the comments off this blog post are useful too.

If you look at FileStream object you will see it has an outputProgressEvent so that would be useful, you know, if Socket had that too.

I don’t know how you get around this issue, other than trying to guess how fast the socket can transmit and try to stay under that. So now I’m not sure what to do, other than abandon it and come back to it when its fixed, which hopefully will be soon. Thankfully, I can go back to ruby and maybe play with some RubyCocoa or Shoes framework.

Update: Feel free to chime in at Adobe Air Forum or Feature Request/Bug Report Form

Protocol

December 2, 2007 — Leave a comment

The similarity of this approach to protocols was clear to users of OOP languages long ago. Smalltalk and ObjectiveC, both dynamic OOP languages, have long used the term Protocol to refer to this concept.

The Protocol concept is certainly useful, if only to give a name to a particular set of messages.

Duck Typing and Protocols vs. Inheritance

It would be nice to know ahead of time what methods a Ruby object accepts. It would be nice to talk about a bunch of classes as all defining read, write and size methods as IO classes. Even if you could use some kind of marker interface (or marker module) that says, “Hey, you probably don’t care but my object might respond to these methods..”, ruby doesn’t itself protect or enforce it anyway.