For now I'm going to leave Windows ports as something for other people to do downstream if they want to. It should be pretty easy, and I don't want to do it myself because I don't have access to a Windows machine or understand anything about the OS.
Currently, ensure-dir and date use system to run Unix commands. It would be much more portable if they used mzscheme operations instead. This has caused me trouble not only on Windows, but different versions of Linux. And I think make-temporary-file could replace /dev/urandom.
I changed date to get the date from Mzscheme, but it's not so easy to change ensure-dir. Mz's make-directory doesn't create intermediate directories like mkdir -p, and I don't want to get into trying to understand pathnames.
If anyone wants to take on being a distributor for a Windows port (or for different variants of Linux, for that matter), I do have a patch for date here: http://catdancer.github.com/date.html
Another option is the Anarki stable branch (http://github.com/nex3/arc/commits/stable/), which has most of fixes necessary to make most of Arc work portably on Windows and other OSes. (And, being a bug-fix branch, the amount of other random material is limited.)
I agree with the option, but I also think these posts will fall off the deep end in about 2 months. By then new members may only discover the option after they've discovered the problem. So we're not really saving new members wasted efforts unless the install page guides people.
pg: Even if you'd rather not think about supporting Windows portability yourself, providing a link to the Anarki stable branch would help new Windows users. Finding this stuff on the forum after it's fallen off the top couple of pages is not very easy.
I have most of them already fixed myself, with the exception of pipe-from, but an average person (aka me) with Windows OS is going to spend time both trying to get Arc working and sifting through the forum which isnt easily searchable (I had to sift through over 300 posts, with 80% of the content being way over my head, to determine pipe-from wasn't expected to be working for a specific reason.... had no clue what "dev/urandom" even was).
If I might suggest: if your not going to fix these that you start a known issues document to save people from the headaches and tail chasing. Even putting something on your install page noting that Windows isn't supported would be appreciated by newcomers.
[Edit] As an idea maybe we could have one posting thread for OS related issues that your install page has a link to ? ....
I like what you've done, but I don't believe this will catch many of the other common conflicts. Example: names, global or table names and also dynamically generated versions of both - I've come across a few of these too.
I am under the impression that a language community led by original authors create something similar to anarki with a board or group that manages some form of standards, quality and compliance ect... similar to what I imagine scheme or python has. This way it's not the authors responsibility, but can be the communities too. I just think arc needs to establish itself with a bigger community and until then it's going to be a little more painful (a little less with your new hack).
Kinda sucks, no big community = a bit of a disincentive for hackers like yourself to contribute valuable code to the community if you end up getting all kinds of requests/baggage from it.
I don't believe this will catch many of the other common conflicts
Doesn't need to. This is one tool in the toolbag which does nothing but fix one problem. If you have a different problem, pull out a different tool :-)
board or group that manages some form of standards, quality and compliance
Sure, that's what's usually done, but it also has a lot of overhead in bureaucracy, politics, and conformance to poorly designed standards. I'm curious about another approach: what if patches were really easy? What if you could say, "ok, here are the fifteen patches I want in my Arc", and you could just push a button to get them? Now you don't need a board to be filtering patches for you, you can choose which ones you find to be of high quality. Or perhaps, for a particular project, a patch of terrible quality but happens to do something you want for that project :) I'm not sure of all the details yet, but I'm playing around with it.
disincentive for hackers like yourself to contribute valuable code to the community if you end up getting all kinds of requests/baggage from it
Well, my goal is to make it easy for me to share my Arc hacks. I have a whole bunch of hacks to Arc that I've written while doing my own programming, and some of them I've had the time to write up and publish. I'd like to make this easier and faster, so that I can publish more of my hacks without it being any trouble.
And I'd like to become easy for programmers such as yourself to publish your own hacks, such as the patches you made to the JSON library. That way if someone finds your version to be better, they can use yours. Or if they don't like what you did with symbols or something, they can use mine. Or pull out what changes they like from yours.
Now I'm not so worried about requests and stuff. If you see a way to make one of my hacks better, go ahead and publish your changes. No one is forced to use your version, but if it is better, then people can use it.
Eventually we have a lot of hacks floating around and people will start publishing collections. "Here are the thirty Arc hacks and libraries that I recommend". Each person who publishes a collection will have their own standards for what hacks they include. To get started, you can pick a collection author who has standards you agree with to get your initial collection of Arc hacks and libraries. But the collection still consists of individual hacks that you can pick and choose from, so you're not stuck with the collection compiler's decisions. That's the idea anyway... I still need to write up more about it.
Test cases: (some input cases are just to make sure there are no infinite runs)....
(forstep i 5 10 1 (prn i))
(forstep i 5 10 2 (prn i))
(forstep i 10 5 2 (prn i))
(forstep i 5 10 -2 (prn i))
(forstep i 0 1 0 (prn i))
(forstep i 1 0 0 (prn i))
(forstep i -2 2 1 (prn i))
(forstep i 2 -2 1 (prn i))
(forstep i -4 2 2 (prn i))
(forstep i -4 2 -2 (prn i))
(forstep i 4 -2 -2 (prn i))
(forstep i 4 -2 2 (prn i))
That being said, I don't understand why changing 'for' this way would create problems for you, or why you want
(for i 1 0 (prn i)) to return nil.
also, I still think it would be nice for arc to support keyword arguments (hint, hint pg - though he's probably not reading this), then I could have 'step' as an optional arg with a default. i.e....
(mac for (v start end (o step 1) . body)...
could allow:
(for i 20 5 (prn i)) and also something like: (for i 20 5 step:2 (prn i))
A much better alternate version too. The redundant code in my hacked version was obvious and ugly, but I struggled reducing it to a simpler form... Thanks!
I made a few slight adjustments though, as it failed 2 of my test cases (however unlikely they are to occur, infinite runs scare me).
That being said, I don't understand why changing 'for' this way would create problems for you
Perhaps I'm doing i from 1 to the number of things I have, and sometimes I have zero things.
Actually though it was a bit silly of me to suggest "forstep" when your version of "for" was doing what you wanted it to do. It's not a version that I'd want to use in my code, but that's no reason for you not to have your version.
As a note - It may still be a good idea, but I care less after some thought:
Originally I was trying grab the last number of items in a table (something similar to your code in prompt.arc where you are grabbing/printing the last n items passed into the repl).
When using a list, as you had, we can easily grab the last 'n' items in the list since lists maintain order.
(= records* (list "record 1 text" "record 2 text" "record 3 text" "record 4 text" "record 5 text" "record 6 text"))
(def lastn (n nlist)
(firstn n (rev nlist)))
arc>(each record (lastn 3 records*)
(prn record))
record 6 text
record 5 text
record 4 text
However if storing the data in a table it's not as clear grabbing the last n items since tables have no inherent order.
as you can see this isn't as straight forward:
(= records* (obj 1 "record 1 text" 2 "record 2 text" 3 "record 3 text" 4 "record 4 text" 5 "record 5 text" 6 "record 6 text"))
arc> (each record (firstn 3 (sort > (keys records*)))
(prn (records* record)))
record 6 text
record 5 text
record 4 text
so I had hoped 'for' in reverse would be cleaner...
arc> (for i (len records*)(- (len records*) 3)
(prn (records* i)))
record 6 text
record 5 text
record 4 text
record 3 text
only after re-writing I noticed that I was getting too many results thus ended up having to hack:
If my hope was to make the code more readable, it didn't work.
So.... instead I wrote 'grab':
(def lastn (n nlist)
(firstn n (rev nlist)))
(def grab (which n them (o sop nil))
(case (type them)
table (case which first (if (no sop) (firstn n (sort < (keys them)))(firstn n (sort sop (keys them))))
last (if (no sop) (firstn n (sort > (keys them)))(firstn n (sort sop (keys them)))))
cons (case which first (if (no sop) (firstn n them)(firstn n (sort sop them)))
last (if (no sop) (lastn n them) (lastn n (sort sop them))))))
And now I feel it's much more readable + works on both lists and tables:
arc>(each record (grab 'last 3 records*)
(prn (records* record)))
record 6 text
record 5 text
record 4 text
T.
[EDIT] - Hadn't thought about it until now, but it has re-use even if the table doesn't have nums for keys, it would also work on other keys (example grabbing the last n items of alphabetical order). Anyway... don't spend time on re-working 'for' it it doesn't help anyone else.....
Anarki has a lot of great stuff in it, but it also has alot of crap in it. I spent 2 weeks just going through the code pulling out the pieces I like from Anarki and not the rest. I certainly hope pg keeps the arc code down to the dozen or so core files forcing the community to build libraries on top rather than integrate adhoc extras at such a low level that it's brutal to separate the good from the bad.
I am not sure if this is a bug or by design, but I will throw it out there. Records stored in tables are not returned in the original order they were loaded (unlike lists are). It would be nice to iterate/process records in the table without having to create code to store the original loaded order.
Further to order type issues shouldn't the 'accum' function return the list of items in the order in which it was accumulated ? Currently it returns the reversed order. it would be nice for this to work as one would expect.
It's intentional. You have to use an explicit rev if you care about the order-- since sometimes you might not. But I'm open to changing that, because I'm often annoyed to have to add the explicit rev. (This is why you have to write apps in a language at the same time you're working on it.)