« first day (1051 days earlier)      last day (1604 days later) » 
02:00 - 23:0023:00 - 00:00

2:51 AM
I know that I can set keyboard shortcuts for F1–F12 with the PFKEY system function. But is there any way to set other shortcut keys in the Linux TTY IDE? (I've found instructions for the Windows GUI IDE and (more limited) instructions for RIDE, but I'm having trouble finding anything for the version I use.)
 
3:17 AM
(From some references in the docs, I suspect that /opt/mdyalog/17.0/64/unicode/aplkeys/xterm might be related somehow, but I couldn't quite tell how that file works. Minor edits to it didn't seem to have a major effect, and I am reluctant to change it more without a better understanding.)
 
 
8 hours later…
11:42 AM
#tio alias view
 
@Adám
Command Aliases:
]help -> #TIO do apl-dyalog {0::⎕←⊃⎕DM⋄⎕←⎕SE.UCMD'help %args% -url'}(⎕NS⍬).(enableSALT⊣⎕CY'salt')
⋄ -> #TIO apl {0::⎕←⊃⎕DM⋄%args%⋄⍬⊤⍬}(⎕NS⍬).(⎕SE.UCMD'box on -f=on -t=tree'⊣enableSALT⊣⎕CY'salt')
)tio -> #tio do apl-dyalog ⎕←'https://tio.run/##','\+' '='⎕R'@' ''base64 10↓¯8↓256|⊃⌽3(219⌶)¯128+256|128+(⎕UCS'apl-dyalog'),t,('UTF-8'⎕UCS'%args%'),t←255 255⊣'base64'⎕CY'dfns'
⍞← -> #TIO do apl-dyalog {0::⎕←⊃⎕DM⋄⎕←%args%⋄⍬⊤⍬}⍬
f← -> #tio do apl-dyalog ⎕←'https://tio.run/##','\+' '='⎕R'@' ''base64 10↓¯8↓256|⊃⌽3(219⌶)¯128+256|128+∊{255,⍨'UTF-8'⎕UCS⍵}¨'apl-dyalog' '' '%args%' 'f←
 
12:06 PM
#tio alias command ⎕← #tio apl ⎕SE.d←{(1=≡⍺)∧⍬≡⍴⍺:⎕←⍺dft 0⋄⎕←disp⍺}⋄{0::⎕←⊃⎕DM⋄⎕←%args%⋄⍬⊤⍬}⎕SE.(⎕WS'Event'('SessionPrint' 'd')⊣⎕CY'dfns')
 
@Adám Added alias for ⎕←
 
⎕←⍳2 3
 
@Adám
┌───┬───┬───┐
│1 1│1 2│1 3│
├───┼───┼───┤
│2 1│2 2│2 3│
└───┴───┴───┘
 
#tio alias command ⋄ #tio apl ⎕SE.d←{(1=≡⍺)∧⍬≡⍴⍺:⎕←⍺dft 0⋄⎕←disp⍺}⋄{0::⎕←⊃⎕DM⋄%args%⋄⍬⊤⍬}⎕SE.(⎕WS'Event'('SessionPrint' 'd')⊣⎕CY'dfns')
 
@Adám Added alias for ⋄
 
12:07 PM
⋄ a←⍳2 3 ⋄ ⎕←⍺
 
@Adám
VALUE ERROR
 
⋄ a←⍳2 3 ⋄ ⎕←a
 
@Adám
┌───┬───┬───┐
│1 1│1 2│1 3│
├───┼───┼───┤
│2 1│2 2│2 3│
└───┴───┴───┘
 
 
1 hour later…
1:11 PM
⎕←⎕SE.pco⍳100
 
@Adám
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541
 
Announcement: The chat bot now has the dfns workspace loaded into ⎕SE (when using ⎕← or ).
 
 
6 hours later…
7:05 PM
are object-oriented classes the only way to merge namespaces together in *.dyalog scripts?
hmm what's the point of :Require ns.dyalog if I can't reference ns.variable in my other script?
I can interact with both namespaces in the REPL, but it would be nicer to call functions in one namespace from the other namespace
 
