Novemberborn, Straight lines circle sometime

Experiment: Function.$case

One of the few things I like about Java is how methods are identified not by their identifier (language collision here, it’d seem) but by their signature. In code:

public static void foo (String bar) {
  // do things
}

public static void foo (String[] bar) {
  // do things
}

These foo() methods are different in that they accept different types of parameters. In dynamic languages this is not possible, but of course you aren’t limited to one type of parameter.

And yet, I was wondering if there was an elegant way to implement someting comparable in JavaScript. Let’s take the following code, and try to make it more elegant:

function say (value) {
   value = value || "";

   if (typeof (value) != "string") {
      if (value.constructor == Array)
         value = value.join("\n");
      else {
         var result = "";
         for(var prop in value)
            result += prop + ": " + value[prop] + "\n";
         return result;
      }
   }

   alert(value);
}

Hmm, some conditions and specific code in their bodies. It’d almost look like a switch statement, but in JavaScript you can only compare values, not use your own conditions. However, Ruby has a switch mechanism which lets you evaluate conditions:

case
when 1 + 1 == 2
  puts "1 + 1 is indeed  2"
when 1 * 1 == 1
  puts "1 * 1 is indeed 1"
else
  puts "Somebody must have disproved mathematics"
end

Quite elegant. Let’s consider this example:

function say (value) {
   value = value || "";

   alert (Function.$case (
      typeof value == "string", // when
         value, // expression

      value.constructor == Array, // when
         function () { // expression
            return value.join("\n");
         },

      function () { // else
         var result = "";
         for(var prop in value)
            result += prop + ": " + value[prop] + "\n";
         return result;
      }
   ));
}

The even attributes (counting from 0) are the conditions. The odd attributes are the expressions, and the last even attribute is the “or else” expression.

I’d say this is (in theory) more elegant, but it looks confusing and requires more code — sounds a bit like Java, actually. And this is what Function.$case() looks like:

Function.$case = function () {
   var condition;
   for (var i = 0, expr = null; i < arguments.length; i+=2, expr = null) {
      condition = arguments[i];
      if (i == arguments.length - 1)
         expr = condition;
      else if (condition === true)
         expr = arguments[i + 1];
      else if (typeof (condition) == "function" && condition () === true)
         expr = arguments[i + 1];

      if (typeof (expr) == "function")
         return expr ();
      else if (expr != null) // To obviate the need for superfluous functions, you can also use a value instead of a function
         return expr;
   }
}

link | javascript experiments | 19 October 2005, 20:18


Comments

  1. This is one thing I’ve always liked about Python, where you can just do

    def func(*args, **kwargs):

    And then have the function do different things based on what it finds in its arguments. Django uses that trick in its database API to do all sorts of neat stuff.

    James | 19 December 2005, 00:33 | link

Leave your comment

Please keep it polite and on topic. Yes, your e-mail address is required, but it's kept private. HTML is not allowed in the comments but you can use Markdown. Non-contributing comments run the risk of being removed. Especially if the website seem “fishy”. Spammers, beware.

(required)
(required, kept private)
(optional, but let's share it!)
(required)

Remember my details


Novemberborn: Extra

About the author

Mark Wubben is a hacker/writer in Enschede, the Netherlands.

Read more about Mark...

Go to

Jobs (NL)

Xopus zoekt programmeurs! Verbeter de code en win!

Subscribe