Arc Forumnew | comments | leaders | submitlogin
6 points by pg 6159 days ago | link | parent

This may be as good a place as any to ask: what if any new ideas in Qi are worth adopting?


5 points by greatness 6159 days ago | link

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

-----

3 points by lojic 6159 days ago | link

Currying

Partial application

Pattern matching

Guards

-----

2 points by pg 6159 days ago | link

Can you give me some examples of code that ends up being shorter with these things?

-----

7 points by almkglor 6159 days ago | link

  (def pair (xs (o f list))
    " Applies pairs of elements to the function `f'.
      See also [[tuples]] [[map]] "
    (if (no xs)
         nil
        (no (cdr xs))
         (list (list (car xs)))
        (cons (f (car xs) (cadr xs))
              (pair (cddr xs) f))))

  (defpat *defpat-pair
          " Example/testcase for defpat in redefining
            the `pair' function. "
          ((x y . zs))    `((,x ,y) ,@(*defpat-pair zs))
          ((x y . zs) f)  `(,(f x y) ,@(*defpat-pair zs f))
          ((x) . _)       `((,x))
          (() . _)        ())

-----

7 points by almkglor 6159 days ago | link

  (def map1 (f xs)
    " Return a sequence with function f applied to every element in sequence xs.
      See also [[map]] [[each]] [[mappend]] [[maps]] [[andmap]] [[ormap]] "
    (if (no xs)
        nil
        (cons (f (car xs)) (map1 f (cdr xs)))))

  (defpat map1-pat
     (_ ())        ()
     (f (x . xs))  (cons (f x) (map1 f xs)))

-----

3 points by pg 6159 days ago | link

Do you have an example of a function you might write in an application, rather than the definition of one of the basic list traversal operators? As I said in the Arc Challenge, pattern-matching looks great when it's used for those, but tends not to be so useful in applications, precisely because operations like map, once they're defined, give you so much of what you need from pattern matching.

-----

3 points by almkglor 6159 days ago | link

