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

With power comes responsibility. Java sees programmers as irresponsible, so it gives them no power. Arc/Lisp gives us power, including unhygienic macros, and leaves it to us to use them responsibly. /Can/ you contrive an example that breaks things? Yes, but that is no surprise, PG said Arc would do that. What would be more compelling is an example of real-world coding that ran afoul of capture. In CL, btw, I do not think it is the extra namespaces that help us, I think it is that ghastly warning we get when we try to redefine a bit of the language.

-----

7 points by andreuri2000 6744 days ago | link

Hygiene does not diminish power. Various hygienic macro systems exist that are at least as powerful as defmacro. An extremely simple one is explicit renaming, which allows simple controlled capture. Syntax-case (see R6RS) is strictly more powerful than MAC (in the sense that MAC can be expressed in terms of syntax-case but not vice versa). Explicit renmaing and syntax-case have the power to respect lexical scoping, while no amount of tricks can stop MAC from breaking lexical scoping. Syntax-case also allows controlled capture, indeed much finer control over capture than MAC does. So an argument based on power would in fact favor hygienic macro systems over MAC.

-----

1 point by kennytilton 6741 days ago | link

But variable capture is just a hobgoblin to frighten the kiddies, nothing that ever Actually Happens(tm) to those using unhygienic macros in anger. Meanwhile, syntax-case may theoretically be able to express MAC, but the reality is that it is a PITA to program with. The power of syntax-case is theoretical, the power of MAC is in practice. When I have to write some code, I'll take the latter.

-----

2 points by andreuri2000 6739 days ago | link

It is not "downward" variable capture that bothers me. I can insert gensyms as well as anybody else to avoid that. It is lexical scoping, as in

  (def sort (sequence <)
    ----
    (some-macro-use)
    ---
    )
I can never be sure that this is correct unless I go and read the definitions of (some-macro-use) and all the macros that it may in turn depend on, to make sure that they do not depend on, say, the standard binding of < and perhaps some toplevel binding of "sequence". And I have to do this for /every/ local variable binding surrounding every macro use in the whole program. Also, I had better be sure that no-one will go and change the definition of some-macro-use, or any of the macros on which it depends, at any time to depend on the toplevel <, a toplevel "sequence", or /any/ other lcoal variable that may surround /any/ use of some-macro-call anywhere in the code.

The fact that you have not run into this problem shows amazing discipline, and may have something to do with CL not being a Lisp-1. I have no such discipline, and prefer having the language take care of lexical scoping for me. But then, I don't plan on using Arc, so feel free to ignore this.

-----

2 points by kennytilton 6739 days ago | link

It is not clear that the nightmare outlined above applies to actual programming. I am a little weak on my Lisp-1, but IIUC the above changes < to be whatever comparison operator got passed to sort, so the author of the above sort should be fired for breaking <. As Arc matures it might not hurt for the compiler to issue a warning over such sabotage, which is really what it is so I am not sure why we are discussing it as a Real World Problem.

As for "sequence" and someone depending on some /other/ higher level binding, ie, it is capturing the variable sequence by design, (a) intentional variable capture is as rare as it is powerful and the premise is that one has a suite of cooperating macros that work together to bind and then use the rare variable designated for capture, so one is not invoking one of these macros in isolation unaware of how it works or what it captures. A good example from my code at one time was the binding and capture of SELF, being used in some OO wizardry to stand for the "instance at hand" a la smalltalk. If I was rebinding self outside the cooperating suite of macros (which I did, rarely) it was because I had coded myself into a corner, but I knew damn well what I was doing and why I was doing it and I still crossed my fingers.

btw, a trick the CL crowd uses for lexical vs dynamic binding (the latter being an opportunity for a similar kind of confusion as the one you fear) is simply to name dynamic variables +like-this+. (not really, we use asterisks, but this forum would just show like-this if I bracket it with asterisks.) That simple convention solves the whole problem, as long as we fire anyone naming a scratch variable that way. :)

-----

2 points by hakk 6745 days ago | link

Going further, many CL implementations also come with a package locking mechanism.

-----

1 point by kennytilton 6746 days ago | link | parent | on: and operator

