Arc Forumnew | comments | leaders | submit | rocketnia's commentslogin
2 points by rocketnia 5005 days ago | link | parent | on: Apply for macros: a solution

"without quote, Kernel can't use this solution,"

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

-----

1 point by akkartik 5005 days ago | link

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

-----

2 points by rocketnia 5002 days ago | link

"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]

-----

1 point by akkartik 5002 days ago | link

Yeah, that's really interesting.

But is it convincing that existing lisp syntax is more valuable than Kernel's approach of no syntax?

-----

1 point by rocketnia 5002 days ago | link

"But is it convincing that existing lisp syntax is more valuable than Kernel's approach of no syntax?"

Well, I'd say so, yeah. I'd say `foo is a less helpful syntax than a.b, but still helpful.

-----

1 point by akkartik 5002 days ago | link

Thanks. I'm going to keep the qq.() idea up my sleeve. It's totally consistent with my idea that symbols should be overrideable and syntax should not.

-----

2 points by rocketnia 5005 days ago | link | parent | on: Apply for macros: a solution

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."

-----

1 point by akkartik 5005 days ago | link

Ah, I figured out what you were getting at:

  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.

-----

1 point by akkartik 4993 days ago | link

macros-calling-functions-generating-backquoted-lists now works!

The cost is a special variant of eval to call inside macros: http://github.com/akkartik/wart/commit/e3124e9559#diff-3

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

-----

1 point by akkartik 5005 days ago | link

I'm not sure I understand you, so let me show a few examples:

  ; function calls inside macros?
  wart> (def f(x) x)
  wart> (mac foo(a b) `(cons ,a ,f.b))
  wart> (foo @'(1 (2 3)))
  (1 2 3)

  ; splice friendly macros?
  wart> (foo @(foo @'(1 ((2 3)))))
  (1 2 3)

  ; splice friendly macros?
  wart> (mac bar(a b) `(cons 3 ,@(foo a b)))
  wart> (bar @'(1 (2 3)))
  (3 . 1)
Do these address any concerns?

-----

1 point by rocketnia 5005 days ago | link

It does tell me I don't understand your system yet, at least. :-p

So if x is a variable containing ''abc, when we say (bar x x) we wind up evaluating (cons 3 ''(cons ''x ''x))?

When we evaluate (cons ''x ''x), it strips off the '' to get (cons foo foo), and then we end up with (''abc . ''abc)?

Then, altogether, we end up with a result of (3 . (''abc . ''abc)), which appears at the REPL complete with ''?

Let me know if I'm getting anything wrong.

-----

1 point by akkartik 5005 days ago | link

Almost:

  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.

-----

1 point by rocketnia 5002 days ago | link

Oh, I see. Would you mind showing me what happens with (mac bar(a b) `(cons 3 ,(foo a b)))?

-----

1 point by akkartik 5002 days ago | link

  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.

http://github.com/akkartik/wart/blob/6d5d5a845c/007scope.cc#...

-----

1 point by akkartik 5002 days ago | link

Ah, I answered my own question. It turns out this doesn't work:

  (all present? '((1) (2 4 6)))
if you define all as:

  def all(f seq)
    (and @(map f seq))
For precisely this reason.

(present? is a synonym for idfn.)

-----

1 point by rocketnia 5002 days ago | link

Hmm, what happens when you say `,(write `,'foo)? ^_^

-----

1 point by akkartik 5002 days ago | link

  wart> `,(write `,'foo)
  foo005types.cc:263 can't coerce symbol foo to function
Is that what you expect? I'm not sure what you're trying.

-----

1 point by rocketnia 5001 days ago | link

Something bugs me about this claim:

" '' 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.

-----

1 point by akkartik 4992 days ago | link

"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
Update: fixed (http://github.com/akkartik/wart/commit/70cfb18504)

  wart> `,(write `,'foo)
  foofoo

-----

1 point by akkartik 5001 days ago | link

Hmm, I haven't fully digested this, but I do have a passing test on nested unquote: http://github.com/akkartik/wart/blob/a5a9f2ffcd/030.test#L35

-----

1 point by rocketnia 5006 days ago | link | parent | on: Rainbox Aborting

What does "java -version" tell you?

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

-----

1 point by jsgrahamus 5006 days ago | link

  C:\Users\Steve>java -version
  java version "1.7.0_04"
  Java(TM) SE Runtime Environment (build 1.7.0_04-b22)
  Java HotSpot(TM) Client VM (build 23.0-b21, mixed mode, sharing)

  C:\Users\Steve>

-----

1 point by rocketnia 5006 days ago | link

Yeah, that's the JRE....

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.

-----

1 point by jsgrahamus 5005 days ago | link

Thanks, Rocketnia. That did the trick.

Steve

-----


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.

-----

2 points by rocketnia 5012 days ago | link | parent | on: Generalizing expressions as dataflow

Whoops, I guess I didn't reply to this.

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.

Instead I think the notable part of this article is that they've implemented Outlet, a (mostly?) self-compiling Scheme dialect with a debugger. More general info here: http://jlongster.com/2012/01/04/outlet-my-lisp-to-javascript...

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.

-----

2 points by rocketnia 5022 days ago | link | parent | on: Running Java in Arc

I think that quote is just a typo. Try (map 'getTime (list (new java.util.Date))).

-----

1 point by jsgrahamus 5022 days ago | link

  Jarc> (map 'getTime (list (new java.util.Date))).
  (stdin):2: Error: Can't apply function: getTime

  0:      (map (quote getTime) (list (new java.util.Date)))
  DEBUG 0: Unknown command: .
  0:      (map (quote getTime) (list (new java.util.Date)))
  DEBUG 0: r 13
  13

  ---

  Jarc> (map 'getTime (list (new java.util.Date)))
  (stdin):4: Error: Can't apply function: getTime

  0:      (map (quote getTime) (list (new java.util.Date)))
  DEBUG 0: r 13
  13

  ---

  Jarc> (map 'getTime (new java.util.Date))
  (stdin):6: Error: Type-error:
  Tue May 15 12:02:40 MDT 2012 is not of type LIST

  0:      (map (quote getTime) (new java.util.Date))
  DEBUG 0: r 13
  13

  ---

  Jarc>

-----

1 point by rocketnia 5022 days ago | link

First error: You included a spurious . at the end. (You caught this.)

Third error: The sequence you passed to 'map was a java.util.Date, not a string or list like 'map expects.

Second error: Now that seems weird.

I can't help much at this time of day, but what happens when you say "(getTime:new java.util.Date)" and "(idfn!getTime:new java.util.Date)"?

-----

1 point by jsgrahamus 5022 days ago | link

  Jarc> (getTime:new java.util.Date)
  1337107797339

  Jarc> (idfn!getTime:new java.util.Date)
  1337107814529

  Jarc>
Thanks.

-----

1 point by rocketnia 5022 days ago | link

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))?

-----

1 point by jsgrahamus 5022 days ago | link

  Jarc> (apply 'getTime (list:new java.util.Date))
  1337113306091
  Jarc>

-----

2 points by varbanov 5021 days ago | link

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)))

(1337177450156)

-----

2 points by rocketnia 5022 days ago | link | parent | on: Running Java in Arc

Some ways to call Java from Rainbow are listed here: http://arclanguage.org/item?id=8819

I think the best way to get up to speed with Rainbow is to see it in action (https://github.com/conanite/rainbow/blob/master/src/arc/rain...) and to look at exactly what the selection of JVM-related primitives is (https://github.com/conanite/rainbow/tree/master/src/java/rai...).

A while back, I made a library, jvm.arc, that I find slightly more convenient to use for accessing JVM stuff from Arc, regardless of whether I'm using Rainbow or Jarc (http://rocketnia.wordpress.com/2010/06/01/lathes-arc-to-impl...).

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.

-----

1 point by jsgrahamus 5021 days ago | link

"I think the best way to get up to speed with Rainbow is to see it in action (https://github.com/conanite/rainbow/blob/master/src/arc/rain...)

So I looked at swing.arc and tried copying and pasting it into Jarc:

  Jarc> (java-imports java
    (lang Integer Float)
    (awt Font event.KeyListener))

  (stdin):1: Error: Symbol 'java' has no value

  0:      java
  DEBUG 0:
Does something need to be loaded before executing this?

Thanks, Steve

-----

1 point by varbanov 5020 days ago | link

java-imports is Rainbow specific construct. Jarc doesn't have such function. I guess Jarc doesn't have imports :)

varbanov

-----

2 points by rocketnia 5022 days ago | link | parent | on: SS-Lisp: run Lisp in your browser

Nice comeback to my post about SMLtoJs. :-p

-----

1 point by rocketnia 5029 days ago | link | parent | on: SML compiler in the browser

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. :)

-----

More