eiffel: does the across structure move the cursor of current iterable structure? - eiffel

I was wondering if the across structure uses an own cursor or a separated one? does it ensure that cursor hasn't moved and if so how can it be expressed for other examples?

ITERABLE uses so called external cursors, not internal ones merged with the underlying structure. As a result, iteration affects neither the structure nor any other cursor, created the same way. This is important to support nested or recursive iterations. For example, to find if there are duplicates, one can do the following:
across structure as i loop
across structure as j loop
if i.item = j.item then print ("Duplicates found.") end
end
end
Doing the same with internal cursors, like (note: the code is incorrect)
from structure.start until structure.after loop
x := structure.item
from structure.start until structure.after loop
if x = structure.item then print ("Duplicates found.") end
structure.forth
end
structure.forth
end
does not work, because the inner loop also changes the cursor of the outer loop.
The limitation of the cursors associated with ITERABLE is that the associated structure should not be changed during the whole course of iteration. This is not a theoretical limitation, but a practical one, to simplify implementation and to make it a bit more efficient.

Related

Single loop containing multiple if-statements or multiple if-statements with loops inside?

Is it recommended to create multiple if statements and nest loops inside of them or create one loop and nest multiple if statements inside of that? I am wondering in terms of memory, time, and other factors I may have overlooked.
Here is some pseudocode:
if a:
for i in range(500):
do x
if b:
for i in range(500):
do y
versus
for i in range(500):
if y:
do x
if z:
do p
In other words, when is the best time to do the if-statement. Inside a few nested loops or before any of the loops?
I am also wondering this because it may be more efficient to do one if statement at the beginning for a check then do the loops nested in this if statement. However, this might result in lots of repeated code.
The first way is the best for the performances, you do the test one time rather than at each turn
Of course I suppose there is no side effect making the two solutions different
In some situations, you won't be able to check the condition before the loop, but if you can this is the better solution because a condition is checked one time instead of every loop iteration.
It really depends what you are iterating through and what you need to check for!
If you need to check each iteration in both cases a and b you should go with option 2.
But if it's either a or b just go with option 1.

In Verilog Procedural Interface, is it possible to scan through iteration loop several times?

We can use vpi_scan in the following way:
vpiHandle iter = vpi_iterate(property, handle);
if (iter)
while ( entry = vpi_scan(iter) )
/*code*/;
iter will be freed when vpi_scan() returns NULL.
But what if I need to scan through the loop several times? Is there a way to tell vpi_scan not to free the iterator, so that I could vpi_free_object when I'm done?
I think I can solve the problem using an additional container (to collect and keep all entries), but is it really needed?
EDIT:
1. I would not like to call vpi_iterate more than once, since it can be expensive.
2. Suppose I go with an additional container solution. Is there a way to find out the number of entries in the vpi_scan loop without actual scanning through the loop? This could make implementation simpler.
ut what if I need to scan through the loop several times? vpi_iterate returns an initialized pointer to the iterator. Every vpi_scan removes an element from the list and frees it. If vpi_scan did not run till the end, you'd better use vpi_free_object to clean the rest of the iterator list. If you need to rescan the same object again, you can call vpi_iterate again and it will return a new iterator object which you can re-scan.
s there a way to tell vpi_scan not to free the iterator, so that I could vpi_free_object when I'm done? No, (1) is the only mechanism which can be used to access and free iterator elements. There is no other exist in the standard.
I think I can solve the problem using an additional container (to collect and keep all entries), but is it really needed? -- this is a good idea if you want to re-scan your data structs. It could be much better from the performance point of view. Verilog simulator usually has a separately generated vpi database which it needs to consult, probably multiple times to provide you with vpi access information.
Is there a way to find out the number of entries in the vpi_scan loop without actual scanning through the loop? not really. there are no defined way to query this information from the iterator. There might be a work-around with using vpi_handle(vpiUse, iterator) but it depends on the underlying data and the type of iteration. It is much easier to use linked lists created by the first scanning loop.
you can get all additional information for LRM or a verilog pli handbook.

Comparing Two Datasets - Slow

I have a set of data in the following format, although very simplified:
DealerName, AccountCode, Value
Dealer1, A-1, 5
Dealer2, A-1, 10
Dealer1, A-2, 20
Dealer2, A-2, 15
Dealer3, A-3, 5
I am trying to achieve an end result that gives me the data summed by AccountCode, so the following in the case of the above data:
AccountCode, Value
A-1, 15
A-2, 35
A-3, 5
I have done this by creating an array of distinct account codes named OutputData and then going through the data comparing the account code to the same field in SelectedDealerData and adding it to the existing values:
For i = 0 To UBound(SelectedDealerData)
For j = 0 To UBound(OutputData)
If SelectedDealerData(i).AccountNumber = OutputData(j).AccountNumber And SelectedDealerData(i).Year = OutputData(j).Year Then
OutputData(j).Units = OutputData(j).Units + SelectedDealerData(i).Units
Exit For
End If
Next j
Next i
There are around 10,00 dealers and 600-1000 account codes for each, so this means a lot of unnecessary looping.
Can someone point me in the direction of a more efficient solution? I am thinking that some kind of Dictionary compare but I am unsure how to implement it.
Add a reference to Microsoft Scripting Runtime for a Dictionary:
Dim aggregated As Dictionary
Set aggregated = New Dictionary
For i = 0 To UBound(SelectedDealerData)
With SelectedDealerData(i)
If aggregated.Exists(.AccountCode) Then
aggregated(.AccountCode) = aggregated(.AccountCode) + .Value
Else
aggregated(.AccountCode) = .Value
End If
End With
Next
For Each Key In aggregated.Keys
Debug.? Key, aggregated(Key)
Next
The code is slow because there are 10 million comparisons and assignment operations going on here (10,000 x 1000).
Also, looping through collections is not very efficient, but nothing can be done about that since the design is already set and maintained the way it is.
Two ways you can make this more efficient (you can time your code right now and see the % savings after these steps).
There are two condition-checks going on with an And. VBA will evaluate both even if the first one is false (no short circuiting). So put nested if then conditions, so that if the first condition fails, you do not proceed to checking the second one. Also, keep the condition more likely to fail in the outer if statement (so it fails fast and moves to the next element). At best, you get a minor speed bump here, at worst, you are no worse off.
There are too many comparisons happening here. Too late to change that, but you can go through the loops based on the following pseudocode if you can sort your collections or build an index which maintains their sort order (save that index array on your spreadsheet if you like). The sorting should be done based on a composite field called Account_Number_Year (just concatenate them)
You can use this concatenated field in the dictionary structure suggested by Alex K. So you can lookup this joint field in the second dictionary and then do operations if needed.
Code to try to fully implement it in VBA:
'Assuming both arrays are sorted
For i = 0 to Ni
MatchingIndex = _
BinarySearchForAccNumberYear(SelectedUserData(i).AccountNumberYear)
Next i
You can look up Binary Search here.
This will reduce your time complexity from O(n^2) to O(n log n) and your code will run an order of magnitude faster.

