On Mon, 10 Nov 2008, Mindaugas Kavaliauskas wrote:

Hi Mindaugas,

> I'm just trying to made my understand about an answer to two questions:
> 1) is it good that enumerators are detached to references to iterated items 
> (or is it better to remain it enumerators in the codeblocks)?

If we left them as enumerator they will be updated by farther iterations
and it will not be possible to detach given item.

> 2) can it remain an enumerator in codeblocks? Can we implement it 
> technically? Or this is not possible because of current enumerators 
> implementation or some other side effects.

We do not have such functionality now but it can be implemented.
We will have to add support for reference counter to enumerators
and unblock their copping but it's possible. The question is if
we want to have such functionality.

> PROC main()
> LOCAL aCountry, aI, aJ, nI
>
>    aCountry := {"LTU", "ZWE"}
>    aJ := {}
>    FOR nI := 1 TO LEN(aCountry)
>      aI := aCountry[nI]
>      AADD(aJ, {|| aI})
>    NEXT
>    FOR nI := 1 TO LEN(aCountry)
>      ? EVAL(aJ[nI])
>    NEXT
> RETURN
> But in this sample aI is not detached to current aI value, and sample 
> prints:
> ZWE
> ZWE
> How can I easy understand/remember the difference between this behavior and 
> enumerators behavior?

Just like now you have to remember that:
   FOR EACH aI IN aCountry
      aI := NIL
   NEXT

will set NIL to all aCountry items. FOR and FOR EACH are different
things. In FOR EACH iterator is reference to item. When this reference
is detached it's not longer updated by next iterations. For me it's
correct behavior.

The only one problem I see here is the fact that comp;iler does
not generate compile time warning for the code you send. It should.
It's caused by side effect of simple codeblock implementation.
When expressions are created compiler does not know that they are
part of codeblock which is not allocated yet and finds aI as iterator
in parent function. For extended codeblocks and simple aI:__enum*()
usage warning message is correctly generated. F.e.:

   PROC main()
   LOCAL aCountry, aI, bc
      aCountry := {"LTU"=>"Lithuania", "ZWE"=>"Zimbabwe"}
      FOR EACH aI in aCountry
        QOUT(aI:__enumKey)              // OK
        EVAL({|| QOUT(aI:__enumKey), asd asd})   // RTE
        bc:={||; return aI:__enumKey; } // WARNING
      NEXT
      QOUT(aI:__enumKey) // WARNING
   RETURN

It should be fixed. To make it well we should change the method
of codeblock creating in compiler but it's to small problem for
me to invest time for it now. I'll make it in the future with some
other modifications but now I can simply add new variable to FUNCTION
structure to indicate that we are in simple codeblock context.
I'll commit this modification in a while.

Meanwhile you may think about expected behavior for other FOR EACH
related contexts. F.e. please also remember that after leaving FOR EACH
original enumerator value is restored, f.e.:

   aI := 1234.567
   FOR EACH aI IN aCountry
      aI := NIL
   NEXT
   ? aI  // 1234.567

It's original behavior implemented by Ryszard we still keep.
If we begin to detach enumerators then after leaving FOR EACH
detached enumerators should also point to original value (1234.567
in above example).
Other method is declaring temporary local variables for enumerators
and forbid using normal MEMVAR/STAATIC/LOCAL variables so the code
will look like:

   proc p( aCountry )
      for each aI in aCountry  // aI is temporary local variable
                               // allocated automatically by compiler
         ? aI
      next
   return

best regards,
Przemek
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to