guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Special variables to relax boxing


From: Stefan Israelsson Tampe
Subject: Re: Special variables to relax boxing
Date: Fri, 22 Mar 2013 23:33:06 +0100
User-agent: KMail/4.9.5 (Linux/3.5.0-26-generic; KDE/4.9.5; x86_64; ; )

Hi list, Mark and Noah,

Yesterday I noticed that the sematics for special variables are quite
close to fluids and decied to see if I could model special variables
ontop of that with-fluids semantics. That was pretty easy. The basic
difference between fluid and special variables is that with fluids one
swaps between the storages at the with-fluids point, both backwards
and forwards. in the case of special variables one bascially takes on
half of the swap at the wind and the other half at the unwind. So it
become quite easy to just copy the fluid logic and then slightly
modify that source. The scheme compilation part is a little hacky but
it was not that hard to plumb an acceptable solution for testing. I
did verify that it manages the value as said and noticed a 10x
increase of speed when it comes to code passing into a with-fluids
without any prompts compared to any possible setup using dynamic-wind
and fluids. The system is still pretty rough though but there are some
significant optimization implemented.

a preliminary git diff is attached for you to play with.

I did try to implement special variables in current guile. I found
that it is pretty difficult to get the correct semantics working
anyone able to spot it. I use,


(define guards (make-vector 10))
(let lp ((i 0))
  (when (< i 10) (vector-set! guards i (make-fluid))))

(define-syntax with-special-soft 
  (lambda (x)
    (syntax-case x ()
      ((_ (x ...) code ...)
       (with-syntax (((((a k) ...) (y ...))
                      (let loop ((i 0) (l #'(x ...)) (r '()))
                        (if (or (= i 10) (null? l))
                            (list (reverse r) l)
                            (loop (+ i 1) (cdr l) (cons (car l) r))))))
        (with-syntax (((i ...) (iota (length #'(a ...)))))                    
            (if (null? #'(y ...))
            #'(with-fluids (((vector-ref guards i) a) ...)
                (with-special* ((i a k) ...)
                 code ...))
            #'(with-fluids (((vector-ref guards i) a) ...)
                (with-special* ((i a k) ...)
                   (with-special-soft (y ...) code ...))))))))))

(define special-wind-guard (make-fluid (lambda (x) #t)))
(define-syntax-rule (with-special* ((i a k) ...) code ...)
  (dynamic-wind
      (lambda () 
        (set! a (fluid-ref (vector-ref guards i)))
        ...)
      (lambda () 
        code ...)
      (lambda y
        (fluid-set! (vector-ref guards i) a)
        ...)))

(define (f x) 
  (let ((s 0)) 
    (with-special-soft ((s 0)) 
       (let lp ((i 0)) 
          (cond 
             ((>= i 100) s) 
             ((= i 50) (abort-to-prompt 'tag) (lp (+ i 1))) 
             (else (set! s (+ s i)) (lp (+ i 1))))))))

(define k (call-with-prompt 'tag (lambda () (f 1)) (lambda (k . l)
k)))

scheme@(guile-user)> (k)
$1 = 4900
scheme@(guile-user)> (k)
$2 = 8575

Can you spot the bug?

The example works very well with my hardcoded version code and is as
fast as this logic can get, much better than 10x faster because this
case can be very well optimized.

To note here also is that with this code we might get into stack
issues due to the with-special can spoil tail call stack features just
as with-fluids.

WDYT?

/Stefan

Attachment: special.diff
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]