ArityException occurs when clojure gen-class an interface with overloaded methods - clojure

I have an java interface as below:
public interface Wrapper {
void error( Exception e);
void error( String str);
}
And i am trying to create an implementation in clojure with gen-class:
(ns myimpl)
(gen-class
:name myimpl
:implements [Wrapper]
:state state
:init init
:prefix "w-"
:main false
)
(defn- w-error [this ^Exception e]
(println e))
(defn- w-error [this ^String s]
(println s))
Then i try to create an instance and call the method in repl:
> (def w (myimpl. ))
> (.error w "oops")
This will give me an ArityException: Wrong number of args (2) passed to: myimpl$w-error.
What have i done wrong here?

The following code happens to be a misconception of how Clojure functions work.
(defn- w-error [this ^Exception e]
(println e))
(defn- w-error [this ^String s]
(println s))
"Regular" functions defined with defn can't dispatch on type - only on the number of arguments.
I belive that would actually be an useful and feasible feature, but we have to settle instead for multimethods and protocol implementations which together cover the 80% case for type-dispatch needs.
I don't know why are you getting an arity exception in particular, but I'd say it doesn't matter a lot.
Lastly, you might be interested in implementing your Java interface in Java, delegating the actual functionality to Clojure code. That would require either AOT-compiling your Clojure project, or dynamically loading code via RT, Var, etc.

Related

Group multiple namespace definitions under one namespace

Suppose I have the namespaces foo.car.components.engine, foo.car.components.transmission, foo.car.components.brakes.
In foo.car.components.engine there is (defn engine [] ...), foo.car.components.transmission there is (defn transmission [] ...),
foo.car.components.brakes there is (defn brakes [] ...).
I'd like to make these available in foo.car.components such that other namespaces only need to require foo.car.components to use engine, transmission, and brakes.
The following works, but I'm wondering if there are cleaner ways to do this or if it's even good practice.
(ns foo.car.components
(:require
[foo.car.components.engine :as engine]
[foo.car.components.transmission :as transmission]
[foo.car.components.brakes :as brakes]))
(def engine engine/engine)
(def transmission transmission/transmission)
(def brakes brakes/brakes)
I don't offhand know of a better way, but this way does come with downsides, so take these into consideration when deciding if you want to use this:
It doesn't transfer Meta information to the "wrapper", so any docstrings/other information attached to the main function won't show up in IDEs when you use the wrapper.
Along the same vein, because the wrapper doesn't have an argument list, if you ctrl+q the wrapper functions, it also won't show the available argument lists of the main function.
Having said that, Seesaw, a major Clojure library that wraps Swing does use this "technique". If I ever forget the docs/arguments of a function that has a "convenience wrapper", I just have to hit ctrl+b twice (in IntelliJ), and it will take me to the original source where I can look it over. It's ironically inconvenient, but I guess that's the price for convenience elsewhere.
To get around these faults, you could write a function (or a macro that wraps def) that transfers Meta information. Considering argument list information is stored as Meta information, that might be enough to overcome the faults.
This answer doesn't really answer your question, so I hope someone else is able to give some insight here. I thought that this was relevant information though.
You can use:
import-vars
from https://github.com/ztellman/potemkin
It doesn't seem that this feature is provided by Clojure API. You can consider https://github.com/ptaoussanis/encore look for defalias.
On the other hand, if you have brakes, transmission and engine as public interfaces and you can use them separately why would you merge them? As opposite, you can provide all definitions in components or even car which will use in turn brakes, transmission and engine. In such way, it is not necessary to expose all components.
I think the way you're doing it is the best way, because it makes explicit the sources of the defs in each namespace. If you have large namespaces with a lot of functions, you could write a basic helper function to do this for you:
(ns foo.utils)
(defn export-refs
[target-ns source-namespaces]
(doseq [ns source-namespaces
[sym f] (ns-interns ns)
:let [existing (get (ns-interns target-ns) sym)]]
(when (and existing (not= (var-get existing) f))
(throw (Exception.
(format (str "Cannot refer to symbol %s in %s from %s, because that symbol "
"already exists in the target namespace")
sym (ns-name ns) (ns-name target-ns)))))
(intern target-ns sym f)))
(ns foo.car.components.engine)
(defn engine [] (println "engine"))
(ns foo.car.components.transmission)
(defn transmission [] (println "transmission"))
(ns foo.car.components.brakes)
(defn brakes [] (println "brakes"))
(ns foo.car.components
(:require [foo.utils :refer [export-refs]]))
(export-refs 'foo.car.components '[foo.car.components.engine
foo.car.components.transmission
foo.car.components.brakes])
(ns user
(:require [foo.car.components :refer [engine transmission brakes]]))
(engine) ;; Prints "engine"
(transmission) ;; Prints "transmission"
(brakes) ;; Prints "brakes"
Whether it's "good practice" or not is up to you. Obviously it has the advantage of splitting code into smaller files with specific functionality, while allowing the import of only a single namespace. The disadvantage is that there's a bit of indirection in where the functions come from, which will make finding the function sources more difficult, and there's more risk of name collisions.

