Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Scheme

(uses the hygenic macro system)

Date:08/11/05
Author:Evan Farrer
URL:http://www.cs.utah.edu/~farrer/
Comments:2
Info:http://www.schemers.org/
Score: (2.95 in 21 votes)
;; 99 bottles implemented using a hygenic macro in Scheme (R5RS)
;; Evan Farrer Evan.Farrer@gmail.com
;; 
;; At compile time the (beer 99) expression expands into a call to display with a string of the song
lyrics passed as the argument
;; (beer 99) -> (display "99 Bottles of beer on the wall, 99...")

(define-syntax beer
  (lambda (stx)
    (let* ((plural (lambda (count)
                     (case count
                       ((1) (format "~a ~a" count "bottle"))
                       ((0) "no more bottles")
                       (else (format "~a ~a" count "bottles")))))
           (gen-line (lambda (pre count)
                       (let ((pre (syntax-object->datum pre))
                             (count (syntax-object->datum count)))
                         (string-append
                          pre
                          (if (= 99 count)
                              ""
                              (format "~a~a~a\n" "Take one down and pass it around, " (plural count)
" of beer on the wall."))
                          
                          (format "\n~a~a~a~a\n" (string-titlecase (plural count)) " of beer on the
wall, " (plural count) " of beer.")
                          
                          (if (= 0 count)
                              "Go to the store and buy some more, 99 bottles of beer on the
wall.\n"
                              ""))))))
      (syntax-case stx ()
        ((_ pre count)
         (let ((last (= 0 (syntax-object->datum #'count))))
           (with-syntax ((new-pre (gen-line #'pre #'count))
                         (new-count (sub1 (syntax-object->datum #'count))))
             (if last
                 #'new-pre
                 #'(beer new-pre new-count)))))
        ((_ count)
         #'(display (beer "" count)))))))

(beer 99)

Download Source | Write Comment

Alternative Versions

VersionAuthorDateCommentsRate
original versionTim Goodwin04/20/052
REALLY using hygienic macrosNMH02/02/110
slightly shorter, efficient, featurefulRicardo Malafaia08/29/051
define-less versionlambda the ultimate10/14/100
Cleanly factored MAP-based versionGnomon04/18/082

Comments

>>  mala said on 08/29/05 17:11:32

mala quite frankly, this is just overkill. and there's much redundancy there. why not cache (plural count) in a let binding, for instance?

>>  David said on 03/18/07 00:38:30

David I think writing it in syntax-case is pretty lame. Unless you can do it in syntax-rules, don't bother with the macro system. Guess I'll go try to do it in syntax-rules now.

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: