I do not see why you feel the need to change a perfectly good name.
It may be similar to other names that are part of the arc compiler, but those names are scheme names. This name is visible in arc, and arc naming conventions are "short and sweet". 'mz is a perfectly good mnemonic for what it does, and is very unlikely to need to be taken for anything else.
I do not understand how your "Why not name after the backend", in fact, explains why we should not name it after the backend. You admit yourself that "the implementation of the interface would naturally be very different depending on the backend" - so it won't be a problem that the "lower to CL" version of mz is named something different. You don't, AFAICT, present any argument that 'ac-tunnel should be named the same with different backends, merely an argument that, for people building library interfaces, it won't be much trouble. But not everyone is engineering libraries: arc is to a large extent about experimentative coding, and there are no significant disadvantages to just letting it be named 'mz. Sure it's easy to just (mac mz body `(ac-tunnel ,@body)), but why should it be necessary?
In the end, this is a fairly small issue. I hardly want to get into a flame war over it, and it's your hack... but, as I say, I don't get why you want to fix something that isn't broke.
I do think that this would be a useful facility to add to Arc. I think it has high leverage, in that it is a small addition to Arc that has a lot of power: with this change several features can be written with code that can be loaded instead of needing patches.
pg tends to go for short names for function/macro names that need to be typed a lot. I was concerned that something as short as "mz" was too valuable an identifier to be used for something that most people wouldn't be typing.
But if people want to name it "mz" or something else that refers to MzScheme, that's fine with me!
Maybe it's just that I've been writing a lot of libraries, but I use 'mz a lot ;)
Besides, I can't imagine needing that combination of letters for anything else. Especially after having it refer to mzscheme for so long now, it would be hard to switch it.
It doesn't matter to me what it gets named as. pg could add it to the Arc core as %%%internal-compile-to-mzscheme, and I could still use "mz" in the code I write using load-w/rename or some similar mechanism.
I think that FOR NOW, 'mz is fine. Even though each person has their own patched-up Arc, it seems as though the vast majority are based on pg's Arc on mzscheme. If somebody is using an Arc built on some other VM (eg Rainbow on the JVM), then they will be putting quite different code within the body of an 'mz, so I don't think it's an issue that they'd also have to change the name of the symbol.
I completely agree ac-tunnel (or mz) is a useful facility to add to arc, especially to use for once-off hacks, or to figure something out before committing to an xdef. I wrote rainbow just so I could use java libs while playing in arc (among other reasons).
As the author, you get to name your babies. I didn't agonise over java-new, java-implement, or (ugh) java-static-invoke - they're mostly buried under arc macros in any case.
In the worst case, if there's a conflict with mz (or ac-tunnel), I would recommend an excellent symbol renaming hack available on github at http://catdancer.github.com/load-rename.html
Oh. That's good then. Whoops. :) Now I feel like a bit of a jerk for ragging on about the name so much.
I am completely in agreement that this is a good feature. When anarki was still up-to-date, I used '$ quite a bit, and this is essentially just a better version of that - one that lets you access local variables and has less overhead to boot!
Speaking of Anarki, what needs to be done to get it back up to date?
I haven't heard much about that. Maybe we should make a new thread about updating it?
You're comment about local variables made me think of something:
What if we used ac-tunnel, like CatDancer suggested, and then make mz defined as:
(mac mz body
(list 'ac-tunnel (cons 'quasiquote body)))
That way mz is defined in terms of the tunnel, and adds the feature of being able to unquote variables to pass the value through to scheme. $ had that feature, but called seval instead, so it lost the local environment. This way, we get the local environment, and the quasiquoting.
Making the entire thing quasiquoted doesn't work. That would mean that the following:
(let x 2 (mz (+ 2 ,x)))
Would compile down to this:
((lambda (x) `(+ 2 ,x)) 2)
Which obviously is not the intended functionality - it evaluates to the list (+ 2 2), not to the value 4. A quasiquote is, after all, a quote. So you'd need to add an 'eval outside it, and then you just have '$. Anyway, you already get the local environment with 'mz, because arc compiles local variables down to the same-named variables in mzscheme. That is to say, with 'mz as it currently stands, the following:
(let x 2 (mz (+ 2 x)))
Compiles into:
((lambda (x) (+ 2 x)) 2)
So it just works! This does depend on the internals of the compiler, but then, that's the whole point of 'mz.
As for getting anarki back up to date, I discussed that a little in the arc3 release thread. Ultimately I think it's a wasted effort to try and port the entire thing. Instead I think the best idea is probably to port the best features from anarki (the help system, the ability to define how to call tagged objects, various utility functions and macros) separately to arc3, a la CatDancer's "Sharing arc hacks", and publish them as a sort of stripped-down new anarki. I've done some preliminary work here; in particular, I've ported the help subsystem to arc3. I have a repository at http://github.com/rntz/arc, though I haven't uploaded the help changes to it just yet and it's very badly organized. I think I'll probably make a more concerted effort once arc3.tar has been finalized.
You are given the full literal contents of what appears in (foo ...) in args. You can do anything you want to with it, including searching for (unquote x) forms and replacing them with something else. (The reader expands ,x into (unquote x), so that's what you'll see when you look at args).
Now, what would you like this macro expression to expand into? Something like this?
(with (x1 a x2 b)
(ac-scheme (+ x1 (* x2 2))))
(yeah, this morning I'm trying out the name "ac-scheme" for "ac-tunnel" :-)
Now, let's say that expansion is what you want. So your next step is to write a program that takes
(+ (unquote a) (* (unquote b) 2))
and turns it into
(with (x1 a x2 b) (ac-scheme (+ x1 (* x2 2))))
this part has nothing to do with macros; you're just creating a list from another list.
arc> (myprogram '(+ ,a (* ,b 2)))
(with (x1 a x2 b) (ac-scheme (+ x1 (* x2 2))))
note that's a regular quote ' character there, not a backquote `. We're just feeding a regular old list to myprogram, and it's giving us a regular old list back.
OK! Got that program written? Now the macro is easy:
I'm aware of the process for making macros, however my attempts at writing the transformation itself have been rather unsuccessful.
What I originally tried was transforming
(mz (+ 3 ,a))
into
(mz (+ 3 __a))
But I couldn't get it to work. The problem is that I seem to need two levels of transformation and evaluation, but macros only give you one.
What is the reason that 'eval is so looked down upon? Isn't that pretty much what macros do themselves? How hard would it be to get an eval that could use the current local scope?
It should apply f to each node of the tree, preserving the tree structure. Seems pretty useful to me, if you're going to be doing much transformation of arbitrary list structures.
In retrospect, it's not much good for transforming the structure, but great for many other things.
For everything else, the other tree functions like trav, treewise, ontree, etc. might be more useful.
How would you make a more general purpose version of maptree that could encompass your transform function? It needs to be able to selectively modify some branches of the tree, and avoid calling map on them. Mine can't do that because it restricts you to atoms. Maybe if it took in two functions, one that operates on atoms, and one on lists, which can then optionally continue the mapping on a subnode. But then what has been gained? You're pretty much writing the whole pattern over again anyway.
Hmm. There seems to be a pattern here, but I can't see how to abstract it out, beyond the somewhat useful but restricted maptree posted above. Ideas?
'eval is not particularly looked down on, it's just rather inflexible. Given the way arc works, an 'eval that can use the current local scope is impossible - because arc compiles down into scheme, and an 'eval in arc compiles down to an 'eval in scheme, and an 'eval in scheme cannot use the current local scope. In order to get such an eval, you'd need to rewrite arc as an interpreter.
Edit: Unless mzscheme itself has some special 'eval with that functionality. I didn't think of that. I don't think it does, though.
parser.arc (at least, the parser lib I wrote; there are at least two others in anarki) uses coerce to get corresponding atoms from the token in string form. 'eval would probably have worked too. Otherwise, parser.arc just returns the forms it reads in, only transforming bracket syntax and string interpolations.
The ac-global-name function will prefix a symbol with an underline for you to create the global symbol name.
As for getting at the lexical scope, with eval or something else, that's up to the Scheme implementation. You'd need to go looking in the MzScheme documentation, or ask on the MzScheme user mailing list, to find out if there's some way to do that. Though why would you need that for this?
So, anyway, when you say you couldn't get "it" to work, what is the "it" that you're trying to do? I thought you were saying you didn't know how to transform "(mz (+ 3 ,a))" into "(mz (+ 3 __a))", but you say you know how to do that, so what is the it that's not working?
Actually what's funny is that I had no idea that people were using it! I mean, it's not like a web application where I can see how many how any hits it's getting, right? I just throw this code out there and it drifts away into the Internet, never to be see again. Then I suggest naming it something else and people say "no! no! Don't take away my mz!" :-) Oh. I guess some people found it useful! ^__^
I do feel stupid. However, this creates new bindings. From the code that shader posted, I think he doesn't want to create a new lexical binding. Is there some way of using destructuring for assignment?
The lisp-1 versus lisp-2 issue is an old one, as you note. I prefer lisp-1's, because they are conceptually cleaner - they don't make an arbitrary distinction between where to find values of a certain kind (functions) and where to find values of another kind (everything else). It reduces cognitive load not to have to think about "okay, is this going to be found in the function namespace or in the other-values namespace?".
More practically, as I tend towards a functional programming style, it's also a boon to me not to have to type #' or $' (or some other special syntax) whenever I want to use a function somewhere other than functional position. This may seem like a small issue, but arc itself is a fairly functional language; many of its core functions (eg: map, keep, rem, trues, zap, check, only, pos, find, sort, ...) are higher-order, so such a prefix would have noticeable cost in terms of characters typed.
I've been writing up a little something along similar lines. I hadn't thought using a commit-per-hack approach - it runs completely counter to the way I think about version control (which can briefly be summarized as "commit early, commit often"), so mostly what I'm writing is a howto on using `git-rebase` to handle development sanely (and an associated rant on why we should really just use darcs; if you haven't already tried darcs, I highly recommend it). I think in the long run, even for Arc, representing libraries directly in version control may get hairy. Git is not very good at dealing with subtly different histories, though I suppose restricting ourselves to one commit per patch/library/hack may help this somewhat. Ultimately it seems like a good idea, I'm just not sure present version control systems, even git and darcs, are up to the task.
Right, I'm using Git as a way to pull in and manage hack dependencies, instead of for version control.
You can first use Git to develop a library using Git as a version control system and then publish your library using Git in my approach. However you can't use the same commit for both: you can't take a commit that has version control type ancestors and publish it as a dependency type commit. Instead you have to create a new commit which has only prerequisite hacks as ancestors.
This is somewhat similar to creating a clean patch series: you don't lose your development history, but you don't expose the upstream recipients of your clean patches to the messy details of your development history either.
Thanks for the comment, I'll add a paragraph talking about this.
I don't know yet if Git is up to what I want it to do either, but it seems to be OK so far, if a bit awkward. (Which isn't surprising, since after all it was designed as a version control system).
Thirded. I'd very much like to see this get into arc3's final release. This makes iterating over a given table just like iterating over the corresponding association list.
This makes iterating over a given table just like iterating over the corresponding association list
That's a cool point!
If calling a list wasn't already doing a lookup by position, I might like a call on a cons to do an alref so that I could use x!foo to do a lookup by 'foo whether x was a table or an assoc list.
More generally, why would you want the pass-through-compiler feature to be named the same thing in different arc systems if the backend is different? Code that works when you're compiling to mzscheme is useless if you're compiling to CL; you'd rather have it warn you that it doesn't know what the hell you're talking about when it sees "mz" than have it (mis)interpret your mzscheme code as CL code.
I've already pushed arc3.tar to anarki's "official" branch and merged the changes into "stable". Merging them into the master branch may prove more difficult and tedious, but I think it can be done.
Hmm, as an interim step you could make a macro called "set" which you loaded after Arc and before Anarki. That way you could try out Anarki with arc3 and get things working before going on to do all the tedious renaming.
The trouble is, I wouldn't know where to start with testing anarki as a whole. There's just too many different parts, because anarki has so many things:
- Forks and compilers (arc2c, arc-f)
- Pet projects and examples (LightMakesRight, wiki-arc)
- Extensions to arc (help strings, function signatures, compilation)
- Bugfixes to arc (making 'atomic work even on exception throw)
I think I can probably update the latter three, but the former will just have to rely on whoever contributed them. Perhaps it's time for a new anarki - throw out the unmaintained cruft and try and separate changes to core arc functionality (bugfixes, extensions) from additions/libraries from standalone projects.
From my cursory look, pg has fixed many if not most of the core issues that anarki resolved. (ie cut fn not handling -1, providing a static directory for files to be published, added some basic math functions - sin cos etc..).
I would suggest starting a new branch with arc3 and if the libraries from anarki are still relevant then people will incrementally add them. This way were not integrating a bunch of code just because it's there - even though it's no longer useful.
+ just because you make them work with core arc3 files doesn't mean there will not be conflicts - as example the int function in the anarki math.arc library conflicts with news.arc only (as pg added an int function).
Some of the things anarki adds that are not in arc3 are tremendously useful.
For example, help strings and the 'help macro to access them, and similarly, the ability to call up any function or macro's source with 'src.
I do think the idea of integrating anarki code incrementally is probably the right way to do it. To this end, I've forked anarki's "official" branch (http://github.com/rntz/arc), and I've been applying CatDancer's "minimum-distance-from-arc" patching philosophy (http://catdancer.github.com/sharing-hacks.html). We'll see how many things from anarki I end up converting this way.
When you're done with you're patching process (I wouldn't mind helping) we should probably merge it back into nex3's copy, as his has public commit access.
One approach is to only port over things that you personally use and care about; and let other people port over things they care about. That's a pretty good filter for separating out the important from the unimportant.
Just giving it a preliminary look over, it seems like you changed 'set to 'assign. Any reason for this in particular, pg? It seems like it changes a lot of code, and as 'set is fairly common, it kind of goes against the philosophy of short names for common operators.
It's not so many uses that it's impossible to update. Many if not most of these uses could admittedly be replaced with '=, and arguably this was the correct thing to do in the first place. It just seems like an odd decision, and I'm wondering if there's any specific reason for it.
In my opinion "set" is a better name for what "assert" used to do, and I think "set" was available since it was being used for a low-level operation for which in user code "=" is a better and shorter name.
"I worry about releasing it, because I don't want there to be forces pushing the language to stop changing. Once you release something and people start to build stuff on top of it, you start to feel you shouldn't change things. So we're giving notice in advance that we're going to keep acting as if we were the only users. We'll change stuff without thinking about what it might break, and we won't even keep track of the changes."