Arc Forumnew | comments | leaders | submit | akkartik's commentslogin

Rather than compare it to arc, I found it tantalizing to think about how I'd implement that syntax. It looks like he's built objects for modules/namespaces, ranges, etc. But he's somehow supporting infix without spaces and also names like print-line. How does it work?! :)

Edit 8 minutes later: Also, the square brackets around the call to [f 1] are strange. If they're mandatory, there's something there I don't follow.

-----

2 points by shader 4430 days ago | link

Interesting direction to take it. It would be interesting to know how he implemented it, so that he can still consider it to be a lisp. In particular that '#include' syntax sticks out a bit.

I also found it ironic how conflicted he is over its relationship with lisp.

-----

2 points by akkartik 4431 days ago | link | parent | on: Anarki clone problem

That looks like something I broke, sorry about that. I'll investigate later today.

Edit 1 hour later: Now fixed: https://github.com/arclanguage/anarki/commit/98e1edf198. Sorry again!

-----

2 points by chp 4431 days ago | link

Thank you. Had the same issue. This works.

-----

1 point by akkartik 4432 days ago | link | parent | on: A FizzBuzz solution in Arc

Interesting, I wasn't aware of the gcd trick. I had something to learn even in fizzbuzz, who knew?!

But hmm, I don't see gcd defined anywhere in arc3.1 or anarki. Where are you seeing it?

-----

2 points by heated 4431 days ago | link

Whoops. Seems to be my implementation only. (and Racket)

-----

2 points by akkartik 4431 days ago | link

Cool; added. https://github.com/arclanguage/anarki/commit/e893c94e5d

-----

1 point by svetlyak40wt 4430 days ago | link

That is not fair in this case. Please, write example code in terms of Arc3.1 primitives.

-----

2 points by heated 4425 days ago | link

Ok

-----

2 points by akkartik 4433 days ago | link | parent | on: Replace loop with xloop

It took me a while to understand this, but you're right. No reason that while (https://github.com/arclanguage/anarki/blob/5c9983144c/arc.ar...) can't be built out of xloop.

Changing the names is a separate matter. We could rename the existing loop to for. Does anybody object to that? It's been baked in since the original arc, so I'm feeling a little cautious about messing with it. Any suggestions for alternative names to the existing for which only works on ranges of numbers? One idea is to call it up since there's already a down just below it that scans downward on ranges of numbers.

In wart I chose to define for with a variable declaration. Compare https://github.com/akkartik/wart/blob/b7b822f4fb/048control.... and https://github.com/arclanguage/anarki/blob/5c9983144c/arc.ar.... Once for declares its own variable I think you no longer need a separate macro for up and down. Thoughts?

-----

2 points by malisper 4432 days ago | link

For some reason I thought for and while were both implemented using loop. Turns out only for is so that probably led to some confusion. I guess it would make sense to implement while with xloop. I do like the idea of moving the current for to up. What I meant originally was to replace the uses of loop with xloop.

I have to agree with you that the current loop should definitely allow variable declarations as it should be the general case of up/down. The remaining cases should be covered by while (unless we want to put the update and the test in the same place which I see no reason for).

Just a question about some of your code. How is while not infinitely recursive? Are macros substituted at runtime in wart?

Edit: I just realized that we can implement the current loop in terms of xloop.

-----

2 points by akkartik 4431 days ago | link

Ok, anarki now has a coherent set of iteration primitives. At bottom is the erstwhile xloop, now called loop: https://github.com/arclanguage/anarki/blob/96a2757190/arc.ar....

Almost all existing occurrences of rfn are now switched to use loop. For example, see the new rev: https://github.com/arclanguage/anarki/blob/96a2757190/arc.ar...

The old loop is renamed to the subtly different for which now declares its own variable. Since for is kinda imperative, it supports break and continue out of the box: https://github.com/arclanguage/anarki/blob/96a2757190/arc.ar.... So does while: https://github.com/arclanguage/anarki/blob/96a2757190/arc.ar...

I've made a subtle change to up and down -- following C, they are no longer inclusive of their second bound. Before:

  arc> (up i 0 3 prn.i)
  0
  1
  2
  3
After:

  arc> (up i 0 3 prn.i)
  0
  1
  2
I think I've caught all their callers and corrected them, but there might be stray bugs in lib/math.arc. (It's amazing how much cleaner math.arc has gotten with the saner, C-inspired bounds.)

As the piece de resistance, compare drain before (https://github.com/arclanguage/anarki/blob/426b07440bb8d8531...):

  (mac drain (expr (o eof nil))
    (w/uniq (gacc gdone gres)
      `(with (,gacc nil ,gdone nil)
	 (while (no ,gdone)
	   (let ,gres ,expr
	     (if (is ,gres ,eof)
	       (= ,gdone t)
	       (push ,gres ,gacc))))
	 (rev ,gacc))))
And after (https://github.com/arclanguage/anarki/blob/96a2757190/arc.ar...):

  (mac drain (expr (o eos nil))
    (w/uniq (gacc gres)
      `(accum ,gacc
	 (whiler ,gres ,expr ,eos
	   (,gacc ,gres)))))
I'm still concerned about changing the semantics of loop and for, especially with the prospect of updates from pg. Fortunately it's easy to roll back these changes :)

