Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Clojure Design
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
Colour
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Undo
Redo
Keyboard Shortcuts Help
<h2>Problem Statement</h2> <ul> <li>People looking to call Clojure code from Java are faced with a large number of Java classes from the Clojure implementation and don't know which ones are stable and safe to use.</li> </ul> <p><strong>Other problems, not in scope</strong></p> <ul> <li>people don't like to type <ul> <li>why are they using Java then?</li> </ul> </li> <li>people don't understand Clojure, but still want to leverage it from Java <ul> <li>Clojure is not a Java library</li> <li>People can and do write libraries in Clojure for consumption from Java, but each must define its own Java API</li> </ul> </li> </ul> <p><strong>Mission</strong></p> <ul> <li>Solve the problem, without introducing others</li> </ul> <p><strong>Proposal</strong></p> <ul> <li>provide the smallest possible API, in a single class, to allow people to find and call Clojure fns <ul> <li>a single thing to refer people to</li> <li>opens up entire API <ul> <li>everything in Clojure is exposed via fns</li> <li>if something critical is missing, let's add a fn rather than grow this API</li> </ul> </li> <li>no wrappers that need to be maintained</li> <li>no semantic or other mismatch with original fns</li> <li>docs are Clojure docs</li> </ul> </li> </ul> <p><strong>Issues</strong></p> <ul> <li>We want to give people access to Var objects but not have them use the Var class <ul> <li>too much other stuff there, plus it's concrete</li> <li>the interfaces they need are IFn and IDeref</li> <li>but no interface unifies them, so we have no good type to use <ul> <li>make one?</li> </ul> </li> </ul> </li> <li>bindings are also tricky to use from Java <ul> <li>can we function-ify them? <ul> <li>with-bindings (fn!)</li> <li>with-repl-bindings</li> <li>with-compilation-bindings</li> </ul> </li> </ul> </li> </ul> <h2>Stable Public Java API</h2> <p>Clojure does not currently provide a stable public Java API. This makes calling Clojure code from Java more verbose and more complicated than it needs to be, and requires developers to refer to classes that are actually just details of Clojure's current implementation that can and probably will change in the future.</p> <p>A public Java API probably only needs to be a single class providing a small set of static utility methods, primarily intended to smooth the path for calling Clojure functions from Java. Off the top of my head, this might be an initial set of such methods:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>var(String nsName) var(String ns, String name) deref(String nsName) deref(String ns, String name) call(String varName, Object...) call(Var var, Object...) call(IFn fn, Object...) eval(String code) load(File f)</pre></td></tr></table> <p>In addition, some data-related methods would be helpful:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>keyword(String nsName) keyword(String ns, String name) symbol(String nsName) symbol(String ns, String name) vector(Object... vals) vector(java.util.Collection list) hashmap(Object... keyvals) hashmap(java.util.Map m) set(Object... vals) set(Collection vals)</pre></td></tr></table> <p>As long as we are careful with our naming, all of these methods could be statically imported in Java files, making a lot of common interop tasks much less verbose.</p> <h2>IFn.invoke throws Exception :-(</h2> <p><span style="text-decoration: line-through;">Because</span> <code><span style="text-decoration: line-through;">clojure.lang.IFn.invoke</span></code> <span style="text-decoration: line-through;">throws</span> <code><span style="text-decoration: line-through;">Exception</span></code><span style="text-decoration: line-through;">, calling Clojure functions in Java (via IFn or resolved vars) implies a lot of checked exception pain. Without some solution to this, the public API for Java would also bubble up that pain through any</span> <code><span style="text-decoration: line-through;">call</span></code> <span style="text-decoration: line-through;">method or</span> <code><span style="text-decoration: line-through;">.invoke</span></code> <span style="text-decoration: line-through;">calls made using</span> <code><span style="text-decoration: line-through;">Var</span></code> <span style="text-decoration: line-through;">or</span> <code><span style="text-decoration: line-through;">IFn</span></code> <span style="text-decoration: line-through;">obtained through that API.</span></p> <p><span style="text-decoration: line-through;">h3. Potential solutions</span></p> <p><span style="text-decoration: line-through;">Wrap</span> <code><span style="text-decoration: line-through;">IFn</span></code> <span style="text-decoration: line-through;">with a delegate that catches</span> <code><span style="text-decoration: line-through;">Exception</span></code> <span style="text-decoration: line-through;">and rethrows them as</span> <code><span style="text-decoration: line-through;">RuntimeException</span></code><span style="text-decoration: line-through;">. An example of this is</span> <span style="text-decoration: line-through;"><a href="https://github.com/clojure/tools.nrepl/blob/master/src/main/java/clojure/tools/nrepl/SafeFn.java">SafeFn.java</a></span><span style="text-decoration: line-through;">, which allows nREPL connection functions to be used from Java with a minimum of exception management pain. The public Java API would presumably perform this wrapping automatically when making calls or when returning a function or var that will be {{.invoke}}d later.</span></p> <p><span style="text-decoration: line-through;">Alternatively, drop the</span> <code><span style="text-decoration: line-through;">throws Exception</span></code> <span style="text-decoration: line-through;">declaration from</span> <code><span style="text-decoration: line-through;">IFn.invoke</span></code> <span style="text-decoration: line-through;">entirely, and change function code generation to catch</span> <code><span style="text-decoration: line-through;">Exception</span></code> <span style="text-decoration: line-through;">and rethrow them as</span> <code><span style="text-decoration: line-through;">RuntimeException</span></code><span style="text-decoration: line-through;">. That would simplify the Java interaction, not force the introduction of one or two new classes, and avoid any wrapping inefficiencies, but I don't yet know what the repercussions would be to the compiler to effect this change or what the perf impact would be (either at runtime or compile/load time given the additional heft of each new function class).</span></p> <p>RH - or drop the declaration and don't wrap. Checked exceptions are a fiction of javac, and not a fiction of Clojure. <a href="https://github.com/clojure/clojure/commit/8fda34e4c77cac079b711da59d5fe49b74605553">Implemented</a>.</p> <h2>Prior Discussion</h2> <p><a href="http://dev.clojure.org/jira/browse/CLJ-452">CLJ-452</a></p> <p><a href="http://groups.google.com/group/clojure-dev/browse_frm/thread/d50918167bdb5d9a">2010/03/21 clojure-dev thread</a></p>
Attachments
Labels
Location
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced