Author Topic: AutoLisp or/and not complying to CL's  (Read 9787 times)

0 Members and 1 Guest are viewing this topic.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
AutoLisp or/and not complying to CL's
« on: July 18, 2012, 09:51:44 AM »
OK, AL's or and and only return T or nil. According to the CLHS, this is incorrect.

This is my take on attempling a CL or / CL and:
Code - Auto/Visual Lisp: [Select]
  1. (defun cl_or (forms / now)
  2.   (while (and (not (setq now (car forms)))
  3.               (setq forms (cdr forms))))
  4.   now)
  5.  
  6. (defun cl_and (forms / )
  7.   (if (apply 'and forms) (last forms)))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: AutoLisp or/and not complying to CL's
« Reply #1 on: July 18, 2012, 09:59:40 AM »
Another for OR:

Code - Auto/Visual Lisp: [Select]
  1. (defun _or ( forms )
  2.     (cond ((car forms)) (forms (_or (cdr forms))))
  3. )

AND, not so elegant:

Code - Auto/Visual Lisp: [Select]
  1. (defun _and ( forms )
  2.     (if (and (car forms) (cdr forms)) (_and (cdr forms)) (car forms))
  3. )
« Last Edit: July 18, 2012, 10:03:55 AM by Lee Mac »

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #2 on: July 18, 2012, 10:15:22 AM »
Another alternative for OR:
Code - Auto/Visual Lisp: [Select]
  1. (defun _or (forms / )
  2.   (vl-some '(lambda (item) item) forms))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #3 on: July 18, 2012, 10:21:27 AM »
A version of AND which doesn't use the current AND:
Code - Auto/Visual Lisp: [Select]
  1. (defun _and  (forms)
  2.   (cond ((car forms)
  3.          (cond ((cdr forms) (_and (cdr forms)))
  4.                ((car forms))))))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: AutoLisp or/and not complying to CL's
« Reply #4 on: July 18, 2012, 10:38:10 AM »
Or variation
Code - Auto/Visual Lisp: [Select]
  1. (defun ph:or (forms)
  2.   (car (vl-remove nil forms))
  3.   )

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: AutoLisp or/and not complying to CL's
« Reply #5 on: July 18, 2012, 11:04:18 AM »
Another OR:

Code - Auto/Visual Lisp: [Select]
  1. (defun _or ( forms ) (vl-some ''((x) x) forms))

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #6 on: July 18, 2012, 11:11:34 AM »
Wow! Didn't know that one! So you don't actually need a lambda:
Code: [Select]
Command: ('((x) (1+ x)) 2)
3
A quote does just fine!
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: AutoLisp or/and not complying to CL's
« Reply #7 on: July 18, 2012, 11:15:19 AM »
Indeed  :-)

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoLisp or/and not complying to CL's
« Reply #8 on: July 18, 2012, 02:38:10 PM »
Wow! Didn't know that one! So you don't actually need a lambda:
Code: [Select]
Command: ('((x) (1+ x)) 2)
3
A quote does just fine!

Awesome.  :mrgreen:
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoLisp or/and not complying to CL's
« Reply #9 on: July 18, 2012, 02:47:28 PM »
[OffTopic]

... Wait a minute.

Are you guys seeing the same differences in speed, or am I missing something?  :?

Code - Auto/Visual Lisp: [Select]
  1. (defun lambda1 ()
  2.   ('((acDoc)
  3.      (vla-get-name acDoc)
  4.     )
  5.   )
  6. )
  7.  
  8. (defun lambda2 ()
  9.   ((lambda (acDoc)
  10.      (vla-get-name acDoc)
  11.    )
  12.   )
  13. )
  14.  
  15. (defun lambda3 ()
  16.   (car
  17.     (mapcar
  18.       (function
  19.         (lambda (acDoc)
  20.           (vla-get-name acDoc)
  21.         )
  22.       )
  23.     )
  24.   )
  25. )
  26.  
  27. (bench '(lambda1 lambda2 lambda3) '() 100000)
  28.  

Benchmark result:
Code - Auto/Visual Lisp: [Select]
  1. LAMBDA1
  2. Elapsed: 9641
  3. Average: 0.0964
  4.  
  5. LAMBDA2
  6. Elapsed: 5101
  7. Average: 0.051
  8.  
  9. LAMBDA3
  10. Elapsed: 5974
  11. Average: 0.0597
  12.  

[/OffTopic]
« Last Edit: July 18, 2012, 02:53:17 PM by RenderMan »
"How we think determines what we do, and what we do determines what we get."

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: AutoLisp or/and not complying to CL's
« Reply #10 on: July 18, 2012, 02:55:21 PM »
Without testing, I don't doubt that the quoted format of the lambda function will be slower since without the use of a lambda function intently expressed there is more work for the LISP interpreter to interpret the list structure as a lambda function; this behaviour is similar to the use of the function function in place of a quote.

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoLisp or/and not complying to CL's
« Reply #11 on: July 18, 2012, 02:56:45 PM »
Thanks for the clarification, Lee... Sorry for the tangent, Irne  :lol:
"How we think determines what we do, and what we do determines what we get."

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: AutoLisp or/and not complying to CL's
« Reply #12 on: July 18, 2012, 11:40:18 PM »
To analyze AND / OR you can use code like this, sometimes this approach is very useful!
Code - Auto/Visual Lisp: [Select]
  1. (apply '+ (mapcar '(lambda (a) (if a 1 0)) l))

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #13 on: July 19, 2012, 03:28:50 AM »
Never mind the inability to define default / infinite arguments - causing the call to have to pass all forms inside one list!

What I still can't figure out how to accomplish is to stop pre-evaluation of arguments. You'll notice the CLHS defines and/or as macros instead of functions. That means none of the forms are evaluated prior to and/or is called - then they're only called one at a time until the boolean logic causes the macro to stop.

Therefore you can do something like this for global values:
Code - Auto/Visual Lisp: [Select]
In current AL that won't only not give the correct result, but would have no efficiency gain (since both the forms are evaluated prior to passing it to _or).

You could of course quote the forms individually, but then it's breaking from what normal lisp coders would expect.

I suppose one could do something like this:
Code - Auto/Visual Lisp: [Select]
  1. (defun _or  (forms /)
  2.   (vl-some '(lambda (item) (eval item)) forms))
  3.  
  4. (defun _and  (forms / result)
  5.   (vl-every '(lambda (item) (setq result (eval item))) forms)
  6.   result)
But that means to use it you need to call it thus:
Code - Auto/Visual Lisp: [Select]
In which case, you loose the elegance of your code in order to jump through the limitation hoops of AL.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoLisp or/and not complying to CL's
« Reply #14 on: July 19, 2012, 04:44:19 AM »
< ..>
Code - Auto/Visual Lisp: [Select]
In current AL that won't only not give the correct result, but would have no efficiency gain (since both the forms are evaluated prior to passing it to _or).


Personally I see nothing wrong with the current AutiLisp functionality.
I don't understand why you'd want to make it look like CommonLisp

This is perfectly clear and functional
Code - Auto/Visual Lisp: [Select]
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #15 on: July 19, 2012, 05:36:37 AM »
That's just used as a sample ... not a particularly good one at that. Your code would actually be ever so slightly more efficient than the forced CL example - since the setq only happens if needed.

A better example might be where you'd like to set a variable's value to something only if a set of conditions are met:
Code - Auto/Visual Lisp: [Select]
  1. ;; AutoLisp code
  2. (setq result (if (and cond1 cond2 cond3 cond4) value))
  3. ;; Common Lisp version
  4. (setq result (and cond1 cond2 cond3 cond4 value))
Another sample might be that you want the 1st item which is not nil as well as some other value:
Code - Auto/Visual Lisp: [Select]
  1. ;; AutoLisp Version
  2. (setq result (cond ((setq tmp (eval cond1)) (setq result2 1) tmp)
  3.                    ((setq tmp (eval cond2)) (setq result2 2) tmp)
  4.                    ((setq tmp (eval cond3)) (setq result2 3) tmp)
  5.                    ((setq tmp (eval cond4)) (setq result2 4) tmp)
  6.                    (t (setq result2 0) nil)))
  7. ;; Common Lisp version
  8. (setq result (or (and (setq result2 0) (eval cond1))
  9.                  (and (setq result2 1) (eval cond2))
  10.                  (and (setq result2 2) (eval cond3))
  11.                  (and (setq result2 3) (eval cond4))
  12.                  (and (setq result2 4) nil)))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoLisp or/and not complying to CL's
« Reply #16 on: July 19, 2012, 05:47:45 AM »

It would drive me crazy if AND and OR did not return a boolean value.  ...

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: AutoLisp or/and not complying to CL's
« Reply #17 on: July 19, 2012, 05:49:55 AM »
Code - Auto/Visual Lisp: [Select]
  1. (defun _or (l) (eval (cons 'cond (mapcar 'list l))))

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #18 on: July 19, 2012, 06:04:11 AM »

It would drive me crazy if AND and OR did not return a boolean value.  ...
Huh? In lisp everything /= nil is evaluated as "not-false". There is no such thing as "true", there's only "not-false" ... or rather "not-nothing". The T symbol is only added as a constant for special cases: http://www.lispworks.com/documentation/HyperSpec/Body/v_t.htm Effectively it's not needed.

Code - Auto/Visual Lisp: [Select]
  1. (defun _or (l) (eval (cons 'cond (mapcar 'list l))))
Good one! That's probably how it would be implemented inside CL!
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoLisp or/and not complying to CL's
« Reply #19 on: July 19, 2012, 06:15:23 AM »

I mean boolean having two possible values representing “true” or “false.”
... not ANY other value

AND and OR by 'logical' definition return a boolean value.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #20 on: July 19, 2012, 07:11:11 AM »
That may be true in other languages, but lisp works differently. In lisp everything is considered "true" unless it is nil. E.g.
Code - Auto/Visual Lisp: [Select]
  1. (if value
  2.   (princ "Tue")
  3.   (princ "False"))
If value=100, then above would print "True". If value=(1 3 5 2 76), then it would print "True". If value=T then it would print "True". The only time when it would EVER print "False" is when value=nil.

Even consider this:
Code - Auto/Visual Lisp: [Select]
  1. $ (setq value 'nil)
  2. nil
  3. _$ (if value "True" "False")
  4. "False"
  5. _$ (if 'value "True" "False")
  6. "True"
So even a reference to the value containing nil is still considered True. It's only when the actual value being checked results in nil that a False is signaled.

The CL versions of the logical operators are defined to reflect this very concept instead of attempting to enforce some unnatural rule that only True /= False. It's one of the major differences between Lisp and most other languages. In lisp you can see such as analogous to an if asking: "Is the test resulting in something?"

For this reason you don't need to check specifics like you need to in other languages. E.g. say you're checking if an argument was passed in C# with an instantiated object, you'd need to do this:
Code - C#: [Select]
  1. if (arg != nothing)
  2. { // Continue with true part
  3. }
  4. else { // Continue with false part
  5. }
In Lisp all you need to do is:
Code - Auto/Visual Lisp: [Select]
  1. (if arg
  2.    (progn ;; Continue with true part
  3.    )
  4.    (progn ;; Continue with false part
  5.    )
  6. )
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #21 on: July 19, 2012, 07:22:28 AM »
If lisp worked as per your idea, then the logical operators should also only allow T or nil as input arguments. E.g. instead of:
Code - Auto/Visual Lisp: [Select]
  1. (or nil 1 3 6 nil)
You'd then have to write:
Code - Auto/Visual Lisp: [Select]
  1. (or (not (eq nil nil)) (not (eq 1 nil)) (not (eq 2 nil)) (not (eq 6 nil)) (not (eq nil nil)))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoLisp or/and not complying to CL's
« Reply #22 on: July 19, 2012, 07:40:12 AM »
irneb

I've been playing with Lisp since before you were in nappies, I don't need language lessons, but thanks.

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

JohnK

  • Administrator
  • Seagull
  • Posts: 10626
Re: AutoLisp or/and not complying to CL's
« Reply #23 on: July 19, 2012, 08:33:20 AM »
You know Kerry, if you stop using the (or *var* (setq *var* ... syntax people might not get confused. :P

Hi Kerry, It's been awhile. How have you been?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

JohnK

  • Administrator
  • Seagull
  • Posts: 10626
Re: AutoLisp or/and not complying to CL's
« Reply #24 on: July 19, 2012, 08:35:45 AM »
Why Common Lisp? CL and AL are so different. Scheme would be a slightly better reference.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #25 on: July 19, 2012, 10:11:52 AM »
I've been playing with Lisp since before you were in nappies, I don't need language lessons, but thanks.
Then I'm a bit confused as to why you're questioning this. So you were playing with lisp since the 70's? I tip my hat, I was only starting with it in the early 90's. Hope I didn't offend - it just appeared that you were under a misconception about how lisp handled "booleans". It wouldn't be the first time I've misread someone's intention in a post  :ugly:

Why Common Lisp? CL and AL are so different. Scheme would be a slightly better reference.
Even in scheme the or & and work this way. See page 26 here: http://groups.csail.mit.edu/mac/ftpdir/mit-scheme/7.7/7.7.1/doc-pdf/scheme.pdf

About SCM being closer to AL, that's debatable. The syntax is much the same, but concepts such as Lexical/Dynamic scope (in SCM Lex is enforced, in CL it's optional, in AL it's impossible). AL uses the same value for falsity, failure & empty list - i.e. nil, SCM uses different constants for each. Even the some of the basic "standard" functions are named differently in SCM, e.g. defun is in CL, but the equivalent SCM would be a define of a lambda.

AFAICT the only point where AL is more like SMC is that it uses a single namespace, whereas CL uses separate namespaces for functions and variables (i.e. a function and a variable may have the same name; also if a function is passed as an argument for callback you need to prefix with #').  http://c2.com/cgi/wiki?LispSchemeDifferences

Perhaps I'm missing something, could you point me in some direction as to why SCM is a closer match to AL?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: AutoLisp or/and not complying to CL's
« Reply #26 on: July 19, 2012, 10:30:31 AM »
I do not understand you!
Do you want to say that the bad language AutoLISP, compared to others? As far as I know, all languages ​​are created on the basic functions, and then appended to the inside. What's stopping you from creating the necessary functions for your convenience?

Here, gathered followers of LISP. We love him for who he is. If necessary, we add new features in LISP or use other languages​​...

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #27 on: July 19, 2012, 10:53:04 AM »
Not sure you were posting in response to me. If so I definitely don't think AutoLisp is a BAD language, I just think it's lost ground on other lisps - and would like to make it more capable. I'd actually like to stay with lisp instead of mixing different languages for my programs, but I'm constantly running into situations where AL/VL simply cannot do it - and then noticing that CL/SCM could have.

If it's about the which is closer SCM/CL ... then I'm simply looking for a place where these "extensions" I'm attempting is already defined. Rather than reinventing stuff.
« Last Edit: July 19, 2012, 10:56:24 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

JohnK

  • Administrator
  • Seagull
  • Posts: 10626
Re: AutoLisp or/and not complying to CL's
« Reply #28 on: July 19, 2012, 11:09:51 AM »
...could you point me in some direction as to why SCM is a closer match to AL?

*Pthht*, beats me?! I haven't done LISP in several years now, and when I did it was more academic in nature (I did what you are doing now; create LET, understand EVAL, create an AL Huffman encoding function, etc.). CL and I never got along but I did start to read "ON-LISP" (I got side-tracked with the paragraph on "hygienic variables" and never went back though). I only said `slightly better' because I kinda remembered discussion(s) between several of the older gods-of-Autolisp. -i.e. When I wanted to learn Autolisp I was told by those `old-hands' to read SICP (Scheme) so I did. My thought was that since this exercise, and the Scheme language, seems more skewed towards the academic side...
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #29 on: July 20, 2012, 03:12:19 AM »
Thanks Se7en, I do remember a thread mentioning something about AL being closer to SCM than CL (just don't remember where it was). But I've investigated both myself, and looking at sample code for both I get the feeling that CL looks more familiar to me, while most of the SCM stuff looks very foreign (in comparison to AL that is). If anyone could give me a conclusive answer to this I'd swap to SCM anytime, but thus far I just don't see it.

In any case, for the purposes of this thread SCM/CL is a moot point - since both set the definitions for and/or the same way. Even the original lisp ("daddy") of AL (XLisp) has the or/and defined this way: http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-192.htm

Though I can't find a reference for XLisp 1.0's (the one from which AL was derived) or/and definitions. So possibly this change happened in the 2.0 version - which also includes a lot of CL's additions (most notably objects & classes). But I wouldn't be surprised if it was one of the changes made by Adesk in order to get the original AL to compiled size <64kbi.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: AutoLisp or/and not complying to CL's
« Reply #30 on: July 20, 2012, 04:05:34 AM »
Actually ... just found the original source code of XLisp 0.0 here: http://www.softwarepreservation.org/projects/LISP/xlisp/0_0/

Extract from xlmath.c
Code - C: [Select]
  1. /* lor - logical or */
  2. static struct node *lor(args)
  3.   struct node *args;
  4. {
  5.     struct node *oldstk,arg,*val;
  6.  
  7.     /* create a new stack frame */
  8.     oldstk = xlsave(&arg,NULL);
  9.  
  10.     /* initialize */
  11.     arg.n_ptr = args;
  12.     val = NULL;
  13.  
  14.     /* evaluate each argument */
  15.     while (arg.n_ptr != NULL)
  16.     if (cnvnum(xlevarg(&arg.n_ptr)) != 0) {
  17.         val = true;
  18.         break;
  19.     }
  20.  
  21.     /* restore the previous stack frame */
  22.     xlstack = oldstk;
  23.  
  24.     /* return the result value */
  25.     return (val);
  26. }
Clearly it returns the first value which evaluates to != 0.

Same for and:
Code - C: [Select]
  1. /* land - logical and */
  2. static struct node *land(args)
  3.   struct node *args;
  4. {
  5.     struct node *oldstk,arg,*val;
  6.  
  7.     /* create a new stack frame */
  8.     oldstk = xlsave(&arg,NULL);
  9.  
  10.     /* initialize */
  11.     arg.n_ptr = args;
  12.     val = true;
  13.  
  14.     /* evaluate each argument */
  15.     while (arg.n_ptr != NULL)
  16.  
  17.     /* get the next argument */
  18.     if (cnvnum(xlevarg(&arg.n_ptr)) == 0) {
  19.         val = NULL;
  20.         break;
  21.     }
  22.  
  23.     /* restore the previous stack frame */
  24.     xlstack = oldstk;
  25.  
  26.     /* return the result value */
  27.     return (val);
  28. }
Returns the value of the last item if all arguments evaluates to != 0.

So this is definitely an ADesk change! Which makes AL the only lisp to return T / nil ONLY from or/and.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.