Lara
Lara

Reputation: 3174

How to practically define a lot of things based on a condition in Scheme/Racket?

I'm working in Racket but as far as I know this is the case in Scheme in general; you cannot do something like this because we are trying to define something in an expression context:

(if condition
    (define x "do a backflip")
    (define x "do a barrel roll"))

Now for this particular case I could do something like this instead:

(define x
  (if condition
      "do a backflip"
      "do a barrel roll"))

But if you have a lot of different things to define this gets really awful, because instead of

(if condition
    (begin (define x "do a backflip")
           (define y "awesome")
           (define z "shoot me"))
    (begin (define x "do a barrel roll")
           (define y "nice")
           (define z "give me sweet release")))

we get

(define x                                                                                                                                                                                                                                      
  (if condition
      "do a backflip"
      "do a barrel roll"))
(define y                                                                                                                                                                                                                                      
  (if condition
      "awesome"
      "nice"))
(define z                                                                                                                                                                                                                                      
  (if condition
      "shoot me"
      "give me sweet release"))

Which isn't as DRY as it could be, we are constantly repeating the test for condition. And the result is that if instead of testing for condition we want to check for other-condition, we have to make changes n times for n the amount of things being defined. Is there a better way to do this, and if so: How?

Upvotes: 6

Views: 105

Answers (2)

Ryan Culpepper
Ryan Culpepper

Reputation: 10653

If "a lot" is really large, you might want to use Racket's units.

First define a signature with all the variables you want to define:

(define-signature acro^ (x y z))

Then define units that contain the different sets of definitions:

(define-unit flippy@
  (import) (export acro^)
  (define x "do a backflip")
  (define y "awesome")
  (define z "shoot me"))

(define-unit rolly@
  (import) (export acro^)
  (define x "do a barrel roll")
  (define y "nice")
  (define z "give me sweet release"))

You can choose dynamically which unit do invoke and bind to the names in the signature:

(define-values/invoke-unit
  (if .... flippy@ rolly@)
  (import) (export acro^))

x
;; => either "do a backflip" or "do a barrel roll", depending on condition

Upvotes: 4

soegaard
soegaard

Reputation: 31145

Use define-values:

(define-values (x y z) (if condition
                           (values "do a backflip"    "awesome" "shoot me")
                           (values "do a barrel roll" "nice"    "give me sweet release")))

Upvotes: 5

Related Questions