« first day (1091 days earlier)      last day (1564 days later) » 

3:30 AM
0
Q: What changes about the data type of this APL variable with these lines of code?

Jaden RanzenbergerI am writing a text file from APL. I have a character matrix defined as UMMB in my APL script, which is being used for the body of this text file. I am able to successfully call my .txt document writing function using this variable as the body. When I do the following, however: k←⊂⍕UMMB m←⊂'<html>

 
 
9 hours later…
12:31 PM
@Bubbler how would you distinguish stuff like f g 1, is f applied on g 1, or is f applied on g and 1?
@Bubbler what would distinguish this from a lisp?
 
@Adám - Assuming you're conversant in Pascal, please check my understanding: RANK in APL is purely the number of dimensions - that is, APL RANK 2 (e.g., 3 3 rho iota 9) is like Pascal ARRAY [1..3,1..3] OF INTEGER, where as APL DEPTH (e.g. (1 2 3)(4 5 6)(7 8 9)) is like Pascal ARRAY [1..3] OF ARRAY [1..3] OF INTEGER.
 
@JeffZeitlin Correct.
 
And that's also reflected in indexing; taking the 5 from 3 3 rho iota 9 would be (in #IO<-1) A[2;2], while from the second example would be A[2][2] - mirroring the Pascal syntax (modulo APL semicolon for Pascal comma).
 
12:46 PM
@JeffZeitlin And modulo as you really need ⊃(⊃A[2])[2]. However, it is easier on the eyes to do 2⌷2⌷A for the matrix case and 2⊃2⊃A for the vector-of-vectors case.
And 2⌷2⌷A is the same as 2 2⌷A while 2⊃2⊃A is the same as 2 2⊃A.
 
Uh? I don't recognize either of those operators - remember, I'm more-or-less coming from a TradAPL environment. Why do I want that left-cup or narrow-quad rather than the pure bracket notation that I recall?
@Adám - also, is it better to "ping" you on every reply, rather than assuming a "live" convo?
 
@JeffZeitlin It is, especially if I'm in the middle of giving a workshop :-D
 
@Adám :)
 
@JeffZeitlin is a functional form of [] which can work on an array without making assumptions about the rank of the array. Traditional brackets needs zero or more ;s matching the array rank minus one. is a new function to give the same kind of functionality for nested arrays.
Oh, and neither nor [] will ever "open up" elements of a nested array.
 
1:02 PM
@Adám I see! In the matrix case, A[2] gives a RANK ERROR, whereas 2 nquad A gives me 4 5 6, the entire second row. Making the nquad notation actually a bit more flexible.
@Adám (I should note that I'm being a bit lazy - I do have Dyalog open in another window, just haven't been bothering to cutpaste the actual APL code, hence things like "rho iota" and "nquad"...)
 
@JeffZeitlin is called "squad" or "squish quad", though it has no more connection to than its shape. It is actually [ and ] merged together!
@JeffZeitlin Which OS are you on?
 
@Adám Win10, and I did just discover the Dyalog IME :) Ctrl for the APL symbols, rather than the traditional unicase keyboard.
 
Right. If Ctrl bothers you (interfering with Select All on Ctrl-A etc.), you can uninstall the IME and install this to use right-side Alt instead.
 
@Adam - With the caveat that I'm on a Blink browser, and it's suboptimal for overstrikes, do overstrikes in fact work in Dyalog proper? I'm OK with Ctrl; I tend to think of AltGr (right-side Alt) for multilingual word processing characters (e.g., A-with-ring, O-with-slash, AE ligature, etc.)
@Adám - I do remember most TradAPLs using overstrikes for some of the extended functions (e.g., quote-quad)
 