and has to check them all and returns the last if all are non-nil. The OR operator would stop at the first non-nil (cuz then it's done) and return that.

-----

1 point by kennytilton 6746 days ago | link

I should add that you asked why it did not work as you expected, without explaining why you expected what you did so I am flailing here, but hey, it was it is. They could have returned the first of them or all of them or a boring t -- I think it was just a bit of hacker cleverness and a good guess (IMO) of what to use as a true return value.

-----

1 point by kennytilton 6746 days ago | link | parent | on: Self referencing lambda

btw, here is while (from arc.arc):

(mac while (test . body) (w/uniq (gf gp) `((rfn ,gf (,gp) (when ,gp ,@body (,gf ,test))) ,test)))

-----

1 point by kennytilton 6746 days ago | link | parent | on: Self referencing lambda

You want rfn, the equivalent of CL labels as far as I can make. So /I think/ the above should just be (rfn iter...) instead of (def iter...).

-----

1 point by lojic 6746 days ago | link

Thanks. Here's a version with afn after I got help on #arc:

  (def foldl (op initial sequence)
    (let iter (afn (result rest)
                (if (no rest)
                  result
                  (self (op result (car rest)) 
                        (cdr rest))))
      (iter initial sequence)))
but it uses self inside the lambda and iter outside. I'll look into rfn.

-----

2 points by simonb 6745 days ago | link

I don't think rfn will help here. rfn is useful for macros to prevent shadowing self and perhaps some obscure tricks involving mutually recursive nested lambdas.

However in your case you can get rid of let with a simple function call:

  (def foldl (op initial sequence)
    ((afn (result rest)
        (if rest
          (self (op result (car rest)) (cdr rest))
          result))
     initial sequence))

-----

1 point by lojic 6745 days ago | link

Of course - I do that in JavaScript all the time. Thx for the tip. Of course, I still want to be able to define a lambda that is bound to a name that also calls itself by the name instead of using self within and the name outside.

-----

2 points by simonb 6745 days ago | link

I think that's one of the cases where CL labels form would be more elegant.

But luckily this is Lisp so it shouldn't be too hard to make with a wee bit smarter so it would transform

  (with (foo (fn ...)))
to

  (with (foo (rfn foo ...)))

-----

2 points by randallsquared 6746 days ago | link

Ah, so rfn is short for 'recursive fn'.

-----

2 points by kennytilton 6746 days ago | link

Looks that way. :) This is why I think arc.arc should look like: (mac rfn yadda yada "Recursive FN: an anonymous function that can call itself" ...implementation...) FYI, CL is funny, both flet and labels elt us give names to loacl functions, but only those declared with labels can be called recursively. I wonder why flet got kept, backwards compatibility?

-----

2 points by randallsquared 6746 days ago | link

Well, as you know, there's a LOT of that in CL. CL is the PHP of lisps. :)

-----

2 points by kennytilton 6746 days ago | link | parent | on: I hereby propose...

Yer no fun. :) How about "geeks": we actually enjoy this stuff! And lemme tell you something, for twelve years I have been <ugh> a Lisper -- do not leave this to chance! :)

-----


I agree. As I said, the wiki solution would be needed iff the Arc team does not want to do this. As an open tool provider myself I always invite those complaining about my doc to go ahead and contribute some. Great way to silence them. :) And maybe we can have the best of both worlds if we do the work collaboratively on a wiki which then periodically gets scraped into arc.arc so typical users are just looking at that. as an aside, if this happens I do think the wiki entries should also include the relevant code.

-----

1 point by Gotttzsche 6745 days ago | link

Maybe we should do a temporary wiki and just paste arc.arc in it so everyone can add comments in a centralized way.

Maybe get one at wikia? (they are for free, right?)

edit: nevermind, there's already git.nex-3.com :)

-----

1 point by kennytilton 6746 days ago | link | parent | on: More on running Arc under Windows

Hunh. I had to create a couple of directories, now I am stuck on: open-output-file: cannot open output file "C:\arc0\arc/logs/srv-".

-----

1 point by andyn 6746 days ago | link

There's still some work to do - Have a peek at the (system ...) statements, there's some *nix specific calls in there to do with logging.

-----

1 point by kennytilton 6747 days ago | link | parent | on: Unhygienic macros?

Mortals need not fear. Avoiding variable capture is easy albeit mildy tedious, and deliberate variable capture can be quite useful. I have seen good Schemers explaining why Scheme's macros were just as good as CL's and they convinced me they were not. :)

-----

1 point by kennytilton 6747 days ago | link | parent | on: Arc as first Lisp

Do both, esp. if you have Real Work to do and Arc being a moving target will mess you up. What you learn in PCL will be a great help to understanding Arc, so you really are not doubling your studies.

-----

11 points by kennytilton 6747 days ago | link | parent | on: I hereby propose...

Not "Archer"? Mad cool resonance there: minimal, accurate, fast, and Arc is short for arch. QED?

-----

2 points by nex3 6746 days ago | link

I like it. The only problem is that the phonetic "arc" isn't there, but that's not necessarily a requirement.

-----

2 points by kennytilton 6746 days ago | link

Archetyper? Archetypist? Arconaut? Great, now I'll be up all night. :)

-----

3 points by Xichekolas 6746 days ago | link

I like Architect... let PG be the Archangel.

-----

1 point by kennytilton 6735 days ago | link

Wait, how about "cracker"? Resonates with hacker, one speaks of cracking code (secret codes, anyway), and it goes great with Graham.

-----

1 point by absz 6735 days ago | link

Unfortunately, "cracker" already has the meaning of "one who breaks into other people's computer systems or software." We've had to fight hard enough to retain the real, positive meaning of "hacker" (and haven't entirely succeeded); "cracker" is a lost cause.

-----

More