Er, I'll assume you're talking about the fact that Kernel omits quote from the core language, and instead leaves it up to programmers to implement their own nonstandard quote if they need it.
($define $q
($vau (result) env
result))
Even so, I'm not sure what having quote has to do with anything. Your examples don't use quote except to get first-class access to symbols, which you could already get access to as the unevaluated arguments of an fexpr call.
---
"so it can't use apply with operatives, and so its fexprs are less powerful."
I can understand if you've got the @ syntax on your mind and you'd like to squeeze a lot of value out of it, the way Arc squeezes so much out of putting things in functional position. However, whatever power you get here, I don't think it makes up for the ways you undermine your language, as I describe in my other comment.
As we continue to discuss this, it might help if we look at things in terms of John Shutt's own thorough definitions of expressive and abstractive power (http://lambda-the-ultimate.org/node/4345#comment-66918). A formal theory can't tell us how to formalize the informal things we care about, but if we do manage to use it well, we can skip ahead to more profound conclusions. This theory in particular has gotta be extremely relevant to Kernel, since it's by the same person. :-p
I haven't looked at your link yet, but I want to clarify my comment first so that we can attack it together after I'm updated. ^_^
My solution relies on unquote and therefore on backquote. I don't recall Kernel mentioning them; scheme seems to ignore them in general. But let's assume that they are implementable just like quote. When I say "quote" I mean this holy trinity :)
I know Kernel doesn't prevent quote, but it discourages it. Even if you got apply working with backquoted macros in Kernel, it wouldn't be very helpful if most macros were backquote-less as a matter of course. This seems like a limitation of the philosophy.
More strongly, I want to argue that having syntax for quote/backquote/unquote is valuable. In wart all symbols are overrideable[1]. It uses punctuation for quote/backquote/unquote/splice to highlight that they are different from symbols, more fundamental to the programming model. Supporting apply for macros has made them even more so, even more fundamentally entangled together and baked into the interpreter.
[1] The one exception is fn. Perhaps I should make it λ? Nah, that doesn't solve the problem. Hmm, the only punctuation character wart hasn't already put to use is #.. :D
"My solution relies on unquote and therefore on backquote."
Oh, right.
---
"More strongly, I want to argue that having syntax for quote/backquote/unquote is valuable."
I don't think that's as expressive as infix syntax. With the right kind of a.b syntax, we could write `(a b ,c) as qq.(a b uq.c), trading in some readability for the flexibility to define our own variants.[1] Would you still want to have dedicated quasiquotation syntax then?
(Even I might answer yes sometimes. The staged fexpr system I describe at http://arclanguage.org/item?id=15868 uses unquote syntax as a way to compute during a previous stage of the command processor.)
[1] Penknife does something like this, but the use of structured string manipulation instead of s-expressions forces it to use a string-like escaping mechanism for unquote: qq.[a b \,c]
Doesn't this feature mean I have to use quasiquotation to build macro results if I want this behavior? I'm guessing if I try to use any function as I'm building macro results, it'll strip '' on the way into the function. This limits me to fexprs that don't use functions this way. And if I use a typical macro, that macro will probably be prepared for splicing itself, which means it too will intentionally strip '' on the way in.
Now that we're disarmed of functions and of splice-friendly macros (which probably encompasses almost the entire standard library!), we have to see if we can make do with whatever we have left. I don't think that's very much in the spirit of "first-class."
wart> (def helper(a b) `(cons ,a ,b))
wart> (mac foo(a b) (helper a b))
wart> (foo 1 '(2 3))
(1 2 3)
wart> (foo @'(1 (2 3)))
008eval.cc:79 calling macros with splice can have subtle effects (http://arclanguage.org/item?id=15659)
005types.cc:263 can't coerce number 2 to function
Eep! You're right, this is a fairly common use case.
The good news is that wart's warning system has held up. If it can't handle it it throws that warning.
I still emit the warning, because examples like this fail:
wart> (def helper(a b) `(cons ,a ,b))
wart> (mac foo args (helper @args))
wart> (foo @'(1 (2 3)))
008eval.cc:79 calling macros with splice can have subtle effects (http://arclanguage.org/item?id=15659)
005types.cc:263 can't coerce number 2 to function
wart> (mac foo(a b) `(cons ,a ,b))
wart> (mac bar(a b) (prn `(cons 3 ,@(foo a b)))) ; prn for debugging
wart> ((fn(x) (bar x x)) 'abc)
(cons 3 x . x)
004cell.cc:158 car of non-cons: x
004cell.cc:158 car of non-cons: x
(3 . abc)
My bar example is poorly constructed; besides that I think you're right.
wart> (mac foo(a b) `(cons ,a ,b))
wart> (mac bar(a b) `(cons 3 ,(foo a b)))
wart> ((fn(x) (bar x x)) 'abc)
005types.cc:263 can't coerce symbol abc to function
There was a typo in grandparent, so let me summarize the correct versions:
wart> (mac foo(a b) `(cons ,a ,b))
wart> (mac bar(a b) `(cons 3 ,@(foo a b)))
wart> ((fn(x) (bar x x)) @'(abc))
(3 . abc)
wart> (mac foo(a b) `(cons ,a ,b))
wart> (mac bar(a b) `(cons 3 ,(foo a b)))
wart> ((fn(x) (bar x x)) @'(abc))
005types.cc:263 can't coerce symbol abc to function ; no change
I think you're asking what happens to (''a b c). Hmm, I don't translate that to ''(a b c). It seems to be acting like (a b c). Does that seem right?
---
Another potential concern: I'm using a single boolean to track whether we encounter a '', and I reset it before unquote's eval and check it after. I think it might need to be a stack of booleans to handle nested expressions, but I've not been able to come up with a failing test case.
" '' is an internal detail. The reader provides no way to type it in. If you ever see it printed at the REPL, that's a bug."
If unquote adds a '', then `,'foo should return ''foo, right? Then 'write should write ''foo at the REPL.
In order to weasel out of anything that stripped '' from the arguments to a function, I tried putting `, around the whole command, in the hopes that it would somehow manipulate the state of the don't-strip-'' flag(s) for the duration of the command.
In any case, there's no reason foo should be called, is there? O_o
In other news, this might be an easy test case for the scope of the don't-strip-'' flag. If your implementation sets it to true on the way in and false on the way out, then it'll become false on the way out of the inner `, , rather than recovering its previous value of true.
"If unquote adds a '', then `,'foo should return ''foo, right?"
Unquote doesn't add '', @ does. Perhaps that changes your example?
"In any case, there's no reason foo should be called, is there? O_o"
:) Yeah that's a bug with my paren inference; it was implicitly wrapping the expression in parens. I'd never seen backquote-comma before. Here's a temporary workaround:
wart> (list `,(write `,'foo))
foo(foo) ; ignore the (foo) -- it's the return value
I'm guessing you still have the JRE version in your path, even if you also have the SDK. I'm always wrestling with the automatic JRE updater changing my path to point to the JRE version. :-p
I'd look at your PATH and JAVA_HOME environment variables. If they refer to a JRE directory, change that to the JDK directory. Then start a new shell and see if "java -version" has changed.
In the meantime, if you manually invoke the full path to your JDK's java.exe with the -version option, you can see if that one's even a server VM to begin with. :-p If it isn't, maybe try "C:\...\java.exe -server -version" to be sure.
For the record, this doesn't have anything to do with Racket. This is atstrings, a feature of Arc.
Atstrings is off by default in plain Arc 3.1, but it's activated by the line (declare 'atstrings t), and news.arc includes that line for its own purposes.
Yes, part of what FredBrach did with scopes was eerily similar to what I was thinking about at the time. ^_^ I didn't talk about it much in response, but I did consider it promising.
I was also thinking about this topic a couple of days before http://arclanguage.org/item?id=15831, where I wrote "Suppose there were a special form (varscope <var> <...body...>) which scoped (<var> <name> <val>) as a special form in the body, which both defines and assigns to a variable and returns the new value. One can say (var foo foo) to define a variable without modifying it."
I think this kind of generalized scope jives well with a linear system. Linearity is about assuming every value is produced once and consumed once by default. Everyday lambda calculus lets you introduce a variable at the acquisition site and then (nonlinearly) use it any number of times in the body. For the reverse of that, when we're dealing with values we use once but define in any number of places (e.g. for set accumulation or nondeterministic choice), maybe it can make more sense to "introduce" the variable at the usage site.
My blog post's "Aside" expressions cater to many-to-many, zero-to-many, many-to-zero, and zero-to-zero operations, where there's no obvious definition or usage site to single out for the variable introduction.
---
"I haven't wrapped my head around it all (are linear variables different from linear types?)."
Hmm, when I said "linear variable," I just meant a variable with a linear value or a linear type. This kind of variable appears in the code at exactly one definition site and one usage site, unless the code uses conditionals or something.[1]
If you're in the midst of changing your question to "are linear values different from linear types?" the answer is no, I'm talking about the same concept. :) However, it is possible to have dynamically checked linear values in an untyped language. Likewise, I bet it's even possible to have linear typing without linear values, in the sense of fostering a programming subculture which considers the types important and the values unimportant.
If you're in the midst of changing your question again, no, I'm not sure why it's called "linear." :-p But in order to rationalize the name myself, I look at the life story of a single value. For an intuitionistic value, this timeline can split apart across multiple parts of the program at once. A linear value can't typically branch, merge, begin, or end, unless it does so by transferring its content into new linear values. This makes its life story linear.
[1] Conditionals don't even exist in the expression language I described in that blog post, and I expect that'll make it less helpful as a language but easier to implement. :/ I haven't come up with a way to add conditionals yet.
I would say "callback hell" and CPS are pretty much synonymous. And https://github.com/jashkenas/coffee-script/wiki/List-of-lang... has a section for "Synchronous to Asynchronous JavaScript Compilers (CPS)." My ChoppaScript currently has support for many textual macros that alleviate this issue, not that I use any of them. :-p
I actually prefer JS to most of these CPS-transforming variants of JS. I like having asynchrony be independent from imperative control flow, with no awkward questions about how "finally" and nonlocal exits are supposed to work.
Much like Arc, it has certain abstraction leaks it doesn't close, without actually embracing the JavaScript platform that's leaking through:
"You'll notice in the last example that we can call native functions on objects. This is a funny result from the fact that Scheme identifiers allow "." in them, and Outlet simply copies the name into the javascript code. Javascript then evaluates it like normal. I don't intend build anything on this though. If you want to write javascript, write javascript."
However, like Arc, it has a rather concise implementation.
Oh, now that we're talking about it, I seem to remember there's some kind of issue where Jarc allows regular function calls on symbols but 'apply on a symbol doesn't work. So how about (apply 'getTime (list:new java.util.Date))?
I guess there's an issue here because getTime is not a "regular" arc function, but a Java method and the mapping from names to methods is not "hooked" in map implementation (I guess :) ...
Anyway the following works:
Jarc> (map (fn (_) (getTime _)) (list (new java.util.Date)))
More recently, jazzdev released a version of Jarc that implemented Rainbow's style of JVM access in addition to the Jarc style (http://arclanguage.org/item?id=12684). I cover a lot of corner cases in jvm.arc using reflection, and some of those could probably be implemented in a more direct style now.
One thing to note: Jarc and Rainbow each have their own policies for automatically converting between Arc values and java.util.Maps and such. This is convenient in practice, but it may make some corner-case things impossible without writing custom code in another JVM language like Java. For instance, if a single utility (say, a JSON parser) can return either java.lang.Boolean.FALSE or null, Arc will probably see nil in both cases.
One thing that's been keeping me in JavaScript is the desire to be able to develop with only a browser and client-side files. Many languages compile to JS, but not quite as many of those compilers run in JS themselves. Here's one. :)