https://github.com/digikar99/reader
A utility library intended at providing reader macros for lambdas, arrays, accessors, hash-tables and hash-sets.
https://github.com/digikar99/reader
common-lisp library reader-macros
Last synced: 3 months ago
JSON representation
A utility library intended at providing reader macros for lambdas, arrays, accessors, hash-tables and hash-sets.
- Host: GitHub
- URL: https://github.com/digikar99/reader
- Owner: digikar99
- License: mit
- Created: 2019-10-24T10:58:04.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-02-12T11:11:22.000Z (about 3 years ago)
- Last Synced: 2024-06-21T18:10:24.577Z (almost 2 years ago)
- Topics: common-lisp, library, reader-macros
- Language: Common Lisp
- Homepage:
- Size: 35.2 KB
- Stars: 10
- Watchers: 4
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- curated-awesome-cl - cl-reader - A utility library (Python ##)
- awesome-cl - cl-reader - A utility library intended at providing reader macros for lambdas, mapping, accessors, hash-tables and hash-sets. [MIT][200]. (Miscellaneous ##)
README
# Installation
Download from the [Releases section](https://github.com/digikar99/reader/releases).
> I'll promote v0.10.0 to v1.0.0 if there are no significant changes over the next year.
# Getting Started
```lisp
;; Enable reader macros using the following:
(reader:enable-reader-syntax &rest reader-macro-identifiers)
;; OR
(reader+swank:enable-package-local-reader-syntax &rest reader-macro-identifiers)
;; For instance, to enable reader macros for hash table and set:
(reader:enable-reader-syntax 'hash-table 'set)
;; The following gives you a list of identifiers:
(documentation 'reader:enable-reader-syntax 'cl:function)
;; Complementory macros
;; (reader:disable-reader-syntax) ; is complementary
;; OR
;; (reader+swank-disable-package-local-reader-syntax)
```
# Examples
```lisp
CL-USER> #[[1 2 3
4 5 6]
[3 2 1
7 8 9]]
#3A(((1 2 3) (4 5 6)) ((3 2 1) (7 8 9))) ; cleaner syntax for arrays
CL-USER> (gethash 'a {eq 'a 1 'b 2}) ; hash-tables
1
T
CL-USER> (let ((reader:*set-function* 'hash-set:list-to-hs))
(hash-set:hs-memberp (eval (read-from-string "#{\"a\" \"b\" \"c\"}"))
"c"))
T
CL-USER> #{'(1) '(1)} ; default is CL:REMOVE-DUPLICATES
((1) (1))
CL-USER> #{'(1) '(1) :test #'equal}
((1))
CL-USER> [#2A((1 2 3) (4 5 6)) 1 0] ; accessors
4
CL-USER> (setf reader:*get-val-array-function* 'select:select)
SLCT:SELECT
CL-USER> (let ((arr #2A((1 2 3) (4 5 6))))
[arr t 0])
#(1 4)
CL-USER> [{"a" 1 "b" 2} "a"]
1
T
CL-USER> [(cl-json:decode-json-from-string "{\"a\":1, \"b\":2}") :b] ; works with alists
2
CL-USER> (-> {"a" "apple" "b" "ball"} ["b"] [1]); accessors can be chained using ->, an arrow
; see https://github.com/hipeta/arrow-macros/
#\a
CL-USER> #!echo -n hello world
hello world ; Captures until the end of line
NIL ; Should be possible to capture into a string
NIL ; but not ideal for speed
0
CL-USER> (let ((a t)) !a) ; not
NIL
CL-USER> (let ((a 5.0d0)) $a) ; write-to-string
"5.0d0" ; should this be "ensure-string"? raise an issue!
CL-USER> ?reader:enable-reader-syntax ; variable use not intended
READER:ENABLE-READER-SYNTAX
[symbol]
ENABLE-READER-SYNTAX names a macro:
Lambda-list: (&REST READER::READER-MACRO-IDENTIFIERS)
Documentation:
READER-MACRO-IDENTIFIERS are any of the following symbols:
GET-VAL, HASH-TABLE, NOT, STRING, DESCRIBE, ARRAY, SET, RUN-PROGRAM
Source file: /home/user/quicklisp/local-projects/reader/reader.lisp
```
## Notes
The functions used for constructing arrays, hash-tables, sets, accessing array elements or accessors in general can be specified by
- `*array-function*`
- `*hash-table-function*`
- `*set-function*`
- `*get-val-array-function*`
- `*get-val-function*`
This should allow users to use [fset](https://github.com/slburson/fset) or [access](https://github.com/AccelerationNet/access) or other libraries for the respective functions.
By default, alists and plists are treated distinct from lists whenever possible (see the `get-val` method specialized on lists). To disable this behavior, set each of these to `T`:
- `*alists-are-lists*`
- `*plists-are-lists*`
### Hash Tables
- `{"a" 1 "b" 2}` - hash tables use `'equalp` as the default test. The intended test function can be specified as the first element of the literal syntax. Besides providing with a choice, this also gets the indentation correct (see [Modification for emacs](#modifications-for-emacs).
### Setting alists and plists
- `(setf [] ...)` does not work with empty alists and plists. This seems to require setf-expanders with `get-val` generic-function.
### array vs get-val
- `[...]` (`get-val`) does not work inside `#[...]` (`array`) syntax. I do not have a plan or haven't figured out how to combine the two; and I find that okay since the `array` syntax is meant for cleaner representation in works involving matrices.
## Notes for existing users upgrading to v0.10.0 from v0.9.1
### Lambda
- `lambda` with the following usage has been removed.
```lisp
CL-USER> (mapcar λ(write-to-string -) '(2 3 4)) ; lambdas
("2" "3" "4")
```
This begins to feel like line-noise after a while and is not ideal for readability; a better equivalent is the simple macro
```lisp
CL-USER> (defmacro lm (&rest var-body)
`(lambda ,(butlast var-body)
,@(last var-body)))
LM
CL-USER> (mapcar (lm o (write-to-string o)) '(2 3 4))
("2" "3" "4")
```
### Hash-table
Since the function used for constructing hash-tables is now configurable (via `reader:*hash-table-function*`), the first input to the hash-table may be interpreted as the equality function. Thus, hash-table syntax can take an even (with default test `cl:equalp`) or odd (with the first symbol being interpreted as the equality function) number of arguments.
### Setting alists and plists
Now works for non-empty lists.
## Testing
```lisp
(ql:quickload "reader")
(5am:run :reader)
;; OR
(asdf:test-system "reader")
```
# Emacs Indentation Support
```lisp
(modify-syntax-entry ?\[ "(]" lisp-mode-syntax-table)
(modify-syntax-entry ?\] ")[" lisp-mode-syntax-table)
(modify-syntax-entry ?\{ "(}" lisp-mode-syntax-table)
(modify-syntax-entry ?\} "){" lisp-mode-syntax-table)
(define-key paredit-mode-map (kbd "{") 'paredit-open-curly)
(define-key paredit-mode-map (kbd "}") 'paredit-close-curly)
(global-set-key (kbd "C-S-l") (lambda () ; for inserting lambda
(interactive)
(insert-char (aref (symbol-name 'λ) 0))))
(setq paredit-space-for-delimiter-predicates
(list (lambda (endp delimiter)
(not (and (eql ?\( delimiter)
(member (char-before (point))
'(?\@ ?λ))))))))
(set-language-environment "UTF-8")
```
Motivation: [paredit curly brace matching in swank-clojure repl - Stack OverFlow](https://stackoverflow.com/questions/8598116/paredit-curly-brace-matching-in-swank-clojure-repl)
## Known Issues
Known issues include aligning hash-tables without first-element-as-key:
```lisp
{"hello" 1
"world" 2}
```
A work-around is to specify the test as the first element, and let that default exist for one-liners:
```lisp
{equal "hello" 1
"world" 2}
{"hello" 1 "world" 2}
```
# Comments
- [`cl-interpol`](http://edicl.github.io/cl-interpol/) is a prominent library providing perl / shell-like string interpolation facilities.
- [`cl-json`](https://common-lisp.net/project/cl-json/cl-json.html) can be used for parsing JSON.