2.5.2.2. Iteraciones sobre los Elementos de una Secuencia


FOREACH

Evalúa cada expresión para todos los miembros de una lista
(foreach nombre lista expresión ...)
Recorre la lista, asignando sucesivamente cada elemento de la lista a lavariable nombre y evaluando de esta manera cada expresión para cada uno de los elementos de la listarepresentados por nombre. Puede especificar tantasexpresiones como desee. La función FOREACH devuelve elresultado de la última expresión evaluada.

VLAX-FOR

Efectúa una iteración a través de una colección de objetos evaluando cada expresión
(vlax-for símbolo colección [expresión1 [expresión2 ...]])
El argumento símbolo será asignado a cada Objeto-VLA de lacolección. El argumento colección representa un objeto ActiveXdel tipo colección. [expresión1 [expresión2 ...]]son las expresiones a evaluar. La función devuelve el valor de laúltima expresión evaluada para el último objeto de lacolección.

Ejemplos de iteraciones con FOREACH:

Esta pequeña subrutina, parte de un programa mayor, imprime enpantalla en formato de columna la lista que se le pase como argumento. En elejemplo se usa para imprimir de manera ordenada la lista de definicióndeuna entidad polilínea (AutoCAD 2000).

;;;Listado de entidades;;;Salida por pantalla(defun disp_l (lis_e /) (foreach sublista lis_e (print sublista) ) ;_ fin de foreach (princ) ;evita la repetición de la última línea) ;_ fin de defun

Command: (entget(car(entsel)))Select object: ((-1 . <Entity name: 1487558>) (0 . "LWPOLYLINE") (330 . <Entity name: 14874f8>) (5 . "2B") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 4) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 99.3432 134.975) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 130.202 185.828) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 202.747 163.648) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 269.336 215.041) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0))


La lista impresa en pantalla resulta difícil de leer, al no estar ordenada en columna

Command: (disp_l (entget(car(entsel))))(-1 . <Entity name: 1487558>)(0 . "LWPOLYLINE")(330 . <Entity name: 14874f8>)(5 . "2B")(100 . "AcDbEntity")(67 . 0)(410 . "Model")(8 . "0")(100 . "AcDbPolyline")(90 . 4)(70 . 0)(43 . 0.0)(38 . 0.0)(39 . 0.0)(10 99.3432 134.975)(40 . 0.0)(41 . 0.0)(42 . 0.0)(10 130.202 185.828)(40 . 0.0)(41 . 0.0)(42 . 0.0)(10 202.747 163.648)(40 . 0.0)(41 . 0.0)(42 . 0.0)(10 269.336 215.041)(40 . 0.0)(41 . 0.0)(42 . 0.0)(210 0.0 0.0 1.0)

Ejemplos de iteraciones con VLAX-FOR:

LISTADO DE CAPAS

Considerado desde el punto de vista de la jerarquía de objetosActiveX a la que podemos acceder con Visual LISP,

AutoCAD y sus dibujos consisten en muchos objetos diferentestales como tipos de líneas, capas, bloques, etc. Estos objetos seagrupan en colecciones. Las colecciones de Bloques (Block), Grupos (Group),Conjuntos de Selección (SelectionSet), EspacioModelo (ModelSpace) yEspacioPapel (PaperSpace) pueden contener una variedad de objetosgráficos diferentes, tales como líneas, arcos, texto, etc. Todaslas demás colecciones contienen objetos de un sólo tipo.
Las colecciones AutoCAD son de base cero, es decir que se enumeran a partir decero en sentido ascendente. Algunas colecciones poseen objetos de maneraautomática. Por ejemplo, la colección Layers (capas) simprecontiene un objeto capa de nombre "0", mientras que otras seencuentran vacías inicialmente.
Sutphin, J. AutoCAD 2000 VBA Programmers Reference, pág 47.

La rutina que exponemos a continuación extrae los nombres de lascapas de un dibujo aplicando la función VLAX-FOR a lacolección "Layers". Para obtener la colección "Layers" tenemos que recorrer la jerarquía deobjetos, a partir del único objeto accesible públicamente que esel objeto "Application" (Aplicación). La secuencia aseguir es la siguiente:

  1. Obtener el objeto "Aplicación": (vlax-get-acad-object)
  2. Obtener el objeto "Documento Activo" es decir, el dibujo en quese trabaja: (vla-get-ActiveDocument (vlax-get-acad-object))
    En caso de que se vaya a hacer referencia a este objeto en múltiplesocasiones, sería conveniente extraerlo una sóla vez y guardarloen una variable global:
    (setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object)))
    Esta línea la situamos fuera del defun. Se ejecutaría al cargar el programa.
  3. Obtener la colección "Layers" (Capas): (vlax-get *EsteDibujo* "Layers" )

