
clojure.algo.generic.comparison.clj Maven / Gradle / Ivy
The newest version!
;; Generic interfaces for comparison operations
;; by Konrad Hinsen
;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this
;; distribution. By using this software in any fashion, you are
;; agreeing to be bound by the terms of this license. You must not
;; remove this notice, or any other, from this software.
(ns
^{:author "Konrad Hinsen"
:doc "Generic comparison interface
This library defines generic versions of = not= < > <= >= zero?
as multimethods that can be defined for any type. Of the
greater/less-than relations, types must minimally implement >."}
clojure.algo.generic.comparison
(:refer-clojure :exclude [= not= < > <= >= zero? pos? neg? min max])
(:use [clojure.algo.generic
:only (root-type nulary-type nary-type nary-dispatch)]))
;
; zero? pos? neg?
;
(defmulti zero?
"Return true of x is zero."
{:arglists '([x])}
type)
(defmulti pos?
"Return true of x is positive."
{:arglists '([x])}
type)
(defmulti neg?
"Return true of x is negative."
{:arglists '([x])}
type)
;
; Equality
;
(defmulti =
"Return true if all arguments are equal. The minimal implementation for type
::my-type is the binary form with dispatch value [::my-type ::my-type]."
{:arglists '([x] [x y] [x y & more])}
nary-dispatch)
(defmethod = root-type
[x] true)
(defmethod = nary-type
[x y & more]
(if (= x y)
(if (next more)
(recur y (first more) (next more))
(= y (first more)))
false))
(defn not=
"Equivalent to (not (= ...))."
[& args]
(not (apply = args)))
;
; Greater-than
;
(defmulti >
"Return true if each argument is larger than the following ones.
The minimal implementation for type ::my-type is the binary form
with dispatch value [::my-type ::my-type]."
{:arglists '([x] [x y] [x y & more])}
nary-dispatch)
(defmethod > root-type
[x] true)
(defmethod > nary-type
[x y & more]
(if (> x y)
(if (next more)
(recur y (first more) (next more))
(> y (first more)))
false))
;
; Less-than defaults to greater-than with arguments inversed
;
(defmulti <
"Return true if each argument is smaller than the following ones.
The minimal implementation for type ::my-type is the binary form
with dispatch value [::my-type ::my-type]. A default implementation
is provided in terms of >."
{:arglists '([x] [x y] [x y & more])}
nary-dispatch)
(defmethod < root-type
[x] true)
(defmethod < [root-type root-type]
[x y]
(> y x))
(defmethod < nary-type
[x y & more]
(if (< x y)
(if (next more)
(recur y (first more) (next more))
(< y (first more)))
false))
;
; Greater-or-equal defaults to (complement <)
;
(defmulti >=
"Return true if each argument is larger than or equal to the following
ones. The minimal implementation for type ::my-type is the binary form
with dispatch value [::my-type ::my-type]. A default implementation
is provided in terms of <."
{:arglists '([x] [x y] [x y & more])}
nary-dispatch)
(defmethod >= root-type
[x] true)
(defmethod >= [root-type root-type]
[x y]
(not (< x y)))
(defmethod >= nary-type
[x y & more]
(if (>= x y)
(if (next more)
(recur y (first more) (next more))
(>= y (first more)))
false))
;
; Less-than defaults to (complement >)
;
(defmulti <=
"Return true if each arguments is smaller than or equal to the following
ones. The minimal implementation for type ::my-type is the binary form
with dispatch value [::my-type ::my-type]. A default implementation
is provided in terms of >."
{:arglists '([x] [x y] [x y & more])}
nary-dispatch)
(defmethod <= root-type
[x] true)
(defmethod <= [root-type root-type]
[x y]
(not (> x y)))
(defmethod <= nary-type
[x y & more]
(if (<= x y)
(if (next more)
(recur y (first more) (next more))
(<= y (first more)))
false))
;
; Implementations for Clojure's built-in types
;
(defmethod zero? java.lang.Number
[x]
(clojure.core/zero? x))
(defmethod pos? java.lang.Number
[x]
(clojure.core/pos? x))
(defmethod neg? java.lang.Number
[x]
(clojure.core/neg? x))
(defmethod = [root-type root-type]
[x y]
(clojure.core/= x y))
(defmethod > [java.lang.Number java.lang.Number]
[x y]
(clojure.core/> x y))
(defmethod < [java.lang.Number java.lang.Number]
[x y]
(clojure.core/< x y))
(defmethod >= [java.lang.Number java.lang.Number]
[x y]
(clojure.core/>= x y))
(defmethod <= [java.lang.Number java.lang.Number]
[x y]
(clojure.core/<= x y))
;
; Functions defined in terms of the comparison operators
;
(defn max
"Returns the greatest of its arguments. Like clojure.core/max except that
is uses generic comparison functions implementable for any data type."
([x] x)
([x y] (if (> x y) x y))
([x y & more]
(reduce max (max x y) more)))
(defn min
"Returns the least of its arguments. Like clojure.core/min except that
is uses generic comparison functions implementable for any data type."
([x] x)
([x y] (if (< x y) x y))
([x y & more]
(reduce min (min x y) more)))
© 2015 - 2025 Weber Informatics LLC | Privacy Policy