Arc Forumnew | comments | leaders | submit | akkartik's commentslogin
3 points by akkartik 1 day ago | link | parent | on: Quitting the arc server

Not a dumb question at all; there may well be something broken here.

It'll be a few hours before I can try running it, but one possibility: perhaps it will quit after serving one further request? Looking at the code ( I think it's waiting on serve-socket before it gets around to checking quitsrv again. Can you try that if you haven't already?


2 points by noobie 13 hours ago | link

Thank you for your help!! Could you help me understand what you'd like me to do?

I'm not sure what you think I should try.

After looking up the definition of the 'until' macro, the line of code referenced seems to tell me: if quitsrv* is not nil, then continue to serve-socket, which looks to me, at a noobie's glance, as returning the function "accept-request-with-deadline", opening up threads to serve the request?

i.e., quitsrv* now returns t. According to this definition, doesn't that mean that serve-socket should stop?

And incidentally, when I run more defop macro calls, it returns the 'procedure' but (asv) doesn't work; none of the new page on localhost show up (instead it is "Unknown"). I'll look more into it but not really sure how to proceed after glancing at (def asv).

I've copied down the definitions for while and whilet from arc.arc but they don't seem helpful at first glance. Will look further into them if you think it would be useful.

Thank you!!


1 point by akkartik 8 hours ago | link

Not at all. I meant that if your server doesn't serve much traffic it'll spend much of its time inside serve-socket blocked on a new connection. It's only after serving a connection that it'll loop around to check quitsrv.

I just ran an experiment, and indeed the server stops after one more request:

    $ ./run-news
    initializing arc..
    ready to serve port 8080
    arc> (= quitsrv* t)
    ; now browse to localhost:8080; page served
    quit server ; printed by *serve*
    ; hit reload on localhost:8080; no response


I don't really know Heroku, sorry, but to answer your final question: It was a while ago, but I used to host an Arc webapp on a VPS behind Apache/Nginx.


3 points by matthewwiese 7 days ago | link

Cool, thanks for the reply :) I've seen it discussed elsewhere that the way to have SSL (at least with the News example in the repository) is to run through Nginx.

Did that complicate your setup by much?


5 points by shader 7 days ago | link

I've recently discovered the Caddy server (, which makes SSL and application proxy deployments super easy. Like, 2 lines of config:               #uses the domain to automatically set up SSL with Let's Encrypt
  proxy / localhost:8080   #redirect everything to Arc on 8080
I will say that Arc runs a bit resource intensive, and the slightly slow boot times mean you don't want it to have to re-launch because of infrequent requests. I don't know how well it would work on Heroku.

Also, some VPS services like offer $5/mo nodes that have more resources than what you get from Heroku at $7/mo anyway.


4 points by shader 7 days ago | link

I should mention that if what you want from Heroku is their deployment process, you can actually replicate some of it pretty easily with Caddy (though I have not done so yet myself; I plan to soon...)

Specifically, they have support for automatically fetching code from git and running a command in the repo, either periodically or triggered by a webhook:

That doesn't get you the app ecosystem that heroku offers, but you can get a lot of that pretty easily via docker and docker-compose now.


Hmm, I don't think pg has abandoned Arc. And I don't think maintaining compatibility is a concern even so. So far Arc has made no compatibility guarantees. We're all forking pre-alpha software. So it's conceivable the hundred-year language will have features from Anarki. Forks that restrict where they get good ideas from will be outcompeted by forks that don't.

Though lately I consider it more likely that a hundred-year language will have a leveled-up conception of "compatiblity", one that assumes orders of magnitude more forking activity. (See "the Zen of Mu" at the bottom of; Mu is my attempt at building out the foundations for a hundred-year stack. With, perchance, something like Arc on top.) Perhaps Arc shouldn't be a single language but a family of forks ( Not a single tree but a clonal colony ( That'll only work if we can make it easy for superficially-incompatible forks to exchange features and functionality back and forth. Which is an unsolved problem so far. So we may well be very far from a hundred-year language.

Anyways, this tangent is my contribution. I don't have a short-term answer for how to solve Arc's users-vs-libraries chicken-and-egg problem ^_^


4 points by shader 16 days ago | link

> I don't have a short-term answer for how to solve Arc's users-vs-libraries chicken-and-egg problem ^_^

