Take this for what it's worth but if you are running into a problem with progn's limits it speaks more to the structure of one's programming than it does of said limits. Subtitle: Properly modularized code will never breach these limits. To wit, I have source code files approaching one hundred thousand lines of code and have never run up against any related limits.
An aside, progn is very useful for compartmentalizing one's code, especially if one is using a programmer's editor (*cough* UltraEdit) capable of intelligent code collapsing. See the following for scaled down example.
(progn ;; ======================================================= FILENAME.LSP
(progn ;; ======================================= Error Trapping Functions
(defun _Try ( try_statement / try_catch try_result )
;; Trap the execution af arbitry statements. Cache
;; errors in a LIFO error stack should examination
;; be desired by the caller.
;;
;; If the caller establishes a local var of *try_errors*
;; any cashed error msgs are solely for that function,
;; otherwise they are global.
(if
(vl-catch-all-error-p
(setq try_catch
(vl-catch-all-apply
(function
(lambda ( )
(setq try_result (eval try_statement))
)
)
)
)
)
(setq *try_errors* ;; lexical global
(cons
(list
try_statement
(vl-catch-all-error-message try_catch)
)
*try_errors*
)
)
)
try_result
)
)
(progn ;; ================================================== AEC Functions
(defun _GetAecDwgUnits ( doc / aec_vars_dwg_setup )
(_Try
'(setq aec_vars_dwg_setup
(vla-item
(vla-item (vla-get-dictionaries doc) "AEC_VARS")
"AEC_VARS_DWG_SETUP"
)
)
)
aec_vars_dwg_setup
)
(defun _KillAECBecauseItIsEvil ( doc / aec_vars_dwg_setup result )
;; Inform user of result, return kill state to caller.
(if (setq aec_vars_dwg_setup (_GetAecDwgUnits doc))
(progn
(princ "AecDwgUnits entry found")
(_Try
'(progn
(vla-delete aec_vars_dwg_setup)
(setq result (vlax-erased-p aec_vars_dwg_setup))
)
)
(if result
(princ " [deleted].\n")
(princ " [could not delete].\n")
)
result
)
(progn
(princ "No AecDwgUnits entry found.\n")
nil
)
)
)
)
(progn ;; =================================================== AEC Commands
(defun c:KillAEC ( / aec_vars aec_vars_dwg_setup )
(vl-load-com)
(_KillAECBecauseItIsEvil (vla-get-activedocument (vlax-get-acad-object)))
;; This would also work for the current drawing:
;;
;; (if (setq aec_vars (dictsearch (namedobjdict) "AEC_VARS"))
;; (if (setq aec_vars_dwg_setup
;; (cdadr (member '(3 . "AEC_VARS_DWG_SETUP") aec_vars))
;; )
;; (progn
;; (entdel aec_vars_dwg_setup)
;; (princ "AecDwgUnits havebeen removed.\n")
;; )
;; (princ "No worries, AecDwgUnits are not present.\n")
;; )
;; (princ "No worries, AecDwgUnits are not present.\n")
;; )
;;
;; Using the activeX method affords the ability to (potentially)
;; perform the "cleansing" via objectdbx, ergo the penning of
;; function _KillAECBecauseItIsEvil.
(princ)
)
)
(progn ;; ======================================================== On Load
(princ "FILENAME loaded\n")
(princ)
)
)
And yes, all my lisp source files start and end with a progn construct so I can copy the whole mess to the clipboard and paste to AutoCAD's command line, primarily useful when initially developing, but also useful to keep things segregated when combining files.
/2¢