vlax-put-property usage

Discussion in 'AutoCAD' started by David Kozina, Jan 3, 2004.

  1. David Kozina

    David Kozina Guest

    There were some comments made a few weeks ago regarding the utter lack of
    necesity for the *entire* set of vla- functions - and that that entire set
    could be reduced to 3 vlax- functions: vlax-invoke-method,
    vlax-get-property, and vlax-put-property.

    So - after reviewing my code for vla- functions, I noticed that, with
    respects to the vla-put- property functions, once I replaced them with their
    vlax- equivalents, they looked like a prime target for further
    optimization...

    IOW, once I changed this code:
    (vla-put-Color _obj acByBlock)
    (vla-put-Layer _obj "0")
    (vla-put-Linetype _obj "BYBLOCK")
    (vla-put-LineWeight _obj acLnWtByBlock)

    to this:
    (vlax-put-property _obj 'Color acByBlock)
    (vlax-put-property _obj 'Layer "0")
    (vlax-put-property _obj 'Linetype "BYBLOCK")
    (vlax-put-property _obj 'LineWeight acLnWtByBlock)

    it seemed that now it could be reduced further, with a small 'wrapper'
    function, PutProperties, which goes like so:

    ; applies new property values to an object
    (defun PutProperties
    (_obj ; object to apply new property values to
    Property_alst ; assoc list of new ('Property . Value) dotted pairs
    /
    ;
    )
    ; begin
    ; ...process property pairs
    (mapcar
    (function
    (lambda
    (Property_dp)
    (vlax-put-property
    _obj
    (car Property_dp)
    (cdr Property_dp)
    )
    );_end lambda
    );_end function
    ; begin list
    Property_alst
    ; end list
    );_end mapcar
    ; end
    );_end defun


    However, if I try to work with an actual list of dotted pairs:
    (PutProperties
    _obj
    '(('Color . acByBlock)
    ('Layer . "0")
    ('Linetype . "BYBLOCK")
    ('Lineweight . acLnWtByBlock)
    )
    )

    AutoCAD revolts under the strain. Why?
    (I've tried various combinations of a literal quoted association list, to no
    avail.) I imagine it's a pretty basic oversight on my part- but I can't see
    it. Can a quoted list be used here?

    Yet, using list and cons does work:
    (PutProperties
    _obj
    (list
    (cons 'Color acByBlock)
    (cons 'Layer "0")
    (cons 'Linetype "BYBLOCK")
    (cons 'Lineweight acLnWtByBlock)
    )
    )

    It just isn't as compact as I was hoping for.

    Finally, is this basically a good/sound idea or not?

    Have you found a more effective/efficient way to use vlax-put-property in
    your code? Would error-trapping be a good thing to add to the PutProperties
    routine, or would it just bog it down needlessly?

    Comments would be appreciated.

    Best regards,
    David Kozina
     
    David Kozina, Jan 3, 2004
    #1
  2. David Kozina

    ECCAD Guest

    David,
    If you packed it any tighter, you would need C-4 to unpack it.
    (for other humans).
    Bob
     
    ECCAD, Jan 3, 2004
    #2
  3. acByBlock and acLnWtByBlock are symbols that
    must be evaluated.

    Not sure what the point to the "wrappers" are, but
    I prefer to have code that is more expressive in
    nature (e.g., individual calls to vla-put-xxxxx).

    The fact that you can reduce all ActiveX method
    calls and property references to only 3 functions
    doesn't necessarily mean that doing so serves a
    good purpose. In this case, it doesn't really,
    since it makes code harder to read and understand,
    without making it the least bit faster.

    On the other hand, here is a case where a wrapper
    can do wonders for Visual LISP ActiveX programming:

    ;; Universal nested property getter
    ;;
    ;;
    ;; Syntax:
    ;;
    ;; (vla-get <proplist>)
    ;;
    ;;
    ;; Where <proplist> '(PropertyName|IndexKey ...))
    ;;

    (defun vla-get (proplist)
    (if (and proplist (atom proplist))
    (vlax-get-property
    (vlax-get-acad-object)
    proplist
    )
    (vla-get-aux (vlax-get-acad-object) proplist)
    )
    )

    (defun vla-get-aux (obj proplist / value result)
    (cond
    ( (not proplist) obj)
    (t (setq value
    (if (member (type (car proplist)) '(int str))
    (vlax-invoke-method obj 'Item (car proplist))
    (vlax-get-property obj (car proplist))
    )
    )
    (setq result (vla-get-aux value (cdr proplist)))
    (if (and (cdr proplist)
    (eq (type value) 'vla-object)
    )
    (vlax-release-object value)
    )
    result
    )
    )
    )

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    It's too much typing for me to fully explain what the
    above functions do, but this should make it perfectly
    clear:

    Command: (vla-get '(ActiveDocument ActiveLayer Name))
    "0"

    Command: (vla-get '(ActiveDocument Layouts 1 Name))
    "Layout2"

    [You need at least 1 object in Modelspace for this]:

    Command: (vla-get '(ActiveDocument Modelspace 0 EntityName))
    "AcDbCircle"

    Command: (vla-get '(ActiveDocument ActiveLayout))
    #<VLA-OBJECT IAcadLayout 01bc0924>

    The really interesting part, is that all intermediate
    results which are VLA-OBJECTS are also released via
    calls to (vlax-release-object)
     
    Tony Tanzillo, Jan 3, 2004
    #3
  4. David Kozina

    John Uhden Guest

    I've found that (vlax-invoke), (vlax-get), and (vlax-put) work the best most of
    the time and avoid the tedium of dealing with safearrays and variants. BUT, you
    can't use them all the time. A prime example is the GetBoundingBox method where
    you have to supply the quoted symbol names for the return values of MinPoint and
    MaxPoint.

    (vlax-invoke Object 'GetBoundingBox 'MinPoint 'Maxpoint) doesn't set the symbols
    MinPoint or MaxPoint, whereas
    (vla-GetBoundingBox Object 'MinPoint 'Maxpoint) will.

    Your idea of "wrapping" may or may not be advantageous. Judge for yourself by
    counting the number of evaluations any function performs. Then do a time-test.
    Learning is fun.

    Practice makes perfect, or at least gets closer.
     
    John Uhden, Jan 3, 2004
    #4
  5. Just a side note regarding comments you've
    recieved:

    If performance were so important as some seem
    to think, to the extent that they can use it
    as justification for obsfucated and extremely
    difficult to read code, then consider using a
    proramming language that does not execute like
    molasses in January.

    The "programmer-in-a-vacume" mentality that
    some independent, renagade consultants who do
    not have to routinely deal with other formally
    educated programmers have, often misleads them
    into beliving they can get away with writing
    obsfucated code. However, that is not the rule,
    it is the exception.

    If you're serious about programming and expect
    to collaborate or work with others who are,
    writing code in the "let me make them scratch
    their heads" style of coding that some routinely
    exhibit here, will win you 0 friends in the
    world of formally educated, qualfied software
    engineering professionals.
     
    Tony Tanzillo, Jan 4, 2004
    #5
  6. David Kozina

    Doug Broad Guest

    David,
    Tony explained why yours didn't work and demonstrated a nice
    wrapper function. Here is another flavor (just for fun).

    ;|begin vla-get.lsp-----------------------------------------
    An ActiveX wrapper function inspired by Tony Tanzillo.
    D. C. Broad, Jr. 1/4/2004
    Function: Universal nested property getter
    Format: (vla-get <property list>)
    NOTE: Property list must be in order of specific to general
    Examples:
    (vla-get '("door" blocks activedocument)) ;;assuming block door
    (vla-get (list 'count *model*)) ;where *model* is the modelspace
    (vla-get nil) ;returns application
    (vla-get '(color 0 modelspace activedocument)) ;assuming mspace obj
    (vla-get '(name activelayer activedocument))
    -----------------------------------------------------|;
    (defun vla-get (lst)
    (cond
    ((null lst) (vlax-get-acad-object))
    ((= (type (car lst)) 'vla-object) (car lst))
    ((member (type (car lst)) '(int str))
    (vlax-invoke-method (vla-get(cdr lst)) 'item (car lst)))
    ((vlax-get-property (vla-get (cdr lst)) (car lst)))))
    ;;-------------------------------------------end vla-get.lsp
     
    Doug Broad, Jan 4, 2004
    #6
  7. Doug - thanks for the flattery. Aside from requiring
    the elements in the list to be backwards; requiring the
    object parameter to be in the list; and not bothering to
    release intermediate vla-objects, how does this differ
    from/improve on what I posted?
     
    Tony Tanzillo, Jan 4, 2004
    #7
  8. David Kozina

    Doug Broad Guest

    1)Reorganizing the list backwards eliminated the
    necessity for 2 functions to implement the recursion.
    This seemed simpler and more readable
    but that is up to others (including you) to decide.
    2)An object is not required to be in the list but is
    allowed to be in the list, so, theoretically, it is more
    generalized. If an object is already known, there
    is no need to look it up again from the root object.
    3)IMO, objects which are not bound to symbols
    do not need to released. Since the only symbol was
    the list argument and since that would be automatically
    garbage collected it seemed unnecessary to release
    the object binding. (Without storing the intermediate
    vla-objects, there was no mechanism to release them.)
    My understanding is that unless the object is bound
    to a global symbol, it does not require release.
    What do you think?
    4)If the property list is more than 1 item long, the
    revised version seems to operate faster although
    I doubt anyone would notice.

    Thanks again for your demonstration.
     
    Doug Broad, Jan 4, 2004
    #8
  9. Sounds like you've got the cart in front of the horse
    here. It's not about the readability of the api function,
    but the readability of the calls made to it that are the
    issue. I can see any compelling reason why one would
    sacrifice the latter to serve the former.

    Using the same outer-to-inner syntax used in most other
    languages (like VB for example) is the primary objective
    to start with. The backwardness of what you're doing
    only to eliminate the need for two functions to do the
    recursion is IMHO, self-defeating.
    I think You're assuming that my (vle-get) is the only
    entry point. One can just as easily use (vle-get-aux)
    without (vle-get) when the root object is something other
    than the Application, and since they may already have
    that object in a variable, it makes sense to express it
    as a seperate argument, rather than requring them to add
    it to the list.
    I don't agree. Not releasing an AcadEntity can lead to
    problems (the BREAK a CIRCLE into an ARC scenario).
     
    Tony Tanzillo, Jan 4, 2004
    #9
  10. David Kozina

    Doug Broad Guest

    In response,
    1)List order quirky
    Point taken. The list order is a weakness of the revision.
    2)Aux function has its own uses
    Point taken. I would have prefered the single function
    but can see your point. I also better understand your
    point of requiring the object in the list wheras your
    vla-get-aux keeps them separate.
    3)Not releasing objects causes problems.
    Agree. After testing, my function causes problems
    if requesting the color of a circle that is later broken into
    an arc whereas yours does not. This is a serious
    weakness.

    A call to (gc) would have been necessary to reset
    mine in the circle/arc scenario, wheras it would not be
    required with your function. Although mine could
    be fixed, it would have no advantages over yours
    and still have the reverse list order problem.

    Using any version to return a vla-object also causes
    problems if that object is not released later by the
    calling function or (gc) done.

    Thanks for your response and for your functions.
     
    Doug Broad, Jan 4, 2004
    #10
  11. David Kozina

    David Kozina Guest


    Doh! Of course.


    Well, for me, using the vlax- functions actually *does* make the code easier
    to read and understand - since the code actually *says* that I'm using a
    'method' or working with a 'property'. I can see that the vla- functions
    result in more abbreviated code - but the vlax- functions seem to be more
    consistently written - which makes it easier for me to follow. I don't know
    why - perhaps it was/is just the primary learning curve, but trying to
    figure out and use the vla- functions has been a major headache for me.
    After the vlax- functions were brought to my attention, I thought, 'Hey, for
    some reason, this is *much* simpler for me to write.' Just my own
    experience.

    As for the little PutProperties function - it seemed like a fair way to use
    a 'dxf'-like (yet more readable than dxf group code numbers) association
    list when setting object properties. So there I go - make the code less
    abbreviated by using the vlax- functions, and then try to abbreviate the
    result. What can I say? :)


    Way nice, Tony - Thanks!

    Best regards,
    David Kozina
     
    David Kozina, Jan 5, 2004
    #11
  12. David Kozina

    David Kozina Guest

    John,

    Many thanks for the 'heads up' regarding GetBoundingBox.
    I know I've used that a time or two - and I thought it was working okay
    after switching over to vlax-invoke, but, on second thought, maybe not...
    I'll have to go back and recheck that now.

    What other vla- <-> vlax- idiosyncrasies have you encountered?

    Best regards,
    David Kozina



    ....
     
    David Kozina, Jan 5, 2004
    #12
  13. David Kozina

    David Kozina Guest

    John,

    Could you provide a specific example wherein
    (vlax-invoke-method obj 'GetBoundingBox 'Min_pt 'Max_pt)
    does not work as advertised?

    After doing some extremely minimal (and most likely far-from-sufficient)
    testing, I'm not coming across any noticeable difficulties.

    Or is this more like one of those "Twilight Zone-ish" inconsistent gremlin
    thingies that sometimes happens and sometimes doesn't?
     
    David Kozina, Jan 5, 2004
    #13
  14. Try it with (vlax-invoke) instead of (vlax-invoke-method)
     
    Jason Piercey, Jan 5, 2004
    #14
  15. David Kozina

    David Kozina Guest

    I ain't *worried* about (vlax-invoke)... ;)
    (but I'll see what happens)
     
    David Kozina, Jan 5, 2004
    #15
  16. (vlax-invoke-method 'GetBoundingBox 'minpt 'maxpt) always
    works. I believe he was referring to this not working with
    (vlax-invoke), but that's because (vlax-invoke) handles
    the results of multiple output parameters internally, and
    always returns them as a list of results (and converts to
    LISP types where appropriate).

    While that may seem easy, it requires a lot of additional
    code in the internal implementation, whereas because the use
    of quoted symbols is consistent and doesn't attempt to do
    any conversion to LISP types, it requires little additional
    code internally.
     
    Tony Tanzillo, Jan 5, 2004
    #16
  17. i use something similar of the function used in the a-mtext.lsp under the
    sample\visual lisp\reactors folder is call it: update-parameter

    i did the update to use vlax-put-property and also vlax-property-available-p

    and both functions works just fine... hth

    David Kozina
     
    Luis Esquivel, Jan 5, 2004
    #17
  18. (vlax-invoke-method 'GetBoundingBox 'minpt 'maxpt) always
    works. I believe he was referring to this not working with
    (vlax-invoke), but that's because (vlax-invoke) handles
    the results of multiple output parameters internally, and
    always returns them as a list of results (and converts to
    LISP types where appropriate).

    While that may seem easy, it requires a lot of additional
    code in the internal implementation, whereas because the use
    of quoted symbols is consistent and doesn't attempt to do
    any conversion to LISP types, it requires little additional
    code internally.
     
    Tony Tanzillo, Jan 5, 2004
    #18
  19. David Kozina

    David Kozina Guest

    Tony (and Jason),

    Again, thanks for the additional info on these functions. I see that
    vlax-invoke doesn't do the same thing.

    Just was wondering if John had come across something else that I ought to be
    aware of.

    I think that's been a major part of the 'learning curve' difficulty for me
    with these "new" functions - there's even more ways now to 'skin the cat',
    and up 'til recently, I just haven't seen too much in the way of direction
    for what is the more optimal path to take. But I think I'm starting to see
    at least some progress in getting these functions to at least *work*, so I'm
    happy about that.

    On another front, I know I'm still very much in the dark regarding the
    proper way to handle errors - so I think I've gone way overboard in some of
    my routines to try and not allow anything 'wrong' to occur. I'll probably
    post some (more) god-awful code one of these days, hoping to get some
    'optimization' guidelines on how it could be done better. I'm sure I'll be
    able to provoke *somebody* out there... ;)

    And no doubt learn much more at the same time...
     
    David Kozina, Jan 5, 2004
    #19
  20. David Kozina

    John Uhden Guest

    Tony:

    (vlax-invoke) doesn't work with quoted return symbols at all, internally,
    externally, whatever. That's all I meant.

    But I sorta think that...
    (defun lwpoly#1 (Coords)
    (vla-AddLightWeightPolyline
    Model
    (vlax-safearray-fill
    (vlax-make-safearray vlax-vbDouble (cons 0 (1- (length Coords))))
    Coords
    )
    )
    )

    and...
    (defun lwpoly#2 (Coords)
    (vlax-invoke-method
    Model
    'AddLightWeightPolyline
    (vlax-safearray-fill
    (vlax-make-safearray vlax-vbDouble (cons 0 (1- (length Coords))))
    Coords
    )
    )
    )

    both look like a bundle more code than...
    (defun lwpoly#3 (Coords)
    (vlax-invoke Model 'AddLightWeightPolyline Coords)
    )

    the last of which also happens to be twice as fast.
     
    John Uhden, Jan 6, 2004
    #20
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.