Una vez obtenida la colección de capas se aplica mediante VLAX-FOR acada objeto-VLA de dicha colección la función
(setq ListaCapas (cons (vlax-get objeto-VLA "Name")*ListaCapas*))
Aquí primero extraemos el nombre de la capa. El nombre de cada objeto"Layer" se encuentra en la propiedad "Name" y se puedeextraer mediante (vlax-get objeto-VLA "Name"). Una vez obtenido elnombre de la capa, la incluimos mediante CONS en una variable local ListaCapas.Esta lista contendrá al terminar el ciclo de VLAX-FOR los nombres detodas las capas del dibujo activo. Ya para terminar, ordenamos la lista decapas mediante la función ACAD_STRLSORT. Esta lista serviría, porejemplo para llenar una casilla de lista en un cuadro de diálogo creadomediante el lenguaje DCL.

;;;Función ListaCapas;;;Devuelve una lista con los nombres de capas ordenados alfabéticamente;;;Obsérvese la posibilidad aquí demostrada de tener una función y una variable ;;;con idéntico nombre en un mismo entorno. Para ello será necesario que dicha ;;;variable, en este caso ListaCapas sea una variable local de la función.
(setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object))) ;se ejecuta previamente
(defun ListaCapas (/ ListaCapas) (vlax-for objeto-VLA (vlax-get *EsteDibujo* "Layers") (setq ListaCapas (cons (vlax-get objeto-VLA "Name") ListaCapas)) ;el mismo nombre se utiliza para la variable local que guarda ;temporalmente el listado de capas. ) ;_ fin de vlax-for (acad_strlsort ListaCapas)) ;_ fin de defun

Ejemplo de su utilización:

Command: (LOAD "C:/Mis documentos/Lisp/Fuentes/ListaCapas.lsp") LISTACAPASCommand: !*EsteDibujo*<#VLA-OBJECT IAcadDocument 00eb6aa4>Command: (listaCapas)("0" "DEFPOINTS" "DOTACIONES" "IT" "RBA" "RE-2" "RI" "RI-1" "RIA" "SG-EL" "SG-M" "SGP")

Más adelante se estudiará en más detalle el acceso alos objetos ActiveX desde Visual LISP.

Unos ejemplos para concluir...

Como ejemplo del empleo dentro de AutoCAD de estas últimas funcionesestudiadas, aquí van algunas pequeñas utilidades creadas porVladimir Nesterovsky. La primerade ellas, SEL2LST crea una lista de nombres de entidad a partir de unconjunto de selección. La segunda, LST2SEL, realiza el proceso inverso,creando un conjunto de selección a partir de una lista de nombres deentidad:

;;;SEL2LST;;;Recibe un conjunto de selección y devuelve una lista(defun sel2lst( sel / n l) (repeat (setq n (sslength sel)) (setq n (1- n) l (cons (ssname ss n) l)) ))

;;;LST2SEL;;;La función opuesta, recibe una lista y devuelve un conjunto de selección (defun lst2sel(l / ss) (setq ss (ssadd)) (foreach e l (ssadd e ss)) )

La siguiente función extrae el resto de una lista l a partirdel término n indicado en el primer argumento:

(defun cdnr ( n l ) (repeat n (setq l (cdr l)) ))

La función STRTOL recibe una cadena de caracteres s ydevuelve los caracteres aislados (cadenas de un sólo carácter)agrupados en una lista:

(defun strtol ( s / lst c ) (repeat (setq c (strlen s)) (setq lst (cons (substr s c 1) lst) c (1- c) ) ) lst)

Como se ve, esta puede ser otra vía para abordar el desarrollo delpredicado PALINDROMOP: obtener mediante STRTOL la cadena decaracteres en forma de lista y entonces compararla con la lista invertida por reverse:

(defun palindromop (cadena) (setq cadena (strtol cadena)) (equal cadena (reverse cadena)))
;; Created by Vladimir Nesterovsky ;; YOU MAY USE THIS FUNCTION AS IT IS FOR ANY PURPOSE;; AT YOUR OWN RISK IF YOU RETAIN THIS NOTICE COMPLETE ;; AND UNALTERED. NO WARRANTIES GIVEN WHATSOEVER.

Inicio |Índice | Continuar...