Identificar referencias mutuas en tipos de datos
En las definiciones de tipos de datos ocurre una referencia mutua cuando la definición de un tipo de dato se refiere a otro tipo de dato que, a su vez, hace referencia al primero, sea directa o indirectamente, formando lo que se conoce como un ciclo de referencia mutua.
En esta entrada se muestran dos ejemplos de identificación de referencias mutuas; uno con referencias directas y otro con indirectas. Para los dos se usan árboles de aridad arbitraria, que son una de las estructuras donde se dan referencias mutuas.
Referencias directas
Miremos esta representación de una jerarquía de archivos de sistema:
(define-struct elt (name data subs)) ;; Element is (make-elt String Integer ListOfElement) ;; interp. An element in the file system, with name, and EITHER data or subs. ;; If data is 0, then subs is considered to be list of sub elements. ;; If data is not 0, then subs is ignored. ;; ListOfElement is one of: ;; - empty ;; - (cons Element ListOfElement) ;; interp. A list of file system Elements
En este caso, la definición del tipo de dato
Element
se refiere al tipo de dato
ListOfElement
. Y este último se refiere al tipo de
dato Element
. Entonces, estas dos referencias
forman un ciclo de referencias mutuas como se ve en la
Figura 1.

Referencias indirectas
En este caso no todos los ciclos de referencias mutuas son fáciles de encontrar. Las siguientes definiciones de datos son un ejemplo donde ocurren ciclos de referencias mutuas formados tanto por referencias directas como indirectas:
(define-struct woman (name sons daughters)) ;; Woman is (make-woman String ListOfMan ListOfWoman) ;; interp. a woman with name, list of her sons, and list of her daughters (define-struct man (name sons daughters)) ;; Man is (make-man String ListOfMan ListOfWoman) ;; interp. a man with name, list of his sons, and list of his daughters ;; ListOfWoman is one of: ;; - empty ;; - (cons Woman ListOfWoman) ;; interp. a list of women ;; ListOfMan is one of: ;; - empty ;; - (cons Man ListOfMan) ;; interp. a list of men
Dibujemos todos los tipos de referencias que se ven a primera vista:

-
Woman
hace referencia aListOfMan
y aListOfWoman
. -
Man
hace referencia aListOfMan
y aListOfWoman
. -
ListOfWoman
hace referencia aWoman
y a sí mismo. -
ListOfMan
hace referencia aMan
y a sí mismo.
Hay ciclos de referencias mutuas obvios entre
Woman
y ListOfWoman
, y entre
Man
y ListOfMan
:

Y resulta que las referencias (R) restantes, que parecen referencias comunes y corrientes, forman, indirectamente, ciclos de referencias mutuas. Para encontrar este tipo de ciclos escondidos, se puede hacer lo siguiente:
- Ponga el dedo al inicio de una línea de referencia.
- Siga la línea de referencia hasta el final.
- Intente llegar al inicio de la referencia siguiendo otras líneas de referencia (de cualquier tipo).
Si puede volver al principio, las aparentes líneas de referencia ordinarias que siguió para lograrlo son realmente referencias mutuas.
Usando los tres pasos anteriores, puede verificar que las referencias que quedan en la Figura 3 son referencias mutuas:
-
Empiece en
Woman
. -
Siga la referencia a
ListOfMan
. -
Siga la referencia mutua a
Man
. -
Siga la referencia a
ListOfWoman
. -
Siga la referencia mutua a
Woman
.
Volvió al inicio. Entonces, todas las líneas que siguió para llegar al principio se convierten en referencias mutuas. Finalmente:
-
Empiece en
Man
. -
Siga la referencia a
ListOfWoman
. -
Siga la referencia mutua a
Woman
. -
Siga la referencia a
ListOfMan
. -
Siga la referencia mutua a
Man
.
Aquí también, llegó al principio. Entonces el diagrama de referencias debería verse realmente así:

A la hora de diseñar funciones que operen sobre estos tipos de datos, todas estan referencias deberían poder identificarse también en el código como invocaciones a funciones que operan sobre el tipo de dato referenciado.
Fuentes de consulta
- Módulo Mutual Reference del curso How To Code: Complex Data, de la University of British Columbia.
Temas relacionados: