Arc Forumnew | comments | leaders | submitlogin
A "scanner" abstraction: now on arc-wiki.git
5 points by almkglor 5861 days ago | 6 comments
I've uploaded a "scanner" abstraction system on arc-wiki.git

A scanner is simply a perfect subset of lists: they have only two valid operations, car and cdr. indexing off a scanner is not supported; basically the scanner is just a moving pointer across whatever sequence you want to scan. A scanner does not support mutating the underlying data structure being scanned.

I think the best use of scanners is if you want to specially structure strings. For example, your strings might really be a nested definition, however, you might want to use regular expressions to search for certain parts of the string.

I probably should make the creation of scanner types much prettier, since I think the scanner abstraction can be quite useful.



5 points by almkglor 5860 days ago | link

Sitting bored again...

  (def inf-iter (f c)
    " Creates a lazy-list-like scanner whose first element
      is `c' and whose succeeding elements are the result of
      `f' applied on the previous element. "
    (let d nil
      (make-scanner
        'car (fn () c)
        'cdr (fn () (or d (= d (inf-iter f (f c))))) )))

  arc> (= p2 (inf-iter [* 2 _] 1))
  #3(tagged scanner (#<procedure> . #<procedure>))
  arc> (car p2)
  1
  arc> (repeat 10 (= p2 (cdr p2)) (prn (car p2)))
  2
  4
  8
  16
  32
  64
  128
  256
  512
  1024
  nil

-----

4 points by nex3 5860 days ago | link

The more I think about these scanners, the cooler they seem. It's a very neat abstraction, and a great way to integrate laziness into Lisp in a very Lisp-y manner.

-----

1 point by almkglor 5860 days ago | link

It would be neat too if function application would destructure using Arc-side 'car and 'cdr (Scheme side '_car '_cdr, or '__car '__cdr on Arc-wiki now that we have FFI). Basically the requirement for 'apply would be a scanner, not a 'cons; after all, 'apply does not mutate the applied list.

However as is it's possible to use p-m: or kennytilton's dsb (which should really be ds-b: and put on the arc-wiki.git) for destructuring scanners.

Also the syntax for creating scanners should really be neater. Possibly this might help:

  (mac scanner args
    (let (a d) nil
      ( (afn ((opt val . args))
          (if
            (iso opt ''car)
              (= a val)
            (iso opt ''cdr)
              (= d val)
              (err:tostring:pr "Unknown option - " opt))
          (if args (self args)))
        args)
      (w/uniq (a-v d-v a-valid d-valid)
        `(let (,a-v ,d-v ,a-valid ,d-valid) nil
           (make-scanner
             'car (fn ()
                    (if ,a-valid ,a-v
                                 (= ,a-valid t
                                    ,a-v ,a)))
             'cdr (fn ()
                    (if ,d-valid ,d-v
                                 (= ,d-valid t
                                    ,d-v ,d)))))))) 
'inf-iter can then be defined somewhat more neatly as:

  (def inf-iter (f c)
    (scanner
      'car c
      'cdr (inf-iter f (f c))))

All the above untested of course, including the grandparent post ^^ I'm sitting bored in the office ^^

-----

4 points by nex3 5860 days ago | link

Yeah, agreed. In general, I'd like to see ac.scm calling out to Arc functions as much as possible, to maximize the power of in-Arc tinkering via redef/defm, like scanner.

-----

4 points by almkglor 5860 days ago | link

Created a better scanner syntax, based on my idea here:

http://arclanguage.org/item?id=4785

On the git. ^^ It's also somewhat optimizing: the representation is mutated if 'car/'cdr is invoked on the scanner, and the function that captures the expression's environment is replaced with a function which returns the expression's result. Of course, I made sure not to actually measure any so-called improvement in time. ^^

-----

5 points by almkglor 5861 days ago | link

Oh and by the way: scanners are inherently lazy, and won't compute 'cdr unless you actually get it via (cdr scanner)

-----