7:22 PM
@ZhengqunKoo And you don't want to use dotted names to refer between namespaces?
@ZhengqunKoo Do you know that you can use ⎕NS to merge namespaces?
 
7:41 PM
let me be clearer: it would be nicer to call functions in one namespace script from the other namespace script
 
@ZhengqunKoo Like this?
 
sorry for my incomplete description, my namespaces are in dufferent files
e.g. ns2.dyalog, ns3.dyalog, and I want to call ns3.fn from ns2
 
@ZhengqunKoo Sure, but how are you running the code? Also, you can do ⎕FIX'file://path/to/ns.dyalog' to "import" such a namespace. After that, you can just do ns.fnname
@ZhengqunKoo I don't quite get what the problem is with :Require. Doesn't ns.variable work?
 
8:03 PM
ns3.dyalog:
:Namespace ns3
fn←{⍵ ⍵ ⍵}
:EndNamespace
ns2.dyalog:
:Require file://ns3.dyalog
:Namespace ns2
fn←{ns3.fn ⍵ ⍵}
:EndNamespace
⎕SE.SALT.Load'./ns2'⋄ns2.fn 1
VALUE ERROR: Undefined name: ns3
 
@ZhengqunKoo OK, first thing: Use ⎕FIX'file://./ns2.dyalog'
Then remember that ns3 isn't a member of ns2 but rather a sibling, that is, a child of ns2's parent. So use ##.ns3.fn
@frank Hi there. Interested in APL?
 
more or less, it looks interesting
 
@frank Do you want a quick intro?
 
sure
 
@frank OK, can I ask you what your background is? You know Python right?
 
8:13 PM
I do
dont have super in depth programming knowledge, im a mechanical engineering student
 
Ah cool. That's perfect.
So actually, it is easiest to grasp APL if you begin with the idea that it isn't just another programming language. Instead, look at it as an alternative mathematical notation where the inconsistencies and oddities of traditional mathematical notation (TMN) have been smoothed out, and various concepts (especially from linear algebra) have been generalised and harmonised.
Because it has been made regular and formalised, APL, as a mathematical notation, happens to be machine executable. However, it was actually originally meant as a notation for communication of mathematics between humans.
@frank So, e.g. you know how TMN (and Python etc.) have an order of evaluation; multiplication before addition, etc., right?
 
yes
 
APL has a very rich symbolic vocabulary, and instead of keeping a large list of precedences, it uses one simple rule: All functions have long right scope.
So, all functions have the same precedence, we just execute from right to left.
⍞←2×2+3
 
@Adám 10
 
ah I see
 
8:20 PM
Feel free to experiment with the APL bot at any time.
 
so the first 2 is multiplied by everything to the right of it
 
Exactly!
 
and the second 2 is added to everything to the right of it
 
Spot on.
 
interesting
 
8:21 PM
@Adám nice, thanks!
 
@frank There are a couple of reasons why APL uses right-to-left and not left-to-right, which I can go into if it bothers you. Otherwise, we'll just continue.
@ZhengqunKoo No problem. Sorry for the confusion.
 
It doesnt bother me but I am curious haha
 
OK, so in short, it generalises that f(x) and -x have their argument on their right, and it is also modelled after English which likewise is written and reads left-to-right, but actually parses from right to left: Reverse the old car — notice how each word applies to everything on its right until the end of the sentence.
Btw, APL uses proper mathematical symbols, not poor ASCII substitutes: × and ÷ are multiplication and division. There are many others: etc.
 
Makes sense
 
The most basic of APL's generalisations of TMN comes from the - symbol. Just like both a-b and -b have meaning, so to does APL allow all functions to have a dyadic (infix) meaning and a different (usually related) monadic (prefix) meaning.
In many cases the monadic form is identical to a dyadic call with a specific "default" left argument.
For minus, that'd be 0
For ÷ it is 1:
⍞←÷4
 
