All Projects β†’ vodori β†’ missing

vodori / missing

Licence: MIT License
A utility library for Clojure of functions and macros that complement clojure.core

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to missing

Awesome-Math-Learning
πŸ“œ Collection of the most awesome Math learning resources in the form of notes, videos and cheatsheets.
Stars: ✭ 73 (+180.77%)
Mutual labels:  topology, graph-theory
po-util
Classic Edition of po-util: The Ultimate Local Particle Experience for Linux and macOS
Stars: ✭ 51 (+96.15%)
Mutual labels:  utility
regenny
A reverse engineering tool to interactively reconstruct structures and generate header files
Stars: ✭ 58 (+123.08%)
Mutual labels:  utility
springboard
Springboard jumpstarts your projects for you. Hello, warp speed.
Stars: ✭ 13 (-50%)
Mutual labels:  utility
aspZip
A classic ASP zip and unzip utility class that uses the native zip support from Windows (XP and above) - no components needed
Stars: ✭ 24 (-7.69%)
Mutual labels:  utility
go-ethutil
Ethereum utility functions for Go.
Stars: ✭ 17 (-34.62%)
Mutual labels:  utility
dePAC
seamless Proxy Auto-Config (a.k.a. Web Proxy Auto Discovery) for CLI apps
Stars: ✭ 26 (+0%)
Mutual labels:  utility
everystreet
An algorithm finding #everystreet route on Open Street Map (OSMnx)
Stars: ✭ 43 (+65.38%)
Mutual labels:  graph-theory
Introduction-to-Discrete-Mathematics-for-Computer-Science-Specialization
[Coursera] Introduction to Discrete Mathematics for Computer Science Specialization
Stars: ✭ 71 (+173.08%)
Mutual labels:  graph-theory
pegjs-util
Utility Class for PEG.js
Stars: ✭ 29 (+11.54%)
Mutual labels:  utility
reminders-menubar
Simple macOS menu bar application to view and interact with reminders. Developed with SwiftUI and using Apple Reminders as a source.
Stars: ✭ 250 (+861.54%)
Mutual labels:  utility
bncsutil
The Classic Battle.netβ„’ client library
Stars: ✭ 19 (-26.92%)
Mutual labels:  utility
HashKode
Kotlin hashcode utilities
Stars: ✭ 15 (-42.31%)
Mutual labels:  utility
arr-flatten
Recursively flatten an array or arrays. This is the fastest implementation of array flatten.
Stars: ✭ 55 (+111.54%)
Mutual labels:  utility
goto
Goto - The Good Way to Program
Stars: ✭ 14 (-46.15%)
Mutual labels:  utility
rearmed rails
A collection of helpful methods and monkey patches for Rails
Stars: ✭ 34 (+30.77%)
Mutual labels:  utility
Graph-Theory
A workshop about implementing graph theory with Neo4j
Stars: ✭ 70 (+169.23%)
Mutual labels:  graph-theory
django-papertrail
django-papertrail - An elegant solution for keeping a relational log of events in a Django application.
Stars: ✭ 30 (+15.38%)
Mutual labels:  utility
vscode-jump
πŸƒβ€β™‚οΈ Jump/Select to the Start/End of a word in VSCode
Stars: ✭ 67 (+157.69%)
Mutual labels:  utility
to-no-case
Remove an existing case from a string.
Stars: ✭ 15 (-42.31%)
Mutual labels:  utility

Build Status Maven metadata URL codecov

Missing

A utility library for Clojure of functions and macros that complement clojure.core.

Install

[com.vodori/missing "0.1.28"]

Sample usages

Below are some examples of functions available in this library. For a full indication of what the library supports, please see the tests.


Comparable operators for more than numbers and O(n) scans

The existing <, >, <=, >= unfortunately only work on numbers. Use these for a more general alternative with similar semantics. If all you're looking for is the smallest or largest item, you shouldn't have to sort your sequence.

