Arc Forumnew | comments | leaders | submitlogin
1 point by akkartik 5458 days ago | link | parent

My refactoring with several general utilities:

  (mac init args
    `(unless (bound ',(car args))
       (= ,@args)))

  (mac after* block
    (let (body finally) (split-by block ':do)
      `(after
         (do ,@body)
         (do ,@finally))))

  (mac redef(var expr)
    `(after*
       (set disable-redef-warnings*)
       (= ,var ,expr)
      :do
       (wipe disable-redef-warnings*)))

  (mac after-exec(fnname args . body)
    `(let old ,fnname
        (redef ,fnname
              (fn ,args
                (let result (old ,@args)
                  ,@body
                  result)))))

  ;; dynamic scope when writing tests
  (mac shadow(var expr)
    (let stack (globalize stringify.var "-stack")
      `(do
         (init ,stack ())
         (push ,var ,stack)
         (redef ,var ,expr))))

  (mac unshadow(var)
    (let stack (globalize stringify.var "-stack")
      `(do
        (if (or (~bound ',stack)
                (empty ,stack))
           (prn "*** couldn't unshadow " ',var)
           (redef ,var (pop ,stack)))
        nil)))

  (mac shadowing(var expr . body)
    `(after*
       (shadow ,var ,expr)
       ,@body
      :do
       (unshadow ,var)))

  (mac count-cons(expr)
    (w/uniq cons-count
    `(shadowing cons cons
        (let ,cons-count 0
          (after-exec cons(x y)
            (++ ,cons-count))
          (after
            ,expr
            (prn "consed " (plural ,cons-count "time") "."))))))

  (def split-by(seq delim)
    (case type.seq
      cons    (split seq (or (pos delim seq) (len seq)))
      string  (split seq (or (posmatch delim seq) (len seq)))
              (err "bad type for split-by")))


1 point by fallintothis 5443 days ago | link

Rather random thing to comment on after 2 weeks, I know. I was just reading this and noticed that your redef macro isn't really doing much: safeset doesn't get called by = unless you happen to make a defset to that effect, which seems unlikely.

  arc> (def f (x) (+ x 1))
  #<procedure: f>
  arc> (= f [+ _ 2])       ; no redef warning
  #<procedure: f>
  arc> (def f (x) (+ x 3)) ; redef warning
  *** redefining f
  #<procedure: f>

  arc> (defset blah (x)
         (w/uniq g
           (list (list g x)
                 x
                 `(fn (val) (safeset ,x val)))))
  #<procedure>
  arc> (= x 100)
  100
  arc> (= x 200)        ; no redef warning
  200
  arc> (= (blah x) 300) ; redef warning
  *** redefining x
  300
Still an interesting idea to selectively silence safeset, though.

-----

1 point by akkartik 5441 days ago | link

Ah, that's embarrassing :)

So all I need is this then without any change to safeset:

  (mac redef(f args . body) `(= ,f (fn ,args ,@body)))

-----

1 point by fallintothis 5441 days ago | link

Right. So then after-exec becomes (keeping the presumably-intended variable capture)

  (mac after-exec (fnname args . body)
    `(let old ,fnname
       (redef ,fnname ,args
         (let result (old ,@args)
           ,@body
           result))))
And your uses of redef when you aren't redefining a function should be changed to = (e.g., in shadow).

It might still be cool to toggle safeset warnings. With Arc's single namespace, it's annoying to

  (load "foo.arc")
just to have it spit out redefinition warnings. But silencing safeset isn't really the answer to that problem.

-----

1 point by akkartik 5441 days ago | link

Yes. When I updated anarki I decided to just do

  (= redef =) ; how pretty!
It seems plausible to want redefs to look different from defs.

Disabling these warnings on reload is useful, but a separate use case. I tend to ignore them on reload, but I don't want to see them when I startup lest I start ignoring them altogether.

-----

1 point by akkartik 5457 days ago | link

redef controls whether the "redefining var" warnings are displayed. I changed the safeset macro thus at the start of arc.arc:

  (assign disable-redef-warnings* nil)
  (assign safeset (annotate 'mac
                    (fn (var val)
                      `(do (if (is nil disable-redef-warnings*)
                           (if (bound ',var)
                               (do (disp "*** redefining " (stderr))
                                   (disp ',var (stderr))
                                   (disp #\newline (stderr)))))
                           (assign ,var ,val)))))

-----