[Date Prev][Date Next][Thread Prev][Thread Next][Author Index][Date Index][Thread Index]

iterations



Date: Mon, 23 Oct 89 13:44:42 PDT
   From: tribble (Eric Dean Tribble)

   Any further thoughts about mutable iteration objects?  

Yup.  It'll be in an upcoming mail message.  The new thoughts are only
amusing though, not useful.

   (what is Mu used for (besides meditations)?).  

I'd like to use it for MuTable (and MuSet, see previous mail message).
I think, given the other names, this is clearer for a table kind of
thing with a "store" operation than simply "Table".  Admittedly,
"MuSet" isn't as cute as "SetBang".

   I think I mentioned the problem of
   not having Var types in Smalltalk.  Since a code fragment is worth
   1024 words, here's a sample of loops that use objects that change
   state for every run around the loop.

   for (Iteration * it = TableIteration(table);
		   it ->notEmpty();
		   it ->step())
   {
	   blither(it ->iterand());
   }

   Actually this isn't general enough, and it might break compilers.


That's not proper C++.  Did you mean to say:

for (IterationVar it = TableIteration(table);
	   	 it.notEmpty();
		 it.step())
{
	blither(it.iterand());
}

This is proper C++, but may break compilers.  If instead you meant to
say NEW(TableIteration(table)), then the rest of your original code is
valid C++, and will not break compilers (although it will again when
we replace "*" with various kinds of PtrVars).


   {	Iteration * tableIt = NEW(TableIteration(table));
	   Accumulation * sumIt = NEW(SumAccumulation(0));

	   while (tableIt ->notEmpty() && sumIt ->notEmpty()) {
		   sumIt ->step(CAST(tableIt ->iterand(), IntegerVar));
		   tableIt ->step();
	   }
	   sum = sumIt ->iterand();
   }

I can't make any sense of "CAST(tableIt ->iterand(), IntegerVar)".  Do
you mean "CAST(IntegerVar, tableIt ->iterand())"?  This I understand,
but is invalid X++.  What could "iterand()" be defined as returning
that is safe-castable to an "IntegerVar *"?  A "Var *"?  A "Tofu *"?
I am going to assume you meant "CAST(Integer, tableIt ->iterand())".
I know you're going to say the only reason I got confused here is that
I haven't fixed the "IntegerVar" / "Integer *" duality, but I can't
figure out how to.  I think we're stuck with this duality as it is
currently defined.

   This last structure is a bit cumbersome, but very powerful.  Notice
   that it allows lots of pre-defined pieces, but the connections between
   those pieces can be made inline (such as the accumulation step).  I
   vaguely recall a better syntax for initializing;  one that also
   preserved all the type information for cimpiling inlines.  At the very
   least we can do better with pseudoconstructors and message sends:

   {	TableIteration * tableIt = table->iteration();
	   SumAccumulation * sumIt = sumFrom(0);
   ...
   }

I also like it better with the message sends & pseudo-constructors.
I'm not sure I understand the point you're trying to make though.  Is
the point that mutable iterators variables can be Heapers instead of
Vars, and so ease the translation burden?  This is correct and a good
idea, but I'm not sure if I'm answering the question.

   Something sneaky occurred to me:  Our implementation can know that an
   iteration won't change the state of a table, for example, if it is
   given a ScruTable or ImmuTable.  In those cases, it doesn't need to
   copy that state of the table (or set).  When handed a MuTable, then it
   copies the elements into another table.  If you have an iteration that
   won't change the state, but you're applying it to a MuTable, then just
   wrap it in a ScruTable to prevent the copying.  This communicates
   information about permissible side-effects using the type system.

Works fine on an ImmuTable, but there you don't need to be sneaky.
Doesn't work on a ScruTable.  What we need to know is whether anything
in the body of the loop could be changing the underlying table.  Even
if the view of table that we constructed the Iterator from is a
read-only view, the body of the loop could be changing the table being
viewed through another access channel.

What's wrong with copy-on-write?  When we could have gotten away with
one of these sneaky schemes, a copy-on-write scheme wouldn't have
copied, and been about as efficient.

Is this any help?