(require '[missing.core :refer :all])

(lt "a" "b") ;=> true
(lte "a" "a") ;=> true
(gt "b" "a") ;=> true
(gte "b" "b") ;=> true

(least ["a" "b" "c"]) ;=> "a"
(greatest ["a" "b" "c"]) ;=> "c"
(least-by :count [{:count 0} {:count 1} {:count -1}]) ;=> {:count -1}
(greatest-by :count [{:count 0} {:count 1} {:count -1}]) ;=> {:count 1}

Concurrent execution of forms

A little macro sugar on top of future to execute multiple independent tasks concurrently and return a sequence of their results.

(require '[missing.core :refer :all])

(zipmap [:users :posts] (together (get-users) (get-posts)))

Combinatorics

(require '[missing.core :refer :all])

(subsets #{1 2 3}) 
;=> #{#{} #{1} #{2} #{3} #{1 2} #{2 3} #{1 2 3}}

(submaps {:a 1 :b 2 :c 3}) 
;=> {} {:a 1} {:c 3} {:b 2} {:c 3, :b 2} {:b 2, :a 1} {:c 3, :a 1} {:c 3, :b 2, :a 1}

(intersect? #{1 2 3} #{1 3} #{1}) 
;=> true

(exclusive? #{1 2 3} #{4 5} #{6}) 
;=> true

Lazy merge sort

Create a single sorted sequence by lazily interleaving already sorted sequences.

(require '[missing.core :refer :all])

(def x [:a :c :d :e :i])
(def y [:b :f :g :h])
(merge-sort [x y]) ;=> [:a :b :c :d :e :f :g :h :i]

Indexing collections

Use these when you're building lookup tables to efficiently perform batch operations.

(require '[missing.core :refer :all])

(def users 
    (index-by :username 
        [{:username "fred" :email "[email protected]"} 
         {:username "greg" :email "[email protected]"}])

(get users "fred") 
;=> {:username "fred" :email "[email protected]"}


(def resources 
  [{:meta {:app "sso" :version "2018-10" :stage "dev"}}
   {:meta {:app "db" :version "2018-07" :stage "prod"}}
   {:meta {:app "api" :version "2018-07" :stage "dev"}}])
    
(def table (group-by-labels :meta resources))

(get table {:version "2018-10"})
;=> [{:meta {:app "sso" :version "2018-10" :stage "dev"}}]

(get table {:stage "dev"}) 
;=> [{:meta {:app "sso" :version "2018-10" :stage "dev"}}
;    {:meta {:app "api" :version "2018-07" :stage "dev"}}]

(get table {:version "2018-07" :stage "dev"}) 
;=> [{:meta {:app "api" :version "2018-07" :stage "dev"}}]


(let [pk1           "[email protected]"
      pk2           "[email protected]"
      person-info  [{:id pk1 :name "Paul" :age 26}
                    {:id pk2 :name "Raul" :age 62}]
      account-info [{:email pk1 :year-joined 2018}
                    {:email pk2 :year-joined 8102}]]
  (collate [[:id person-info] [:email account-info]])))
  
;=> {"[email protected]"
;    [{:id "[email protected]", :name "Raul", :age 62}
;      {:email "[email protected]", :year-joined 8102}],
;
;    "[email protected]"
;    [{:id "[email protected]", :name "Paul", :age 26}
;     {:email "[email protected]", :year-joined 2018}]}

Locking by value

Clojure has lots of great ways to deal with state. Reference locking is probably least among them but if the use case is isolated and the exclusive operation involves side effects (can't run in a CAS loop) sometimes it's an appropriate choice. Missing provides reentrant locks that lock on values so you can ensure different parts of your program never act on behalf of the same value (often an identifier) at the same time.

(require '[missing.locks :as locks])

(locks/locking "user-id" (update-user user))

; you can also subdivide the exclusive scope by wrapping 
; evaluation with your own lock tables (a map in an atom)

(def profile-locks (atom {}))

(locks/with-locks profile-locks
  (locks/locking "user-id" (update-user user)))

Transducers: distinct-by and dedupe-by

The xxx-by transducers are, in my opinion, always preferable to a xxx transducer. The reason being that xxx-by degrades into xxx when f is identity and so is equivalent but more powerful.

(require '[missing.core :refer :all])

(distinct-by :x [{:x 1} {:x 2} {:x 1}]) ;=> [{:x 1} {:x 2}]

(dedupe-by :x [{:x 1} {:x 1} {:x 2} {:x 1}]) ;=> [{:x 1} {:x 2} {:x 1}]

Transducer: contiguous-by

Sometimes you have a sequence of elements that are potentially overlapping / abutting. You might want to merge these segments into one item instead. This transducer just wraps partition-by with one-dimensional overlap tracking to chunk the sequence into contiguous segments. It works on any comparables and is lazy.

(require '[missing.core :refer :all])

(def flat [{:x1 0 :x2 4} {:x1 1 :x2 5} {:x1 5 :x2 6} {:x1 10 :x2 12}])

(contiguous-by :x1 :x2 flat)
;=> [[{:x1 0 :x2 4} {:x1 1 :x2 5} {:x1 5 :x2 6}] [{:x1 10 :x2 12}]]

; after this you'll probably perform a map to merge the
; contiguous items in each partition into one element

Preemptables

Sometimes you want to bail on further computation if you happen to discover a result early but you don't want to restructure your code to plan for the early termination. Preemptables offer a generic solution to this problem by utilizing exceptions as a pseudo-continuation.

(require '[missing.core :refer :all])

; preemptable marks the place that preempt can provide a value for.
; preempt provides a value and throws to unwind the stack rather than
; continue the computation. If you never call preempt then the return
; value is equal to the result of the entire evaluation.

(preemptable
 (dotimes [x 1000]
   (if (and (pos? x) (even? x))
     (preempt x)
     x)))
; => 2

Structural Selections

Sometimes you want flat data that describes the structure of nested data. Missing provides a path protocol and implementations to extract a path to each leaf in a piece of data. There's even a function that will "select" a given structure from another piece of data by example.

(require '[missing.core :refer :all])

(index-values-by-paths {:a [:b {:c :d}]})
; => {[:a 0] :b, [:a 1 :c] :d}

(select-structure 
  ; data to extract from
  {:a [1 {:test [4 [{:one 5}]]}] :extra :stuff}
  ; example structure to use for the extraction
  {:a [:b {:test [:thing [{:one :two :three 4}]]} :d]})
  
; => {:a [1 {:test [4 [{:one 5 :three nil}]]} nil]}

Graph Functions

The missing.topology namespace contains simple implementations of many basic graph functions. Every function that takes a graph accepts just a plain adjacency map (map of node to list of nodes it has edges to). If your nodes don't have value semantics then you should just use a graph of identifiers and perform lookups back to your objects.

Perhaps most generally useful are the topological sorts:

(require '[missing.topology :refer :all])

; define an adjacency graph with edges indicating
; left 'is a requirement of' right
; a is a requirement of b and c
; b is a requirement of d
(def g {:a [:b :c] :b [:d]})

; sort them into phases where items
; in each phase can be resolved 
; concurrently
(topological-sort-with-grouping g) 
; => [#{:a} #{:c :b} #{:d}]

; If you'd rather, you could define
; an adjacency graph with edges indicating
; left 'depends on' right
; b depends on a
; c depends on a
; d depends on b

(def g' {:b [:a] :c [:a] :d [:b]})

; and just invert it before sorting:
(topological-sort-with-grouping (inverse g')) 
; => [#{:a} #{:c :b} #{:d}]

License

This project is licensed under MIT license.

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].