nicheware.platform.utilities.common.core

This namespace contains functions that complement those in clojure.core, operating on the main clojure collections and data types.

There are groups of functions within common.core that deal with:

Function group Functions
slicing collections slice, slice-wrap, remove-slice, remove-slice-wrap, filter-count
collection inserts insert-before, insert-after, replace-at
integer functions range-of-range, negate, snap
general sequence functions rotate-seq, selective-merge, pad-with, seq-of
collection searching find-first, find-last, find-index, find-last-index, find-nth, replace-leading-nils
map utility deep-merge, dissoc-in, index-by
map transform map-values, map-keys, map-all-keys
map filtering filter-val, filter-key, filter-remove-val, remove-nil, remove-empty
vector functions vec-remove-nil, find-by-pred, find-element, replace-element-by-pred, replace-element
string functions after, before, before-last, str-to-int
cross-platform functions rand-uuid, parse-int, current-time-millis, edn-read
function composition compose-fns
exceptions throw-illegal-arg
threading macros cond-t

after

(after strn after-value)

Returns the substring after the first occurrence of the given substring.

  • strn: String to be examined.
  • after-value: Substring within strn to search for.
  • returns: substring after ‘after-value’ or nil if not found.

eg:

  (after "prefix-end-suffix" "-end-")  =>  "suffix"

assoc-in-thread-last

(assoc-in-thread-last keys value hash-map)

Version of assoc-in for use with ->> where the collection must be the last item. Just does a simple reordering of the arguments.

  • keys: Sequence of keys identifying new key path to add to map.
  • value: New value to be associated with final key in the path.
  • hash-map: Existing map that key to be added to.
  • returns: New map with addition of specified nested key and value.

before

(before strn before-value)

Returns the substring before the first occurrence of the given substring.

  • strn: String to be examined.
  • before-value: Substring within strn to search for.
  • returns: substring before ‘before-value’ or nil if not found.

eg:

  (before "prefix-end-next-end" "-end")  =>  "prefix"

before-last

(before-last strn before-value)

Returns the substring before the last occurrence of the given substring.

  • strn: String to be examined.
  • before-value: Substring within strn to search for.
  • returns: last substring before ‘before-value’ or nil if not found.

eg:

  (before-last "prefix-end-next-end" "-end")  =>  "prefix-end-next"

compose-fns

(compose-fns coll-fns)

Performs a compose of the functions in a given collection. It will execute the functions in order of first to last in the collection (which is different from the clojure compose which executes from right to left.)

  • coll-fns: Collection of functions to be composed, left to right.
  • returns: single function equivalent to composition of given functions.

