BrunoBonacci.where

https://github.com/BrunoBonacci/where.git

git clone 'https://github.com/BrunoBonacci/where.git'

(ql:quickload :BrunoBonacci.where)
19

where

Clojars Project CircleCi last-commit Dependencies Status

Human readable conditions and filter best companion. A Clojure and ClojureScript library to write expressive predicate functions.

Advantages: * Predicate functions are very expressive and easy to read * All built-in comparators are nil safe. * All built-in comparators which operate on strings have a case insensitive version * Very fast execution (same as hand crafted version) * Very easy to embed in your DSL * Support for glob pattern matching (like: *.txt)

Motivations

Maps are everywhere is Clojure. And when dealing with loads of maps it is important to work comfortably and make your code as readable as possible. However when it comes to filter maps building a clean predicate function becomes increasingly harder. Even harder with nested maps or when it required to combine predicate function with logical operators.

The purpose of this library is to simplify the construction of predicate functions. A predicate function is a function which takes a value and return a truthy or a falsey value. f(x) -> truthy | falsey. These are often used together with function like filter to retain only items which match a specific condition.

where allows to build very expressive predicate functions and nil-safe.

Usage

To use this library add the following dependency in your project.clj

[com.brunobonacci/where "0.5.5"]

Latest version: where

then require the library

(ns your-ns
  (:require [where.core :refer [where]])

The signature of the function is:

(where extractor comparator value)

where cheatsheet

(where extractor comparator target)
;;=> predicate function

With maps

Logical operators

Built-in Generic comparators

The generic comparator accept any Clojure value.

Built-in String comparators

All String comparators they expect a String and are nil safe (don't throw NullPointerException like they String.class counterparts), :matches require a valid Pattern.

Built-in Case-insensitive String comparators

All String comparators they expect a String and are nil safe (don't throw NullPointerException like they String.class counterparts), :MATCHES require a valid Pattern.

Built-in Negation of String comparators

All String comparators they expect a String and are nil safe (don't throw NullPointerException like they String.class counterparts), :not-matches and :NOT-MATCHES require a valid Pattern.

Built-in numerical comparators

All numerical comparators are nil safe (don't throw NullPointerException) when one of the argument is nil.

Built-in comparators.

There are a number of common compartors which are provided as built-in functions. These comparators allow for much simpler and expressive code than their respective Clojure's counterparts. Additionally all built-in comparators have the following properties:

Comparators to work with Strings

| Comparator | Complement (not) | Case-insensitive | Insensitive Complement | | ————- | —————– | —————- | ———————- | | :is? | :is-not? | :IS? | :IS-NOT? | | :starts-with? | :not-starts-with? | :STARTS-WITH? | :NOT-STARTS-WITH? | | :ends-with? | :not-ends-with? | :ENDS-WITH? | :NOT-ENDS-WITH? | | :contains? | :not-contains? | :CONTAINS? | :NOT-CONTAINS? | | :in? | :not-in? | :IN? | :NOT-IN? | | :matches? | :not-matches? | :MATCHES? | :NOT-MATCHES? | | :matches-exactly? | :not-matches-exactly? | :MATCHES-EXACTLY? | :NOT-MATCHES-EXACTLY? | | :glob-matches? | :not-glob-matches? | :GLOB-MATCHES? | :NOT-GLOB-MATCHES? | | | | | |

| Comparator | Example | |————– | ———————————————— | | :is? | (where :country :is? "USA") | | :starts-with? | (where :country :starts-with? "US") | | :ends-with? | (where :country :ends-with? "SA") | | :contains? | (where :country :contains? "SA") | | :in? | (where :country :in? ["USA" "Italy" "France"]) | | :matches? | (where :country :matches? #"United.*") |

Comparators to work with Numbers

| Comparator | Complement (not) | |——————- | ———————- | | :between? | :not-between? | | :strictly-between? | :not-strictly-between? | | :range? | :not-range? | | :in? | :not-in? |

| Comparator | Example | True for | |——————- | —————————————– | ————– | | :between? | (where :age :between? [18 21]) | 18, 19, 20, 21 | | :strictly-between? | (where :age :strictly-between? [18 21]) | 19, 20 | | :range? | (where :age :range? [18 21]) | 18, 19, 20 | | :in? | (where :age :in? [18 20 22 24]) | 18, 20, 22, 24 |

Using where outside of maps.

where can be used also with numbers and strings. When the extractor doesn't apply then simply use the two-arity version of the function.

For example:

(filter (where > 5) (range 10))
;; => (6 7 8 9)

(filter (where ends-with "er") ["warrior" "singer" "player"])
;; => ("singer" "player")

See more examples.

Development

CI status: CircleCI

How to build.

Build profiles are by Clojure version:

lein build-all

TODOs

Here are things I'm considering to add.

License

Copyright © 2015 - 2018 Bruno Bonacci - Distributed under the Apache License v2.0