Lambda makes my head spin

Discussion in 'AutoCAD' started by Gordon Price, Sep 23, 2004.

  1. Gordon Price

    Gordon Price Guest

    In the code below, my understanding is that the '(lambda creates what is
    effectively a loop, going thru all the Layer Filters in the dictionary, and
    deleting them. Slick, bit I am looking to selectively delete only those
    filters that do not begin with 'THA_'. This way our office standard filters
    are saved, but the garbage from other offices is removed. However, my
    understanding of both the Lambda function and vla- stuff is pretty weak. Can
    someone show me what a For Next loop would look like for this?

    Much thanks,

    (defun C:LayerFilterDelete ()
    (vl-Catch-All-Apply '(lambda () (vla-Remove (vla-GetExtensionDictionary
    (vla-Get-Layers (vla-Get-ActiveDocument (vlax-Get-Acad-Object))))
    (princ "\nAll layer filters have been deleted.")
    Gordon Price, Sep 23, 2004
  2. Gordon Price

    Dan Allen Guest

    Try this, I added the progress dialog to Stig's routine (however it doesn't
    really work but I'm too lazy to remove).


    ;;; Delete layer filters based on wildcard string
    ;;; Modified from original routine by Stig Madsen, September 2001
    ;;; Deleting named layer filters is achieved by deleting
    ;;; the single XRecords in dictionary "ACAD_LAYERFILTERS"
    ;;; If a layer filter is currently in effect the filter is
    ;;; deleted but is visible in the Layer Dialog until one of
    ;;; the 3 built-in filters is chosen.
    ;;; The built-in filters cannot be deleted.
    (defun DeleteLayerFiltersWC (pattern / activeDoc xDictLayers layfilters
    count tmp tmpName x y total newcount)
    (setq activeDoc (vla-get-ActiveDocument (vlax-get-acad-object))
    xDictLayers (vla-getExtensionDictionary (vla-get-Layers activeDoc))
    pattern (strcase pattern)
    ) ;_ setq
    (if (/= (vla-get-count xDictLayers) 0)
    (progn (setq layfilters (vla-item xDictLayers "ACAD_LAYERFILTERS")
    count (vlax-get-property layfilters 'Count)
    ) ;_ setq
    ) ;_ progn
    (setq count 0)
    ) ;_ if
    (if (= count 0)
    (princ "\nDrawing contains no named layer filters")
    (progn ;;(prompt (strcat "\n" (itoa count) " layer filters found"))
    (setq x 0
    y count
    ) ;_ setq
    "Deleting Layer Filters"
    (strcat "Processing " (itoa count) " layer filters, please
    ) ;_ dos_getprogress
    (dos_waitcursor T)
    (repeat count
    (setq tmp (vla-item layfilters (- count 1)))
    (setq tmpName (vlax-get-property tmp 'Name))
    (if (wcmatch (strcase tmpname) pattern)
    (progn ;;(princ (strcat "\nDeleting Filter " tmpName))
    (vl-Catch-All-Apply '(lambda () (vla-delete tmp)))
    ; _progn
    ) ;_ if
    (setq count (1- count))
    (while (< x y) (dos_getprogress -1) (setq x (1+ x)))
    ) ;_ repeat
    (setq layfilters (vla-item xDictLayers "ACAD_LAYERFILTERS")
    newcount (vlax-get-property layfilters 'Count)
    total (- y newcount)
    ) ;_ setq
    (strcat "\nDeleted " (itoa total) " of " (itoa y) " layer
    filters, " (itoa newcount) " remain.")
    ) ;_ princ
    (dos_getprogress T)
    ) ;_ progn
    ) ;_ if
    ) ;_ defun
    Dan Allen, Sep 23, 2004
  3. Lambda creates a nameless function. *Just* like defun
    but without the need for a name.
    Jason Piercey, Sep 23, 2004
  4. Gordon Price

    Gordon Price Guest

    WOW. Lots more code to digest ;)
    I am going to print that baby out and head for the coffee house.

    As for anyone who has a simple loop replacement for the lambda and vla stuff
    I posted, I am still open to seeing it (assuming it isn't sitting right
    there in Dan's code, and I just don't know it yet.

    Gordon Price, Sep 23, 2004
  5. Gordon Price

    Jeff Mishler Guest

    Here's another version I cooked up, based upon the code by R. Robert Bell,
    to delete filters based on wildcard patterns. It does not fully support the
    2005 filters......

    (defun c:filtrdel (/ names)
    (princ "\nRoutine to delete all but the specified Layer filters. When
    entering filter
    names to retain, wildcards are allowed. i.e., entering \"zz*,xx*\" will
    delete all filters except those beginning with zz and xx.")
    (setq names (getstring "\nEnter filter names to retain, press Enter for
    none: "))
    '(lambda ()
    (setq dicts (vla-GetExtensionDictionary
    (vlax-for dict dicts
    (if (and (= (vla-get-name dict) "ACAD_LAYERFILTERS")
    (> (vla-get-count dict) 0))
    (vlax-for filtr dict
    (if (not (wcmatch (vla-get-name filtr) names))
    (vla-delete filtr)
    (princ "\nSpecified layer filters have been deleted.")
    Jeff Mishler, Sep 23, 2004
  6. <Snip>

    Now that is the best explaination I have seen.

    Just wish I knew when to use it.

    W. Kirk Crawford
    Rochester Hills, Michigan
    W. Kirk Crawford, Sep 24, 2004
  7. Gordon Price

    Fatfreek Guest

    I love your simplification but am still wondering if there's something else
    to this lambda thing (which I confess has always been a puzzle until [I
    think] now. Take this simple routine below:

    (apply '(lambda (/ spring_point spring_dia spring_lgth)
    (setq spring_point
    (getpoint "Where do you want bottom center of spring?..\n")
    (setq spring_dia (getdist "What diameter? Enter or pick ...\n"))
    (setq spring_lgth (getdist "What length? Enter or pick ...\n"))
    (command "insert" "spring" spring_point
    spring_dia spring_lgth pause

    If I remove the topmost line -- (apply '(lambda ... and its supporting
    parens below -- that would leave a simple script that would run when loaded,
    If so, wouldn't that be even simpler?
    Therefore, the only advantage in this example (that I can see) would be that
    the function enables the locally declared variables to evaporate after the
    function is used whereas a simple script could leave global variables
    scattered around with the potential of bad things happening.

    Len Miller
    Fatfreek, Sep 24, 2004
  8. Gordon Price

    MP Guest

    Hi Fatfreek,
    I don't understand why you're using apply lambda in that situation
    the combination of soliciting user input and issuing commands is typically
    put in a defun so you can use it as needed
    IMHO that is a case where a meaningful name is useful and appropriate (it
    seems to me)
    (defun C:Springpoint();or whatever
    then you load the file, and when you want a spring you issue the command, as
    many times as needed

    (defun C:Springpoint( / spring_point etc );takes care of localizing vars(as
    you did in your lambda structure)

    from the posts here (where I learned the use of lambda) one of the most
    common uses of lambda seems to be in a mapcar pattern...

    (setq listone(list 1 2 3 4 5 6 7))
    now if i want a list that is one greater than each entry,
    (setq listtwo
    (1+ item)

    gives (2 3 4 5 6 7 8)

    now you could also define a function
    (defun addOne(item)
    (1+ item)
    and then call mapcar
    (setq listtwo

    also gives (2 3 4 5 6 7 8)

    but in this case, it's not really necessary to define a named function and
    in fact makes it harder to read the mapcar phrase( it seems to me)

    the idea of writing a routine that runs as soon as the file is loaded
    doesn't make any sense to me though maybe there's some specialized
    situations where you'd want something like that.
    usually I think of lisp routines as commands that can be issued at will
    (once the file is loaded) and can be repeated whenever needed.

    but maybe i'm missing something in your example.
    hope some of that makes sense
    MP, Sep 24, 2004
  9. Glad I could make it understandable for ya. First
    line in the help file on lambda states "Defines an
    anonymous function" Same thing I said but shorter :)

    Only time I use Lambda is in conjunction with mapcar,
    apply, function, and vl-catch-all-apply (can't think of
    any others off the top of my head, at the moment)
    Jason Piercey, Sep 24, 2004
  10. Gordon Price

    Doug Broad Guest

    (setq fun (lambda (name) (princ (strcat "\nHi " name "! "))))
    is roughly equivalent to
    (defun fun (name) ....)

    I only use it as you stated also.

    Doug Broad, Sep 24, 2004
  11. I'll agree with Mark, in that instance lambda doesn't
    benefit you in any way, you'd be better off using a

    Taking Mark's examples you could also do away with
    lambda all together.

    (mapcar '1+ (list 1 2 3 4 5 6 7)) returns (2 3 4 5 6 7 8)

    I'd search google with the keyword of lambda and authors
    like Tanzillo, Puckett, Uhden, Broad, Bell (off the top of my
    head). I'm sure they have already given better examples and
    explantions than I.
    Jason Piercey, Sep 24, 2004
  12. Gordon Price

    BillZ Guest

    Handy tool for a myriad of uses.

    Command: (setq lt1 (list "this is the " " the " " and "))
    ("this is the " " the " " and ")

    Command: (setq lt2 (list "first" "middle" "last"))
    ("first" "middle" "last")

    Command: (mapcar '(lambda (a b)(strcat a b)) lt2 lt1)
    ("this is the first" " the middle" " and last")

    I love this stuff! :)

    BillZ, Sep 24, 2004
  13. Lambda is useful for creating a locally-scoped closure
    for variables:

    (defun foo (x)
    (setq x "\nValue of x in foo")
    (print x)
    ((lambda ( / x)
    (setq x "\nValue of x in lambda closure")
    (print x)
    (princ "\nExiting lambda closure")
    (print x)
    (princ "\nLeaving foo")
    Tony Tanzillo, Sep 24, 2004
  14. Gordon Price

    Doug Broad Guest

    Interesting use. Thanks.

    Doug Broad, Sep 25, 2004
  15. Thanks for the example. While I don't see an
    immediate use for this in my own code, I'll try
    and keep this in mind for future use.
    Jason Piercey, Sep 26, 2004
  16. Gordon Price

    Gordon Price Guest

    Jeff, just out of curiosity, what aspect of R2005 filters does this not

    Gordon Price, Oct 1, 2004
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.