The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Quantum::Superpositions::Lazy::Manual::Comparisons - How to compare superpositons

DESCRIPTION

Comparison reducers

Since superpositions have multiple values, a reduction strategy needs to be introduced in order to obtain a single result of the operation. Lets look at some plain array examples first:

        my @array = qw(a b c);

        # EVERY state needs to meet the condition
        # (the number of elements found is equal to the length of an array)
        if (@array == grep { $_ eq 'a' } @array) { ... }

        # ANY state needs to meet the condition
        # (the number of elements found is greater than zero)
        if (0 < grep { $_ eq 'a' } @array) { ... }

        # ONE state needs to meet the condition
        # (the number of elements found is 1)
        if (1 == grep { $_ eq 'a' } @array) { ... }

These reduction strategies are implemented in superpositions with "every_state" in Quantum::Superpositions::Lazy, "any_state" in Quantum::Superpositions::Lazy and "one_state" in Quantum::Superpositions::Lazy. Every time you execute a logical operation on a superposition, one of the reduction strategies is chosen under the hood. You can force a strategy by using one of the functions as a wrapper:

        if (every_state { $pos eq 'a' }) { ... }
        if (any_state { $pos eq 'a' }) { ... }
        if (one_state { $pos eq 'a' }) { ... }

By default (without any wrapper), superpositions are compared with any result reduction type, meaning that any state that meet the check will cause the entire operation to return a true value. This may not always be the best strategy:

        my $pos = superpos(qw(a b c));

        # Likely an error, since both 'b' and 'c' meet the condition
        if ($pos ne 'a') { ... }

        # Correct
        if (every_state { $pos ne 'a' }) { ... }

Boolean comparisons

        my $pos = superpos(qw(a b c));
        my $boolean = $pos gt 'a';  # true

Boolean comparisons should be pretty straightforward. By default, boolean comparisons should work the same as with regular Perl scalars. A tricky part can be comparing two superpositions:

        my $pos1 = superpos(qw(a b c));
        my $pos2 = superpos(qw(d e f));

        $pos1 eq $pos2;

The code above performs all the possible checks, and since there's no wrapper, chooses the any strategy (which can be pictured with ||):

        'a' eq 'd' ||
        'a' eq 'e' ||
        'a' eq 'f' ||
        'b' eq 'd' ||
        'b' eq 'e' ||
        'b' eq 'f' ||
        'c' eq 'd' ||
        'c' eq 'e' ||
        'c' eq 'f'

Comparing for results (fetching matches)

Another way of utilizing the comparisons is fetching all of the matches of an operation. This can be done by using the "fetch_matches" in Quantum::Superpositions::Lazy wrapper, just like the wrappers above:

        my $pos = superpos(qw(a b c));
        my $result = fetch_matches { $pos gt 'a'; }  # superpos(qw(b c))

This works by returning every state of the first superposition that meets the condition with the chosen reduction strategy. When the other argument is just a scalar value, the strategy does not matter. When comparing two superpositions for values however, it is crucial:

        my $pos1 = superpos(qw(a b c));
        my $pos2 = superpos(qw(d e f));

        fetch_matches { $pos1 eq $pos2 };

a will only be returned if it meets the condition:

        'a' eq 'd' ||
        'a' eq 'e' ||
        'a' eq 'f'

As you can see, the reduction strategy only applies to a single item. Changing the strategy in this scenario can be done by nesting the wrappers:

        my $matches = fetch_matches { every_state { $pos1 ne $pos2 } };

Custom comparisons

A custom check can be performed with the help of compare method:

        $pos->compare(sub { $_ > 2 && $_ < 5 });

FURTHER READING

Quantum::Superpositions::Lazy::Manual provides a general introduction to the module.