What uses can you think of for Perl 6's junctions? - perl

More information from the Perl 6 Wikipedia entry
Junctions
Perl 6 introduces the concept of junctions: values that are composites of other values.[24] In the earliest days of Perl 6's design, these were called "superpositions", by analogy to the concept in quantum physics of quantum superpositions — waveforms that can simultaneously occupy several states until observation "collapses" them. A Perl 5 module released in 2000 by Damian Conway called Quantum::Superpositions[25] provided an initial proof of concept. While at first, such superpositional values seemed like merely a programmatic curiosity, over time their utility and intuitiveness became widely recognized, and junctions now occupy a central place in Perl 6's design.
In their simplest form, junctions are created by combining a set of values with junctive operators:
my $any_even_digit = 0|2|4|6|8; # any(0, 2, 4, 6, 8)
my $all_odd_digits = 1&3&5&7&9; # all(1, 3, 5, 7, 9)
| indicates a value which is equal to either its left or right-hand arguments. & indicates a value which is equal to both its left and right-hand arguments. These values can be used in any code that would use a normal value. Operations performed on a junction act on all members of the junction equally, and combine according to the junctive operator. So, ("apple"|"banana") ~ "s" would yield "apples"|"bananas". In comparisons, junctions return a single true or false result for the comparison. "any" junctions return true if the comparison is true for any one of the elements of the junction. "all" junctions return true if the comparison is true for all of the elements of the junction.
Junctions can also be used to more richly augment the type system by introducing a style of generic programming that is constrained to junctions of types:
sub get_tint ( RGB_Color|CMYK_Color $color, num $opacity) { ... }
sub store_record (Record&Storable $rec) { ... }

How many days are in a given month?
given( $month ){
when any(qw'1 3 5 7 8 10 12') {
$day = 31
}
when any(qw'4 6 9 11') {
$day = 30
}
when 2 {
$day = 29
}
}

The most attractive feature of junctions is that you don't need to write a lot of code test for complex situations. You describe the situation with the junctions, then apply the test. You don't think about how you get the answer (for instance, using short circuit operators or if blocks) but what question you are asking.

Autothreading sounds cool, although I don't know what its current status is.
for all(#files) -> $file {
do_something($file);
}
Junctions have no order, so the VM is free to spawn a thread for every element in #files and process them all in parallel.

Related

Question about how to represent data in perl

I'm messing around in perl, and I want to build a script to print hockey points and assists, with the date. It's about 40 rows, and I want to associate the date with the 2 pieces of information. I'm stuck on how to implement this.
Something
Like
10/24 2 goals 1 assist
As well filtering the totals. I can do this in a simple DB and use SQL but that seems like an overblown solution. (Plus I want to learn more perl). I feel I may be overthinking this. Any help is much appreciated.
When you represent structured data in Perl (and many other languages), it's common to use a hashmap. Perl doesn't have structs, so developers typically use hashes with well-known keys (which is also what many object-oriented frameworks in Perl end up doing under the hood). Without knowing anything else about your other goals, I'd start with something like this:
my %data = (
"2022-11-24" => { goals => 2, assists => 1 },
"2022-11-23" => { goals => 3, assists => 0 },
...
);
From this data structure, you can:
# get today's number of assists
my $assists_today = $data{"2022-11-24"}{assists};
# sum up each day's number of goals
my $total_goals = 0;
$total_goals += $data{$_}{goals} foreach keys %data;

Differences in optimization statement syntax (clingo 3 and clingo 4)

I have an optimization statement in a logic program, for clingo3:
#minimize [ batteryFlat(mycar)=1, batteryFlat(yourcar)=1, hasNoFuel(mycar)=1,
hasNoFuel(yourcar)=1, brokenIndicator(mycar)=1, brokenIndicator(yourcar)=1].
(Basically, I want the solution to contain as few of the above as possible - they are all of equal weight).
This syntax works for clingo3, but not clingo4. How should it be re-written for clingo4?
How about this:
#minimize {batteryFlat(mycar); batteryFlat(yourcar); hasNoFuel(mycar);
hasNoFuel(yourcar); brokenIndicator(mycar); brokenIndicator(yourcar)}.
The set is now separated with ; and you can then use , to conjoin conditions. Each element has the same priority, but if you want different priorities you can do something like:
#minimize {1#1: batteryFlat(mycar); 1#2: batteryFlat(yourcar); hasNoFuel(mycar);
hasNoFuel(yourcar); brokenIndicator(mycar); brokenIndicator(yourcar)}.
Now the first atom has priority one (for at least one occurrence, I think) and the second atom a higher priority.
Or, if you have variables give priority to the number of different groundings like so:
#minimize {X#1: batteryFlat(X); 1#2: batteryFlat(yourcar); hasNoFuel(mycar);
hasNoFuel(yourcar); brokenIndicator(mycar); brokenIndicator(yourcar)}.
Comparisons are shown here: http://sourceforge.net/projects/potassco/files/clingo/4.2.0/