8:29 PM
@Adám 0.25
 
For × it is the reciprocal magnitude, which gives us the sign:
⍞←×-5
 
@Adám ¯1
 
Notice also that APL (and TI-Basic, btw.) uses a high minus as negative number prefix.
@frank Everything clear so far?
 
Makes sense so far yes
⍞←×0
 
@frank 0
 
8:33 PM
Yeah, so it isn't really the reciprocal magnitude, but you get the idea :-)
Let's talk about arrays.
In APL, all data resides in arrays. As opposed to Python (but in common with linear algebra, NumPy, and other mathematical libraries and programming languages), arrays can have any number of dimensions.
A single number, a scalar, has 0 dimensions. A vector has 1, and a matrix has 2, etc.
 
Scalars arent 1-dimensional?
 
@frank No, it isn't the number of dimensions in the space they map, but the number of axes along which their content is positioned.
 
Ah, I see
 
So in order to pinpoint which element of a list (i.e. a vector) we're talking about, we need exactly one index, while a matrix element needs two. A scalar does't need any indices, as there's only that one element.
In APL, you can write a vector simply juxtaposing the elements: 3 1 4 1 5 is the length-5 vector TMN would write as (3,1,4,1,5). The parenthesis and comma notation works fine in APL too, but is not necessary.
 
I was concatenating onto a long array just now with ,. Is it just my imagination, or is concatenating slower with a large array? I would have thought that appending to an array would be O(1)
(concatenating one element on, I mean)
 
8:40 PM
@codesections If you concatenate in-place, it is O(1), but if you preserve the original, APL needs to copy everything, so it becomes O(n).
 
@Adám By "concatenate in place" you mean with A,←⊢?
 
@codesections Yeah (but without the )
@frank Another thing APL generalises is the concept of higher order functions, which we call operators. E.g. ∑ and ∏ of TMN are really specific instances of a general concept, namely reducing the number of dimensions by 1 using a function, addition or multiplication in these two cases.
 
@Adám Hmm, the code I had that seemed to be O(n) was of the form large_vector,←(⊂single_element). But it sounds like you are saying that should have been O(1)?
 
@codesections Another thing that can change concatenation from O(1) to O(n) is if the internal representation has to be changed. Was large_vector a simple vector before the concatenation? Clearly you are appending a nested element.
@frank / is a higher order function (remember that ÷ is division) which takes a dyadic function on its immediate left and derives a new function, this one monadic, which is the corresponding reduction (or fold). Hence, +/ is sum, and ×/ is product:
⍞←+/3 1 4 1 5
 
@Adám 14
 
8:49 PM
So +/ and ∑ are essentially the same when applied to a vector?
 
@frank Yes, well, APL doesn't have ∑ as it is generalised away.
 
Ah I see what you mean
 
@codesections a thing to be wary of is to not keep large_vector around in any form before/after appending - y←x ⋄ x,←1 will be O(n)
 
Right, if you have a large_vector←original_large_vector they will share data internally, and so extending large_vector becomes O(n)
 
@Adám Well, the general form was to start with large_vector←⍬ and then use a recursive function to repeatedly apply large_vector,←(⊂single_element) (where single_element is a matrix of ints with ⍴ 3 4). I wouldn't think that involves changing the internal representation of large_vector, but maybe I'm confused?
 
8:55 PM
@frank Here's another generalisation: the dot product of two vectors is really a conjunction of repeated multiplication followed by repeated multiplication. APL generalises this into a dot operator which takes two functions, one on the left and one on the right, and conjoins them in the same way as + and × are handled in the dot product. Thus, the classical dot product is +.×:
⍞←3 1 4+.×2 1 7
 
@Adám 35
 
@dzaima Does defining large_vector outside a function and then modifying it from inside count as keeping it around in any form?
 
