Recursive Functions and return values

Discussion in 'AutoCAD' started by Jason Piercey, Dec 16, 2004.

  1. For the most part recursive functions make my head spin so
    perhaps I am overlooking the simple stuff here but, what is
    the proper way to handle return values from a recursive
    function that needs to build a list?

    Is it proper to define two functions, where the child function
    uses a global variable and the parent function declares that
    variable as local?

    In this example I just want to iterate a through subfolders and
    grab the name of each folder. I swiped most of the following
    code examples from Tony's map-folder function.


    ; Function to iterate through the specified folder and
    ; all of its subfolders to create a list of folder names
    ; Arguments:
    ; [rootFolder] - string, folder to start in
    ; return value is of no importance
    (defun getFolderNames-aux (rootFolder)
    (foreach subfolder (vl-directory-files rootFolder nil -1)
    (if (/= (substr subfolder 1 1) ".")
    (getFolderNames-aux (addpath rootFolder subfolder))
    )
    )
    (setq lst (cons rootFolder lst)); <<<- lst is global
    )


    ; Function to iterate through the specified folder and
    ; all of its subfolders to create a list of folder names
    ; Arguments:
    ; [rootFolder] - string, folder to start in
    ; return: list of strings
    ; Example: (getFolderNames "C:\\Temp")
    (defun getFolderNames (rootFolder / lst)
    (getFolderNames-aux rootFolder)
    lst
    )

    ; Tony Tanzillo
    ; Add element to path:
    ; [path] - string, path name
    ; [item] - string, sub folder
    ; return: string
    (defun addPath (path item)
    (if (eq (substr path (strlen path)) "\\")
    (strcat path item)
    (strcat path "\\" item)
    )
    )


    Comments?
     
    Jason Piercey, Dec 16, 2004
    #1
  2. Jason Piercey

    Doug Broad Guest

    Jason,
    Your routine works fine.

    A recursive routine just defines a function in terms of itself.
    The most important step is to check for the end condition.

    A recursive routine depends on the stack whether or not it
    returns a result in list form. To reduce the overhead, those
    variables that don't change in the recursive call are usually
    managed in a top level non-recursive main routine.

    For your example, two other possibilities are:

    ;;D. C. Broad, Jr - Demonstration to return subfolders
    ;;Format1: Return folder list in binary tree list
    (defun foldertree (root / fname)
    (if root
    (mapcar
    '(lambda (n)
    (setq dname (strcat root "/" n))
    (cons dname (foldertree fname)))
    (cddr (vl-directory-files root nil -1)))));;<<-return value is the list


    ;;-----------------------------------------------------

    ;;recursive subfunction for subfolderlst
    (defun subfolderlst1 (root)
    (if root
    (foreach n (cddr(vl-directory-files root nil -1))
    (setq fname (strcat root "\\" n))
    (setq lst (cons fname lst))
    (subfolderlst1 fname))))

    ;;Format2: Return folder list in flat form
    (defun subfolderlst (root / lst fname) ;;<<-locals are globals to subfolderlst1
    (subfolderlst1 root) ;ignore return value
    (reverse lst))

    -------------

     
    Doug Broad, Dec 16, 2004
    #2
  3. Jason Piercey

    Doug Broad Guest

    Oops, that should be:
    ;;D. C. Broad, Jr - Demonstration
    ;;Format1: Return folder list in binary tree list
    (defun foldertree (root / fname)
    (if root
    (mapcar
    '(lambda (n)
    (setq fname (strcat root "/" n))
    (cons fname (foldertree fname)))
    (cddr (vl-directory-files root nil -1)))))
     
    Doug Broad, Dec 16, 2004
    #3
  4. Thanks for the additional examples, Doug. Looks to
    me like one function is better than two. Although there
    could be some advantage to the nested list return value
    it might also be nice to have a flat list. 'suppose it would
    depend on the usage.

    Thanks again.
     
    Jason Piercey, Dec 16, 2004
    #4
  5. Doug,

    nice function. But take care: (vl-directory-files) does not
    return "." and ".." for the drive root.

    Stephan
     
    Stephan Koster, Dec 19, 2004
    #5
  6. Jason Piercey

    Doug Broad Guest

    Stephan,
    Thanks. Major Oops again there. ;-)
    So much for that demo.
     
    Doug Broad, Dec 19, 2004
    #6
  7. Jason Piercey

    John Uhden Guest

    From 3-07-2004

    ;; Function to create a tree-structured list of folders
    ;; given the parent folder as a Path.
    ;; Note that using a path of "" or "." or "\\" will exclude
    ;; the drive letter. McNeel's DOSLIB has a DOS_FULLPATH function
    ;; that can return such folders with drive designations.
    ;; (c) John F. Uhden, Cadlantic
    (defun @Folders (Path / Folders @Dirs)
    (defun @Dirs (Path / Dir Dirs)
    (and
    (= (type Path) 'STR)
    (or
    (/= (type DOS_FULLPATH) 'EXRXSUBR)
    (setq Path (DOS_FULLPATH Path))
    )
    (if (wcmatch Path ",*/,*\\")
    (setq Dir Path)
    (setq Dir (strcat Path "\\"))
    )
    (setq Dirs (vl-directory-files Dir "*.*" -1))
    (setq Folders (cons Path Folders))
    (setq Dirs (vl-remove-if '(lambda (x)(vl-position x '("." ".."))) Dirs))
    (mapcar '@Dirs (mapcar '(lambda (x)(strcat Dir x)) Dirs))
    )
    )
    (@Dirs Path)
    (reverse Folders)
    )
     
    John Uhden, Dec 20, 2004
    #7
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.