-----

3 points by akkartik 4431 days ago | link

A final, more speculative change: for loops are named, so you can break and continue multiple loops at once using the name of the loop variable. Both these fragments have identical output:

  (up i 0 3
    (up j 0 3
      (if (> j i) (break))
      (prn i " " j)))

  (up i 0 3
    (up j 0 3
      (if (> j i) (continue-i))
      (prn i " " j)))

-----

1 point by akkartik 4421 days ago | link

What do people think of how tokens looks with afn vs loop? https://github.com/arclanguage/anarki/commit/1dd646ddcb

-----

1 point by akkartik 4432 days ago | link

Yes, wart has first class macros :) I meant to bring that up when comparing while in arc and wart.

-----


Yeah. Technical debt[1] is a real phenomenon, and it's easy to under-estimate if you just look at nascent projects. After looking at a few short-term successes you may be tempted to assume you can just do what you think they did to get their results. But that approach is susceptible to survivor bias[2]. In reality doing anything on your own is a risky endeavor, and one way to inarguably reduce risk is to get time on your side[3]. If you take on too much technical debt time starts working against you.

The real problem is that we still have only a hazy understanding of what technical debt entails. I suspect many of the things we worry about aren't the biggest sources of technical debt or incidental complexity[4]. So yes, sometimes doing a lot of conventional 'engineering' turns out to be unnecessary. But that is a case for being more thoughtful, not less.

[1] http://en.wikipedia.org/wiki/Technical_debt

[2] http://en.wikipedia.org/wiki/Survivorship_bias

[3] http://paulgraham.com/die.html

[4] http://en.wikipedia.org/wiki/No_Silver_Bullet; http://www.codequarterly.com/2011/rich-hickey

-----

2 points by malisper 4433 days ago | link

Thanks for catching the survivorship bias.

I definitely have to agree with you that being thoughtful is important. If anything that's what programming is about. Knowing which tools of those available to you are the best for each situation.

-----

3 points by akkartik 4433 days ago | link

On the other hand, he does have a point in the bit you quoted: there's a lot of different considerations one has to deal with, and you're often doing something wrong if your focus is on architecture.

My incomplete answer at this point is to try to always record the scenarios I considered when building, in hopes that it'll keep the code easy to rewrite later on without causing regressions. By taking on that burden I hope to drop the larger burden of worrying about architecture too prematurely.

This is why almost all my thinking lately has been around how to increase the surface area that can be covered by tests: http://akkartik.name/prose (especially http://akkartik.name/post/tracing-tests). Eventually I want us to be able to easily write tests for performance, concurrency, fault tolerance, UI layout, etc., etc.

-----

2 points by akkartik 4435 days ago | link | parent | on: Streams

Hmm, I think you need to do more to redefine scar and scdr:

  arc> (= x '(1 2 3))
  arc> x
  (1 2 3)
  arc> (= car.x 4)
  4
  arc> x
  (4 2 3)
  arc> (load "lib/streams.arc")
  *** redefining scar
  *** redefining scdr
  nil
  arc> (= car.x 5)
   scar: arity mismatch;
   the expected number of arguments does not match the given number
    expected: 1
    given: 2
    arguments...:
     '(4 2 3 . nil)
     5
The problem is that prior uses of scar and scdr (such as assignment to car[1]) will try to call your version. It's usually a bad idea to repurpose names for something unrelated. At the least we need to go through and fix callers of the old name.

Not a huge deal at the moment since your library isn't loaded by default. So we have some time to think about how to fix this.

[1] https://github.com/arclanguage/anarki/blob/3662afea89/arc.ar...

-----

2 points by malisper 4435 days ago | link

The simplest fix would be to overload scar/scdr based on the number of arguments. While it's a nice quick fix, I do not like the idea of using the same name for two different functions.

-----

1 point by akkartik 4435 days ago | link

Yeah, especially since one of them is destructive and one isn't!

If we can get regular car and cdr to handle lazy streams then this issue will be moot. I'm investigating this. I didn't understand your point 1 above regarding when to tag, so I'm trying to recreate the primes example from SICP 3.5 to better understand the issue.

Can you point me at any sample calls to your library, maybe things you tried on the commandline while you built it?

-----

2 points by rocketnia 4434 days ago | link

Now may be a good time to mention almkglor's lazy list library for Arc 2, which did extend 'car and 'cdr like you're talking about:

https://github.com/arclanguage/anarki/blob/arc2.master/lib/s...

---

Meanwhile, here's a generator library for Arc 2 by rkts: https://github.com/arclanguage/anarki/blob/arc2.master/lib/i...

And here are three relevant libraries I made as part of Lathe:

- A lazy list library, which happens to use a multimethod framework I made: https://github.com/rocketnia/lathe/blob/master/arc/orc/oiter...

- A generator library: https://github.com/rocketnia/lathe/blob/master/arc/iter.arc

- An amb operator library: https://github.com/rocketnia/lathe/blob/master/arc/amb.arc

I've never actually found much use for these, heh.

-----

1 point by akkartik 4434 days ago | link

Thanks for the links! Too bad none of them show example usage.. :) But no matter, I'll add some to this version. It's looking promising so far, I'll push it later today.

