# varg.ss ```lisp (import varg) ``` This is a chicken scheme egg, section structure will be like: - [http://wiki.call-cc.org/eggs%20tutorial#sections](http://wiki.call-cc.org/eggs%20tutorial#sections). ## Authors - [riku-ri@outlook.com](riku-ri@outlook.com) ## Repository [https://codeberg.org/rikuri/varg.ss/](https://codeberg.org/rikuri/varg.ss/) ## Requirements ## API ### Exception Exceptions is supposed to be compliant with the module `(chicken condition)` and SRFI-12 - http://wiki.call-cc.org/man/5/Module%20(chicken%20condition) Find more details about exception in the specific procedure below #### non-continuable The non-continuable conditions expand system conditions from: - http://wiki.call-cc.org/man/5/Module%20(chicken%20condition)#system-conditions More specifically, they would be: - be with composite kind `(exn varg)` - for a condition from a specific procedure `

`, the composite kind would be `(exn varg

)` - in the `exn` field, it will contain properties listed below: - `'message` - `'call-chain` ### `(varg |Parameters|)` #### Return - If `#:lambda` is not set, `(varg |Parameters|)` will return a list: ``` (list (cons #:with-value |with-value-list|) (cons #:without-value |without-value-list|) (cons #:literal |literal-list|) ) ``` - `|with-value-list|` `|without-value-list|` `|literal-list|` are all list parsed based on parameters to `varg` #### Parameters `|Parameters|` in `(varg |Parameters|)` can contain 1 or more element listed below: > order is not sensitive - `(cons #:with-value ...)` where `...` should be a list of keyword