Be the change you want to see in the world... I'm not really sure how to motivate the community, but I am rather attached to it, even if I have been a very infrequent lurker over the past years. We have had a relatively high amount of discussion over the past few days though...

I don't think we can just expect to flip a switch and suddenly get a community; we have to /be/ a community, and then people might be willing to join us.


3 points by shader 16 days ago | link

Maybe we should emphasize the flexibility of our language designs by making the language itself more modular. It would be challenging from a compatibility/dependency standpoint, but those are problems we might have to solve anyway. It would help to have better isolation of components.


2 points by hjek 16 days ago | link

I agree.

Some newbie friendly documentation to ns.arc would be great, or perhaps some very simple examples. Have you tried using ns.arc?


2 points by rocketnia 12 days ago | link

It looks like I might've subtly broken ns.arc with my own changes to make Anarki installable as a Racket package. Here's an example that should be working, but currently isn't:

  ; my-file.arc
  (= n 2)
  (= my-definition (* n n))
    (= my-definition
      (let my-ns (nsobj)
        ; Populate the namespace with the current namespace's bindings.
        (each k (ns-keys current-ns)
          ; Racket has a variable called _ that raises an error when
          ; used as an expression, and it looks like an Arc variable, so
          ; we skip it. This is a hack. Maybe it's time to change how
          ; the Arc namespace works. On the other hand, copying
          ; namespaces in this naive way is prone to this kind of
          ; problem, so perhaps it's this technique that should be
          ; changed.
          (unless (is k '||)
            (= my-ns.k current-ns.k)))
        ; Load the file.
        (w/current-ns my-ns (load "my-file.arc"))
        ; Get the specific things you want out of the namespace.
  arc> n
  _n: undefined;
   cannot reference an identifier before its definition
    in module: "/home/nia/mine/drive/repo/mine/prog/repo/not-mine/anarki/ac.rkt"
The idea is, you create an empty Arc namespace with (nsobj), you use `w/current-ns` to load a file into it, and you use `a!b` or `a.b` syntax to manipulate individual entries.

An "Arc namespace" is just a convenience wrapper over a Racket namespace that automatically converts between Arc variables `foo` and their corresponding Racket variables `_foo`.

For some overall background...

I wrote ns.arc when I didn't have much idea what Racket namespaces or modules could do, but I was at least sure that changing the compiled Arc code to more seamlessly interact with Racket's `current-namespace` would open up ways to load Arc libraries without them clobbering each other. It wouldn't be perfect because of things like unhygienic macros, but it seemed like a step in the right direction.

I went a little overboard with the idea that Racket namespaces and Racket modules could be manipulated like Arc tables. However, that was the only clear vision I had when I embarked on writing the ns.arc library, so I approximated it as well as I could anyway. In fact, I don't think the utilities for generating first-class modules (like `simple-mod` and `make-modecule`) are all that useful, because as I understand a little better now, Racket modules are as complicated as they are mainly to support separate compilation, so generating them at run time doesn't make much sense.

I'm still finding out new things about what these can do, though. Something I didn't piece together until just now was that Racket has a Racket has a `current-module-name-resolver` parameter which can let you run arbitrary code in response to a top-level (require ...) form. I presume this would let you keep track of all the modules required this way so you can `namespace-attach-module` them to another namespace later. Using this, the kind of hackish partial-namespace-copying technique I illustrate above can probably be made into something pretty robust after all, as long as Anarki sets `current-module-name-resolver` to something specific and no other code ever changes it. :-p


2 points by rocketnia 2 days ago | link

I tinkered with Anarki a whole bunch and finally got this working smoothly. There was a missing step, because it turns out we need to load certain Racket-side bindings into a namespace in order to be able to evaluate Arc code there. It seems more obvious in hindsight. :)

I approached this with the secondary goal of letting a Racket program (or a determined Arc program) instantiate multiple independent intances of Anarki. The ac.rkt module was the only place we were performing side effects when a Racket module was visited, and Racket's caching of modules makes it hard to repeat those side effects on demand, so I moved most of them into a procedure called `anarki-init`.

By adding one line to the example I gave...

  (= my-definition
    (let my-ns (nsobj)
      ; Load the Arc builtins into the namespace so we can evaluate
      ; code.
      (w/current-ns my-ns ($.anarki-init))

      ...)) becomes possible to evaluate Arc code in that namespace, and the example works.

I used issue #95 on GitHub to track this task, and I talk about it a little more there:

Before I started on that, I did a bunch of cleanup to get the Anarki unit tests and entrypoints running smoothly on all our CI platforms. To get started on this cleanup, I had a few questions hjek and akkartik were able to discuss with me on issue #94:

A lot of the problems I'm fixing here are ones I created, so it's a little embarrassing. :) It's nice to finally put in some of this missing work, though. I want to say thanks to shader and hjek for talking about modules and packages, provoking me to work on this stuff!


2 points by akkartik 2 days ago | link

And thank you :) I'm glad you got something out of it, because the project's certainly better for it.


