Metaphysical Developer

Literal Collections In Java

Posted in Languages by Daniel Ribeiro on May 23, 2009

Terse ways to express Literal Collections such as Maps and Lists can be useful when building an Internal DSL. Java is famous for not having any facility to craft those. It does have literal object arrays, but these are a bit awkward when nesting, which is usually what you are going to do when employing this technique. But using variable arguments functions can supplement this deficiency quite nicely.

Below I show some ways to achieve this using an useful import static from http://code.google.com/p/fluentjava/: import static org.fluentjava.FluentUtils.*. I also comapare with the original ruby examples from Martin Fowler’s DSL Book.

  • Lists and Maps in Java
  • alist("computer",
      alist("processor", map(pair("cores", 2), pair("type", "i386"))),
      alist("disk", map(pair("size", 150))),
      alist("disk", map(
       pair("size", 78),
       pair("speed", 7200),
       pair("interface", "sata")))
      );
  • Lists and Maps in Ruby
  • [:computer,
     [:processor, {:cores => 2, :type => :i386}],
     [:disk, {:size => 150}],
     [:disk, {:size => 75, :speed => 7200, :interface => :sata}]
    ]
  • Just Lists in Java
  • alist("computer",
      alist("processor", alist("cores", 2), alist("type", "i386")),
      alist("disk", alist("size", 150)),
      alist("disk", alist("size", 78), alist("speed", 7200),
        alist("interface", "sata")));
  • Lists and Pairs in Java
  • alist("computer",
     alist("processor", pair("cores", 2), pair("type", "i386")),
     alist("disk", pair("size", 150)),
     alist("disk",
      pair("size", 78), pair("speed", 7200), pair("interface", "sata"))
     );
  • Just Lists In Ruby
  • [:computer,
     [:processor,
      [:cores, 2,],
      [:type, :i386]],
     [:disk,
      [:size, 150]],
     [:disk,
      [:size, 75],
      [:speed, 7200],
      [:interface, :sata]]]
  • Using a symbol as a vararg function (Java only)
  • $("computer",
     $("processor", $("cores", 2), $("type", "i386")),
     $("disk", $("size", 150)),
     $("disk", $("size", 78), $("speed", 7200), $("interface", "sata"))
    );
    
    private FluentList<Object> $(Object... args) {
       return alist(args);
    }

From the comparison, it is easy to see that ruby is bit more appropriate for this technique (and so are other languages such as python, perl and lisp). However, some cleverly defined (or imported) functions can help Java code benefit from it as well.

Advertisements
Tagged with: , , , ,

5 Responses

Subscribe to comments with RSS.

  1. gorlok said, on May 24, 2009 at 12:21 pm

    It will be nice if you show the same examples in groovy. I think Groovy fill the gap between Java and dynamic languages.

  2. kodeninja said, on May 25, 2009 at 3:43 am

    Here’s the above nested list in Groovy:

    def nestedList =
    [
    “computer”,
    [“processor”, [cores:2, type:”i386″]],
    [“disk”, [size:150]],
    [“disk”, [size:75, speed:7200, “interface”:”sata”]]
    ]

    • danrbr said, on May 25, 2009 at 9:09 pm

      Good Example. However, the focus of the post itself is not to show all variations on several languages, as most dynamic languages can do it easily, whereas Java, natively, can’t. Ruby example was only added as it was the original one.

      But in case anybody else wondered:

      Two ways in python:

      1. Using named args:

      def m(**kwargs):
      return kwargs

      ret = [‘computer’,
      [‘processor’, m(cores=2, type=’i386′)],
      [‘disk’, m(size=150)],
      [‘disk’, m(size=75, speed=7200, interface=’sata’)],
      ]

      2: Using litteral collections (too many strings):
      [‘computer’,
      [‘processor’, {‘cores’: 2, ‘type’: ‘i386’}],
      [‘disk’, {‘size’: 150}],
      [‘disk’, {‘interface’: ‘sata’, ‘speed’: 7200, ‘size’: 75}]
      ]

  3. Stephan Schmidt said, on March 4, 2010 at 3:06 am

    I like the $ trick, used it to build markup in Java,

    http://codemonkeyism.com/rest-lean-json-and-xml-from-the-same-code/

    Cheers
    Stephan

    • Daniel Ribeiro said, on March 4, 2010 at 4:14 am

      In my defense, I only saw your post several months after posting this :) Otherwise I’d have linked to it giving credits.

      It is a nice trick a colleage showed me, when I was complaining about constant dollar usage on Perl. Collection litterals would be better, but jdk7 rejected its respective Project Coin proposoal. And of course, all more verbose when compared to Lisp’s S-expressions.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: