Jump to content

trying to lambda-ize a function into another


Jef!

Recommended Posts

The title says it all. Got 2 functions (created by Peter Jamtgaard) and they do exactly what I need.

The function fix1 will never be used outside of fixblks, I tried to put it in a lambda without success. I've read a lot on lambda and even if I thought I understood lambda function understanding the common simple examples given in tutorials / help files, the error messages I got kindly reminded me that I did not. (hahaha)

 

 

I know sometimes lambda can be used on its own, and sometimes paired with apply or mapcar functions... but ATM I'm not even sure which one I should use, as I have to feed it an argument (and fix1 refers to itself). The next step will be to feed the block Ename programmatically instead of by entsel but, in my first tries I got errors like "; error: no function definition: BNAM".

 

 

I'll refrain from posting my failed attempts, but here's are the 2 working functions.

 

 

(defun C:FIXBLKS (/ ELST ENAM ESEL BNAM FLST)
 (vl-load-com)
 (setq ESEL (entsel "\nSelect block: ")
ENAM (car ESEL)
ELST (entget ENAM)
BNAM (cdr (assoc 2 ELST))
FLST nil
 )
 (fix1 BNAM)
 (vl-cmdf "regen")
 (prin1)
)

 

 

(defun FIX1 (BNAM / BENAM)
 (if (not (member BNAM FLST))
(progn
  (setq FLST  (cons BNAM FLST)
 BENAM (tblobjname "block" BNAM)
  )
  (while (setq BENAM (entnext BENAM))
(print (entget BENAM))
(if (= (cdr (assoc 0 (entget BENAM))) "INSERT")
  (fix1 (cdr (assoc 2 (entget BENAM))))
  (vla-put-color (vlax-ename->vla-object BENAM) 256)
)
  )
)
 )
)

 

 

Can someone help me replace fix1 to lambda? With that concrete example I think my understanding of lambda will greatly increase.

Thanks and cheers,

Jef!

Link to comment
Share on other sites

To answer your question, Jef!

 

(defun C:FixBlks ( / elst enam esel bnam flst )
 (vl-load-com)
 (setq esel (entsel "\nSelect block: ")
       enam (car esel)
       elst (entget enam)
       bnam (cdr (assoc 2 elst))
       flst nil
       )
 ((lambda ( func )
    (func bnam)
    )
   (lambda ( bnam / benam )
     (if (not (member bnam flst))
       (progn
         (setq flst  (cons bnam flst)
               benam (tblobjname "block" bnam)
               )
         (while (setq benam (entnext benam))
           (print (entget benam))
           (if (= (cdr (assoc 0 (entget benam))) "INSERT")
             (func (cdr (assoc 2 (entget benam))))
             (vla-put-color (vlax-ename->vla-object benam) 256)
             )
           )
         )
       )
     )
   )
 (vl-cmdf "regen")
 (prin1)
 )

I'm still trying to decide if I would use it that way myself... I certainly would if FIXBLKS were a subfunction called from a main routine... I'm undecided when FIXBLKS is called from the command line.

Either way, hope it helps.

Link to comment
Share on other sites

Hi Clint!

 

 

I cant say that I would never use it as a command, but my plan is to use it as a subfunction and target specific blocks instead of using entsel. Since I go through all the entities of blocks, 1 stones many steps, for now I've added some lines to change the attribute text styles as well to match our standard, and will add some more if I find any other things to modify within the blocks.

 

 

Hope it helps you asked? As always, your input was indeed very helpful and appreciated. :)

 

 

I spent part of the last evening thinking about this one, and my conclusion was that since fix1 referred back to itself, it wasn't possible to make it into a lambda function.

I must say that you totally fiber-glassed.. fable gazed..flabler.. overwhelmed me (haha) using 2 embedded lambdas. One thing that I can't figure out.

If you have a functionXYZ

(defun functionXYZ ( args / var1 var2)

...)

