Arc Forumnew | comments | leaders | submitlogin
2 points by jb 4250 days ago | link | parent | on: New logo

Thanks! I don't really have any concrete questions, but any advice on learning Lisp would be welcome. Maybe I should learn Scheme and read SICP before learning Clojure? Maybe I should forget Lisp altogether until I have more experience with programming in general? I get the feeling Arc is not the best place to start learning Lisp.

I did have a short look at the tutorial, but I had a bit of a hard time diffing it mentally, as I am still fairly new to Lisp. But I will definitely point him in that direction if he is interested in having more than a cursory glance.

Also, are most "Arcers" using Anarki?


My one-sentence summary of arc: minimalist common-lisp-flavored lisp-1 atop scheme. It takes quasiquoting and some other more dynamic design choices from common lisp and overlays them atop the more modern Racket runtime with as little code as possible. Other than that it's lots of tiny ergonomic conveniences. Maybe you should read/show him the tutorial next: http://ycombinator.com/arc/tut.txt. And arc.arc is a pretty fun read: https://github.com/arclanguage/anarki/blob/3fc14d16e9/arc.ar.... What really got me into arc was writing programs in one split window with the friggin compiler for my language in the other.
2 points by akkartik 4251 days ago | link | parent | on: New logo

Nice! And welcome! Feel free to ask questions even if they aren't about arc. We might be able to answer them.
1 point by akkartik 4252 days ago | link | parent | on: Uploading files in Arc

Is there an append in arc3.1? I wasn't aware of that. I don't see it from a quick grep, nor in http://arclanguage.github.io/ref/fnindex.html.

But yes, it might make sense to avoid pulling in spliceable-list. As long as you can see what it's being used for, there are other ways to get the behavior it provides, though the easy alternatives will be slower.

But as you're finding out, it's work. You can't just pull in dependencies willy-nilly. Fundamentally, arc3.1 and anarki are both about sharing code as ideas, not code as functionality. We've repeatedly mentioned how neither makes promises of compatibility. You can't treat them as interchangeable lego blocks and expect them to just snap into place. No matter how similar they look, they're not close to each other. They're really more like separate universes that you're 'wormholing' matter and energy through. Start with the assumption that that will cause some annihilation unless you're willing to be careful and detail-oriented. How much time should it take? Maybe "dawn to midnight" is reasonable. There's no way to tell until you try to do it. You're in terra incognita with every single little task like this.

Anarki tries to make such wormholing easier by providing tests. Tests are a better "unit of transplanting" than functions or something else. Try to first understand what's involved in making a test pass, then copy the test over, then make it pass. Think of the file upload code in anarki as merely an exposition to help guide you when creating your own version.

But this is harder when transplanting to arc3.1 because it has no tests. Honestly I have no idea why you stick with it. Imagine I'm a villain in a superhero movie or a bollywood movie: "where is your savior now? How long will you be faithful to him?" :) Stay with one repo and you'll be out on a limb less. Pick a repo with tests, and you won't be locked in to it when you do need to go out on a limb and transplant code from somebody else.

I feel bad that you struggled for so long by yourself. If you'd ask for help sooner, and if you provide more information, I think your path could be much eased. For starters, it sounds like you've added to arc3.1 over the years. It makes it harder for me to be sure that any code I suggest won't harm you. I recently made a suggestion to tvvocold over email that caused problems because it turned out he'd made changes I wasn't aware of. I'd prefer not to have more of that on my conscience. Can you share the current state of your codebase?

The final thing that helps us help you: forget about compatibility. Programming gets harder the more constraints you add, so try to focus on concrete issues rather than imaginary abstractions. How do you know your existing changes to arc 3.1 are "compatible"? If someone not called pg magically included file upload atop arc3.1, how would you be sure it was "compatible"? In my opinion the reason that "sending anything to a server requires this whole complicated way of multipart encoding/decoding stuff" is the expectation that things just work when you transplant them from one setting to another. I'll make a moral judgement as kindly and respectfully as I can: To the extent that you care about compatibility, you're part of the problem. Uploads are complicated because somebody else decided they didn't want to know about the details and just wanted uploads to work. Add thousands of such people with slightly different scenarios and vague fears of breaking each other, and you end up with all this complexity.

