# preserves order, flattens array refs
sub union {
    my @r = ();
    my %elements;
    while (@_) {
        my $e = shift(@_);
        while (ref($e) eq "ARRAY") {
            unshift @_, @{ $e };
            $e = shift(@_);
        }
        next if exists($elements{$e});
        push @r, $e;
        $elements{$e} = 1;
    }
    return @r;
}