eg:

  ((compose-fns [inc #(Mth.abs %)]) -1)  => 0

cond-t

macro

(cond-t val pred-fn map-fn)

Macro for use in threading (as expr in ->). It allows a mapping function to be conditionally applied if the predicate function is true.

  • val - value to be tested - will come from the threading macro
  • pred-fn - predicate function which will be given val, or it could be any non-function expression - which would be tested for truthy
  • map-fn - Executed on the value if the pred-fn or expression is true and then returned as threading value.

Otherwise val returned untouched.

eg:

  (-> end
      (cond-t #(> start %) inc)
      ...)

current-time-millis

(current-time-millis)

Returns the current time in millis, as appropriate for the platform.

deep-merge

(deep-merge & maps)

Like merge, but merges maps recursively. At each level in any nested maps, keys in the initial map will be replaced by keys from subsequent maps.

  • Variable number of arguments, each being a map to be merged from left-to-right
  • returns: New map which is deep merge of all argument maps.

eg:

(deep-merge {:one 1 :two 2 :nested {:three 3 :nested {:four 4 :five 5}}}
            {:two 4 :nested {:three 4 :nested {:four 5}}})

=>

{:one 1 :two 4 :nested {:three 4 :nested {:four 5 :five 5}}

dissoc-in

(dissoc-in hmap key-path)

Performs a dissoc of the nested key. It only removes the last key in the path of keys.

  • hmap: Map to be modified.
  • key-path: Sequence of keys, defining nested path in map.
  • returns: New map where final key in key-path has been removed.

eg:

(dissoc-in {:one {:two {:three 3 :four 4}}} [:one :two :three]) =>   {:one {:two {:four 4}}}

edn-read

(edn-read str)

Cross platform edn string reader.

  • str: edn formatted string to be parsed.
  • returns: Clojure data read from edn string.

filter-count

(filter-count coll n)

Take exactly count elements from the collection, including first and last as well as [count - 2] from the remaining collection elements, skipping elements as evenly as possible.

  • coll: Collection to filter from
  • n: Number of elements to extract from collection.
  • returns: lazy sequence with n elements extracted from coll.

eg:

(filter-count [1 2 3 4 5 6 7] 4)  =>  [1 3 5 7]

filter-key

(filter-key fn value-map)

Returns a map with only the entries where (fn key) is true.

  • fn: Function which should accept a single argument (the key of each map entry) and return boolean true if entry to be kept.
  • value-map: Hash map to be filtered.
  • returns: New map containing only entries where (fn key) is true.

filter-remove-key

(filter-remove-key fn value-map)

Returns a map where any key where (fn key) is true, is removed (0.8 usec)

  • fn: Function which should accept a single argument (the key of each map entry) and return boolean true if entry to be removed.
  • value-map: Hash map to be filtered.
  • returns: New map containing only entries where (fn key) is false.

filter-remove-val

(filter-remove-val fn value-map)

Returns a map where any key where (fn val) is true, is removed (0.8 usec)

  • fn: Function which should accept a single argument (the value of each map entry) and return boolean true if entry to be removed.
  • value-map: Hash map to be filtered.
  • returns: New map containing only entries where (fn value) is false.

filter-val

(filter-val fn value-map)

Returns a map with only the entries where (fn value) is true.

  • fn: Function which should accept a single argument (the value of each map entry) and return boolean true if entry to be kept.
  • value-map: Hash map to be filtered.
  • returns: New map containing only entries where (fn value) is true.

find-by-pred

(find-by-pred coll pred)

Finds and returns the first element in the collection that satisfies the given predicate.

  • coll: Collection to be searched.
  • pred: function which accepts a single value (an element from the collection) and returning true for the required element.
  • returns: The first element from the collection that matches the predicate. Maps will be tested and returned as vector elements of the form [key value] nil if nothing found.

find-element

(find-element coll id-key id)

Finds the element in the collection of maps, which has the specified value for the given key.

  • coll: Collection of maps to be searched.
  • id-key: Key to access in each map of the collection.
  • id: Expected value of the key in map of matching element.
  • returns: Map from coll that has id-key with value of id. nil if not found.

eg:

(find-element [{:id 1 :value 10} {:id 2 :value 100}] :id 1) => {:id 1 :value 10}

find-first

(find-first coll pred)

Find first value that satisfies predicate.

  • coll: Collection to be searched.
  • pred: Predicate function accepting a value from coll, returning true if matches required condition.
  • returns: First element from coll that matches the predicate. nil if nothing found.

find-index

(find-index coll element)(find-index coll element compare-fn)

Find the first index of the given element in the collection, using the given compare-fn (which defaults to equality).

  • coll: Collection to be searched.
  • element: Element to compare to elements in collection until match is found.
  • compare-fn: Optional 3-arity argument. Function used to match element with those in coll. It should take two args, which will be the item in the list and the element to match. If not present, then an equality comparison is performed.
  • returns: The index of the first element in coll which results in true from the compare-fn. nil if no match.

eg:

(find-index [10 20 30 40] 30)  => 2

find-index-by-pred

(find-index-by-pred coll pred)

Find the first index of the element in the collection, using the given predicate.

  • coll: Collection to be searched.
  • pred: Predicate function accepting a value from coll, returning true if matches required condition.
  • returns: Index of first element from coll that matches the predicate. nil if no match.

find-indexes

(find-indexes coll element)(find-indexes coll element compare-fn)

Find the all indexes of the element in the collection, using the given compare-fn (which defaults to equality)

  • coll: Collection to be searched.
  • element: Element to compare to elements in collection.
  • compare-fn: Optional 3-arity argument. Function used to match element with those in coll. It should take two args, which will be the item in the list and the element to match. If not present, then an equality comparison is performed.
  • returns: Lazy sequence of all the indexes of elements in coll which result in true from the compare-fn. Empty sequence if no match.

eg:

(find-index [10 20 30 40 30] 30)  => (2, 4)

find-indexes-by-pred

(find-indexes-by-pred coll pred)

Find all the indexes of the elements in the collection matching the given predicate.

  • coll: Collection to be searched.
  • pred: Predicate function accepting a value from coll, returning true if matches required condition.
  • returns: Lazy sequence of indexes of elements from coll that match the predicate. Empty sequence if no match.

find-last

(find-last coll pred)

Find last value that satisfies predicate.

  • coll: Collection to be searched.
  • pred: Predicate function accepting a value from coll, returning true if matches required condition.
  • returns: Last element from coll that matches the predicate. Will examine all elements in coll. nil if no match.

find-last-index

(find-last-index coll element)(find-last-index coll element compare-fn)

Find the index of the matching element in the collection, using the given compare-fn (which default to equality)

  • coll: Collection to be searched.
  • element: Element to compare to elements in collection for match.
  • compare-fn: Optional 3-arity argument. Function used to match element with those in coll. It should take two args, which will be the item in the list and other the element to match. If not present, then an equality comparison is performed.
  • returns: The index of the last element in coll which results in true from the compare-fn. nil if no match.
(find-last-index [10 20 30 40 30] 30)  => 4

find-last-index-by-pred

(find-last-index-by-pred coll pred)

Find the last index of the element in the collection, using the given predicate.

  • coll: Collection to be searched.
  • pred: Predicate function accepting a value from coll, returning true if matches required condition.
  • returns: Last index of first element from coll that matches the predicate. nil if no match.

find-nth

(find-nth seq index)

Will return nth element of sequence, or return nil if the index is < 0 or >= number elements, rather than exception returned by clojure core nth.

  • seq: sequence to access. Must return true to sequential?
  • index: 0 based index of element in seq to return.
  • returns: nth element in sequence or nil if invalid index.

index-by

(index-by coll key-fn)

Generates a map indexed by the value identified by the key applied to each element in the collection. Can be used to convert a vector of maps to a map indexed by a specific key by supplying the key as the function. (from juxt doc examples)

  • coll: Collection of maps.
  • key-fn: Fn used to select an element from each map in the collection. eg Could be just a key.
  • returns: New map with an entry for each element in coll, where the key is the key of the attribute selected by key-fn and the value is the original map.

eg:

(index-by [{:id 1} {:id 2}] :id) => {1 {:id 1} 2 {:id 2}}

insert-after

(insert-after coll ins-after elements)

Insert the given list after the 0-based index. To insert at the start of the list use -1 or insert-before.

  • coll: Collection to be inserted into.
  • ins-after: Index of element in coll that elements will be inserted after. (0 based)
  • elements: collection of elements to be inserted
  • returns: lazy sequence consisting of coll with elements inserted as specified.

insert-before

(insert-before coll ins-before elements)

Insert the given list into the position just before the specified 0-based index. To prepend to list use 0. To append to list use list length or more.

  • coll: Collection to be inserted into.
  • ins-before: Index of element in coll that elements will be inserted before. (0 based)
  • elements: collection of elements to be inserted
  • returns: lazy sequence consisting of coll with elements inserted as specified.

is-empty?

(is-empty? v)

Returns true for nil or empty collection. Any non-seqable data type will not be true.

  • v: data element to be tested.
  • returns: true if v is nil or empty collection. False also if non-seqable data type.

map-all-keys

(map-all-keys map-fn value-map)

Transforms the keys in the map and nested maps using the given function.

  • fn: Function used to transform the keys. Takes a single argument, the existing key, returning a new key value.
  • value-map: Map to be transformed.
  • returns: New map, with all keys, including keys in nested maps, transformed by fn. Handles nil value-map, returning nil

map-keys

(map-keys map-fn value-map)

Transforms the top-level keys in the map using the given function. Uses for-map. (14.564 usec).

  • fn: Function used to transform the keys. Takes a single argument, the existing key, returning a new key value.
  • value-map: Map to be transformed.
  • returns: New map, with all top-level keys in value-map transformed by fn. Handles nil value-map, returning nil

map-remove-nil

(map-remove-nil value-map)

Removes all top-level entries with nil values from the map. Uses dissoc, so reuse of map data will be maximised (.8 usec).

Alternate name for remove-nil for backwards compatibility.

map-values

(map-values map-fn hmap)

Peforms a map over the values of the hash-map, returning a new hashmap with same keys and updated values.

  • map-fn: Function to be applied to all values in the hash-map. Should accept a single argument (value) and return new value.
  • hmap: The hash-map to be traversed
  • returns: New hash map with all values modified by the map-fn.

max-length

(max-length max)

Create a predicate function to ensure maximum length of string or collection is max.

  • max: Integer value to be used in predicate as max length.
  • returns: predicate function accepting a countable data structure, returning true if count is less than or equal to max.

eg:

(filter (max-length 5) ["123456" "123"]) => ("123")

min-length

(min-length min)

Create a predicate function to ensure minimum length of string or collection is min.

  • min: Integer value to be used in predicate as min length.
  • returns: predicate function accepting a countable data structure, returning true if count is greater than or equal to min.

eg:

(filter (min-length 5) ["123456" "123"]) => ("123456")

negate

(negate number)

Negate the number (int or real)

  • number: Int or real number to be negated.
  • returns: negated number.

nth-items

(nth-items coll indexes)

Selects all the given indexes from the supplied collection.

  • coll: Collection from which to extract indexed elements.
  • indexes: collection of indexes. Each is used to extract the nth element from coll
  • returns: lazy-sequence of elements extracted from coll

pad-with

(pad-with seq value new-size)

Pads the collection with the given value to make up to the final count.

  • seq: Collection to be padded.
  • value: Value to pad with.
  • new-size: New size of seq, to be padded to this size using value.
  • returns: Newly padded lazy sequence. Original collection returned if new-size less than or equal to current seq size. Maps will return a sequence of vectors with [key value] then padded with the pad value.

eg:

(pad-with [1 2 3] 0 6) => (1 2 3 0 0 0)

parse-int

(parse-int string-int)

Platform independent int parser.

Will fail on invalid characters, including digits with trailing non-digits, which standard Javascript does not.

  • string-int: String representation of integer
  • returns: integer version of string. If no valid integer returns nil

uses:

  • Integer/parseInt for Clojure
  • js/parseInt for ClojureScript.

rand-uuid

(rand-uuid)

Platform independent uuid generator. java.util.UUID/randomUUID for Clojure and random-uuid for ClojureScript.

  • returns: random integer

range-of-range

(range-of-range {:keys [start end], :as range-spec})

Returns a lazy clojure range using the given {:start ... :end} range map where the values are inclusive (unlike Clojure range which is exclusive of the end)

  • range-spec: {:start <range-start-inclusive> :end <range-end-inclusive}
  • returns: lazy sequence from start to end inclusive. Empty if either start or end missing.

remove-empty

(remove-empty value-map)

Removes all top-level entries which are empty collections or nil values from the map. Uses dissoc, so reuse of map data will be maximised (.8 usec).

Uses the is-empty? function from this lib, so will retain values which are non-seqable.

  • value-map: Map for which entries with empty values to be removed.
  • returns: New map with no empty value entries.

remove-nil

(remove-nil value-map)

Removes all top-level entries with nil values from the map. Uses dissoc, so reuse of map data will be maximised (.8 usec)

  • value-map: Map for which entries with nil values to be removed.
  • returns: New map with no nil value entries.

remove-slice

(remove-slice coll start end)(remove-slice coll remove-range)

Removes the slice specified by {:start :end} with same defaults and semantics as described for slice.

If range is not able to be clamped to be valid, returns original collection.

  • coll: Collection to be sliced.
  • remove-range: 2 arity argument, either a map {:start <default 0> :end <default end-coll>} or vector [start end]
  • start: 3 arity argument, index (0 based) of inclusive start of slice to remove.
  • end: 3 arity argument, index (0 based) of inclusive end of slice to remove
  • returns: lazy sequence with slice removed.

eg:

(remove-slice [0 1 2 3 4] 1 3)  => (0 4)
(remove-slice [0 1 2 3 4] {:start 3})  => (0 1 2)
(remove-slice [0 1 2 3 4] {:start 1 :end 7})  => (0)
(remove-slice [0 1 2 3 4] [1 3])  => (0 4)
(remove-slice [0 1 2 3 4] {:start 3 :end 2}) => nil

remove-slice-wrap

(remove-slice-wrap coll start end)(remove-slice-wrap coll range)

Removes the slice but handles wrapping, so that start can be greater than end, in which case it removes from start to last of vec and from beginning of vec to end.

See remove-slice for details on arguments. eg:

(remove-slice-wrap [0 1 2 3 4] {:start 3 :end 1}) => (2)

replace-at

(replace-at coll rep-at elements)

Replaces all elements starting at the given element with the new elements. May extend the sequence if the new elements run longer then the existing sequence.

  • coll: Collection containing elements to be replaced into
  • rep-at: Index of element in coll that replacement to start (0 based)
  • elements: Elements to be used to replace existing elements in coll
  • returns: lazy sequence with coll elements replaced by elements as specified.

eg:

  (replace-at [1 2 3 4] 3 [5 6 7]) =>  (1 2 3 5 6 7)

replace-at-wrap

(replace-at-wrap coll rep-at elements)

Replaces elements in the given collection with the new elements, starting at the given index. If the number of new elements would extend past the end of the collection, the replacement wraps, starting at the beginning of the collection.

See replace-at for details on arguments. eg

(replace-at-wrap [1 2 3 4] 3 [5 6 7]) =>  (6 7 3 5)

replace-element

(replace-element vec replacement-element id-key)(replace-element vec replacement-element id-key id)

Replaces a map element of a vector, given a new one and the keyword of the unique identifying attribute in the map.

  • vec: vector in which element is to be replaced.
  • replacement-element: New element to put into vector
  • id-key: The key in the element which is to be used as the matching unique identifier.
  • id: Optional id, identifying the element to be replaced. If not supplied will use the id-key value from the given replacement-element.

eg:

(replace-element [{:id 1 :value 100} {:id 2 :value 200}] {:id 1 :value 1000} :id)
  => [{:id 1 :value 1000} {:id 2 :value 200}]

(replace-element [{:id 1 :value 100} {:id 2 :value 200}] {:id 1 :value 1000} :id 2)
  => [{:id 1 :value 100} {:id 1 :value 1000}]

replace-element-by-pred

(replace-element-by-pred vec replacement-element pred)

Replaces an element of a vector, given a new one and a predicate fn that must return true on the element to be replaced. Will only replace the first element matched.

  • vec: Vector to have element replaced
  • replacement-element: New element to replace the found element.
  • pred: Function taking a single argument (element in the vec), returning true if it is the one to replace.
  • returns: new vector with first matching element replaced by replacement-element. Same as original vector if no match.

replace-leading-nils

(replace-leading-nils coll val)

Replaces all leading nils in the collection with the given value.

  • coll: Collection to be examined for nils.
  • val: Value to replace leading nils with.
  • return: vector of values in collection with leading nils replaced by val. If coll is a map it will return a vector of vectors [key value], with no replacements.

eg

(replace-leading-nils [nil nil 1 2 3] 0) => [0 0 1 2 3]

replace-trailing-nils

(replace-trailing-nils coll val)

Replaces all trailing nils in the collection with the given value.

  • coll: Collection to be examined for nils.
  • val: Value to replace trailing nils with.
  • return: vector of values in collection with trailing nils replaced by val. If coll is a map it will return a vector of vectors [key value], with no replacements.

eg:

  (replace-trailing-nils [1 2 3 nil nil] 0) => (1 2 3 0 0)

rotate-seq

(rotate-seq index coll)

Rotates the collection so that the selected index is the new first item in the collection.

  • index: 0 based index at which rotation to start in coll
  • coll: collection to be rotated.
  • returns: lazy sequence of rotated collection. Maps will return list of [key, value] vectors.

eg:

  (rotate-seq 2 [0 1 2 3 4 5]) => (2 3 4 5 0 1)

selective-merge

(selective-merge fst snd selections)

Accept two collections and a truthy collection, all with the same number of values and replaces the first with the second, only if the matching selection sequence has is true. Otherwise retains the first collection.

  • fst: First collection, values will be used if selection entry is false.
  • snd: Second collection, values will be used if selection entry is true.
  • selections: Same size as fst and snd, with true, false values, used as described above.
  • returns: lazy sequence, same size as fst and snd, with merged values according to selections. Maps will retrurn elements as [key value] vectors in the lazy sequence.

eg:

(selective-merge [1 2 3 4] [5 6 7 8] [true false true false]) => (5 2 7 4)

seq-of

(seq-of value n)

Creates a lazy sequence filled with the given value n times.

  • value: Value to be repeated.
  • n: Number of times to repeat value
  • returns: Lazy sequence with value repeated n times.

slice

(slice coll start end)(slice coll range)

Select the elements from the collection based on the supplied start and end range. start and end are 0 based and inclusive.

  • coll: Collection to be sliced
  • range: 2 arity argument, either a map {:start <default 0> :end <default end-coll>} or vector [start end]
  • start: 3 arity argument, start index of slice.
  • end: 3 arity argument, end index of slice.
  • returns: lazy sequence from start to end

It will attempt to make a valid start and end (eg set start to 0 if < 1 and end to last index in the collection if too large). If range is not able to be made valid, returns nil.

eg:

(slice [0 1 2 3 4] 1 3)  => (1 2 3)
(slice [0 1 2 3 4] {:start 3})  => (3 4)
(slice [0 1 2 3 4] [1 7])  => (1 2 3 4)
(slice [0 1 2 3 4] {:start 1 :end 7})  => (1 2 3 4)
(slice [0 1 2 3 4] {:start 3 :end 2}) => nil

slice-wrap

(slice-wrap coll start end)(slice-wrap coll range)

Performs a slice but handles wrapping around the vector if the start is after end.

See slice for details on arguments.

eg:

(slice-wrap [0 1 2 3 4] {:start 3 :end 1}) => (3 4 0 1)

snap

(snap number)

Snaps the number to its biggest magnitude from 0. This means a ceiling for positive numbers and a floor for negative numbers

  • number: integer to be snapped.
  • returns: snapped integer

str-to-int

(str-to-int string-value)

Returns the given string value as an integer, using the platform specific parseInt. Returns nil if any format errors.

Alternate name for parse-int.

  • string-value: Value to be converted to an integer
  • returns: Integer value of string, or nil on format errors.

throw-illegal-arg

(throw-illegal-arg message)

Throws an IllegalArgumentException, as appropriate for the platform.

  • message: Message to be included as part of response.
  • throws for Clojure: java.lang.IllegalArgumentException
  • throws for ClojureSciprt: js/Error with the string “IllegalArgumentException” in the message.

vec-remove-nil

(vec-remove-nil vec)

Removes any entries that are nil from given vector, returning a vector.

  • vec: Vector to have nils removed.
  • returns: new vector containing only the original non-nil values.

eg:

(vec-remove-nil [1 nil 3 nil 4]) => [1 3 4]