Grrr 发表于 2022-7-5 17:18:24

vl catch all适用于lambda

大家好,
我正在学习“错误捕捉”,但出现了一些问题。
我想我已经理解了它的基本原理(通过这个示例代码和注释):
(defun C:test ( / SS a errCount o ll ur )
(if (not (setq SS (ssget "_I")))
        (progn
                (prompt "\nSelect objects to rotate: ")
                (setq SS (ssget "_:L"))
        )
)

(if SS
        (progn
                (sssetfirst nil nil)
                (initget 1)
                (setq a (getangle "\nSpecify rotation angle: "))
                (setq errCount 0)
                (vlax-for o (setq SS (vla-get-ActiveSelectionSet (vla-get-activedocument (vlax-get-acad-object))))
                        (vla-GetBoundingBox o 'll 'ur)
                        (if
                                (vl-catch-all-error-p ; determines if the value of (vl-catch-all-apply) is an error, returns T or nil
                                        (vl-catch-all-apply ; requires a (function) and a (list)
                                                'vla-rotate ; the function (can be a lambda expression either)
                                                (list ; the list
                                                        o ; <- arg (vla-object)
                                                        (vlax-3D-point ; <- arg (safearray point)
                                                                (mapcar '(lambda (a b) (/ (+ a b) 2.))
                                                                        (vlax-safearray->list ll)
                                                                        (vlax-safearray->list ur)
                                                                )
                                                        )
                                                        a ; <- arg (angle)
                                                ); list
                                        )
                                )
                                (setq errCount (1+ errCount))
                        ); if
                ); vlax-for
                (if (/= 0 errCount) (princ (strcat "\n" (itoa errCount) " objects were on locked layer!")))
                (vla-delete SS)
        );progn
); if SS
(princ)
); defun
(vl-load-com)(princ)
 
然后,为了知道该错误消息是什么,只需将函数vl-catch-all-error-p替换为该vl-catch-all错误消息
 
希望这有帮助。

Tharwat 发表于 2022-7-5 17:37:34

 
因此,使用vla StartUndoMark函数,您可以设置一个标记,用于撤消在该函数和必要的后续函数之间运行的一系列操作,即vla EndUndoMark,以结束或标记您在程序中执行的一系列操作的结束,然后,当你需要撤销你已经做过的事情时,你可以撤销之前在这两个函数之间包含的所有任务。
 
运行Test1,当您完成时,尝试撤消并对第二个程序Test2执行相同的操作,以通过使用上述函数查看两者之间的差异。

; the main task: trying to use (vl-catch-all-apply) with (lambda)
; the goal here is to iterate trough all layers, and return the non-active ones (couldn't figure out a better example)
(defun C:test ( / LayersLst )
(vl-load-com)
; any explanation when/why "Start/End UndoMark" method is used for?
(vla-StartUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))

(vlax-for lay (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))
        (setq LayersLst (cons lay LayersLst))
); vlax-for
; The main question is below:
(if
        (vl-catch-all-error-p
                (vl-catch-all-apply ; will (vl-catch-all-apply) + (lambda) work for more than one list?
                        '(lambda ( x ) ; arguments?!
                                (eq
                                        (car x)
                                        (cadr x)
                                ); test for the error (must be like this?)
                        )
                        (list ; wrap 2 lists in one?
                                (mapcar 'vla-get-name LayersLst)
                                (list (vla-get-name (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object)))))
                        )
                )
        )
        (princ (strcat "\nNot Active: " (vla-get-name (car x))))
        (princ (strcat "\nActive Layer: " (vla-get-name (car x))))
); if

(vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
(princ)
); defun

Tharwat 发表于 2022-7-5 17:43:22

谢谢你的帮助Tharwat!
在测试错误捕捉时,我取得了一点进展:

(vl-catch-all-error-p (vl-catch-all-apply
                     '(lambda nil
                         ;; Forced to have an error in this case since it's not possible
                        ;; to concatenate a string with a list of strings in this example.
                        (strcat "Layer1" (mapcar 'vla-get-name layerslst))
                        )
                     )
)

它似乎可以评估函数的结果,在上面的代码中,我测试了2个defun,并将结果写在每个defun的右侧。
这意味着如果指定了属性值,则返回T进行计算。
我将继续这些实验,因为我觉得我还没有找到一个好的实际例子。(通常我看到人们通过集合对象在迭代中使用它)。
 
另一方面,对于额外的问题,您的示例确实帮助我理解了Start/End UndoMark的作用,因此我为自己编写了另一个测试代码:

(defun c:Test1(/ doc ins)
(if (zerop (getvar 'pdmode))
   (setvar 'pdmode 3)
   )
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(repeat 3
   (if (setq ins (getpoint "\nSpecify a point :"))
   (progn
       (vla-startundomark doc)
       (entmake (list '(0 . "POINT") (cons 10 ins)))
       (vla-endundomark doc)
       )
   )
   )
(princ)
)
;;                        ;;
(defun c:Test2(/ doc ins)
(if (zerop (getvar 'pdmode))
   (setvar 'pdmode 3)
   )
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(vla-startundomark doc)
(repeat 3
   (if (setq ins (getpoint "\nSpecify a point :"))
   (entmake (list '(0 . "POINT") (cons 10 ins)))
   )
   )
(vla-endundomark doc)
(princ)
)

很抱歉我的回复太晚了,我没有太多的空闲时间回复(但足以分析代码)。
如果我有什么发现,我会稍后发布,再次感谢!

Grrr 发表于 2022-7-5 17:54:37

你好
 
vla put LayerOn和vla put lock这两个函数始终返回nil,因此您的vl catch****示例在这种情况下确实有帮助。
 
以下代码也不会计算/到达第二行,因此变量“AcDocForB”始终为零
 
; if the active layer can be turned off, then lock it:
(defun C:test1 ( / ) ; Locked and turned off
(if
        (not
                (vl-catch-all-error-p ; if theres an error this returns T
                        (vl-catch-all-apply
                                '(lambda ()
                                        (vla-put-LayerOn (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-false)
                                )
                        )
                )
        )
        (vla-put-lock (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-true)
)
(princ)
); defun

(defun C:test2 ( / ) ; only turned off (NOT LOCKED!)
(if
        (vla-put-LayerOn (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-false)
        (vla-put-lock (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-true)
)
(princ)
)

Tharwat 发表于 2022-7-5 18:13:41

你好,塔瓦
谢谢,现在我知道我错了。。。我只是想问你,你是这样在控制台中检查它们的吗

; Start-End-UndoMark Testing:
; pick a series of entities, to draw for each one its boundingbox
; upon undoing (ctrl+Z), the Mark type "A" should undo all the created BoundingBoxes
; upon undoing (ctrl+Z), the Mark type "B" should undo one by one, every created BoundingBox
(defun C:test ( / AcDocForA AcDocForB ent vla-obj ll ur p1 p2 p3 p4 )
(vl-load-com) (setvar 'errno 0)
(or
        (setq AcDocForA (vla-get-ActiveDocument (vlax-get-acad-object))) ; put semicolon here
        (setq AcDocForB (vla-get-ActiveDocument (vlax-get-acad-object))) ; or put semicolon here
)

(if AcDocForA (vla-StartUndoMark AcDocForA)); Mark type: "A"

(while T
        (while
                (not
                        (and
                                (setq ent (car (entsel "\Pick an entity to draw its BBox: ")))
                                (setq vla-obj (vlax-ename->vla-object ent))
                        )
                )
                (if (or (member (getvar 'errno) '(7 52)) (null ent)) (princ "\nYou missed, try again!"))
        ); while
       
        (if AcDocForB (vla-StartUndoMark AcDocForB)); Mark type: "B"
       
        (vla-GetBoundingBox vla-obj 'll 'ur)
        (setq
                p1 (vlax-safearray->list ll)
                p2 (vlax-safearray->list ur)
                p3 (list (car p2) (cadr p1)) ; lr
                p4 (list (car p1) (cadr p2)) ; ul
        )
        (LWPoly-Red (list p1 p3 p2 p4) 1)
       
        (if AcDocForB (vla-EndUndoMark AcDocForB)); Mark type: "B"
       
); while T

(if AcDocForA (vla-EndUndoMark AcDocForA)); Mark type: "A"
(princ)
)

(defun LWPoly-Red (lst cls)
(entmakex
        (append
                (list
                        (cons 0 "LWPOLYLINE")
                        (cons 100 "AcDbEntity")
                        (cons 100 "AcDbPolyline")
                        (cons 62 1)
                        (cons 90 (length lst))
                        (cons 70 cls)
                )
                (mapcar (function (lambda (p) (cons 10 p))) lst)
        )
)
)

当谈到回报和评估时,我还是有点绿。
然而,我做了一系列关于vl catch-***函数的测试代码,在某些情况下还有lambda,所以这里有一些打印结果:

(or
        (setq AcDocForA (vla-get-ActiveDocument (vlax-get-acad-object)))
        (setq AcDocForB (vla-get-ActiveDocument (vlax-get-acad-object)))
)

这段代码实际上是2合1:(我没有发布两个单独的代码,而是只做了一个代码,其中分号必须放在您评论的以下行之一之前。
or subr在代码中没有实际用途(我只是为了更容易的修订而这样做-以后如果需要的话),而不会在代码中出现任何错误(我通常将代码的一部分包装在or中,因此这意味着有几个选项可以工作)。
另一种方法是通过键入“或者这也可以工作/或者这是另一个选项”在代码的每一行/块后面进行注释,但我发现使用实际的or函数更可读。
抱歉给你带来困惑-我有这些奇怪的习惯,这对你来说没有意义(包括(whilet…代码的一部分)。
顺便说一句,我测试了我的结束/撤消标记尝试,并更改了
_$ (not
                (vl-catch-all-error-p ; if theres an error this returns T
                        (vl-catch-all-apply
                                '(lambda ()
                                        (vla-put-LayerOn (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-false)
                                )
                        )
                )
        )
T
_$ (vla-put-LayerOn (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object))) :vlax-false)
nil
_$
因此,现在撤销操作正在正确执行。
非常感谢你的帮助!对不起,我的回答太愚蠢了,我太好奇了。

Grrr 发表于 2022-7-5 18:30:02

页: [1]
查看完整版本: vl catch all适用于lambda