for-all(3scm)

πŸ“¦ version 0-unstable-2024-02, in nixpkgs unstable

πŸ’… for-all(3scm) β€” bestie edition πŸŽ€

okay so this is from the Scheme Programmer's Manual, and honestly? it's giving "tiny procedures, huge personality" ✨ stick around, we're gonna go through the whole thing together 🫢


🌸 NAME 🌸

for-all, exists β€” bestie, these two apply a predicate to lists of objects. that's it, that's the job πŸ’–


πŸ“š LIBRARY πŸ“š

lowkey the most important part, don't skip it:

(import (rnrs))                     ;R6RS
(import (rnrs lists))               ;R6RS

✨ SYNOPSIS ✨

(for-all proc list ...)
(exists proc list ...)

πŸ’œ DESCRIPTION πŸ’œ

okay so here's the tea β˜• β€” these procedures apply proc to the elements of the lists. They start with the first elements of each list, then the second elements, etc. The for-all procedure stops when proc returns #f, and the exists procedure stops when proc returns a true value. no cap, it's that simple 🌈

If iteration stops because proc returns #f (for for-all) or a true value (for exists) then that value is returned. Otherwise the return value is as described in the next two points πŸ‘‡

🧺 Empty lists 🧺

If the lists are all empty, then for-all returns #t and exists returns #f. iconic behaviour, honestly πŸ’…

πŸŒ€ Tail calls πŸŒ€

If these procedures reach the last elements of the lists, then they perform a tail call of proc on the last element of each list. slay 🧚

🌫️ Dynamic environment 🌫️

proc is always called in the same dynamic environment as for-all or exists itself. This generally means there is no internal state in the procedure that would get messed up if there are multiple returns from proc. so you can chill 😌

πŸ“ Matching lengths and arguments πŸ“

The lists should all have the same length, and proc should accept as many arguments as there are lists, and return a single value. proc should not mutate the list arguments πŸš«πŸ™ˆ

The implementation must check that the lists are chains of pairs only to the extent necessary to determine the return value. (yes, exactly that much and no more, bestie β€” it's literally in the spec πŸ’€)

🎁 RETURN VALUES 🎁

These procedures return a single value, which is either a true value returned by proc, or #f.

A special case is when proc is tail called on the last elements of the lists, in which case whatever proc returns will returned. Depending on the implementation, it may be possible for multiple values to be returned, but this should not be relied upon πŸ‘€


πŸ“ EXAMPLES πŸ“

bestie, the examples are the whole vibe check, look:

(for-all even? '(3 1 4 1 5 9))
   => #f
(for-all even? '(2 4 14))
   => #t
(for-all even? '(2 4 14 . 9))
   => &assertion exception
(for-all (lambda (n) (and (even? n) n))
         '(2 4 14))
   => 14
(for-all < '(1 2 3) '(2 3 4))
   => #t
(for-all < '(1 2 4) '(2 3 4))
   => #f

see how that improper list just exploded? πŸ’€ &assertion exception, we love a boundary πŸŽ€

(exists even? '(3 1 4 1 5 9))
   => #t
(exists even? '(3 1 1 5 9))
   => #f
(exists even? '(3 1 1 5 9 . 2))
   => &assertion exception
(exists (lambda (n) (and (even? n) n)) '(2 1 4 14))
   => 2
(exists < '(1 2 4) '(2 3 4))
   => #t
(exists > '(1 2 3) '(2 3 4))
   => #f

and the moment we've all been waiting for πŸ”₯

(exists values '(#f 42 #f))
   => 42

like, values ate that. main character energy fr fr πŸ‘‘


πŸ› οΈ APPLICATION USAGE πŸ› οΈ

These procedures are used in code that needs to check if all or any elements in list satisfies some condition. An example would be a variadic procedure that checks if all its arguments are of a certain type. literally the "are we all valid here" check of your codebase πŸ’–


πŸ’€ ERRORS πŸ’€

This procedure can raise exceptions with the following condition types:

  • &assertion (R6RS) β€” The wrong number of arguments was passed or an argument was outside its domain. In particular, if the lists are not empty then this will be raised if proc is not a procedure that takes the right number of arguments. It may be raised if proc returns something other than a single value. It will be raised if the lists are of different lengths and one of the lists is fully traversed, or if traversal reaches a suffix of one of the list arguments which is either not a chain of pairs or is circular.
okay that last one is the scary one 😭 different lengths, not-a-chain-of-pairs, or a circular list β€” all of those are &assertion town. consider yourself warned bestie πŸ™ˆ

πŸ‘€ SEE ALSO πŸ‘€

go read those too, they're siblings 🫢


⭐ STANDARDS ⭐

R6RS. periodt πŸ’…


πŸ¦‹ HISTORY πŸ¦‹

These procedures are new in R6RS. Similar procedures exist in SRFI-1 under the names every and any. so if you've met every and any before, yeah, same energy, different era 🌸


πŸ‘‘ AUTHORS πŸ‘‘

This page is part of the scheme-manpages project. It includes materials from the RnRS documents. More information can be found at https://github.com/schemedoc/manpages/.


okay that's the whole page, bestie, you ate that reading πŸ“βœ¨ quick sign-off: this was the for-all(3scm) page, dated 2021-07-23, straight out of the Scheme Programmer's Manual / scheme-manpages collection β€” mwah, go write some tail calls πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from