January 11, 2008
Tags:
testing
Dojo supports both IE6 and IE7 so when developing it's important to test on both of these browsers. And it's nice to be able to test both browsers on the same machine.
My Windows XP has IE7 installed and to test on IE6 I was, until recently, using the "standalone" packaged version of IE6 from the evolt.org browser archive. However, its behaviour is not always consistent with a regular IE6 install on other computers.
I've just switched to another solution: virtualization with Virtual PC. Microsoft offers Virtual PC as a free download and also offers a free Virtual PC image of Windows XP with IE6 (an image of Windows XP with IE7 is also available from the same download page).
The images have been available for a while (announced on the IEBlog in November 2006) and have been regularly updated.
For testing, I run a web server on my local machine and my browsers can access it with "http://localhost/". But I can't access the web server with "localhost" inside the virtual machine — it'll point to the virtual machine. To access my web server from the virtual machine I've been using the IP address of the host machine (you can get the IP address by running "ipconfig"). So, if my host machine, running the web server, has IP address 1.2.3.4 then I'd use "http://1.2.3.4/" inside the virtual machine.
December 24, 2007
Tags:
java
Continuing with the theme of functions and closures (Registering JavaScript object methods as callbacks, Python bound methods), I thought I'd have a look at the relationship between functions, closures, and objects. I'll build a filter, that returns elements from a collection for which a given predicate is true, in Scheme (a language with first-class functions and closures, but no objects), and in Java (a language with objects, but no first-class functions or closures.)
A function is an object with an "apply" method
In Scheme we can define a filter function that takes two parameters: a function (the predicate), and a list. It will call the predicate function on each element in the list, returning a new list containing all of the elements for which the predicate is true:
(define (filter pred lis)
; if lis is empty
(if (null? lis)
; return an empty list
'()
; otherwise, if the predicate is true on the first element
(if (pred (car lis))
; return the first element concatenated with the
; result of calling filter on the rest of lis
(cons (car lis) (filter pred (cdr lis)))
; otherwise (if the predicate was false) just
; return the result of filtering the rest of lis
(filter pred (cdr lis)))))
We can then define a predicate and use it to filter:
(define (non-negative n)
(>= n 0))
(filter non-negative '(-2 3 7 1)) ; (3 7 1)
(filter non-negative '(100 -9 8)) ; (100 8)
In Java, we don't have first-class functions, but we do have objects. And we can define a Predicate as an object with a public method that takes a single parameter and returns a boolean:
public interface Predicate<T> {
public boolean apply(T arg);
}
We can now write our Java filter function as a method that takes two parameters: a Predicate and a Collection:
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
public class Utils {
public static <T> List<T> filter(Predicate<T> pred, Collection<T> c) {
List<T> filtered = new ArrayList<T>();
// loop through all the elements in c
for (T obj : c) {
// if the predicate is true for the current element
if (pred.apply(obj)) {
// append it to the result list
filtered.add(obj);
}
}
return filtered;
}
}
NonNegative.java:
public class NonNegative implements Predicate<Integer> {
public boolean apply(Integer n) {
return n >= 0;
}
}
With Predicate, Utils.filter, and NonNegative defined we can now filter:
// as our NonNegative class instances have no state,
// we only need one
Predicate<Integer> pred = new NonNegative();
Utils.filter(pred, Arrays.asList(-2, 3, 7, 1));
Utils.filter(pred, Arrays.asList(100, -9, 8));
The Scheme and Java examples above operated on collections of numbers but the filter functions (and Predicate interface in the Java case) are generic -- they can filter collections of any type and filter on any provided predicate logic.
A closure is an object with an "apply" method and some state
Let's say we want to filter all numbers greater than 4. We could define a greater-than-4 function:
(define (greater-than-4 n)
(> n 4))
And if we wanted to filter all numbers greater than 1, we could define a function for that too. The greater-than-1 function is going to be very similar to greater-than-4 and it would be quite convenient to write a generic greater-than function:
(define (greater-than m n)
(> n m))
(greater-than 4 1) ; false
(greater-than 4 20) ; true
Now, if we want to use our greater-than predicate with our filter function, we have a problem: the filter function expects the predicate to be a function that takes exactly one parameter (the element currently being considered), not two.
We can make our greater-than predicate work with our filter function by currying it:
(define (greater-than m)
; return a closure:
; a function that takes one parameter
; with a binding to the value provided for m
(lambda (n)
(> n m)))
We have rewritten greater-than to be a builder of functions (that take one parameter, as we need for filter). Rather than calculating if n is greater than m immediately, we delay the test and package it up into a closure and return that. We provide the parameters m and n in two stages: m is provided when we call greater-than (and stored for later use in the closure) and n is provided whenever the function returned from greater-than is called. For example, if we wanted to calculate 1 > 4 and 20 > 4:
(define greater-than-4 (greater-than 4))
(greater-than-4 1) ; false
(greater-than-4 20) ; true
; or, without naming the function
((greater-than 4) 1) ; false
((greater-than 4) 20) ; true
It is this two-stage quality that enables us to use greater-than with our filter function:
(filter (greater-than 4) '(-2 3 7 1)) ; (7)
(filter (greater-than 10) '(100 -9 8)) ; (100)
We can do something very similar in Java, but rather than a closure we use an object. We can implement GreaterThan as a Predicate in which m is provided to the object constructor and stored in an instance variable. The apply method will retrieve it later to perform its test:
public class GreaterThan implements Predicate<Integer> {
private Integer m;
public GreaterThan(Integer m) {
this.m = m;
}
public boolean apply(Integer n) {
return n > m;
}
}
No changes are necessary to either the Predicate interface or to Utils.filter:
Utils.filter(new GreaterThan(4), Arrays.asList(-2, 3, 7, 1));
Utils.filter(new GreaterThan(10), Arrays.asList(100, -9, 8));