Ecere SDK/eC Forums
http://ecere.org/community/
Print view

How to Create an Iterator
http://ecere.org/community/viewtopic.php?f=1&t=429
Page 1 of 1
Author:  cloutiy [ Sun Jul 24, 2016 3:18 pm ]
Post subject:  How to Create an Iterator

Hello,

I would like to undestand a bit more about iterators and how to create them.

In the code example below, the compiler is not happy with the following line of code:

Code: Select all

Iterator<int> i { planets };

What is the proper what to create an iterator to go over a list of type Planet?

The entire code below:

Code: Select all

// define some domain specific data types
typedef int Coordinate;
typedef String Name;

// describe a Planet
typedef struct Planet
{
   Name name;
   Coordinate x, y;
} Planet;

// A function to print a planet's information
void showPlanet( Planet planet )
{
   printf("%s: %d, %d\n", planet.name, planet.x, planet.y);
}

// The Main app
class PlanetApp : Application
{
   void Main()
   {
      // Some instantiations of
      Planet earth = { "Earth", 3, 4};
      Planet jupiter = { "Jupiter", 1, 1};

      // An array of planets
      Planet planets[2] =
      {
         { "Mercury", 5, 5 },
         { "Pluto", 7, 7 }
      };

      showPlanet(earth); showPlanet(jupiter);
      
      // An iterator to iterate through an array of planets.
      Iterator<int> i { planets };
      while(i.Next()) showPlanet(i);
   }
}
Author:  jerome [ Sun Jul 24, 2016 5:09 pm ]
Post subject:  Re: How to Create an Iterator

Hi Yves,

Iterators can only be used on eC containers, not C arrays.

Here is a slightly modified version more in line with eC style and which the compiler is happy with:

Code: Select all

// define some domain specific data types
class Coordinate : int;
class Name : String;
 
// describe a Planet
struct Planet
{
   const Name name;
   Coordinate x, y;
 
   // A method to print a planet's information
   void show()
   {
      PrintLn(name, ": ", x, ", ", y);
   }
};
 
// The Main app
class PlanetApp : Application
{
   void Main()
   {
      // Some instantiations of
      Planet earth { "Earth", 3, 4 };
      Planet jupiter { "Jupiter", 1, 1 };
 
      // An array of planets
      Array<Planet> planets
      { [
         { "Mercury", 5, 5 },
         { "Pluto", 7, 7 }
      ] };
      Iterator<Planet> i { planets };
 
      earth.show(); jupiter.show();
 
      // An iterator to iterate through an array of planets.
      while(i.Next()) i.data.show();
 
      // You could also simply write (without need for an iterator):
      for(p : planets) p.show();
 
      // As of the current eC version, local 'class' instances must be explicitly deleted
      // There are plan to fix this in an upcoming version. ( http://ec-lang.org/mantis/view.php?id=513 )
      delete planets;
   }
}
Author:  cloutiy [ Sun Jul 24, 2016 5:29 pm ]
Post subject:  Re: How to Create an Iterator

Aaahh, I see. Wow this is brilliant.

Thanks for pointing out the use of Array<Planet> planets vs Planet planets[].

I'll need to remind myself to try to use the eC counterparts to C ones where they exist.

Another small question, is there a reason why you kept the Planet type as a struct instead of turning it into a class? What are the reasons one would use one over the other?

Regards, and thanks for taking the time to educate.

yves
Author:  jerome [ Sun Jul 24, 2016 5:47 pm ]
Post subject:  Re: How to Create an Iterator

Hi Yves,

Before going all out on eC containers, keep in mind that they do come with a little bit of a performance cost. They are mainly meant for convenience, elegance and for dynamic containers. C arrays should still be used if you have a fixed number of elements and are not in need of this generic/elegant aspect.

There are some differences between struct and class in eC.
For a full explanation, see http://ec-lang.org/overview/#classes as well as page 64 in the Tao: http://ecere.com/tao.pdf#page=69 .

Structs are allocated 'in place', while classes are always allocated on the heap, therefore classes have an implied indirection level. Classes also have some overhead as they support reference counting, run-time type information, virtual methods, constructors and destructors. Structs support none of these things. There is also a hybrid class : struct which is always allocated on the heap, but do not support virtual methods, reference counting or run-time type information.

Note that it is possible to treat C arrays as eC containers while avoiding copying it into another eC container, but it's kind of an advanced topic. This is what the compiler ends up doing internally when initializing an eC container with a list of elements as in the previous example. Here's how it's done:

Code: Select all

Planet planets2[2] =
{
   { "Mercury", 5, 5 },
   { "Pluto", 7, 7 }
};
BuiltInContainer bic
{
   _vTbl = class(BuiltInContainer)._vTbl,
   _class = class(BuiltInContainer),
   data = planets2, 
   count = sizeof(planets2) / sizeof(planets2[0]),
   type = class(Planet)
};
Container<Planet> pc = (Container<Planet>)&bic;
 
// Can now use pc as a regular Planet container: 
for(p : pc) p.show();
Eventually, eC might (should?) be able to do this automatically when using an Iterator or a for each loop on a C array.
All times are UTC-05:00 Page 1 of 1