3 points by shader 16 days ago | link


I was confused for a second or two, because the current top post on that site is almost identical to the one you commented on a year ago.

(What are you working on this week? by caius)


2 points by hjek 16 days ago | link

> Forks that restrict where they get good ideas from will be outcompeted by forks that don't.

That is so true. LibreOffice and Gitea come to mind, but also what happened with io.js/nodejs.


No I didn't try it..


1 point by akkartik 43 days ago | link | parent | on: The cargo cult of versioning

I updated my original post based on conversations I had about it, and my updated recommendation is towards the bottom:

"Package managers should by default never upgrade dependencies past a major version."

I now understand the value of version pinning. But it seems strictly superior to minimize the places where you need pinning. Use it only when a library misbehaves, rather than always adding it just to protect against major version changes.


CI integrated with a package manager would indeed be interesting. Hmm, it may disincentivize people from writing tests though.


2 points by shader 42 days ago | link

A reduced need for tests may not be a bad thing.

We don't write tests just to have tests, but to verify that certain important functionality is preserved across versions. The trouble with many tests, is that they are written to fill coverage quotas, and don't actually check important use cases. By using actual dependents and _their_ tests as a test for upstream libraries, we might actually get a better idea of what functionality is considered important or necessary.

Anything that nobody's using can change; anything that they rely on should not, even if it's counter intuitive.

The problem remains that most user code will still not exist in the package manager. It might be more effective if integrated with the source control services (github, gitlab, etc.), which already provide CI and host software even if it's not intended to be used as a dependency. The "smart package" system could then use the latest head that meets a specified testing requirement, instead of an arbitrary checkpoint chosen by the developers.


2 points by akkartik 42 days ago | link

Oh, I just realized what you meant. Yes, I've often wanted an open-source app store of some sort where you had confidence you had found every user of a library. That would be the perfect place for CI if we could get it.

Perhaps you're also suggesting a package manager that is able to phone home and send back some sort of analytics about function calls and arguments they were called with? That's compelling as well, though there's the political question of whether people would be creeped out by it. I wonder if there's some way to give confidence by showing exactly what it's tracking, making all the data available to the world, etc. If we could convince users to enter such a bargain it would be a definite improvement.


2 points by shader 40 days ago | link

I wasn't really considering that level of integration testing. It would certainly be cool to get detailed error reports from the CI tool. I don't see why you couldn't, since the code is published on the public package system, and you would be getting error listings anyway.

I don't think it would be creepy as long as it's not extracting runtime information from actual users. If it's just CI test results, it shouldn't matter.

Live user data would be a huge security risk. Your CI tests could send you passwords, etc., if they happen to pass through your code during an error case.


2 points by akkartik 42 days ago | link

I wasn't saying there'd be a reduced need for tests. It's hard for me to see how adding CI would reduce the need for tests. I'm worried that people will say this stupid CI keeps failing, so "best practice" is to not write tests. (The way that package managers don't enforce major versions, so "best practice" has evolved to be always pinning.)

Unnecessary tests are an absolutely valid problem, but independent :)


2 points by shader 40 days ago | link

By "reduced need for tests" I didn't mean that the absolute number of tests would decline, but rather the need and incentives for the development team to write the tests themselves. Since they have the ecosystem providing tests for them, they don't need to make as many themselves. At least, that's how I understood the discussion.

So yes, if the package manager only enforced the tests you include in your package it would incorrectly discourage including tests. But if it enforces tests that _other_ people provide, you have no way around it. The only problem is how to handle bad tests submitted by other people. Maybe only enforce tests that passed on a previous version but fail on the current candidate?


1 point by akkartik 40 days ago | link

Ooh, that's another novel idea I hadn't considered. I don't know how I feel about others being able to add to my automated test suite, though. Would one of my users be able to delete tests that another wrote? If they only have create privileges, not update, how would they modify tests? Who has the modification privileges?

