Arc Forumnew | comments | leaders | submit | kinnard's commentslogin

This seems like something important deserving the community's support.

-----

4 points by kinnard 3343 days ago | link | parent | on: ASK: Axioms of Arc?

By the way: pg responded via email saying: "I'm not sure yet. Give me another year or so."

-----

1 point by kinnard 3348 days ago | link | parent | on: ASK: Axioms of Arc?

Very thorough. That's 19 though, and some of them don't seem very axiomatic.

-----

2 points by Pauan 3348 days ago | link

It's far more than 19.

13 types + 5 special forms + 1 global variable + 92 built-in functions.

And that's not including things such as first-class functions, lexical scope, first-class continuations, tail call elimination, or macros. I don't even know how to count those.

The fact is that practical programming languages need a lot of axioms. If you look at the list of built-in functions, they are all useful, and most of them are for I/O, which cannot be written in an axiomatic way.

I think it would be interesting to write an "eval" function in Arc, and see how few functions it needs in order to accomplish it. But I don't see much practical benefit to it.

-----

2 points by kinnard 3347 days ago | link

I thought that was the whole thing that pg was arguing/exploring. 'What's the least number of axioms necessary for a practical programming language?' And that arc was the product of that exercise.

"Of course, as soon as McCarthy's spec fell into the hands of hackers, all this theorizing was cut short. In Lisp 1.5, read and print were not written in Lisp. Given the hardware available at the time, there is no way they could have been. But things are different now. With present-day hardware you can continue till you have a runnable spec for a complete programming language. So that's what I've been doing.

The question I'm trying to answer at the moment is, what operators do you have to add to the original seven in order to be able to write an eval for a complete programming language? I'm not finished yet with this exercise, but so far I've been surprised by how few primitives you need to add to the core in order to make these things work. I think all you need to define new types is three new primitives (plus assignment and lexical scope). One of the new primitives replaces the original atom, so you still only end up with nine total."

-----

3 points by Pauan 3347 days ago | link

There are two questions here:

1) What is the least number of axioms needed for a practical language?

2) What is the least number of axioms needed to write an evaluator for the language in the language itself?

As I demonstrated, you need a lot of axioms to support practical programming, because practical programming involves I/O, threads, sockets, exceptions, etc.

Trying to find the smallest axioms necessary for I/O is a cool idea. But any I/O axioms will be intimately tied to the hardware, and the hardware is currently more C based than Lisp based. So the result won't be very elegant.

If you ignore practical programming and I/O, and only care about mathematical elegance, then McCarthy's original Lisp is already a quite good answer for question number 2.

Arc is quite a bit more elegant than most other programming languages, but at the end of the day it is still a practical language.

So my question to you is: what are you looking for?

-----

2 points by kinnard 3347 days ago | link

I'm wondering first, exactly what axioms pg settled on. And I'm also curious as you've described it, if the hardware were built for the language and rather than the language being built for the hardware, "what is the least number of axioms need for a practical language".

-----

3 points by Pauan 3347 days ago | link

I can't really answer that. Somebody would need to write an "eval" function in Arc. That would give you a pretty good starting point for figuring out how many axioms you need.

-----

2 points by kinnard 3350 days ago | link | parent | on: Arc implementation in C++

I found this to be very approachable, much more approachable than the scheme ac.scm, but that's probably because I'm new to/not used to reading lisp.

-----

2 points by kinnard 3350 days ago | link | parent | on: ASK: What is Lisp Enlightment?

That makes sense.

-----

2 points by kinnard 3351 days ago | link | parent | on: Lisp is more low-level than C

This makes me want to learn more level programming . . . but not while I'm learning lisp.

-----

2 points by kinnard 3352 days ago | link | parent | on: Anarki is now a Racket package

Glad to be of service.

-----

2 points by kinnard 3356 days ago | link | parent | on: π-calculus FAQ

TLDR: π-calculus is to concurrent programs as λ-calculus is to sequential programs.

-----


VS SML? https://github.com/arclanguage/anarki/blob/master/lib/sml.ar...

-----

3 points by rocketnia 3362 days ago | link

I can't speak for jazzdev, but I bet the code in sml.arc is just meant to be a more convenient way to generate XML from Arc.

  ; SXML
  (tagname (@ (attr "value") (attr2 "value2"))
    (tagname2)
    (tagname3 "data"))
  
  ; sml.arc's "old format"
  (tagname (@ attr "value" attr2 "value2")
    (tagname2)
    (tagname3 "data"))
  
  ; sml.arc's current example
  (tagname attr "value" attr2 "value2"
    (tagname2)
    (tagname3 "data"))
Meanwhile, Racket's batteries-included tools go their own way (http://docs.racket-lang.org/pollen/second-tutorial.html?q=x-...):

  ; X-expressions
  (tagname ((attr "value") (attr2 "value2"))
    (tagname2)
    (tagname3 "data"))
Several Racket libraries are tagged "sxml," but I wonder which formats they use exactly.

As for SXML, I think it's pretty nice that the SXML standard actually has well-defined ways to use doctypes, namespaces, processing instructions, and comments. That makes it more capable of representing an actual XML document. The spec is only a few pages long, and half of that is preamble, so it would be pretty simple to implement it faithfully.