@codesections Right, if large_vector is already a vector of matrices, then it should be O(1), assuming there's enough free memory immediately following the current pocket. (We reserve extra space for such extensions, so there normally will be.)
@codesections Depends on the exact code.
 
@codesections this test seems to say modifying in a recursive function is fine
 
@frank But one could use any two functions like this:
⍞←1 1 0∨.∧1 0 1
 
8:58 PM
@Adám 1
 
⍞←3 1 4+.+2 1 7
 
⍞←0 1 0∨.∧1 0 1
 
@frank 18
@Adám 0
 
interesting
 
ngn
@codesections in dyalog a,←b can be O(1) only if you're lucky enough that the memory right after a is free, in addition to the conditions already mentioned
 
8:59 PM
@ngn I just said that :-)
@frank So these four are actually all the fundamental classes in APL: arrays, functions, monadic operators and dyadic operators. You know pretty much all of APL — syntactically speaking.
 
ngn
@Adám sorry. i'm a slow reader and even slower typist :)
 
There's thing to note about operators: They bind their operands with long left scope, continuing until the end of the left-hand array or function phrase (but only one of those, never both). So, e.g. +.×.+ is (+.×).+ and +.×/ is (+.×)/
@frank Do you want more? E.g. how to do matrices etc.?
 
Sure, if theres more to know about the language
 
Oh, sure. APL is very array oriented. "mapping" happens automatically:
⍞←2+3 4 5
 
@Adám 5 6 7
 
9:07 PM
⍞←10 20 30+3 4 5
 
@Adám 13 24 35
 
seems useful
 
Right, and pretty much all built-ins deal seamlessly with arrays. Arithmetic ones map like this, various structural ones each have their own (sensible) rules. E.g. membership:
⍞←3 1 4 1 5∊2 7 1 8 2 8
 
@Adám 0 1 0 1 0
 
As you've probably noticed by now, APL doesn't have any reserved words. You're free to use pretty much any Western European identifier. Assignment is done using :
⋄ print←42 ⋄ if←print print ⋄ ⎕←if
 
9:11 PM
@Adám
42 42
 
Comparison functions are considered like arithmetic functions, returning 0 and 1:
⍞←3 1 4 1 5≥2 7 1 8 1
 
@Adám 1 0 1 0 1
 
⍞←3 1 4 1=7 1 8 1
 
@Adám 0 1 0 1
 
This means that we can use summation to count truths:
⍞←+/3 1 4 1 5 9 2 7∊2 7 1 8
 
9:14 PM
@Adám 4
 
I.e. the left-hand vector has 4 elements that occur in the right-hand vector
@frank Do you know the Greek alphabet?
 
Some of it haha
 
No problem. The first, and therefore leftmost, character is ⍺ while the last, rightmost, is ⍵. When we define lambdas (we call them dfns — /dee-funs/) we use these to indicate the left argument and the right argument:
⍞←3 1 4 1 5 9 2 7 {+/⍺∊⍵} 2 7 1 8
 
@Adám 4
 
We can also name lambdas before use:
⋄ CountIn←{+/⍺∊⍵} ⋄ ⎕←3 1 4 1 5 9 2 7 CountIn 2 7 1 8
 
9:18 PM
@Adám
4
 
I didn't mention it before, but you've probably figured out that the diamond is the statement separator. Diamonds are unbreakable!
@frank Brain overflow, or are you OK with more?
 
Im fine with more, makes sense so far
think Im going to need some practice for it to really make sense lol
 
Good. I'm happy to hear that. And yes, let's find a task for you in a moment. I just want to give you one more function to play with:
(Greek Iota) generates Indices, or Integers if you want:
⍞←⍳10
 
@Adám 1 2 3 4 5 6 7 8 9 10
 
@frank Exercise: Find the sum of the first 100 odd numbers.
 
9:24 PM
Are APL arrays 1-indexed?
 
