www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

assumption-weak-hash.rkt (4902B)


      1 #lang racket
      2 
      3 ;; We use a weak hash to associate a pvar xᵢ with its the values contained in
      4 ;; the derived yᵢ. The assumptions below must hold, otherwise we would risk
      5 ;; memory leaks.
      6 
      7 (require (for-syntax racket/private/sc)
      8          rackunit
      9          version-case)
     10 
     11 (define h (make-weak-hasheq))
     12 
     13 (define (all-eq? l)
     14   (foldl (λ (x acc)
     15            (and (eq? x acc) acc))
     16          (car l)
     17          (cdr l)))
     18 
     19 ;; The data stored in the valvar is unique fore each use of (datum->syntax …)
     20 (check-false
     21  (check-duplicates
     22   (for/list ([range-a (in-range 5)])
     23     (with-syntax ([(xᵢ ...) (datum->syntax #'here '(1 2 3))])
     24       (define-syntax (hh stx)
     25         #`(hash-ref! h
     26                      #,(syntax-mapping-valvar
     27                         (syntax-local-value #'xᵢ))
     28                      (gensym)))
     29       (all-eq? (for/list ([range-b (in-range 5)])
     30                  (collect-garbage)
     31                  (collect-garbage)
     32                  (collect-garbage)
     33                  (hh)))))))
     34 
     35 ;; but not if the syntax object is a constant, e.g. #'(1 2 3), in Racket < 6.7
     36 ;; I'm not sure how this affects subtemplate in Racket ≥ 6.7, but I suppose it
     37 ;; is not a problem, as the beahviour is the same as in the general case where
     38 ;; the syntax object is not constant.
     39 (check-pred (version-case
     40              [(version< (version) "6.90") all-eq?]
     41              [else (negate all-eq?)])
     42             (for/list ([range-a (in-range 5)])
     43               (with-syntax ([(xᵢ ...) #'(1 2 3)]) ;; CHANGED THIS LINE
     44                 (define-syntax (hh stx)
     45                   #`(hash-ref! h
     46                                #,(syntax-mapping-valvar
     47                                   (syntax-local-value #'xᵢ))
     48                                (gensym)))
     49                 (all-eq? (for/list ([range-b (in-range 5)])
     50                            (collect-garbage)
     51                            (collect-garbage)
     52                            (collect-garbage)
     53                            (hh))))))
     54 
     55 ;; nor it the same syntax object is reused, in Racket < 6.7
     56 ;; I'm not sure how this affects subtemplate in Racket ≥ 6.7, but I suppose it
     57 ;; is not a problem, as the beahviour is the same as in the general case where
     58 ;; the syntax object is not shared.
     59 (define stxobj (datum->syntax #'here '(1 2 3))) ;; cached stxobj here
     60 (check-pred (version-case
     61              [(version< (version) "6.90") all-eq?]
     62              [else (negate all-eq?)])
     63             (for/list ([range-a (in-range 5)])
     64               (with-syntax ([(xᵢ ...) stxobj]) ;; CHANGED THIS LINE
     65                 (define-syntax (hh stx)
     66                   #`(hash-ref! h
     67                                #,(syntax-mapping-valvar
     68                                   (syntax-local-value #'xᵢ))
     69                                (gensym)))
     70                 (all-eq? (for/list ([range-b (in-range 5)])
     71                            (collect-garbage)
     72                            (collect-garbage)
     73                            (collect-garbage)
     74                            (hh))))))
     75 
     76 
     77 ;; Another example showing this behaviour:
     78 ;; The contents of the valvar is eq? when using a literal syntax object like:
     79 ;;     #'(1 2 3)
     80 ;; but not with:
     81 ;;     (datum->syntax #'here '(1 2 3))
     82 ;; I expected the result to always be different at each execution of the
     83 ;; with-syntax, but it turns out the syntax object is kept as-is.
     84 ;;
     85 ;; With racket ≥ 6.7, the syntax object is different, i.e. not eq?, in every
     86 ;; invocation of with-syntax.
     87 (begin
     88   (let ()
     89     (define old1 #f)
     90 
     91     (check-true
     92      (andmap identity
     93              (for/list ([range-a (in-range 100)])
     94                ;; #'(1 2 3) HERE:
     95                (with-syntax ([(xᵢ ...) #'(1 2 3)])
     96                  (define-syntax (hh stx)
     97                    #`#,(syntax-mapping-valvar (syntax-local-value #'xᵢ)))
     98                  (if (not old1)
     99                      ;; Initial set!
    100                      (set! old1 (hh))
    101                      (andmap identity (for/list ([range-b (in-range 5)])
    102                                         ((version-case
    103                                           [(version< (version) "6.90") eq?]
    104                                           [else (negate eq?)])
    105                                          old1
    106                                          (hh))))))))))
    107 
    108   (let ()
    109     (define old2 #f)
    110 
    111     (check-equal?
    112      (let ([res (for/list ([range-a (in-range 100)])
    113                   ;; CHANGED THIS:
    114                   (with-syntax ([(xᵢ ...) (datum->syntax #'here '(1 2 3))])
    115                     (define-syntax (hh stx)
    116                       #`#,(syntax-mapping-valvar (syntax-local-value #'xᵢ)))
    117                     (unless old2
    118                       ;; Initial set!
    119                       (set! old2 (hh)))
    120                     (andmap identity (for/list ([range-b (in-range 5)])
    121                                        (eq? old2 hh)))))])
    122        (list (car res) (ormap identity (cdr res))))
    123      '(#t #f))))