Key Operator

General APL language issues
Post Reply
User avatar
jmosk
Posts: 69
Joined: Thu Jul 18, 2013 5:15 am

Key Operator

Post by jmosk »

In
{⍺⍵}⌸'Mississippi'

⍵ is 'Mississippi'

what is the meaning of ⍺ ?

The result is:
┌─┬────────┐
│M│1 │
├─┼────────┤
│i│2 5 8 11│
├─┼────────┤
│s│3 4 6 7 │
├─┼────────┤
│p│9 10 │
└─┴────────┘

Can ⌸ only be used in context with ⍺ and ⍵ and never as some other X ⌸ Y
+←--------------------------------------------------------------→
+ Jay Moskowitz
+←--------------------------------------------------------------→
+ http://www.linkedin.com/in/jay-moskowitz-5745b83
+
petermsiegel
Posts: 159
Joined: Thu Nov 11, 2010 11:04 pm

Re: Key Operator

Post by petermsiegel »

Let's do it as

Code: Select all

     {⍺⍵}⌸t←'Mississippi'
We've used the variable t, so it’s easier to see which right argument goes with what.
Then
  • t is 'Mississippi'. t is the right argument to ⌸ (key), but not the right argument within the left operand {⍺⍵} to key;
    in operand {⍺⍵} is each unique letter in t in turn, i.e. each letter in (∪t); and
    in operand {⍺⍵} is a vector (enclosed list) containing the indices showing where that unique letter occurred in t.
Try this:

Code: Select all

     {('⍺=',⍺)('⍵=' ⍵)}⌸t←'Mississippi' 
⍺=M   ⍵=  1        
⍺=i   ⍵=  2 5 8 11 
⍺=s   ⍵=  3 4 6 7  
⍺=p   ⍵=  9 10  
Note that I referenced both ⍺ and ⍵ in the left operand to key, but I could just as well have omitted either one. A common thing to do is to use ≢⍵ to tally (count) the number of references to each unique element in turn, like this:

Code: Select all

     {⍺ (≢⍵)}⌸t←'Mississippi'
M 1
i 4
s 4
p 2
This says, for example, that s occurs 4 times in 'Mississippi'.

Note also that these both produce the unique elements in their right arguments:

Code: Select all

      Lk← ⊣⌸   ⍝ {⍺}⌸
      U← ∪
      Lk 'ccattss'
cats
      U 'ccattss'
cats
User avatar
Bob Armstrong
Posts: 27
Joined: Wed Dec 23, 2009 8:41 pm
Location: 39.038681° -105.079070° 2500m
Contact:

Re: Key Operator

Post by Bob Armstrong »

I rarely comment , being an ` outsider but evolving from the same Iversonian tradition .
Everybody forever had their ` unique verb . Sometime along the way Iverson named it ` nub . Whitney's K was the first place I had ` nub , his name ` range , and ` group .

In CoSy the equivalents are defined in https://cosy.com/4thCoSy/Code/CoSy/CoSy.f relatively recently . They're small enough I'll include the code :

Code: Select all

