All Projects → killme2008 → Defun

killme2008 / Defun

Licence: epl-1.0
A macro to define clojure functions with parameter pattern matching just like erlang or elixir.

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to Defun

yara-rust
Rust bindings for VirusTotal/Yara
Stars: ✭ 35 (-91.9%)
Mutual labels:  pattern-matching
strings
String helper methods and an inflector
Stars: ✭ 31 (-92.82%)
Mutual labels:  pattern-matching
matchete
Simple pattern-matching library for Clojure(Script)
Stars: ✭ 65 (-84.95%)
Mutual labels:  pattern-matching
lispy
Learning with Peter Norvig's lis.py interpreter
Stars: ✭ 133 (-69.21%)
Mutual labels:  pattern-matching
mux-stream
(De)multiplex asynchronous streams
Stars: ✭ 34 (-92.13%)
Mutual labels:  pattern-matching
pattern-matching-with-typescript
TypeScript does not have any pattern matching functionality built in. This article shows several ways how you can replicate the core of a simple pattern matcher using a few simple structures and functions within TypeScript. Resulting code will have improved maintainability and better runtime type safety when done right.
Stars: ✭ 70 (-83.8%)
Mutual labels:  pattern-matching
bop
Bop is a very fast Boyer-Moore parser/matcher for String or Buffer patterns.
Stars: ✭ 15 (-96.53%)
Mutual labels:  pattern-matching
Qo
Qo - Query Object - Pattern matching and fluent querying in Ruby
Stars: ✭ 351 (-18.75%)
Mutual labels:  pattern-matching
siringa
Minimalist dependency injection library for Python that embraces type annotations syntax
Stars: ✭ 51 (-88.19%)
Mutual labels:  pattern-matching
pattern-case
Simple pattern matching in Typescript
Stars: ✭ 40 (-90.74%)
Mutual labels:  pattern-matching
babel-plugin-proposal-pattern-matching
the minimal grammar, high performance JavaScript pattern matching implementation
Stars: ✭ 34 (-92.13%)
Mutual labels:  pattern-matching
conditional-expression
JavaScript functional conditional expression
Stars: ✭ 63 (-85.42%)
Mutual labels:  pattern-matching
cats.match
Pattern matching for the monads in the cats Clojure library
Stars: ✭ 49 (-88.66%)
Mutual labels:  pattern-matching
Bracmat
Programming language for symbolic computation with unusual combination of pattern matching features: Tree patterns, associative patterns and expressions embedded in patterns.
Stars: ✭ 42 (-90.28%)
Mutual labels:  pattern-matching
Rascal
The implementation of the Rascal meta-programming language (including interpreter, type checker, parser generator, compiler and JVM based run-time system)
Stars: ✭ 284 (-34.26%)
Mutual labels:  pattern-matching
dry-matcher
Flexible, expressive pattern matching for Ruby
Stars: ✭ 91 (-78.94%)
Mutual labels:  pattern-matching
flowpython
tasty feature extensions for python3(NO MAINTENANCE!).
Stars: ✭ 66 (-84.72%)
Mutual labels:  pattern-matching
Whyhaskellmatters
In this article I try to explain why Haskell keeps being such an important language by presenting some of its most important and distinguishing features and detailing them with working code examples. The presentation aims to be self-contained and does not require any previous knowledge of the language.
Stars: ✭ 418 (-3.24%)
Mutual labels:  pattern-matching
Pampy
Pampy: The Pattern Matching for Python you always dreamed of.
Stars: ✭ 3,419 (+691.44%)
Mutual labels:  pattern-matching
gomatch
Library created for testing JSON against patterns.
Stars: ✭ 41 (-90.51%)
Mutual labels:  pattern-matching

defun

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

News

  • Since 0.3.0-RC1, defun namespace is renamed to defun.core .

Usage

Dependency in leiningen:

    [defun "0.3.1"]

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!)

Since 0.3.0-RC, defun namespace is renamed to defun.core .

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

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 : 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 © 2014 Dennis Zhuang

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

your option) any later version.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].