Git Product home page Git Product logo

defntly's Introduction

defntly

A library that makes the creation of defn like macros in Clojure/Script a commodity.

The problem it addresses

Quite often in an mid size application, we need to apply some patterns to functions.

A pattern could be wrapping the body of a function in a try/catch or adding some instrumentation on this function.

One way to wrap the body of a function f is to create a high order function that wraps it. The code would probably looks like this:

(defn wrapper [f]
  (fn [& args]
     (try 
      (apply f args)
      (catch Throwable e
        (throw (Exception. (str "Exception caught in function " name ": " e))))
        
(defn foo [a b]
  (+ a b))

(def foo-wrapped (wrapper foo))

The major problem with this approach is that the code for foo-wrapped is distant from its effective body.

An attempt to solve this problem is to write foo as an anonymous function.

(defn foo [a b]
  (+ a b))

(def foo-wrapped (wrapper (fn [a b]
                             (+ a b))))

But then the expression that defines foo-wrapped is a def form which is a bit weird.

defntly addresses this issue by making it super easy to write a defn like macro.

For instance, with defntly you could create a defn-try macro and uses it exactly like defn:

(defn-try foo [a b]
    (+ a b))

Writing a defn-try macro is not an easy task if you want to support all the various ways to use defn: docstring, metadata, multi-arity...

With defntly, writing a defn like macro it becomes a commodity!

Usage

Leiningen/Boot: [viebel/defntly "0.0.1"]

Clojure CLI/deps.edn: viebel/defntly {:mvn/version "0.0.1"}

(require '[defntly.core :refer [defn-update-body]])

Examples

Let's create a defn-try macro that automatically wraps the function body in a try/catch form.

(require '[defntly.core :refer [defn-update-body]])

(defn wrap-try [name body]
  `((try ~@body
    (catch Throwable ~'e
      (throw (Exception. (str \"Exception caught in function \" ~name \": \" ~'e)))))))

(defmacro defn-try [& args]
  (defn-update-body wrap-try args))

We use defn-try exactly like defn:

(defn-try foo [a b]
    (+ a b))

is macroexpanded into:

 (defn foo [a b]
  (try
    (+ a b)
    (catch
      java.lang.Throwable
      e
      (throw (str "Exception caught in function " "foo" ": " e)))))

We can pass to our freshly created defn-try macro all the args that defn receive (metadata, docstring, multi arity).

For instance, a mutli arity function with a docstring like:

(defn-try foo
    "foo has a docstring"
    ([a] (foo a 42))
    ([a b] (+ a b)))

is macroexpanded into:

(defn foo
  "foo has a docstring"
  ([a]
    (try
      (foo a 42)
      (catch
        java.lang.Throwable
        e
        (throw (str "Exception caught in function " "foo" ": " e)))))
  ([a b]
    (try
      (+ a b)
      (catch
        java.lang.Throwable
        e
        (throw (str "Exception caught in function " "foo" ": " e))))))

How it works

Explanations about you the internals of defn-update-body and how it leverages clojure.spec in this article.

defntly's People

Contributors

caiorulli avatar viebel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

escherize

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.