Deutsch   English   Français   Italiano  
<varmjt$cgmi$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!feeds.phibee-telecom.net!2.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: "B. Pym" <Nobody447095@here-nor-there.org>
Newsgroups: comp.lang.lisp,comp.lang.scheme
Subject: Re: Lisp newbie needs help
Date: Fri, 30 Aug 2024 05:51:09 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 174
Message-ID: <varmjt$cgmi$1@dont-email.me>
References: <vapdj5$3tkts$1@dont-email.me> <vapf1m$3tr94$1@dont-email.me> <vapmii$3uu2c$1@dont-email.me> <var6g1$6nq5$1@dont-email.me>
Injection-Date: Fri, 30 Aug 2024 07:51:10 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="abfbf0e8d1f6a5c18d0eb734601f646f";
	logging-data="410322"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18VgzrimRR4syabTeHwMGlo"
User-Agent: XanaNews/1.18.1.6
Cancel-Lock: sha1:evtHE2+WA47yeoh5L2SLkBlH4+8=
Bytes: 6370

B. Pym wrote:

> B. Pym wrote:
> 
> > B. Pym wrote:
> > 
> > > B. Pym wrote:
> > > 
> > > > > (defun my-test ()
> > > > >    (loop for number = (1+ (random 6))
> > > > >          as sum = number then (+ sum number)
> > > > >          until (= number 1)
> > > > >          do (format t "~&~D thrown. Sum: ~D" number sum)
> > > > >          finally (format t "~&One thrown.")))
> > > > 
> > > > Gauche Scheme
> > > > 
> > > > (use srfi-1)  ;; unfold
> > > > (use srfi-27) ;; random-integer
> > > > 
> > > > (define (my-test)
> > > >   (fold
> > > >     (^(n sum) (print n " thrown.  Sum: " (inc! sum n)) sum)
> > > >     0
> > > >     (cdr (unfold zero? ($ + 1 $) (^_ (random-integer 6)) -1)))
> > > >   (print "One thrown."))
> > > > 
> > > > 
> > > > gosh> (my-test)
> > > > 2 thrown.  Sum: 2
> > > > 2 thrown.  Sum: 4
> > > > 6 thrown.  Sum: 10
> > > > One thrown.
> > > > 
> > > > gosh> (my-test)
> > > > One thrown.
> > > > 
> > > > 
> > > > Explanation of "unfold":
> > > > 
> > > > Function: unfold end-test key gen-next-seed seed :optional tail-gen
> > > > 
> > > > (unfold zero? (lambda(n) (+ 800 n)) (lambda(n) (- n 1)) 7)
> > > >   ===>
> > > > (807 806 805 804 803 802 801)
> > > > 
> > > > (unfold zero? (lambda(n) (+ 800 n)) (lambda(n) (- n 1)) 7
> > > >   (lambda(n) (list "The number" n "ended the unfolding.")))
> > > >   ===>
> > > > (807 806 805 804 803 802 801 "The number" 0 "ended the unfolding.")
> > > 
> > > Using "do" is a bit tricky, but the result is shorter.
> > > 
> > > (define (my-test)
> > >   (do ((n #f (+ 1 (random-integer 6)))
> > >        (sum 0))
> > >     ((eqv? 1 n) (print "One thrown."))
> > >     (if n (print n " thrown.  Sum: " (inc! sum n)))))
> > 
> > It seems to me that "do*" is more appropriate for this,
> > but this version is 2 characters longer!
> > 
> > (define (my-test)
> >   (do* ((n #f (+ 1 (random-integer 6)))
> >         (sum 0 (+ n sum)))
> >     ((eqv? 1 n) (print "One thrown."))
> >     (if n (print n " thrown.  Sum: " sum))))
> > 
> > I don't know why Common Lisp has "do*", but Gauche, Racket,
> > and Chicken Scheme don't.
> > 
> > Here's a version that I cobbled together.  (A macro guru
> > may give us a better one.)  "do" is to "do*" as "let" is
> > to "let*".
> > 
> > (define-syntax do*-aux
> >   (syntax-rules ()
> >     [(do* (inits ...) ((var update) ...) (test expr ...) stuff ...)
> >      (let* (inits ...)
> >        (if test
> >          (begin expr ...)
> >          (begin
> >            (begin stuff ...)
> >            (let loop ()
> >              (begin (set! var update) ...)
> >              (if test
> >                (begin expr ...)
> >                (begin  stuff ...
> >                  (loop)))))))]))
> > 
> > (define-syntax do*
> >   (syntax-rules (!!!)
> >     [(do* !!! (inits ...) (updates ...)
> >        ((var init update) more ...) until body ...)
> >      (do* !!! (inits ... (var init)) (updates ... (var update))
> >        (more ...) until body ...)]
> >     [(do* !!! (inits ...) (updates ...)
> >        ((var init) more ...) until body ...)
> >      (do* !!! (inits ... (var init)) (updates ... )
> >        (more ...) until body ...)]
> >     [(do* !!! inits updates () until body ...)
> >      (do*-aux inits updates until body ...)]
> >     [(do* inits-updates until stuff ...)
> >      (do* !!! () () inits-updates until stuff ...)]))
> > 
> > (do* ((x 0 (+ 1 x))
> >       (y 922))
> >   ((= 9 x) (print 'ok))
> >   (print x " " y))
> > 
> > 0 922
> > 1 922
> > 2 922
> > 3 922
> > 4 922
> > 5 922
> > 6 922
> > 7 922
> > 8 922
> > ok
> >  
> 
> Another way:
> 
> (define (my-test)
>   (let1 r (cut  + 1 (random-integer 6))
>     (do* ((n (r) (r))
>           (sum n (+ n sum)))
>       ((eqv? 1 n) (print "One thrown."))
>       (print n " thrown.  Sum: " sum)))) 

Use ":for" when the same expression is to be assigned
to the variable every time.

(define-syntax do@-aux
  (syntax-rules ()
    [(do* (inits ...) ((var update) ...) (test expr ...) stuff ...)
     (let* (inits ...)
       (if test
         (begin expr ...)
         (begin
           (begin stuff ...)
           (let loop ()
             (begin (set! var update) ...)
             (if test
               (begin expr ...)
               (begin  stuff ...
                 (loop)))))))]))

(define-syntax do@
  (syntax-rules (:for  !!!)
    [(do@ !!! (inits ...) (updates ...)
       ((:for var expr) more ...) until body ...)
     (do@ !!! (inits ... (var expr)) (updates ... (var expr))
       (more ...) until body ...)]
    [(do@ !!! (inits ...) (updates ...)
       ((var init update) more ...) until body ...)
     (do@ !!! (inits ... (var init)) (updates ... (var update))
       (more ...) until body ...)]
    [(do@ !!! (inits ...) (updates ...)
       ((var init) more ...) until body ...)
     (do@ !!! (inits ... (var init)) (updates ... )
       (more ...) until body ...)]
    [(do@ !!! inits updates () until body ...)
     (do@-aux inits updates until body ...)]
    [(do@ inits-updates until stuff ...)
     (do@ !!! () () inits-updates until stuff ...)]))

(define (my-test)
  (do@ ((:for n (+ 1 (random-integer 6)))
        (sum n (+ n sum)))
    ((= 1 n) (print "One thrown."))
    (print n " thrown.  Sum: " sum)))