Iterator pattern - How adding or removing elements from an aggregate can you end up accessing an element twice or missing it completely? - iterator

How adding or removing elements from an aggregate can you end up accessing an element twice or missing it completely ?
The GoF Design Patterns mentions this under the Iterator pattern :
"if elements are added or deleted from an aggregate you might end up accessing an element twice or missing it completely"
I cannot think of a use case when this could happen ?
Thanks in advance.

Here is a simple example. Imagine you are iterating over an array-like collection. An iterator might keep track of your current index in the list.
*
[ 1, 2, 3, 4 ]
In this example, if you insert an element to the front of the list while iterating, the index will now be pointing to an element that has already been seen.
*
[ 0, 1, 2, 3, 4 ]
Similarly, if you delete an element, the index will now skip an element.
*
[ 2, 3, 4 ]

Related

How can I stop Raku collapsing a list containing a single list?

i've got a function, into which i want to be able to pass a list of lists, like in this artificial example:
sub print_lists(#input) {
.say for #input
}
my #list_of_two_lists = ((1, 2), (3, 4));
print_lists(#list_of_two_lists);
this gives the following output, as expected:
(1, 2)
(3, 4)
but if i do this:
my #list_of_one_list = ((1, 2));
print_lists(#list_of_one_list);
i get this output:
1
2
i.e. it flattens the list containing one list of two elements, into a single list of two elements.
what am i doing wrong? what do i need to do if i want to be able to pass in a list containing a single list?
This behavior is a consequence of two Raku features, both of which are worth knowing.
The first is the Single Argument Rule. It's important enough to be worth reading the docs on, but the key takeaway is that when you pass a single list (as you do in with #list_of_one_list) constructs like for will iterate over each item in the list rather than over the list as a single item. In this case, that means iterating over the two items in the list, 1, and 2.
At this point, you might be thinking "but #list_of_one_list didn't have two items in it – it had one item: the list (1, 2)". But that's because we haven't gotten to the second point to understand: In Raku ( and ) are not what makes something a list. Instead, using the , operator is what constructs a list. This can take a tad bit of getting used to, but it's what allows Raku to treat parentheses as optional in many places that other languages require them.
To see this second point in action, I suggest you check out how .raku prints out your #list_of_lists. Compare:
my #list_of_one_list = ((1, 2));
say #list_of_one_list; # OUTPUT: «[1, 2]»
my #list-of-one-list = (1, 2),;
say #list-of-one-list; # OUTPUT: «[(1, 2)]»
And that's all the info you need to answer your question: simply add a , when you build your list of one list.
I hope that helped :)

How to yield all substrings from string using sequence?

I'm trying to learn the Sequence in Kotlin.
Assume I want to get a sequence of all substrings of a string with the yield statement. I understand how to do this with two nested loops with the right and left borders.
It seems to me that there is an efficient way to use a Sequence or a pair of nested Sequences instead of loops. But I can't figure out how to do it.
How to yield all substrings from string using sequence?
Thanks
Frankly, I don't know what is the most efficient method. And I would just use for loops. But here's my solution to this problem, maybe it will help you understand sequences and this style of writing code:
Here it is on the Playground
fun String.substrings() =
indices.asSequence().flatMap { left ->
(left + 1..length).asSequence().map { right -> substring(left, right) }
}
Sequences aren't especially efficient, there's a bunch of overhead involved for each one - their main strength is being able to pass each element through the whole chain of operations one at a time.
This means you don't have to create an entire new collection of elements for each intermediate step (lower memory usage), you can terminate earlier once you find a result you're looking for, and sequences can be infinite. Even then, they might still be slower than the normal list version, depending on exactly what you're working with.
The most efficient sequence is probably what you're doing, using a couple of for loops and yielding items. But if you mean "efficient" like "using the standard library instead of writing out for loops" then #Furetur's answer is a way to do it, or you could use sliding windows like this:
val stuff = "12345"
val substrings = with(stuff) {
indices.asSequence().flatMap { i ->
windowedSequence(length - i)
}
}
print(substrings.toList())
>>>>[12345, 1234, 2345, 123, 234, 345, 12, 23, 34, 45, 1, 2, 3, 4, 5]
basically just using windowed (with the default of partialWindows=false) for every possible substring length, from length to 1, using the sequence versions of everything

Is there a way to merge 2 arrays in GREL

In a GREL expression, is there a way to merge 2 arrays?
I tried ["a","b"]+["c","d"] but the result is a java error.
Short answer: Not with Grel.
Here is the complete list of the "arrays" methods in Grel and their respective Java code. It should not be very difficult to add a "merge" or "append" method, but would it be worth it? It is very rare to have more than one array in a cell (I have never encountered this case).
It is precisely to solve this kind of rare but possible case that Open Refine offers two other more powerful scripting languages, Jython and Clojure. In Python/Jython, the operation you want to do is as simple as:
return [1,2,3] +[3,4,5] #result : [ 1, 2, 3, 3, 3, 4, 5 ]
Would it be possible/worth the effort to make it easier with some Grel new function?
There is a way to do it (though it might be a bad idea):
split(join(["a","b"], "|") + "|" + join(["c","d"], "|"), "|")
Join each array with a delimiter character that does not appear in the data. (I've chosen the pipe character.) Add the resulting joined-up arrays together, and add the delimiter between them. Now, they form the string a|b|c|d. This string can be split on the | delimiter into a new array.

Using a hash with object keys in Perl 6

I'm trying to make a Hash with non-string keys, in my case arrays or lists.
> my %sum := :{(1, 3, 5) => 9, (2, 4, 6) => 12}
{(1 3 5) => 9, (2 4 6) => 12}
Now, I don't understand the following.
How to retrieve an existing element?
> %sum{(1, 3, 5)}
((Any) (Any) (Any))
> %sum{1, 3, 5}
((Any) (Any) (Any))
How to add a new element?
> %sum{2, 4} = 6
(6 (Any))
Several things are going on here: first of all, if you use (1,2,3) as a key, Rakudo Perl 6 will consider this to be a slice of 3 keys: 1, 2 and 3. Since neither of these exist in the object hash, you get ((Any) (Any) (Any)).
So you need to indicate that you want the list to be seen as single key of which you want the value. You can do this with $(), so %sum{$(1,3,5)}. This however does not give you the intended result. The reason behind that is the following:
> say (1,2,3).WHICH eq (1,2,3).WHICH
False
Object hashes internally key the object to its .WHICH value. At the moment, Lists are not considered value types, so each List has a different .WHICH. Which makes them unfit to be used as keys in object hashes, or in other cases where they are used by default (e.g. .unique and Sets, Bags and Mixes).
I'm actually working on making this the above eq return True before long: this should make it to the 2018.01 compiler release, on which also a Rakudo Star release will be based.
BTW, any time you're using object hashes and integer values, you will probably be better of using Bags. Alas not yet in this case either for the above reason.
You could actually make this work by using augment class List and adding a .WHICH method on that, but I would recommend against that as it will interfere with any future fixes.
Elizabeth's answer is solid, but until that feature is created, I don't see why you can't create a Key class to use as the hash key, which will have an explicit hash function which is based on its values rather than its location in memory. This hash function, used for both placement in the list and equality testing, is .WHICH. This function must return an ObjAt object, which is basically just a string.
class Key does Positional {
has Int #.list handles <elems AT-POS EXISTS-POS ASSIGN-POS BIND-POS push>;
method new(*#list) { self.bless(:#list); }
method WHICH() { ObjAt.new(#!list.join('|')); }
}
my %hsh{Key};
%hsh{Key.new(1, 3)} = 'result';
say %hsh{Key.new(1, 3)}; # output: result
Note that I only allowed the key to contain Int. This is an easy way of being fairly confident no element's string value contains the '|' character, which could make two keys look the same despite having different elements. However, this is not hardened against naughty users--4 but role :: { method Str() { '|' } } is an Int that stringifies to the illegal value. You can make the code stronger if you use .WHICH recursively, but I'll leave that as an exercise.
This Key class is also a little fancier than you strictly need. It would be enough to have a #.list member and define .WHICH. I defined AT-POS and friends so the Key can be indexed, pushed to, and otherwise treated as an Array.

Accessing the last element in Perl6

Could someone explain why this accesses the last element in Perl 6
#array[*-1]
and why we need the asterisk *?
Isn't it more logical to do something like this:
#array[-1]
The user documentation explains that *-1 is just a code object, which could also be written as
-> $n { $n - 1 }
When passed to [ ], it will be invoked with the array size as argument to compute the index.
So instead of just being able to start counting backwards from the end of the array, you could use it to eg count forwards from its center via
#array[* div 2] #=> middlemost element
#array[* div 2 + 1] #=> next element after the middlemost one
According to the design documents, the reason for outlawing negative indices (which could have been accepted even with the above generalization in place) is this:
The Perl 6 semantics avoids indexing discontinuities (a source of subtle runtime errors), and provides ordinal access in both directions at both ends of the array.
If you don't like the whatever-star, you can also do:
my $last-elem = #array.tail;
or even
my ($second-last, $last) = #array.tail(2);
Edit: Of course, there's also a head method:
my ($first, $second) = #array.head(2);
The other two answers are excellent. My only reason for answering was to add a little more explanation about the Whatever Star * array indexing syntax.
The equivalent of Perl 6's #array[*-1] syntax in Perl 5 would be $array[ scalar #array - 1]. In Perl 5, in scalar context an array returns the number of items it contains, so scalar #array gives you the length of the array. Subtracting one from this gives you the last index of the array.
Since in Perl 6 indices can be restricted to never be negative, if they are negative then they are definitely out of range. But in Perl 5, a negative index may or may not be "out of range". If it is out of range, then it only gives you an undefined value which isn't easy to distinguish from simply having an undefined value in an element.
For example, the Perl 5 code:
use v5.10;
use strict;
use warnings;
my #array = ('a', undef, 'c');
say $array[-1]; # 'c'
say $array[-2]; # undefined
say $array[-3]; # 'a'
say $array[-4]; # out of range
say "======= FINISHED =======";
results in two nearly identical warnings, but still finishes running:
c
Use of uninitialized value $array[-2] in say at array.pl line 7.
a
Use of uninitialized value in say at array.pl line 9.
======= FINISHED =======
But the Perl 6 code
use v6;
my #array = 'a', Any, 'c';
put #array[*-1]; # evaluated as #array[2] or 'c'
put #array[*-2]; # evaluated as #array[1] or Any (i.e. undefined)
put #array[*-3]; # evaluated as #array[0] or 'a'
put #array[*-4]; # evaluated as #array[-1], which is a syntax error
put "======= FINISHED =======";
will likewise warn about the undefined value being used, but it fails upon the use of an index that comes out less than 0:
c
Use of uninitialized value #array of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block <unit> at array.p6 line 5
a
Effective index out of range. Is: -1, should be in 0..Inf
in block <unit> at array.p6 line 7
Actually thrown at:
in block <unit> at array.p6 line 7
Thus your Perl 6 code can more robust by not allowing negative indices, but you can still index from the end using the Whatever Star syntax.
last word of advice
If you just need the last few elements of an array, I'd recommend using the tail method mentioned in mscha's answer. #array.tail(3) is much more self-explanatory than #array[*-3 .. *-1].