HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

API wrapper for Clojure

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
wrapperapiclojurefor

Problem

I wanted to wrap the jkeymaster library in a Clojure wrapper (for my own use, but perhaps also to save others some time). I'm just learning Clojure so I'm still not quite sure what "idiomatic libraries/APIs" look like. In Ruby, I would have created an object with methods, but in one of the clojure books they recommended letting users manage state themselves, so I have function that creates a provider, and this provider must then be passed to the register function.

Here's first an example of usage:

(ns keymaster.core
  (:require [keymaster.keymaster :as km]))
(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (km/register (km/provider) "control shift 1" #(println "hi")))


And here is the full text of the "library".

(ns keymaster.keymaster
  (:gen-class)
  (:use (com.tulskiy.keymaster.common)))

(defn provider []
  "Gets and initiates a keymaster provider, which must be passed to register to register shortcuts"
  (let [provider (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)]
    (.init provider)
    provider))

(defn- conv-keystroke [x]
  "Takes keystroke in the form \"control shift 1\" and returns a Keystroke class"
  (javax.swing.KeyStroke/getKeyStroke x))

(defn- conv-listener [f]
  "Takes a function with one argument, which will get passed the keycode, and creates a listener
   Todo: How to accept a function with or without a parameter to accept hotKey?"
   (proxy [com.tulskiy.keymaster.common.HotKeyListener] [] (onHotKey [hotKey] (f))))

(defn register
  [provider shortcut listener]
  "Registers a shortcut on provider, which will trigger listener (with one argument)"
  (let [k (conv-keystroke shortcut)
        l (conv-listener listener)]
    (.register provider k l)))


In addition to any general style feedback, both about the coding, and the design of the API, I'm also wondering if there is any way to have conv-listener accept either a 0 or 1-arity function. Right now I made the choice of accepting a 0-arity function,

Solution

As a wrapper goes I think this looks fine. The feedback I do have is that I wouldn't use let as often as you do and would use the treading macro (-> ...) instead.

For example:

(-> (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)
      .init)


does the same as

(let [provider (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)]
  (.init provider)
  provider)


and it's easier to read and shorter. You could also do it this way:

(.init (com.tulskiy.keymaster.common.Provider/getCurrentProvider true))

Code Snippets

(-> (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)
      .init)
(let [provider (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)]
  (.init provider)
  provider)
(.init (com.tulskiy.keymaster.common.Provider/getCurrentProvider true))

Context

StackExchange Code Review Q#25575, answer score: 2

Revisions (0)

No revisions yet.