Make sure to click on the blue flashing text; they're hyperlinks. Arc is discussed in the "Brevity Guild" section; the first of the three new Lisp guilds.
I thought that let looked odd, because I thought that with a let in arc, you had 1 variable/value pair. Thanks, zck, for pointing out the difference. And thanks, akkartik, for repeatedly telling me this.
Ah, thanks for spotting that so quickly. Arc warns when we replace a function with another. Perhaps it should also do so when we replace a function with anything else?
I did see it running momentarily on Windows a few weeks ago: http://arclanguage.org/item?id=19458. It might have a few issues, but if you report them I'll try to fix them.
Interesting. I like the consistency. I don't love how it makes the most common case (I think the no-setup case is most common) and adds more code to it.
Maybe I can come up with a simpler, less awful thing.
Perhaps:
(suite foo (setup a 1
b 2)
(test must-bar
(assert-same b (+ a a))))
I'm kinda growing to like my idea the more I think about it. You're right that it adds 3 characters to the common case, but lisp has a long tradition of empty parens in various places. Saving characters shouldn't be a high priority, IMO. Paul Graham's notion of conciseness counts tokens, not characters.
But yeah, happy to see what other ideas we can come up with. I think the setup keyword above is worse; lisps don't tend to have keywords that aren't functions or macros. Then again, test is already a keyword that's not a function.. Hmm, I like it better if you indent it like this:
(suite foo
(setup a 1
b 2)
(test must-bar
(assert-same b (+ a a))))
The benefit of this approach is that it makes the syntax seem extensible. It's obvious how new features should be added.
But this clutters up the namespace. We can use a local helper function to move make-list-helper inside the body of make-list, and wrap it in afn to make it able to recurse.
This is identical to your version, except I dropped the now-unnecessary base case (if now generates the initial list at the bottom-most recursive call) and moved the cons outside the call to make-list.
I'm surprised by the redefinition warnings. They don't happen for me. Perhaps you have some of your own code being loaded? Or maybe you have an old version? (Though I don't remember make-list ever being a thing.)
If you want to view all branches, `hg branches`. There are some old ones I need to finish and merge back in. To view the current branch, `hg branch`.
Or if you want to look at it online, the link above (https://bitbucket.org/zck/unit-test.arc/src/8b9dbe91702c3866...) should take you to the right branch. (Edit: you'll know you're on the right branch if the second code block runs tests with (test), not (run-suite))
It's not backwards compatible. Hence me trying to get feedback before pushing the 1.0.
The specific backwards incompatibility (I assume you got "We can't parse this as a suite body") is moving from this format for the tests:
(suite suite-name
test-name (test-body))
to the format you suggested last year:
(suite suite-name
(test test-name (test-body)))
I don't think supporting both ways of writing tests is useful. I'm also planning on migrating the anarki tests when I roll out the 1.0. Actually, I could get started on a branch even before. That'd be something to do.
If you start doing some of the migration work, push the in-progress stuff to a branch and I'll help work on it. I'll do the same if I get to it before you. Thanks.
This must be the most fun thing on my radar right now, because I got to it first thing this morning :)
; translate.arc
(def translate (expr)
(accum acc
(translate-2 expr acc)))
(def translate-2 (expr acc)
(if (atom expr)
(acc expr)
(is car.expr 'suite)
(do (acc 'suite)
(let (suite-name . suite-body) cdr.expr
(acc suite-name)
(translate-suite-body suite-body acc)))
(is car.expr 'suite-w/setup)
(do (acc 'suite-w/setup)
(let (suite-name suite-setup . suite-body) cdr.expr
(acc suite-name)
(acc suite-setup)
(translate-suite-body suite-body acc)))
'else
(map acc expr)))
(def translate-suite-body (suite-body acc)
(if suite-body
(if (acons car.suite-body)
; nested suite
(let (nested-suite . rest) suite-body
(acc (accum acc2
(translate-2 nested-suite acc2)))
(translate-suite-body rest acc))
; test name must be atomic
(let (test-name test-body . rest) suite-body
(acc `(test ,test-name ,test-body))
(translate-suite-body rest acc)))))
; bootstrap tests for a test harness :)
; suite with tests
(assert:iso '(suite a (test t1 b1) (test t2 b2))
(translate '(suite a t1 b1 t2 b2)))
; suite with tests and nested suites
(assert:iso '(suite a (test t1 b1) (suite s2 (test t3 b3)) (test t2 b2))
(translate '(suite a t1 b1 (suite s2 t3 b3) t2 b2)))
; suite with setup and tests
(assert:iso '(suite-w/setup a (x 1 y 2) (test t1 b1) (test t2 b2))
(translate '(suite-w/setup a (x 1 y 2) t1 b1 t2 b2)))
; suite with setup and tests and nested suites
(assert:iso '(suite-w/setup a (x 1 y 2) (test t1 b1) (suite s2 (test t3 b3)) (test t2 b2))
(translate '(suite-w/setup a (x 1 y 2) t1 b1 (suite s2 t3 b3) t2 b2)))
; run
(each f cdr.argv
(prn f)
(fromfile string.f
(tofile (+ string.f ".2")
(each expr (drain:read)
(let out translate.expr
(ppr out))))))
Run it like so:
$ arc translate.arc *.t lib/*.t lib/tests/*
I haven't committed it anywhere yet because I'm not too happy with the state of Anarki's pretty-printer. Would you mind if I change the indentation style for suites and tests in Anarki? I was thinking something like this:
What are your goals? Although the people here are pretty helpful, there isn't much out there, resource-wise, for Arc. This is both in terms of documentation and libraries.
Are you interested in hacking a Lisp itself? Then Arc is a good choice. Are you interested in learning a Lisp you can find companies using? Arc is suboptimal.
I suppose I'm learning lisp for more idealistic/philosophical rather than professional reasons. Though it seems there are compelling professional outcomes nonetheless.
I'd describe myself as a bottom-up thinker. [But I'm unopposed to the description "top-down" because . . . "which way is up?"] I like to work from axioms to outcomes. I'm frustrated under other conditions.
Clojure also has a pretty cool way to not have to call (uniq) by hand. If, inside a backquote, you append a # to a symbol, clojure will replace that variable with a gensym. And it'll use the same gensym every time you use that variable in the backquoted form.
(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
{:added "1.0"}
([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~@next) and#))))
See how it uses and#, but it doesn't capture the variable and?
I'm not entirely sure how you would capture a variable (e.g., Arc's "aand"); if you try to, clojure errors by default. There's probably some way, but I don't know offhand.
It would be nice, but I have a hard time recommending it to anyone with no releases since 2009.
Perhaps Anarki would be something to recommend. But that's not really being driven forwards either. Any changes are the result of design by committee, which doesn't tend to lead to great design.
It doesn't seem fair to call Anarki design by committee. It's closer to a small number of scatterbrained people who periodically have a shiny new idea and add it in in anarchist fashion. Maybe design by Dory? http://www.imdb.com/character/ch0003708 :)