Tack (⊣ ⊢)
– What is it good for?!
Dyalog APL offers two symbols which do, on the surface, a seemingly pointless task. I’m referring to left tack (⊣)
and right tack (⊢)
. As with most APL functions, they have two uses depending on their number of arguments: monadic, if used only with a right argument; or dyadic if used with a left and a right argument.
First, some background
If used monadically, it’s use is “same”. The interpreter returns the argument:
⊣'ABC'
ABC
⊢ 1 2 3 4 5
1 2 3 4 5
'left' ⊣ 'right' ⍝ return left argument unchanged
left
'left' ⊢ 'right' ⍝ return right argument unchanged
right
So, what’s the point, why have two symbols for something that returns the argument? Well I’m writing this blog as this question has come up a couple of times internally, and I want to make sure the wider community is aware of the use cases also.
Use as a separator between functions to prevent binding
files←'abc.csv' 'foo.txt' 'test2.jpg' ⍝ a vector of pseudo-random filenames
'foo.*' ⎕S '\0'⊢files
foo.txt
('foo.*' ⎕S '\0')files
foo.txt
or...
(2∘⊥⍣¯1)5
1 0 1
Goes to...
2⊥⍣¯1⊢5 ⍝ don’t need the jot here either- another bonus.
1 0 1
Essentially tack acts as a separator, and is great for saving a character in code golf.
Arguments in tacit programming
When programming tacitly, ⊢
functions like ⍵
, and ⊣
like ⍺
. We can turn a d-fn into a train using this knowledge:
{⍵,⌽⍵}’abc’
{{⍵},⌽{⍵}}’abc’
(⊢,⌽∘⊢)’abc’
(⊢,⌽)’abc’
(⊢,⌽)'hello' ⍝ myself unchanged, catenated with the reverse of myself.
helloolleh
{⍵,⌽⍵}'hello'
helloolleh
Get the right-most/left-most items from an array
⎕←mat←?3 5⍴15
6 4 2 9 9
13 14 9 5 1
7 14 10 2 7
⊢/mat ⍝ right-most column
9 1 7
⊣/mat ⍝ left-most column
6 13 7
Still not particularly impressed?
]runtime '⊢/mat' 'mat[;2⊃⍴mat]' 'mat[;≢⍉mat]' ',1↑⊖⍉mat' '⊃¨⌽¨↓mat' -compare
⊢/mat → 1.2E¯7 | 0% ⎕⎕⎕⎕
mat[;2⊃⍴mat] → 3.6E¯7 | +207% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
mat[;≢⍉mat] → 3.4E¯7 | +185% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,1↑⊖⍉mat → 3.4E¯7 | +191% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
⊃¨⌽¨↓mat → 1.1E¯6 | +835% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
Run in Dyalog APL/W-64 Version 17.1.36847
I came up with a few alternative ways to get the last column from a matrix. None of them can compete in terms of performance. The last one is a tad hyperbolic but proves matrix operations can be far quicker than iterative operations on vectors.
Intermediate execution
With left and right tack, you execute both sides of the function before choosing left or right. In the below example, we benefit from the side effects of running a function and not storing the result:
A_function←{
…
(Guard): ⍬ ⊣ ⎕FUNTIE tn ⍝ Failed to find any hits, untie file and return zilde.
…
}
Essentially, we untie the file, then we evaluate zilde. Finally, we decide to return zilde as the tack is facing left. The file gets untied as a result, and we get an opportunity to return the result we want, not the ⎕FUNTIE
shy result. (In d-fns, the first result not captured into a variable will be returned, so we’d need to something with the result of ⎕FUNTIE
here or it will be the return value).
In conclusion
Tack may seem like a simple function with little place amongst the powerful symbols Dyalog APL offers. I think that it deserves its place, though.
A d-fn as long as {(+⌿⍵)÷(1⌈≢⍵)}
can be turned into a train like (+⌿÷1⌈≢)
. This is a little shorter, and slightly easier to remember in that sense.
Certain idioms like ⊢/
and ⊣/
certainly stand up when indexing, and variants of this can be applied through axis with ⌿
.
⊢⌿mat ⍝ last row instead of last column
7 14 10 2 7
Lastly, if you’re just a simple lover of code golf, you can always save yourself an extra character by omitting brackets. Unpopular opinion, excessive brackets make your code less readable anyway…
APL Team Leader
James is an APL Programmer with a keen interest in mathematics. His love for computing was almost an accident. From a young age he always enjoyed using them- playing video games and such- but it was never considered that anything more would come from it. James originally had plans to pursue a career in finance. More about James.
Ask James about APL / APL Consultancy / APL Legacy System Support
- APL CodeGolf using MERN and APL
- How have video games changed our lives?
- Using a gaming mouse at work
- Bridging the gap between APL and Python
- RegEx with ⎕R and ]locate
- Indexing arrays in APL: Squad indexing on multi-dimensional arrays
- Order of execution in APL programming
- Rendering HTML in Dyalog APL
- Setting coding priorities and quality bars as project groundwork