@JeffZeitlin The only Blink-vs-APL issue is which looks like ≡/ And yes, overstrikes do work in Dyalog. If you switch to Replace mode by pressing your Insert button or double-click Ins in the status bar, then, if you try writing a character on an existing character, and they can be overstruck, they will combine. E.g. / and - on top becomes .
@JeffZeitlin While the above works, Dyalog has assigned keystrokes to all composite symbols, often useing Ctrl+Shift. E.g. is Ctrl+Shift+[
 
1:17 PM
@Adám OK, good - as I indicated, coming from TradAPL, I'll be tending to think of overstrikes rather than looking for a single keystroke. I do note that pointing at the graphical bar does give me the single stroke, too.
 
@JeffZeitlin If I recall correctly, you can also go to Options>Configure>Unicode Input and enable a sleeker way to do overstrikes.
 
1:35 PM
@Adám - OK, after playing a bit, I think I have a workable understanding: ⌷ works only on rank; if I need to pull something out of depth, I need ⊃
 
Correct. And works only on depth; it can never keep the initial depth.
 
@Adám - I may be missing something fundamental about rank, though: Why is ⍴ of a scalar null, rather than 0?
 
@JeffZeitlin is shape, not rank. gives you the length along each axis. A scalar has zero axes, so the result of is a list of length zero.
 
@Adám Ah. Yes, that's a pretty fundamental "miss".
@Adám - What I was obviously confusing with ⍴ was ⍴⍴ - which does return 0 for a scalar.
 
1:51 PM
@JeffZeitlin Yes, but you should use ≢⍴ to get a scalar result rather than a 1-element vector.
 
⍴⍴⍴1
Ignore that - wrong window
 
@Adám :D
@Adám - But it does point up the fact that ⍴⍴ returns a 1-element vector - if it returned a scalar, ⍴⍴⍴ should logically be null!
 
@JeffZeitlin Btw, "null" is not the best name for 0⍴0. While modern (well, even quite old) APL has ("zilde") as a shorthand for (0⍴0), you also want to distinguish it from '' which is the "null string" (or more precisely, an "empty character vector") and all other empty vectors (there are infinitely many). Dyalog also has ⎕NULL which is its own data type and corresponds to null in many languages, and to empty cells in spreadsheets.
 
2:07 PM
@Adám - So what ⍴ of a scalar is returning is actually zilde? Or is it ⎕NULL?
 
@JeffZeitlin It is identical to zilde, or 0⍴0. You can test it:
⎕←(0⍴0)≡⍴'a' ⋄ ⎕←''≡⍴'a'
 
@Adám
1
0
 
@Adám - I see! So null values are typed in APL, and all null values are not created equal. 0↑'ABCD' is the null string, not zilde; 0↑1 2 3 4 is zilde.
 
@JeffZeitlin Exactly, and 0↑('a'1)('b'2) is a zero-element vector where each of the non-existing elements is a two-element vector consisting of a character and a number.
 
@Adám - ...
@Adám - OK, I see how that is.
@Adám - It actually makes sense; you're taking elements from a vector/matrix, so even if "empty/null", their type doesn't and shouldn't change.
@Adám - This is fundamental in strongly-typed languages; if I declare (in Pascal) VAR A: INTEGER;, it's still an INTEGER even if I never actually say A:=....
@Adám - (but somehow I never really perceived APL as being a strongly-typed language)
 
2:23 PM
No languages (other than APL) handle dynamic typing+type preservation in empties. It allows you to apply many transformation functions even if the argument is empty, and still get a meaningful result back. Also, you can extend an empty array and get a meaningful result.
⎕←(3↑⍬),42 ⋄ ⎕←(3↑''),'*'
 
@Adám
0 0 0 42
   *
 
Compare with:
⎕←(3↑''),42 ⋄ ⎕←(3↑⍬),'*'
 
@Adám
    42
0 0 0 *
 
@JeffZeitlin It isn't, and it does tend to auto-convert empty arrays to an appropriate type. E.g. 1+'' gives
 
2:36 PM
@Adám - Hmm... And it doesn't seem to matter whether I add '' to 1, or 1 to ''; it's still zilde.
 
@JeffZeitlin Right, because dyadic + returns numbers.
 
@Adám - So what is 'concatenate', e.g., 'A' ¿ 'B' -> 'AB' ?
 
@JeffZeitlin I'm not sure what you're asking. '',⍬ ? It is necessarily an arbitrary decision for the language implementors.
Dyalog makes it the left argument. Other dialects make it the right argument.
 
@Adám - No, I'm asking what the operator is for concatenation - e.g., if I have Z←'AB' and Y←'DE', and I want to make W←... equal to 'ABDE', what operation do I perform on Z and Y to get W?
 
Oh, that'd be ,
 
2:45 PM
@Adám - Ah.
 
Although you may also want to look at which joins along the leading axis. (Same as , for vectors, but adding rows to matrices.)
 
That's comma-bar? (It's a little small on this display.)
 
It is. Comma-bar tends to look tiny in fonts that are not geared especially for APL.
 
3:31 PM
Are there any APL variants that have a 1 byte increment function?
 
@EdgyNerd - What do you mean?
 
3:52 PM
@EdgyNerd I don't think so. J has increment and decrement, but they are two characters each.
@JeffZeitlin A built-in function equivalent to {1+⍵}. The closest are the tacit functions +∘1 and 1+⊢ etc.
 
4:08 PM
@Elronnd Hi there. Interested in APL?
 
4:32 PM
no way, @Elronnd would you happen to be the same elronnd as the co-contributor of slex?
 
 
1 hour later…
5:56 PM
@Adám - I'm looking at the list of bookmarked lessons, and a question arises: What is the distinction between a 'function' and an 'operator'?
 
@JeffZeitlin A function takes one or two arrays as arguments and (optionally) returns an array as result. An operator takes one or two operands (each operand can itself be a function or an array) and derives a new function from an infinite set of related functions. This derived function can in turn be applied to one or two array arguments.
E.g. is a function, while ¨ is a monadic operator (it takes a single operand) and derives a function from that.
 
@Adám - Clear as mud, I'm afraid.
 
¨ can (currently) only derive meaningful functions from function operands, but you can still give it an array operand and get a function back — the derived function just won't have any valid use.
So is (monadically ) the "reverse" function, while f←⌽¨ makes f into a new function we could call "reverse-each".
so f is a member of the family of functions that do something on each element of an array rather than on the array as a whole.
⍴¨ is another member of that family. It finds the shape of the elements of an array.
 
@Adám - AH! ¨ is like piping to ForEach-Object {...} in PowerShell, as opposed to just letting the scriptblock {...} operate on the whole collection coming from the pipeline at once.
 
@JeffZeitlin Right, but there are many other operators, and you can write your own too. E.g. @ is a dyadic operator. It can take an array left operand and an array right operand, e.g. 2@3 is a new function which replaces the third element of its argument with a 2.
Clearly, @ can derive an infinite set of functions. E.g. 2@4 replaces the fourth element of its argument with a 2.
So you can use operators to generalise your code, and indeed, this is what APL does by not having a "sum" and a "product" function, but rather having a "reduce" operator / which takes a function and derives a new function. The derived function reduces its argument along the trailing axis by inserting the original operand between all elements, so +/ is sum and ×/ is product.
 
6:10 PM
@Adám - So, operators apply functions to data in ways "extended" from the normal syntax/semantics of the function being applied?
 
Yes, but some operators are also able to do so based on one or two array operands, without any base function's syntax or semantics.
If you learn a way to write your own operators, this may become clearer.
 
@Adám - OK, that sounds confusing.
 
You're familiar with dfns, right?
 
@Adám - Ummm... No. I know they exist, but I don't really 'get' them.
 
OK, simplified, a dfn is an expression in curly braces with for the right argument and optionally for the left argument. E.g.:
⍞← {'→→→',⍵,⍵,'←←←'} 'text'
 
6:15 PM
@Adám →→→texttext←←←
 
@JeffZeitlin Makes sense?
 
@Adám OK, I think so. How is this different/better than traditional functions (that in line-oriented APLs were edited with the editor)
 
@JeffZeitlin Both traditional functions (tradfns) and dfns have their place. Dfns are neat for inline usage, to group functionality, and they conveniently auto-localise upon assignment. They also make error-trapping and simple conditionals very straight-forward. Tradfns have a rich set of flow control and are also necessary for many OO-related jobs.
 
6:33 PM
@Adám OK, so a dfn can be created 'on the fly' for what amounts to 'one liners'
@Adám So, you're implying that a dfn can be an operator?
 
@JeffZeitlin Yes. Although they can actually have multiple statements too. And you can give them a name for later usage, using the assignment arrow syntax myfn←{something}
@JeffZeitlin No, but "dops" use a syntax very similar to dfns. They just use ⍺⍺ to represent the left operand, and optionally ⍵⍵ for the right operand. E.g. we can write a function Increment←{⍵+1} and an operator Twice←{⍺⍺ ⍺⍺ ⍵}:
⋄ Increment←{⍵+1}
⋄ Twice←{⍺⍺ ⍺⍺ ⍵}
⋄ ⎕←Increment Twice 10
 
@Adám
12
 
@Adám /me blinks
@Adám - Why the doubling of alpha?
 
