Have you ever wondered if the ease of calling C libraries could
be responsible for a lot of Python's popularity? C function calls
look just like native Python calls.
import george;
george.wash("car");
You can't tell from the Python code whether the module, george, is
written in C or Python. It doesn't matter to the calling program.
That's a simple foreign function interface.
Jarc brings this same
simple foreign function interface to Arc.
Unlike Clojure and JScheme, the syntax for calling a Java
method is the same as for calling any Lisp function.
Jarc> (getTime (new java.util.Date))
1268254080703
Jarc> (getTime "foo")
Error: Symbol 'getTime' has no value
Even though there is no function
getTime defined,
that function can still be called on a Date instance.
Jarc uses dispatch on first arg to figure out
how to evaluate the method call. This was suggested
by Paul Graham in
Arc at 3 Weeks.
Although Arc doesn't currently have dispatch on
first arg it is ideal for Jarc to access Java methods.
If you've defined classes in Python (or Perl), this may seem
intuitive.
class HelloClass:
def f(self):
return 'hello world'
That
self there is the first argument to the function.
Even though you call the function as
x.f() what's happening
under the covers is that
x is passed as the first argument.
This same thing is happening under the covers in Perl and C++.
Advantages
1. You can treat Arc calls and Java calls exactly the same
Polymorphism, anyone? Here's the Jarc macro with-open,
which is just like let except that it also calls
close on variable. It is slightly more complicated then
that because is always calls close even if there is an error.
And it ignores any errors that might happen when calling close.
(mac with-open (var init . exprs)
`(let ,var ,init
(protect (fn () ,@exprs)
(fn () (errsafe (close ,var))))))
This is quite handy and ensures that your "stream" gets closed,
both when it is an arc type:
(with-open f (outfile "what.ever")
...)
Where Jarc calls the Arc function
close,
and when the "stream" is a Java object:
(with-open db (java.sql.DriverManager.getConnection ...)
...)
Where Jarc calls the
close method on the
java.sql.Connection instance.
2. Java objects work with map
No helper function
(like memfn in Clojure) is needed to use Java instance
methods with map.
(map 'getTime '(list (new java.util.Date)))
Both
map and
apply accept a symbol
(in addition to a function, of course) and interpret that as
a Java method call.
3. One less character
And of course, since
succinctness is power, saving one
whole character is an advantage as well. Clojure requires you to type an additional
period.
(.getTime (new java.util.Date))
Astute readers will know that succinctness is defined by the number of
nodes in the parse tree. And the Clojure example above still has the same
number of nodes as the Jarc version. But the number of nodes is also
a proxy for how hard it is to read the code. Our brains have to process
the code too. And I think parsing
.getTime requires parsing
the dot separately. And it's not useful information. Just like in Python,
I don't want to be distracted with extra syntax to indicate that this is
a Java method call. It's just a function call and should be just as simple.