@frank You actually have a choice between 1 and 0. The bot has 1 as default.
Don't be afraid to experiment and build your solution piece by piece. In the worst case, the bot will shout about an error.
@frank Oh, you may want to have a look at this to facilitate typing the APL symbols.
You can experiment on tryapl.org if you prefer.
 
⍞←⍳50×2
 
@frank 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
 
@frank Remember that all functions have long right scope, so sees 50×2, thus this is equivalent to ⍳100
You can use parentheses exactly like you do in TMN.
 
⍞←(⍳50)×2
 
9:33 PM
@frank 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
 
⍞←+/((⍳50)×2)-1
 
@frank 2500
 
⍞←((⍳50)×2)-1
 
@frank 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
 
⍞←+/(((⍳50)×2)-1)
 
9:35 PM
@frank 2500
 
So that works, but I dont know if thats the best way to do it haha
 
@frank That's the sum of the first 50 odd numbers. I did ask for the first 100 ;-)
 
Oh I thought you meant odd numbers up to 100 haha
 
No problem. You get the idea.
@frank It is fine. I personally dislike parentheses, so I'd write:
⍞←+/¯1+2×⍳100
 
@Adám 10000
 
9:37 PM
Ah I see
Guess I was thinking in TMN haha
 
With time, you'll think in APL instead. Another thing we generalise is that all functions are inline prefix or suffix. So where TMN uses position in 3², APL uses the * symbol:
⍞←3*2
 
@Adám 9
 
Can you guess what the default left argument of * is?
 
Order of magnitude?
 
@frank That'd be the 10-logarithm, not the 10-to-the-power-of.
⍞←*1
 
9:40 PM
@Adám 2.718281828
 
oh its e?
 
Indeed. And log₁₀ is:
⍞←10⍟1000
 
@Adám 3
 
So obviously, monadic is ln.
@frank Challenge: using just the built-ins I've shown you, can you define a function Count which takes a numeric vector as argument, and returns its length?
 
⋄ Count←{+/⍵*0} ⋄ Count 2 3 4 5 6
oh forgot the bot
⋄ Count←{+/⍵*0} ⋄⍞← Count 2 3 4 5 6
 
9:46 PM
Due to certain technical limitations, you need a ⎕← there instead.
⋄ Count←{+/⍵*0} ⋄⎕← Count 2 3 4 5 6
 
@Adám
5
 
Don't worry, it is just when dealing with the bot. Try it!
Also: good job!
@frank Now write me an arithmetic mean function.
Feel free to use Count inside your definition: ⋄ Count←{+/⍵*0} ⋄ Mean←{…Count…} ⋄ ⎕←Mean 3 1 4 1 5
 
⋄ Count←{+/⍵*0} ⋄ Mean←{+/⍵÷Count⍵} ⋄ ⎕←Mean 3 1 4 1 5
 
The bot doesn't pick up on edits :-(
 
⋄ Count←{+/⍵*0} ⋄ Mean←{+/⍵÷Count⍵} ⋄ ⎕←Mean 3 1 4 1 5
 
9:51 PM
@frank
2.8
 
Yup. I'd probably go for parenthesising (+/⍵) for performance reasons, but you solution is of course correct.
Indexing works pretty much like in other languages, except you can index using an array:
 
oh is it summing ⍵÷Count⍵ instead of summing and then dividing
 
Exactly.
⍞←2 7 1 8 2 8[3 1 4 1 5]
 
@Adám 1 2 8 2 2
 
@frank Understand how ^ works?
 
9:54 PM
is it or?
 
Oh, no I meant how the indexing works :-D
Also, it'd be AND, , while OR is .
 
oh, yeah I understand, youre returning the elements of the vector on the left at each index on the right
is it returning a vector?
 
It is.
Now, using just the pieces you've learned. Can you write me a Reverse function such that Reverse 2 7 1 8 gives 8 1 7 2?
 