What's the best way to delete elements from an object inside an iterator?

Suppose you want to delete an element from inside an iteration:
a = ['a','b','c','d','e'];
for i = 0 to len(a){
print a[i];
if (i==1) a.remove(i);
};
The output is a b d e, with c missing. This is a common bug that happens because you changed the array while it was still looping. Some workarounds include keeping a list of elements to delete after the loop, and updating the index after a deletion. How do you deal with this problem?
The most obvious approach is to iterate from the end of the array to the beginning:
a = ['a','b','c','d','e'];
for i = len(a)-1 downto 0 {
print a[i];
if (i==1) a.remove(i);
};
Many languages have iterators with support for deleting elements during forward iteration by telling the iterator to do the deletion. However, this does not always work (e.g., an iterator for the list returned by Java's Arrays.asList will not support deleting elements, because the list does not "own" the backing array.
If you have to forward iterate using an index, at least subtract 1 from the index when you delete the element. That way you won't skip elements.
It depends on whether your iterator access -- including the loop, which in your example iterates from 0 to 5, even though position 5 may no longer exist by the end -- is by concrete position in the collection, or by abstract reference to the next element.
For instance, iterators in Java are of the abstract type, so you can delete the pointed-to item and then reliably continue iterating through the remainder of them.
In a language like C, when iterating through an array you would more typically encounter the difficulty you describe and risk writing buggy code. Perhaps the best general solution is to accumulate the "to-delete" set of things which you want to delete, and then process them as a separate step. Only if you have full knowledge to the internal representation of the collection and how iteration works can you safely perform the deletion and then adjust the iterator -- and the termination condition of the loop -- correctly to continue iterating. This will, however, often by the case anyway if you are working with an array. It's just a question of whether the additional adjustment code is simpler than the code to maintain the "to-delete" set.
Your can delete it even inside an iteration via an iterator.
vector::iterator itVec = vectInt.begin();
for ( ; itVec != vectInt.end(); )
{
if (*itVec == 1022)
itVec = vectInt.erase(itVect);
else
++itVec;
}
the interator response to know the end of the elements (instead of via recording the length of the end), and free the memory.

array_length() of an empty array returning NULL

I'm developing some stored proceduces in PL/pgSQL and some of them are giving me some problems. The sprocs I'm developing receive by parameter an array which I use in a FOR LOOP to get all its elements. To define the upper bound of the FOR LOOP I use the array_length function.
FOR i IN 1..array_length(array,1) LOOP
--array[i] something in here
END LOOP;
The problems occurs when I give to the sprocs an empty array. Instead of not entering the cycle, the sproc simply returns an error, stating that the upper bound of the FOR LOOP is NULL. Shouldn’t it be 0?
Am I doing anything wrong with the FOR LOOP?
Is there any other way to use the same bounds in a LOOP without it returning NULL when using an empty array?
Note: I know I can always use a condition before the LOOP, like this:
IF array_length(array,1) IS NOT NULL THEN
but the problem is: This sproc is supposed to process thousands of calls in the shortest amount of time. As so, I'm not looking to something that adds an unnecessary overhead to the processing. I'm just looking if there is any way to “cycle” an empty array in a LOOP.
As always, if you want to have different behavior for NULL values, use the coalesce construct:
FOR i IN 1..coalesce(array_length(array, 1), 0) LOOP
RAISE NOTICE '%', array[i];
END LOOP;
As for the return value: array_length(x, N) returns the number of elements in Nth dimension. Since an empty array has no dimensions, it returns NULL. You're right that it's counterintuitive if you only consider simple arrays, but makes sense for multi-dimensional arrays.
Edit: Like Erwin Brandstetter wrote in the comments, it's more correct to use array_lower/upper to loop over array indices. These will work for arrays that are not 1-based. These also take a dimension argument and require coalesce:
FOR i IN coalesce(array_lower(array, 1), 1)..coalesce(array_upper(array, 1), 1) LOOP
RAISE NOTICE '%', array[i];
END LOOP;
Avoid the problem altogether by looping through the array with FOREACH, introduced with Postgres 9.1:
FOREACH i IN ARRAY $1
LOOP
-- do something
END LOOP;
Depending on what you want to do inside the loop, you might be able to avoid looping altogether and use plain SQL with unnest() instead. Set-based operations are typically faster than looping in PostgreSQL.
Example:
RETURN QUERY
SELECT elem || 'foo'
FROM unnest($1) AS t(elem);

Resources