|
Adolfo Di Mare |
Resumen |
Abstract |
Se muestra cómo es posible utilizar iteradores Java para contenedores de la biblioteca estándar C++, los que son más simples que los usados usualmente en programas C++. | We show how to use Java iterators for the C++ standard library containers, which are simpler than those usually used in C++ programs. |
Introducción |
Introduction |
Abstracción es una concepto mencionado cuando se habla de construcción de programas pues no es posible producir algo sin antes tener una idea, aunque sea muy general, que defina aquello que se desea crear. El estudioso de la programación conoce las formas de abstracción que se usan para programar: abstracción de datos, abstracción de procedimientos, abstracción de iteración y abstracción de jerarquías de tipos de datos [LG-2000]. Es fácil dejar de lado la abstracción de iteración porque su implementación se hace usando abstacción de datos, pero eso no le disminuye su importancia. | Abstraction is a concept mentioned when talking about building programs because it is not possible to produce something without having an idea first, although very general, to define what it is to be created. The studious of programming knows which abstractions are used to program: data abstraction, procedural abstraction, iteration abstraction, and data type hierarcal abstraction [LG-2000]. It's easy to ignore iteration abstraction because it is implemented using data abstraction, but that does not diminishes its importance. |
El uso de la abstracción de iteración en la construcción de programas no es reciente, y ya se ha discutido mucho cómo se debe incorporarla en un lenguaje de programación [Parnas-1983]. Las ideas que han sido implementadas van desde la propuesta de los generadores de Alphard [SW-1977], o los iteradores [MOSS-1996], hasta construcciones más recientes como las propuestas para Chapel [JCD-2006]. También se ha argumentado que es necesario especificar iteradores para poder facilitar el razonamiento sobre la correctitud de los programas [Weide-2006]. Si se pone en el iterador la inteligencia para partir una tarea en pedazos que pueden resolverse concurrentemente, se puede usar la abstracción de iteración para aumentar el paralellismos de los programas usando técnicas como "MapReduce" [DG-2004] (cliente-servidor o maestro-esclavo), y también se puede usar iteradores sobre conjuntos como se hace en el modelo de programación Galois [KPWRBC-2009]. | The use of iteration abstraction for program construction is not recent, and much has already been discussed on how to incorporate it into a programming language [Parnas-1983]. The ideas that have been implemented, ranging from the proposed generators for Alphard [SW-1977], or iterators [MOSS-1996], to more recent constructions as those proposed for Chapel [JCD-2006]. It has also been argued that it is necessary to specify iterators in order to facilitate reasoning about the correctness of programs [Weide-2006]. If the intelligence to split a task into pieces that can be solved concurrently is in the iterator, the iteration abstraction can be used to increase the concurrency of programs using techniques such as "MapReduce" [DG-2004] (client-server or master-slave), or by using set iterators as it is done in the Galois programming model [KPWRBC-2009]. |
La popularidad actual de los lenguajes Java y C++ saca a relucir 2
maneras de implementar la abstracción de iteración.
Usando sobrecarga de operadores y plantillas, los iteradores C++
se ven como punteros con los que se accede a los valores de una
colección. Java toma un camino más a tono con la
Programación Orientada a los Objetos y representa un
iterador como una clase externa, que contiene 2 operaciones
fundamentales:
{
hasNext()
next()
} .
Los iteradores Java son una realización concreta de ideas
bien discutidas
[ZC-1999] o
[Eckart-1987], con la gran cualidad de
que estos iteradores son muy simples lo que facilita su
especificación y uso. Java no incluye contrucciones
sintácticas especiales para iteración debido a que
la pareja
{ hasNext() next() }
es adecuada para implementar tanto iteradores como generadores.
Por ejemplo, a diferencia de los iteradores CLU
[LSAS-1977], los iteradores Java
sí permiten doble iteración sobre una
colección, como se muestra más adelante en la
implementación genérica del método
"isPalindrome() "
(ver Figura 3).
|
The current popularity of Java and C++ brings out 2 ways to
implement the iteration abstraction. Using operator overloading
and templates, C++ iterators act as pointers used to access values
from a collection. Java is more in tune with Object Oriented
Programming and represents an iterator as an external class that
has 2 basic operations:
{
hasNext()
next()
} .
Java iterators are a concrete realization of ideas well discussed
[ZC-1999] or
[Eckart-1987];
a great quality of these iterators is that they are very simple
which facilitates their specification and usage. Java does not
include special syntactic constructions for iteration because the
pair
{ hasNext() next() }
is adequate to implement both iterators and generators. For
example, unlike CLU iterators
[LSAS-1977], Java iterators do allow
double iteration over a collection, as it is shown later in the
generic implementation of method "isPalindrome() "
(see Figure 3).
|
Todos estos argumentos sirven para afirmar que hay consenso en que
la abstracción de iteración es necesaria para
construir programas. En el contexto del lenguaje C++ se puede
avanzar en el uso de la abstracción de iteración al
incorporar el patrón de iteración Java en el uso
cotidiano del lenguaje, tanto al construir programas como al usar
la biblioteca estándard de C++. En este trabajo se
demuestra que C++ tiene suficiente poder expresivo para que
cualquier programador use iteradores o generadores que siguen el
patrón de lo iteradores de Java. Adicionalmente, el
compilador C++ puede verificar que un objeto marcado
"const " sea modificado, lo que disminuye los
problemas que se han detectado para iteradores implementados en
otros lenguajes
[HPS-2002]. La solución propuesta
aquí es simple y compacta, pues la
implementación completa cabe totalmente en un el archivo de
encabezado
"iterJava.h ",
lo que facilita mucho la incorporación del patrón de
iteración en programas C++ porque basta incluir ese archivo
de encabezado para usar iteradores { hasNext() next()
} en C++ (por eso no es necesario ligar ninguna biblioteca
adicional al programa C++).
|
All these arguments are used to assert that there is agreement
that the iteration abstraction is needed to build programs. In the
context of the C++ language it is possible to advance in the use
of the iteration abstraction by incorporating the Java iteration
pattern in the daily use, both to build programs an with the C++
standard library. In this paper it is shown that C++ has enough
expressive power for any programmer to use iterators and
generators that follow the Java iterator pattern. Additionally,
the C++ compiler can verify that an object marked
"const " is not modified, reducing the problems that
have been identified for iterators implemented in other languages
[HPS-2002]. The solution proposed here is
simple and compact as the complete implementatio fits in a single
header file
"iterJava.h ",
which greatly facilitates the incorporation of the iteration
pattern in C++ programs because its enough to include this header
file to use the { hasNext() next() } iterators in C++
(this is why it is not necessary to link any library to the C++
program).
|
Uso de iteradores |
Iterator usage |
Para usar iteradores Java en C++ basta crear un envoltorio C++, en la forma de una plantilla, que permita usar los iteradores Java para los contenedores C++ más populares. Las operaciones de un iterador Java son las siguientes [Java-2009]: | As Java iterators are very simple, it is a good idea to be able to use them in C++. To achieve this goal its is enough to create a C++ wrapper, as a template, to access the more popular C++ containers with Java iterators. The operations of a Java iterator are these [Java-2009]: |
Para recorrer cualquier contenedor de la biblioteca estándar C++ se requiere utilizar 2 iteradores [Str-1998]. El primero indica cuál es el siguiente valor del contenedor que será usado y el segundo es una marca fuera del rango a recorrer. El ciclo de iteración C++ ha concluido cuando el primer iterador alcanza al segundo. | To traverse any C++ standard library container 2 iterators are required [Str-1998]. The first references the next value in the container to be used and the second is a mark outside the iteration range. The C++ iteration cycle is completed when the first iterator reaches up to the second. |
{ // [0] [1] [2] [3] [4] [5] int V[] = { 0 , 1 , 2 , 3 , 4 }; int *it = &V[0]; // it = V+0; int *itEND = &V[5]; // itEND = V+dim(V) for ( it = &V[0]; it != itEND ; ++it ) { std::cout << (*it); } } |
Los iteradores de la biblioteca estándar C++ funcionan como
un puntero a un vector. En la
Figura 1 el puntero "it " es
el que sirve para acceder a cada uno de los valores del vector. En
cada iteración, el valor de "it " aumenta para
acceder el siguiente valor del contenedor hasta que,
eventualmente, "it " denota un valor que está
fuera del rango de iteración, lo que ocurre cuando alcanza
a "itEND " que es el punto de quiebra del ciclo.
|
C++ standard library iterators work as a pointers into a vector.
In
Figure 1, pointer "it " is
used to access each value in the vector. In each iteration, the
value of "it " increases to access the next value in
the container until, eventually, "it " denotes a value
that is outside the iteration range, which happens when it reaches
"itEND " where the cycle is broken.
|
// Java static void useIterator( java.util.Collection C ) { java.util.Iterator iter = C.iterator(); while ( iter.hasNext() ) { System.out.print( iter.next() ); iter.remove(); } } |
// C++ template <class Collection> void useIterator( Collection& C ) { iterJava< typename Collection::iterator > iter( C.begin(), C.end() ); while ( iter.hasNext() ) { std::cout << iter.next(); C.erase( iter ); // C.erase( iter.current() ); } } |
Para obtener los valores almacenados en un contendor con un
iterador Java basta usar sus
operaciones, como se
muestra en la parte superior de la
Figura 2. El método
"hasNext() " indica si todavía quedan objetos
por acceder y "next() " obtiene el siguiente valor.
Opcionalmente, es posible eliminar de la secuencia el valor
recién obtenido con "next() " invocando el
método "remove() ".
|
To get the values stored in a container with a Java iterator it is
enough to use its
operations, as it is
shown in the upper part of
Figure 2. Method
"hasNext() " indicates whether objects are still
accessible, and "next() " gets the next value.
Optionally, it is possible to delete from the sequence the value
just returned by "next() " invoking method
"remove() ".
|
Los iteradores C++ vienen en varios sabores diferentes: constantes
o mutables y hacia adelante o hacia atrás. Por eso existen
4 clases de iteradores:
"iterator ",
"const_iterator " y
"reverse_iterator ".
La ventaja principal de este tipo de iteradores es que permiten
lograr una gran independencia entre los algoritmos y los
contenedores, pues la biblioteca estándar C++ incluye
muchos algoritmos implementados como plantillas que usan
iteradores en lugar de usar los contenedores. Como estos
iteradores C++ han sido construidos de una forma tan completa y
exhaustiva, la implementación de iteradores Java para C++
se simplifica mucho, hasta el punto que basta una sola clase de
plantillas
"iterJava<> ".
|
C++ iterators come in different flavors: constant or mutable and
forward or backward. So there are 4 types of iterators:
"iterator ",
"const_iterator ",
"reverse_iterator " and
"const_reverse_iterator ".
The main advantage of these iterators is that they achieve a high
degree of independence between algorithms and containers, as the
C++ standard library includes many algorithms implemented as
templates that use iterators instead of containers. As C++
iterators are very comprehensive and thorough implementations, the
task of implementing Java iterators for C++ is simple, to the
point that the single class template
"iterJava<> "
is enough.
|
Decisiones de diseño para la clase "
|
Design decisions for the "
|
Lograr que los iteradores C++ se usen de la misma manera en que se
usan los iteradores Java es el criterio más dominante al
decidir entre las diferentes alternativas de diseño
disponibles. Por eso es necesario seguir la interfaz
java.util.Iterator
en la que están definidas las 3 operaciones que tiene
cualquier iterador Java
{
next() ,
hasNext() ,
remove()
}. Además, en la clase "iterJava<> " se
incluyen la operación "set() " para usar el
mismo iterador en otra iteración y "current() "
para obtener el valor actual de iteración, que es el que la
última invocación de "next() "
retornó.
|
Making the use of C++ iterators similar to Java iterators is the
most dominant criteria in deciding among the different design
alternatives available.
This makes it necessary to follow the
java.util.Iterator
interface where the 3 operations common to all Java iterators are
defined
{
next() ,
hasNext() ,
remove()
}.
Furthermore, class "iterJava<> " includes the
operation "set() " to use the same iterator in another
iteration and "current() " to get the current value of
iteration, which is what the last invocation of
"next() " returned.
|
No es usual que un iterador Java incluya la operación
"current() ", posiblemente porque los objetos Java son
referencias, por lo que si el programador Java necesita conservar
el valor que la última invocación de
"next() " retornó basta que lo almacene en
alguna variable temporal:
Object tmp = iter.next();
|
It is unusual for a Java iterator to include operation
"current() ", possibly because the Java objects are
references, so if the Java programmer needs to keep the value of
the last invocation of "next() " would return it is
enough to store it in some temporary variable:
Object tmp = iter.next();
|
template <typename C> bool isPalindrome( const C& CCC ) {{ typedef typename C::const_iterator IterFwd; typedef typename std::reverse_iterator<IterFwd> IterBck; iterJava< IterFwd > itFwd( CCC.begin(), CCC.end() ); iterJava< IterBck > itBck( CCC.rbegin(), CCC.rend() ); while ( itFwd.hasNext() && itBck.hasNext() ) { if ( itFwd.next() != itBck.next() ) { return false; } } return ( !itFwd.hasNext() && !itBck.hasNext() ); }} |
En la
Figura 3 se muestra cómo es
posible recorrer el mismo objeto
contenedor usando 2
iteradores. Debido a que cada iterador es un objeto, puede
mantener su estado sin interferir con otros objetos.
Además, el compilador es el encargado de verificar que
estos iteradores son constantes que no pueden modificar el objeto
recorrido. A diferencia de Java, el lenguaje C++ tiene bien
definido el uso de "const " para que el compilador
impida que el programador modifique un objeto cuyo valor no debe
ser modificado
[TE-2005].
|
In Figure 3 it is shown how to traverse
the same container object using 2 iterators. As each iterator is
an object, it can maintain its state without interfering with
other objects. Furthermore, the compiler is responsible for
enforcing the constness of these iterators, as they should not
change the object being traversed. Unlike Java, C++ has clearly
defined the use of "const " to have the compiler
prevent a programmer from modifying an object that must not be
changed
[TE-2005].
|
template <typename C> bool isPalindrome( const C& CCC ) {{ typedef typename C::const_iterator Iter; iterJava< Iter > itFwd, itBck; itFwd.set(CCC); itBck.set(CCC); itBck.setReverse(); while ( itFwd.hasNext() && itBck.hasNext() ) { if ( itFwd.next() != itBck.next() ) { return false; } } return ( !itFwd.hasNext() && !itBck.hasNext() ); }} |
Como se muestra en la
Figure 4, el método
"setReverse() " y su sinónimo
"setBackward() " de la clase
"iterJava<> " sirven para que la iteración
se haga de atrás hacia adelante en lugar de la forma
natural, de adelante hacia atrás. No se incluye la
operación "setForward() " porque no es
válido utilizar "setReverse() " si ya la
iteración comenzó, por lo que nunca es necesario
invocar "setForward() ". Además de los
métodos observadores "isForward() " y
"isBackward() ", también se incluyen las
operaciones de copia que es usual usar con cualquier clase.
|
As it is shown in
Figure 4, methods
"setReverse() " and its synonym
"setBackward() " in class
"iterJava<> " are used for the iteration to be
carried out from back to front instead of the natural way, from
front to back. There is no "setForward() " operation
because it is not valid to use "setReverse() " if the
iteration already started, so it is never necessary to invoke
"setForward() ". In addition to the observer methods
"isForward() " and "isBackward() ", a copy
operations is also included, which is usually present in any
class.
|
{{ // test::Tree_BF() TL::Tree<char> T; make_a_o(T); Tree_BF<char> iter; std::string L; iter.set(T); while ( iter.hasNext() ) { TL::Tree<char> S = iter.next(); L.push_back( *S ); } assertTrue( L == "abcdefghijklmno" && "Tree_BF" ); }} |
T = a /|\ / / \ \ b c d e /|\ /|\ f g h i j k / \ l m / \ n o |
Talvez la forma más simple de notar las cualidades de de la abstracción
"iterJava<> " es examinar la forma no recursiva para recorrer un árbol, como
se muestra en la Figura 5, en donde se ve que el patrón de iteración
siempre es el mismo, independientemente de adónde o sobre qué se itera.
|
Perhaps the simplest way to realize the qualities of abstraction
"iterJava<> " is to examine the non-recursive
traversal of a tree, as shown in Figure 4.5, where it can be seen that the iteration
pattern is always the same regardless of where or what is iterated on.
|
Implementación de "
|
"
|
La operación de borrado
"remove() "
se llama diferente para los iteradores de la biblioteca
estándar C++:
"erase() ".
Debido a que la operación "erase() " tiene un
funcionamiento que no es uniforme para todos los iteradores, queda
como responsabilidad del programador que usa la clase
"iterJava<> " determinar si la puede usar o no.
Por ejemplo, al invocar "erase() " en una
lista sus iteradores siguen siendo válidos, pero lo
contrario ocurre si se usa "erase() " en un
vector.
|
The erase operation
"remove() " is named differently from C++ standard
library iterators:
"erase() ".
As "erase() " is an operation that does not have a
uniform behaviour for all iterators, it is the responsibility of
the programmer who uses the class "iterJava<> "
determine whether it can be used. For example, when invoking
"erase() " in a
list its iterators remain valid, but the opposite happens
when using "erase() " in a
vector.
|
Los iteradores C++ están construidos en base a la clase
"iterator_traits<> "
en la que se indican varias cualidades del iterador. Debido a que
el parámetro de la plantilla
"iterJava<> " es un iterador, en lugar del
contenedor que se recorre con el iterador, para declarar el tipo
de valor que retorna "iterJava<>::next() " es
necesario obtenerlo de los atributos descritos en la clase
"iterator_traits<> "
de la siguiente manera:
template <typename Iter>
typename std::iterator_traits<Iter>::reference
iterJava<Iter>::next() ;
|
C++ iterators are constructed based on class
"iterator_traits<> "
where iterator features are described. Because the parameter for
template "iterJava<> " is an iterator, instead
of the container traversed with the iterator, to declare the type
of the value returned by "iterJava<>::next() "
it is necessary to get it from the attributes described in the
class
"iterator_traits<> " as follows:
template <typename Iter>
typename std::iterator_traits<Iter>::reference
iterJava<Iter>::next() ;
|
Para implementar la operación de borrado
"remove() " de los iteradores Java, en C++ es
necesario recurrir a un truco que consiste en dotar a la clase
"iterJava<> " de un convertidor a un iterador, de
manera que el compilador C++ pueda compilar apropiadamente la
invocación de la operación "erase() ".
Como se muestra en la
Figura 2, para eliminar del contenedor
el valor recién retornado por "next() " el
programador Java escribe "iter.remove() " mientras que
el programador C++ sí debe mencionar al contenedor
"C.erase(iter) ". El convertidor
"operator Iter()
const " retorna el iterador que denota el
valor actual de iteración, y es con base en ese valor del
iterador C++ que el método "erase() " elimina
del contenedor el último valor retornado por la
operación "next() ". Un efecto equivalente
puede obtenerse usando "C.erase(iter.current()) ",
pues el método "current() " sirve para obtener,
de nuevo, el valor que la última invocación de
"next() " retornó.
|
To implement the delete operation "remove() " for Java
iterators, in C++ it is necessary to resort to a trick including
in class "iterJava<> " a conversion to an
iterator, so the C++ compiler can properly compile the operation
invocation for "erase() ". As it is shown in
Figure 2, to eliminate the value of
container recently returned by "next() " a Java
programmer writes "iter.remove() " while the C++
programmer should mention the container
"C.erase(iter) ". The conversion operator
"operator Iter()
const " returns the iterator that denotes
the present value of iteration, and is based on the value of this
C++ iterator that the "erase() " method removes the
last value of the container returned by operation
"next() ". An equivalent effect can be obtained using
"C.erase(iter.current()) ", as method
"current() " gets, yet again, the value that the last
invocation of "next() " returned.
|
{ // [0] [1] [2] [3] [4] [5] int V[] = { 0 , 1 , 2 , 3 , 4 }; int *it = &V[0]; // it = V+0; int *itEND = &V[5]; // itEND = V+dim(V) iterJava< int* > iter( it, itEND ); while ( iter.hasNext() ) { std::cout << it.next(); } } |
¿Es posible que la clase "iterJava<> "
incluya un puntero al contenedor que está recorriendo? La
respuesta simple es "sí", pero la respuesta más
completa es "mejor no". Como se puede ver en la parte inferior de
la
Figura 2, el parámetro de la
clase "iterJava<> " es el tipo de iterador con el
que se inicializa el objeto para realizar la iteración (que
en este caso es la variable "iter "). Si se incluye en
los campos de la clase "iterJava<> " un puntero
al contenedor, sería necesario utilizar una clase
diferente, por ejemplo "iterPtrJava<> " para usar
punteros directamente; ya no sería posible compartir la
misma clase para "iterJava<> " valores y
punteros. En la
Figura 6 se muestra que la forma de
recorrer con un objeto "iterJava<> " los valores
almacenados en un contenedor se hace de una forma similar a como
se recorre un vector C++.
|
Is it possible for class "iterJava<> " to include
a pointer to the container being taversed? The simple answer is
yes, but the more complete answer is "better not". As it can be
seen at the bottom of
Figure 2, the
"iterJava<> " class parameter is the type of
iterator used to initialize the object used to perform the
iteration (in this case, it is variable "iter "). If a
pointer to the container is included as a field for class
"iterJava<> ", it would necessary to use a
different class, eg. "iterPtrJava<> ", to use
pointers directly, and it would not be possible to share the same
class "iterJava<> " for values and pointers. In
Figure 3 it is shown that traversing a
container with an "iterJava<> " object is done in
a similar manner as traversing a C++ vector.
|
template <typename Iter> class iterJava { // Iterate using pointers/iterators protected: Iter itPrev; // Remember last value returned Iter itNext; // Next value to return Iter itEnd; // Past the last value bool isFwd; // false if it is a reverse_iterator }; |
El tamaño de un objeto "iterJava<> " es
relativamente pequeño y lo usual es que los programadores
usen relativamente pocas variables de iteración en sus
programas. Por eso, en lugar de ahorrar espacio, dentro de un
objeto "iterJava<> " se mantienen almacenados 3
iteradores que denotan 3 posiciones en el contenedor:
"[itNext ]" el valor siguiente de iteración,
"[itPrev ]" el valor que en la última
ocasión retornó "next() " y
"[itEnd ]" la indicación del final de la
iteración. Además, con el fin de permitir que un
"iterJava<> " sirva para recorrer en orden
inverso, también se incluye una bandera
"[isFwd ]" que indica si ese iterador avanza hacia
adelante o hacia atrás.
Como se muestra en la
Figura 7, entre los campos de la clase
"iterJava<> " no aparece ninguna referencia
directa al contenedor.
|
The size of an "iterJava<> " object is relatively
small and it is usual for programmers to use relatively few
iteration variables in their programs. So, instead of saving
space, inside an "iterJava<> " object 3 iterators
are stored to recall 3 positions in the container:
"[itNext ]" the next iteration value,
"[itPrev ]" the value returned on the last invocation
of "next() " and "[itEnd ]" the indication
of the end of the iteration. Furthermore, to allow a
"iterJava<> " to go in reverse order, a flag
"[isFwd ]" is included to indicate whether the
iterator moves forward or backward. As it is shown in
Figure 6, among the fields for class
"iterJava<> " there is no direct reference to the
container.
|
// Cannot erase from constant list void const_compile_error( std::list<long> & L ) { typedef iterJava< std::list<long>::const_iterator > Iter; Iter iter( L.begin(),L.end() ); //_CONST_ while ( iter.hasNext() ) { L.erase(iter); // forbidden for const_iterator } assert( L.empty() ); } |
Como solo se usa sola clase para usar cualquier tipo de iterador,
surge una duda importante: si un contenedor C++ es un objeto
constante, ¿evitará el compilador que sea modificado
cuando se le recorre con un iterador
"iterJava<> "? La respuesta es afirmativa; como
esta clase es una plantilla, al instanciarla el compilador usa el
iterador provisto en la declaración. Si se trata de usar un
iterador no constante, el compilador emitirá errores cuando
la referencia retornada por "next() " se use como un
valor izquierdo
(l-value) por lo que también impedirá que
se use la variable de iteración con la operación
"erase() ", que requiere un iterador no constante como
argumento. Por ejemplo, en la rutina de la
Figura 8 el compilador emitirá el
siguientes error:
... no matching function for call to std::list<...>::erase(...)
|
As only a single class it used for any type of iterator, there
arises an important question: if a C++ container is a constant
object, will the compiler prevent it to be modified when traversed
by an "iterJava<> " iterator? The answer is yes;
as this class is a template, upon instantiation the compiler uses
the iterator instance included in the declaration. If a non
constant iterator is used, the compiler will issue an error when
the reference returned by "next() " is used as a left
value
(l-value) and it will also prevent using the iteration
variable for operation "erase() ", which requires a
non-constant iterator as an argument. For example, in the routine
in
Figure 7 the compiler will issue the
following error:
... no matching function for call to std::list<...>::erase(...)
|
Uso de "
|
Using "
|
Iterar sobre valores diversos usando la pareja
{ hasNext() next() }
es tan simple que vale la pena usar este patrón de
iteración aún si los valores no están
almacenados en un contenedor de la biblioteca estándar C++.
Por ejemplo, tiene mucho sentido usar este estilo de
programación para obtener una secuencia de números
aleatorios o para recorrer contenedores no lineales, como
árboles y grafos.
|
Iterating over diverse values using the pair
{ hasNext() next() }
is so simple that it is worth using this iteration pattern even if
the values are not stored in a container in the C++ standard
library. For example, it makes a lot of sense to use this
programming style to get a sequence of random numbers or to
traverse nonlinear containers, such as trees and graphs.
|
class Random { unsigned m_qty; ///< #. unsigned m_last; ///< Max. long m_val; ///< current(). public: Random( int n=1 , long seed=3145159 ) : m_qty(0), m_last(n) { srand(seed); } bool hasNext() const { return m_qty < m_last; } const long& next() { m_qty++; return (m_val = rand()) ; } }; |
void generateRandom( ) { Random iter( 15, 271828 ); while ( iter.hasNext() ) { std::cout << iter.next() << std::endl; } } |
En la Figura 9 se muestra cuán
sencillo es encapsular un generador de números aleatorios
en un iterador Java; al final de este escrito se incluye el
iterador
"Tree_BF "
para recorrer un árbol por niveles
(breadth-first) que funciona para la clase árbol
descrita en
[DiMare-1997]. La clase
"iterJava<> " también puede usarse en
conjunción con prestigiosas bibliotecas C++ como Boost
[Boost-2009].
|
In Figure 8 it is shown how easy it is
to encapsulate a random number generator in a Java iterator; at
the end of this paper it is included iterator
"Tree_BF "
to traverse a tree by levels
(Breadth-First) which works for the tree class described
in
[DiMare-1997]. Class
"iterJava<> " can also be used in conjunction
with leading C++ libraries such as Boost
[Boost-2009].
|
Enseñanza universitaria |
Teaching at the university |
En la Universidad de Costa Rica hemos escogido enseñar programación con una secuencia de 2 cursos. En el primero entrenamos a los estudiantes en el uso y construcción de algoritmos, y en el segundo les mostramos como reutilizar módulos a través de la abstracción y la especificación. Para el primero curso hemos escogido el lenguaje Java [King-1997] pues tiene las siguientes cualidades: | At the Universidad de Costa Rica we have chosen to teach programming with a sequence of 2 courses. In the first we train students in the use and construction of algorithms, and in the second we show them how to reuse modules through abstraction and specification. For the first course we chose the Java language [King-1997] because it has the following qualities: |
|
|
Desde el segundo curso de programación y durante toda la carrera se utiliza C++ como la herramienta primordial de programación. Así se evita limitar a los alumnos a una máquina virtual que los separa de la realidad de la arquitectura de la máquina y de su sistema operativo. Cambiar de lenguaje del primer curso tiene varias desventajas que se manifiestan durante el segundo curso, entre las que se pueden destacar éstas: | From the second programming course and during the whole degree C++ is used as the primary tool for programming. This avoids limiting students to a virtual machine that separates them from the reality of the machine architecture and its operating system. Changing the languages of the first course has several disadvantages which manifest during the second course, among which the following can be highlighted: |
|
|
Al cambiar al paradigma de programación C++, además
de otras cosas, también se pierden los iteradores Java,
pues los iteradores estilo C++ son
punteros
inteligentes, implementados como clases que sobrecargan las
principales operaciones de los punteros
{ ++ -- * -> } ,
mientras que en Java se usan generadores { hasNext() next()
} .
|
By changing to the C++ programming paradigm, among other things,
Java iterators are also lost, since C++ style iterators are
intelligent pointers, implemented as
classes that overload the main operations on pointers
{ ++ -- * -> } ,
while Java uses generators { hasNext() next() } .
|
Conclusiones |
Conclusions |
En este trabajo se ha demostrado que no hace falta desechar los
iteradores C++ para aprovechar las ventajas del patrón de
iteración Java, que es simple, lo que facilita la
especificación y uso de iteradores. El uso de la clase
"iterJava<> "
permite aprovechar esta potente abstracción de
iteración para C++, lo que aumenta las herramientas
disponibles para programadores C++ y le ayuda a obtener una mejor
implementación. Más aún, debido a que C++
permite declarar referencias "const ", la
verificación de que no sea modificado un contenedor
inmutable la hace el compilador.
|
In this work it has been demostrated that there is no need to
discard C++ iterators to take advantage of the Java iteration
pattern, which is simple, what facilitates iterator specification
and usage. The use of class
"iterJava<> "
helps in taking advantage of this powerful iteration abstraction
for C++, increasing the tools available for C++ programmers and
helps them to get a better implementation. Moreover, because in
C++ it is possible to declare "const " references, the
verification that an immutable container is not modified is
carried out by the compiler.
|
Si los estudiantes ya conocen el lenguaje Java es útil usar
la clase "iterJava<> " en un segundo curso de
programación C++. También es ventajoso incorporar el
patrón de uso de los iteradores Java en la práctica
diaria de cualquier programador C++, pues puede facilitar el
incorporarle paralelismo a un algoritmo de iteración. La
implementación
"iterJava.h "
que aquí se presenta cabe en un solo archivo de encabezado,
es eficiente porque no usa métodos virtuales y está
implementada usando métodos
"inline ", por lo que al usarla no se renuncia a la
posibilidad de que el compilador genere mejor código
objeto. Además, esta simple solución se puede
aplicar inmediatamente sin necesidad de instalar programas o
bibliotecas.
|
If students already know the Java language it is helpful to use
class "iterJava<> " in a second course in C++
programming. It is also advantageous to incorporate the Java
iterator pattern in the daily practice of any C++ programmer, as
it can facilitate incorporating parallelism to an iteration
algorithm. The
"iterJava.h "
implementation presented here fits into a single header file, is
efficient because it has no virtual methods and it is implemented
using "inline " methods, so using it does not require
to give up to the possibility for the compiler to generate better
object code. Furthermore, this simple solution can be applied
immediately without having to install programs or libraries.
|
Agradecimientos |
Acknowledgements |
Alejandro Di Mare aportó varias observaciones y
sugerencias importantes para mejorar este trabajo.
Walter Wabe colaboró con la
implementación de los iteradores
{
PLR -
LPR -
LRP
} para la clase
"TL::Tree ".
Tanto el Programa de Posgrado en Computación e
Informática, como la Escuela de Ciencias de la Computación
e Informática y la Universidad de Costa Rica aportaron fondos
para realizar esta investigación.
|
Alejandro Di Mare made several important observations
and suggestions for improving this work.
Walter Wabe colaborated with the
implementation of the iterators
{
PLR -
LPR -
LRP
} for the
"TL::Tree "
class.
The Graduate Program in Computación e Informática, the
Escuela de Ciencias de la Computación e Informática and
the Universidad de Costa Rica provided funding for this research.
|
Código fuente |
Source code |
iterJava.zip
:
[.zip]
http://www.di-mare.com/adolfo/p/iterJava/iterJava.zip
http://www.di-mare.com/adolfo/p/iterJava/es/index.html
http://www.di-mare.com/adolfo/p/iterJava/en/index.html
iterJava.h
:
[.spanish]
[.english]
[.h]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/iterJava_8h_source.html
http://www.di-mare.com/adolfo/p/iterJava/en/iterJava_8h_source.html
test_iterJava.cpp
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/classtest__iterJava.html
http://www.di-mare.com/adolfo/p/iterJava/en/classtest__iterJava.html
Tree_L.h
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/classTL_1_1Tree.html
http://www.di-mare.com/adolfo/p/iterJava/en/classTL_1_1Tree.html
Tree_BF.h
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/Tree__BF_8h_source.html
http://www.di-mare.com/adolfo/p/iterJava/en/Tree__BF_8h_source.html
Tree_PLR.h
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/Tree__PLR_8h_source.html
http://www.di-mare.com/adolfo/p/iterJava/en/Tree__PLR_8h_source.html
Tree_LPR.h
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/Tree__LPR_8h_source.html
http://www.di-mare.com/adolfo/p/iterJava/en/Tree__LPR_8h_source.html
Tree_LRP.h
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/iterJava/es/Tree__LRP_8h_source.html
http://www.di-mare.com/adolfo/p/iterJava/en/Tree__LRP_8h_source.html
ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.5.9-setup.exe
Bibliografía |
Bibliography |
|
|
[BK-2007] | Barnes, David J. & Kölling Michael:
Programación orientada a objetos con Java,
ISBN: 978-84-8322-350-5, Pearson Educación, 2007.
http://www.bluej.org/objects-first/
|
[Boost-2009] | Boost:
Boost C++ Libraries,
2009.
http://www.boost.org/
|
[Ceballos-2006] | Ceballos, Francisco Javier:
Java 2 - Curso de Programación - 3º ed.,
ISBN 970-15-1164-6, Alfaomega Ra-Ma, 2006.
http://www.fjceballos.es/publicaciones_java.html
|
[Deitel-2007] | Deitel, Harvey M. & Deitel, Paul J.:
Java How to Program 7th ed,
ISBN: 978-0132222204,
Prentice Hall, 2007.
http://www.deitel.com
|
[DG-2004] | Dean, Jeffrey & Ghemawat, Sanjay:
MapReduce: Simplified Data Processing on Large Clusters,
Sixth Symposium on Operating System Design and Implementation,
OSDI'04, San Francisco, California, Dec 2004.
http://labs.google.com/papers/mapreduce-osdi04.pdf
|
[DiMare-1997] | Di Mare, Adolfo:
Una clase C++ completa para conocer y usar árboles,
Reporte Técnico ECCI-2005-01,
Escuela de Ciencias de la Computación e Informática;
Universidad de Costa Rica, 2005.
http://www.di-mare.com/adolfo/p/TreeCpp.htm
|
[Eckart-1987] | Eckart, J. Dana: Iteration and Abstract Data Types, ACM SIGPLAN Notices, Vol.22, No.4, Apr 1987. |
[HPS-2002] | Hallstrom, Jason O. & Pike, Scott M. & Sridhar, Nigamanth: Iterators Reconsidered, Fifth ICSE Workshop on Component-Based Software Engineering, Orlando Florida, May 2002. |
[Java-2009] | Sun Micro Systems:
Java 2 Platform Standard Edition 5.0 API Specification.
http://java.sun.com/j2se/1.5.0/docs/
|
[JCD-2006] | Joyner, Mackale & Chamberlain, Bradford L. & Deitz, Steven J.: Iterators in Chapel, IPDPS 2006, 20th International Parallel and Distributed Processing Symposium, 2006. pp 25-29, Apr 2006. |
[King-1997] | King, K. N.:
The Case for Java as a First Language,
Proceedings of the 35th Annual ACM Southeast Conference,
pp 124-131, Apr 1997.
http://knking.com/books/java/java.pdf
|
[KPWRBC-2009] | Kulkarni, Milind & Pingali, Keshav & Walter, Bruce & Ramanarayanan, Ganesh & Bala, Kavita & Chew, Paul: Optimistic parallelism requires abstractions, Communications of the ACM, Vol.52, No.9, Sep 2009. |
[LG-2000] | Liskov, Barbara & with Guttag, John: Program Development In Java: Abstraction, Specification and Object-Oriented Design, ISBN 0-201-65768-6, Addison-Wesley Professional, 2000. |
[LSAS-1977] | Liskov, Barbara & Snyder, Alan & Atkinson, Russell & Schaffert, Craig: Abstraction mechanisms in CLU, Communications of the ACM , Vol.20, No.8, Aug 1977. |
[MOSS-1996] | Murer, Stephan & Omohundro, Stephen & Stoutamire, David & Szyperski, Clemens: Iteration Abstraction in Sather, ACM Transactions on Programming Languages and Systems, Vol. 18, No.1, pp 1-15, Jan 1996. |
[Parnas-1983] | Parnas, David Lorge: A generalized control structure and its formal definition, Communications of the ACM, Vol.26, No.8 Aug 1983. |
[Str-1998] |
Stroustrup, Bjarne:
The C++ Programming Language, 3rd edition,
ISBN 0-201-88954-4;
Addison-Wesley, 1998.
http://www.research.att.com/~bs/3rd.html
|
[SW-1977] | Shaw, Mary & Wulf, William A.: Abstraction and Verification in Alphard - Defining and Specifying Iteration and Generators, Communications of the ACM, Vol.20, No.8, Aug 1977. |
[TE-2005] | Tschantz, Matthew S. & Ernst, Michael D.: Javari: Adding reference immutability to Java, OOPSLA'05, pp 211-230, Oct 2005. |
[Weide-2006] | Weide, Bruce W.: SAVCBS 2006 Challenge: Specification of Iterators, Fifth International Workshop on Specification and Verification of Component-Based Systems (SAVCBS 2006), Portland Oregon, Nov 2006. |
[ZC-1999] | Zendra, Olivier & Colnet, Dominique: Adding external iterators to an existing Eiffel class library, Proceedings on Technology of Object-Oriented Languages and Systems, TOOLS 32, pp 188-199 22-25 Nov 1999. |
Indice
|
Index
|
Acerca del autor |
About the author |
Adolfo Di Mare: Investigador costarricense en la Escuela de Ciencias de la Computación e Informática [ECCI] de la Universidad de Costa Rica [UCR], en donde ostenta el rango de Profesor Catedrático. Trabaja en las tecnologías de Programación e Internet. También es Catedrático de la Universidad Autónoma de Centro América [UACA]. Obtuvo la Licenciatura en la Universidad de Costa Rica, la Maestría en Ciencias en la Universidad de California, Los Angeles [UCLA], y el Doctorado (Ph.D.) en la Universidad Autónoma de Centro América. |
Adolfo Di Mare: Costarrican Researcher at the Escuela de Ciencias de la Computación e Informática [ECCI], Universidad de Costa Rica [UCR], where he is full professor and works on Internet and programming technologies. He is Cathedraticum at the Universidad Autónoma de Centro América [UACA]. Obtained the Licenciatura at UCR, and the Master of Science in Computer Science from the University of California, Los Angeles [UCLA], and the Ph.D. at the Universidad Autónoma de Centro América. |
Acerca de este documento |
About this document |
Referencia: | Di Mare, Adolfo: Iteradores Java para C++, Artículo 65 de la Décima Conferencia del Latin American And Caribbean Consortium Of Engineering Institutions (Consorsio de Escuelas de Ingeniería de Latinoamérica y del Caribe), (LACCEI-2012), realizada del 23 al 27 de julio de 2012 en Universidad Tecnológica de Panamá, Panamá, Panamá. |
Internet: |
http://www.di-mare.com/adolfo/p/iterJava.htm
http://www.laccei.org/LACCEI2012-Panama/RefereedPapers/RP065.pdf
|
Autor: | Adolfo Di Mare
<adolfo@di-mare.com>
|
Contacto: | Apdo 4249-1000, San José Costa Rica Tel: (506) 2511-8000 Fax: (506) 2438-0139 |
Revisión: | ECCI-UCR, Agosto 2009 |
Visitantes: |