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错误消息
希望这有帮助。
因此,使用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!
在测试错误捕捉时,我取得了一点进展:
(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)
)
很抱歉我的回复太晚了,我没有太多的空闲时间回复(但足以分析代码)。
如果我有什么发现,我会稍后发布,再次感谢! 你好
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)
) 你好,塔瓦
谢谢,现在我知道我错了。。。我只是想问你,你是这样在控制台中检查它们的吗
; 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
_$
因此,现在撤销操作正在正确执行。
非常感谢你的帮助!对不起,我的回答太愚蠢了,我太好奇了。
页:
[1]