Loop implementation for scheme
License
moon-chilled/loop
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is an implementation of Common Lisp's 'loop' macro for Scheme. It originates in SICL (https://github.com/robert-strandh/SICL). It's not portable, depending on a number of features specific to s7; however, if you can do (single) dynamic dispatch it shouldn't be difficult to port. Note also that I have largely tried to keep the code close to the original where possible, rather than trying to make it idiomatic, so that it will be easier to port future upstream improvements. There is an existing implementation of the macro that has been ported fairly widely; this, unlike that, is permissively licensed and supports a number of additional features: - Destructuring (loop for (x y) in '((1 2) (3 4) (5 6))) - Keywords (loop :for i :below 5) - Use of multiple values (loop for i below 5 collect (if (< i 3) (values) (values i i))) #| --> (3 3 4 4) |# (In many cases this can be obviated through clever use of conditional and conjunctional clauses. For instance, the above example can be equivalently written as (loop for i below 5 if (>= i 3) collect i and collect i).) - Use arbitrary iterators with 'across' (loop for (k . v) across (hash-table 'a 5 'b 6) collect k) (For this reason, hash-keys/hash-values are elided. For obvious reasons, iteration across packages is as well.) - The 'select' clause is similar to 'collect' or 'append', but creates strings. For example: (loop for x in '(#\a "BC" #\d) select x into q select q) #| --> "aaBCaBCd" |# Additional notes: - Variables which are not explicitly initialized will be initialized to #<undefined> rather than nil (loop with x return x) #| --> #<undefined> |# - However, loops without an explicit result will return null. E.G. (loop repeat 1) #| --> () |# - Type specifiers are parsed, but largely ignored. The exception is uninitialized variables: (loop with x integer? return x) #| --> 0 |# I'm not sure what more there is to do with them; suggestions welcome! (The full list of types supported is: integer? let? list? hash-table? float? string? vector? byte-vector? float-vector? int-vector?.) - When destructuring, the catch-all no-bind is (). E.G. (loop with (x () y) = '(1 2 3 4) return whatever) ←→ (let ((x 1) (y 3)) whatever) In this case, () is the empty (de)structure which matches everything and binds nothing, placing no constraints; a case where (imho) null being a special object rather than a symbol leads to more elegant formulations. - Minimize and maximize clauses that never run produce +inf.0 and -inf.0, respectively. Maximize and minimize clauses cannot affect the same accumulation variable; hence: (loop repeat 0 maximize 5) #| --> -inf.0 |# (loop minimize 0 maximize 0) #| error |# Todo: - Collect a vector instead of a list with 'volita' - Collect major cells using 'volitas'? - Collect into a lazy iterator? - Figure out what to do with named loops (just use the name as a return function?)
About
Loop implementation for scheme
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published