Destruct
1 Why would I use this?
Structs package related values into a single one:
(struct fruit (name calories color)) (define banana (fruit "banana" 105 'yellow)) (define apple (fruit "apple" 95 'red))
Then you can unpack those values later to use them:
; There is an IMPORT TAX for fattening fruits, fruits with long names, or fruits that confuse people with bright colors (define (bright? color) (equal? color 'yellow)) (define (long? name) (> (string-length name) 5)) (define (has-fruit-tariff1? fruit) (or (> (fruit-calories fruit) 100) (bright? (fruit-color fruit)) (> (string-length (fruit-name fruit)) 5)))
It works, but is redundant: The expression (fruit-calories fruit) mentions "fruit" twice, and needs a wrapping pair of parentheses. Visually scanning for the second argument 5 is more difficult because the expression is so long, but it’s not worth the vertical space putting 5 onto its own line.
Here’s how it looks with destruct:
(define (has-fruit-tariff2? f) (destruct fruit f) (or (> f-calories 100) (bright? f-name) (> (string-length f-name) 5)))
Now only one mention of fruit is needed, instead of twice for each use of a field.
(define (has-fruit-tariff? f) (match f [(struct fruit (name calories color)) (or (> calories 100) (bright? name) (> (string-length name) 5))]))
We still have to mention the fields twice, but it’s all-at-once on a single line. But if you had to bind many structs, your indentation would spiral out of control.
Adding zero indentation
Using O(1) parentheses instead of O(uses)
Mentioning the type O(1) times instead of O(uses)
Its downside is that it introduces variables like f-calories that aren’t explicitly defined in the code: The parameter f and the field accessor calories are defined, but not the local variable f-calories.