Code Monkey home page Code Monkey logo

defun's Introduction

defun

A macro to define clojure functions with pattern matching just as erlang or elixir.

Since 0.3.0, defun supports ClojureScript.

Usage

Dependency in leiningen:

    [defun "0.3.0-alapha"]

Basic usage

Require defun in clojure:

(require '[defun :refer [defun]])

Or refer-macros in clojurescript:

(ns cljs-test
  (:require  [defun :refer-macros [defun]])
(enable-console-print!)            

Try to define function just like defn:

(defun hello
   "hello world"
   [name] (str "hello," name))
(hello "defun")
;; "hello,defun"

Supports variadic arguments, doc, metadata etc. as defun too. No supprises?

The fun thing is coming, let's say hi to people:

(defun say-hi
  ([:dennis] "Hi,good morning, dennis.")
  ([:catty] "Hi, catty, what time is it?")
  ([:green] "Hi,green, what a good day!")
  ([other] (str "Say hi to " other)))

Then calling say-hi with different names:

(say-hi :dennis)
;;  "Hi,good morning, dennis."
(say-hi :catty)
;;  "Hi, catty, what time is it?"
(say-hi :green)
;;  "Hi,green, what a good day!"
(say-hi "someone")
;;  "Say hi to someone"

We define functions just like Erlang's function with parameters pattern match (thanks to core.match), we don't need if,cond,case any more, that's cool!

Recursion

Let's move on, what about define a recursive function? That's easy too:

(defun count-down
  ([0] (println "Reach zero!"))
  ([n] (println n)
     (recur (dec n))))

Invoke it:

(count-down 5)
;;5
;;4
;;3
;;2
;;1
;;Reach zero!
nil

An accumulator from zero to number n:

    (defun accum
      ([0 ret] ret)
      ([n ret] (recur (dec n) (+ n ret)))
      ([n] (recur n 0)))

	 (accum 100)
	 ;;5050

A fibonacci function:

(defun fib
    ([0] 0)
    ([1] 1)
    ([n] (+ (fib (- n 1)) (fib (- n 2)))))

Output:

(fib 10)
;; 55

Of course it's not tail recursive, but it's really cool, isn't it?

Guards

Added a guard function to parameters:

(defun funny
  ([(N :guard #(= 42 %))] true)
  ([_] false))

(funny 42)
;;  true
(funny 43)
;; false

Another function to detect if longitude and latitude values are both valid:

(defun valid-geopoint?
    ([(_ :guard #(and (> % -180) (< % 180)))
      (_ :guard #(and (> % -90) (< % 90)))] true)
    ([_ _] false))

(valid-geopoint? 30 30)
;; true
(valid-geopoint? -181 30)
;; false

Private defun

Of course, you can use defun- to define a function that is private just as defn-

More Patterns

In fact ,the above say-hi function will be expanded to be:

(defn
 say-hi
 {:arglists '([& args])}
 [& args#]
 (clojure.core.match/match
  [(vec args#)]
  [[:dennis]]
  (do "Hi,good morning, dennis.")
  [[:catty]]
  (do "Hi, catty, what time is it?")
  [[:green]]
  (do "Hi,green, what a good day!")
  [[other]]
  (do (str "Say hi to " other))))

The argument vector is in fact a pattern in core.match, so we can use all patterns that supported by core.match.

For example, matching literals

(defun test1
    ([true false] 1)
    ([true true] 2)
    ([false true] 3)
    ([false false] 4))

(test1 true true)
;; 2
(test1 false false)
;; 4

Matching sequence:

(defun test2
    ([([1] :seq)] :a0)
    ([([1 2] :seq)] :a1)
    ([([1 2 nil nil nil] :seq)] :a2))

(test2 [1 2 nil nil nil])
;; a2

Matching vector:

(defun test3
    ([[_ _ 2]] :a0)
    ([[1 1 3]] :a1)
    ([[1 2 3]] :a2))

(test3 [1 2 3])
;; :a2

Rest Pattern, Map Pattern, Or Pattern etc.

I don't want to copy the core.match's wiki,please visit it by yourself.

fun and letfun

Since 0.2.0, there are two new macros: fun and letfun, just like clojure.core/fn and clojure.core/letfn

((fun
    ([[_ _ 2]] :a0)
    ([[1 1 3]] :a1)
    ([[1 2 3]] :a2))
  [1 2 3])
;; :a2

(letfun [(test3 ([[_ _ 2]] :a0)
                    ([[1 1 3]] :a1)
                    ([[1 2 3]] :a2))]
  (test3 [1 2 3]))
;; :a2

Criterium benchmarking

Uses the above function accum compared with a normal clojure function:

(require '[criterium.core :refer [bench]])

(defn accum-defn
    ([n] (accum-defn 0 n))
    ([ret n] (if (= n 0) ret (recur (+ n ret) (dec n)))))

(defun accum-defun
  ([0 ret] ret)
  ([n ret] (recur (dec n) (+ n ret)))
  ([n] (recur n 0)))

(bench (accum-defn 10000))
;;Evaluation count : 210480 in 60 samples of 3508 calls.
;;             Execution time mean : 281.095682 µs
;;    Execution time std-deviation : 2.526939 µs
;;   Execution time lower quantile : 277.691624 µs ( 2.5%)
;;   Execution time upper quantile : 286.618249 µs (97.5%)
;;                   Overhead used : 1.648269 ns

(bench (accum-defun 10000))
;;Evaluation count : 26820 in 60 samples of 447 calls.
;;             Execution time mean : 2.253477 ms
;;    Execution time std-deviation : 13.082041 µs
;;   Execution time lower quantile : 2.235795 ms ( 2.5%)
;;   Execution time upper quantile : 2.281963 ms (97.5%)
;;                   Overhead used : 1.648269 ns

accum-defn is much faster than accum-defun. Pattern matching does have a tradeoff.

Contributors

Thanks .

License

Copyright © 2014 Dennis Zhuang

Distributed under the Eclipse Public License either version 1.0 or (at

your option) any later version.

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.