Arc Forumnew | comments | leaders | submit | kens's commentslogin

I've added some of the missing template files to github. Let me know if there is anything else missing - it's all kind of a mess of files on my end from when I tried to move to arc3.


1 point by aw 2969 days ago | link

Looking much better! The only thing I see missing now is that foundation-doc.tem wants to import docs/hdr1.txt; there's an docs/hdr1.html but not a docs/hdr1.txt.


1 point by kens 2967 days ago | link

I've added hdr.txt; hdr1.txt was going to be a new header, but never actually existed.


Thanks, waterhouse. Where is your math library available? sum look like a convenient construct.


2 points by waterhouse 3033 days ago | link

It is a big fat Arc file on my computer. :-) In fact, the math stuff is just a subset of what's in that file. I suppose "library" probably isn't a good term for it. Should I perhaps put it in a form useful to the general public?

Well, here is a link to my arc3.1 folder (with some irrelevant things removed). The "a" file is the abovementioned big fat Arc file that has everything.

I've done some nonstandard things, like changing the order of expansion of ssyntax so a:b.c = (a:b c), and importing a bunch of Racket functions with $ (which at least is Anarki standard), so you probably can't paste in all my code and have it work, without, so to speak, pasting my version of ac.scm as well. I therefore supply this link, so you can run things directly. The code should probably be fairly understandable (if you know what the function's supposed to do) and it probably won't be very hard to port individual things you want to standard Arc.

By the way, my version of "sum" is simple: (sum f a b) = (reduce + (map f (range a b))), although it's implemented with a loop rather than map/reduce, which is more efficient. arc3.1 has a built-in function called "sum", which is different: (sum f xs) = (reduce + (map f xs)). Somewhere, akkartik had the idea of calling my "sum" function "sumn" (probably similar to "mapn", as in (mapn f a b) = (map f (range a b))), which is probably a reasonable compromise for standardization.


1 point by akkartik 3033 days ago | link

"changing the order of expansion of ssyntax so a:b.c = (a:b c)"

I've wondered about this myself. When wart started out I did what you do just because that was simplest (no precedence). Now I think I do as arc does. Do people have an opinion on what a:b.c should expand to?


3 points by waterhouse 3033 days ago | link

I have a very strong opinion that it should expand to (a:b c), rather than (compose a b.c). I think I've once had a use for the latter, whereas I use the former all the time. Some examples (all of them were run with the former interpretation of a:b.c), found with this shell command:

  $ egrep 'arc> .*[a-z]+:[a-z]+\.[a-z0-9]+' Documents/ARC_LOG

  arc> (def psr (n) (xloop (i isqrt.n) (if (divides i n) i next:dec.i)))
  arc> (def run-markov (mk start n) (when (> n 0) (pr start " ") (run-markov mk rand-elt:mk.start dec.n)))
  arc> (def markov-chain (xt) (w/table u (xloop (xs tokens.xt) (unless no:cdr.xs (push cadr.xs u:car.xs) next:cdr.xs))))
  arc> (let xs (n-of 100000 5) time:no:nrev.xs)
  arc> (let xs (n-of 100000 5) time:no:rev.xs)
  arc> (w/infile ach "ac.scm" (whiler s (errsafe:read ach fail*) fail* prn:len.s))
  arc> pbcopy:sqrt.2
  arc> time:partition.200000
  arc> time:meh.10000
  arc> time:fib.9000
  arc> (def u () (aif car:gm.nil (apply mv prn.nil))
  arc> time:src.generators
  arc> pbcopy:tostring:write.that
  arc> time:no:fib.10000000
  arc> time:log:fib.10000000
  arc> ach:much.1
  arc> ach:much.203
For previous comments on the topic, see:


2 points by akkartik 3033 days ago | link

Have you used ~f.g much? I ended up switching because arc.arc uses ~testify.f in a couple of places. And it seems inconsistent for that to work the other way..


2 points by waterhouse 3033 days ago | link

Interesting case. No, I've never used that; actually, I never use the ~ operator, preferring "no:" (as you can see above). (I take it this is a different arc.arc than the one in arc3.1, as I don't find ~testify.f in there.)

Perhaps you could make ~ a function by itself: the "complement" function.[0] Then you could write ~:testify.f.

[0] Hmm, for some reason "complement" is defined as a macro in arc.arc. I don't think it needs to be that way. I think this would work fine:

  (def complement (f)
    (fn args (no:apply f args)))


1 point by rocketnia 3033 days ago | link

I think it's that way so that 'complement can be used with macros. I don't think I ever use it that way, though. Either I use (~foo ...), where the metafn meaning takes control, or I use ~foo by itself with foo being a function. I don't give it much thought, 'cause there are good alternatives to ~, like the ones you're talking about.


1 point by waterhouse 3033 days ago | link

I don't think this can be used with a macro. It applies f:

  (mac complement (f)
    (let g (uniq)
      `(fn ,g
         (no (apply (unquote f) (unquote g))))))
... Yet it actually does work.

  arc> (mac no-mac (x) `(no ,x))
  #(tagged mac #<procedure: no-mac>)
  arc> ((complement no-mac) 2)
It's clearly using some kind of black magic with the Arc compiler, because macex-ing it makes it fail.

  arc> (macex1 '(complement no-mac))
  (fn gs2704 (no (apply no-mac gs2704)))
  arc> ((fn gs2704 (no (apply no-mac gs2704))) 2)
  Error: "Function call on inappropriate object #(tagged mac #<procedure: no-mac>) (2)"
...Ohai, special cases, printed right there at the top of ac.scm.

        ; the next three clauses could be removed without changing semantics
        ; ... except that they work for macros (so prob should do this for
        ; every elt of s, not just the car)
        ((eq? (xcar (xcar s)) 'compose) (ac (decompose (cdar s) (cdr s)) env))
        ((eq? (xcar (xcar s)) 'complement) 
         (ac (list 'no (cons (cadar s) (cdr s))) env))
        ((eq? (xcar (xcar s)) 'andf) (ac-andf s env))
Well. That explains it, at any rate...

  arc> ((complement no-mac 2 3 4) (is 2 3))

I do like the side effect that (a:b:c x) is the same as (a (b (c x))) even if a,b,c are macros. That's something I'd hate to give up. This seems it could be implemented in either of some ways:

1. [current] A call to 'compose in functional position is special-cased by the compiler. This seems like a bit of a hack, although it's served pretty well and isn't likely to fail in the near future.

2. The thing that expands ssyntax will expand (a:b c ...) to (a (b c ...)). This would be hard and would suck, because then ssyntax would no longer be just intra-symbol. (An "ssexpand" function that just takes a symbol argument would be insufficient.)

2a. If ssexpansion is done by the reader (which I do believe it should be), like how [f _] becomes (fn (_) (f _)), then this might be tolerable. Being a reader change, this will and should apply everywhere, even inside quotes; for example, "(a '(b:c d.e))" would get read as (a (quote (b (c (d e))))). I think this might be something to aim for.

3. We make macros first class, so they can be applied, and probably make the compiler capable of optimizing such cases. I think this, combined with (2a) as a cheap way to optimize, would be good.


3 points by rocketnia 3033 days ago | link

Yet it actually does work.

That's the metafn meaning I was talking about. >.>


This seems it could be implemented in either of some ways

My preferred way, which you didn't mention, is to have macros return intermediate things that can either be unwrapped into expressions or applied as syntax operators themselves. That way "compose" can be a syntax operator and "(compose a b c)" can also be a syntax operator. I describe this idea in context with several of my other ideas in, "A rough description of Penknife's textual syntax."

In the past couple of days, I've also been toying with the idea of having : be a read macro. It can start a list and stop once it reaches an ending bracket, without consuming that bracket. This would be similar in effect to

  (accum acc: each x args: acc:* 2 x)
One thing it gives up is the ability to say (map a:b c); you have to say (map [a:b _] c) instead. Also, it doesn't give you a:b.c, and it's not clear to me how to indent it. :-p

I don't see a good read macro equivalent for a.b; a read macro has to come before the things it reads, like "!a b", but chaining with "!!!!a b c d e" wouldn't be nearly as nice. Any reader-level solution for a.b ssyntax would probably need to ditch the Racket reader (or at least ditch it within certain delimiters), and it would probably use something like Penknife's or ar's approach, biting off a block of text somehow--using brackets, line breaks, whitespace, or whatnot--then parsing it all at once. ...Technically we might be able to replace Racket's list syntax with a syntax that keeps a public stack of subexpressions, and then have . pop off of that stack, but that strategy doesn't help at the top level.

Oh, PS: Semi-Arc is another Arc-like which implements ssyntax in the parser.


1 point by akkartik 3033 days ago | link

Yeah, in wart call started out as just funcall then turned into a macro so it could handle macros. Hmm, would I need a transform to get that if I somehow make wart a lisp-1?

Also, it always bugged me that call needed to be aware of compose. But now that I have open def it's cleaner.


1 point by akkartik 3033 days ago | link

Oh you're right, the original arc.arc has versions without ssyntax:

  (def all (test seq)
    (~some (complement (testify test)) seq))

  (def keep (test seq)
    (rem (complement (testify test)) seq))


1 point by evanrmurphy 3033 days ago | link

When I read this, I was surprised to learn that Arc doesn't do it waterhouse's way!

I haven't used this ssyntax combo enough to hold a nuanced view, but a:b.c => (a:b c) seems most intuitive to me.


3 points by kens 3093 days ago | link | parent | on: News.arc for newbies

I've written up a detailed analysis of the published parts of the news.arc ranking algorithm:

I noticed that a few pieces of the algorithm were not released, and the algorithm has surely changed since arc3.1, but the published code explains at least the overall behavior of Hacker News ranking.


I assume you're using Anarki, because standard Arc doesn't have any of those escape valves other than system, which I find quite annoying.


4 points by aw 3475 days ago | link

If you prefer not to have all the changes that Anarki makes to Arc, the patch adds just the ability to drop into Scheme from Arc.


2 points by akkartik 3474 days ago | link

And once you have $/ac-scheme, you can load libraries through scheme's FFI, or load scheme libraries say for parsing json.

I'm not using anarki, just pieces that I like.

(sorry, addressing grandparent)


3 points by kens 3481 days ago | link | parent | on: Arc beats Python for a web-controlled stereo

I didn't think of using arg; that's obviously better.

Yes, the code parameter is written to the serial port, where it is received by the Arduino microcontroller board. This board does the work of generating the IR signal corresponding to the code. The details are at


4 points by kens 3482 days ago | link | parent | on: Arc beats Python for a web-controlled stereo

I should have said:

"Arc requires the clearing of srvops* unless you want the webserver to respond to a dozen URLs in unexpected ways."

Specifically, the Arc web server automatically implements /login, /logout, /whoami, /admin, /mismatch, and various other things, unless you clear out srvops*. I don't know that any of these are security holes, but I'd rather disable them since I don't want them.


1 point by thaddeus 3481 days ago | link

I see.


2 points by kens 3502 days ago | link | parent | on: Two recent discoveries: diskvar, defcache

New features such as diskvar, defcache, datestring, memory, positions, and many others are listed in my article "What's new in Arc 3":

Unfortunately I haven't updated the full documentation to include Arc 3 features.


3 points by kens 3516 days ago | link | parent | on: Simple genome analysis with Arc

Oh, yeah, I forgot that Arc 3 has default values for table. Someone should write some documentation on this :-)

Thanks for the suggestions; I've updated my blog post.


2 points by kens 3591 days ago | link | parent | on: Arc + Arduino + ARM

Now that Arc runs on mzscheme 4.x, it's really easy to run Arc on a SheevaPlug; it's just the same as any other Linux box.

I had tried running Arc on the SheevaPlug in the mzscheme 372 era, but that was a disaster. Mzscheme 372 isn't available for the ARM processor, so I tried compiling it myself, but the ARM FFI support wasn't there yet, so the compile broke, and I tried to work around that but ended up in a maze of compilation errors. But now you can just install the mzscheme 4.x package and you're set.

As for the MIMO USB-based monitor, also see the thread at It seems easier to just buy a computer with video in the first place, but maybe that's just me :-)


1 point by thaddeus 3591 days ago | link

I was thinking along the lines of automation lines/robotics or remote location web services running automation..... ie. you could walk up to one of many remote sheevas then hook up a portable mimo monitor to interface with it.

Arc having an interpreter where the program can dynamically be updated should be huge! potentially no downtime to optimize an algorithm running a production line - would save big $$$$.


2 points by kens 3601 days ago | link | parent | on: Mapa-b

There's documentation at:


2 points by absz 3600 days ago | link

Yes, and you are an awesome person for doing that. However, I don't think anything "official" links to, so finding it is a bit difficult. And of course you haven't documented every single one of the bajillion little changes on Anarki, because you are a human being and need sleep.

Nevertheless, (isa " 'awesome-thing).