I wanted to use this as an example, but I suspect there's a bug when typ == 'choice - what's (cadr 'choice) ?

  (def varline (typ id val)
    (if (in typ 'users 'syms 'toks 'bigtoks)  (apply prs val)
        (is typ 'lines)                       (map prn val)
        (is typ 'yesno)                       (pr (if val 'yes 'no))
        (is typ 'choice)                      (varline (cadr typ) nil val)
        (text-type typ)                       (pr (or val ""))
                                              (pr val)))

-----

2 points by pg 6159 days ago | link

Oops, yes, you're right. I think that test should be (caris type 'choice).

-----

2 points by almkglor 6159 days ago | link

  (def varline (typ id val)
    (if (in typ 'users 'syms 'toks 'bigtoks)  (apply prs val)
        (is typ 'lines)                       (map prn val)
        (is typ 'yesno)                       (pr (if val 'yes 'no))
        (caris typ 'choice)                   (varline (cadr typ) nil val)
        (text-type typ)                       (pr (or val ""))
                                              (pr val)))

  (defpat varline-pat
    (,(typ (in typ 'users 'syms 'toks 'bigtoks))
        _ val)
         (apply prs val)
    ('lines _ val)
         (map prn val)
    ('yesno _ val)
         (pr (if val 'yes 'no))
    (('choice c) _ val)
         (varline c nil val)
    (,(typ (text-type typ)) _ val)
         (pr (or val ""))
    (_ __ val)
         (pr val))

-----

2 points by almkglor 6159 days ago | link

Might probably be shorter if I also add ,@(test _):

  (defpat varline-pat
    (,@(in _ 'users 'syms 'toks 'bigtoks)
        _ val)
         (apply prs val)
    ('lines _ val)
         (map prn val)
    ('yesno _ val)
         (pr (if val 'yes 'no))
    (('choice c) _ val)
         (varline c nil val)
    (,@(text-type _) _ val)
         (pr (or val ""))
    (_ __ val)
         (pr val))
The above won't work on nex-3's arc-wiki.git yet, but I'll add it this evening; I don't have access to my hacking computer right now.

-----

4 points by almkglor 6159 days ago | link

  (def eschtmlchar (c)
    (case c
       #\<  "&lt;"
       #\>  "&gt;"
       #\&  "&amp;"
            (string c)))

   (defpat eschtmlchar-pat
     (#\<)  "&lt;"
     (#\>)  "&gt;"
     (#\&)  "&amp;"
     (c)    (string c))

-----

7 points by almkglor 6159 days ago | link

  (def rev (xs)
    " Reverses a sequence. "
    ((afn (xs acc)
       (if (no xs)
           acc
           (self (cdr xs) (cons (car xs) acc))))
     xs nil))

  (defpat rev-pat
     (x)            (rev-pat x nil)
     ((x . xs) acc) (rev-pat xs (cons x acc))
     (()       acc) acc)

-----

3 points by lojic 6159 days ago | link

I've only read a bit and dabbled myself. I particularly liked the currying and partial application that I saw in Haskel. It just seemed like a fundamentally good idea to me. Possibly even axiomatic. The impression I got was that it added power in flexibility of function composition.

Regarding pattern matching & guards, I have even less experience with that, but the functional folks are certainly enamored with them. There was a thread on comp.lang.lisp regarding a symbolic simplifier that was apparently much more concise with pattern matching.

Hopefully some functional experts will come along to articulate the benefits.

-----

4 points by cooldude127 6159 days ago | link

partial application is something I always miss in lisp. I often find myself writing anonymous functions that would be much shorter with partial application. here are a few examples from some of my own CL code (pay attention to the second let binding):

With anonymous function

  (defmethod do-step ((w world))
    (let* ((locs-to-check (all-cells w))
           (actions (mapcar (lambda (x) (act w x)) locs-to-check)))
      ...)
With an explicit curry macro:

  (defmethod do-step ((w world))
    (let* ((locs-to-check (all-cells w))
           (actions (mapcar (curry act w) locs-to-check)))
      ...)
The way it should be (built into the language):

  (defmethod do-step ((w world))
    (let* ((locs-to-check (all-cells w))
           (actions (mapcar (act w) locs-to-check)))
      ...)
It might seem small, but do it enough times and you appreciate the succinctness.

-----

4 points by raymyers 6158 days ago | link

I also enjoy currying and "pointfree" style. However, wouldn't it require giving up functions that take an arbitrary number of arguments? (In fact Scala has both, but it required introducing a special syntax.)

I find that Arc's shortcut closure [] notation is a surprisingly good curry-substitute. For example:

    (map (act w) locs-to-check) ; currying
    (map [act w _] locs-to-check) ; only one token longer

-----

2 points by cooldude127 6157 days ago | link

there's something to that. i didn't really think about it, but that might just be fine. that's actually exactly what scala's explicit partial application looks like, with the underscore.

i honestly haven't been doing a whole lot of practical arc programming. CL and Slime have spoiled me to the point where I find it difficult to use a language that doesn't have that convenience

-----

3 points by ryantmulligan 6159 days ago | link

Optional & User Defined Typing maybe

-----

3 points by pg 6159 days ago | link

By optional, do you mean optional type declarations like you might get with this?

  (mac declare args
    `(do ,@(map (fn ((x y))
                  (w/uniq g
                    `(let ,g ,y
                       (unless (isa ,g ',x) (error "Bad type." ',x ,g)))))
                (pair args))))
For user-defined typing, do you need something more than annotate?

-----

5 points by Jekyll 6159 days ago | link

Qi is completely type inferring, so it proves the type correctness of the code at compile time from a minimum number of declarations, like the ML family of languages.

However, as this is optional, it can also be switched off in places to handle code that the type system can not prove correct.

To make a similar system work, you'd have to label the inputs and return type of each function, and enforce the consistency of this, all at compile time. There is a complete prolog system buried in QI allowing the types to self reference and be turing complete in terms of complexity.

Having said that, the whole of QI is only meant to be 4k lines of common lisp and under an MIT license, so it'd be quite easy to port the interesting bits of it once the core of arc has stabilised.

-----

1 point by ryantmulligan 6159 days ago | link

pg, I was referring to Jekyll's explanation of optional typing. The 'maybe' means that I don't know the value in it, I've just heard that some people like it.

-----

2 points by jules 6157 days ago | link

How can Qi be type inferring when its type system is turing complete?

-----

1 point by Jekyll 6156 days ago | link

IRC, the type inference is not guaranteed to terminate in pathological cases.

-----

0 points by jules 6103 days ago | link

You mean type checking.

-----