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

Autor here. The implementation on github is for arc 2 and is really outdated. I've got a lot of improvements, including support for arc3 and a self hosting compiler that I haven't released yet. I've stopped working on it after seeing how slow Parrot is at the moment (or at least how slow it was a few months ago). The implementation is quite complete and can load a slightly modified version of arc.arc (mostly to avoid overriding internal functions) but could be easily modified to load the official arc.arc. To give an idea of how slow it currently is, just loading arc.arc takes a few minutes (but it can be pre-compiled, so startup is fast). On my computer it took something like 9 minutes, after an optimization to my code generator I brought it down to 4 minutes, and after a new release of Parrot it went back to 9 minutes (without changing my code, it was the VM's fault). After that, I stopped the development. Another show stopper is that just spawning a new thread makes the VM segfault, thus preventing me to run a slow version of news.arc.

If someone is interested, I can push this new code to the github repo. It probably needs some modifications (not too many hopefully) to work in the latest Parrot, since they've been changing a lot of stuff in the last months. Keeping up with these continuous changes is also among the reasons why I stopped the development. Every month, after a new Parrot release, something broke because the API, or the build system, changed.


2 points by pmarin 3982 days ago | link

I believed that after the version 1 there should be any modification in the API. You have the same problem with Parrot than the rest of the developers. I think the only proyects that are still update are Partcl and Rakudo.

I follow Partcl becouse I am a Tcl user. It is being rewriting in NQP. The Pir version could pass 4089/7397 test from the official test suit. It a lot slower that the official version.

Can you explain how is possible(theorically) to use libraries from various languages with another language in Parrot? The library have to be compiled to Pir?


3 points by stefano 3982 days ago | link

They're still deprecating stuff after every release, and the following month deprecated stuff is removed.