These are whole new vistas, and it seems fun to think through various scenarios.


2 points by shader 37 days ago | link

It's not really the same as others being able to add tests to your automated suite. Rather, they add tests to their own package, and then the CI tool collects all tests indirectly dependent on your library into a virtual suite. Those tests are written to test their code, and only indirectly test yours. If a version of their package passes all of their tests with a previous version of your code, but the atomic change to the latest version of your code causes their test to fail, the failure was presumably caused by that change. The tests will probably have to be run multiple times to eliminate non-determinism.

It's still possible that someone writes code that depends on "features" that you consider to be bugs, or a pathologically sensitive test, so there may need to be some ability as the maintainer to flag tests as poor or unhelpful so they can be ignored in the future. Hopefully the requirement that the test pass the previous version to be considered is sufficient to cover most faulty tests though.


1 point by akkartik 37 days ago | link

Yes, this was kinda what I had in mind when I talked about an open source app store. Make it easy for libraries to be aware of how they're used.


2 points by shader 34 days ago | link

It doesn't look like it would be too hard to start building such a system on top of Github; they provide an api for seaching for repos by language.

We could potentially build it first for Arc, which would be pretty small and simple, but also provide the package manager we've always wanted :P


You're passing in a function to gt10, and the article does admit that that is doable everywhere:

"The trick is to change the unit of currency from passing source code to passing functions."

But try passing in '(pr msg) as a list to gt10.


4 points by akkartik 87 days ago | link | parent | on: Poll: What's the best payment system?

We don't have access to the actual code running live on the site, but looking at policies from back in 2009 or so, it looks like you may have run afoul of the sockpuppet detector: That's too bad; sockpuppet detection is overkill for a site this niche.

Try it now on some other vote (votes on polls seem to be using the same code as votes on stories or comments). If your vote sticks now, that would confirm my hypothesis. (


5 points by i4cu 87 days ago | link

BTW I'm thaddeus. I check in once in a blue moon, but decided to vote on this and forgot my password so I created another account;).

And it looks as though, because I created the account seconds before voting, I failed at least one test in 'legit-user':

  new-karma-threshold* 2
It's possible I failed new-age-threshold* too, but I wasn't all that interested in investigating further.

I dunno; I understand the reasoning, but it still seems like a bad design choice. I'd much rather, circumstantially, be put through a better legit-user test on account creation than to see a forum introduction like that. Oh well, the odds are low for a new user to vote on a poll as a first action anyway. I just seem to always beat the odds :) haha.


5 points by akkartik 125 days ago | link | parent | on: Ask ARC: Can I start with Arc?

Thanks for the reminder! Your comment reminded me that the Arc tutorial ( doesn't quite match the state of Anarki, so I created copies of the tutorial for both stable and master branches at

The stable branch uses the Arc tutorial unchanged. All I did was to make it a little easier to read:

The master branch of Anarki has one major incompatibility with Arc 3.1, and I created a version of the tutorial with it highlighted in bold:

micoangelo, if you decide to try out Arc, be sure to start at rather than the instructions here at Even if you use the stable branch which is compatible with Arc 3.1, it has a couple of crucial bugfixes that are otherwise liable to bite you at an inopportune moment.


5 points by akkartik 127 days ago | link | parent | on: Ask ARC: Can I start with Arc?

I think "learning Lisp" is Arc's best niche. So yes, try using it and come ask us questions. Feel free to also ping me over email, that is sometimes faster. My address is in my profile.

One caveat: it can be easier to learn from a book if you follow the language it was written for. Land of Lisp is a fine book by all accounts, so if you use it you may be better off just using Common Lisp or whatever. But feel free to come ask questions anyway. Maybe we can show you both Common Lisp and Arc versions of programs.


Whoa, I could have sworn I responded to this one :/

rocketnia is right that I tend to just run Arc from within its directory, keeping it alongside any Arc program I may be working on at the moment. As a result, I'd kinda always assumed you could run it from anywhere and find yourself in the Arc directory once you loaded up. Now I find this isn't the case:

  $ pwd
  $ ./anarki/
  arc> ($:current-directory)
This was initially surprising, but of course we're only parameterizing the current directory while loading libraries:

I'm not sure what to do about this. In addition to rocketnia's `current-load-file*` suggestion, should we just expose `arc-path` from boot.scm? I couldn't immediately see how to get to it from Arc.