ProductPromotion
Logo

Clojure

made by https://0x3d.site

GitHub - killme2008/defun: A macro to define clojure functions with parameter pattern matching just like erlang or elixir.
A macro to define clojure functions with parameter pattern matching just like erlang or elixir. - killme2008/defun
Visit Site

GitHub - killme2008/defun: A macro to define clojure functions with parameter pattern matching just like erlang or elixir.

GitHub - killme2008/defun: A macro to define clojure functions with parameter pattern matching just like erlang or elixir.

Clojure CI

defun

A macro to define clojure functions with pattern matching just as erlang or elixir. It supports both clojure and clojurescript.

Usage

Dependency in leiningen:

    [defun "0.4.0"]

Basic usage

Require defun.core in clojure:

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

Or refer-macros in clojurescript:

(ns cljs-test
  (:require  [defun.core :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 surprises?

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

((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 : 106740 in 60 samples of 1779 calls.
;;             Execution time mean : 578.777537 µs
;;    Execution time std-deviation : 23.354350 µs
;;   Execution time lower quantile : 552.627735 µs ( 2.5%)
;;   Execution time upper quantile : 637.001868 µs (97.5%)
;;                   Overhead used : 17.111650 ns

(bench (accum-defun 10000))
;;Evaluation count : 54660 in 60 samples of 911 calls.
;;             Execution time mean : 1.115643 ms
;;    Execution time std-deviation : 32.916487 µs
;;   Execution time lower quantile : 1.078117 ms ( 2.5%)
;;   Execution time upper quantile : 1.180711 ms (97.5%)
;;                   Overhead used : 17.111650 ns

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

Contributors

Thanks .

License

Copyright © 2023 Dennis Zhuang

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

your option) any later version.

More Resources
to explore the angular.

mail [email protected] to add your project or resources here 🔥.

Related Articles
to learn about angular.

FAQ's
to learn more about Angular JS.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory