Author Topic: DisEval  (Read 4046 times)

0 Members and 1 Guest are viewing this topic.

ronjonp

  • Needs a day job
  • Posts: 7529

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: DisEval
« Reply #16 on: October 25, 2020, 03:23:08 PM »
Whilst I applaud the code you have shared, note that quoting every nested expression in the supplied list is not quite achieving the same result as both mine & MP's example functions, in which certain specific expressions are evaluated immediately as part of the function definition (e.g. references to objects, such as the active document object), whilst others are evaluated when the function itself is evaluated.

Consider the difference in the result of the following function definitions, as may be illustrated through the use of defun-q:
Code - Auto/Visual Lisp: [Select]
  1. ...

Thank you for pointing and explaining that out Lee!
Now I do remember the nostalgic confusion I got years ago when I was trying to understand the manual 'diseval-uation' technique:
where I thought the logic was that everything should be recursively 'quotted' and 'nestedly-list-capsulated', but then seeing
(vla-get-activedocument (vlax-get-acad-object)) within the body, instead of (list (quote vla-get-activedocument) (list (quote vlax-get-acad-object))) .
Completely forgot about this detail while writing the sub ^^.


*sigh* ...I'm beginning to think people believe "obfuscation" equals "better".

'obfuscation' is not the thing I'm after in this thread, although it resulted in such (if I remember there was a thread somewhere here related to protecting code with obfuscation).
Reason that I do not categorise it as such, was because of Roy's explanation :

Quote
Code: [Select]
(defun LM:acdoc nil
  (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object))))
  (LM:acdoc)
)
When first called, Lee's LM:acdoc function redefines itself. The new definition directly returns the active document object and is therefore a (minute) bit faster than the less complex function proposed by Aftertouch.


Code: [Select]
(setq obj (vlax-ename->vla-object (car (entsel))))

(mp-benchmark
  '(
    (mp-get-owner-1 obj)
    (mp-get-owner-2 obj)
  )           
)

Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP-GET-OWNER-2 OBJ).....1125 / 1.35 <35% faster>
(MP-GET-OWNER-1 OBJ).....1516 / 1.00 <slowest>

(did multiple tests, observed everything from 29-41% speed increase).

TLDR: Wifey says speed isn't everything.

An aside, I prefer encapsulating objects when applicable, eliminates superfluous processing and it's tidy; win.

Thanks for providing a benchmark example, MP - helps me understand better what Roy ment back in 2017.

Still wondering were you encapsulating manually (thats the correct term, right: encapsulation?)
*Thinking that there could be a regex alternative to my suggestion*



Glad to see that ronjonp gained one more brain cell. :D

