Arc Forumnew | comments | leaders | submit | zck's commentslogin
4 points by zck 5626 days ago | link | parent | on: Problems with arc

So w/alias is like let, but any changes are shadowed back to where the alias came from?

So

  (let var (cons 1 2)
    (w/alias head car.var
      (= head 2))
    var)
would output

  (2 . 2)
This seems related to macros and backquoting, although I can't quite explain it.

-----

1 point by zck 5633 days ago | link | parent | on: Wish list.

> 1) Mini languages in the core: A scope mini language were you can write some thing like { let x 3 ; print x } => (progn (let ((x 3)) print x)) a lambda scrope mini language { let x %1; print x} => (lambda (y) (let ((x y)) print y)) shortcuts in the scope mini language {let z arr[3]; print z} => (progn (let ((z (aref arr 3))) print z) Infix mini language and infix lambda mini language.

In Lisp, this would be a very bad idea to put in the core. There's no reason to do it. It should be built out of functions, macros, or read-macros. In fact, you can build it yourself!

> I wish you can declare strong and dynamic mode so it could be fast or dynamic.

I'm not sure what you're talking about here. Are you talking about Common Lisp's (declaim (optimize (speed 3)) statement?

> If every instance of a class can have a macro: for example an array will have an each macro. We could use a statment like: (call arr each (x) (print x)) will print all element of an array it could be great. "(x)" will be the first argument of each and "(print x)" will be the second argument.

Arc already has each! (http://files.arcfn.com/doc/iteration.html#each) Arc code to do your example is as follows:

  (each x arr
       (prn x))

-----

1 point by ylando 5633 days ago | link

Thank you for your answers.

When I talk about scope i meant a region where you can separate the function calls by a character, for example @ and the let statement span through all the region. You can easily write a macro that do (scope let x 2 @ let y 4 @ print (* x y) ) But it seem useful to me, why not have it in the core?

A class macro (this is how i call it) can be use to implement a more general case of ruby blocks in lisp. May be this idea has a problem of making a bloated binary code.

-----

1 point by zck 5633 days ago | link

Is

  (scope let x 2 @ let y 4 @ print (* x y) )
analogous to Common Lisp's let, or is it let* ?

I'm a little unclear as to what @ really does. What is the reason you want @? Is it just for let statements, or for any statement? Is it to make cleaner code, or for efficiency? Can you post some code that you think works better or is more elegantly written using @, rather than without it? Maybe some code of 5-10 lines?

-----

2 points by fallintothis 5633 days ago | link

I figure it's something like

  (mac scope exprs
    (trav exprs [if (caris _ '@)
                    (list (self (cdr _)))
                    (cons (car _) (self (cdr _)))]))
So then

  arc> (macex1 '(scope let x 2 @ let y 4 @ prn (* x y)))
  (let x 2 (let y 4 (prn (* x y))))
I think the idea is to reduce parentheses, but historically these sort of tricks don't seem to pan out.

-----

1 point by rocketnia 5632 days ago | link

I've actually wanted something similar from time to time, but without the '@ and 'let. Right now, I have just one place I really miss it (which you can see at http://github.com/rocketnia/lathe/blob/c343b0/arc/utils.arc), and that place currently looks like this:

  (=fn my.deglobalize-var (var)
    (zap expand var)
    (if anormalsym.var
      var
      
      ; else recognize anything of the form (global 'the-var)
      (withs (require     [unless _
                            (err:+ "An unrecognized kind of name was "
                                   "passed to 'deglobalize-var.")]
              nil         (do.require (caris var 'global))
              cdr-var     cdr.var
              nil         (do.require single.cdr-var)
              cadr-var    car.cdr-var
              nil         (do.require (caris cadr-var 'quote))
              cdadr-var   cdr.cadr-var
              nil         (do.require single.cdadr-var)
              cadadr-var  car.cdadr-var
              nil         (do.require anormalsym.cadadr-var))
        cadadr-var)
      ))
(Note that the Lathe library defines 'anormalsym to mean [and _ (isa _ 'sym) (~ssyntax _)]. Also, 'my is a Lathe namespace here, and I use Lathe's straightforward '=fn and '=mc to define things in namespaces. Finally, don't forget that (withs (nil 2) ...) binds no variables at all ('cause it destructures).)

If I define something like 'scope, I save myself a few parentheses and nils:

  (=mc my.scope body
    (withs (rev-bindings nil
            final nil
            acc [push _ rev-bindings])
      (while body
        (let var pop.body
          (if no.body
            (= final var)
              anormalsym.var
            (do do.acc.var (do.acc pop.body))
            (do do.acc.nil do.acc.var))))
      `(withs ,rev.rev-bindings ,final)))
  
  (=fn my.deglobalize-var (var)
    (zap expand var)
    (if anormalsym.var
      var
      
      ; else recognize anything of the form (global 'the-var)
      (my:scope
        require     [unless _
                      (err:+ "An unrecognized kind of name was passed "
                             "to 'deglobalize-var.")]
                    (do.require (caris var 'global))
        cdr-var     cdr.var
                    (do.require single.cdr-var)
        cadr-var    car.cdr-var
                    (do.require (caris cadr-var 'quote))
        cdadr-var   cdr.cadr-var
                    (do.require single.cdadr-var)
        cadadr-var  car.cdadr-var
                    (do.require anormalsym.cadadr-var)
                    cadadr-var)
      ))
Furthermore, I suspect this version of 'scope would almost always be preferable to 'do, 'let, and 'withs, partly because it's easier to refactor between those various cases. However, it doesn't do any destructuring, and it's probably a lot harder to pretty-print. (I'm not even sure how I would want to indent it in the long term.)

-----

2 points by fallintothis 5632 days ago | link

That example doesn't really call out to me: it looks like you could save yourself a few parentheses and nils by refactoring with something simpler, rather than with a complex macro. E.g., if I understand the code correctly:

  (=fn my.aglobal (var)
    (and (caris var 'global)
         (single:cdr var)
         (caris var.1 'quote)
         (single:cdr var.1)
         (anormalsym var.1.1)))

  (=fn my.deglobalize-var (var)
    (zap expand var)
    (if (anormalsym var)
         var
        (aglobal var)
         var.1.1
        (err "An unrecognized kind of name was passed to 'deglobalize-var.")))
But then, I avoid setting variables in sequence like that.

-----

2 points by rocketnia 5631 days ago | link

Hmm, I kinda prefer local variables over common subexpressions. It's apparently not for refactoring's sake, since I just name the variables after the way they're calculated, so it must just be a premature optimization thing. :-p

But yeah, that particular example has a few ways it can be improved. Here's what I'm thinking:

  (=fn my.deglobalize-var (var)
    (zap expand var)
    (or (when anormalsym.var var)
        (errsafe:let (global (quot inner-var . qs) . gs) var
          (and (is global 'global)
               (is quot 'quote)
               no.qs
               no.gs
               anormalsym.inner-var
               inner-var))
        (err:+ "An unrecognized kind of name was passed to "
               "'deglobalize-var.")))
I still like 'scope, but I'm fresh out of significant uses for it.

-----

2 points by fallintothis 5631 days ago | link

(To continue the digression into this particular case...) I had thought about destructuring, but found the need for qs and gs ugly. Really, a pattern matching library would be opportune. But since there's no such luck in Arc proper, it'd be ad-hoc and probably altogether not worth it (though not difficult to implement). I say this with respect to vanilla Arc; I don't know if Anarki has such a library. Still, it'd be hard to beat something like

  (=fn my.deglobalize-var (var)
    (zap expand var)
    (or (check var anormalsym)
        (when-match (global (quote ?inner-var)) var
          (check ?inner-var anormalsym))
        (err "An unrecognized kind of name was passed to 'deglobalize-var.")))

-----

2 points by akkartik 5633 days ago | link

I'm not sure I fully understand the features you're suggesting, but the question should be "does it have to be in the core". Err on the side of keeping the core as minimal as possible unless there is a clear reason to do otherwise.

-----

1 point by rocketnia 5632 days ago | link

Exactly. The core can't contain everything everybody would ever find useful. Instead, it's the core's job (IMO) to make it easy to define those things as they come up.

Additionally, it may or may not be the core's job to encourage canonical APIs for non-fundamental but really useful stuff, just so that programmers don't end up defining the same things over and over in ways that are flawed or incompatible with each other. I think this "may or may not" issue is the R7RS split in a nutshell.

In my own opinion, a "core" that tries to provide a comprehensive bookshelf of useful but programmer-definable things isn't a language; it's a utility library. Some libraries may be extremely popular, and they may even be standardized, distributed, and/or documented alongside their languages, but it's ultimately up to the development team to choose the combination of languages and libraries that's right for the project.

-----


Not all the code I've done is up there. Also, I only recently started putting code up, so the commit times aren't actually when I did the problem; I'm not that fast.

Here's my Project Euler profile: http://projecteuler.net/index.php?section=profile&profil... . Feel free to ask any questions. I generally stopped optimizing code once it ran in less than a minute, so there are definitely some problems that could be optimized more.

-----

1 point by zck 5681 days ago | link | parent | on: What does 'nil buy us?

It's nice to have a form for that value that you can to say to someone without having to explain. Saying "the empty list" sounds awkward, and it would be consistent with pg's design goals for Arc to make it simple to talk about that value.

-----

2 points by akkartik 5680 days ago | link

That's a fair reason, though you can just teach people to read '() as 'nil' (say in the tutorial).

I'm not second-guessing the decision; I just want to confirm that I'm not missing a more substantial reason. From an implementor's perspective, it's good to know that nil-termination isn't a reason to require a 'compiler pass' for arc. Even if you include 'nil to be eq to '(), ac-denil and ac-niltree are redundant. It seems a strange decision to perform the translation when much of arc is so barebones and no-nonsense.

-----

1 point by zck 5694 days ago | link | parent | on: Differences between Arc and Lisp

I'm going to nitpick on your terminology, 'cause it's important. Arc is a dialect of Lisp. There are many Lisps (Common Lisp, Emacs Lisp, AutoLISP, Clojure, etc.), but I'm going to go with you meaning Common Lisp.

Have you checked out the tutorial? (http://ycombinator.com/arc/tut.txt) It's a good introduction, and you can diff what you see with what you would write in Common Lisp in your head pretty easily, as the code examples are small.

A lot of the stuff on pg's Arc page (http://www.paulgraham.com/arc.html) goes into detail about how he's designing it.

But for a specific list of differences (e.g., "Arc is a Lisp-1, so you don't refer to functions as #'function-name"), I don't know of one.

-----

1 point by zck 5700 days ago | link | parent | on: Infomation

Even though these links are also found in fallintothis's comment, I think it's worth highlighting them. http://ycombinator.com/arc/tut.txt is the tutorial to Arc, and is good no matter what your Lisp experience is. http://files.arcfn.com/doc/index.html has a lot of documentation.

-----

2 points by zck 5747 days ago | link | parent | on: Scheme version requirements

It was fixed: http://arclanguage.org/item?id=10254 . For reference, I'm currently using MzScheme 4.2.1 .

-----

1 point by zck 5785 days ago | link | parent | on: Atdefs - mutual atomicity

I haven't played around with atomicity, but wouldn't it be cool if this worked?

  (atomic (def enq (obj q) ...)
      (def deq (q) ...))
Edit: if I'm testing properly, this doesn't work:

  arc> (atomic (def wait () (sleep 5) (prn "done with wait")) (def stuff () (prn "stuff!")))
  #<procedure: stuff>
  arc> (thread (wait))
  #<thread>
  arc> (stuff)
  stuff!
  "stuff!"
  arc> done with wait

-----

1 point by lg 5785 days ago | link

I thought about this too, but it doesn't look right to me. I would expect this makes the act of defining the functions atomic, but not calls to those functions once defined.

-----

1 point by zck 5785 days ago | link

To me, it feels the same as

  (let ctr 0
       (def inc () (++ ctr))
       (def reset () (= ctr 0))

-----

1 point by zck 5808 days ago | link | parent | on: Function argument converter

Wow, I really like this syntax. Of course, I haven't played around with it yet, but I like the elegance here.

-----

2 points by zck 5853 days ago | link | parent | on: Why Arc?

It seems like there are two questions here.

1. Why Lisp? 2. Given Lisp, why Arc?

Given your background, I think what you're asking is mainly question 1. Here's a few answers to Why Lisp? I use Lisp because it's closer to the way I think. It allows me not to have to worry about variable types. [0] It has integers that aren't bounded. [1] There's a REPL. [2]

Now, given Lisp, why Arc? I like Arc because, although I haven't tried out a lot of Lisps (I'm only on chapter 7 of ANSI Common Lisp, so I'm just learning), it seems concise. I like that it's evolving, and I like pg's goal of trying to make shorter programs. I don't like how long keywords are in many Lisps. Arc is a good Lisp getting better.

[0]You can assign types to variables in Lisp, but this only needs to be done for speed.

[1]My friend and I talk about Project Euler often. He's using C; I'm using Arc. I've never had to worry about integer overflow. He's had to use a 200-cell array of integers to simulate a 200-digit number, and he's had to write his own operators to add, subtract, multiply, and divide these arrays.

[2]Read Evaluate Print Loop. If you use Bash, or the Windows command shell, imagine having to open up a text editor, type in your command, save it, and run it to do any command. This is what compiling feels like to me now.

-----

More