Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

A student's question

Name: Anonymous 2011-05-30 12:20

My teacher keeps drilling into our collective heads that using the break command is harmful, and that if we wish to terminate a loop early it would be far better to create a boolean variable, set it to 0, and add a condition to the head of the loop, and set the boolean variable to 1 when a break is needed. Note that this way you actually have to check this every single loop (where it is not needed almost every time) as well as waste a command to reset the boolean in case it was set to true.

Is there a reason to this?

Name: Anonymous 2011-05-30 17:42

>>31
Also, an implementation of CL's tagbody (not exactly, same semantics, different syntax) in Racket, but it should be easily portable to R6RS too:

(define-syntax-parameter goto
  (lambda (stx)
    (raise-syntax-error 'goto (if (identifier? stx) "bad syntax" "bad syntax (not inside a tagbody)") stx)))

(define-syntax (tagbody stx)
  (define (%tag-next x)
    (let ((x (syntax->list x)))
      (do ((x x (cdr x))
           (y (cdr x) (cdr y))
           (r (list (car x)) (cons (list (car x) (car y)) r)))
        ((null? y) (reverse (cons (list (car x) #'void) r))))))
  (syntax-case stx ()
    ((tagbody (tag b ...) ...)
     (andmap identifier? (syntax->list #'(tag ...)))
     (with-syntax (((first (tag next) ...) (%tag-next #'(tag ...))))
       #'(letrec ((tag
                   (lambda ()
                     (let/ec escape
                       (syntax-parameterize
                           ((goto (lambda (stx)
                                    (syntax-case stx ()
                                      ((goto label)
                                       (if (and (identifier? #'label)
                                                (or (free-identifier=? #'label #'tag) ...))
                                           #'(escape label)
                                           (raise-syntax-error 'goto "bad syntax (not a valid label)" stx #'label)))))))
                         b ...
                         (next))))) ...)
           (let loop ((f (first)))
             (if (procedure? f) (loop (f)) f)))))))


;; Example taken from the HyperSpec: http://www.lispworks.com/documentation/HyperSpec/Body/s_tagbod.htm
(define-syntax-rule (inc! x n) (set! x (+ x n)))

(let ((val #f))
  (tagbody
   (start
    (set! val 1)
    (goto point-a)
    (inc! val 16))
   (point-c
    (inc! val 4)
    (goto point-b)
    (inc! val 32))
   (point-a
    (inc! val 2)
    (goto point-c)
    (inc! val 64))
   (point-b
    (inc! val 8)))
  val)
; 15


Really, more languages should provide some non-local exit mechanism, and not in the form of exceptions.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List