All in all, I think I'd like to write code in a style like sml.arc, but then normalize it to something like SXML.

-----


Can non-hygienic macros be easily made hygienic in arc?

-----

3 points by rocketnia 3362 days ago | link

I think there is one way to consider Arc to be a language with good hygiene: We can program so that if we ever use a name as a global variable, we never use it as a local variable, and vice versa. As long as an Arc problem follows this rule and the usual (w/uniq ...) idiom, it won't encounter hygiene issues.

Paul Graham has this to say about hygiene in the tutorial:

  Some people worry unduly about this kind of bug.  It caused the
  Scheme committee to adopt a plan for "hygienic" macros that was
  probably a mistake.  It seems to me that the solution is not to
  encourage the noob illusion that macro calls are function calls.
  People writing macros need to remember that macros live in the land
  of names.  Naturally in the land of names you have to worry about
  using the wrong names, just as in the land of values you have to
  remember not to use the wrong values-- for example, not to use zero
  as a divisor.
However, he's only careful about one direction of variable capture. Here's one example from the tutorial where he doesn't mind capturing the names let, repeat, push, and rev:

  (mac n-of (n expr)
    (w/uniq ga
      `(let ,ga nil
         (repeat ,n (push ,expr ,ga))
         (rev ,ga))))
I think he gets away with this because he's following that rule I mentioned, keeping a careful separation between the names of locals and globals.

It seems we don't particularly follow that rule here on the Arc Forum. For instance, a few of us have agreed that a certain behavior in Arc 3.1 is a bug: When we make a function call to a local variable, we don't want a global macro of the same name to take effect, which is what happens in Arc 3.1. If we were keeping locals and globals separate, we wouldn't even encounter this problem.

Which means that if we want to write macros that are hygienic, we can't write them in quite the way we see in arc.arc or the tutorial. If we're dedicated to hygiene, we might even want to rewrite arc.arc to fix its hygiene issues... but that's practically the whole language, so it effectively starts to be a new language project. The Anarki arc2.hygiene branch, Penknife, ar, Semi-Arc, and Nulan are several examples of Arc-based or Arc-inspired projects that pursued some kind of hygiene.

If we don't mind the lack of hygiene in arc.arc but only care about proper hygiene for our own new macros, it is possible to be diligent about hygiene in plain Arc 3.1 or Anarki:

  (mac n-of (n expr)
    (w/uniq ga
      (rep.let ga nil
         (rep.repeat n (rep.push expr ga))
         `(',rev ,ga))))
Coding this way looks a little arcane and loses some of Arc's brevity, but one of the techniques here is to embed a the rev function into the syntax as a first-class value. By putting most of the macro implementation into an embedded function, it can become rather familiar-looking again:

  (mac n-of (n expr)
    `( ',(fn (n expr)
             (let a nil
               (repeat n (push (expr) a))
               rev.a))
       ,n
       (fn () ,expr)))
Here's a macro that makes this even more convenient:

  (mac qq-with args
    (let (body . rev-bindings) rev.args
      (let (vars vals) (apply map list (pair rev.rev-bindings))
        `(',list `',(fn ,vars ,body) ,@vals))))
  
  (mac n-of (n expr)
    (qq-with n n expr `(fn () ,expr)
      (let a nil
        (repeat n (push (expr) a))
        rev.a)))
I think if I programmed much in Arc again, I'd start by defining that macro or something like it. :)

As it is, right now I'm just settling into a macro system I designed. I don't have convenient gensym side effects like Arc does, and I want the generated code to be serializable (not containing opaque first-class functions), so my options are limited. I still can and do implement macros, but the implementation of each macro is pretty verbose.

-----

1 point by kinnard 3352 days ago | link

I'm still learning lisp and haven't fully wrapped my head around macros. So the hygienic vs unhygienic debate is still more or less opaque to me :D

-----

5 points by Pauan 3358 days ago | link

With the current implementation of Arc, it is possible but rather tricky to write hygienic macros.

However, there is a very simple change that can be made to the Arc compiler which would make hygienic macros easy to write.

The Arc compiler would have a big hash table which maps from global symbols to gensyms.

Whenever you define a global variable, it will create a new gensym and store it in the hash table.

When using the quasiquote syntax, it will lookup the variable in the hash table and will use the gensym rather than the symbol.

As an example, if you have this Arc program:

  (= foo 1)

  (mac bar ()
    `(+ foo 2))
The Arc compiler would expand it to this code instead:

  (= #<foo:1> 1)

  (mac #<bar:1> ()
    `(#<+:1> #<foo:1> 2))
In this case, #<foo:1>, #<+:1>, and #<bar:1> are gensyms, rather than ordinary symbols.

Now the macro bar will always expand to the correct global variable foo, and therefore it is 100% hygienic.

If you want to intentionally break hygiene, you can simply do this:

  (mac bar ()
    `(+ ,'foo 2))
The above code uses "," to insert the symbol "foo", rather than the gensym for foo.

This change is very easy to make in the Arc compiler, and it only requires a few minor changes to the language.

-----

1 point by akkartik 3363 days ago | link

No, they're conflicting philosophies.

-----

More