All languages on Parrot compile down to a common denominator, Parrot's assembly language (PIR), either dynamically at run time or before execution. It has an object system and common function call conventions, this means that as long as a language supports calling functions and a compatible object system (or some wrappers around it) it can call any function and use any object as other languages running on the VM. Arc doesn't have an object system, so some wrapper would be needed. To get seamless interoperability the language implementation should define a mapping between the language's primitive types and the corresponding Parrot's types. Primitivearc currently lacks the wrappers around the object system to interoperate with object oriented libraries (adding them wouldn't be a huge task I think), but it can already call any function loaded into the VM. To call a Perl 6 function (this doesn't work because 'load assumes an Arc file but it could be easily modified to call the correct compiler, since the mechanism is already present in Parrot):

  file foo.p6:
    sub foo(%tb) {
      return %tb{"bar"};

  Arc REPL:
    > (load "foo.p6")
    > (foo (listtab '((bar "Baz!"))))


1 point by s-phi-nl 3981 days ago | link

Conanite's Rainbow has a wrapper around the Java object system that you might want to look at.


2 points by adm 3982 days ago | link

maybe work on this can be resumed after, Rokudo star release.


1 point by stefano 4410 days ago | link | parent | on: Proposal: concise function definition

For global functions, I find the usual 'def to be more concise. As of for local functions, it could be quite handy, but possibilities of collision with names defined by 'defset seem quite high to me. I would prefer something similar to CL's 'labels:

  (flet (f (x) (expr x))

  (fwith ((f (x) (expr x))
          (g (x) (f x)))


5 points by stefano 4411 days ago | link | parent | on: Where are we going?

Clojure has already taken many things from Arc (there is also 'prn !)


9 points by stefano 4411 days ago | link | parent | on: Where are we going?

> These are just bugs

This is one reason why it is important for you to be here: some simple things like the problem with 'splice are clearly bugs, but other things are not. For example, the fact that '(1 . 2 . 3) reads as '(2 1 3) is just something drained accidentaly from mzscheme's reader or is part of Arc? Since you've written Arc, you're the only one to really know this. We can only suppose.


14 points by stefano 4412 days ago | link | parent | on: Where are we going?

How are we supposed to look at Arc then? The problem doesn't lay only in the fact that no source has been written, but in the fact that who has full control over Arc doesn't discuss about the language with the community. Is Arc just a one-man work and just a way to show the world this work from time to time?

It's ridiculous that to bring you back in the forum we needed such a harsh post.


11 points by pg 4412 days ago | link

If I were you I'd look at it from the Lisp tradition: as part of a 50 year history with many dialects, rather than as an urgent effort to manage one particular implementation consisting of a huge pile of libraries on top of a badly designed language core.

People who want languages like that already have plenty of options, even Lisp dialects.


7 points by stefano 4411 days ago | link

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.


9 points by jimbokun 4412 days ago | link

Your mantra in your role running Y-Combinator is "make something people want."

Is Arc exempt from that?


17 points by pg 4412 days ago | link

You're forgetting two things.

1. The time scale. I don't want to make what people think they want right now. Following that recipe earlier would have got me Perl, which lost its lead to the language I would have gotten a little later, Python, which lost its lead to the language I would have gotten a little later, Ruby, which... See the pattern?

2. The audience. "Make something people want" is a recipe for companies. Their goal is to make a lot of money, which means aiming for a wide audience. That shouldn't necessarily be one's goal in every kind of work. It's ok to want to be Jane Austen instead of Perez Hilton, even though Perez Hilton is what most people want.


10 points by jimbokun 4412 days ago | link

"I don't want to make what people think they want right now."

Fair enough. I think this sentence pretty succinctly answers the questions in the original post of this discussion.


5 points by john_amendall 4412 days ago | link

Actually, it might be! PG doesn't need to make a living off of Arc.


3 points by cronin1024 4412 days ago | link

Yes and no - he may not be selling Arc itself, but his reputation as a Lisp expert is indeed on the line.


7 points by horia314 4412 days ago | link

hardly. I don't think anybody will thing less of him if Arc somehow fails. It was an ambitious project to begin with.


5 points by stefano 4412 days ago | link | parent | on: Where are we going?

Clojure is on my list. When (if) I give up on Arc It will be the next language I'll learn and use. A lot of libraries from the start. Good performance (the JVM is fast once started). And, most importantly, Rich Hickey follows the language and promotes it. Arc had the great advantage that it had a community of users from the beginning. After its launch, a lot (relatively) of people were already using it. Despite this advantage, Arc hasn't reached the popularity that Clojure has today. Arc had the possibility of being a great language. That possibility has been wasted.

If you want to fork arc, you'd better change its name to break with the past. Make something new. I like the ideas behind snap. I only wonder how much time it would take to have a usable system. Sadly, I'm not able to really help :(


3 points by stefano 4414 days ago | link | parent | on: Reading a webpage

With http-get loaded this macro should do the job. You could also have a look at xml.arc to parse xhtml pages.

  (mac w/url (var url . body)
    `(let ,var (cadr (get-request (str->url ,url)))


1 point by skenney26 4414 days ago | link

Awesome, that's exactly what I needed.

I'm not familiar with how to use xml.arc but this is what I came up with for finding the links on a page:

  (def find-links (str)
    (with (start 0 acc nil)
      (whilet p (posmatch " href=" str start)
        (= start
           (+ p (if (in (str (+ p 6)) #\' #\") 7 6)))
      (push (cut str start (pos [in _ #\' #\" #\> #\space] str start))
      (rev acc)))

  (w/url u ""
    (find-links u))


4 points by stefano 4417 days ago | link | parent | on: Can you spot my error? Newbie question

You forgot a #\" before bottle".

  (def beer (x)
    (with (y t z x)
      (while (is y t)
          (prn (if (is x 0) "No more" x) 
               " bottle" ; *** here the error
               (if (is x 1) "" "s")
               " of beer on the wall, " 
               (if (is x 0) "no more" x)
               " bottle" 
              (if (is x 1) "" "s") 
              " of beer!")
          (if (is x 0) 
             (prn "Go to the store and buy some more, "
                  z " bottle" (if (is z 1) "" "s")
                  " of beer on the wall!")
             (= y nil))
           (prn "You take one down, pass it around, " 
                (if (is (- x 1) 0) "no more" (- x 1)) 
                " bottle" (if (is (- x 1) 1) "" "s") 
                " of beer on the wall!"))
          (= x (- x 1))))))


2 points by rincewind 4415 days ago | link

This should be part of Anarki, so Arc can have the second shortest "99 bottles of beer" program of all langauges ...


1 point by forensic 4415 days ago | link

Which language would have the shortest?

I found a site that lists "99 bottles" programs in 1000 languages, but they don't correct for proper grammar and they don't accept inputs that aren't 99. One guy wrote a shorter 99 bottles program in Arc but it used more high-level functions than mine did.

I can't think of a language that could do the proper grammar, accepting any initial # of bottles, with fewer tokens than Arc.


2 points by rincewind 4415 days ago | link


It is an esoteric language, designed to have the shortest programs for "Hello, World!" "99 bottles of beer" and quines.


1 point by forensic 4417 days ago | link

Thank you, but could you elaborate a little please? I guess I don't understand how to use #\ properly.


3 points by fallintothis 4417 days ago | link

#\x is just the character literal for the letter x -- each element of a string being a character. What the parent means is that you forgot to put a quotation mark before the mentioned line. You don't need to use #\ in this context, but in writing it makes more sense than saying you forgot a " before bottle".


1 point by forensic 4417 days ago | link

Thank you sir. It is clear to me now.


Using array would be a better solution. There should be support for arrays in Anarki.


1 point by bOR_ 4418 days ago | link

General computer philosophy.. shouldn't the structures that work well with CPU's be present in the language, and used by the language, but not neccesarily accessible by humans, and the structures that work well with humans be the ones that are accessible to humans.

So while anarki might need to support arrays internally for efficiency, they need not neccesarily be part of the language as far as the users can tell.

If the above is true, then right now the implementation of things that are efficient for the language when it wants to communicate with the cpu are of a lower priority than the things that are efficient for the communication between the user and the language.

Given all this, why would users want arrays?


3 points by cchooper 4418 days ago | link

I think we can have the best of both worlds. I would love Arc to have an intelligent compiler that figures out the best representation for your data, but I would also like access to the low-level data types.

Why? Because Lisp is supposed to be a reprogrammable programming language, where the user can do anything the compiler can do. If the user has access to the underlying bits and bytes, then they can implement new representations of high-level structures, rather than relying on the compiler writer. In fact, I would argue that Arc should only provide low-level structures in the axioms, and then high-level ones can be implemented on top.


1 point by almkglor 4418 days ago | link

If I wanted to represent a matrix of objects.... say a world populated by virtual creatures... I might prefer to predefine the size of the world and identify creature locations using numeric coordinates. I might then want to use an array of arrays to represent the world ^^. I might even abstract away the position of an object using a "location" type composed of a pair of numeric coordinates and a reference to the world, then have "north" and "east" etc. functions to get locations in those directions. Then I might get the reference or set the reference of a location object and thus query and/or change the state of the creatures in that world.... ^^

In Arc-F for example I might use:

  (using <vector>v2) ; vector and vector-of

  (def make-world (xwidth yheight)
    (apply vector
           (w/collect:for i 0 (- xwidth)
             (collect:vector-of yheight nil))))

  ; create a location type
  (def location (world x y)
    (annotate 'location
      (list world x y)))

  (defcall location (r)
    (let (world x y) r
      (world.x y)))

  (defm sref ((t loc location) val)
    (let (world x y) (rep loc)
      (sref world.x val y)))

  ; 0---> INF
  ; |
  ; |
  ; v
  ; INF
  (def south (loc (o step 1))
    (err "'north and 'south expect a location"))
  (defm south ((t loc location) (o step 1))
    (let (world x y) (rep loc)
      (location world x (+ y step))))

  (def north (loc (o step 1))
    (south loc (- step)))

  (def east (loc (o step 1))
    (err "'east and 'west expect a location"))
  (defm east ((t loc location) (o step 1))
    (let (world x y) (rep loc)
      (location world (+ x step) y)))

  (def west (loc (o step 1))
    (east loc (- step)))


1 point by bOR_ 4418 days ago | link

just a random hypothetical situation eh? ;).

I should put some more work into it. The good news is that I just found a nice and simple editor that plays well with arc-f on windows (LispIDE -

btw. arc-f arc.bat doesn't play nice yet with "Program Files" type of directories. Works fine in C:\arc-f.

Got this error:

> default-load-handler: cannot open input file: "C:\Program" (The system cannot find the file specified.; errno=2)


1 point by almkglor 4417 days ago | link

> just a random hypothetical situation eh? ;)

Of course, of course ^^

> btw. arc-f arc.bat doesn't play nice yet with "Program Files" type of directories.

Huh. I guess I really should fix my WinXP computer at some point in time T.T


1 point by stefano 4418 days ago | link

We could give only lists to the user, and implement them internally as arrays when they are frequently used with indexed access and with lists when they are mainly used with car/cdr. Not an easy thing to implement, though.


2 points by almkglor 4417 days ago | link

I made a suggested implementation of lists as unrolled lists which preserves the use of 'scdr on the Arc Forum a long time ago. . Basically it would be effectively arrays.


1 point by almkglor 4417 days ago | link

The problem with the proposed implementation however is that the "cons pointer" is a data structure of at least two cells (a pointer to the root of the underlying array, which includes a pointer to the cdr-table somewhere, and a pointer to the actual entry within the array).

However recently I thought of a method by which all that is necessary would be a (probably tagged) pointer to the actual entry within the array. This would require tagged pointers (i.e. no Boehm-Weiser!).

Basically we would define a tagged pointer type which, when found in a list-as-array, would not be a valid 'car of that entry, but rather would be a pointer to an object containing the real 'car and 'cdr for that object. It might be possible to also use a tagged pointer (potentially the same tag, but say with a null pointer) to denote the end of a list.

Let's call this invalid tag a "NON_CAR_TAG", and let's call the tag for a pointer to an array-as-list-cons-cell a "CONS_ARRAY"

Basically a (list 1 2 3 4) would be represented with the array:

  [0] INTEGER(1) // tagged with an INTEGER
  [1] INTEGER(2)
  [2] INTEGER(3)
  [3] INTEGER(4)
  [4] NON_CAR_TAG( NULL ) // null pointer
A 'cons object would either be a (potentially nontagged) pointer to a real cons cell, or a CONS_ARRAY() tagged pointer to an entry in an array such as the above.

Now suppose we have the operation (= foo (list 1 2 3 4)). 'foo would then contain a CONS_ARRAY() tagged pointer to the above. Suppose the pointer to the above array is 0xDEADBEE0. 'foo would then be CONS_ARRAY(0xDEADBEE0).

Now suppose that a cell is exactly 16 bytes (just an example for easier reasoning). So (cdr foo) would be CONS_ARRAY(0xDEADBEF0), (cdr:cdr foo) would be CONS_ARRAY(0xDEADBF00), etc. Basically, 'cdr would first check if the input is a CONS_ARRAY() tagged pointer, and just add 0x10 (or the cell size). If the resulting address points to an entry that happens to be NON_CAR_TAG(NULL), it should return a NILOBJ, otherwise it returns the result of the addition.

Now, suppose we then do (scdr (cdr foo) 42). 'scdr should first detect if the the pointer it is given is a CONS_ARRAY() tagged pointer. If so, it determines if the value being pointed to is a NON_CAR_TAG() or not. If it's a NON_CAR_TAG(), it gets the underlying cons cell pointed to by the NON_CAR_TAG and modifies that. Otherwise, it allocates a new cons cell, populates it with the existing 'car and the new 'cdr, tags the cons cell pointer with NON_CAR_TAG(), and replaces the entry:

                   +---------> CONS: A INTEGER(2)
  [0] INTEGER(1)   |                 D INTEGER(42)
  [1] NON_CAR_TAG( * )
  [2] INTEGER(3)
  [3] INTEGER(4)
Note however that it has a drawback that l.index is still O(N) T.T


1 point by cchooper 4417 days ago | link

I've just pushed support for MzScheme's byte strings, which are very similar to binary arrays.


2 points by stefano 4419 days ago | link | parent | on: New user: some general Arc questions



1 point by mr_excellent 4419 days ago | link

Thanks, Stefano.

Funny thing. I made up my username here quickly and without much thought, but if I'm going to stick around, maybe I'll change it.