ModuleIterator - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

Online Help

All Products    Maple    MapleSim


ModuleIterator

iterate over the elements of a module

 

Calling Sequence

Description

Examples

Compatibility

Calling Sequence

module() local ModuleIterator, ...; ... end module;

module() option object; export lowerbound, upperbound, `?[]`, ...; ...; end module;

Description

• 

The ModuleIterator routine allows a module or object to return an interface that can be used to iterate over elements contained within the module (or object).

• 

If a module defines a ModuleIterator routine as a local or export, that module may be used as the container in for-in loops, as well as calls to seq, add and mul.

• 

A call to ModuleIterator should return two procedures.

(hasNext,getNext) := ModuleIterator( obj );

 

The hasNext function should return true or false depending on if there are more elements remaining.

The getNext function should return the next element to be accessed.

The getNext function has an optional unevaluated name parameter. If passed a name, the function should assign the index of the returned element to this name. If the concept of an index makes no sense for the module or object, the name should be left unassigned.

A module with a getNext function that does assign an index can be used as the container in a two-variable for-in loop.

• 

The basic pattern for using these routines is as follows

while hasNext() do
      e := getNext('i');
      # Do something with e; index of e is available in i.
  end do;

• 

It should always be safe to call getNext if a call to hasNext returns true.  If a call to hasNext returns false, the return value of a call to getNext is unspecified.

• 

Calling hasNext multiple times without intervening calls to getNext should always return the same result.

• 

If the module being defined is an object, then there is an alternative mechanism for iterating over the module. This works by overriding three methods for the object: lowerbound, upperbound, and `?[]`. If an object has these three methods but no ModuleIterator member, then Maple will call the lowerbound and upperbound members to get bounds (which must be integers) for indexing, and the `?[]` member to retrieve the elements between these bounds, inclusive. In particular, for such an object m,

for i, e in m do
      # Do something with e.
  end do;

  

is equivalent to

for i from lowerbound(m) to upperbound(m) do
      e := m[i];
      # Do something with e.
  end do;

Examples

We can create a module that can be used to iterate over all prime numbers.

Primes := module()
   local ModuleIterator := proc()
       local i, e;

       i := 1;
       e := 1;

       (
           proc()
               true;
           end proc,
           proc( returnIndex := NULL )
               if returnIndex <> NULL then
                   returnIndex := i;
                   i := i + 1
               end if;
               e := nextprime( e );
           end proc
       )
   end proc;
end module;

PrimesmodulelocalModuleIterator&semi;end module

(1)

As there are infinitely many primes, we need to introduce our own termination condition. For example, the following loop will print the first 100 primes:

fori,pinPrimesdoprintpuntil100i

2

3

5

7

11

13

17

19

23

29

31

37

41

43

47

53

59

61

67

71

73

79

83

89

97

101

103

107

109

113

127

131

137

139

149

151

157

163

167

173

179

181

191

193

197

199

211

223

227

229

233

239

241

251

257

263

269

271

277

281

283

293

307

311

313

317

331

337

347

349

353

359

367

373

379

383

389

397

401

409

419

421

431

433

439

443

449

457

461

463

467

479

487

491

499

503

509

521

523

541

(2)

A container object with a ModuleIterator can be used like a built-in Maple structure.

module IterObj()
   option object;

   local _list;

   export setValue::static := proc( obj::IterObj, l::list )
       obj:-_list := l
   end proc;

   export ModuleIterator::static := proc( obj::IterObj )
       local i, l;

       i := 1;
       l := obj:-_list;

       (
           proc()
               i <= numelems( l )
           end proc,
           proc( returnIndex := NULL )
               local e;
               e := l[i];
               if returnIndex <> NULL then
                   returnIndex := i
               end if;
               i := i+1;
               e;
           end proc
       );
   end proc;
end module:

ioObjectIterObj&colon;

setValueio&comma;1&comma;2&comma;3&colon;

hasNext,getNextModuleIteratorio

hasNext,getNextproci<=numelemslend proc,procreturnIndexNULLlocale&semi;el&lsqb;i&rsqb;&semi;ifreturnIndex<>NULLthenreturnIndexiend if&semi;ii&plus;1&semi;eend proc

(3)

whilehasNextdoegetNextenddo

1

2

3

(4)

foriiniodoienddo

1

2

3

(5)

addi&comma;iinio

6

(6)

muli&comma;iinio

6

(7)

seqi2&comma;iinio

1,4,9

(8)

Alternatively, this object could be implemented as follows.

module IterObj2()
   option object;

   local _list;

   export setValue::static := proc( obj::IterObj2, l::list )
       obj:-_list := l
   end proc;

   export lowerbound::static := ( self::IterObj2 ) -> 1;
   export upperbound::static := ( self::IterObj2 ) -> numelems( self:-_list );

   export `?[]`::static := proc( self::IterObj2, idx::list )
       if type( idx, ['posint'] ) and idx[1] <= numelems( self:-_list ) then
           return self:-_list[idx[1]];
       else
           error "invalid subscript selector";
       end if;
   end proc;
end module:

io2ObjectIterObj2&colon;

setValueio2&comma;1&comma;2&comma;3&colon;

foriinio2doienddo

1

2

3

(9)

addi&comma;iinio2

6

(10)

muli&comma;iinio2

6

(11)

seqi2&comma;iinio2

1,4,9

(12)

Compatibility

• 

The ModuleIterator command was introduced in Maple 16.

• 

For more information on Maple 16 changes, see Updates in Maple 16.

• 

The ModuleIterator command was updated in Maple 17.

See Also

add

for

module

mul

Object

Object,create

Object,methods

Object,overview

procedure

seq