Idiomatic way of handling lists and/or tuples


Here's my unit test, or the first attempt at it:

#lang racket/base

(require rackunit

(define initials-block
  (list '("ron reagan-smith" "R.R-S.") '("Nell Guinn" "N.G.") '("ben lazar" "BL.")))

(for ([i initials-block])
  (check-equal? (initials (car i)) (car (cdr i)) "initials test")
  (printf "'~a' '~a'\n" (car i) (car (cdr i))))

I want to keep the test input separately, to use it for testing alternative implementations, for instance. I hope the idea is clear, but the code seems to me accidental and ugly. Is there a way to make it more natural? Or have I done it just right at my first attempt?

Hi, @Tyrn.

It probably depends on your own sense of aesthetics, to some degree.

But, if the code feels too "unnatural", perhaps adding some additional structure might help to help guide the mind.

Consider, for example, the match-define form:

(for ([i initials-block])
  (match-define (list full-name expect-initials) i)
  (check-equal? (initials full-name) expect-initials "initials test")
  (printf "'~a' '~a'\n" full-name expect-initials))

Ah, this is pattern matching Racket style! Good! What about initials-block? Is it just right?

I mean... I hesitate to make any pronouncements about "right/wrong" :sweat_smile:

I find that, while it is very useful to have "goldilocks" code, i.e. everything is "just right", I often experience that my sense of "just right" changes over time.

A comment or two usually does a better job to clarify what it is I mean, if the code itself can't be persuaded into something more "self-evident".

As an aside, I recently started reading Don't Make Me Think by Steve Krug, and he makes a good point about settling for "self-explanatory" instead of "self-evident" when it is not evident (haha) what that should be exactly.

Apologies if this is unhelpful.

It's helpful enough :smile:

Here's my progress:

(define (block-check fn data-block [message ""] [print? #f])
  (for ([i data-block])
    (match-define (list in out) i)
    (check-equal? (apply fn in) out message)
    (when print?
      (printf "~v ~v\n" in out))))

(define initials-block
  (list (list (list "ron reagan-smith") "R.R-S.")
        (list (list "Nell Guinn") "N.G.")
        (list (list "john ronald reuel Tolkien") "J.R.R.T.")))

(block-check initials initials-block "initials test" #t)

This is pretty much what I ever wanted. The only wrinkle: there are too many list keywords. Is there a way to do something about it?

Somewhat "quotidian":

;; from
(define initials-block
  (list (list (list "ron reagan-smith") "R.R-S.")
        (list (list "Nell Guinn") "N.G.")
        (list (list "john ronald reuel Tolkien") "J.R.R.T.")))
;; to
(define initials-block
  '((("ron reagan-smith") "R.R-S.")
    (("Nell Guinn") "N.G.")
    (("john ronald reuel Tolkien") "J.R.R.T.")))

Thanks! Something forced me to use list along the way. In the end, there's no telling what it was :smile: .

1 Like