3 points by lark 4253 days ago | link | parent | on: Uploading files in Arc

I stopped at spliceable-list (in scan-past) which needed lib/spliceable-list.arc. I didn't want to go down the rabbit hole of loading it after I saw a redefinition of append.

The dependencies might not be incompatible but I didn't try.

1 point by akkartik 4253 days ago | link | parent | on: Uploading files in Arc

Can you elaborate on the incompatible dependencies?
2 points by Pauan 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

As promised, here are the benchmarks for unsorted arrays: http://pastebin.com/raw.php?i=DyTHMHNZ

You can also see it in chart form: http://i.imgur.com/BI0NDoD.png

----

So, today I learned that cons cells, despite having O(n) behavior, are really fast. They outperform mutable JS arrays at random inserts!

It's only once you get up to ~100 elements that AVL trees start to outperform cons cells. A good optimization would be to use cons cells for small lists, and then automatically switch to AVL trees once the list grows to be a certain size.

2 points by Pauan 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

How disappointing. Mori[1] (which uses ClojureScript's data structures) was either the same as Immutable-js, or significantly worse. In the end, AVL trees win by a large margin for small to medium dictionaries, while Immutable-js performs better for large (> 100 keys) dictionaries.

Get/insert/remove 1 key:

  Immutable AVL Tree x 37,909,434 ops/sec ±0.37% (101 runs sampled)
  Immutable-js Map   x 19,492,874 ops/sec ±0.15% (101 runs sampled)
  Mori Hash Map      x  2,306,565 ops/sec ±0.74% (96 runs sampled)
  Mori Sorted Map    x 13,424,409 ops/sec ±0.51% (97 runs sampled)

  Immutable AVL Tree x 6,257,569 ops/sec ±0.43% (99 runs sampled)
  Immutable-js Map   x 2,111,085 ops/sec ±1.07% (91 runs sampled)
  Mori Hash Map      x 1,553,193 ops/sec ±0.77% (93 runs sampled)
  Mori Sorted Map    x 3,785,671 ops/sec ±0.43% (96 runs sampled)

  Immutable AVL Tree x 3,426,260 ops/sec ±1.38% (97 runs sampled)
  Immutable-js Map   x 1,415,893 ops/sec ±0.41% (96 runs sampled)
  Mori Hash Map      x   699,113 ops/sec ±0.40% (98 runs sampled)
  Mori Sorted Map    x 1,550,116 ops/sec ±1.54% (100 runs sampled)
Get/insert/remove 10 keys:

  Immutable AVL Tree x 21,954,005 ops/sec ±0.81% (98 runs sampled)
  Immutable-js Map   x 17,236,706 ops/sec ±1.02% (99 runs sampled)
  Mori Hash Map      x  2,474,120 ops/sec ±0.77% (95 runs sampled)
  Mori Sorted Map    x    911,264 ops/sec ±0.41% (100 runs sampled)

  Immutable AVL Tree x 399,700 ops/sec ±0.15% (97 runs sampled)
  Immutable-js Map   x 218,274 ops/sec ±0.63% (98 runs sampled)
  Mori Hash Map      x 150,978 ops/sec ±0.74% (96 runs sampled)
  Mori Sorted Map    x  73,598 ops/sec ±0.68% (98 runs sampled)

  Immutable AVL Tree x 135,120 ops/sec ±0.76% (99 runs sampled)
  Immutable-js Map   x 100,893 ops/sec ±0.20% (97 runs sampled)
  Mori Hash Map      x  74,750 ops/sec ±10.95% (96 runs sampled)
  Mori Sorted Map    x  42,696 ops/sec ±0.45% (99 runs sampled)
Get/insert/remove 100 keys:

  Immutable AVL Tree x  6,467,149 ops/sec ±0.38% (93 runs sampled)
  Immutable-js Map   x 14,233,214 ops/sec ±1.05% (96 runs sampled)
  Mori Hash Map      x  2,513,928 ops/sec ±1.24% (98 runs sampled)
  Mori Sorted Map    x    384,132 ops/sec ±0.53% (98 runs sampled)

  Immutable AVL Tree x 19,760 ops/sec ±0.52% (100 runs sampled)
  Immutable-js Map   x 12,798 ops/sec ±0.26% (100 runs sampled)
  Mori Hash Map      x 10,619 ops/sec ±2.59% (93 runs sampled)
  Mori Sorted Map    x  3,078 ops/sec ±1.49% (98 runs sampled)

  Immutable AVL Tree x  6,420 ops/sec ±0.51% (101 runs sampled)
  Immutable-js Map   x  6,204 ops/sec ±0.20% (99 runs sampled)
  Mori Hash Map      x  5,394 ops/sec ±0.81% (93 runs sampled)
  Mori Sorted Map    x  1,757 ops/sec ±0.51% (100 runs sampled)
---

* [1]: https://github.com/swannodette/mori

3 points by Pauan 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

Here are some performance metrics, using Node.js v0.10.22 and http://benchmarkjs.com/. Higher numbers are better.

Get from a dictionary with 1 key:

  Mutable object     x 27,279,012 ops/sec ±0.74% (97 runs sampled)
  Frozen object      x 26,178,537 ops/sec ±0.18% (101 runs sampled)
  RB Tree            x 43,176,557 ops/sec ±0.34% (94 runs sampled)
  Immutable AVL Tree x 38,223,676 ops/sec ±0.12% (101 runs sampled)
  Immutable-js Map   x 19,359,187 ops/sec ±0.22% (100 runs sampled)
Insert 1 key into an empty dictionary:

  Mutable object             x 6,957,772 ops/sec ±1.96% (96 runs sampled)
  Mutable object copying     x 6,323,751 ops/sec ±0.62% (99 runs sampled)
  Frozen object copying      x   201,268 ops/sec ±1.56% (91 runs sampled)
  RB Tree                    x 7,872,867 ops/sec ±0.42% (100 runs sampled)
  Immutable AVL Tree         x 6,349,293 ops/sec ±0.63% (97 runs sampled)
  Immutable-js Map           x 1,872,937 ops/sec ±0.17% (102 runs sampled)
  Immutable-js Map Transient x 2,056,430 ops/sec ±1.75% (96 runs sampled)
Insert 1 key into an empty dictionary and then remove 1 key:

  Mutable object             x 2,217,063 ops/sec ±0.72% (99 runs sampled)
  Mutable object copying     x 1,993,320 ops/sec ±0.58% (98 runs sampled)
  Frozen object copying      x   143,611 ops/sec ±1.48% (93 runs sampled)
  RB Tree                    x 3,923,739 ops/sec ±0.41% (95 runs sampled)
  Immutable AVL Tree         x 3,511,233 ops/sec ±0.38% (97 runs sampled)
  Immutable-js Map           x 1,334,255 ops/sec ±0.55% (100 runs sampled)
  Immutable-js Map Transient x   886,683 ops/sec ±0.16% (103 runs sampled)
----

Get from a dictionary with 10 keys:

  Mutable object     x 28,446,194 ops/sec ±0.44% (99 runs sampled)
  Frozen object      x 25,922,457 ops/sec ±0.24% (99 runs sampled)
  RB Tree            x 16,603,460 ops/sec ±0.43% (97 runs sampled)
  Immutable AVL Tree x 22,367,775 ops/sec ±0.61% (95 runs sampled)
  Immutable-js Map   x 17,869,208 ops/sec ±0.28% (100 runs sampled)
Insert 10 keys into an empty dictionary:

  Mutable object             x 600,844 ops/sec ±0.71% (100 runs sampled)
  Mutable object copying     x 137,961 ops/sec ±0.16% (102 runs sampled)
  Frozen object copying      x   8,982 ops/sec ±1.77% (97 runs sampled)
  RB Tree                    x 914,296 ops/sec ±0.25% (99 runs sampled)
  Immutable AVL Tree         x 414,025 ops/sec ±0.48% (100 runs sampled)
  Immutable-js Map           x 219,537 ops/sec ±0.44% (101 runs sampled)
  Immutable-js Map Transient x 305,737 ops/sec ±1.06% (98 runs sampled)
Insert 10 keys into an empty dictionary and then remove 10 keys:

  Mutable object             x 302,855 ops/sec ±0.74% (100 runs sampled)
  Mutable object copying     x  49,878 ops/sec ±0.57% (98 runs sampled)
  Frozen object copying      x   8,899 ops/sec ±1.59% (95 runs sampled)
  RB Tree                    x 534,523 ops/sec ±0.54% (99 runs sampled)
  Immutable AVL Tree         x 144,249 ops/sec ±0.16% (99 runs sampled)
  Immutable-js Map           x 111,517 ops/sec ±0.37% (99 runs sampled)
  Immutable-js Map Transient x 173,799 ops/sec ±0.48% (100 runs sampled)
----

Get from a dictionary with 100 keys:

  Mutable object     x 25,410,034 ops/sec ±0.19% (102 runs sampled)
  Frozen object      x 25,156,950 ops/sec ±0.27% (101 runs sampled)
  RB Tree            x 23,728,410 ops/sec ±0.17% (100 runs sampled)
  Immutable AVL Tree x 21,287,235 ops/sec ±0.40% (97 runs sampled)
  Immutable-js Map   x 14,605,600 ops/sec ±0.55% (92 runs sampled)
Insert 100 keys into an empty dictionary:

  Mutable object             x 58,322 ops/sec ±0.55% (100 runs sampled)
  Mutable object copying     x    818 ops/sec ±0.44% (99 runs sampled)
  Frozen object copying      x    139 ops/sec ±0.93% (81 runs sampled)
  RB Tree                    x 51,910 ops/sec ±0.45% (99 runs sampled)
  Immutable AVL Tree         x 20,738 ops/sec ±0.47% (100 runs sampled)
  Immutable-js Map           x 14,000 ops/sec ±1.65% (97 runs sampled)
  Immutable-js Map Transient x 37,714 ops/sec ±0.16% (102 runs sampled)
Insert 100 keys into an empty dictionary and then remove 100 keys:

  Mutable object             x 31,602 ops/sec ±0.56% (100 runs sampled)
  Mutable object copying     x    729 ops/sec ±1.54% (97 runs sampled)
  Frozen object copying      x    137 ops/sec ±2.12% (80 runs sampled)
  RB Tree                    x 31,957 ops/sec ±0.43% (99 runs sampled)
  Immutable AVL Tree         x  7,122 ops/sec ±0.47% (99 runs sampled)
  Immutable-js Map           x  6,001 ops/sec ±0.57% (99 runs sampled)
  Immutable-js Map Transient x 19,958 ops/sec ±0.49% (99 runs sampled)
----

"Mutable object" means a plain old mutable JavaScript object.

"Frozen object" means a plain old mutable JavaScript object that was made immutable using `Object.freeze(foo)`.

"Mutable object copying" means a plain old mutable JavaScript object that was first copied before performing each insertion/deletion.

"RB Tree" means mutable Red Black trees that I implemented in JavaScript: https://github.com/onilabs/stratifiedjs/blob/91d173989c64181...

"Immutable AVL Tree" means waterhouse's algorithm, ported to JavaScript: https://github.com/onilabs/stratifiedjs/blob/c1e5d670784f659...

"Immutable-js Map" means https://github.com/facebook/immutable-js.

"Immutable-js Map Transient" means an Immutable-js Map that uses "withMutations" for extra speed.

I also want to test out ClojureScript's data structures, but I haven't gotten around to it yet.

----

As I said earlier, AVL trees are fast. They tend to be 0-3x slower than JavaScript objects.

Stop and think about that for a moment: JavaScript objects are mutable, they're written in C++, they're heavily optimized with various tricks, and they're probably implemented as hash tables.

Meanwhile, AVL trees are immutable, do not use any kind of optimization tricks (the algorithms are very simple and straightforward), and they are implemented in vanilla JavaScript, in less than 400 lines of code.

JavaScript engines are fast. So fast that immutable AVL trees are completely viable. I would not hesitate to replace all my programs with them. This is quite amazing.

In addition, notice that according to those benchmark numbers, you can create 20 empty AVL trees, then insert 100 keys into each AVL tree (for a total of 2,000 insert operations)... once per millisecond. In this case, worrying about the performance cost of immutability is a huge premature optimization.

(I'm not directing this at anybody in particular, in fact I am the kind of person that does premature optimization, so these numbers help with my own personal fears about performance.)

----

I'll test the performance of unsorted arrays soon and post the results here.

2 points by akkartik 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

Pushed, thanks. https://github.com/arclanguage/anarki/commit/af2ea9c8f4
2 points by Pauan 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

In case anybody wants it, here is the JavaScript code for sorted dictionaries, sorted sets, and unsorted arrays[1]:

https://github.com/onilabs/stratifiedjs/blob/c1e5d670784f659...

It includes algorithms for getting/inserting/removing an element at a particular index (in the case of arrays), and code for getting/inserting/removing an element in sorted order (for dictionaries and sets).

If anybody wants, I can translate the code from JavaScript to Arc.

---

* [1]: Adding in sorted arrays shouldn't be hard, but I haven't had any need for them yet.

2 points by Pauan 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

I used Arc/Nu (https://github.com/arclanguage/arc-nu).

It seems the problem with Anarki is that Arc's lists are terminated with the symbol 'nil rather than Racket's null. So you have to convert from Arc lists to Racket lists (and back again). Here is the relevant code:

https://github.com/arclanguage/anarki/blob/0c4eb66c162f973e7...

1 point by akkartik 4256 days ago | link | parent | on: Re: waterhouse's AVL trees

What arc did you run this on, Pauan? I'm trying to add it to anarki and having trouble with nil-terminated lists and shuffle:

  arc> ($.shuffle '(1 2 3))
  sort: contract violation
    expected: list?
    given: '(1 2 3 . nil)
    context...:
     /home/agaram/.local/racket/collects/racket/private/list.rkt:43:2: sort7
     /home/agaram/Desktop/s/anarki/ac.scm:1215:4
(The require seems unnecessary on anarki.)
4 points by waterhouse 4257 days ago | link | parent | on: Re: waterhouse's AVL trees

Thank you for your kind words. I'm glad you've found my post useful. And that's a good catch about node/r.

It looks like the two versions of node/r differ just in the case when (depth x!lf) = (depth x!rt) [and likewise for y], which it appears I had assumed would not be true; perhaps that was valid for insertions but not deletions. (I must admit deletions came as a bit of an afterthought, as evidenced by the typos in "aremove".) I'm pleased that the resolution is so simple.

Anyway, thanks to you, we now have AVL trees that are actually tested and proven to work.

3 points by Pauan 4259 days ago | link | parent | on: Re: waterhouse's AVL trees

In fact, the normal binary search tree deletion can sometimes cause an unbalanced tree when concatting two arrays, but waterhouse's "amerge" function works correctly!
2 points by c-a-smallwood 4272 days ago | link | parent | on: Another Arc implementation in C

Hmmm. Guess I'm gonna have to make a Windows VM and do some digging.
2 points by SteveGraham 4272 days ago | link | parent | on: The Plain English Compiler

I remember running into a language in the mid to late 80's called Plain English. Funny how things repeat.

Have downloaded the package and need to try it.

Thanks.

2 points by SteveGraham 4272 days ago | link | parent | on: Another Arc implementation in C

Downloaded and tried again. It did make. However, I then got an alert box stating that 'arc.exe has stopped working'.

The parent would be the story you just created. whence is a url to go to on error. For starters it can probably be nil.

What would I pass as the arg for parent and whence?

I think A should be doable. Just call process-comment after submit-item? You'd be double-counting some stats, like for the oversubmitting check. But we can worry about that later.
2 points by c-a-smallwood 4273 days ago | link | parent | on: Another Arc implementation in C

Sorry, for some reason I didn't send the commit for that file before, but it is finally updated this time.
2 points by SteveGraham 4273 days ago | link | parent | on: Another Arc implementation in C

Went to the page, selected Download Zip, downloaded the file, extracted it and ran 'make && ./' and got:

  cc -o arc *.c
  read.c: In function 'load_file':
  read.c:308:47: warning: initialization makes pointer from integer without a cast [enabled by default]
  C:\Users\Steve\AppData\Local\Temp\cctkjQZb.o:read.c:(.text+0xeb4): undefined reference to `_realpath'
  collect2.exe: error: ld returned 1 exit status
  make: *** [all] Error 1
2 points by c-a-smallwood 4275 days ago | link | parent | on: Another Arc implementation in C

Should be fixed in the latest commit.
3 points by c-a-smallwood 4276 days ago | link | parent | on: Another Arc implementation in C

Strange... It can't find realpath. Seems to be a MinGW issue according to google. I've developed the whole on Android w/ C4droid, and I'm not too experienced with MinGW, but I'll see about finding a fix!
2 points by SteveGraham 4276 days ago | link | parent | on: Another Arc implementation in C

I'm on a Win7-64 system running under MinGW.
2 points by SteveGraham 4277 days ago | link | parent | on: Another Arc implementation in C

Error in make:

  sh-3.1$ pwd

  /c/Users/Steve/arc-master

  sh-3.1$ make

  cc -o arc *.c

  builtins.c: In function 'builtin_load':

  builtins.c:369:13: warning: assignment makes pointer from integer without a cast [enabled by default]

  read.c: In function 'load_file':

  read.c:268:47: warning: initialization makes pointer from integer without a cast [enabled by default]

  C:\Users\Steve\AppData\Local\Temp\ccTbSwOD.o:builtins.c:(.text+0x1276): undefined reference to `_realpath'

  C:\Users\Steve\AppData\Local\Temp\ccr5oXek.o:read.c:(.text+0xd45): undefined reference to `_realpath'\

  collect2.exe: error: ld returned 1 exit status

  make: *** [all] Error 1

  sh-3.1$
2 points by akkartik 4283 days ago | link | parent | on: Arcadia: An Implementation of Arc in C

Awesome. Very rare to see a small lisp that gets all the way to to macros.

I played with it a bit, got it running and didn't see any obvious problems. I'll poke around the code as well.


I saw this yesterday and got pretty excited. A while back, I stumbled across the same source of inspiration: http://www.lwh.jp/lisp/index.html

Being mainly a CL hacker who came from Python, Arc has looked interesting to me for a while, but I couldn't justify running a small language on a HUGE backend like Racket... So I started implementing the environment described at the link above, which you did as well. Incorporating my initial work with quite a bit of yours, I spent 24 hours hacking together something similar. I haven't done nearly enough to it yet, but I added some new types and support routines. The code layout is slightly reminisce of Quake code. Take a look if you're interested: https://github.com/camden-smallwood/arc

More