https://github.com/wting/hackernews
This is a great place to start with understanding Arc, as the jump to Anarki (an Arc fork) will make more sense as it comes bundled with News - a Hacker News style app - which is fun to play with if you have experience with HN and want to try a variation of this site.
arc> (= l '(1 2 3))
(1 2 3)
arc> (= f [+ _ 1])
#<fn: f>
arc> (map l '(0 1 2))
(1 2 3)
arc> (map f '(0 1 2))
(1 2 3)For the benefit of people familiar with Common Lisp:
* (= ...) is assignment, not equality testing
* (map list index-list) is equivalent to (loop for index in index-list collecting (nth index list)), or in a more FP style (mapcar (rcurry #'nth list) index-list)
* (map function list) is equivalent to (mapcar function list)
I think your example would have been less confusing if it used larger numbers to highlight where addition was happening and where indexing was happening: arc> (= l '(4 5 6))
(4 5 6)
arc> (= f [+ _ 10])
#<fn: f>
arc> (map l '(2 1 0 0))
(6 5 4 4)
arc> (map f '(0 1 2))
(10 11 12)And looks like an easy trap for misreading code ...
arc> (map l '(0 1 2))
(1 2 3)
What is the logic here? Is l made into a function that holds state and returns each element in turn (like an iterator function)? Because I would've expected: arc> (map l '(0 1 2))
((1 2 3) (1 2 3) (1 2 3))
In what way is map being applied here?> In Arc, data structures can be used wherever functions are, and they behave as functions from indices to whatever's stored there.
(quoted from the Arc tutorial)
So
arc> (l 0)
1
and so on. So the GP makes sense. 1
and l
in the same code listing.Clojure is definitely better thought out as a language, and while Arc has some interesting ideas around web development, it also doesn't have a module system, so everything is just loaded into the same global namespace, which is pretty insane.
To say they are functions would be incorrect. By the same logic, a keyword is would be a function.
Wouldn't it be better to separate CSS and JS into separate, static files and only have the forum deal with, at best, IDs and classes in HTML?
I'm asking because I'm tempted to actually try to fork it and make a PR for it but it seems like such a simple and obvious bit of housekeeping that I have to assume there's a reason no one else has bothered yet.
[0]https://github.com/arclanguage/anarki/blob/master/lib/news.a...
Interesting to see what this will lead to.
(I've used Clojure and JS, which also seems like a "Lisp"-1 in that you can just put fns into variables and call them like 1st class fns, I just don't get why the distinction is in any way positive rather than confusing, and in Lisp-2s you now need to dereference everything all the time, like in Ruby).
(your-macro
(let ((x (foo y))
(bar x))))
I probably don't want the meaning of FOO or BAR to be up for grabs based on the expansion of YOUR-MACRO, and certainly not LET. Lisp-1s often have hygienic macros to deal with this concern, but not always. (def str “foo”)
In Clojure, because you’ll shadow the builtin definition of str (which leads to really weird bugs). But, this means that there’s one more thing to think about when naming your variables.Additionally, I think we’re pretty used to “separate namespaces” for nouns and verbs in normal languages: it’s fairly rare, for example, for the word “run” to be ambiguous between its noun use and it’s verb use, in the context of a sentence.
At this point I'm so used to lisp-2 that I make all sorts of silly mistakes when I program in a lisp-1. In English, a word could be a noun or a verb depending on its position in a sentence, so there is a parallel there. Whether or not it's a good thing is a matter of taste.
The only clearly objective difference is that lisp-1 is simpler, which is probably why most lisps created in the past 30 or so years are lisp-1s.
The advantage of a Lisp-2 is that it makes macro writing easier; you can include calls to known functions in the expansion without having to deal with the possibility that those names have been shadowed.
In addition to the simplified hygiene, one consideration is that Lisp dialects typically have mutable variables. But the ANSI-Lisp-style labels and flet forms bind functions immutably. Thus a compiler never has to suspect that a local function will change.
In TXR Lisp, developed a way to combine Lisp-2 and Lisp-1 into a single dialect, to get the best of both with almost no downsides. In a nutshell, the square bracket syntax performs Lisp-1 style evaluation: [a b c] means expand/evaluate a, b, c in the same mannner, and then treat the value of a as a callable object which receives the values of b c.
Furthermore, any arguments of [...] which are symbolic (after macro-expansion) are treated in a combined namespace which contains both function and variable bindings. When the symbol is global, if it has both kinds of bindings, preference is given to the variable.
This [a b c] is a sugar for (dwim a b c), which is a special operator that is recognized properly by the macro expander, interpreter and compiler, including the various shadowing corner cases between macro and ordinary bindings.
Thus, there is no reason to have to choose between Lisp-1 and Lisp-2.
However, the implementation is a bit more complicated than just Lisp-2 alone, never mind Lisp-1.
Someone with insight mentioned that there was a belief that it would be easier to optimize separate namespaces, but that reality proved them wrong, but I haven't verified that claim.