you must feed it value(s) for its argument(s)... (functionXYZ value). Lambdas are like functions. If lambda is paired with apply or mapcar functions, they are outside the lambda before it, and the arguments are outside the lambda after it. That I understood... but I'm not sure at all where the arguments passed to a "standalone" lambda come from. From my understanding (maybe I'm wrong), in your previous post, the 2nd lambda is the argument (func) of the first lambda?

If so I cant figure what would be passed as the argument (bnam) of the 2nd lambda since there is nothing after the lambda closing parenthesis.

Another thing I cant quite figure out is the reason why there are a 2nd opening parenthesis before the 1rst and enclosing both lambdas.

 

 

I promised myself to never use any given lisp parts/functions as long as I don't fully understand exactly how it works... but that one, even if I completely understand how that (very nice) Peter Jamtgaard function works, and seeing the working lambda version, I don't get how it works. From my point of view, lady Lambda is still very mysterious, and I would never have been able to lambda-ize it myself. Clint, let me tell you this: You are very good! =)

Link to comment
Share on other sites

Hi Jef!

you totally fiber-glassed.. fable gazed..flabler.. overwhelmed me

Hahaha. I admit that was my reaction when I first saw it done as well. So I tucked it away in the toolbox like we all do. :D

Thanks for the kind words of appreciation as well.

 

I'll try to explain how it works - see if it helps. To clarify what happens with a "standalone" lambda function, think of it like a normal function. Using cons as a normal function example... we know it has two arguments. So the syntax for that would be

(                      ;open parenthesis
cons                  ;the name of the function to invoke - defined elsewhere
 "item1"              ;argument 1
 "item2"              ;argument 2
 )                    ;close parenthesis

For a "standalone" lambda it is the same.

(                      ;open parenthesis
(lambda ( a b )
  (cons (substr a 3) (substr b 3))
  )                   ;the lambda function - defined in place
 "item1"              ;argument 1
 "item2"              ;argument 2
 )                    ;close parenthesis

Perhaps the thing to note is that the lambda function has it's own parentheses, (just like a defun does). And everything that occurs inside those brackets is the "function". Then there are another set of parentheses (as there are with any other function) that group the arguments for the function with the function itself. Perhaps that might answer your question about why the two parentheses?

 

With that in mind, you are correct about the second lambda being passed as a variable to the first lambda. So inside the first lambda it then becomes a function referred to by the variable name 'func'. When the first lambda function is processed, it calls (func bnam) - in fact that's all it does. This is the same as your original function calling (fix1 bnam). This is how the second lambda is invoked and is passed the argument 'bnam'. And then, because the second lambda function is being run as a function inside the first, the function 'func' remains available to be called recursively within the second lambda.

When the recursion of 'func' has completed, since there are no more commands to process, we exit the first lambda. And once that has occurred the function 'func' is no longer available to use.

Hope that helps.

Link to comment
Share on other sites

Oh my god! I'm like a blind man who just had his first sight! Thank you so much for that generous explanation, I just 100% understood. The connection is now made, every piece of the puzzle fell into place. This routine worth its weight in gold (for what it does, and educationally speaking). I'd even say it is a masterpiece.

 

 

When the recursion of 'func' has completed, since there are no more commands to process, we exit the first lambda

 

 

When func is launched from 1rst lambda, it starts going through the entities of a block, and at the first insert type entity found (nested block), it jump 1 level into recursion. With Benam being local, the recursion scan entities of the nested block, changing the color of any non-insert entities, and jump into a deeper recursion if it finds any insert type. If none are found, when the recursion complete, it jumps back to resume the preceding recursion. At that point, if there are other instances of the same nested block they would be skipped (since the bnam would be member of the flst list). If any other inserts are found, it jumps deeper into recursion, and when the first instance of func is completed (completion of "entnex-ing" all entities of the originally selected block) then we exit the 1rst lambda.

Simple but yet, soooo clever. Awesome!

 

 

Your explanations were price-less! Thanks again and again.

 

 

@pBe, I hope you'll like my "entnex-ing" ;)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...