How to use a symbol only if it is defined

I would like to execute some Clojure code that depends upon a certain var, but only if that var is defined. As a simplified example, the body of the if form should only be executed if sym is defined:
(if (resolve 'sym) (println sym))
Unfortunately, this doesn't work. If sym is not defined, the compiler still tries to resolve it and throws:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: sym in this context
From reading Rich Hickley's comment here, I gathered that this behavior is due to Clojure's use of (mostly) single-pass compilation. However, as much sense as that makes, it obviously results in undesirable behavior in this case.
I can get around the problem by forcing the symbol resolution to happen at runtime:
(if (resolve 'sym) (println (deref (resolve 'sym))))
But this is an undesirable hack. Is there a better way, or is it not possible with Clojure's read-eval model?
(Why do I need to do this? I have multiple composable profiles defined in my profiles.clj. One of them is for vinyasa, which allows me to inject various functions into the conveniently accessible . namespace. Others load various other utility libraries. In the profiles for those other utility libraries, I want to use vinyasa to inject the most important functions, but only if vinyasa is loaded. I am currently using a variation of the hack above.)
The approach recommended by #Michiel with when-let is the best way to solve this problem. Importantly, you can make the conditionality almost completely transparent by using let's ability to shadow an existing binding:
(when-let [foo (resolve 'foo)]
(foo))
;;=> nil
(defn foo []
:bar)
(foo)
;;=> :bar
(when-let [foo (resolve 'foo)]
(foo))
;;=> :bar
(defn get-when-var-defined [sym]
(when-let [var-for-sym (resolve sym)]
#var-for-sym))
(get-when-var-defined 'foo) ;;=> nil
(def foo 1)
(get-when-var-defined 'foo) ;;=> 1

can cljc single-file macro definitions to work with clojurescript?

I have clojurescript successfully importing macros from other namespaces. But I wonder whether a single-file construction is/should be possible with clojure 1.7, such that a macro can be defined and used. What I have tried does not work, but maybe I've missed a detail someplace.
(ns cljc.core)
#?(:cljs
(enable-console-print!))
#?(:clj
(defmacro list-macro [x y]
`(list ~x ~y)))
(defn foo [a]
(println (list-macro a a)))
(foo :a)
This form fails with list-macro being undefined when compiling cljs; if I remove the :clj guard around list-macro, then defmacro is undefined within the cljs compilation. Is there a way?
Yes, there is a way for a single file construction.
(ns cljc.core
#?(:cljs (:require-macros [cljc.core :refer [list-macro]])))
#?(:clj
(defmacro list-macro [x y]
;; ...
Assumedly one of the next CLJS compiler versions will do the import automatically.

Strange unexpected defrecord behavior: a bug or a feature?

;; Once upon a time I opened a REPL and wrote a protocol
;; definition:
(defprotocol SomeProtocol
(f [this]))
;; And a record:
(defrecord SomeRecord []
SomeProtocol
(f [this]
"I don't do a whole lot."))
;; And a very useful side-effect free function!
(defn some-function []
(f (SomeRecord.)))
;; I call my function...
(some-function)
;; ...to see exactly what I expect:
;; user=> "I don't do a whole lot."
;; Unsatisfied with the result, I tweak my record a little bit:
(defrecord SomeRecord []
SomeProtocol
(f [this]
"I do a hell of a lot!"))
(some-function)
;; user=> "I don't do a whole lot."
Looks like a bug to me. I just cannot be sure after having seen so
many false compiler bug reports in c++ user group.
You need to re-define the some-function after redefining the record again. The reason for this is that defrecord creates a new type (using deftype) and using the (SomeRecord.) notation inside the function will bind the code to that type even after a new type with same name is defined. This is why it is usually prefer to use (->SomeRecord) notation to instantiate the record, using this notation will make your code work like you expected.

How do I reference a dynamically generated symbol?

I am trying to dynamically create functions based on some static public fields of a Java class. So in one file I have something like:
(intern *ns* (symbol (get-fieldname-from-class class)) some-func)
The problem is that I want to call that particular function while it isn't defined yet.
For example, the Java class has a static int PARENTHESIZED_EXPRESSION field. From this I generate a parenthesized-expression? function. This works quite nice, but when I load a Clojure file in the REPL that uses this functions I get an
unable to resolve parenthesized-expression?
error. So I have to make sure that the symbol's are interned first. How can I do this?
I realize this is not a very functional approach, but I'm a little bit hesitant to enter almost 80 similar functions for all the fields of this class. Besides, this class might be subject to change.
I wonder if you could get by using a macro like this:
user=> (defmacro f [sym] `(defn ~(symbol (str sym "?")) [x#] (= x# ~(symbol (str "java.util.Calendar/" (str sym))))))
#'user/f
user=> (f DAY_OF_MONTH)
#'user/DAY_OF_MONTH?
user=> (DAY_OF_MONTH? java.util.Calendar/DAY_OF_WEEK)
false
user=> (DAY_OF_MONTH? java.util.Calendar/DAY_OF_MONTH)
true
user=>