Reading through the old arcsug.txt http://www.archub.org/arcsug.txt I remember reading this idea about "scanners" by Stephen Ma, which were basically just a string with an index parameter. It seemed somewhat overkill at the time, since you could always store the index cheaply anyway. cref. 'markdown However, recently I thought of a rather nice application for scanners: when the string isn't a basic Arc string. Suppose I've divided a string into words, for purposes of, hmm, calculating the diff between versions of an article ^^. I could store the original article string as my primary representation and compute the word-divided string from it. However, this means that during diff operations I need to store about twice the data I need: the original string representation, and the word-divided version. Now suppose instead that I make my primary representation the word-divided version. This then loses the otherwise-neat ability to access string elements by (str index). I could create a function that simulates this, but then I'd have to compute which word a particular index is in each time. However if instead I could build my own scanner, providing only the 'car and 'cdr interfaces (not 'scar and 'scdr, it wouldn't scan), then I could trivially compute indices: at each 'cdr I increment the index in the current word, and if the current word is ended I move to the next word (a single comparison to a single length). Basically if I had this:: (def scanner-for-list-of-words (ws (o index 0))
(with (l (- (len:car ws) index)
w (car ws)
d nil)
(scanner
'car (fn () (w index))
'cdr
(fn ()
(or d
(= d
(if (is l 1)
(scanner-for-list-of-words (cdr ws))
(scanner-for-list-of-words ws (+ index 1)))))))
'scanner would be trivially writeable using my settable-fn's as: (def scanner args
(let pargs (pair args)
(add-attachment
'car (cadr:alist 'car pargs)
'cdr (cadr:alist 'cdr pargs)
(list))))
(redef car (c)
(aif (get-attachment 'car c)
(it)
(old c)))
(redef cdr (c)
(aif (get-attachment 'cdr c)
(it)
(old c)))
Other implementations are of course possible - for example by tagging scanners as their own type and having 'car/'cdr dispatch from the type (although this will probably complicate the use of 'each if you want to scan with that). |