Arc Forumnew | comments | leaders | submit | greatness's commentslogin
1 point by greatness 6110 days ago | link | parent | on: Another small idea for parameters...

So, in this case would _ bind to the same thing as a, or do you mean it would bind to the entire construct before it was destructured?

  _ = a
or

  _ = (a . ( b . c))
I don't know if I like the idea of using [] to accept an indeterminate amount of parenthesis, it seems like it would make the functions created inside of them more complicated. On the other hand, I think this might be one of those cases where it SEEMS like a bad idea, but is actually better than it appears, so you can't really judge it until you've tried it out.

-----

1 point by drcode 6110 days ago | link

_ = (a . ( b . c))

What I'm arguing is that the _ would let you grab the original parameter without destructuring. Sometimes (like in my example) it's useful to have access to the original parameter. This is especially since, unlike CL, arc destructuring is lossy, since it allows (car nil) -> nil.

-----


instead of using (car x) to store the object type is there a way to use annotate to do it? I'm kind of confused on how that works.

-----

1 point by sacado 6110 days ago | link

Yes annotate is the arcish way to do so I think. Just do (= x (annotate x 'sphere)) and after that (type x) would give you what you want.

-----

1 point by greatness 6110 days ago | link | parent | on: Community wiki

I guess another way of doing it is by getting a wikia wiki.

-----

1 point by greatness 6111 days ago | link | parent | on: First Class Special Forms?

IF is a macro because you don't always want to evaluate all of it's arguments...

-----

3 points by kens 6111 days ago | link

I don't want to be pedantic, but 'if' is a special form and not a macro:

  arc> if
  Error: "reference to undefined identifier: _if"
  arc> and
  #3(tagged mac #<procedure>)
It's the basis for other "partial evaluation" macros.

My foundation documentation (http://arcfn.com/foundation-doc.html) lists the special forms.

-----

2 points by greatness 6110 days ago | link

err, I was refering to the way it executed. I believe On Lisp implemented an if macro.

-----

2 points by Darmani 6110 days ago | link

A conditional such as if can only be implemented as a macro if it expands to another conditional such as cond, which must be implemented as a special form.

In Arc, if is just a special form.

-----

3 points by absz 6109 days ago | link

I think the logic is to make if a "primitive macro," the way + is a primitive function. Just as you can't define + in terms of Arc functions, you can't define if in terms of Arc macros. Nevertheless, (isa + 'fn), and so the thinking is that (isa if 'mac) makes sense.

There are valid reasons not to do things this way, of course. For instance, what's so powerful about macros is that they literally expand into a code tree, which (as you observed) if can't do. For that reason, why not have (isa if 'form) (or 'prim, or 'special, or something similarly descriptive)? Then you have first-class special forms without literally making them macros. This would be a big improvement over the current state of affairs:

  arc> (type if)
  Error: "reference to undefined identifier: _if"

.

-----

1 point by mecon 6109 days ago | link

That's what i meant.

-----

1 point by zxquarx 6109 days ago | link

If can be implemented as a primitive function instead of a special form given the fn operator. It could take three arguments: a condition, a then function, and an else function and then call the appropriate function. An example implementation is:

(def if2 (cond then else) (if cond (then) (else)))

If2 would be given as a primitive function and its implementation would be hidden like that of cons is. Given access to if2, a basic if construct is:

(mac basic-if (cond then (o else)) `(if2 ,cond (fn () ,then) (fn () ,else)))

This would make code walkers easier because they wouldn't have to know about as many special forms.

-----


The question, of course, is why would someone be stupid enough to redefine cons. The answer being that this was merely an example and that this is more likely to happen to people using code written by 3rd party developers. Once we get a true module system this shouldn't be as much of an issue. Additionally, it shouldn't be that hard to keep yourself from overriding a function definition; you could merely enter in the name at the repl to see if it exists. It's really not that hard.

  arc> cons
  #<primitive:cons>
  arc> (gee, perhaps I better not overwrite this!)

-----

2 points by ctdean 6111 days ago | link

To answer your question, I would be stupid enough to do this because PROS and CONS seem like reasonable variable names. I would (and have) name variables first, tokens, blank, date, and many others for the same reasons. We're not talking about redefining functions, just lexical binding variables in a small scope.

In a Lisp 2 like Common Lisp it is very easy to work around name collisions problems with a module system. It's much harder to solve this problem in a Lisp 1 with just a module system. All the ways I know how to solve the collision problem in a Lisp 1 that use namespace management require integration with the macro expander. Is there a better way? I'd love to hear it.

-----

2 points by almkglor 6111 days ago | link

By taking advantage of the relation:

  (fn (x) (expression x)) == (fn (y) (expression y))
Suppose that our hypothetical 'fn builtin automatically did this:

  (mac new-fn (parms . body)
    (let ptab (fill-table (table) (mappend [list _ (parms)] parms))
      (let translate
           (afn (xs)
              (if (caris xs 'quote)
                 xs
                 (map [if (acons _) (self _) (or (ptab _) _)] xs)))
        `(fn ,@(translate (cons parms body)))))
This solves two problems currently in Arc: local variables can override function names used by macros, and macro names always override local variables.

-----

1 point by ctdean 6111 days ago | link

Unfortunately I have no idea what that macro is supposed to do since it won't run for me. Perhaps you could post a different version?

-----

1 point by almkglor 6111 days ago | link

Sorry, not on my hacking computer right now, so I'm not sure. Will check later what the problem is, in the meantime, what's the error?

-----

2 points by almkglor 6111 days ago | link

Aw nuts, missing parenthesis, then realized that Arc parameter forms aren't straightforward lists but have a nasty (o ...) syntax. Here's a more complex form:

   (mac new-fn (parms . body)
    (let ptab
      (fill-table (table)
        (mappend [list _ (uniq)]
          (accum add
            (withs
              (optionalp [caris _ 'o]
               optional-var cadr
               traverser
               (afn (x)
                 (if (optionalp x)         (add (optional-var x))
                     (acons x)             (do (self (car x)) (self (cdr x)))
                     (and x (isa x 'sym))  (add x))))
              (traverser parms)))))
      (let translate
           (afn (xs)
              (if (caris xs 'quote)
                 xs
                 (map [if (acons _) (self _) (or (ptab _) _)] xs)))
        `(fn ,@(translate (cons parms body))))))

-----

2 points by ctdean 6111 days ago | link

Now I see -- that's great, thanks. (It was the missing UNIQ that got me, I can add parens :))

I think that if we kept going down this direction we would eventually come up with a macro system that was "hygienic in practice". Building a good and simple hygienic macro system is a very achievable goal.

All I really want to say is that there isn't a trivial silver bullet solution: A simple module system doesn't fix name collision. A simple code walker doesn't fix it (it needs integration with the environment.)

I eagerly await the version of Arc that has a macro system where name collision can be avoided.

-----

1 point by ctdean 6111 days ago | link

BTW, some comments on the code walker solution:

These are very hard to get right without hooks into the Lisp environment (at least they are for me!). For example, we always uniqify the variable names, but sometimes that doesn't do what we want. Consider:

  (mac my-assert (val)
    `(unless ,val
       (prn "Assertion failed for " ',val)))

  (new-let wallet 'no-money
    (prn "wallet => " wallet)
    (my-assert (positive wallet))
    wallet)
Where NEW-LET is defined using your NEW-FN. This gives "Assertion failed for (positive gs1449)" when I want "Assertion failed for (positive wallet)".

Also, I don't know if Arc has dynamic variables or not, but if if does those should also not be uniqified.

I'm going to exit this thread now, thanks for the code.

-----

1 point by almkglor 6111 days ago | link

On assertions: it would really be nice to have at least just one extra namespace for local variables, I suppose, with printnames that are the same as the global namespace. new-fn then translates from symbols in the global namespace (which is what read should always emit) to local variable namespace. Aw crick, it's a hard problem.

Also, current bug with this implementation: (fn (do) `(do ,do)) will fail, I'll need to analyze do. And stuff like (fn (b) (tag b (prn "foo"))).

-----


I have had the issue where I had to hit reload for the page to show up, but I've never had the 20-30 second wait period. I've only used the web-server thing in arc0 though, and I was using it under linux.

-----

1 point by greatness 6114 days ago | link | parent | on: Regexp name definition

Yeah, I had the same idea myself, but I eventually decided it wasn't entirely useful because it'd have to match the regular expression before it could make the function call which would be really slow. There are ways around that though, such as differentiating between a regex fn and a normal fn, and first looking to see if a normal definition matches the function call, then iff it couldn't find one, it checks the regular expression function definitions. Additionally, since these regular expressions aren't very large it shouldn't take a significant amount of time to match them; but it would still hurt to have that overhead for something as fundamental as a function call.

-----


I'm still not seeing the win of pattern matching here, I'm afraid. This is actually longer than the standard definition using car/cdr. Maybe it's better for more complicated things, I suppose, but that'll defeat the purpose because it wouldn't be legible at that point (as if it is now).

-----

1 point by almkglor 6116 days ago | link

The big win is that it's assuredly correct, and you don't have to mess around dealing with car and cdr. Crossref def varline in app.arc : arc1 had a bug there because it's ridiculously easy to make a mistake dealing with car and cdr. If you can't find the bug, try rewriting the code into pattern-matching form.

-----


I'm not seeing the big win over something like this:

  (def print-list ((a . b))
    (when or.a.b
       prn.a
       print-list.b))

  (def rem-pairs ((a . (b . c)))
    (when or.a.b.c
      (if is.a.b rem-pairs.c
                 (cons a (rem-pairs:cons b c)))))

-----

1 point by drcode 6116 days ago | link

Well, I'd be happy with that, except it doesn't work- There's no way to know with or.a.b if you're at the end of the list or if there's just a nil as a last item in the list. Notice the missing item here:

  > (do (print-list '(nil nil nil)) 1)
  nil
  nil
  1

-----

1 point by greatness 6116 days ago | link

Ah, I see. When destructuring the arguments, if the last argument is nil it is equivalent to not being an item. ie:

  arc> (= a '(1 2 nil))
  (1 2 nil)
has a last destructuring bind of (nil . nil) so 'a would be nil and 'b would be nil, making my code not work and making it impossible to differentiate between the end of the list and the list with a last item of nil.

Even so, it's not that much of a problem:

  (def print-list (args)
    (unless no.args
       (prn:car args)
       (print-list:cdr args)))
This code shares almost the same amount of brevity, though I believe it defeats the purpose of what you were trying to do with the destructuring bind (make the calls to car/cdr disappear).

I don't believe your solution is the right thing to do because it wouldn't make sense for the car to be optional and then not force the cdr to be optional. I do not believe an optimal destructuring solution exists that could improve on the brevity of the original car/cdr solution.

-----

5 points by greatness 6118 days ago | link | parent | on: Another, older wannabe neo-Lisp

I suppose Qi's greatest "innovation" is their datatyping scheme which allows the definition of datatypes based on C. A. R. Hoare's Sequential Calculus. I haven't read the paper; but I suppose it might be worth looking into. Basically, it's defining a datatype based on a set of rules.

I'm not sure how useful it would be in Arc, Qi and Arc have very different goals. Qi tends toward functional programs and often breaks away from lispyness, while Arc holds simplicity and elegance up as its goals. Arc also wants to stay lispy, albeit adding a few useful shortcuts (though I'm still on the fence with the new .! syntax). Personally, speaking, I don't see the datatypes Qi has as particularly useful unless you also adopt some sort of static typing scheme as well and I'm pretty sure one of Arc's goals is NOT to do that.

Implicit Function Currying is also allowed by Qi. It's useful in some cases and wouldn't HURT adding to the code; though the people who seem to be saying it would dramatically improve the brevity of Arc code are overestimating its effect; Arc has a lot of optional parameters which could make currying useless for a lot of the places it is used in Qi. For example, (+ 4) which curries an addition operating to the next number that is passed to it. In Arc, this is would return 4. I'm unconfident about which way is the right way.

Qi is certainly a decent language for Functional Programming Enthusiasts but doesn't have a lot to offer Arc. Maybe their new class system which is coming around in Qi II would be useful to adopt, but I'm afraid I've never seen it in action myself so I'm unsure of its usefulness.

Something very useful, which you might consider adding to the standard is something similar to Kenny Tilton's Cells. I'd be interested in seeing how someone would adopt Cells to use in, say, a web application. It could be very useful.

-----

3 points by kennytilton 6118 days ago | link

I am working on a "lite" version of Cells for Arc as we speak (rough start here http://common-lisp.net/cgi-bin/viewcvs.cgi/kennysarc2/cells-...) and I do think a logical step after that would be exploration of applying that to a web app. Unfortunately I have not mucked with interwebby programming so I really would not know where to start. And it might make more sense for me to start with a Common Lisp library such as Hunchentoot. Stay tuned.

-----

4 points by almkglor 6118 days ago | link

Wow Cells! All right, I just heard a lot of enthusiasm for Cells on c.l.l but never managed to grok much of it (insufficient docs IMO); it would be interesting how you handle the mutation of objects - there's no hook in Arc for that yet.

From the looks of this framework it's a test specification.

Incidentally, arc.arc already defines an (obj ...) macro. Do you intend to redefine it?

-----

1 point by kennytilton 6118 days ago | link

Thanks, but I think all the enthusiasm on c.l.l is from me. :) Maybe when I provide a Web app example people will get fired up. (I am a dinosaur, thought a desktop GUI would do the trick);

   http://common-lisp.net/project/cells-gtk/
As for controlling change, right, my-obj!my-slot will be a backdoor, Arcells (name?) will have to work via readers/writers that invoke the Arcells engine.

Framework? Test spec? What I have so far is merely motivational examples (and I am using the OBJ macro, not redefining it):

   http://smuglispweeny.blogspot.com
Look for (+ Arc Cells) Baby Steps, which I am mopping up once the caffeine hits my cortex. When done I'll submit a new thread.

-----

More