How to simplify boolean function into two logic gates?

Can anyone help me to simplify this boolean function into two logic gates?
C(out) = AC(in) + BC(in) + AB
This expression represents what is commonly known as a three input majority gate - the output is TRUE only when the majority of inputs are true (2 or 3 inputs must be true for the 3 input case). In general it takes 4 basic logic gates to implement this (5 if you you are restricted to 2-input gates).
If you Google for "majority gate" you will find a variety of implementations, e.g. on this page I found the following, which I think matches your criteria (other than the unfeasible requirement of doing it with only 2 gates):
About majority function with n boolean variables.
for n variables, f(x1,x2,...xn) there will be total nC[n/2] terms for OR operation. Each term contains [n/2] variables for AND operation.
ex: f(00111)= OR{ and(0,0,1) and(0,0,1) and(0,0,1) and(0,1,1) and(,0,1,1) and(0,1,1,) and(0,1,1) and (0,1,1,) and(0,1,1,) and(1,1,1 )
=0 OR 0 OR 0 OR...... OR 1=1=majority of ones is true.

Why do all of these methods of accessing an array work?

It seems to me that some of these should fail, but they all output what they are supposed to:
$, = "\n";
%test = (
"one" => ["one_0", "one_1"],
"two" => ["two_0", "two_1"]
);
print #{$test{"one"}}[0],
#{$test{"one"}}->[0],
$test{"two"}->[0],
$test{"one"}[1];
Why is this?
Your first example is different than the others. It is an array slice -- but in disguise since you are only asking for one item.
#{$test{"one"}}[0];
#{$test{"one"}}[1, 0]; # Another slice example.
Your other examples are alternative ways of de-referencing items within a multi-level data structure. However, the use of an array for de-referencing is deprecated (see perldiag).
#{$test{"one"}}->[0]; # Deprecated. Turn on 'use warnings'.
$test{"two"}->[0]; # Valid.
$test{"one"}[1]; # Valid but easier to type.
Regarding the last example, two subscripts sitting next to each other have an implied -> between them. See, for example, the discussion of the Arrow Rule in perlreftut.

How to do a range query

I have a bunch of numbers timestamps that I want to check against a range to see if they match a particular range of dates. Basically like a BETWEEN .. AND .. match in SQL. The obvious data structure would be a B-tree, but while there are a number of B-tree implementations on CPAN, they only seem to implement exact matching. Berkeley DB has the same problem; there are B-tree indices, but no range matching.
What would be the simplest way to do this? I don't want to use an SQL database unless I have to.
Clarification: I have a lot of these, so I'm looking for an efficient method, not just grep over an array.
grep will be fast, even on a million of them.
# Get everything between 500 and 10,000:
my #items = 1..1_000_000;
my $min = 500;
my $max = 10_000;
my #matches = grep {
$_ <= $max && $_ >= $min
} #items;
Run under time I get this:
time perl million.pl
real 0m0.316s
user 0m0.210s
sys 0m0.070s
Timestamps are numbers. why not common numerical comparaison operators like > and < ?
If you have many of timestamps the problem is not different if you just want to filter your set once. It's O(n) and every other method will be longer.
On the other hand, with a huge set from which you want to extract many different ranges, it could be more efficient to first sort the items. Call the number of search m, the complexity of direct filtering will be O(m.n). With sort followed by search it could be O(n.log(n) + m.log(n)) which is usually much better.
Any O(n.log(n)) sort method will do, including using the built-in sort operator (or b-tree like you suggested). The major difference between efficient sorting methods is if your memory can hold your full set or not. I there is a memory bootleneck to keep both datas and keys (timestamps) in memory you can keep only the timestamp and some index to data in memory and the real data elsewhere (disk file, database). But if your data set is really so big the most efficient solution would probably be to put the whole thing in a database with and index on timestamp (tie to database is real easy using perl).
Then you will have your range. You just use a dicotomic search to look for index of the first element included in range and of the last, complexity will be O(log(n)) (if you do a linear search the whole purpose of sorting will be defeated).
Below example of using sort and binary_search on an array of timestamps, extending use to some data structure with timestamp and content is left as an exercice.
use Search::Binary;
my #array = sort ((1, 2, 1, 1, 2, 3, 2, 2, 8, 3, 8, 3) x 100000);
my $nbelt = #array;
sub cmpfn
{
my ($h, $v, $i) = #_;
$i = $lasti + 1 unless $i;
$record = #array[$i||$lasti + 1];
$lasti = $i;
return ($v<=>$record, $i);
}
for (1..1){
$pos = binary_search(1, $nbelt, 2, \&cmpfn);
}
print "found at $pos\n";
I haven't used it. But found this on searching CPAN. This may provide what you want. You can use Tree::Binary for constructing your data and subclass Tree::Binary::Visitor::Base to do your range queries.
Other easy way is to use SQLite.