more details here > *e.g.* > - `(varg '(#:with-value #:a #:b) '())` > - `(varg '(#:with-value #:a #:b) '(#:explict #:a) '((#:a . "value of a")))` > - `(varg '(#:with-value #:a #:b) '(#:explict #:a) '())` > > `varg` will abort a condition regarding `#:a` is missing because > > `#:a` is in `#:explict` but > > not in `'()`(the last parameter of `varg` here) - *description* - Arguments that are with value. They may present in the necessary parameter `|TO-PARSE|`(see below) as a pair. If a with-value parameter is necessary for your self-defined function, set the keyword in `#:explict` - *if-not-set*: - In the return value, `#:with-value` will follow a empty list
- `(cons #:without-value ...)` where `...` should be a list of keyword
more details here > *e.g.* `(varg '(#:without-value #:c #:d) '(#:c))` - *description* - Arguments that are without value. They may present in the necessary parameter `|TO-PARSE|`(see below) They are like options in command line, set or not. - *if-not-set*: - In the return value, `#:without-value` will follow a empty list
- `(cons #:literal ...)` where `...` should be a list
more details here > *e.g.* > - `(varg '(#:literal 1st 2nd) '("1" "2"))` > > This will return > > `'((#:with-value) (#:without-value) (#:lteral "1" "2"))` > - `(varg '(#:literal 1st 2nd) '("1"))` > > `varg` will abort a condition regarding `2nd` is missing here - *description* - Literal parameters. They **must** present in the necessary parameter `|TO-PARSE|`(see below). > Details of `|any-list|` > make no sense for `varg`, > `varg` only need to know number of them. > So `varg` does not check types of elements in > `|any-list|`, > but it is recommended make all elements to be scheme quoted symbol - *if-not-set*: - In the return value, `#:literal` will follow a empty list
- `(cons #:explict ...)` where `...` should be a list of keyword, and keywords should have been appeared in `#:with-value` parameter or `#:withou-value` parameter
more details here > *e.g.* > - `(varg '(#:with-value #:a #:b) '(#:explict #:a) '((#:b . 1)))` > > `varg` will abort a condition regarding missing `#:a` - *description* - Check if all of `...` appeared in the `|TO-PARSE|` parameter. And any keyword in `...` should have been appeared in `#:with-value` parameter. `#:explict` only check keywords in `#:with-value`. Because `#:without-value` is like boolean value(set or not), and `#:literal` is always necessary (unless `#:enable-unknown`) is set. > If a keyword presented in `#:explict` but not in `#:with-value`, > `varg` will **abort forever**.
- `#:enable-unknown`
more details here > *e.g.* > - `(varg #:enable-unknown '(#:literal only-one) '(1 2 #:a-keyword))` > > This will return > > `'((#:with-value) (#:without-value) (#:literal 1 2 #:a-keyword))`. > > If `#:enable-unknown` is not set, > > `varg` will abort a condition regarding `2 #:a-keyword` is unknown. - *description* - If `#:enable-unknown` is set, `varg` will append unknown arguments to `#:literal` in result but not report error.
- `#:verbose`
more details here - *description* - If set, `varg` will output more information to `(current-error-port)`. Usually used in debug
- `|TO-PARSE|` > *e.g.* > - `(varg)` will abort a condition regarding missing this argument > - `(varg #())` will abort a condition regarding this is not a list > - `(varg ... (list (cons #:with "w") #:with-out))` here `|TO-PARSE|` > is the last list. > And usually you should set relative `#:with-value` `#:withou-value` etc > in `...`. - *description* - `varg` will iterate on it and group each element by settings in `#:with-value` `#:witout-value` etc parameters - `#:lambda`
more details here > e.g. `(varg #:lambda ...)` - *description* - If set, `varg` will return a procedure to access the without `#:lambda` return value. For example `((varg #:lambda ...) #:with-value)` is equal to `(cdr (assoc #:with-value (varg ...)))`
## Examples Bascially *varg* filter the input list by conditions, and group them to 3 classes `#:with-value` `withou-value` `#:literal`. for example ```lisp (import varg) (define (fun . args) (set! varg-output (varg '(#:with-value #:wi1 #:wi2) '(#:without-value #:wo1 #:wo2) '(#:literal #:li1 #:li2) args)) ; After the call of `fun` at the bottom, ; varg-output should be a list: '( (#:with-value (#:wi1 . 1)) ; #:wi2 does not appear ; because the call of `fun` at the bottom did not set it (#:without-value #:wo2) (#:literal "non-keyword1" "non-keyword2") ) ; Hence get values like this: (let ( (with-value (cdr (assoc #:with-value varg-output))) (without-value (cdr (assoc #:without-value varg-output))) (literal (cdr (assoc #:literal varg-output))) ) (print (cdr (assoc #:wi1 with-value))) ; this will be 1 (print (member #:wo2 without-value)) ; this will be equal to #t (print (member #:wo1 without-value)) ; this will be #f (print (list-ref literal 0)) ; this will "non-keyword1" (print (list-ref literal 1)) ; this will "non-keyword2" ) ) (fun '(#:wi1 . 1) #:wo2 "non-keyword1" "non-keyword2" ) ``` For another example, a procedure that copy file to another path named `cp` > Just showing how to use `varg`, no copy implementation in `cp` ```lisp (define (cp . cp-args) (varg '(#:with-value #:mode) '(#:without-value #:force) '(#:literal src dest) cp-args ) ... ... ) ``` `cp` would be called like: - `(cp (cons #:mode #o777) "/tmp/a" "/tmp/b")` Which means copy `/tmp/a` to `/tmp/b`, and set `/tmp/b` mode to `0777` > In the definition of `cp`, `varg` will return > `'((#:with-value (#:mode . 511)) (#:without-value) (#:literal "/tmp/a" "/tmp/b"))` > And `cp` can implement the real copy process based on it. > > `511` is the octal value of `#o777` - `(cp #:force "/tmp/a" "/tmp/b")` Which means copy `/tmp/a` to `/tmp/b`, and replace `/tmp/b` if exists > `varg` will return `'((#:with-value) (#:without-value #:force) (#:literal "/tmp/a" "/tmp/b"))` ## License MIT