Author Topic: How to create subroutine?  (Read 8789 times)

0 Members and 1 Guest are viewing this topic.

HasanCAD

  • Swamp Rat
  • Posts: 1422
How to create subroutine?
« on: September 27, 2010, 09:43:10 AM »
I do not know if this question is logic or foolish but I want to learn how to create and use subroutine
for example this subroutine
Code: [Select]
(defun _FormatDate ( format )
    (menucmd (strcat "m=$(edtime,$(getvar,DATE)," format ")"))
  )

And used as
Code: [Select]
(_FormatDate "DD MON YYYY")
In this code
Code: [Select]
(defun c:myDate ( / _FormatDate _CreateLayer _CreateMText
pickedpoint
; mTextHeight is Global
)
  (vl-load-com)

  (defun _FormatDate ( format )
    (menucmd (strcat "m=$(edtime,$(getvar,DATE)," format ")"))
  )

  (defun _CreateLayer ( name colour )
    (or (tblsearch "LAYER" name)
      (entmakex  (list ...  ) ) ) )

  (defun _CreateMText ( point string layer height )
    (entmakex  (list ...   ) ) )

  (if
    (and
      (setq pickedpoint (getpoint "\nPick Point for Date: "))
      (setq mTextHeight
     (cond
       ((getdist (strcat "\nSpecify MText Height <" (rtos (setq mTextHeight (cond ( mTextHeight ) ( (getvar 'TEXTSIZE) )))) "> : "))) ( mTextHeight )))
    )
    (progn
      (_CreateLayer "Clock" 3)
      (_CreateMText (trans pickedpoint 1 0)
(strcat "{\\fTimes New Roman|b0|i0|c0|p34;\\C2;" [color=red](_FormatDate "DD MON YYYY") [/color] "}") "Clock" mTextHeight )
      )
    )
  (princ)
)

Regards

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: How to create subroutine?
« Reply #1 on: September 27, 2010, 11:10:47 AM »
It seems you already know how to create and use a subroutine. :-)
Your code basically looks OK to me.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to create subroutine?
« Reply #2 on: September 27, 2010, 11:37:42 AM »
That may not be his code but an example he is trying to understand. :-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

HasanCAD

  • Swamp Rat
  • Posts: 1422
Re: How to create subroutine?
« Reply #3 on: September 27, 2010, 04:06:06 PM »
That may not be his code but an example he is trying to understand. :-)
This code created by Lee and I want to understand how to create and use

BlackBox

  • King Gator
  • Posts: 3770
Re: How to create subroutine?
« Reply #4 on: September 27, 2010, 04:12:24 PM »
That may not be his code but an example he is trying to understand. :-)
This code created by Lee and I want to understand how to create and use

Maybe you should learn about attribution first, no?  :wink:
"How we think determines what we do, and what we do determines what we get."

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: How to create subroutine?
« Reply #5 on: September 27, 2010, 04:29:25 PM »
now that attribution is out of the way ..

exactly what don't you understand ??

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

BlackBox

  • King Gator
  • Posts: 3770
Re: How to create subroutine?
« Reply #6 on: September 27, 2010, 04:54:00 PM »
exactly what don't you understand ??

I cannot speak for the OP, but my first hurdle was to understand that a subroutine could simply be a routine that was called from within another routine, or be locally defined within the calling routine itself (as the OP's/Lee's? code demonstrates).

Second (for me) was understanding the terminology (i.e., Subroutine, Function, etc.)

Then I believe I needed to grasp that a routine does not need to be complete, or a full program itself so-to-speak (what do you mean it does one thing!? I have 50 more to do!), and could be responsible for only one particular function (to return a result) in order to be stored to a variable (i.e., a Toolbox function).

"How we think determines what we do, and what we do determines what we get."

Lee Mac

  • Seagull
  • Posts: 12916
  • London, England
Re: How to create subroutine?
« Reply #7 on: September 27, 2010, 06:41:50 PM »
I really like subroutines.

They save a ton of time writing programs and also make programs easier to follow as each step is compartmentalised (phew..).

- Time saving because you don't have to write the same functionality over and over again, you can just look into your toolbox/library and dig out the code that does what you want.

- Programs are easier to follow because each subfunction has its own purpose and so, once the subfunctions are understood, the program can be read like a book.

On creating subfunctions...

Think about the bare essentials needed for the functionality you require. I'm talking about the information that the function can't live without. These are your arguments. For Example, the text string for a subfunction to create a text object, or even the point for the same subfunction.

Try to make the subfunction as generic as possible. Don't specialise. This will make it more useful over a wider range of functions. Going back to the Text object creation: don't hardcode the layer into the function, supply it as an argument. Then - should another program call the subfunction but want the object on a different layer than before, the subfunction needn't be modified, but rather called with different data.

Anyway, I shan't waffle, I'm sure others have more informative sentiments to add.

Lee Mac

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: How to create subroutine?
« Reply #8 on: September 28, 2010, 10:40:40 AM »
Thought should be given to whether the sub will be fail-proof or not.  In some circumstances you always want the sub to return, in which case agressive error handling should be implemented.  Other times it might make more sense to skip the overhead and just have it halt execution (with an appropriate warning, of course).
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

JohnK

  • Administrator
  • Seagull
  • Posts: 10652
Re: How to create subroutine?
« Reply #9 on: September 28, 2010, 12:24:53 PM »
Thought should be given to what the sub will return. boole, int, string, etc. as well and how its used--or can be used--in the main (one of the reasons why i have some hesitations for using a boole instead of a conditional--but some people think a boole is more fancy to use and will gain them some clout amongst forum users-).
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: How to create subroutine?
« Reply #10 on: September 28, 2010, 01:02:34 PM »
Thought should be given to what the sub will return. boole, int, string, etc. as well and how its used--or can be used--in the main (one of the reasons why i have some hesitations for using a boole instead of a conditional--but some people think a boole is more fancy to use and will gain them some clout amongst forum users-).

The lack of a distinct "false" equivalent to "T" instead of the more general purpose "nil" has bitten me more than once...  :whistle:
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to create subroutine?
« Reply #11 on: September 28, 2010, 01:05:10 PM »
?? Not sure I follow.

(null nil) >> T
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Krushert

  • Seagull
  • Posts: 13679
  • FREE BEER Tomorrow!!
Re: How to create subroutine?
« Reply #12 on: September 28, 2010, 06:23:07 PM »
When should one "store" a subroutine(s) inside the routine or outside and called in.  

I place all my subroutines in the routine but I got a real mess brewing with a handful of routines that used the same subroutines.  I am thinking that parse out the subroutines.  :oops: :?
I + XI = X is true ...  ... if you change your perspective.

I no longer CAD or Model, I just hang out here picking up the empties beer cans

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to create subroutine?
« Reply #13 on: September 29, 2010, 10:35:01 AM »
Well there are plenty of examples of subroutines or sub-functions. I will give you my short explanation.

A Sub routine/function is nothing more than a function called nu another function as opposed to being called form the command line.
That function called form the command line (could be a menu or button doing the calling) is the TOP function and when completed
this function should return you to the command line.

Any functions called from this function directly or indirectly may be called a sub-function.

There you have it.

In order to use these functions you must call them with the correct name and the correct number of arguments.
The sub-function may return a useful value for your routine to make use of. More on that later.

The name of functions may be c:MyFunction ,(defun  c:MyFunction (), in which case the routine is usually a top function and may be called from the
command line by entering MyFunction  You may also call this function from another function this way (MyFunction).
Note that arguments are not used in this situation so any variables must be global variables or created by the function c:MyFunction.
That is not the usual way a function is called. The more common situation is to create a function named MyFunction, (defun  MyFunction (),

The Global variable vs Local variable has been discussed so I won't relive it here except to say that the Global variables should be
used sparingly as it is good programming practice.

Therefore you should try to pass variables to your subroutine as arguments. So MyFunction should be defined like so:
(defun  MyFunction (argument1 argument2 argument3 / localVariables)
Some people test the variable type for there arguments like (= (type argument1) 'STR) for a string and then correct it or
return an error flag. Others feel that the subroutine should fail so you can fix the calling function so that it sends the expected
variable type. Most of the time I prefer the latter. But there are times when you want a very versatile subroutine that will
except say an <entity name> or <vla object> type and make the conversion as needed in the sub-function.


As for When to use a sub-function, that is a personal preference.
I use them if I repeat a process more than once. Although if the code lines are few & they are repeated two or three times I may
not create a sub-function. Another case is when I want the code to appear clear & straight forward to the reader I may elect
to remove some code to a sub-function just for readability.
An example is making a polyline using entmake. The code takes up space & therefore I may use a sub-function MakePline to
simplify the code appearance.

Code: [Select]
               ((setq newpline ([b]makePline[/b] space (append RibPtLst1 (reverse RibPtLst2))))
                (vla-put-layer newpline Flexlayer)
                (if FlexColor
                  (vla-put-color newpline FlexColor)
                )
               
See how it simplifys the apearance:

Code: [Select]
  ;;  Expects pts to be a list of 2D or 3D points
  (defun makePline (spc pts)
    (if (= (length (car pts)) 2) ; 2d point list
      (setq pts (apply 'append pts))
      (setq
        pts (apply 'append (mapcar '(lambda (x) (list (car x) (cadr x))) pts))
      )
    )
    (setq
      pts (vlax-make-variant
            (vlax-safearray-fill
              (vlax-make-safearray vlax-vbdouble (cons 0 (1- (length pts))))
              pts
            )
          )
    )
    (vla-addlightweightpolyline spc pts)
  )
 
 
Usually you make all your sub-functions local to the main Lisp routine.
If the function is used by many of your Lisp's then you may want to create a file of the common sub-functions and
load the when you start a DWG. I do this with a lisp called AlansAutoload.lsp which is loaded in every DWG.

Here is a sample of whats in the lisp

Code: [Select]
(princ "\nAlansAutoLoad lisp is starting...>>>>>>>>>>>>>>>")
(setq *usermode* "CAB") ; turn on debug mode
;;  See Debug.lsp for use

(vl-load-com)

;;; ===============================================
;;;    Lisp Routine Loader
;;;    AUTOLOAD only loads the routine when needed
;;; ===============================================

;;;------  Lisp name -- Function name("n1$" "n2$") -------  Discription  -----------------------
(AUTOLOAD "AlignAllDCL CAB" '("AlignAll")) ; Align Text or Objects
(AUTOLOAD "MacAlignV5" '("MacAlign"))
(AUTOLOAD "MacAlignV5(mtext)" '("MacAlignm"))
(AUTOLOAD "Angle Bisect" '("BISECT")) ;
(AUTOLOAD "AreaPrt" '("AreaPrt")) ; Print the Area of "POLYLINE"  "LWPOLYLINE" "CIRCLE" "ELLIPSE"
(AUTOLOAD "arrow line" '("arw")) ; draw a arrow line on stairs, plan view
(AUTOLOAD "ArrowDrainage" '("darrow")) ; draw a drainage arrow
(AUTOLOAD "Arrows by Tim W" '("DPA")) ; draw a hollow arrow, by Tim Willey


(load "vl-SubRoutines.lsp" "vl-SubRoutines.lsp not found")
(load "ACADSet_Variables CAB" "ACADSet_Variables CAB.lsp not found") ; loads & runs
(load "QLeader CAB" "QLeader CAB.lsp not found") ; loads qleader Set & Get
;;  Set my default qleader settings
(acet-ql-set '((40 . 0.0) (60 . 0) (61 . 0)
      (62 . 1) (63 . 1)   (64 . 0) (65 . 0)
      (66 . 0) (67 . 3)   (68 . 0) (69 . 0)
      (70 . 0) (71 . 1)   (72 . 0) (170 . 0)))

(defun C:DOB() (setq ss (ssget)) (command "DRAWORDER" ss "" "B") (princ) )
(defun C:DOF() (setq ss (ssget)) (command "DRAWORDER" ss "" "F") (princ) )
(defun C:DOA() (setq ss (ssget)) (command "DRAWORDER" ss "" "A") (princ) )
(defun C:DOU() (setq ss (ssget)) (command "DRAWORDER" ss "" "U") (princ) )

;;Make 2D point from 3D point
(defun 3dP->2dP (3dpt) (list (car 3dpt) (cadr 3dpt)))

(defun dxf (code lst) (cdr (assoc code lst)))

;;;  Convert  Radians to Degrees
  (defun rtd (r) (* 180.0 (/ r pi)))

;;; Convert DEGREES TO RADIANS
  (defun dtr (d) (/ (* d pi) 180.0))
 
 
(defun c:ResetCAB()
  (load "AlansAutoLoad.lsp")
  (princ)
)
;; ****************
;;  End Of File
;; ****************


That's all I have time for today.
PS  I created this over several short sessions so there may be some rambling. :-)
( My 2 Cents)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Krushert

  • Seagull
  • Posts: 13679
  • FREE BEER Tomorrow!!
Re: How to create subroutine?
« Reply #14 on: September 29, 2010, 12:47:56 PM »
No rambling that I saw.  Just good information. 
When I get time to start reworking those routines I will be back with questions. 
Thanks.
I + XI = X is true ...  ... if you change your perspective.

I no longer CAD or Model, I just hang out here picking up the empties beer cans