⋄ Count←{+/⍵*0} ⋄ Reverse←{⍵[Count ⍵ - ¯1 + ⍳Count⍵]} ⋄ ⎕←Reverse 2 7 1 8
 
@frank
8
 
10:01 PM
@frank Remember everything is right-to-left. So the leftmost Count sees everything on it's right as its argument.
 
⋄ Count←{+/⍵*0} ⋄ Reverse←{⍵[(Count ⍵)- ¯1 + ⍳Count⍵]} ⋄ ⎕←Reverse 2 7 1 8
 
@frank
8 1 7 2
 
Bravo!
Of course, APL has built-in functions for both counting and reversing, but I hope you enjoyed the exercises.
 
Yeah it was fun
 
Up for more?
 
10:02 PM
APL is very interesting haha
sure, Im up for more
 
OK, are you familiar with the TMN for floor, ⌊x⌋ ?
 
yes, I am
 
Since all functions in APL are either prefix or infix, and flooring only needs one argument, it is just:
⍞←⌊¯2.7 1.8
 
@Adám ¯3 1
 
Ceiling is of course
Fun fact: TMN actually got its notations from (proto-)APL, not the other way around.
Anyway, can you write a function IsDivisibleBy such that 15 IsDivisibleBy 5 gives 1 and 15 IsDivisibleBy 6 gives 0?
 
10:10 PM
IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ ⎕←15 IsDivisibleBy 5 ⋄ ⎕← 15 IsDivisibleBy 6
IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ ⎕←15 IsDivisibleBy 5
 
Ah, bot technicalities again. Since we don't want it to react to everything people write, it only looks for messages that being with and ⍞← and ⎕← (and a few other APL specifics).
 
Ah I see
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ ⎕←15 IsDivisibleBy 5 ⋄ ⎕← 15 IsDivisibleBy 6
 
@frank
1
0
 
There you go. And now you can write a Prime function which gives 1 if the argument is a prime, and 0 if it isn't.
Because, notice, that without any further effort your function works an any arrays:
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ ⎕←15 IsDivisibleBy 5 6
 
@Adám
1 0
 
10:14 PM
oh thats neat
 
Yup. APL allows you two denote concepts, and not worry about looping and other lowly stuff like that.
 
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ IsPrime←{2=+/⍵ IsDivisibleBy ⍳⍵} ⋄ ⎕←IsPrime 13
 
@frank
1
 
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ IsPrime←{2=+/⍵ IsDivisibleBy ⍳⍵} ⋄ ⎕←IsPrime 6
 
@frank
0
 
10:17 PM
Very well done. Notice that you just wrote a mathematical formula for primeness!
This one won't work on a vector argument, of course, because it needs to generate the indices. But would you like to hear about matrices now?
 
sure
 
OK, so let's introduce a new function denoted by Greek letter Rho, , which stands for reshape. It takes a shape on the left and content on the right, and returns an array of the requested shape, filled with the given content. If there isn't enough content, it recycles the content:
⎕←5⍴3 1 4
 
@Adám
3 1 4 3 1
 
We can use this to produce a matrix too:
⎕←2 3⍴3 1 4 1 5
 
@Adám
3 1 4
1 5 3
 
10:22 PM
Repeated reshaping is fine:
⎕←4⍴2 3⍴3 1 4 1 5
 
@Adám
3 1 4 1
 
The data is used in row-major order.
@frank Can you guess what needs to go on the left of in order to reshape something into a scalar?
 
0?
 
That'd make a length-0 list:
⎕←0⍴3 1 4 1 5
 
@Adám
 
10:25 PM
ah itd be 1 then
 
Length-0 lists tend to be hard to see ;-)
@frank That'd make a length-1 list, which is not a scalar, though they appear similar to each other. checks for complete equivalence:
⎕←42 ⋄ ⎕←1⍴42 ⋄ ⎕←42≡1⍴42
 
@Adám
42
42
0
 
is scalar the default argument for ⍴?
 
@frank Nope, not that either. Monadic queries the current shape rather than reshapes:
⎕←⍴3 1 4 1 5 ⋄ ⎕←⍴2 3⍴3 1 4 1 5
 
@Adám
5
2 3
 
10:27 PM
@frank Think about it. How many axes does a scalar have?
 
0, right
 
So since the left argument to is the list of lengths along each axis, we'd need a list of lengths along 0 axes, i.e. a length-0 list.
 
ah that makes sense
so something like ()
 
@frank Well, we just made one right before, using 0⍴
⎕←(0⍴0)⍴3 1 4 1 5 ⋄ ⎕←3≡(0⍴0)⍴3 1 4 1 5
 
@Adám
3
1
 
10:31 PM
@frank Although, for convenience, we do provide a short notation, as 0-length lists are very commonly used: It is a 0 overstruck with a tilde ~, the tilde symbolising "not" or "nothing".
⍞←⍬≡0⍴0
 
@Adám 1
 
In fact, ~ is also the NOT function:
⍞←~0 1 0
 
@Adám 1 0 1
 
@frank Want more?
 
Shoot!
 
10:35 PM
Are you familiar with the concept of an outer (or Cartesian) product?
 
yes, from using pyth haha
 
Oh, cool. Well, in APL it is generalised such that ∘.× is the outer product (it is notationally similar to the dot product +.× except we don't do the final summation, so the signals a null-operation here). Effectively, a multiplication table:
⎕←1 2 3∘.×1 2 3 4 5 6
 
@Adám
1 2 3  4  5  6
2 4 6  8 10 12
3 6 9 12 15 18
 
Of course, just as with other operators, any function goes:
⎕←1 2 3∘.+10 20 30 40 50
 
@Adám
11 21 31 41 51
12 22 32 42 52
13 23 33 43 53
 
10:38 PM
And of course, user-defined functions work with all operators as well:
⋄ MyFn←{⍺+2×⍵} ⋄ ⎕←1 2 3∘.MyFn 10 20 30 40 50
 
@Adám
21 41 61 81 101
22 42 62 82 102
23 43 63 83 103
 
Here's another really useful function: gives the indices of the 1s:
⎕←⍸0 1 0 0 1 0 1
 
@Adám
2 5 7
 
@frank Task: PrimesUntil such that PrimesUntil 20 gives 2 3 5 7 11 13 17 19
 
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ IsPrime←{2=+/⍵ IsDivisibleBy ⍳⍵} ⋄ PrimesUntil←{⍵[⍸IsPrime ⍳⍵]} ⋄ ⎕←PrimesUntil 20
 
10:51 PM
@frank
LIMIT ERROR
 
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ IsPrime←{2=+/⍵ IsDivisibleBy ⍳⍵} ⋄ PrimesUntil←{⍳⍵[⍸IsPrime ⍳⍵]} ⋄ ⎕←PrimesUntil 20
 
@frank
LIMIT ERROR
 
@frank Try to start with the divisibility table — don't use your IsPrime function.
 
⋄ DivTable ← {⍳⍵∘.÷⍳⍵} ⋄ ⎕←DivTable 20
 
@frank
LIMIT ERROR
 
10:55 PM
@frank You need (⍳⍵) on the left.
Remember: long right scope for all functions!
However, that is a division table, not a divisibility table.
 
⋄ IsDivisibleBy←{(⍺÷⍵)=⌊⍺÷⍵} ⋄ DivTable←{(⍳⍵)∘.IsDivisibleBy ⍳⍵} ⋄ ⎕←DivTable 20
 
@frank
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
1 1 1 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
 
Good, now look at this:
⎕←1 2 3∘.+10 20 30 ⋄ ⎕←+/1 2 3∘.+10 20 30
 
@Adám
11 21 31
12 22 32
13 23 33
63 66 69
 
02:00 - 23:0023:00 - 00:00

« first day (1051 days earlier)      last day (1604 days later) »