# MIT License, Copyright (c) 2022 Marvin Borner :import std/Char C :import std/Math . :import std/Number/Binary B :import std/Number/Conversion O :input std/List # returns true if two strings are the same eq? eq? B.eq? ⧗ String → String → Boolean …=?… eq? :test ("ab" =? "ab") (true) :test ("ab" =? "aa") (false) # prefix for comparing functions ?‣ &eq? # returns eq, gt, lt depending on comparison of two numbers compare-case B.compare-case' ⧗ a → b → c → String → String → d ‣ &compare-case # returns 1 if a>b, -1 if a… compare <=>‣ &compare :test (compare "2" "2") ((+0)) :test (compare "2" "1") ((+1)) :test (compare "1" "2") ((-1)) :test (compare "12" "1") ((+1)) :test (compare "1" "12") ((-1)) # returns true if string is lexically less than other string lt? c-lt? ∘∘ compare ⧗ String → String → Boolean …?… gt? :test ("1" >? "2") (false) :test ("2" >? "2") (false) :test ("3" >? "2") (true) # returns true if string is lexically less than or equal to other string le? not! ∘∘ gt? ⧗ String → String → Boolean …≤?… le? :test ("1" ≤? "2") (true) :test ("2" ≤? "2") (true) :test ("3" ≤? "2") (false) # returns true if number is greater than or equal to other string ge? \le? ⧗ String → String → Boolean …≥?… ge? :test ("1" ≥? "2") (false) :test ("2" ≥? "2") (true) :test ("3" ≥? "2") (true) # returns true if character is part of a string in? B.?in? ⧗ Char → String → Boolean …∈… in? ni? \in? ⧗ String → Char → Boolean …∋… ni? :test ('b' ∈ "ab") (true) :test ('c' ∈ "ab") (false) :test ("ab" ∋ 'b') (true) :test ("ab" ∋ 'c') (false) # converts a string of digits into a number string→unsigned-number list→number ∘ (map C.char→number) ⧗ String → Number :test (%(string→unsigned-number "123")) ((+123)) # converts a signed string of digits into a number string→signed-number [(sign ^0) (string→unsigned-number ~0)] ⧗ String → Number sign [(B.eq? 0 '-') -‣ i] :test (%(string→signed-number "+123")) ((+123)) :test (%(string→signed-number "-123")) ((-123)) # converts signed/unsigned number strings to a number string→number [C.lt? ^0 '0' signed unsigned] ⧗ String → Number signed string→signed-number 0 unsigned string→unsigned-number 0 :test (%(string→number "123")) ((+123)) :test (%(string→number "+123")) ((+123)) :test (%(string→number "-123")) ((-123)) # converts a number to a string number→string (map C.number→char) ∘ number→list ⧗ Number → String :test (number→string (+123)) ("123") # trims whitespace from the beginning and end of a string trim w b (reverse ∘ (drop-while (ni? "\t\r\n "))) ⧗ String → String :test (trim " ab ") ("ab") :test (trim "\t\r\nab\t\r\n") ("ab") # splits string by newline character lines z [[rec]] ⧗ String → (List String) rec build (break (B.eq? '\n') 0) build [~0 [[[^3 : (5 1)]]] {}(^0) ] :test (lines "ab\ncd") ("ab" : {}"cd") # concats list of strings with newline character unlines concat-map (\(…;…) '\n') ⧗ (List String) → String :test (unlines ("ab" : {}"cd")) ("ab\ncd\n") # slightly stretched DJB2 # WARNING: this may give weird results with/without padded zeros due to bad xor hash O.²³‣ ∘ (foldl [[B.xor! (B.mul (+33b) 1) (B.mul 0 (+208121b))]] (+5381b)) ⧗ String → Number #‣ &hash