(def codetree (file)
(trav + 1 (readall (infile file))))
Anything that appears after two newlines and a blank space is treated as code, till there's a line that doesn't begin with a space. This is like the markdown convention, but you don't have to use four spaces; one will do.Incidentally, the code above tells me the number of nodes in the code tree of a file. Not just leaves, which would be
(len (flat (readall (infile file))))
but interior nodes as well. To me this is the best measure of how long a program is. I used to go by lines of code (def codelines (file)
(w/infile in file
(summing test
(whilet line (readline in)
(test (aand (find nonwhite line) (isnt it #\;)))))))
but I found this was encouraging me to do the wrong things.(This kind of test matters because I'm constantly trying to make news.yc shorter as a way of pushing functionality down into Arc.)
Here's trav, btw:
(def trav (f base tree)
(if (atom tree)
(base tree)
(f (trav f base (car tree)) (trav f base (cdr tree)))))
It traverses a tree, doing something at every node. So e.g. CL copy-tree would be (def copy-tree (tree) (trav cons (fn (x) x) tree))
If you're wondering how the second argument to trav in codetree could be 1, it's because a constant when called as a function simply returns itself. This turns out to be quite handy.Numbers _are not_ functions! This kind of attitude is what gets you python's list formatting operator:
>>> "%s" % ("a string",)
'a string'
>>> "%s" % ["a string"]
"['a string']"
I've been burned by that before, and I'm not exactly stupid.
(I don't think this posted the first time. Forgive me if this turns out to be a double.)
edit: Bah, I can't get this code to format properly. How's that for ironic ;)
list_format("%s", ("a string",)
list_format("%s", ("a string",)
("a string",).format("%s")
["a string"].format("%s")
Looking at it on the screen, making it a method call looks far less confusing. Arc treating constants and sequences as functions doesn't seem like the same kind of thinking to me.