Arc Forumnew | comments | leaders | submit | zck's commentslogin
2 points by zck 4289 days ago | link | parent | on: Is there a repository of Arc libraries?

There isn't. I was considering writing something like quicklisp for Arc, but the downside is that with no module system, recursive loading of dependencies will break two different pieces of code that depend on different versions of a library.

We should probably at least make a wiki page with libraries, though.

-----

2 points by svetlyak40wt 4289 days ago | link

Why there isn't any module system yet?

-----

4 points by rocketnia 4289 days ago | link

Historically speaking, Arc was put forward as a language for experimentation. If you want to package up code in a squeaky clean format for others to use who don't care about implementation details, you're doing something other than experimentation; you're publishing a product people would supposedly rely on.

Moreover. not even the Arc language is stable (or so this website has always said). If it encouraged people to package up their stable code, that would prove deceptive once the whole foundation fell away. This happened to Anarki when Arc 3 was released; the community had built up lots of Arc 2 code, and not much of that was ported to work on Arc 3.

However, Arc is not without module systems. The first thing I did in Arc was build some namespace macros with explicit imports and exports for my own benefit (Lathe). Andrew Wilcox made "the hackinator" which I think could download Arc programs from a Web-hosted manifest file, most often from GitHub.

More recently, Arc/Nu is an Arc implementation with rich support for first-class namespaces, along with several utilities for modular loading of Arc code that's written in the usual sequence-of-commands style. Arc/Nu is probably the best platform to publish stable modules for, since it can load alternate namespaces to achieve backwards compatibility.

-----

2 points by svetlyak40wt 4289 days ago | link

Thank you for detailed answer, now reasons are more clear to me!

-----

2 points by zck 4304 days ago | link | parent | on: Julia

I saw a presentation by Stefan Karpinski, one of the Julia creators. It's a very interesting language that I'm sad to report that I have absolutely no reason to use. Unfortunately, I don't do any kind of mathematical computing.

I'm not too sad, because I do prefer prefix languages, but if I had to do something in that realm, I would definitely try out Julia.

-----

2 points by zck 4332 days ago | link | parent | on: Hacker News Down

Interestingly, HN's error page is returning a 200: http://bibwild.wordpress.com/2014/01/06/hackernews_http_200_...

Found on reddit: http://www.reddit.com/r/programming/comments/1ujjur/hackerne...

-----

2 points by akkartik 4332 days ago | link

Yeah this is a long-standing bug that is fixed in anarki.

I just opened a bug in the new HN bugtracker: https://github.com/HackerNews/HN/issues/54. Thanks!

-----

1 point by zck 4332 days ago | link | parent | on: Hacker News Down

On twitter, @HNStatus: https://twitter.com/HNStatus .

> Server back up and seemingly stable. Now restoring our latest backup to recover from limited filesystem corruption.

