I've just released Jarc 13 which addresses most of these issues.
- quasiquote
I've learned that quasiquote is quite a deep rabbit hole! Jarc 13
handles quasiquote much better. I wrote a Java-based qq-expand
that is simpler than qq.arc. It doesn't handle dotted lists and
it doesn't do any optimizing, but it does handled nested quasiquotes
properly. And qq.arc is now included in Jarc 13. So if you want it,
do (use 'qq).
In Jarc 13, quasiquote is now a macro instead of a special
form. This makes it much easier for the interpreter and
compiler to share the code for handling it. Since neither
has to do any special handling for it. I was able to
rip out some code from Closure and from compile.arc. Always
like it when I can do that!
- split, cut and compiled functions with optional params
Fixed. Jaclyn now handles dotted destructed args too.
- strings
Jarc 13 includes strings.arc, code.arc and pprint.arc when
it starts.
- eval
Unrelated to this thread, but when I "fixed" eval to
ignore the lexical environment it broke the pr-tag macro
in jtml.arc. Since pr-tag is a macro it didn't need
to call eval anyway, so I just rewrote it.
- Changing the definition of a function after it's defined
This scenario is still problematic:
(def foo () `(1))
(= ((foo) 0) 2)
(foo)
While I agree with the hackability of Arc, I think it's
perhaps a problem that you can change the definition of
a function after it's defined. You are essentially
reaching into foo and changing the cons inside it.
The behavior of this is dependent on how you
optimize qq-expand.
Arc 3.1 yeilds (2) for the above code.
Jarc 13 yields (1) for the above code.
Jarc 13 with (use 'qq) yields (2).
Jarc 13 with (use 'qq) (toggle-optimize) yields (1)
As CatDancer pointed out in http://arclanguage.org/item?id=9962
there are multiple ways to expand quasiquote that all
result in the same expression when eval'd.
Unless there's a precise definition for how `(1) should
be expanded, I don't see how we can define what the output of
the above code should be.
While I agree with the hackability of Arc, I think it's perhaps a problem that you can change the definition of a function after it's defined. You are essentially reaching into foo and changing the cons inside it.
Yeah, I don't like this feature either. It makes me a bit paranoid about using quasiquote at all sometimes, since I might be unintentionally opening up parts of my macro code to being modified. I don't let that affect my coding style--I just don't usually mutate macro-expansions and stuff--but it's sort of a pet peeve.
I'm sure there's a pg post somewhere around here about it being a bit of effort to get things to work this way, but I can't find it.
Unless there's a precise definition for how `(1) should be expanded...
I think the obvious one is '(1), which is to say, replacing the 'quasiquote symbol with 'quote. If 'quasiquote is taken out of the core, then 'quote is really the only fundamental form left that you can "reach into" this way. Furthermore, Jarc 12 already worked for '(1):
If (use 'qq) gives you something that yields (2) and it's a macro, then it probably expands `(1) into '(1), and so the work is probably done for you.
This probably also means that your optimizer stops (quote (1)) from returning a reference to a single mutable (1) and makes it cons up a whole new (1) instead. If that's the case, then it isn't even much of an optimization. ^_^ I wonder if the compiled JVM bytecode can contain a sort of quote-closure field for each 'quote form, so that the compiled Java object/class can be initialized with a direct reference to a subtree of foo's syntax.
On the other hand, if this is something you don't want to fix, I'll agree with you there. :-p
Okay, I've brought Lathe's buggy-jarc branch up-to-date with Jarc 13. The code I had for Jarc 12 already worked, so I took the opportunity to remove all the unnecessary workarounds that were still in there. It sure is an awesome relief having the diff with the master branch get so small, but there are still two bugs in my way right now:
- Jarc's metafns aren't metafns. This has been a problem for quite a while, but usually I phrase it in terms of (my:foo ...) not working, since that's the way my namespace system encourages macro calls to look.
Each of the following should result in t rather than trying to apply 1 as a function:
(iso ((compose do) '(1 2 3)) '(1 2 3))
(iso ((andf do) '(1 2 3)) '(1 2 3))
For compatibility, this should work even if someone rebinds 'compose, 'andf, or some other metafn name to a completely different value. Metafn forms are identified purely by name in official Arc.
- Jarc's a&b ssyntax no longer works. The result of (ssexpand 'a&b) is (andf a b) as it should be, and (andf a b) does work correctly in most cases (the above bug being an exception), but for some reason using a&b in the code itself causes an error. It tries to look up the symbol a&b.
This isn't particular to quasiquote. You can reach into any function that returns a literal cons or string.
If this is something you don't want to fix, I'll agree with you there
Yeah, I'm disinclined to try to emulate Arc precisely in this regard because it appears to be an arbitrary artifact of how Arc does quasiquote expansion, and not a defined feature.
Yeah, I'm disinclined to try to emulate Arc precisely in this regard because it appears to be an arbitrary artifact of how Arc does quasiquote expansion, and not a defined feature.
I think the only thing going on here is quotation. Generally, quoted things work like pointers (see http://arclanguage.org/item?id=10248). Because you can still do
arc> (def foo () (cons 1 nil)) ; note: cons creates new data each call
*** redefining foo
#<procedure: foo>
arc> (= ((foo) 0) 2)
2
arc> (foo)
(1)
Then, the reason the quasiquoted thing gets weird results with the qq.arc I ported is that optimizing `(1) manages to switch between always consing new data with (list '1) and trying to reduce runtime consing with '(1).
I'm not (terribly) surprised that the ability to modify literals was intentional. Thanks for that link. I'm still wondering if `(1) expanding to '(1) is intentional or not.
Clearly '(foo) is a literal and `(foo ,bar) is not a literal, right?
I guess it's not a huge stretch to say that `(foo) is a literal. Unfortunately, qq-expand doesn't always expand `(...) with no commas into '(...)
I'm still wondering if `(1) expanding to '(1) is intentional or not.
A quasiquote expander can expand `(1) into '(1) or (list 1), or even (join '(1) ' nil), which is what Bawden's simple, correct, but inefficient quasiquote expander does.
The expander may choose '(1) as being more efficient than (list 1), but isn't required to do so to be a quasiquote expander.
Since it's an optimization, I wouldn't write code that relies on a particular instance of `(1) evaluating to the same list every time, that's just an accidental result of the optimization. Instead, use a plain quote for that.
There. Just updated qq.arc, removing almost 100 lines of cruft in the process. It still passes all the old tests, and (with any luck) is much more pleasant to work with.
This isn't particular to quasiquote. You can reach into any function that returns a literal cons or string.
I know, hence why I talked about 'quote. On principle, I'm equally paranoid about 'quote, 'quasiquote, and literal strings, but I've never mutated strings in my own projects, and I almost exclusively quasiquote my "escaping" cons cells rather than quoting them, so I just glossed over those facets of my paranoia. :-p
it appears to be an arbitrary artifact of how Arc does quasiquote expansion, and not a defined feature.
Like I said, I think there's a relevant pg comment around here somewhere. I've searched some more, but I still can't find it. Maybe it was just my imagination. ^_^;
Oh, wait, fallintothis's post links to it.
Arrgh, it would help if Google weren't so inconsistent. It's a result for ("behavior can be quite useful in some contexts"), but it doesn't show up in the results for ("behavior can be quite useful in some"), and ("can be quite useful in some contexts") has no results at all. Of course, observing this property and posting about it will no doubt change the search results. XD