Destruct
destruct
1 Why would I use this?
8.12

Destruct🔗ℹ

 (require destruct) package: destruct

syntax

(destruct struct-name variable)

Introduces variables with names variable-field for each field in the struct struct-name, initialized with the value (field-accessor variable).

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.

A match statement is an alternative:
(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.

So destruct lets you unpack those structs while:
  • 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.