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.
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?
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):
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:
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.
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 arclanguage.org 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.
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.
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.
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.
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 :(
(def beer (x)
(with (y t z x)
(while (is y t)
(do
(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)
(do
(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!"))
(prn)
(= x (- x 1))))))
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.
#\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".
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.
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.
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)))
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 - http://www.daansystems.com/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)
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.
I made a suggested implementation of lists as unrolled lists which preserves the use of 'scdr on the Arc Forum a long time ago. http://arclanguage.com/item?id=4146 . Basically it would be effectively arrays.
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)
[4] NON_CAR_TAG(NULL)
Note however that it has a drawback that l.index is still O(N) T.T