[plt-scheme] Help with understanding how to reuse macro data

From: Grant Rettke (grettke at acm.org)
Date: Fri Jan 2 17:10:26 EST 2009

Hi folks,

I am trying to understand how reuse macro data, in this particular
contrived scenario:

Suppose you want to crack a safe. The first attempt you make is to use
a safe cracking machine so you write this code for someone to use who
provides the specification via a safe cracking data format:

#|safe-opener-one.scm|#
#lang scheme

(provide crack-safe)

; Given a safe cracking definition, define a command list for processing
; by the SafeCracker2K machine.
(define-syntax crack-safe
  (syntax-rules (→)
    [(_ (1st-num → 2nd-num → 3rd-num) ...)
     (list
      "Init-code 1024"
      "Init-code 2048"
      "Push epoch starttime"
      (string-append
       "Crack-safe: " (number->string 1st-num)
       " then " (number->string 2nd-num)
       " and-finally " (number->string 3rd-num)) ...)]))

; (crack-safe (36 → 24 → 38) (63 → 42 → 83)) =>
; ("Init-code 1024"
; "Init-code 2048"
; "Push epoch starttime"
; "Crack-safe: 36 then 24 and-finally 38"
; "Crack-safe: 63 then 42 and-finally 83")

They try using it here, but the safe isn't cracked:

#|safe-opener-test.scm|#
#lang scheme

(require "safe-opener-one.scm")

(crack-safe
 (36 → 24 → 38)
 (63 → 42 → 83))

So they go about it by a different means, not wanting to change their
specification of course:

#|safe-opener-two.scm|#
#lang scheme

(provide crack-safe)

; Given a safe cracking definition, print out a request to give to
; "Vinnie" who will crack the safe for us.
(define-syntax crack-safe
  (syntax-rules (→)
    [(_ (1st-num → 2nd-num → 3rd-num) ...)
     (string-append
      "Dear \"Vinnie\", we have a job for you.\n"
      "We gave you know who an offer he couldn't refuse and he said that \n"
      "the following codes might work.\n"
      (string-append
       "" (number->string 1st-num)
       "-" (number->string 2nd-num)
       "-" (number->string 3rd-num) "\n") ...
       "If they don't, that is fine. Bring your special toolkit.")]))

; (display (crack-safe (36 → 24 → 38) (63 → 42 → 83))) =>
; Dear "Vinnie", we have a job for you.
; We gave you know who an offer he couldn't refuse and he said that
; the following codes might work.
; 36-24-38
; 63-42-83
; If they don't, that is fine. Bring your special toolkit.

#|safe-opener-test.scm|#
#lang scheme

(require "safe-opener-two.scm")

(crack-safe
 (36 → 24 → 38)
 (63 → 42 → 83))

This one works, but now they find that for some contrived reason they
want to use that specification to generate commands both for the safe
cracking machine, and for Vinnie. Also, since the specification is so
complicated (please pretend it is long and complicated), they don't
want to have to maintain two copies of it. On top of that, they don't
want to have to change how the definition looks at all. They want to
be able to store that config in a single file, and just pass the data
to either of the two safe cracker macros. I'm not sure how one would
do this.

As I write this, I feel like if we could capture the config data:

(define config
  '((36 → 24 → 38)
    (63 → 42 → 83)))

and when we apply it to either of the macros, what we would really
want to have happen is rather than:

(crack-safe config)

which would complain about we really want:

(crack-safe <insert syntax here composed of the contents of config>)

This seems ok because the data specification is static. I only thought
about this just now, so I didn't dig any deeper yet. Is this a
reasonable approach? If so, what is the best way to approach it?

What is the right/idiomatic solution here? Or is this bad idea?

Best wishes,

Grant

-- 
http://www.wisdomandwonder.com/


Posted on the users mailing list.