Jump to content

Help needed with a Lisp .


Tharwat

Recommended Posts

Hello.

 

I wonder why this routine although it is creating a Layer(s) of the selected block(s)

it return an error at the end.

; error: bad argument type: lentityp nil

Here is the routine .

(defun c:blk (/ ss1 i num e blkNme )
(prompt "Select Block(s): ")
 (if (setq ss1 (ssget ":L" '((0 . "INSERT"))))
    (progn
      (setq i -1
            num (sslength ss1))
        (while (< i num)
          (setq e (entget (ssname ss1 (setq i (1+ i))
		)
	)
    )
   (setq  BlkNme
	  (cdr (assoc 2 e))
	 )
   (vl-cmdf "_.-layer" "_m" BlkNme "" "")
      ))
   (princ "Nothing Selected")
 )
 (princ)
 )

 

Thanks.

 

Tharwat

Link to comment
Share on other sites

num (1- (sslength ss1)))

You are getting to the end of the selection set and trying to extract an eName at an index that doesn't exist.

 

This is why I prefer (while (setq e (ssname ss (setq i (1+ i))))

Much less coding and it will stop the loop when you cannot extract anymore eNames from the selection set.

Remember, (entget nil) -> error

 

Also, you don't need the ignore locked objects filter on your ssget selection.

 

Try it this way:

(defun c:Test (/ i ss name)
 (if (setq i  -1
           ss (ssget '((0 . "INSERT")))
     )
   (while (setq e (ssname ss (setq i (1+ i))))
     (or (tblsearch "LAYER" (setq name (cdr (assoc 2 (entget e)))))
         (command "_.-layer" "_new" name "" "")
     )
   )
 )
 (princ)
)

Link to comment
Share on other sites

Thanks Alanjt for the interests.

 

Your routine works well ,and as you have mentioned before it would give an error with (entegt nil)

Command: (entget nil)

; error: bad argument type: lentityp nil

 

So I made it another way according to your advise, also it works well . But if we typed after running

codes (entget nil) the same above mentioned error.

 

Here is new one ...

(defun c:blk (/ ss1 i Notnil e blkNme )
(prompt "Select Block(s): ")
 (if (setq ss1 (ssget '((0 . "INSERT"))))
    (progn
      (setq i -1)
 (while (setq e (ssname ss1 (setq i (1+ i))))
   (setq Notnil (entget e))
   (setq  BlkNme
	  (cdr (assoc 2 Notnil))
	 )
   (vl-cmdf "_.-layer" "_m" BlkNme "")
      ))
   (princ)
 )
 (princ)
 )

 

Would like to know your opinion.

 

Thanks

Edited by Tharwat
Link to comment
Share on other sites

Tharwat, nice to see you're experimenting with VL- functions... but you forgot (vl-load-com). :wink:

 

I've never really done something this way, but here's a crack attempt to 'stream-line' if you will... let me know if I've overlooked something:

 

(defun c:blk (/ ss1 i Notnil e blkNme )
 [color="red"](vl-load-com)[/color]
 (prompt "Select Block(s): ")
  (if (setq ss1 (ssget '((0 . "INSERT"))))
    (progn
      (while 
        (and	
          (setq e (ssname ss1 [color="red"](cond (i (setq i (1+ i)))
                             ((setq i -1)))[/color]))
          (setq Notnil (entget e))
          (setq  BlkNme (cdr (assoc 2 Notnil))))
        (vl-cmdf "_.-layer" "_m" BlkNme "")))
    [color="red"](prompt "\n  <!>  Nothing Selected  <!> ")[/color])
 (princ))      

 

 

...Curious though, why not use foreach in lieu of while?

Link to comment
Share on other sites

Thank you Renderman.

 

I am really so glad to hear from you, although I expected to see your post a long time a go. :)

 

I have some opinions and hope you discuss them with me .

 

But to add (and) after while it's really odd to me. Because I think while function would take care of the following

codes since if and progn functions passed the entity to it. What you think ?

 

And cond function as you have located it, also odd to me, because thefollowing codes after cond is logical and no conditions

as considered in that place . Also what you think ?

 

The routine hasn't worked with me at all, it gives nothing. I am sorry for that.

 

My best regards,

 

Tharwat

Link to comment
Share on other sites

Yeah, it took me a while to check the forums, because I had this whole huge thing, called a 'lazy day', that I had to take care of... :P

 

I'd personally not do something in this manor, I'm simply trying to 'branch out' and try something new.

 

That said, I usually avoid while statements which rely on a counter variable, because it just doesn't appeal to me. I know it works, and many seasoned programers prefer it, but I just don't like it. I usually go for the foreach, or vlax-for statements instead. I do use while statements often for loop functionality though.

 

As for the cond statement, it *should* set the i variable to -1 the first time through, and once defined (non nil), increment accordingly. I'm pretty sure that the VLIDE watch window will confirm my speculation...but you'll have to verify?

 

If the routine hasn't worked for you, I apologize. I'm at home (actually my Fiancé's house) and do not have AutoCAD at the moment (it's on my other computer!). I hope I've not muddied the water with my little experiment, but I'll be watching this thread to see the solution(s) that come about.

Link to comment
Share on other sites

That said, I usually avoid while statements which rely on a counter variable, because it just doesn't appeal to me. I know it works, and many seasoned programers prefer it, but I just don't like it.

 

I prefer WHILE purely for sheer speed in most cases:

 

;; Lets find the total of a list

(defun -while ( l / total )
 (setq total (car l))

 (while (setq l (cdr l)) (setq total (+ total (car l))))

 total
)

(defun -foreach ( l / total )
 (setq total (car l))

 (foreach x (cdr l) (setq total (+ total x)))

 total
)

(defun -mapcar ( l / total )
 (setq total (car l))

 (mapcar (function (lambda ( x ) (setq total (+ total x)))) (cdr l))

 total
)

(defun -repeat ( l / total )
 (setq total (car l))

 (repeat (length (cdr l)) (setq l (cdr l) total (+ total (car l))))

 total
)

(defun -recursive ( l )
 (if l (+ (car l) (-recursive (cdr l))) 0)
)

Now the moment of truth...

 

(setq l '( 1 2 3 4 5 6 7 8 9 10 ))

(Benchmark '((-while l) (-foreach l) (-repeat l) (-mapcar l) (-recursive l)))
Benchmarking ...................Elapsed milliseconds / relative speed for 65536 iteration(s):

   (-WHILE L).........1997 / 1.21 <fastest>
   (-RECURSIVE L).....2106 / 1.15
   (-MAPCAR L)........2137 / 1.13
   (-FOREACH L).......2231 / 1.08
   (-REPEAT L)........2418 / 1.00 <slowest>

Lets ramp things up a bit:

 

(setq l '( 1 2 3 4 5 6 7 8 9 10 ))

(repeat 10 (setq l (append l l)))

Length of list = 10x 2^10 = 10240

 

Results:

 

(Benchmark '((-while l) (-foreach l) (-repeat l) (-mapcar l) (-recursive l)))
Benchmarking ...........Elapsed milliseconds / relative speed for 256 iteration(s):

   (-MAPCAR L).........1638 / 7.18 <fastest>
   (-WHILE L)..........1918 / 6.13
   (-FOREACH L)........2169 / 5.42
   (-RECURSIVE L)......3666 / 3.21
   (-REPEAT L)........11762 / 1.00 <slowest>

:)

Link to comment
Share on other sites

Wow, Lee... nice to see someone takes a day off sometimes. You know, you're totally slacking, my friend... you forgot vlax-for. lol (I'm just ribbing you!) :P

 

Benchmarks really do a great job to illustrate just how much more efficient one method is over another. Thanks! :)

Link to comment
Share on other sites

Wow, Lee... nice to see someone takes a day off sometimes. You know, you're totally slacking, my friend... you forgot vlax-for. lol (I'm just ribbing you!) :P

 

Haha thanks Renderman,

 

But of course vlax-for isn't a generic control flow statement, as it only applies to vla collections.... :whistle:

Link to comment
Share on other sites

...vla collections... as in (vla-get-activeselectionset *activeDoc*), perhaps...? :wink:

 

Well yes, or the layers/linetypes/blocks etc collections, but that's where it stops..

Link to comment
Share on other sites

Certainly.

 

I understand that it (vlax-for) more specifically processes collection and not lists. I only use that example to point out a function structure which Alan taught me (thanks Alan!), which is a simple way to switch from a list to a collection, and step through each to conduct a task.

 

...
(if (setq ss (ssget ...))
 (vlax-for x (setq ss (vla-get-activeselectionset *activeDoc*))
   ...))
(vla-delete ss)
...

 

 

As it happens, I am using more and more vla-* functions lately, so my tendancy to 'lean' towards vlax-for is logical, not necessarily preferable for other situations (i.e., code should be task dependent).

Link to comment
Share on other sites

Sure, I realise that when dealing with a SelectionSet, you can step through it using either ssname, or iterate through the ActiveSelectionSet within the SelectionSet Collection (although at this point it might be more consistent perhaps to obtain the SelectionSet through VL means also), but my point is, the vlax-for loop is certainly not generic and we are not so much 'switching from a list to a collection', as the Vanilla SelectionSet is not a list.

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