BTW I've modified it a bit to avoid quoting numbers or T symbols.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: DisEval
« Reply #17 on: October 25, 2020, 06:56:48 PM »
I agree the `encapsulated' version is tidy; no argument here about it's tidiness (however I would be careful using the term `encapsulating' in descriptions). I agree with it's tidiness because it's ready-to-ship-nature; in that, the author isn't subject to any previously defined wonky version. But I still believe it is more along the lines of obfuscation for that same reason (-e.g. if the code were adopted into a larger standard wholesale without an understanding into it's inner working). I'm not saying this a tempest-in-a-teacup just merely pointing out that you cannot pass this off as "best practices" without notice (take 10 minutes to describe your function instead of dropping it down as the latest fad). Explain the differences because there are some.

No `encapsulating' is not the proper term. Encapsulating a methodology reserved for OOP and classes; it has to do with public and private methods exposed to API users (getter's and setter's).

No, my arguments are not based in speed. Speed should be considered negligible on this level (speed considerations come into play more in operations and other larger tasks --these tasks are minor in the larger scheme of a procedure's operation).

My gripe is more about type-safety and obfuscation then anything. Adopting and perpetuating bad programming practice--especially under the guise of "better than"--is not good for anyone.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: DisEval
« Reply #18 on: October 25, 2020, 07:35:58 PM »
p.s.

self modifying functions will not work if compiled with option 'Optimize and link' set

p.p.s

a way around is to setq function to nil before redefining

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: DisEval
« Reply #19 on: October 25, 2020, 08:43:02 PM »
p.s. self modifying functions will not work if compiled with option 'Optimize and link' set

p.p.s. a way around is to setq function to nil before redefining

That's good to know; thanks for tabling it.

No `encapsulating' is not the proper term. Encapsulating a methodology reserved for OOP and classes;

Sorry, this is nonsense, OOP does not enjoy exclusive rights to the word.

en·cap·su·late

enclose (something) in or as if in a capsule.

it has to do with public and private methods exposed to API users (getter's and setter's).

👇

... I went back to university a number of years ago and formally studied OOP technologies.

👨‍🎓

Adopting and perpetuating bad programming practice--especially under the guise of "better than"--is not good for anyone.

I won't blindly dismiss; will ruminate.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: DisEval
« Reply #20 on: October 25, 2020, 09:56:49 PM »
My statement wasn't about OOP owning a term. My statement was about what is and what isn't in other languages. ...I would call the `encapsulation method` a "MACRO". I don't agree with the `encapsulation` term because if we choose the generic definition of `encapsulate' to describe things we could use it to describe a vast number of things. -e.g. "(defun a () 1) 1 is now encapsulated". ...But overall, I like macros (who doesn't) but they are not encapsulation and they--like most things--have their limitations.

> ruminate
Okay. Sounds good but it wasn't that deep of a thought/statement. -i.e. Mixing types and returns is not a good habit to get into. Many languages now offer more type safety built in.
-e.g.
The statement:
(or <VARIABLE>
returns something different than:
(setq <VARIABLE>
And if [you] understand the differences and uses, then good; use the hell out of it. But teach others so they understand that. I tried.

> wrong about encapsulation
So if encapsulating isn't about classes and methods then what is it?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: DisEval
« Reply #21 on: October 27, 2020, 05:57:08 PM »
I just made an assumption how one would call this nested-list-quoting technique in lisp, if it has any name afterall.
So I came up with 'disevaluation'.

Think we all know that encapsulation is related to function's scope (for semi-functional or fully-functional languages like JS and LISP)
or to classes 'n objects scope (for languages like Java/C#) when it goes for OOP.
The scoping technique for exposing or hiding public and private methods and properties (getters'n'setters) from some classes to be revealed in other classes would be known as 'encapsulation'.
In functional programming like LISP 'encapsulation' would be applied for declaring functions instead of classes, passing function calls instead of methods and passing variables instead of properties.

Code - Auto/Visual Lisp: [Select]
  1. (defun SpaghettiCode ( x / ravioli noodles meatballs )
  2.   ; Spaghetti Code inside, but all of the variables are declared in the parent function definition
  3.   ; assuming that this giant and very complex spaghetti code works without bugs and keeps all the variables and inner-function definitions local
  4.   ; it does something, it returns something, its bug-free, and the author is unknown
  5.   ; so its not worth it to spend time'n effort for reading and understanding the algorithm (we just use the parent function)
  6.   ; and we could say that this is an encapsulated code
  7.   (defun ravioli ..
  8.     (noodles (ravioli (meatballs ..)))
  9.   )
  10.   (defun noodles ..
  11.     (meatballs (ravioli ..))
  12.   )
  13.   (defun meatballs ..
  14.     (ravioli (noodles ..))
  15.   )
  16.   (ravioli (noodles x))
  17. ); defun SpaghettiCode
  18.  

Code - C#: [Select]
  1. namespace SpaghettiCode
  2. {
  3.   // declaring bunch of classes with chained getters'n'setters
  4.   // documenting what this assembly is all about and what are the exposed public methods and properties
  5.   // would we bother to understand the algorithm inside?
  6.   // we may care just about the functionality it provides
  7.   class ravioli
  8.   {
  9.     ..
  10.   }
  11.   class noodles
  12.   {
  13.     ...
  14.   }
  15.   class meatballs
  16.   {
  17.     ...
  18.   }
  19. }

I think we could say that a function/class is encapsulated when its scoped up to a level where its exposing just enough (meaning no redundant variables/properties/methods out of the main body).
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg