« first day (357 days earlier)      last day (2281 days later) » 

12:01 AM
⍞←=/2 2J1E¯13
 
@Uriel 0
 
@Adám looks like the dev team wouldn't be bored for a while
 
@Uriel What do you mean?
 
@Adám um, this behaviour looks a bit buggy
 
@Uriel It isn't, it follows the ISO spec. I'm just fooling around the edges of the default comparison tolerance. Setting ⎕CT←0 gives you expected results even there:
⍞←=/2 2J1E¯14 ⊣ ⎕CT←0
 
12:04 AM
@Adám 0
 
@Uriel Often, ⎕CT is really helpful:
⍞←0J1=×⍨*○0J0.25
 
@Adám 1
 
ngn
⎕←≢∪1+1e¯14×?⍨100
 
@ngn
40
 
@Adám oh I didn't realize the -1 was vectorizing. But then again, why does -2 makes the difference more noticeable? Special behaviour for 0 vs 0+epsilon?
 
12:06 AM
i = (e^(0.25πi))²
⍞←0J1=×⍨*○0J0.25 ⊣ ⎕CT←0
 
@Adám 0
 
@DyalogAPL Wat?
@Uriel ⎕CT is a relative fuzz, but when one of the terms is truly zero, adding a certain percentage still yields truly zero, hence ⎕CT is (as if) ignored on comparisons with zero.
 
@Adám I'm starting to feel bad for whoever had to review these ISOs.
 
@Uriel Why? Complexity?
 
@Adám bordering wierdity
 
12:13 AM
@Uriel Can you come up with a better way to implement fuzz dealing with the inexactness of binary floats?
@NH. Interested in learning APL?
 
@Adám what's fuzz? And I can do such a thing by keeping πs as irrationals (following Julia and sympy)
 
@Uriel I suspect that has a large performance hit.
@Uriel Fuzz is inexactness in comparison.
 
@Adám well, I guess it won't really matter once quantum computing goes public, eh?
 
@Uriel It hadn't yet gone public when the ISO spec was written.
 
@Adám I guess neither did storage devices over a few kilobytes
 
12:24 AM
@Uriel That's not true. My father had a PC with 115 MB hard disk years before that spec came out, and mainframes had way more storage than that. Anyway, what's your point?
 
@Adám I can't believe it. Whopping 115 MB? What could he have done with all of that storage?
Oh, I was just making your point stronger
 
@Uriel :-) He had to split it into C:, D:, E:, and F: because DOS 3.3 couldn't address such huge disks.
@Uriel Oh, ok.
 
ngn
@Uriel will quantum computing speed up floating point operations, though?
 
@ngn no, but dna based storage will make a precision of millions or billions of digits a trivial thing
 
@Uriel A lot of today's computing is limited by memory throughput rather than by computation speed. I suspect DNA storage will remain too slow to meaningfully represent extended precision for computation.
 
ngn
12:37 AM
@Uriel millions (1MB) and billions (1GB) of digits (assuming 1 per byte) doesn't sound an impressive by today's standards :)
@Adám the killer feature of DNA computing is massive parallelism
 
@ngn Fair enough, but a lot of applications have limited potential for parallelisation.
Meanwhile, we're limited to 64-bit floats if we want reasonable performance, but then we need inexact comparisons so that traditional mathematics will appear to work.
 
ngn
@Adám I wish floating point had never been invented...
 
@ngn Some early computers were decimal, and you can also set ⎕FR←1287, but even decimal representations need fuzz, hence ⎕DCT.
 
ngn
@Adám most applications have a definite scale in which their variables vary, but cpus and programming languages make it easy to use floating point and hard to use fixed point calculations
 
@ngn What's a fixed point calculation?
 
ngn
12:44 AM
@Adám you know, in floating point you have a mantissa and an exponent, right?
 
@ngn Yes.
 
ngn
@Adám fixed point would be the same, but the exponent is implicit, and all the bits are used for the mantissa
@Adám like integers have a fixed exponent of 0
@Adám if, say, you need precision down to 0.125, you could use a fixed exponent of -3
 
@ngn Ah, right. We discussed such a thing with SimCorp since they are now beginning to deal with very large amounts of money (which must stay exact). I suggested storing the amount as an int in the smallest unit instead of as a float in the main denomination.
 
ngn
@Adám oh, I think storing money as floating point should be declared a criminal offence :)
 
@ngn Isn't stealing already prohibited?
 
ngn
12:49 AM
@Adám only when the general population do it :)
@Adám money can be stored in pennies (cents, whatever) in a 64-bit integer (ideally with some measures against overflow)
 
@ngn That was my suggestion.
 
ngn
@Adám if anyone has more than 2^64 / 100 money in any currency, they can probably afford to store their variables in hardonic colliders :)
@Adám the problem with Dyalog is, there isn't a 64-bit integral type
 
@ngn We're contemplating adding it. Problem is how to switch to floats when it overflows. Currently, every type that has bigger absolute range has higher precision too, but overflowing from 64-bit int to 64-bit float would lose precision.
 
ngn
@Adám I think I've been through this line of argument
@Adám my favourite solution is to keep them separated - never convert int to float or vice versa automatically
@Adám like two separate numeric towers
@Adám but I realise that's not gonna fly with legacy applications...
 
@ngn With ⎕FR←1287 it is fine, as 128-bit decimal has more precision than 64-bit int, so maybe we could simply not use 64-bit ints when ⎕FR←645?
 
ngn
12:59 AM
@Adám good point
 
@ngn Again, anything that removes current features is out of the question. Feel free to do it in a new language, though.
 
ngn
@Adám a few days ago I decided to add floating point to my k impl :)
 
@ngn Problem then becomes performance. With ⎕FR←1287 all floats are decimal, even if not needed to represent the float fully, e.g. 1.5.
 
ngn
@Adám I got stuck at an unexpected place - how do you fucking print a floating point number? :)
 
@ngn You mean to differentiate it from the corresponding int?
 
ngn
1:01 AM
@Adám no, how do you print its value, its digits
 
@ngn Oh, you mean you have to covert from binary to decimal?
 
ngn
@Adám without dtoa(), as I don't use stdlib
@Adám you have a double, how do fill a char[] with its digits
 
@ngn Heheh, welcome to binary computing.
 
ngn
@Adám you could use floating point operations like *10.0 and %10.0 to get the digits one at a time (that's how I do it for ints), but with FP there are so many things that can go wrong
 
@ngn Well, you could implement your own decimal floats.
 
ngn
1:06 AM
@Adám cpus are fast only on the ieee format
 
@ngn Well, there's your dilemma. Who said it would be easy?
@ngn Actually, Power has hardware support for decimal floats.
 
ngn
@Adám cool, but nobody (to a first approximation) uses them :)
@Adám another problem I have with FP is loss of information when printed
 
@ngn Hey, why don't you just print them in hex?
 
ngn
@Adám that's what I did first - binary, actually :)
@Adám not very useful, though
 
@ngn Every PL needs to balance usefulness with ease of implementation.
 
ngn
1:12 AM
@Adám true, but it's surprising how the most useful stuff is the easiest to implement
@Adám and how much effort and white hair is due to stuff you don't actually need
@Adám so, maybe I don't need FP after all :)
 
On that note, I'll retire for the night.
 
ngn
@Adám ok, good night and see you around ppcg :)
 
 
9 hours later…
10:25 AM
@ngn well, it is if you use it as default for every float. especially considering most of the modern languages default with 4 Bytes
 
 
1 hour later…
11:50 AM
Last month, SimCorp Ukraine celebrated their 10 year anniversary. Amazingly, of the 60 that joined back in 2007, 28 are still part of the team today. Congrats to SimCorp Ukraine!
 
12:06 PM
@Adám Hey Adam! I'm trying to make sense of this function so I can post it later, but I'm having some trouble figuring it out. ≠/∧⌽∧.=(+/∘∊⍳⊆⍨0=⍳|⊢)¨ So, the expression in parenthesis is evaluated first, and inside it we first evaluate ⍳|⊢, then 0=, then we use this result as left argument for ∊⍳⊆, is that right?
 
@J.Sallé Up until 0= is correct. That then becomes the left argument to with being the right argument (as the arguments of are swapped by ). Then the monadic derived function +/∘∊ is applied to that.
 
@Adám ah, I see. I was trying to group it in groups of 3 because I remember you saying something about that
 
@J.Sallé You can see the structure by using ]box on -trains=parens. It gives ≠/∧(⌽(∧.=)(((+/)∘∊(⍳(⊆⍨)(0=(⍳|⊢))))¨))
⎕←≠/∧⌽∧.=(+/∘∊⍳⊆⍨0=⍳|⊢)¨ ⍝ tree view
 
@Adám
  ┌─┼───┐
  / ∧ ┌─┼──────┐
┌─┘   ⌽ .      ¨
≠      ┌┴┐   ┌─┘
       ∧ = ┌─┴──┐
           ∘  ┌─┼───┐
          ┌┴┐ ⍳ ⍨ ┌─┼───┐
          / ∊ ┌─┘ 0 = ┌─┼─┐
        ┌─┘   ⊆       ⍳ | ⊢
        +
 
@Adám oooooh, that's useful
 
12:17 PM
@J.Sallé So as you can see, it does group into groups of 3, from the right of course.
 
@Adám I see, I see. That's handy.
 
12:32 PM
@Adám Could you explain this bit here ∧⌽∧.=? I don't think I've ever used the dot operator before so I don't know what it's actually doing there
 
1:02 PM
@J.Sallé In the general case, it is quite complex (f.g is an inner product, but using f and g instead of + and × in regular mathematics). However, if you just use scalars and/or vectors as arguments, then A f.g B is the same as f/ A g B. With the same number of characters, why use f.g? Because it is a dyadic function, so it fits into a train without needing parens to create the atop by writing (f/g).
 
@Adám Ah, I think I get it. So, assuming A is and B is the expression in parenthesis, it's doing ∧/⌽=B?
 
@J.Sallé Yes, exactly.
 
Great, I think I can explain it now :p
 
@J.Sallé You can see it in action twice here:
0
A: Prime counting function

AdámAPL (Dyalog Unicode), 13 bytesSBCS 2+.=0+.=⍳∘.|⍳ Try it online! ⍳ ɩndices 1…N  ⧽ ∘.| remainder-table (using those two as axes) ⍳ ɩndices 1…N 0+.= the sum of the elements equal to zero (i.e. how many dividers does each have) 2+.= the sum of the elements equal to two (i.e. how many primes a...

 
@Adám ⍳∘.|⍳ is also doing something like ∘/⍳|⍳? I don't think ∘/ is a thing though so I assume that's the only way to do that?
 
1:12 PM
@J.Sallé isn't the left operand of . in that case, ∘. is special syntax for outer product for historical reasons
 
@J.Sallé Ninja'd.
 
special syntax because it only takes a right operand, contrary to what we usually call an operator
 
Aaaaaaah I see, so it's as if ∘. was a single op/fn
 
@J.Sallé @EriktheOutgolfer We can retcon ∘.f to be syntactic sugar for f⍤0 15 which does follow regular syntax.
@J.Sallé Op.
 
@Adám I mix those around so much I just use op/fn now :p
 
1:15 PM
I think it actually behaves more like a dyadic operator but without the left operand
 
@EriktheOutgolfer Well, more like a dyadic operator which analyses its left operand and takes appropriate action. Iverson actually suggested that ∘.f is 0.f where .←{2=⎕NC'⍺⍺':⍺(⍵⍵⍤⍺⍺ 15)⍵ ⋄ ⍺ ⍺⍺.⍵⍵ ⍵}
 
0
A: Are the numbers amicable?

J. SalléAPL (Dyalog Unicode), 45 38 44 36 35 bytes {(≠/⍵)∧(⌽⍵)≡+/¨¯1↓¨(0=⍵|⍨⍳¨⍵)/¨⍳¨⍵} Try it online! Infix Dfn, fixed for the equal inputs case. Thanks @Uriel for 8 bytes; @cole for 1 byte. How? {(≠/⍵)∧(⌽⍵)≡+/¨¯1↓¨(0=⍵|⍨⍳¨⍵)/¨⍳¨⍵} ⍝ Main function, infix. Input is ⍵. { ...

@Adám could you take a look at the explanations when you have some time?
 
@J.Sallé with Boolean left arg groups corresponding to 1-runs.
@J.Sallé I would separate the from +/∘ with the description ⍝ and then
 
@Adám I was going to separate those but I didn't have a good explanation for what did hahahahah. I'll edit those in.
 
@J.Sallé ⌽∧.= ⍝ This is a shorter way to write ⌽(∧/=); So, it returns…
 
1:29 PM
@Adám oh okay, took me a second to figure this one out rofl
 
@J.Sallé Actually, scrap that. I just realised that ∧.= can be written as in your case.
 
@Adám just the ?
 
@J.Sallé Yes.
 
@Adám Oh nice!
 
@J.Sallé Clearly, if all elements ∧/ are equal = then they are identical .
 
1:34 PM
@Adám Indeed they are hahahahah
 
2:02 PM
@J.Sallé Your byte count should be 20.
 
@Adám I kept it at 35 because the Dfn is first on the post, should I swap them around? (or maybe just remove the Dfn answer altogether?)
 
@J.Sallé Well, the progression from dfn to train is nice, but your score should just be whatever is the shortest in the post, i.e. 20.
 
@Adám I see, I'll update it then.
 
2:22 PM
Informal APL learning session tonight at 18:30 UTC in https://chat.stackexchange.com/rooms/52405/apl. See https://chat.stackexchange.com/transcript/message/41299896 if you don't have 20 Stack Exchange rep points.
Informal APL learning session tonight at 18:30 UTC in https://chat.stackexchange.com/rooms/52405/apl. See https://chat.stackexchange.com/transcript/message/41299896 if you don't have 20 Stack Exchange rep points.
 
 
4 hours later…
6:16 PM
@Feeds um
 
@EriktheOutgolfer The tweet was double-posted. The bot did its job.
 
@Adám looks like the double post doesn't exist anymore...
no I wasn't complaining about the Feeds bot
 
@EriktheOutgolfer Right. I told the author.
 
ok this is getting infuriating, chat is telling me the lesson starts in 10 minutes...yes, I know, what could I do apart from joining, which I've already done?
:P
 
@EriktheOutgolfer SE chat is an unloved child.
 
6:23 PM
@Adám yeah, they told him he was the third pillar of SE's three pillars but they didn't respect him as such, what a sad story...
 
@EriktheOutgolfer What are the other two? Main and Meta?
 
@Adám I think the second is mother meta (i.e. Meta.SE) and the first is the rest of SE
anyway, the "third place" philosophy doesn't look very applied to me, chat is abandoned
and so it cries through the annoying bugs it hosts, its parents having claimed a criminal offense, that being abandonment of a child
I don't need to say the rest, its cries express pretty well
 
Welcome to the APL learning session!
We've being going through various useful system functions (special names which begin with ). The next category has tools to deal with user defined functions.
You may want to review Lesson 2.
User defined functions can have various attributes. E.g. they can be niladic/monadic/dyadic/ambivalent, and they of course have an author and a time when they were written. To access this info, we have ⎕AT Attributes.
⎕←⎕AT '⎕SE.Dyalog.Utils.formatText'
 
@Adám
┌──────┬────────────────────┬─┬──────┐
│1 ¯2 0│2018 1 17 18 33 26 0│0│runner│
└──────┴────────────────────┴─┴──────┘
 
Let me decode that for you.
 
6:33 PM
⎕SE?
 
@Pavel ⎕SE is a namespace which is pre-populated with various things. We'll get to that.
The first part, 1 ¯2 0 means that 1: has an result (which is implicitly printed) ¯2: it is ambivalent (the left argument is optional) 0: it is not an operator.
The next part is a timestamp, in ⎕TS form.
The third element is the lock state 0=unlocked (APL allows you to lock your code so others cannot inspect and/or suspend it).
 
Why is the timestamp right now? I presume that the function was defined at an earlier point, being in the standard library and all.
 
And the last element is the username of whoever last established the function. It says "runner" (TIO's username) because this function was stored in a script and imported dynamically as the TIO session was spun up.
@Pavel ^
 
Ah
 
@Adám established? you mean loaded?
 
6:39 PM
@EriktheOutgolfer Made into a function from a text source. It wouldn't update if the function was copied from a different workspace.
Let's have a look at the function. For various practical and/or historical reasons, there are a few different functions that let us inspect code under program control. (A user in an interactive session can of course just use the editor.)
All these system functions have names in the pattern ⎕xR where x is a single letter.
The simplest one is ⎕CR Character/Canonical Representation. It returns a matrix:
⎕←⎕CR '⎕SE.Dyalog.Utils.formatText'
 
@Adám
 text←{vals}formatText text;cr;pw;right;hang;first;lead;left
    ⍝ Format text according to specifications (see ]?format)
 :If 900⌶⍬ ⋄ vals←0 ⋄ :EndIf
 text←{(+/∨\' '≠⌽⍵)↑¨↓⍵}∘⎕FMT⍣(1=≡text)⊢text ⍝ convert everything to VTV
 text←↑,/(⊂''),(⊂vals)formatPar¨text
 
@Adám Not related to this specific lesson, but I, for one, think that these lessons are great. I've learned much more APL that I ever thought I would thanks to them. Thank you!
 
From this you can see on the first line that indeed, the function has a result (text) and that the left argument (vals) is optional (it is in braces).
@cairdcoinheringaahing I'm very happy to hear.
However, sometimes it is more practical to get the code as a vector of vectors (list of strings), e.g. to extract a single line. For that we have ⎕NR Nested Representation:
⎕←⊃⎕NR '⎕SE.Dyalog.Utils.formatText' ⍝ first line
 
@Adám
 text←{vals}formatText text;cr;pw;right;hang;first;lead;left
 
Finally, you may want a single string (with newlines) with all the decorations. ⎕VR Vector/Visual Representation:
⎕←⎕VR '⎕SE.Dyalog.Utils.formatText'
 
6:45 PM
@Adám
     ∇ text←{vals}formatText text;cr;pw;right;hang;first;lead;left
[1]       ⍝ Format text according to specifications (see ]?format)
[2]    :If 900⌶⍬ ⋄ vals←0 ⋄ :EndIf
[3]    text←{(+/∨\' '≠⌽⍵)↑¨↓⍵}∘⎕FMT⍣(1=≡text)⊢text ⍝ convert everything to VTV
[4]    text←↑,/(⊂''),(⊂vals)formatPar¨text
     ∇
 
These three forms are all valid arguments to the function ⎕FX Fix which will establish a function according to the code given (or return an index of the first line which was problematic).
⍞←a plus b ⊣ ⎕FX 'r←a plus b' 'r←a+b'
 
@Adám ERROR: Use ⎕← for a full error report
 
⍞←3 plus 4 ⊣ ⎕FX 'r←a plus b' 'r←a+b'
 
@Adám 7
 
Here ⎕FX established the function plus (and returned its name, but we ignored that in favour of 4) and then we used the function right away.
As you may recall, tradfns and dfns can easily define dfns in their code, but they cannot easily define tradfns. ⎕FX lets you dynamically define tradfns should you want to do so.
⎕FX works for dfns too:
⍞←3 plus 4 ⊣ ⎕FX 'plus←{' '⍺+⍵' '}'
 
6:50 PM
@Adám 7
 
Remember the formatText function? It looks complex. Let's get some order by listing all the identifiers that it uses. Enter ⎕REFS References:
⎕←⎕REFS '⎕SE.Dyalog.Utils.formatText'
 
@Adám
cr
first
formatPar
formatText
hang
lead
left
pw
right
text
vals
 
In the editor, you can set breakpoints (stops) and trace points (output function name, line number and value).
You can also do this under program control using ⎕STOP and ⎕TRACE, but for obvious reasons I cannot demo this in a non-interactive environment.
The syntax is simple, though. linenumbers ⎕STOP 'fnname' to set, and omit the left argument to query. Same for ⎕TRACE.
Actually, I can demo tracing:
⎕←3 plus 4 ⊣ 2 ⎕TRACE ⎕FX'r←a plus b' 'sum←a' 'sum+←b' 'r←sum'
 
@Adám
7
 
Hm, no, it outputs tracing info to STDERR.
So if you look in the Debug pane, you'll see that we passed the trace point in plus on line 2, and the last value evaluated there was 4.
I think we should keep all the OO stuff for a separate lesson (maybe next time?) so I'll skip those for now.
As I'm sure you know, you can explicitly request output using ⎕← or ⍞←.
The chatbot (ab)uses ⍞←. Really ⎕← means print to STDOUT (with trailing newline) and ⍞← means print to STDERR (without trailing newline).
However, you can also use these two symbols for input. ←⍞ means read a line from STDIN, and ←⎕ means get a value from STDIN.
What's the difference?
 
7:03 PM
Note, isn't needed for input
 
@Zacharý Correct (for input). You can use the result directly.
will take an APL expression and evaluate it. If you give it an expression without a value, it will keep prompting until you give in (or enter to abort).
Expressions evaluated in are not encapsulated, so side-effects will persist (e.g. removing your program!)
 
@Adám What constitutes "no value"?
 
@Adám just tried inputting )OFF...don't try!
 
@Zacharý E.g. system commands and {} and result-less function calls.
 
@EriktheOutgolfer Exact same thing
Ah, I see.
 
7:08 PM
For normal input, you can also set a Response Time Limit in seconds: ⎕RTL←10 gives the user 10 seconds to respond before a TIMEOUT error is thrown.
(obviously you can trap this with a dfns error guard {1006::} or tradfn :Trap 1006)
 
⎕←⎕RTL←1⋄⍞
 
@EriktheOutgolfer
1
 
@EriktheOutgolfer The 1 is the value you set ⎕RTL to.
 
⎕←⍞⊣⎕RTL←1
 
7:09 PM
@EriktheOutgolfer
 
why no error >_>_<_<
@Adám trying to achieve TIMEOUT...
 
Well, input isn't possible with this bot (IIRC)
 
@EriktheOutgolfer Because TIO runs in scripted mode, and when there is no more input, but it needs more input, it terminates.
⎕NQ (Enqueue event) is mostly used for GUI programming, but I want to show you one nifty thing you can use it for.
 
Exist the pointer concept in APL?There is something as a pointer to the structure describes stdin stdout and stderr? There is something equivalent to C file pointer, or C++ streams? There is End of File EOF value?
 
@RosLuP When it comes to OO, APL has pointers, or "ref"s. But STDIN/OUT/ERR are just these special variables and . We'll get to file handling.
 
