aboutsummaryrefslogtreecommitdiff
path: root/lib/functions.lisp
blob: 073e34a634011477a7f1ad5f117a96aca150970f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
;;; lib.functions.lisp - 2025-02-09

;; Copyright (C) 2025 Aryadev Chavali

;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License Version 2 for
;; details.

;; You may distribute and modify this code under the terms of the GNU General
;; Public License Version 2, which you should have received a copy of along with
;; this program.  If not, please go to <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Helpful functions for usage throughout the project.

;;; Code:

(in-package :cantedraw.lib.functions)

(fn range (start end &optional (step 1)) (-> (fixnum fixnum &optional fixnum) list)
  "Make a list of numbers from START to END (exclusive).  If STEP is given, then
each member is STEP distance apart."
  (if (< end start)
      (error (format nil "~a < ~a" end start))
      (loop :for i :from start :to (1- end) :by step
            :collect i)))

(fn take (n lst) (-> (fixnum sequence) sequence)
  "Return the first N elements of LST."
  (subseq lst 0 n))

(fn split (n lst) (-> (fixnum sequence) (values sequence sequence))
  "Return CONS where CAR is the first N elements of LST and CDR is the rest."
  (values (take n lst)
          (subseq lst n)))

(fn rev-map (indicator lst &key (key-eq #'eq))
    (-> (function list &key (:key-eq function)) list)
  "Given LST and INDICATOR: LST -> A, return an association list A -> 2^LST
where key x in A has associations {y in LST : INDICATOR(y) = x}."
  (loop :with assoc-list := nil
        :for element :in lst
        :for key := (funcall indicator element)
        :if (assoc key assoc-list :test key-eq)
          :do (->> (alist-val key assoc-list)
                   (cons element)
                   (setf (alist-val key assoc-list)))
        :else
          :do (setq assoc-list (cons (list key element) assoc-list))
        :finally (return assoc-list)))

(fn parse-integer* (inp) (-> (string) (or integer list))
  "Given string INP, attempt to parse an integer.  Return NIL otherwise."
  (parse-integer inp :junk-allowed t))

(fn remove-at-indices (indices lst) (-> (list list) list)
  (loop :for i :from 0 :to (1- (length lst))
        :for item :in lst
        :if (not (member i indices))
          :collect item))