How to Repeat parts of a Program

How to Repeat parts of a Program
Site menu


Login form


Search


Site friends
  • Create your own site


  • Statistics

    Total online: 1
    Guests: 1
    Users: 0


    Welcome, Guest ยท RSS 03 December 2024
    How to Repeat parts of a Program


    Another useful aspect to programs such as AutoLISP is their ability to perform repetitive tasks. For example, suppose you want to be able to record a series of keyboard entries
    as a macro. One way to do this would be to use a series of Getstring functions as in the following:
    (Setq str1 (getstring "\nEnter macro: "))
    (Setq str2 (getstring "\nEnter macro: "))
    (Setq str3 (getstring "\nEnter macro: "))
    (Setq str4 (getstring "\nEnter macro: "))
    .
    .
    .


    Each of the str variables would then be combined to form a variable storing the keystrokes. Unfortunately, this method is inflexible. It requires that the user input a fixed
    number of entries, no more and no less. Also, this method would use memory storing each keyboard entry as a single variable.
    It would be better if you had some facility to continually read keyboard input regardless of how few or how many different keyboard entries are supplied. The While function
    can be used to repeat a prompt and obtain data from the user until some test condition is met. The program in figure 5.9 is a keyboard macro program that uses the while function.

    ;Program to create keyboard macros -- Macro.lsp


    (defun C:MACRO (/ str1 macro macname)
    (setq macro '(command)) ;start list with command
    (setq macname (getstring "\nEnter name of macro: ")) ;get name of macro
    (while (/= str1 "/") ;do while str1 not eq. /
    (setq str1 (getstring "\nEnter macro or / to exit: " )) ;get keystrokes
    (if (= str1 "/")
    (princ "\nEnd of macro ") ;if / then print message
    (Setq macro (append macro (list str1))) ;else append keystrokes to
    ) ;end if macro list
    );end while
    (eval (list 'defun (read macname) '() macro)) ;create function
    ) ;end macro

    A program to create keyboard macros


    Using the While Function
    The syntax for while is:
    (while (test expression)
    (expression 1)(expression 2)(expression 3) ....
    )

    The first argument to while is a test expression. Any number of expressions can follow. These following expressions are evaluated if the test returns a non-nil value.
    Open an AutoLISP file called Macro.lsp and copy the contents of figure 5.8 into this file. Since this is a larger program file than you worked with previously, you may want to make a print out of it and check your print out against figure 5.8 to make sure you haven't made any transcription errors. Go back to your AutoCAD Chapt5 file. Now you will use the macro program to create a keyboard macro that changes the last object drawn to a layer called hidden. Do the following:

    1. Draw a diagonal line from the lower left corner of the drawing area to the upper right corner.
    2. Load the Macro.lsp file
    file:///E|/Dhimant/Support/Programming/Dhimant's%20Autolisp/Chapter 5.htm (16 of 25)27/08/2008 2:08:16 PM
    Chapter 5: Making Decisions with AutoLISP
    3. Enter Macro at the command prompt.
    4. At the following prompt:
        Enter name of macro:
    5. Enter the word chlt. At the prompt:
        Enter macro or / to exit:
    6. Enter the word CHANGE.

    The Enter macro prompt appears again. Enter the following series of words at each Enter macro prompt:
    Enter macro or / to exit: L
    Enter macro or / to exit: [press return]
    Enter macro or / to exit: P
    Enter macro or / to exit: LT
    Enter macro or / to exit: HIDDEN
    Enter macro or / to exit: [press return]
    Enter macro or / to exit: /
    This is where the while function takes action. As you enter each response to the Enter macro prompt, while test to see if you entered a forward slash. If not, it evaluates the
    expressions included as its arguments. Once you enter the backslash, while stops its repetition. You get the prompt:
    End of macro CLAYER
    The input you gave to the Enter macro prompt is exactly what you would enter if you had used the change command normally. Now run your macro by entering:
    chlt


    The line you drew changes to the hidden line type.
    When Macro starts, it first defines two variables def and macro.
    (setq def "defun ")
    (setq macro '(command))
    Def is a string variable that is used later to define the macro. Macro is the beginning of a list variable which is used to store the keystrokes of the macro. The next line prompts the user to enter a name for the macro.
    (setq macname (getstring "\nEnter name of macro: "))
    The entered name is then stored with the variable macname. Finally, we come to the while function.
    (while (/= str1 "/")
    The while expression is broken into several lines. The first line contains the actual while function along with the test expression. In this case, the test compares the variable str1
    with the string "/" to see if they are not equal. So long as str1 is not equal to "/", while will execute the arguments that follow the test. The next four lines are the expressions to
    be evaluated. The first of these lines prompts the user to enter the text that compose the macro.
    (setq str1 (getstring "\nEnter macro or / to exit: " ))
    When the user enters a value at this prompt, it is assigned to the variable str1. The next line uses an if function to test if str1 is equal to "/".
    (if (= str1 "/")
    If the test results in T, the next line prints the string End of macro.
    (princ "\nEnd of macro ")
    This expression prints the prompt End of macro to the prompt line. If the test results in nil, the following line appends the value of str1 to the existing list macro.
    (Setq macro (append macro (list str1)))
    The append function takes one list and appends its contents to the end of another list. In this case, whatever is entered at the Enter macro prompt is appended to the variable
    macro. Each time a new value is entered at the Enter macro prompt, it is appended to the variable macro creating a list of keyboard entries to be saved (see figure 5.10).
    file:///E|/Dhimant/Support/Programming/Dhimant's%20Autolisp/Chapter 5.htm (18 of 25)27/08/2008 2:08:16 PM
    Chapter 5: Making Decisions with AutoLISP
    Figure 5.10: Appending lists to other lists
    file:///E|/Dhimant/Support/Programming/Dhimant's%20Autolisp/Chapter 5.htm (19 of 25)27/08/2008 2:08:16 PM
    Chapter 5: Making Decisions with AutoLISP
    The next two lines close the if and while expressions. Note that comments are used to help make the program easier to understand.
    );end if
    );end while
    The last line combines all the elements of the program into an expression that, when evaluated, creates a new macro program.
    (eval (list (read def) (read macname) '() macro))
    )

    shows gives breakdown of how this last line works.


    How the macro is defined

    The read function used in this expression is a special function that converts a string value into a symbol. If a string argument to read contains spaces, read will convert the first
    part of the string and ignore everything after the space.
    The while expression does not always include prompts for user input. Figure 5.12 shows a simple program that inserts a sequence of numbers in increasing value. Each number
    is increased by one and they are spaces 0.5 units apart. The user is prompted for a starting point and a first and last number. Once the user inputs this information, the program

    calculates the number to be inserted, inserts the number using the text command, calculates the next number and so on until the last number is reached.
    ;Program to draw sequential numbers -- Seq.lsp
    (defun C:SEQ (/ pt1 currnt last)
    (setq pt1 (getpoint "\nPick start point: "))
    (setq currnt (getint "\nEnter first number: "))
    (setq last (getint "\nEnter last number: "))
    (command "text" pt1 "" "" currnt) ;write first number
    (while (< currnt last) ;while not last number
    (setq currnt (1+ currnt)) ;get next number
    (command "text" "@.5<0" "" "" currnt) ;write value of currnt
    );end while
    );end seq

    Sequential number program


    This program expects the current text style to have a height of 0.
    Using the Repeat Function
    Another function that performs recursions is the repeat function. Repeat works in a similar way to While but instead of using a predicate to determine whether to evaluate its
    arguments, repeat uses an integer value to determine the number of times to perform an evaluation. The syntax for repeat is:
    (repeat [n]
    (expression 1)(expression 2) (expression 3) ...
    )
    The n above is an integer or a symbols representing an integer.


    The program in Figure 5.13 shows the sequential number program using repeat instead of while. When run, this program appears to the user to act in the same way as the
    program that uses while.

    ;Program to write sequential numbers using Repeat
    (defun C:SEQ (/ pt1 currnt last)
    (setq pt1 (getpoint "\nPick start point: "))
    (setq currnt (getint "\nEnter first number: "))
    (setq last (getint "\nEnter last number: "))
    (command "text" pt1 "" "" currnt) ;write first number
    (repeat (- last currnt) ;repeat last - currnt times
    (setq currnt (1+ currnt)) ;add 1 to currnt
    (command "text" "@.5<0" "" "" currnt) ;write value of currnt
    );end repeat
    );end seq
    Figure 5.13: Sequential number program using repeat
    Using Test Expressions
    So far, we have shown you functions that perform evaluations based on the result of some test. In all the examples, we use predicates and logical operators for testing values.
    While predicates and logical operators are most commonly used for tests, you are not strictly limited to these functions. Any expression that can evaluate to nil can also be used
    as a test expression. Since virtually all expressions are capable of returning nil, you can use almost any expression as a test expression. The following function demonstrates
    this point:
    (defun MDIST (/ dstlst dst)
    (setq dstlst '(+ 0))
    file:///E|/Dhimant/Support/Programming/Dhimant's%20Autolisp/Chapter 5.htm (23 of 25)27/08/2008 2:08:16 PM
    Chapter 5: Making Decisions with AutoLISP
    (while (setq dst (getdist "\nPick distance or Return to exit: "))
    (Setq dstlst (append dstlst (list dst)))
    (princ (Eval dstlst))
    );end while
    );end MDIST


    This function gives the user a running tally of distances. The user is prompted to pick a distance or press Return to exit. if a point is picked, the user is prompted for a second
    point. The distance between these two points is displayed on the prompt. The Pick distance prompt appears again and if the user picks another pair of points, the second
    distance is added to the first and the total distance is displayed. This continues until the user presses return. The following discussion examines how this function works.
    As usual, the first line defines the function. The second line creates a variable called dstlst and gives it the list value (+ 0).


    (defun MDIST (/ dstlst dst)
    (setq dstlst '(+ 0))
    The next line begins the while portion of the program. Instead of a predicate test, however, this expression uses a setq function.
    (while (setq dst (getdist "\nPick point or Return to exit: "))
    As long as points are being picked, getdist returns a non-nil value to setq and while repeats the evaluation of its arguments. When the user presses return, getdist returns nil and while quits evaluating its arguments. We see that while is really only concerned with nil and non-nil since the test expression in this example returns a value other than T.


    The next few lines append the current distance to the list dstlst then evaluates the list to obtain a total:


    (Setq dstlst (append dstlst (list dst)))
    (princ (eval dstlst))
    The function princ prints the value obtained from (eval dstlst) to the prompt (see Figure 5.14).
    file:///E|/Dhimant/Support/Programming/Dhimant's%20Autolisp/Chapter 5.htm (24 of 25)27/08/2008 2:08:16 PM


    ;Program to measure non-sequential distances -- Mdist.lsp
    (Defun C:MDIST (/ dstlst dst)
    (setq dstlst '(+ )) ;create list with plus

    ;while a return is not entered ...
    (while (setq dst (getdist "\nPick point or Return to exit: "))
    (Setq dstlst (append dstlst (list dst))) ;append distance value
    (princ (Eval dstlst)) ;print value of list
    );end while
    );end mdist

    The Mdist function


    Conclusion
    You have been introduced to several of the most useful functions available in AutoLISP. You can now begin to create functions and programs that will perform time
    consuming, repetitive tasks quickly and easily. You can also build-in some intelligence to your programs by using decision making functions. You may want to try your hand
    at modifying the programs in this chapter. For example, you could try to modify the Mdist function to save the total distance as a global variable you can later recall.
    In the next chapter, you will get a brief refresher course in geometry.