7:14 PM
Woah, I was just fooling around with ⎕NQ, and I just opened a new window o_O
 
The Calendar and DateTimePicker have two methods (functions) called DateToIDN and IDNToDate. But the root object (#, or the APL session itself) also has these methods.
These convert between the ⎕TS format (Y M D h m s ms) and a International Day Number (as a float, so it includes the time). These are great for date and time calculations.
Two days from now:
⍞←3↑2⎕NQ#'IDNTODate',2+2⎕NQ#'DateToIDN'⎕TS
 
@Adám 2018 1 19
 
Don't worry much about the syntax. ⎕NQ needs 2 as left argument (for this job) and then the # says to look in the root object. at the end is the timestamp/IDN, either appended (,) or juxtaposed.
You can also use it to get the weekday:
⍞←4⊃2⎕NQ#'IDNTODate',2⎕NQ#'DateToIDN'⎕TS
 
@Adám 2
 
2 is Wednesday (because 0 is Monday).
@all Any questions before we move on to file handling?
 
7:22 PM
well, you said let the syntax alone...
 
@EriktheOutgolfer Yeah, you can look up the docs for ⎕NQ if you want.
Dyalog APL has two sets of file handling system functions. One is intended to make it easy to work with Unicode files, the other gives low level control.
There are lots of options, but I'll just go through basic functionality.
To read the contents of a Unicode file, use ⊃⎕NGET 'filename'. This will normalise line breaks to LF (⎕UCS 10). If you'd rather a list of lines, use ⊃⎕NGET 'filename' 1
This will autodetect encoding an line break style, and should "just work" for almost all files. See docs if you want more fine-grained control.
Similarly, you can put content into a file with (⊂content) ⎕NPUT 'filename'. If you want to overwrite any existing file, use (⊂content) ⎕NPUT 'filename' 1
content may be either a simple character vector (string) or a "VTV" (vector of character vectors, i.e. a list of strings).
Again, more fine-grained control is available.
There are also some nice utilities which make it easy to perform some of the most common file operations. Ah, why not just use ⎕SH/⎕CMD to ask the OS to do it for you? Because various OSs need various commands and syntax. These system functions will let you write truly cross-platform code.
 
@Adám why would that thought ever cross your mind o_o
 
⎕MKDIR and ⎕NDELETE do what you'd think.
⎕NINFO gives you file listings' info like you'd get from ls/dir, but in a nice array format, perfect for further APL processing.
⎕←⍉↑1 0 6⎕NINFO⍠1⊢'/*'
 
@Adám
┌─┬───────────┬─┐
│1│/usr       │0│
├─┼───────────┼─┤
│1│/bin       │0│
├─┼───────────┼─┤
│1│/etc       │0│
├─┼───────────┼─┤
│1│/var       │0│
├─┼───────────┼─┤
│1│/boot      │0│
├─┼───────────┼─┤
│1│/srv       │0│
├─┼───────────┼─┤
│1│/dev       │0│
├─┼───────────┼─┤
│1│/opt       │0│
├─┼───────────┼─┤
│1│/sys       │0│
├─┼───────────┼─┤
│1│/lib       │0│
├─┼───────────┼─┤
│2│/.rnd      │1│
├─┼───────────┼─┤
│1│/home      │0│
├─┼───────────┼─┤
│1│/run       │0│
├─┼───────────┼─┤
│1│/sbin      │0│
 
7:38 PM
This is a listing of TIO's root. the first column (indicated by the 1 in the left argument) is the type; 1=directory, 2=file. The second column (0) is the name. The third column (6) is Boolean for whether that item is hidden or not.
 
⎕←⍉↑1 0 6⎕NINFO
 
@RosLuP

Rebuilding user command cache... done
⍎SYNTAX ERROR
 __field_initialize_result_←(⎕NS ⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -fns=on -trains=tree''⊣enableSALT⋄''''' ⋄ ⎕←⍉↑1 0 6 ⎕NINFO
                                                                                                                ∧

Real time: 0.977 s
User time: 0.921 s
Sys. time: 0.033 s
CPU share: 97.58 %
Exit code: 0
 
@RosLuP You need to specify a right argument; a filename or pattern.
 
⎕←⍉↑1 0 6⎕NINFO⍠1⊢'*'
 
@RosLuP
┌─┬───────────────┬─┐
│1│.dyalog        │1│
├─┼───────────────┼─┤
│2│.bin.tio.dyalog│1│
├─┼───────────────┼─┤
│2│.env.tio       │1│
├─┼───────────────┼─┤
│2│.debug.tio     │1│
├─┼───────────────┼─┤
│2│.output.tio    │1│
├─┼───────────────┼─┤
│2│.input.tio     │1│
├─┼───────────────┼─┤
│2│.code.tio      │1│
├─┼───────────────┼─┤
│2│.error.tio     │1│
└─┴───────────────┴─┘
 
7:41 PM
The ⍠1 indicates that the right argument contains wildcards. Otherwise it would look for a file which had actual question marks and/or stars in its name (bad idea, but at least APL can handle it).
 
⎕←⍉↑1 0 6⎕NINFO⍠ '*'
 
@RosLuP

Rebuilding user command cache... done
⍎SYNTAX ERROR
 __field_initialize_result_←(⎕NS ⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -fns=on -trains=tree''⊣enableSALT⋄''''' ⋄ ⎕←⍉↑1 0 6 ⎕NINFO⍠'*'
                                                                                                                ∧

Real time: 1.228 s
User time: 1.101 s
Sys. time: 0.046 s
CPU share: 93.39 %
Exit code: 0
 
@RosLuP You need the 1 after , and also to separate the 1 from the filename. Use parens or .
@all Let me know if you want to know about the low-level file handling tools. Otherwise I'll skip them for now.
 
⎕←⍉↑1 0 6⎕NINFO '*'
 
@RosLuP

Rebuilding user command cache... done
⍎FILE NAME ERROR: Invalid file or directory name ("No such file or directory")
 __field_initialize_result_←(⎕NS ⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -fns=on -trains=tree''⊣enableSALT⋄''''' ⋄ ⎕←⍉↑1 0 6 ⎕NINFO'*'
                                                                                                                ∧

Real time: 1.162 s
User time: 1.052 s
Sys. time: 0.053 s
CPU share: 95.10 %
Exit code: 0
 
7:44 PM
@Adám uh, do we have time
 
@RosLuP This was a correct function call. Since you did not specify the wildcard option (⍠1) it assumed you were looking for info on a specific file. Since that file didn't exist, it threw an error.
@EriktheOutgolfer Not today, no. It would probably require an entire lesson anyway.
Let's do error handling then.
In a dfn, you can trap errors with error guards {errornums::result if error ⋄ try this} and in tradfns with :Trap errornums ⋄ try this ⋄ :Case errornum etc..
 
Is there a way to catch any error, irregardless of number?
 
But what are those error numbers? The easiest way to find out is to cause the error and then check ⎕EN which is a variable that you cannot set directly. It contains the error number of the most recent error.
@cairdcoinheringaahing Yes, using number 0 will catch all errors, using number 1000 will catch all exceptions.
⍞←2{0::⎕EN ⋄ ⍺÷⍵}5
 
@Adám 0.4
 
This catches all errors and returns the error number (or the result of the division if no error happened).
⍞←2{0::⎕EN ⋄ ⍺÷⍵}0
 
7:50 PM
@Adám 11
 
Error 11 is DOMAIN ERROR (due to division by zero).
⎕EM is a function which takes an error number and gives you the Error Message for that Error Number (⎕EN):
⍞←{0::⎕EM ⎕EN ⋄ ⍺÷⍵}5
 
@Adám VALUE ERROR
 
@DyalogAPL since we didn't give a left argument, caused a VALUE ERROR.
⎕DM (Diagnostic Message) is a vector of three character vectors; a canonical form of what you see in the session when an error happens:
⍞←{0::↑⎕DM ⋄ ⍺÷⍵}5
 
@Adám VALUE ERROR
 
⎕←{0::↑⎕DM ⋄ ⍺÷⍵}5
 
7:54 PM
@Adám
VALUE ERROR
 __field_initialize_result_←(⎕NS ⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -fns=on -trains=tree''⊣enableSALT⋄''''' ⋄ ⎕←{0::↑⎕DM ⋄ ⍺÷⍵}5
                                                                                                                         ∧
 
Ah, right, I forgot that doesn't quite work with the bot.
 
⎕←9{0::↑⎕DM ⋄ ⍺÷⍵}5
 
@RosLuP
1.8
 
⎕DMX is a namespace (an object) which has Diagnostic Message (Extended). It has a neat display form with more info:
⎕←2{0::⎕DMX ⋄ ⍺÷⍵}0
 
@Adám
 EM       DOMAIN ERROR
 Message  Divide by zero
 
7:58 PM
We can use ⎕JSON to display all its content:
⎕←2{0::⎕JSON⍠'Compact'0⊢⎕DMX ⋄ ⍺÷⍵}0
 
@Adám
{
  "Category": "General",
  "DM": [
    "DOMAIN ERROR",
    " __field_initialize_result_←(⎕NS ⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -fns=on -trains=tree''⊣enableSALT⋄''''' ⋄ ⎕←2{0::⎕JSON⍠'Compact' 0⊢⎕DMX ⋄ ⍺÷⍵}0",
    "                                                                                                                                            ∧"
  ],
  "EM": "DOMAIN ERROR",
  "EN": 11,
  "ENX": 1,
  "HelpURL": "http://help.dyalog.com/dmx/16.0/General/1",
  "InternalLocation": [
 
Here you can even see where in our C source code the error was thrown. It was in arith_su.c on line 652!
Enough for tonight.
 
Thank you
 
@RosLuP My pleasure. I hope that you learned something, and that it wasn't too boring. These system functions aren't as exciting as the primitives.
 
@Adám Still great though
I was lurking because pesky work
 
8:09 PM
@Adám true, but to me they open tens of new worlds
 

« first day (357 days earlier)      last day (2281 days later) »