Showing posts with label object. Show all posts
Showing posts with label object. Show all posts

Monday, May 02, 2011

Clojure: Converting a Java Object to a Clojure Map

Clojure has a great library that helps facilitate most things you'd want to do, but it's also easy to roll your own solution if you need something more specific. This blog entry is about converting an object to a map, something Clojure already has a function for: bean. From the docs:
Takes a Java object and returns a read-only implementation of the
map abstraction based upon its JavaBean properties.
The bean function is easy enough to use, as the following example shows (formatted for readability).
user=> (import 'java.util.Calendar)
java.util.Calendar
user=> (-> (Calendar/getInstance) .getTime bean)
{:seconds 16,
:date 2,
:class java.util.Date,
:minutes 35,
:hours 12,
:year 111,
:timezoneOffset 240,
:month 4,
:day 1,
:time 1304354116038}
The bean function is simple and solves 99% of the problems I encounter. Generally I'm destructuring a value that I pull from a map that was just created from an object; bean works perfectly for this.

However, I have run across two cases where I needed something more specialized.

The first case involved processing a large amount of data in a very timely fashion. We found that garbage collection pauses were slowing us down too much, and beaning the objects that were coming in was causing a large portion of the garbage. Since we were only dealing with one type of object we ended up writing something specific that only grabbed the fields we cared about.

The second case involved working with less friendly Java objects that needed to be converted to maps that were going to be used many times throughout the system. In general it isn't a big deal working with ugly Java objects. You can destructure the map into nice var names, or you can use the rename-keys function if you plan on using the map more than once. This probably would have worked for me, but I had an additional requirement. The particular Java objects I was working with had many methods/fields and the maps contained about 80% more information than I needed. So, I could have used bean, then rename keys, then dissoc. But, this felt similar enough to the situation in the past where I was working with specific method names and I thought I'd look for a more general solution.

The following example shows the definition of obj->map and the REPL output of using it.
user=> (import 'java.util.Date)
java.util.Date
user=> (defmacro obj->map [o & bindings]
(let [s (gensym "local")]
`(let [~s ~o]
~(->> (partition 2 bindings)
(map (fn [[k v]]
(if (vector? v)
[k (list (last v) (list (first v) s))]
[k (list v s)])))
(into {})))))
#'user/obj->map
user=> (obj->map (Date. 2012 1 31)
:month .getMonth
:year [.getYear #(* 2 %)]
:day .getDate)
{:month 2, :year 4024, :day 2}
As you can see from the output, the macro grabs the values of the methods you specify and stores them in a map. At one point I also needed to do a bit of massaging of a value, so I included the ability to use a vector to specify the method you care about and a function to apply to the value (the result of the function will become the value). In the example, you can see that the :year is double the value of what .getYear returns.

In general you should stick with bean, but if you need something more discriminating, obj->map might work for you.

Tuesday, June 03, 2008

ActionScript: The difference between Object and * (an asterisk)

If you've ever wondered what the difference is between the following two statements, you aren't alone.

var result:Object = sendRequest();
var result:* = sendRequest();

It's fairly hard to Google for the explanation, but Subhash Chandra Gupta recently pointed me to a good example.

The full article can be found in the Flex 3 Help.

The difference is that * (an asterisk) signifies that the object can be any type and typing something as an Object will require you to cast if you are compiling in strict mode. Here's a greatly simplified example to demonstrate.

function returnOne():Object {
return 1;
}
var one:Number = returnOne(); // compiler error in strict mode

function returnTwo():* {
return 2;
}
var two:Number = returnTwo(); // no compiler error in strict mode

Friday, August 31, 2007

Ruby: Adding a "not" method for readability

The other day I was working with an if statement that looked similar to the snippet below.

if !response.incomplete? && !response.invalid? && response.total > 0
...
end

I spent enough time in C, C#, etc to be able to parse the if statement fairly easily; however, I thought it would improve readability if I could write the following snippet instead.

if response.not.incomplete? && response.not.invalid? && response.total > 0
...
end

Adding a "not" method to Object turned out to be fairly easy. I started with the following tests (block syntax provided by dust).

require 'rubygems'
require 'test/unit'
require 'dust'

unit_tests do
test "not negates true to false" do
assert_equal false, nil.not.nil?
end

test "not negates false to true" do
assert_equal true, Object.new.not.nil?
end
end

The implementation of the "not" method is similar to the implementation of the "as" method provided by facets (an explanation of the "as" implementation can be found in a previous entry).

class Object
define_method :not do
Not.new(self)
end

class Not
private *instance_methods.select { |m| m !~ /(^__|^\W|^binding$)/ }

def initialize(subject)
@subject = subject
end

def method_missing(sym, *args, &blk)
!@subject.send(sym,*args,&blk)
end
end
end

The Object.not method returns an instance of Object::Not. The Object::Not instance is initialized with the subject (the instance that was sent the "not" message). The Object::Not instances are basically proxies that send all calls back to the original instance. The Object::Not class privatizes almost all of it's methods so that most method calls will be handled by method_missing. The method_missing implementation simply forwards on any method call to the subject and negates the result.