I'm not necessarily thinking in the current Arc,
but in the hypothetical hundred-year Arc.
- Could we make pattern matching through
unification a part of the core language?
- Could we make some tasks easier (I mean
terser) using Icon or Prolog-like
goal-oriented programming?
- Could Haskell typeclasses be adapted to a
dynamic language? (I know that is not possible
in general, but maybe in the most common cases).
CLOS-like oop is the way?
- Easy defstruct as in Haskell is also a win.
- Which would be the best module system?
Python's first order modules are cool, but
I also Haskell's module system seems better
to do ADTs.
- Could we use generators using a lazy
list-like interface?
- To which point could the system be reflective?
In the past it was considered that "flambda"
(user defined, first class special forms)
and redefition of eval with "reflective towers"
are not that good ideas, because of efficiency.
Should we spend more cycles to allow such things?
- Should the read s-expressions also have
associated meta-information?
- Could Arc live in an image?
- Could Arc be just the specification of
its own compiler, making the bytecode
an official part of the language (as
pg once said)?
- Could Arc be blazingly fast?
- Could Arc be prepared for multiprocessor
architectures like the guys (pun intended ;))
in Fortress want it to be? Or to intensive
scalability like Erlang seems to have?
Of course all that questions are implementable.
There probably is a library for every one of them
in Cliki.
I am just asking which of them we should take
and encourage to be seen as part of "Arc's core".
Commonality and practice of an idiom, more than
its mere possibility, is what actually defines
what a language is.
Currently, Arc's core is not much more than sugar for
Scheme (modulo defcall, mostly unseen and great).
This doesn't want to be insultive, I am happy
that people find Arc useful.
Maybe it is that I am looking for a revolution
and Arc is Lisp, which is good but not revolutionary.
You don't have to work on it but we still would like some direction from you, like thoughts on anarki and the new editions that are added by the community.
I agree whole heartedly with this. I have begun abbreviating too.
I think arc like macros should go in Anarki. What does everyone else think? I like seeing everything arc in one place - even if it is CL or Scheme macros.
That being said it sucks that the arc community uses Anarki while pg doesn't. Or at least he doesn't contribute regularly. I think there is plenty of room for a more cohesive community.
> gotta remember that that the non-consing version of APPEND is not NAPPEND but NCONC, for example
Ah, consistency: yet another thing lacking in Arc. Take 'afn and 'acons, for example. Or 'acons and 'number. Or 'number and 'string. Or 'string and 'sym...
Reading that output is beyond a headache. It should be against the law! But more importantly, when writing code/troubleshooting you can't copy the evaluated output make a modification and then call the function again. I know you can bind it and apply functions to modify it, but often that's a real hassle compared to copy/paste.
Clojure has DOZEN's of helper functions (and important traversal functions) that don't exist in Arc. Yeah I could write them, but I still have to. I was highlighting the ease with 'separate', but here's even 'deep-merge'....
(defn deep-merge
"Recursively merges maps. If keys are not maps, the last value wins."
[& vals]
(if (every? map? vals)
(apply merge-with deep-merge vals)
(last vals)))
> (deep-merge players {:joe {:weapon "LongBow"} :jane {:weapon "Lance"}})
It's not even these sample cases that expose the issues. It's about working with REAL data. I have many files containing hash-maps that are 15 levels deep. If I were to attempt pretty much anything, but the most simple cases, in Arc I would hit problem after problem after problem. Which I did. So fine... really I should use a DB, right? ok let me just grab that DB library in Arc....
-- Nil values --
I'd even be fine with any falsey values like boolean false. But Arc will not even store an #f value. To suggest I can't pass in REAL data with falsey values is really limiting. I can't pass in an options table argument. For every operation I would have to add more data or nuanced data or nuanced operations to support "this value was set, but it's set to 'NO' I don't want that option.".
I can't say I'm surprised that breaking the abstraction of cons cells that way ended up being a problem. This new implementation, if anything, breaks the abstraction even more (exploiting the fact that viewing a cons cell as a vector happens to result in mutating certain parts of the "vector" having the desired effect on the cons). Arc (anarki at least) really should switch over to using racket's mutable pairs.
Actually, speaking of that, why not just use unsafe-set-mcar! and unsafe-set-mcdr!? I find it far more likely that the representation of mutable pairs will continue to coincide with that of pairs than that the representation of vectors will, and a quick examination at the mzscheme prompt seems to confirm my suspicion. unsafe-set-mcar! and unsafe-set-mcdr! work just fine on cons cells. I'm using plt scheme 4.2.2, not racket, though.
While I still hack in Arc constantly because I'm always tweaking HN, I haven't made dramatic changes to the language itself lately. I only seem to be able to work on 2 things at once, not 3. Since YC is a given, that means I have to choose between hacking and writing. Lately I've mostly chosen writing.
I should release a new version though. News.arc is greatly improved since the last release.
Next, I see t and nil floating around in an if -- so most of it could probably be done with and/or instead of if, which might make the code clearer. Let's check with some boolean simplification. The top-level if goes
Here's a truth table based on (atom lst1) and (atom lst2).
(atom lst1) | (atom lst2) || (and ...) | (or ...) | (if ...)
nil | nil || nil | nil | 'else
nil | t || nil | t | nil
t | nil || nil | t | nil
t | t || t | t | t
Notice that the if is equivalent to the and, except for the "else". So, whenever the and returns t, we want to return t; i.e., if should be replaced by or. But
(or (and (atom lst1) (atom lst2))
'else) ; wrong
isn't quite right. When the and is nil, we only want to do the "else" if both (atom lst1) and (atom lst2) are false. Note that in arc.arc we have
(def atom (x) (no (acons x)))
So, (acons x) is also the same as (no (atom x)). Therefore, we can guard the "else" by checking that both (acons lst1) and (acons lst2) are true. This communicates the intent more clearly for whatever we have in the "else".
So, the if decides whether to recurse on the cars of the lists. But notice that whenever
(and (atom (car lst1))
(atom (car lst2)))
we know that
(same-shape (car lst1) (car lst2))
by the definition of same-shape, because the first clause of the or is that very atom check!
So, we don't need this if. We can handle it all by recursion. This also means we can get rid of the with, because we don't need to use car/cdr expressions more than once.
I detailed the rewrite for learning's sake, but we could've saved a lot of time noticing that it's really similar to Arc's iso:
(def iso (x y)
(or (is x y)
(and (acons x)
(acons y)
(iso (car x) (car y))
(iso (cdr x) (cdr y)))))
Only instead of is, we're checking that both of the items are atoms. This also suggests a different name: iso comes from the word "isomorphism", so maybe a good name for same-shape is congruent. But I like same-shape, too. Either works.
We can apply a lot of these lessons to same-sig (or maybe congruent-sigs, since we're checking for shape, not equality, and same-sig-shape is awkward). However, we don't have quite the same nice recursive properties that same-shape does.
But with this rewrite, we can see some potential bugs.
First, the var-arg clause checks the cdrs if the cars both take either one of two forms. So,
arc> (same-sig '(x y) '((o x) (o y)))
t
This might be desired -- both parameter lists are "compatible" if we supply the optional arguments. But I reckon with a name like same-sig, it's a bug.
Second, you use same-shape to check if two destructuring parameters are congruent. But same-shape doesn't take into account optional parameters, which are perfectly valid in destructuring lists. E.g.,
arc> (let (x y (o z)) '(a b) (prs x y z) (prn))
a b nil
nil
arc> (let (x y (o z)) '(a b c) (prs x y z) (prn))
a b c
nil
So same-sig gives
arc> (same-sig '(a (b (o c))) '(a (b (c d))))
t
which is surely a bug.
To address the first (potential) bug, instead of using var-arg we can just check for optional parameters. For the second, just use same-sig instead of same-shape.
In my code, I've been doing sorta convoluted things to avoid accidental macro-expansion just like what you're talking about:
(def whatever (row) (row "something")) ; unsafe
(def whatever (row) (do.row "something")) ; safe
(def whatever (row) (or.row "something")) ; safe
; The "or.row" one is possibly more efficient, since it expands to
; "row", but I use "do.row" 'cause I don't want to desensitize myself
; to "or".
(def whatever (tab key) (= tab.key "something")) ; unsafe
(def whatever (tab key) (= do.tab.key "something")) ; doesn't work
(def whatever (tab key) (= or.tab.key "something")) ; confuses me
(def whatever (tab key) (= .key.tab "something")) ; safe
As long as I keep this up, my macros and parameters can conflict all they like, and it doesn't matter. But this approach basically amounts to qualifying the name of each parameter as it's used in function position, so from my point of view, macros and parameters almost don't live in the same namespace.
It'd be interesting if there was a pattern to hyphenated names. I assume there isn't because I just hyphenate when it seems like I "should". i.e., Names are often broken up by hyphens because they're easier to read that way. No real algorithm for that. Things like the length of the name can play a factor (e.g., expand-metafn-call doesn't run together like expandmetafncall). Now that I think of it, that's probably why Common Lisp has so many hyphens: its long names would run together otherwise. Even so, it has butlast, notany, notevery, pushnew, and the p vs -p inconsistency.
Just from this, I see names that work well with hyphens: I can't parse createacct on first glance, hourssince & dayssince are awkward with the two S characters, responderr looks like "responder" with an extra R, pprprogn has too many similar letters jammed together, logfilename could be parsed as either "name of the logfile" or "log the filename", nof is just weird, etc. But there are names that don't strictly need hyphens: I think endtag, filltable, getuser, loadtable, loadtables, randkey, and others look fine, which indicates to me that the issue really is just aesthetic.
Note how 3 was printed twice. This is because the expression(s) passed to the andf-expression are substituted directly into the argument lists passed to the andf-ed functions, which means they will be evaluated once for each andf-ed function applied.
It's easily recognisable even when small which is important for a logo and a favicon. I like the colours. And clearly it shows an amazing degree of artistic talent, the sort that could only be acquired in art school :)
Allow me nonetheless second some other commenters who observed
- the #\a concept is not obvious
- the keystone would normally be part of the arch, not under it
- the blue and black are difficult to distinguish in the small version
- while you explain the #\a and the keystone, the red/blue business is mysterious, and perhaps a tad decadent - art for art's sake and all that.
At a glance, it looks like the white bit has risen up out of the red bit (if you'll forgive the technical language here), and the blue bit is just background.
A slight improvement might be to make the horizontal edges of the #\a (top and bottom) a little thicker, to enhance the a-ity (although I can see that that might diminish the arch-ness). Another might be to use a brighter blue.
Are you planning to stick with this or are you inviting suggestions (not that the absence of an invitation has stopped me or anyone else) ?
The reason you want commonly used operators to be short is so that most of the information you see on your screen is the content of your program. It's the same point Tufte makes about data-ink ratio in graphs. Conversely, long names and required boilerplate are like the stuff he calls "chartjunk."
You see the same thing in math notation. Do you think mathematicians use an integral symbol instead of writing out the word "integral" because it makes them feel clever? I think it's because the resulting bloat would make math expressions harder to read, not easier.
I know, it's 87 days later, sometimes I take my time ... this article stirred me from some months of guilty inaction so I took another look at rainbow (arc in java).
The latest checkin supports complex numbers and a little bit of trigonometry, and it also goes faster, yippee! I was planning to use arc to play with fractals (ergo need for complex numbers) when I have a bit of spare time. This checkin makes rainbow a fairly complete implementation of arc, so if you're interested in trying out arc but need some of that ready-made java library goodness, rainbow might be your thing.
As with most criticisms of Arc, these complaints are mostly treating Arc as if it was something other than a VERY early release of a language that's still under development. Both the syntax and semantics of Arc are expected to change as new features are considered/added/rejected.
However, it's easy to see why the author would think of Arc as something more than it is, since it was so hyped by so many people online and since it's been under development for so long. Plus, given the length of time that it's been out, most of us expected more progress by now.
Of course, this doesn't excuse the article's shortcomings, but I think there are a couple of valid points buried amidst the specious ones, so I'll respond to them all one at a time:
1. Criticizing Arc for a lack of features is pointless. It's an early release of the language, and there's no reason why more features can't be added later.
2. Paul Graham wrote an entire article on "Why Arc is not especially object-oriented" which links to several other articles by both himself and others discussing the pros and cons of OOP. The lack of namespaces is a valid criticism at the moment, especially since a lack of a namespace mechanism makes it more difficult for people to write and share Arc libraries.
3. Arc hasn't had enough releases for me to care about having access to PG's version control repository.
4. I'm not sold on Test-Driven-Design for software which is expected to radically change numerous times before becoming stable. I generally write tests after I've somewhat stabilized a codebase, and only then do I make any effort to keep my tests up to date. This is a nuanced issue and I respect the TDD arguments, but this certainly doesn't turn me off to such early versions of Arc.
5. This is another complaint about a missing feature. I agree that this feature should exist, but things like this don't sink the language.
6. Unusual version numbering is a deadly sin?
7. PG's stated outlook is that the more common an operation, the less intuitive its name can be. I don't find "no" less intuitive than "not", although I think he has a point about it being silly to abbreviate "print" to "pr" just to save 3 characters.
8. Line numbers is errors is my personal #1 desired feature for Arc, and hopefully this feature will be added soon.
Interestingly, his conclusion is entirely correct: "In short, if you were hoping for a usable and modern dialect of Lisp, then Arc is not the answer, and won't be without a lot of work." Arc will indeed take a lot of work to become modern and usable for most tasks, and I'm disappointed that PG hasn't put out a new release in over 9 months, but I hope that he'll eventually find time to take a more active role in Arc's development.
I also have no problem with the way pg is doing things. However, the flack he's getting is starting to reach epic proportions. Perhaps the following quote from Kent Pitman at Lisp50 explains it: "Soliciting volunteers gives critics something to do, which dilutes their passion, pacifies them, and makes them feel involved." Conversely, if they feel they have nothing to do, or their work isn't appreciated, they become critics.
I'm not sure the use of an open forum has been much of a success so far. When pg first announced the existence of Arc, he asked people to email him with suggestions. People were supposed to suggest features from other languages and then give examples of how that would make code shorter. Eventually, he posted all the replies on his web site, and although there were lots of ideas, not a single person had actually done what was asked. This forum has been better, but far from perfect. For example, has anyone has actually tried to write a fast profiler yet?
I think that if you want to offer a language to the community, and expect useful work out of it, you need to provide a structure that people can work in. For example, Perl 6 started with an 'RFC phase' and then moved on to 'Apocalypses'. Writing an RFC forces you to put a lot more thought into your ideas than you would if you were just posting to a forum. Writing the Apocalypses made sure that there was plenty of feedback on these ideas. People had something to do and knew where they stood.
So I don't think it really matters whether you release a compiler. What matters is whether people have a structure they can work in. That's why everyone wants to write libraries for Arc. Writing a library is something that one person can accomplish. It's a structure that channels people's energies towards a given end-point, and they are rewarded through people using the library in their own projects.
For Arc, the compiler was both a help and a burden. It helped because people could actually try out ideas. It was a burden because everyone started working on the compiler, not the language.
So I think community-aided design can work, but it needs to be harnessed correctly. The most important ingredient is probably high-quality feedback on what people are doing. Of course, that also requires the most effort, but no one ever said it was easy. :)
I think part of the reason we were all hoping for more frequent releases was because, despite the fact that pg explicitly described arc as a 100-year language, he also stated that his design philosophy involved rapid iterations.
"I like to find (a) simple solutions (b) to overlooked problems (c) that actually need to be solved, and (d) deliver them as informally as possible, (e) starting with a very crude version 1, then (f) iterating rapidly." http://www.paulgraham.com/newthings.html
I actually think was a good plan, I just wish pg were able to follow it ;-) Even small improvements or bug fixes would make the community feel engaged.
I didn't mean to say that core language isn't important. It is important. My main point point is that the community should be able to partecipate in the design. This is why I've advocated a fork of Arc, because to improve the core of the language you need help from who will use the language. A prototype is a good way to make this happen even when you're in the design phase and not in the production phase, but it is useless without a communication channel between the designer and the users.
PG won't be alive in a 100 years.. and there's a difference between slowly searching for an optimal language and not working at arc at all.
It is a bit sour for the community if their effort are not affecting the progress of the language towards its goal.
To be fair, PG has a point though that n months isn't that much if Arc is supposed to be 'finished' in about 30 years from now. We might just have wrongly expected things to move at a somewhat faster pace.
One pattern that I observe - you respond only to those points that rebuff you. Rather than proposing solutions and/or accepting that you have been less than clear about your plans for Arc (especially as this is a real community now and not your personal pet project), you have been exceedingly discourteous to your fellow Arc-enthusiasts. I feel sorry for them and happy for myself that I am not part of this farce.
Funny thing is, when I read your essays a couple of years back, I did respect you. Reading stuff like this kind of erodes that dramatically. Good luck pg.
What about "100 year language" don't people understand? PG's point isn't to make the language popular now, or in a decade... it's to make it popular 100 years from now.
Personally, I think it underestimates how different the world will be 100 years from now to talk about how programming languages will be then (just imagine what kind of "computers" we'll have then!), but I suppose the "100" number is arbitrary... I think PG just means generally looking at "long term", not "short term", and having a community is a short term advantage.