| return unique items .  Like  K's  ' ? 
: nubb 1p> R@ ['] where 'R ,/ R@ rho iota =i 1P> ; | bool of 1st occurrences
: nubx nubb & ; 	| indices of 1st occurrences 
: nub 1p> dup nubx at 1P> ; 	| unique items .
: nnub 1p> dup nubb 0=i & at 1P> ; | redundants
 
| Group items by uniques | see Wed.Oct,20191002 | https://youtu.be/fxx9kS_seXk |
: grpib 1p> nub R@ ,/ ' =i 'L 1P> ; 	| group integer bool
: grpix grpib ' & 'm ;  		| group integer index

: grpcx >a> nub a> swap  ' conn 'R  ; 
  
| 20191008 | ` nubgrp optimized merge . Eliminates redundant call of ' nub 
: nubgrpib 1p> nub >a> R@ ,/ ' =i 'L a> swap ,L 1P> ; | nub & group integer bool
| and uses CoSy's access to addresses using ' ix rather than just ' i@ and ' i!
| to optimally replace just the second item in the result from ' nubgrpib
: nubgrpix nubgrpib >a> 1 ix dup @ ' & 'm swap rplc a> ; 
 
: nubgrpcx >a> nub a> swap >a> ' conn 'R a> swap ,L  ; 	| 20210625 
| /\ | Takes list . Returns 2 item list of `( nub grp )` .
 
I've yet to add a layer of ` genericity so different names for different types .
You'll note several uses of ` operators , eg: Arthur's eachLeft , 'L , where the verb to be applied is simply passed using Chuck Moore's brilliant ` ' which puts the address of the next word on the stack rather than executing it .

In any case here's the ` mississippi example in CoSy RPN .

Code: Select all

    ` mississippi nubgrpcx
( 
 misp
 ( 
  0 
  1 4 7 10 
  2 3 5 6 
  8 9 
 ) )
a list of 2 lists . To format it a little nicer :

Code: Select all

 R0 fmttbl|
( 
 m  | 0         
 i  | 1 4 7 10  
 s  | 2 3 5 6   
 p  | 8 9       
 )
You see I'm into having a rich vocabulary of variants of a given notion , particularly bool , index , & value , and their complements , rather than complex syntax . I feel most of the APL level power comes from the vocabulary .
User avatar
jmosk
Posts: 69
Joined: Thu Jul 18, 2013 5:15 am

Re: Key Operator

Post by jmosk »

What is confusing here is that 4 {⍺,⍵} 5 associates 4 with ⍺ and 5 with ⍵. Yet there does not seem to be an explicate ⍺ defined in {⍺⍵}⌸'Mississippi'. It is not of the form X {F} Y. Yet when executed it seems that ⍺ does end up taking on the value of the keys in Mississippi. So in this case it seems ⍺ is being assigned a value rather than carrying a value into the function. This seems confusing.

Are there other functions like this where there does not seem to be an explicit ⍺ yet a value is taken on during execution? I do understand that one can explicitly set ⍺ to a value inside a function to set it as a default value if not explicitly defined in the call to the function. Maybe that is how to think of the ⌸ function, as one that sets a default value for ⍺.
+←--------------------------------------------------------------→
+ Jay Moskowitz
+←--------------------------------------------------------------→
+ http://www.linkedin.com/in/jay-moskowitz-5745b83
+
petermsiegel
Posts: 159
Joined: Thu Nov 11, 2010 11:04 pm

Re: Key Operator

Post by petermsiegel »

The thing to note is that an operator is different from a function, since it might take functions as its operands (or, in this example, its single operand ⍺⍺), as well as arguments (in this example, ⍵). Rather than read what's below (TLDR), you might want to look at the Legrand book https://www.dyalog.com/mastering-dyalog-apl.htm. It's a bit dated, but explains things like functions and operators rather well.

For the case at hand...
What's happening here is that we have an operator, Key (⌸), which takes a left operand, (here) a function, and a right argument, the item whose major elements (items) are being evaluated. (I simplify: Key can also take a left argument, but let's pretend otherwise for now).

In our case, Key calls the operand {⍺ ⍵} many times, once for each unique element in the right argument. On each call, Key sets ⍺ to be each unique element in turn-- one at a time, mind you-- and ⍵ to be a list of indices showing where that item occurred in the ORIGINAL array (the right argument to Key itself).

Operators often call their operand(s) with arguments-- and -- which are related to, but precisely NOT the same as their own (operator) arguments.

A simple case would be

Code: Select all

      +/1 2 3 4
10
where + is an OPERAND of reduce / an operator. Reduce appears to apply operand + between all the elements of its right argument. You can see what's really going on by concocting a verbose equivalent:

Code: Select all

     {⎕←('⍺=',⍺)'+'('⍵=',⍵),'=> (⍺+⍵)='(⍺+⍵) ⋄ ⍺+⍵}/1 2 3 4
 ⍺= 3 + ⍵= 4  => (⍺+⍵)=  7
 ⍺= 2 + ⍵= 7  => (⍺+⍵)=  9
 ⍺= 1 + ⍵= 9  => (⍺+⍵)=  10
10
So you can see that the operand {⎕←... ⋄ ⍺+⍵} is called several (N-1) times "by" Reduce / with arguments related to 1 2 3 4, but obviously doled out according to the semantics of reduction.

Cheers!
Post Reply