@JeffZeitlin That means the left operand, as opposed to the left argument.
We can have an operator Mold←{⍺⍺ ⍵⍵⍴⍺,⍺↓⍳⍵} which creates a matrix with as many rows as indicated by its left operand and as many columns as indicated by its right operand, filled cyclically with numbers from the left argument until the right argument:
⋄ Mold←{⍺⍺ ⍵⍵⍴⍺,⍺↓⍳⍵}
⋄ Mold3_4←3 Mold 4
⋄ ⎕←2 Mold3_4 7
 
@Adám
2 3 4 5
6 7 2 3
4 5 6 7
 
6:41 PM
Or we could inline it all:
⎕←2 (3{⍺⍺ ⍵⍵⍴⍺,⍺↓⍳⍵}4) 7
 
@Adám
2 3 4 5
6 7 2 3
4 5 6 7
 
0
Q: What changes about the data type of this APL variable with these lines of code (Part two)?

Jaden RanzenbergerI am writing a text file from APL. I have a character matrix defined as UMMB in my APL script, which is being used for the body of this text file. I am able to successfully call my .txt document writing function using this variable as the body. I then run the following code on the matrix, (which...

 
OK, I _think_ I _barely_ followed that. The effect was to execute `3 4 ⍴ 2, 2↓⍳7`, which, if I'm interpreting correctly, says... (assuming `⎕IO` is 1)
1. drop the first two numbers from the vector 1 2 3 4 5 6 7 -> 3 4 5 6 7
2. prefix a 2 to it -> 2 3 4 5 6 7
3. take that vector, and apply the shape of 3 rows and 4 columns to it, repeating the data as needed to fill.
@Adám - The parens were necessary to distinguish the 3 and 4 from the 2 and 7, rather than having the system interpret them as vectors of 2 3 and 4 7?
 
@JeffZeitlin (markdown doesn't work on multi-line messages)
 
(So I discovered :( )
 
7:03 PM
@JeffZeitlin All correct. (Sorry for the delay — cooking dinner.)
 
@Adám ¡De Nada! I'm multitasking, myself - as much as I'd like it to be, studying APL isn't my day job; I'm doing user-support for a Windows network. But as long as the calls aren't overwhelming, I'm allowed to pursue other interests as well.
@Adám - So, I couldn't write Mold as a tradfn, I can see that. But can I use tradfns as operands to dfns?
 
@JeffZeitlin Yes, you can, but you can also write Mold as a tradop :-)
 
@Adám /me blinks. Several times. O-kay... that's beyond what I was aware was possible in APL - writing operators was not something that I ever saw in any of my APL books...
 
@JeffZeitlin It is a relatively new ability, so old books won't mention it.
 
@Adám Thus explaining the omission - I'm pretty sure all of my APL books predate APL-on-personal-computers. Including predating the IBM5100.
 
 
1 hour later…
8:23 PM
/me finishes industriously downloading documentation, and wonders if the Compleat Dyalog Documentation Set is sufficient, or whether he should also scavenge the web for a (comparatively recent) APL textbook
 
@JeffZeitlin All of the documentation is including in your install in "C:\Program Files\Dyalog\Dyalog APL-64 17.1 Unicode\help" but as for a book, look at Mastering Dyalog APL.
 
@Adám - Included in the pile of PDFs I've got here.
 
 
2 hours later…
10:54 PM
@KritixiLithos That will be distinguished by the type of g. If g is monadic, it is f (g 1), otherwise f and 1 are the two arguments of g.
One downside of this is that we no longer have ambivalent functions (and thus overloaded built-in symbols).
And we'll definitely have fewer parens than a lisp (which needs a paren per every function application).
 
11:16 PM
@Bubbler is f (g 1) "f applied to the result of applying g on 1" or "f applied to the array [g, 1]"?
aka, fns as proper values = no strand notation, at which point the syntax slowly goes to k's. (not that that's a bad thing, an apl with k-ish syntax (but still unicode) is one of many apl things i'd like to attempt to make at some point)
though keeping types (whether static or dynamic) is an interesting difference. no custom dyadic fns in k is one unfortunate result of its syntax
 
11:33 PM
@dzaima I meant the former.
And yeah, I missed that g can be a nilad, in which case the strand notation is applied, and the result will be "f applied to array [g,1]".
 

« first day (1091 days earlier)      last day (1564 days later) »