(https://twitter.com/HNStatus/status/420179162138021888)

-----

1 point by jsgrahamus 4332 days ago | link

Thanks, zck

-----

4 points by zck 4340 days ago | link | parent | on: The trouble with arc's if statement

I wonder if the author thinks the traditional if statement is flawed in the same way.

Most of my if blocks _are_ a single s-expression for each branch. I guess it depends whether you prefer to write functionally or imperatively. pg stated somewhere that, if the choice is forced, he will make the functional version of the code shorter, rather than the imperative version of code.

I also find it very interesting that the author doesn't indent the code at all. I hope it's just to make the point in this article, and now how ey normally writes code.

-----

3 points by fallintothis 4340 days ago | link

Most of my if blocks _are_ a single s-expression for each branch.

I was going to say...

  (def if-with-do (expr)
    (and (caris expr 'if)
         (some [caris _ 'do] expr)))

  (def accum-expr (accumf testf exprs)
    (map [ontree (andf testf accumf) _] exprs))

  (def keep-expr (testf exprs)
    (accum a (accum-expr a testf exprs)))

  (def count-expr (testf exprs)
    (summing s (accum-expr s testf exprs)))

  (defs count-ifs-with-do (exprs) (count-expr if-with-do exprs)
        count-ifs         (exprs) (count-expr [caris _ 'if] exprs)
        ifs-with-do       (exprs) (keep-expr if-with-do exprs)
        ifs               (exprs) (keep-expr [caris _ 'if] exprs))

  arc> (each file '("arc.arc"
                    "strings.arc"
                    "pprint.arc"
                    "code.arc"
                    "html.arc"
                    "srv.arc"
                    "app.arc"
                    "prompt.arc")
         (prn "=== " file)
         (let exprs (readfile file)
           (prn (count-ifs-with-do exprs) "/" (count-ifs exprs))))
  === arc.arc
  11/120
  === strings.arc
  3/18
  === pprint.arc
  5/5
  === code.arc
  0/0
  === html.arc
  4/24
  === srv.arc
  4/21
  === app.arc
  9/53
  === prompt.arc
  2/6
I also find it very interesting that the author doesn't indent the code at all.

I have a feeling (hope) that that was unintentional---like the blog formatting is just eating whitespace or something. Also, the first "Arc if" has a missing right parenthesis and uses = for comparison. :)

-----

3 points by zck 4340 days ago | link

Nice code. Some of my lying-around arc files:

unit-test.arc 2/12

All of my project euler solutions: 4/98

-----

2 points by fallintothis 4340 days ago | link

I was hoping other people would investigate their code! :) My personal arc directory filtered by hand for completeness (I have a lot of half-finished projects lying around), plus some stock Arc stuff I forgot in the last post:

  (each file (lines:tostring:system "find . -name \\*.arc")
    (prn "=== " file)
    (let exprs (errsafe:readfile file)
      (prn (count-ifs-with-do exprs) "/" (count-ifs exprs))))

  === ./transcribe/transcribe.arc
  1/1
  === ./qq/qq-test.arc
  1/3
  === ./qq/qq.arc
  0/10
  === ./macdebug/macdebug.arc
  7/17
  === ./bench/nbody.arc
  0/0
  === ./bench/pidigits.arc
  1/1
  === ./ansi.arc
  1/1
  === ./news.arc
  16/99
  === ./sscontract.arc
  0/0
  === ./blog.arc
  0/0
  === ./libs.arc
  0/0
  === ./profiler/profiler.arc
  0/2
  === ./vim/gen.arc
  0/11
  === ./hygienic.arc
  0/3
  === ./trace/trace.arc
  1/4
  === ./contract/test.arc
  0/1
  === ./contract/contract.arc
  0/9
  === ./contract/special-cases.arc
  0/2
  === ./contract/reconstruct.arc
  0/2
  === ./contract/defcase.arc
  0/1
  === ./contract/test/canonical.arc
  0/4
  === ./contract/test/ssyntax.arc
  0/4
  === ./contract/ssyntax.arc
  0/5
  === ./contract/util.arc
  0/2
  === ./quick-check/quick-check.arc
  1/8
  === ./arity/arity.arc
  0/8

-----

1 point by akkartik 4340 days ago | link

Nice trick, passing accum functions around!

-----

3 points by akkartik 4340 days ago | link

You're right about blocks, so let's just focus on single-line 'if's. I can't think of a single non-lisp that allows adjacent condition and action without an intervening token. C and Java require parens, Go and Perl require curlies, Python requires the colon, Ruby requires a newline or semi-colon.

  if (condition) action;     # C, Java
  if condition { action; }   # Go, Perl
  if condition: action       # Python
  if condition; action; end  # Ruby
The 'else' token is a further separator. Never in these languages will you ever have two either-or expressions side by side. They're separated by either 'else' or 'else if' or 'elif'. Perl and Ruby even sometimes use 'if' as a separator.

  action if condition        # Perl, Ruby
Am I missing any counter-examples? I think the biggest error in this article is to blame Arc, when it's just extending the logic all lisps have always had. If you permit such adjacencies as (if condition action) and (cond ((condition action))), then Arc's choices don't seem so unreasonable.

(Though Clojure's mixture of Arc 'if' and optional types is a whole new level of unholiness.)

-----

3 points by rocketnia 4340 days ago | link

"Though Clojure's mixture of Arc 'if' and optional types is a whole new level of unholiness."

Is this what you meant instead? "Though Clojure's 'let', which mixes Arc's 'withs' with type hints, is a whole new level of unholiness."

Even so, I think Clojure's 'let doesn't actually have any[1] added complexity when it comes to type hints. It might look like the list is bunched into groups of either two or three depending on whether a type hint is present...

  (let [^String x "x string"
        y 2]
    (body-goes-here))
...but that's not a quality of 'let. That's a quality of the ^ syntax. An occurrence of ^ consumes the next two s-expressions, just like ' consumes the next one s-expression:

http://tryclj.com/

  > '[^String foo "foo"]
  [foo "foo"]
  > (count '[^String foo "foo"])
  2
  > '[^String]
  java.lang.RuntimeException: Unmatched delimiter: ]
  > '^String foo
  foo
  > (meta '^String foo)
  (:tag String)
So the bindings of a 'let are consistently bunched into groups of two s-expressions, just like Arc's 'withs.

[1] Of course, the type hints are actually used for optimization at some point, so the complexity of parsing them has to go somewhere. This is exactly as complex as destructuring: Arc's 'withs syntax supports destructuring, but it doesn't need special-case destructuring logic because it just translates down to 'fn. As it happens, Clojure's 'let syntax also supports destructuring, and it probably uses the same general technique.

-----

2 points by akkartik 4339 days ago | link

Yes! Turns out I didn't notice the switch from if to let.

I have to say, though, I have no sympathy for the argument that it's still groups of two s-expressions. As a reader it's still more onerous to have to mentally group:

  ^a b
compared to:

  'a
So the presence or absence of parsing complexity feels irrelevant.

-----

2 points by fallintothis 4340 days ago | link

I can't think of a single non-lisp that allows adjacent condition and action without an intervening token.

I mean, isn't this requirement mostly because those languages are infix anyway? Parsing gets easier with explicit ways of separating things. I could easily imagine shift/reduce conflicts or what-have-you cropping up when you try to eliminate the requirement for, say, parentheses around conditionals in Java.

For example, in some hypothetical infix language that doesn't require conditional separators (parens, braces, then, etc.), would

  if x==10-x ...
be

  if (x == 10) -x ... // maybe this language doesn't use the "return" keyword,
                      // so the conditional is returning negative ten.
or

  if (x == (10 - x)) ...
?

Because Lisps use s-expressions, "intervening tokens" (per se) are unnecessary. As you say, Arc's choices don't seem so unreasonable, considering that.

-----

2 points by akkartik 4340 days ago | link

Yeah, that's a good point. Non-lisps use keywords and punctuation for readability and to make parsing tractable, and the two reasons are often hard to separate in any single design decision.

To summarize my position: I have some sympathy for the specific argument that multi-branch 'if's are harder to read in lisp than in traditional languages[1]. But this affects any arrangement of parens, whether traditional 'cond' or arc 'if'.

[1] I see I said so to you before, at the end of http://www.arclanguage.org/item?id=16838.

-----

3 points by zck 4364 days ago | link | parent | on: How do you concatenate two lists in Arc?

To repeat my comments from earlier (http://arclanguage.org/item?id=17074), calling 'join on lists is not quite the same as calling '+ on the same lists. The results are 'iso to each other, but not 'is .

  arc> (= l (list 1 2))
  (1 2)
  arc> (+ l)
  (1 2)
  arc> (join l)
  (1 2)
  arc> (is (+ l) (join l))
  nil
  arc> (iso (+ l) (join l))
  t
More confusingly, it also changes the cons cells inside the lists:

  arc> (= l (list (list 1)))
  ((1))
  arc> (is (car (+ l)) (car (join l)))
  nil
  arc> (iso (car (+ l)) (car (join l)))
  t
>Is there also a function for adding two hash tables?

Hash tables are missing a lot of helper functions, yes. There's no built-in way (that I know of) of combining them, although writing one isn't hard -- you just have to decide what to do about collisions. I just took a few minutes and wrote one up. I deal with collisions by letting the earlier hash win. My code:

  (def join-tables tables
       (if (no tables)
           (obj)
         (let rest (apply join-tables (cdr tables))
              (each (key value) (car tables)
                    (= rest.key
                       value))
              rest)))
Unit tests for this code:

  (suite join-tables
         empty (assert-same (join-tables)
                            (obj))
         one-table (assert-same (join-tables (obj 1 2))
                                (obj 1 2))
         two-tables (assert-same (join-tables (obj 1 2) (obj 2 3))
                                 (obj 1 2 2 3))
         multiple-values (assert-same (join-tables (obj 1 2 2 3)
                                                   (obj 3 4 4 5))
                                      (obj 1 2 2 3 3 4 4 5))
         three-tables (assert-same (join-tables (obj 1 2)
                                                (obj 2 3)
                                                (obj 3 4))
                                   (obj 1 2 2 3 3 4))
         overrides-values (assert-same (join-tables (obj 1 2)
                                                    (obj 2 3)
                                                    (obj 3 4)
                                                    (obj 1 0))
                                       (obj (1 2 2 3 3 4))))
Note: somehow, I broke 'assert-same. Not sure why. I'll fix it later today; I don't have the time right now to make sure it's done properly. If you pull the default branch of my repo, and these tests don't work, bug me until I fix it.

There's also no built-in way of telling whether they're 'iso, but I wrote one (https://bitbucket.org/zck/unit-test.arc/src/5d576dea18709cf7...) as part of my unit test framework, which is LGPL'd. Please use it and let me know what you think.

-----

3 points by zck 4364 days ago | link

Ok, fixed the broken part of unit-test.arc which wouldn't let `assert-same work on hash tables. (Commit: https://bitbucket.org/zck/unit-test.arc/commits/f3f10c942861...)

Of course, one unit tests above was also broken. The fixed unit test suite:

    (suite join-tables
            empty (assert-same (join-tables)
                               (obj))
            one-table (assert-same (join-tables (obj 1 2))
                                   (obj 1 2))
            two-tables (assert-same (join-tables (obj 1 2) (obj 2 3))
                                    (obj 1 2 2 3))
            multiple-values (assert-same (join-tables (obj 1 2 2 3)
                                                      (obj 3 4 4 5))
                                         (obj 1 2 2 3 3 4 4 5))
            three-tables (assert-same (join-tables (obj 1 2)
                                                   (obj 2 3)
                                                   (obj 3 4))
                                      (obj 1 2 2 3 3 4))
            overrides-values (assert-same (join-tables (obj 1 2)
                                                       (obj 2 3)
                                                       (obj 3 4)
                                                       (obj 1 0))
                                          (obj 1 2 2 3 3 4)))
Thanks for the opportunity to find this bug!

-----

2 points by zck 4364 days ago | link

Ugh, I'm past the edit time. Of course one wouldn't expect `(is (+ l) (join l))` to be 't, because that's the definition of 'is. (even `(is (list 1) (list 1))` returns 'nil). But the second part is bad, I think: the elements inside l should stay the same.

I blame not really hacking in Arc much lately. I haven't really been up for programming much of anything.

-----

3 points by rocketnia 4364 days ago | link

"But the second part is bad, I think: the elements inside l should stay the same."

I agree. I really think this is a simple coding mistake in ac.scm. I talk more about this here, a reply to that thread you linked to: http://arclanguage.org/item?id=17114

I completely forgot about this difference between + and 'join after that thread, and I don't remember encountering it before that either. How fitting it's a testing framework that brings this bug to the surface! :-p

-----


...that's fantastic. Can you say where you are that has Arc projects? Or what the project is? And if you're hiring? (this is half a joke).

There's some community-written documentation on a wiki (https://sites.google.com/site/arclanguagewiki/), which points Windows users towards http://www.arclanguage.org/item?id=12397 as instructions.

While I don't have a Windows machine to test on now, I had gotten Arc working quite easily before on one (I was not running HN, which would exercise more code paths than were executed). Try it and see what happens.

Alternately, if this is an existing project, someone at the office should know how to get it working. If you try it and something breaks, let us know and we can help out!

-----

3 points by rocketnia 4377 days ago | link

"...which points Windows users towards http://www.arclanguage.org/item?id=12397 as instructions."

I use Windows 7 now, and it's the same process as usual. If you're using Anarki, the 'setuid problem should already be fixed.

-----

2 points by rocketnia 4370 days ago | link

I have a Windows 8.1 machine now, and it's still the same process. :)

The biggest pain was when I was trying to download the Anarki GitHub repo in the first place. I've been cloning GitHub repos over SSH URLs using Cygwin's build of Git, and setting this up on Windows 8 was a bit surprising: http://stackoverflow.com/questions/9561759/why-cannot-chmod-...

Nowadays, there are probably easier ways to get Anarki on Windows, like using GitHub for Windows or just using the GitHub website's "Download ZIP" button.

-----

2 points by zck 4381 days ago | link | parent | on: "as is" arc/hackernews install

What are you looking to do with it such that you can't install it yourself? If you want to do anything with it, you'll want to be knowledgeable enough to install it.

-----

1 point by akkartik 4373 days ago | link

Incidentally, https://github.com/jcs/lobsters is an alternative to arc that might work better as a traditional open source project for less knowledgeable folks. http://arclanguage.org/item?id=18181

-----

3 points by zck 4381 days ago | link | parent | on: Adding search and downvote to Arc clone site

Downvoting of comments already exists in the code; each user is prevented from downvoting until that user accumulates enough karma. I don't have the source in front of me, but you could set the threshold for that to 1, so users would be able to downvote comments as soon as they register.

Downvoting submissions is another story. As far as I know, HN has never let users downvote submissions, so you'd have to build in that scaffolding yourself.

-----

1 point by no_keeptalking 4381 days ago | link

All I found was :

1. A graydown.gif in the static folder

2. The following code in the news.arc file: (= up-url* "grayarrow.gif" down-url* "graydown.gif" logo-url* "arc.png")

I looked over all the files again and couldn't find any references to "graydown" or "down-url" any ideas?

-----

2 points by no_keeptalking 4381 days ago | link

I was looking too fast... it's all there in the news.arc file

-----


Ugh, that's awful. I want to print out error messages that, in part, can be copied and pasted into the REPL. Right now, since double quotes are escaped, I'm printing single quotes, which obviously don't work. (https://bitbucket.org/zck/unit-test.arc/issue/40/make-error-...)

I guess this is a reason to switch to Anarki. But even that doesn't help too much given that I want unit-test.arc to work with arc3.1.

-----

2 points by fallintothis 4395 days ago | link

To play devil's advocate (and/or nihilist), why do you need that? Error messages in Arc are already universally this way, so it's expected behavior that the messages look crappy. :P

On a more constructive note, is there some part of your code (or could there be, with some rewriting) where you could specifically catch the exception whose message you want to display nicely? Seems like you could probably work out some way to wrap something like:

    arc> (on-err (fn (c)
                    (pr "Error: ")
                    (prn (details c)))
                 (fn () (err "a \"b\" c")))
    Error: a "b" c
Even with a macro:

    (mac w/nice-errors exprs
      `(on-err [do (pr "Error: ") (prn (details _))]
               (fn () ,@exprs)))
It's a bit of hack, but if you need to subvert the language's defaults in an implementation-conforming way, them's the breaks.

Side note: paging through your source code, I notice you have a few functions to support to-readable-string. I believe it could be greatly simplified, because write's job is already to print out values in ways that read can parse back in. Thus, save for the single-quote stuff, I think you could boil it all down to tostring:write. Play around with it and see if it's what you want:

    arc> (tostring:write (list 'a "b" (obj c 'd)))
    "(a \"b\" #hash((c . d)))"

-----

2 points by zck 4395 days ago | link

> To play devil's advocate (and/or nihilist), why do you need that? Error messages in Arc are already universally this way, so it's expected behavior that the messages look crappy. :P

Because I'm not satisfied with crappy behavior. It makes readability worse, and debugging harder.

I'll take a look to see if I can catch it better; reading over my code, some of it does seem to be convoluted, if working. I've never quite been happy with how the failure messages are calculated; if that changes, I can easily change how we handle printing the errors.

Other than the double-quote issue, I don't recall other big reasons to use to-readable-string. I'd certainly be a fan of removing code, if I can make it work. It would bring my macro:function ratio below 1:1 again, which would be awesome. :)

-----

2 points by akkartik 4395 days ago | link

The reason to use 'write rather than 'display is precisely so that things can be pasted into the repl. All you should have to do is 'read and 'eval the entire error string.

But there's definitely something busted about this. In anarki:

  arc> (= x "abc")
  arc> (err x)
  Error: "abc"           ; ok, looks good
  arc> (= x 'abc)
  arc> (err x)
  Error: "error: abc"    ; whaa..
There's also a long-standing issue that's bothered me before:

  arc> (= x "abc")
  arc> (err x " shouldn't be a string")
  Error: "abc \" shouldn't be a string\""
You're right, that's pretty ghastly. It should print:

  Error: "abc" shouldn't be a string
or:

  Error: "\"abc\" shouldn't be a string"
I'm still mulling what the culprit is here, but I don't think it's write vs display.

-----

4 points by rocketnia 4395 days ago | link

The culprit is that 'err is defined to be Racket's 'error. It looks like every single use case of 'error is discouraged for one reason or another in the Racket reference:

http://docs.racket-lang.org/reference/exns.html#%28def._%28%...

- (error sym) creates a message string by concatenating "error: " with the string form of sym. Use this form sparingly.

- (error msg v ...) creates a message string by concatenating msg with string versions of the vs (as produced by the current error value conversion handler; see error-value->string-handler). A space is inserted before each v. Use this form sparingly, because it does not conform well to Racket’s error message conventions; consider raise-arguments-error, instead.

- (error src frmat v ...) creates a message string equivalent to the string created by

  (format (string-append "~s: " frmat) src v ...)
When possible, use functions such as raise-argument-error, instead, which construct messages that follow Racket’s error message conventions.

-----

2 points by rocketnia 4394 days ago | link

Er, I knew it was weird for me to say "'err is defined to be Racket's 'error," but I just realized, that factoid was in the original post of this thread. :-p

-----

More