Skip to content

Commit

Permalink
mlib: fixed "(incf (gethash..." with default value, added frequencies
Browse files Browse the repository at this point in the history
  • Loading branch information
mayerrobert committed Dec 4, 2024
1 parent c858563 commit 23d17f9
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 6 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Changes in JMurmel-1.5.0 relative to JMurmel-1.4.8

* added fresh-line, make-string-writer, tabulate

* mlib: added format, formatter, error, and*, or*
* mlib: added format, formatter, error, and*, or*, frequencies
* fixed mlib: "(incf (gethash..." with default value


Changes in JMurmel-1.4.8 relative to JMurmel-1.4.7
Expand Down
3 changes: 2 additions & 1 deletion mlib.completions
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,5 @@ string-replace
string-subseq
maphash
remhash
gethash
gethash
frequencies
10 changes: 10 additions & 0 deletions mlib.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
- [scan](#function-scan), [scan-multiple](#function-scan-multiple), [scan-concat](#function-scan-concat)
- strings
- [string-trim](#function-string-trim), [string-subseq](#function-string-subseq), [string-replace](#function-string-replace), [string-split](#function-string-split), [string-join](#function-string-join)
- hash tables
- [frequencies](#function-frequencies)

## Description of functions and macros

Expand Down Expand Up @@ -1020,6 +1022,14 @@
Similar to CL's `maphash` but modifying the hash-table
from within `function` is not supported.

### Function: frequencies
(frequencies sequence [test]) -> hash-table

Since: 1.5

Count the number of times each value occurs in the sequence
according to the test function `test` which defaults to `eql`.

### Function: identity
(identity object) -> object

Expand Down
10 changes: 10 additions & 0 deletions mlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ as well as the following additional functions and macros:
- [scan](#function-scan), [scan-multiple](#function-scan-multiple), [scan-concat](#function-scan-concat)
- strings
- [string-trim](#function-string-trim), [string-subseq](#function-string-subseq), [string-replace](#function-string-replace), [string-split](#function-string-split), [string-join](#function-string-join)
- hash tables
- [frequencies](#function-frequencies)

## Description of functions and macros

Expand Down Expand Up @@ -1011,6 +1013,14 @@ Since: 1.4
Similar to CL's `maphash` but modifying the hash-table
from within `function` is not supported.

### Function: frequencies
(frequencies sequence [test]) -> hash-table

Since: 1.5

Count the number of times each value occurs in the sequence
according to the test function `test` which defaults to `eql`.

### Function: identity
(identity object) -> object

Expand Down
16 changes: 16 additions & 0 deletions samples.murmel-mlib/mlib-test.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,22 @@ all the result list to a single list. FUNCTION must return a list."
; => NIL
)

#+murmel
(defun hash-equal (h1 h2)
(if (= (hash-table-count h1) (hash-table-count h2))
(let ((ok t))
(maphash (lambda (k v)
(unless (eql v (hashref h2 k))
(setq ok nil)))
h1)
ok)
nil))

#+murmel
(tests frequencies
(hash-equal (frequencies '(1 2 2 3 3 3 4 4 4 4 5 5 5 5 5)) #H(eql 1 1 2 2 3 3 4 4 5 5)) => t
(hash-equal (frequencies #(1 2 2 3 3 3 4 4 4 4 5 5 5 5 5)) #H(eql 1 1 2 2 3 3 4 4 5 5)) => t)


;;; - higher order

Expand Down
28 changes: 24 additions & 4 deletions samples.murmel-mlib/mlib.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
;;; - [scan](#function-scan), [scan-multiple](#function-scan-multiple), [scan-concat](#function-scan-concat)
;;; - strings
;;; - [string-trim](#function-string-trim), [string-subseq](#function-string-subseq), [string-replace](#function-string-replace), [string-split](#function-string-split), [string-join](#function-string-join)
;;; - hash tables
;;; - [frequencies](#function-frequencies)


;;; == Description of functions and macros
Expand Down Expand Up @@ -1462,6 +1464,7 @@
(let ((read-var (gensym "read-var"))
(tmp1 (gensym "tmp1"))
(tmp2 (gensym "tmp2"))
(tmp3 (gensym "tmp3"))
(store-var (gensym "store-var")))
(if (symbolp place) `(nil nil (,read-var) (setq ,place ,read-var) ,place)
(let ((op (car place))
Expand Down Expand Up @@ -1492,22 +1495,22 @@

;; hashref with default value: setf (hashref h k def) - eval and ignore default value form
((and (eq 'hashref op) (cddr args))
`((,tmp1 ,tmp2)
`((,tmp1 ,tmp2 ,tmp3)
(,(car args) ,(cadr args) ,(caddr args))
(,store-var)
(hashset ,tmp1 ,tmp2 ,store-var)
(hashref ,tmp1 ,tmp2)))
(hashref ,tmp1 ,tmp2 ,tmp3)))

;; hashref w/o default value
((eq 'hashref op) (setf-helper args tmp1 tmp2 store-var 'hashref 'hashset))

;; gethash with default value: setf (gethash k hash def) - eval and ignore default value form
((and (eq 'gethash op) (cddr args))
`((,tmp1 ,tmp2)
`((,tmp1 ,tmp2 ,tmp3)
(,(cadr args) ,(car args) ,(caddr args))
(,store-var)
(hashset ,tmp1 ,tmp2 ,store-var)
(hashref ,tmp1 ,tmp2)))
(hashref ,tmp1 ,tmp2 ,tmp3)))

((eq 'gethash op)
`((,tmp1 ,tmp2)
Expand Down Expand Up @@ -2703,6 +2706,23 @@
(function (car pair) (cdr pair))))



;;; = Function: frequencies
;;; (frequencies sequence [test]) -> hash-table
;;;
;;; Since: 1.5
;;;
;;; Count the number of times each value occurs in the sequence
;;; according to the test function `test` which defaults to `eql`.
(defun frequencies (seq . test)
(let ((counts (make-hash-table (car test))))
(if (listp seq)
(dolist (x seq counts)
(incf (hashref counts x 0)))
(dovector (x seq counts)
(incf (hashref counts x 0))))))


; higher order ********************************************************

;;; = Function: identity
Expand Down

0 comments on commit 23d17f9

Please sign in to comment.