list "hey"))
```
⇒ (#\e #\y #\h)
Here is how the my-map example I’ve been using looks like in this system:
```Code
(define (my-map proc (x . xs)) (cons (proc x) (my-map proc xs)))
(define (my-map proc ()) '())
(my-map add1 '(1 2 3))
```
⇒ (2 3 4)
## require
You can also call require to backtrack out of functions if a return requirement is not met.
For example, here is a strange that multiplies its arguments, unless if their sum would be even, in which case return the sum instead:
```Code
(define (strange a b) (list 'product (* a b)))
(define (strange a b) (list 'sum (require even? (+ a b))))
(map strange '(1 2 3 4) '(5 5 7 8))
```
⇒ ((sum 6) (product 10) (sum 10) (sum 12))
This require takes two arguments. The first is either a boolean or a predicate, and the other is a value.
```Code
(define (mysterious a b) 'vanilla)
(define (mysterious a b)
(require even? (* a b))
(require even? (+ a b))
(require (< a b) 'neapolitan))
(map mysterious
'(1 2 2)
'(2 3 4))
```
⇒ (vanilla vanilla neapolitan)
It uses backtracking which means that side effects are executed.
This only applies to side effects before the requirements check:
```Code
(define (eerie a) (print "Catch-all"))
(define (eerie b)
(newline)
(newline)
(print "Time to check if it's positive:")
(require positive? b)
(print "It was.\nTime to check if it's odd:")
(require odd? b)
(print "It was that too. Nice"))
(for-each eerie '(1 2 -1))
```
This prints out:
> Time to check if it’s positive:
> It was.
> Time to check if it’s odd:
> It was that too. Nice
>
> Time to check if it’s positive:
> It was.
> Time to check if it’s odd:
> Catch-all
>
> Time to check if it’s positive:
> Catch-all
## Lovable quirks
### Precedence order
LIFO baby! Most recently defined is checked first. So put the fall backs first and then go more specific. This is a deliberate reversal of match-lambda since it lets you define special cases later.
This does apply to require. Put require last so it can backtrack up to previous definitions.
### Defining variables
If you just define a plain vanilla variable, then there’s not gonna be any dispatching there:
```Code
(define horses 23)
```
Any older stuff you had stored in horses isn’t lost, it’ll be ready for when you define a new generic using their same car signature.
The same goes for
```Code
(define horses (lambda () 23))
```
That’s not gonna be part of a generic.
“Single variables” like this aren’t saved, and can be overwritten on next call to define.
### Resetting & hacking
“OMG, I sent a mistyped definition to the REPL and now I can’t define over it since this new define just adds stuff!”
This doesn’t work:
```Code
(define (wrong tyop) typo)
(define wrong #f)
(define (wrong typo) typo)
```
It’ll have both the tyop and the typo version in there.
I mean, that’d kind of be fine in this particular case since the dispatcher will see the latest version first and that happens to shadow the typos, but, if you put typos in predicates or whatever you might be in for a rough time.
However, to reset when you mistype something and wanna re-define at the REPL, do (define reset: This content has been proxied by September (3851b).Proxy Information
text/gemini; lang=en
# The fanciest define of all time
A define that can destructure, pattern match, be nested, and create generics!
```Code
(define (foop so much #!key (insight 2) (joy 3)) (list so much insight joy))
(define (foop (? string? apples) (? string? horses)) (string-append horses apples))
(list (foop "way" "no ") (foop 3 2 joy: 1))
```
⇒ (“no way” (3 2 2 1))
It works.♥
When there’s just a normal define (with or without DSSSL stuff), it expands to a normal define. Using that variable or calling that function doesn’t have any overhead, it’s just bound normally.
Then when you define more stuff, it changes to become a dispatching generic multimethod.
One normal define becomes a normal define. It can have DSSSL stuff such as keyword arguments, that’s fine.
Two defines (normal or not), or one un-normal define (using destructuring for example), and it switches to matching.
```Code
(define (just-a-single (oh my what)) (list my what oh))
(just-a-single (string->list "hey"))
```
⇒ (#\e #\y #\h)
Here is how the my-map example I’ve been using looks like in this system:
```Code
(define (my-map proc (x . xs)) (cons (proc x) (my-map proc xs)))
(define (my-map proc ()) '())
(my-map add1 '(1 2 3))
```
⇒ (2 3 4)
## require
You can also call require to backtrack out of functions if a return requirement is not met.
For example, here is a strange that multiplies its arguments, unless if their sum would be even, in which case return the sum instead:
```Code
(define (strange a b) (list 'product (* a b)))
(define (strange a b) (list 'sum (require even? (+ a b))))
(map strange '(1 2 3 4) '(5 5 7 8))
```
⇒ ((sum 6) (product 10) (sum 10) (sum 12))
This require takes two arguments. The first is either a boolean or a predicate, and the other is a value.
```Code
(define (mysterious a b) 'vanilla)
(define (mysterious a b)
(require even? (* a b))
(require even? (+ a b))
(require (< a b) 'neapolitan))
(map mysterious
'(1 2 2)
'(2 3 4))
```
⇒ (vanilla vanilla neapolitan)
It uses backtracking which means that side effects are executed.
This only applies to side effects before the requirements check:
```Code
(define (eerie a) (print "Catch-all"))
(define (eerie b)
(newline)
(newline)
(print "Time to check if it's positive:")
(require positive? b)
(print "It was.\nTime to check if it's odd:")
(require odd? b)
(print "It was that too. Nice"))
(for-each eerie '(1 2 -1))
```
This prints out:
> Time to check if it’s positive:
> It was.
> Time to check if it’s odd:
> It was that too. Nice
>
> Time to check if it’s positive:
> It was.
> Time to check if it’s odd:
> Catch-all
>
> Time to check if it’s positive:
> Catch-all
## Lovable quirks
### Precedence order
LIFO baby! Most recently defined is checked first. So put the fall backs first and then go more specific. This is a deliberate reversal of match-lambda since it lets you define special cases later.
This does apply to require. Put require last so it can backtrack up to previous definitions.
### Defining variables
If you just define a plain vanilla variable, then there’s not gonna be any dispatching there:
```Code
(define horses 23)
```
Any older stuff you had stored in horses isn’t lost, it’ll be ready for when you define a new generic using their same car signature.
The same goes for
```Code
(define horses (lambda () 23))
```
That’s not gonna be part of a generic.
“Single variables” like this aren’t saved, and can be overwritten on next call to define.
### Resetting & hacking
“OMG, I sent a mistyped definition to the REPL and now I can’t define over it since this new define just adds stuff!”
This doesn’t work:
```Code
(define (wrong tyop) typo)
(define wrong #f)
(define (wrong typo) typo)
```
It’ll have both the tyop and the typo version in there.
I mean, that’d kind of be fine in this particular case since the dispatcher will see the latest version first and that happens to shadow the typos, but, if you put typos in predicates or whatever you might be in for a rough time.
However, to reset when you mistype something and wanna re-define at the REPL, do (define reset: