Arc Forumnew | comments | leaders | submitlogin
Another, older wannabe neo-Lisp
12 points by vrk 6158 days ago | 28 comments
I didn't notice a link to Qi on this forum, but this might be of interest to Arcists and Anarchists alike:

http://www.lambdassociates.org/qilisp.htm

Sorry if it was common knowledge.



6 points by pg 6158 days ago | link

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 6158 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 6158 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 6158 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 6157 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 6158 days ago | link

Currying

Partial application

Pattern matching

Guards

-----

2 points by pg 6158 days ago | link

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

-----

7 points by almkglor 6158 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 6158 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 6158 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 6158 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 6158 days ago | link

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

-----

2 points by almkglor 6158 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 6158 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 6158 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 6158 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 6158 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 6158 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 6157 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 6156 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 6158 days ago | link

Optional & User Defined Typing maybe

-----

3 points by pg 6158 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 6158 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 6158 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 6156 days ago | link

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

-----

1 point by Jekyll 6155 days ago | link

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

-----

0 points by jules 6102 days ago | link

You mean type checking.

-----

2 points by sp 6157 days ago | link

Qi is built onto CL and any type correct Qi type can be compiled down to common-lisp (complete with Qi type checking).

Qi can make calls to the underlying lisp and vice versa.

Qi has a much 'purer' functional form than CL eg side effects.

Qi isn't Lisp. Qi isn't a neo-Lisp. Its built with/on lisp thats it.

Qi doesn't expand CL so much as it encompasses it. Given a Qi dsl implementation with a detailed type theory/type-checker the comparison of Qi to CL becomes irrelevant -the two are entirely different animals.

--- I spent some time attempting digesting the Qi manual... Figured that Qi/Arc had merge potential and as PG hadn't opened up Arc as of late Nov. this was all personal speculation.

As the question has been opened by PG it seems pertinent to ask, "Once the core is solidified why not build Arc with Qi?"

-Arc would be type correct with Qi type checking with timely termination.

-Arc would compile to an optimized Common-Lisp without necessarily having to build WITH common-lisp allowing erlang, haskell, ML, prolog developers etc. to contribute to ARC using a more neutral (less 'lispy') platform.

-Arc would gain from integration of sequent calculus, built in FOL, pattern-matching etc.

-Building on Qi would remove Arc from the "C - procedural - Unix" paradigm and revitalize the "Turner - functional - symbolics Genera" camp. (the 100 year language will not run on a C based operating system!)

--- Which brings to mind the second question?

Maybe the 100 yr language is less about grammar and syntax an more about reexamining the foundations for a 100 yr OS - The Functional OS (tm).

-Open Genera 2.0 is floating around on bit torrents right now waiting for a venture visionary with sufficient tech-savy to resuscitate a once truly visionary OS.

I know that the Genera system is mired in a legal quagmire... but what if Arc (the user level 'scripting' language -think .arc) was built on Qi (analogous to a C subsystem) which was itself implemented as the system abstraction layer for a reimplementation of the aging Genera lisp system. Wouldn't such a re-implementation be sufficiently divorced from the original code to free it from some of the present obstacles?

Qi seems to have some pretty strong ties with SRI et al.

I'm sure an initiative could be drummed up somewhere. If Norvig and Google don't see the merit in contributing some VC to the project (think yahoo/msn insurance) then perhaps the DARPA folks could be coaxed into action; judging by the current Balkanized state of their myriad and lingering Lisp based semanitc, rdf, expert/production systems that are driving most of the US intelligence Infrastructures software systems they could certainly benefit from such a development.

Certainly judging by what some of the CL McClim fellas are accomplishing the proposal and impetus for a Genera style system isn't completely without merit... even if it will never materialize if dependent only on CL.

-----