One thing I learned from malisper's code was the existence of afnwith in anarki (https://github.com/arclanguage/anarki/blob/87d986446b/lib/ut...), which is a neat alternative solution to my http://arclanguage.org/item?id=18036.

-----

1 point by akkartik 4434 days ago | link

Ok, I've turned streams into a tagged type. I had to just support them in car and cdr and carif to get common list operations to work. However, existing operations still return regular (eager) lists when you pass them lazy streams, so I followed malisper's idea of creating lazy variants that preserve laziness in the result.

I've also added unit tests for them in lib/streams.arc.t, which is my first serious attempt at using zck's nice unit-test harness with suites.

malisper, I took some liberties with your code, such as renaming the 's' prefix to 'lazy-'. I'm not attached to these things, so feel free to revert any of my changes you don't like. Thanks for a fun exercise!

I'm not sure how you're measuring overhead, but let me know if it seems slower than before.

https://github.com/arclanguage/anarki/commit/6180f0e65

-----

2 points by malisper 4434 days ago | link

Why append lazy to the beginning when we can just extend all of them to use scons when given a stream.

-----

1 point by akkartik 4434 days ago | link

Well, you need it for cons and the generator lazy-gen and other functions that don't take a stream. Maybe the others don't, but it seemed to me that sometimes it makes sense to return a list and sometimes not. So especially since functions like firstn do something useful without changing anything, maybe we should keep that behavior around. But it's just an idea. What do you think? Since you're using them for project Euler, it'll be good to hear your experiences.

-----

2 points by rocketnia 4434 days ago | link

I'm a little surprised to see 'afnwith. Anarki also has aw's 'xloop, which is the exact same thing as 'afnwith but with the "self" anaphoric variable renamed to "next".

-----

1 point by akkartik 4434 days ago | link

Ah, that's a much nicer name. I (too) found the presence of fn to be misleading since the afn is called immediately after it's created.

I've deleted afnwith from anarki: https://github.com/arclanguage/anarki/commit/a0052f031

In wart the name can be nicer still -- just loop since for does what arc's loop does, in the footsteps of classical C.

Edit 20 minutes later: I ended up going with recur instead of next, to form a loop.. recur pair. I also considered with loop.. recur to strengthen the connection with with for the alternating var/val syntax. (The other pair of keywords in wart is collect.. yield in place of accum acc.) https://github.com/akkartik/wart/commit/b7b822f4fb has has an example use, which had me hankering for absz's w/afn (though with a better name; http://arclanguage.org/item?id=10125)

Edit 25 minutes later: It turns out xloop nests surprisingly cleanly. This does what you expect:

  loop (a 0)
    loop (b 0)
      prn a " " b
      if (b < 5) (recur ++b)
    if (a < 5) (recur ++a)
Edit 29 minutes later: Oh, loop.. recur is precisely what clojure uses!

-----

3 points by shader 4425 days ago | link

I feel like we need to extend the documentation on arclanguage.github.io to include the extra libraries on anarki, to improve discoverability.

-----

2 points by malisper 4434 days ago | link

I don't know what I was thinking. Of couse we could just tag the streams when they are created with scons. If we really wanted to we could just extend all of the basic operations for working with lists.

There still is the problem of efficiency though. For what I have been using them for (project euler) efficiency is a big deal.

-----

1 point by akkartik 4435 days ago | link | parent | on: Streams

That reminds me: I never did get around to adding your test harness to anarki like I promised. I'll do that if I get around to adding some lazy tests this weekend. Otherwise feel free to do so when you look at this again.

-----

1 point by akkartik 4430 days ago | link

Now that anarki has its first suite of tests using your harness, I've designated all prior tests as "old tests" to encourage us to move away from our patchwork of prior solutions.

https://github.com/arclanguage/anarki/commit/a30d51ce87

-----

1 point by akkartik 4437 days ago | link | parent | on: A FizzBuzz solution in Arc

I love rosetta code. I spent a few weeks adding samples for my arc-like dialect: http://rosettacode.org/wiki/Category:Wart. I'd meant to add samples for arc as well, but never got around to it. Glad to see someone else taking charge!

-----


I'm curious how you found that link, malisper.

-----

3 points by malisper 4437 days ago | link

I was just looking at some of the older posts here and came across the discussion of arc2js[0]. When that link didn't work I used Google and came across another post[1] where he mentioned an updated page and that one had a link that worked. I must have accidentally copied the broken link instead of the one to the actual page.

[0] http://arclanguage.org/item?id=14795

[1] http://arclanguage.org/item?id=15086

-----


Crap. It's a real problem that branches aren't version controlled.

-----

More