syndicate-rkt/syndicate/bag.rkt

76 lines
2.3 KiB
Racket
Raw Normal View History

; SPDX-License-Identifier: LGPL-3.0-or-later
; Copyright (C) 2010-2021 Tony Garnock-Jones <tonygarnockjones@gmail.com>
#lang racket/base
;; Bags and Deltas (which are Bags where item-counts can be negative).
2018-04-27 08:55:19 +00:00
(provide make-bag ;; mutable
bag ;; immutable
bag-change!
2018-04-27 08:55:19 +00:00
bag-change
bag-ref
bag-clear!
2018-04-19 16:55:52 +00:00
bag-member?
2018-05-02 17:20:24 +00:00
bag-empty?
2018-04-29 15:08:01 +00:00
bag-key-count
2018-04-19 16:55:52 +00:00
in-bag
2018-04-27 08:55:19 +00:00
in-bag/count
2018-05-03 21:09:13 +00:00
for/bag/count
for/bag
2018-04-27 22:53:31 +00:00
set->bag
bag->set)
2018-04-27 08:55:19 +00:00
(require racket/set)
;; A `(MutableBagof X)` is a `(MutableHash X Nat)`, where the `Nat`
;; against an `X` is its replication count in the bag.
;;
;; A `(Bagof X)` is similar, but immutable.
;;
;; `MutableDeltaof` and `Deltaof` are like `MutableBagof` and `Bagof`,
;; respectively, except the replication counts can be negative.
(define make-bag make-hash)
2018-04-27 08:55:19 +00:00
(define bag hash)
(define (bag-change! b x delta)
(define old-count (bag-ref b x))
(define new-count (+ old-count delta))
(if (zero? new-count)
(begin (hash-remove! b x)
(if (zero? old-count) 'absent->absent 'present->absent))
(begin (hash-set! b x new-count)
(if (zero? old-count) 'absent->present 'present->present))))
(define (bag-change b x delta #:clamp? [clamp? #f])
2018-04-27 08:55:19 +00:00
(define old-count (bag-ref b x))
(define new-count (if clamp?
(max 0 (+ old-count delta))
(+ old-count delta)))
2018-04-27 08:55:19 +00:00
(if (zero? new-count)
(values (hash-remove b x)
(if (zero? old-count) 'absent->absent 'present->absent))
(values (hash-set b x new-count)
(if (zero? old-count) 'absent->present 'present->present))))
(define (bag-ref b x)
(hash-ref b x 0))
(define bag-clear! hash-clear!)
2018-04-19 16:55:52 +00:00
(define bag-member? hash-has-key?)
2018-05-02 17:20:24 +00:00
(define bag-empty? hash-empty?)
2018-04-29 15:08:01 +00:00
(define bag-key-count hash-count)
2018-04-19 16:55:52 +00:00
(define-syntax-rule (in-bag piece ...) (in-hash-keys piece ...))
(define-syntax-rule (in-bag/count piece ...) (in-hash piece ...))
2018-04-27 08:55:19 +00:00
2018-05-03 21:09:13 +00:00
(define-syntax-rule (for/bag/count iters expr ...) (for/hash iters expr ...))
(define-syntax-rule (for/bag iters expr ...) (for/bag/count iters (values (begin expr ...) 1)))
(define (set->bag s [count 1])
2018-04-27 08:55:19 +00:00
(for/hash [(e (in-set s))]
(values e count)))
2018-04-27 22:53:31 +00:00
(define (bag->set b)
(list->set (hash-keys b)))