Yeah should be pretty easy to do. Easiest way might be to save the html of https://news.ycombinator.com/bookmarklet.html, make your edits, and save it under the static/ subdirectory.
I apologize, I must admit I am terrible at creating Makefiles... I'll make fixing it top priority.
Among other things, I recently added a prototype curly-infix reader, which has been kind of fun coding with, because it makes math bearable, and it makes certain things easier to read. Along with variable negation, it seems quite handy.
examples:
(def isa (a b) {type.a is b})
=> (def isa (a b) (is (type a) b))
cc -o mtl-arc -std=c11 mtl-arc.c
mtl-arc.c: In function ‘new_sym’:
mtl-arc.c:46:2: warning: implicit declaration of function ‘strdup’ [-Wimplicit-function-declaration]
symname(result) = strdup(sym);
^
mtl-arc.c:46:18: warning: assignment makes pointer from integer without a cast [enabled by default]
symname(result) = strdup(sym);
^
mtl-arc.c: In function ‘new_string’:
mtl-arc.c:59:20: warning: assignment makes pointer from integer without a cast [enabled by default]
stringval(result) = strdup(string);
^
mtl-arc.c: In function ‘new_builtin’:
mtl-arc.c:118:15: warning: assignment makes pointer from integer without a cast [enabled by default]
help(result) = strdup(doc);
^
mtl-arc.c: In function ‘char_to_token’:
mtl-arc.c:170:2: warning: return makes pointer from integer without a cast [enabled by default]
return strdup(cbuf);
^
mtl-arc.c: In function ‘split_string’:
mtl-arc.c:194:20: warning: assignment makes pointer from integer without a cast [enabled by default]
*(result + i++) = strdup(token);
^
mtl-arc.c: In function ‘buf_to_string’:
mtl-arc.c:212:2: warning: return makes pointer from integer without a cast [enabled by default]
return strdup(buf);
^
mtl-arc.c: In function ‘read_expr’:
mtl-arc.c:327:4: warning: passing argument 1 of ‘split_string’ makes pointer from integer without a cast [enabled by default]
char **nums = split_string(strdup(token), '/');
^
mtl-arc.c:181:8: note: expected ‘char *’ but argument is of type ‘int’
char **split_string(char *a_str, const char a_delim) {
^
/tmp/ccMru0iN.o: In function `builtin_cos':
mtl-arc.c:(.text+0x3b0e): undefined reference to `sin'
/tmp/ccMru0iN.o: In function `builtin_expt':
mtl-arc.c:(.text+0x3bd2): undefined reference to `pow'
/tmp/ccMru0iN.o: In function `builtin_log':
mtl-arc.c:(.text+0x3c53): undefined reference to `log'
/tmp/ccMru0iN.o: In function `builtin_rand':
mtl-arc.c:(.text+0x3db2): undefined reference to `floor'
/tmp/ccMru0iN.o: In function `builtin_sin':
mtl-arc.c:(.text+0x3e46): undefined reference to `sin'
/tmp/ccMru0iN.o: In function `builtin_sqrt':
mtl-arc.c:(.text+0x3ec7): undefined reference to `sqrt'
/tmp/ccMru0iN.o: In function `builtin_tan':
mtl-arc.c:(.text+0x3f48): undefined reference to `tan'
/tmp/ccMru0iN.o: In function `builtin_trunc':
mtl-arc.c:(.text+0x3fc9): undefined reference to `trunc'
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
The Hacker News codebase is in Arc, and will be for the foreseeable future. All the core domain work is done in it, and we write Arc code every day. When it makes sense for performance or practical reasons we call into Racket, but not frequently enough that we've even bothered exposing nice syntax for it (like anarki's $).
Now running on the new server. DNS may take a bit to update.
Things are running on the latest FreeBSD and Racket, but the code is way behind what I've been working on in HN, so please email me at nick@ycombinator.com if you see anything wonky.
We accumulate modified items and profiles by hooking save-item and save-prof. Then every 30 seconds or so we submit an update batch to Firebase using their REST API.
The biggest pain was fixing up Racket's HTTP libraries to support HTTP pipelining correctly and writing our own streaming JSON serializer than minimizes the frequency and lifetime of allocations.
Ahh, I got a server error when I first tried to look at that; it seems to be working now, though. I've read the tutorial - it does seem pretty good. Thanks for the link :)
I just want to start off by saying that you may want to show your professor Clamp[0]. It is a project I have been working on and my goal is to implement as many features from Arc as possible in Common Lisp. Most of the references are to code for Clamp.
Differences between Arc and Common Lisp.
Lisp-1 vs Lisp-2: Arc is what's know as a Lisp-1. That means that procedures are really just procedure objects stored in regular variables (ie "len" is just a variable in Arc, whose value is a procedure that can calculate the length of a sequence). Common Lisp on the other hand is a Lisp-2. This means that it is possible to have a procedure "len" (which can calculate the length of a sequence), and a variable "len" (which may be the length of a particular sequence), without any conflicts even though they are both named "len". Some people prefer a Lisp-1 because it makes code simpler and shorter (you never have to use something analogous to Common Lisp's funcall), and some people prefer a Lisp-2 because then don't have to deal with conflicts between procedures and variables having the same name.
Special Syntax: Arc provides a special kind of syntax called ssyntax, short for special syntax. Each ssyntax provides a shorter way for writing a common pattern. For example a&b is short for (andf a b), a:b is short for (compose a b), a.b is short for (a b), and a!b is short for (a 'b). The last two are extremely useful for accessing into data structures which I explain more in the next section. I just want to point out that it is possible to write a version of ssyntax in Common Lisp[1][2][3]. There are some issues that come up because Common Lisp is a Lisp-2.
Data Structure Access: In Arc, you can use data structures as procedures. Calling a list with an argument will get that place in the list [ie (x 5) will get the element at index 5 in x.]. Note that this is why the shorthand a.b and a!b are so useful. Anarki takes things a step further by allowing a programmer to define how to coerce types to other types and therefore allows one how to define what happens when you call an arbitrary object as a procedure. Common Lisp provides nothing like any of this.
Procedure Arguments: There are some differences in how procedures are defined and called between Common Lisp and Arc. Arc provides an easy way to destructure and argument. For example it is possible to a procedure to get the first element of a list as just (def car ((a . b)) a). It is possible to implement this feature in Common Lisp[4][5]. There are some slight differences with syntax to define a procedure that has optional arguments or rest arguments. Another difference between the two is that Common Lisp provides something called "keyword arguments". Keyword arguments provide a way of having arbitrary ordered optional arguments. For example I wrote a procedure "group"[6], which does roughly the same thing as both pair and tuple in Arc. There are some versions of Arc that provide keyword arguments (Anarki is not one of them).
Reader Macros: Arc provides a shorthand for lambda functions of one argument (Anarki has extended this feature to provide any number of arguments). It is possible to write [+ _ 5] instead of writing out (fn (_) (+ _ 5)). Common Lisp provides something much more general called "reader macros". Reader macros allow a programmer to design new syntax. While I won't go in depth about reader macros, they allow a programmer to create new syntax within Common Lisp. Using brackets as a shorthand for lambda functions is possible to implement with reader macros.
Module System: Most versions of Arc do not provide a module system.
Debugger: One of the most important differences between the two is Arc's lack of a debugger. AFAIK, the only way to debug Arc code is to include print statements throughout your code (using print statements is actually a really effective way to debug code), and there are ways of creating more advanced debugging techniques through the use of macros. Common Lisp provides a full debugger along with something called "restarts"[7]. The Common Lisp restart system is extremely useful, although it should be possible to implement something similar in Arc.
IDE: Arc does not have any sort of IDE, whereas Common Lisp has Emacs/Slime. I wrote about some of the features Slime provides here[8].
That's fair. I think we worked on the reference because the tutorial seemed pretty good. Do you think we need something in between?
Edit: I thought the tutorial had come up in this thread, but it hasn't. I'm not used to having two questions from newcomers at once :) Are you aware of http://old.ycombinator.com/arc/tut.txt?
These docs (https://arclanguage.github.io/ref/) are the ones I was talking about. I haven't read much, but there's no mention of parentheses anywhere. Also, there are symbols in circles to the left of concepts, e.g. F ! ? M, but no explanation of what they mean.
Generally, the docs seem rather terse to me; there's a lot of stuff that only makes sense now, after reading (http://aphyr.com/posts/301). "Clojure from the ground up" does start slowly, but by the end of Chapter 4, I really understood the idea of recursion and representing code as a tree, something that I don't think I could have got from the Arc docs.
You're right, Clojure is not a bad choice either, in my opinion. It's even more heavily functional than Arc, so it's an excellent way to ease into functional programming. There are certain things I really dislike about Clojure, but on the other hand there are some things I absolutely love about it. I think it gets a lot of things right.
I think Arc is a better language for learning Lisp, but you are correct that Clojure would be better for writing actual applications that do things. Solving actual problems with actual applications can give you a lot of motivation, and motivation is important when learning anything.
The reason I use arc: I can't seem to stop. Before arc I tried to learn common lisp and scheme, but they required me to be persistent, and I kept falling off the wagon. With arc, I didn't need to be persistent. That was the concrete, tangible benefit of minimalism for me: the entire experience seemed to cater to me. There were fewer things that were like, "this may seem overly complex, but there's good reason for it, you'll understand when you gain experience." That argument is almost always a rationalization for accidental complexity (https://en.wikipedia.org/wiki/Accidental_complexity), in my experience.
Eventually I grew more fluent with common lisp and racket as well. You're right that they're more grown-up, and sometimes one needs something grown-up and industrial-strength. But arc was the gateway drug, and I can't seem to outgrow it.
I said this in another thread: "What really got me into arc was writing programs in one split window with the friggin compiler for my language in the other." (http://arclanguage.org/item?id=18954) That's really valuable, because to get really good at programming requires breaking out of every box other programmers create for you. Yes it's more immediately valuable to learn to use a few platforms or libraries. But understanding how they work, the design decisions and tradeoffs that are common to all platforms, that gives you superpowers in the long term.
In fairness, all my experiences predate clojure, which may well have all the same benefits. Several people have switched to it from arc in the past. I'd love to hear about your experiences after you try it out. I haven't much experience with it, though I've heard that the boxes it creates are harder to break out of (https://plus.google.com/110981030061712822816/posts/KaSKeg4v...)
I'm curious what docs you looked at that seemed to require familiarity with lisp. Feedback most appreciated.
Re #2 and #3: I think Clojure also puts a heavy emphasis on closures, first-class functions, and recursion (although it seems you have to jump through a hoop to get TCO working (Java and JavaScript don't support TCO (yet))).
Arc may be more minimal and have simpler macros, but I think it'll take me a lot less time to actually start making things with Clojure because there are more resources available for learning it, and it has good support for making web apps (good libraries, good compiler to JavaScript). The Arc docs seem to be good, but targeted more at people who are already familiar with Lisp.
I tend to learn best by creating things, and seeing as I already know HTML and CSS, a language that would allow me to dive right in by creating web apps would be great.
There's also the fact that if someone asked me why I chose Arc over any other Lisp, I wouldn't really know what to say. I like the sound of your philosophy, but at the moment I don't really have the knowledge to understand how Arc is different from other Lisps (other than by being very minimal).
Maybe once I've got some practical experience and a good grasp of the basic concepts behind Lisp and macros, I might start learning Arc, and be able to appreciate it for what it is.
I'm sorry I insinuated you want something from me. You've done a lot to selflessly help Arc since it was released, probably more than its own authors and I appreciate that. I'm also sorry I upset you.
What I really want from you is exactly nothing. I couldn't give a rat's ass what you choose. I'm pointing out that the chains you find yourself shackled in are of your own creation, in your own imagination.
I mean, I did say I'd help you with whatever your repo was, didn't I? What an ungracious insinuation!
> If pg released Arc 3.2, I know I only need to modify my application to account for the diff between Arc 3.1 to Arc 3.2. That should be a smaller changeset than the changeset between Arc3.1 to Anarki.
You're making some big assumptions about Paul Graham's lack of productivity in the last five years.
> They added to Arc 3.1, but they did not remove from it or modify semantics.
If you define a new function and arc 3.2 happens to define the same name, is that incompatible?
> I also stick with Arc because HN is written in it while I don't know of applications written in Anarki.
I don't understand. Anarki provides the HN codebase just like the arc codebase that constitutes 99% of its code.
> What also prevents someone from being locked in is compatibility, not just tests. Having tests for an incompatible language doesn't help a user when switching the language.
I have no idea what the words you use mean. Tests help you if you're willing to, you know, open a file and write code to make them pass.
This is an unproductive discussion. I'll leave you to keep searching for "compatible" additions to a language that never promised compatibility, where that very concept is utterly meaningless.
This is your main point really. Compatibility is nowhere close in importance.
I stick with Arc because one of its premises is following an axiomatic approach to building up a language. I don't know enough about Anarki to know if it does the same thing. I could be poorly informed. An admittedly casual survey of the source didn't make me confident that it does. I thought Anarki had logic it didn't need. It was also suspicious how little I ended up needing to add to Arc 3.1, at least until the issue of uploads.
I also stick with Arc because HN is written in it while I don't know of applications written in Anarki. I don't know if even Anarki's primary contributor uses it for web apps (do you use Anarki?) If they don't, that's a dangerous sign of building out of love for building, not need. It can be a good way to explore ideas, but not as good of a way to pick a language to write a web application in.
I do see the savior argument though. Pg admits Arc is missing a lot and doesn't recommend people use it, and he's the one who wrote it.
> Pick a repo with tests, and you won't be locked in to it
What also prevents someone from being locked in is compatibility, not just tests. Having tests for an incompatible language doesn't help a user when switching the language. They have to rewrite their program, and what they have in their head is the source of their program, not the source of the language. It's harder to switch.
> How do you know your existing changes to arc 3.1 are "compatible"?
They added to Arc 3.1, but they did not remove from it or modify semantics.
> If someone not called pg magically included file upload atop arc3.1, how would you be sure it was "compatible"?
I wouldn't be sure, it would need testing. But I know without testing Anarki is not compatible with Arc 3.1.
If pg released Arc 3.2, I know I only need to modify my application to account for the diff between Arc 3.1 to Arc 3.2. That should be a smaller changeset than the changeset between Arc3.1 to Anarki.
> The final thing that helps us help you: forget about compatibility.
This isn't your main argument. Whether I used Arc 3.1 or Anarki, the compatibility issue would still be an issue. I agree that breaking compatibility helps, by the way. Me complaining about multipart data in HTTP is, you guessed it, a result of not breaking compatibility. If there was a new version of HTTP that was not compatible with the older ones but communicated with sexps, I'd switch.
But what you really want from me is to use Anarki.
I personally think Arc is a fantastic way to learn Lisp:
#1 Arc is minimal. This makes it a lot easier to learn, because it has so few axioms.
#2 Arc heavily emphasizes recursion, and recursion is fundamental to computing in general. So it's important to understand recursion.
#3 You learn about closures and first-class functions, which are very useful and are used in lots of other languages (including JavaScript, Python, and Ruby).
#4 Arc's macros are simple enough that it's easy to fully understand how they work.
Arc is basically a stripped down minimal Scheme with Common Lisp unhygienic macros. It shouldn't be hard to convert the Scheme code in SICP into Arc.
As to whether Arc would be a good first programming language in general... I don't know. I suspect that if you take two programmers, one learns a functional language first, and the other learns an imperative language first, that they would have radically different mindsets.
Because of the recent surge of parallelism, functional languages have a significant advantage, because immutability and purity give both increased correctness and performance compared to mutability. So I don't think it's a bad idea to learn a more functional language like Arc first.
One big difference is that Arc is very minimal, while Common Lisp has lots of libraries and a large standard library. In Arc, you'll end up writing a lot of stuff yourself. But because Arc tends to be more concise than Common Lisp, this can be fun rather than frustrating.
In large part because Arc is so minimal, it only really has two compound data structures: cons cells and mutable key/value dictionaries.
With a bit of effort, it's possible to use Racket libraries and Racket data structures. It's easier to do this in Arc/Nu and Anarki, compared to Arc 3.1.
Arc also does not have a module system, so name collisions are a very real possibility. If your code base is small this isn't a problem, but it does make it a bit trickier to use libraries written by other people.
Another difference is that Arc takes after Scheme, so it has tail-call optimization and full first-class continuations. Recursion is quite common.
Like Scheme, Arc has a single namespace for both functions and variables, unlike Common Lisp which has separate namespaces.
Arc intentionally makes no promises of backwards-compatibility: new versions of Arc might be radically different and completely break your code. Common Lisp, on the other hand, tends to be very stable, and cares a lot about backwards-compat.
Essentially, you can think of Arc as being very similar to Scheme, but much more minimal and concise, and with Common Lisp style unhygienic macros.
What gives you that feeling? (You might well be right; we don't have much experience being a first language.)
What language you use doesn't matter much, within reason. It's just the easy/fun question to think about. Pick one and try to do things with it. If people around you prefer something, use that. Feel free to ask questions here about any language.
SICP is a pretty good choice. Might make sense to work through regardless of what lisp/language you choose.
It's hard to say. I think most people might be discovering arc and never coming to the forums or our community frontpage: http://arclanguage.github.io. They're probably still using arc 3.1.
I prefer anarki because Arc 3.1 has been around for five years without updates, and we've found some serious bugs in it, and also made some serious improvements (tests, online help).