The 0+/ thing is a little more obvious if you start by looking at the subvectors directly (not reductions on them). I discussed the BQN version some in this section.
OK, in general, for replacing bracket indexing, there are a few options. To select major cells (e.g. rows of a matrix) Ym[Iv;] you can do (⊂I)⌷Ym or I⍤0 99⊢Ym
If instead you want to select a single column: Is⌷⍤1⊢Ym
Most of the APL docs I read use the term 'defined functions' (or operators) to refer to what we used to call 'user-defined ..'. Does anyone know why that change in terminology was made? Surely any usable function is defined?
@RomillyCocking Function style names are a very annoying part of APL. APL Wiki believes "defined function" is a tradfn. (soo we have "defined" for tradfns, and "direct"/"dynamic" for dfns? ಠ_ಠ)
I intentionally wrote "something-extended-APL standard" but the added "or something" was just an instinctive must-add before posting a message about something I don't have 100% certainty about
The new (year 2000) 'standard' apparently covers APL2, but not Dyalog APL :(
That is bad from several points of view, not least because it presumably says nothing about direct definition. (I can't be sure, because It costs 196 CFH, which I am not willing to pay)
@dzaima I respect your anonymity, but I can't help thinking that we have met IRL.
<moon-child> @RomillyCocking there is the ‘dyalog apl language reference guide’, which is effectively a reference. (Relevant here is a portion of it that says ‘function may refer to a primitve function, a system function, a defined (canonical, dfn, or assigned) function, or a derived (from an operator) function’)
@DyalogAPL I guess I'll go with that definition, then, though I would feel much happier if 'defined' has the prefix 'user-'. The OED says that defined means 'having a definite outline or specification; precisely marked or stated', and it seems to me that that applies to all functions and operators in APL.
<moon-child> @RomillyCocking well, crucially that definition excludes derived functions. ({+/⍵}) is defined per that definition, but (+/) is not. Even though the latter was still defined by the user
+/ kind of doesn't feel very user-defined-ly. trains though - that's a better question, and doesn't seem to be included in any of the reference options
@DyalogAPL IMO it does not exclude that, We must be using words in different ways, and I doubt it's worth more time exploring that. I will go against my preferences and accept 'authority of position' :)
moon-child: right, that was what I was also thinking
either way, given that some Dyalog reference uses "defined function" for both tradfns and dfns makes it sound like there's actual reason to not call tradfns "defined functions"
also @Marshall/@Adám there 3/7 references are for non-existent (at least in 18.0 docs) pages
There are *loads* of issues with the current Dyalog docs which I am trying to catologue. Should I make my list a public project on GitHub so that others can add to them?
The biggest problem IMO is that many Google searches lead to *very* out-of-date help, which will at best confuse and at worst put off newcomers.
@RomillyCocking i'm kind of surprised google searches even work, so ¯\_(ツ)_/¯
my random search for "dyalog apl natural logarithm" gives a first result to a page with the title "Natural Logarithm - Dyalog APL 18.0 Help" while it links to 12.1 docs. So I see what you mean..
There's also a deeper issue, in that there seems to be a gap between the things that attract potential new users (Code Golf, the Competition etc.) and the things they need to get started. TryAPL is a great step forward but beyond that many will flounder.
@dzaima "Defined functions and operators" only include "tradfns/tradops" and "dfns/dops" while e.g. trains and operator-derived functions/operators are called "derived functions/operators". "Tacit" isn't in the vocabulary at all.
I believe some of the terminology stems from a semi-artificial distinction based on a technical difference that is irrelevant to the normal user.
(personally I wouldn't want to call derived fns/trains as "defined functions". I'm okay with the only connection between trains and dfns being that they're both "functions")
I think his argument includes that all the dialects that don't have any other forms of user-written functions, call their user-written functions "defined functions".
I say: Of course they do, but not to exclude dfns or other types, as those are not in mind at all.
Technically speaking, the interpreter switches from "desktop calculator mode" to "function definition mode when you enter ∇ header, and the reverse on the next ∇ (outside any brackets/strings/comments). Meanwhile, the internal (names used in the C code) representation for primitives/operator-bound stuff/trains is called "derv".
So Dyalog ends up calling anything you can define using the "function definition mode" a "defined function", and everything else a "derv", expanded to "derived function".
Now you just have to be aware of something you can do, but practically nobody ever does:
@dzaima Spot on. The ∇ was there to allow users entering, editing and defining functions in APL\360 and APL\1130 to use golfball terminals to edit code as well as submit expressions for immediate execution.
@dzaima Something like that. I'm not sure what was added first, the ability of ⎕FX to handle dfns or the ability for normal execution to handle dfn assignment, though.
@RomillyCocking As I'm sure you know, we do have our own issue tracker which isn't publicly viewable, but if you prefer a public list, that's fine too. Fyi, we've already decided what to do about the links to old versions, and also how to avoid broken links in the future. As always, we're stretched thin on every front at Dyalog. The documentation team person currently has 535 open issues…
@dzaima I still don't see how that's relevant for how functions are defined, but hey: ⋄ (⍎'{⍵ ⍵}')42
@Adám Thanks. I can remove the links issue from my note to Morten. He said he'd pass the document on but maybe I should just copy you in when it's ready.
@RomillyCocking I think that gap is very real. The reason is that currently, there is no way forward from "APL as a cool toy" to "let me build an application with APL" while adhering to modern practices. It is very sad indeed, and I'd love to do something about it, but two restrictions make this a rather difficult task: backwards compatibility for existing APL code and maintaining single code base for our APL interpreter.
@dzaima Isn't it kind of stupid that ⊂⍣3⍳4 works and P←⍣ ⋄ ⊂ P 3⍳4 doesn't?
I can't see a *perfect* solution, but I think there are workable ones, and I think my basic assumptions may be different from yours. Or maybe it's just a question of priorities.
In particular, I think one could get to a point where there were enough people with real money to spend (whihc is what Dyalog needs IMO)by introducing APL to people who are trying to build *internal* applications to explore new algorithms rather than build finished apps that are ready for a mass market.
Cases in point: Computer Vision, Neural Networks, doing hard stuff with Big Data.
I have a couple more mini books in the pipeline that address ANNs (not using backprop, which was a terrible mistake) and Big Data.
@dzaima No, but that's the same thing. It would have to be "a value" to be assignable, and then it is also returnable, and then it is a valid statement in a function.
(Although why is O←{⍵⍵} allowed but none of {⍵⍵} or O←∘ are…‽)
Hello folks. I'm trying to learn about how/whether does Jarvis parallelize / multithreads. In the source I see calls to the & spawn primitive. That's only "green threads", right? "Threads" page in Dyalog help says that if one thread is running, other are paused. So, I'm inferring that only 1 core is used at any point. Am I reading into it correctly so far?
@MartinJaniczek ^ however, I do think there's a way to make it use multiple OS threads to handle incoming requests. That's what old TryAPL used to do, and it was based on an old version of MiServer, which was a precursor to JSONServer (the precursor to Jarvis).
@MartinJaniczek It was using a vanilla server. Let me have a look at the configs…
@MartinJaniczek Ah, I see, the TryAPL code was setting that up as part of its constructor for the server instance. Still you or I can ask Brian if it wouldn't be a good option to handle callbacks in separate threads. I can see many good uses for this.
@Adám Thanks for checking. I haven't done any benchmarking yet but I suppose it would be handy to be able to use all the machine resources to improve throughput, latency etc. of the server.
@dzaima FYI the page name "Defined function" doesn't specify APL Wiki terminology. It's fine to use the name "tradfn" if it makes sense in context (e.g. not on the "APL.SV" page, since dialect pages use that dialect's terminology).
@MartinJaniczek This whole question is spawned from one of my colleagues finally getting home from holidays and looking at my prototype and asking questions :)
@Marshall The page name should reflect the most prevalent use, and in my research I found that Dyalog resources are basically the only place you'd find the word "tradfn". Every other language where the creator uses that term (such as ngn/apl) doesn't actually have them.
@Adám It's better to have a misleading term that people are familiar with that one that will be totally unknown to a lot of readers (the point of the page title is as a navigational aid, while the text actually explains what's going on). In the first case, readers get annoyed at the ambiguity. In the second case, they think they're on the wrong page and start hunting around for the one they really meant.
Question for people with more real-life APL programming experience than me: How often do you declare a custom operator which can take either a function or a value as argument?
Since the roles of functions vs. values are locked down at parse-time in Kap, I would like to have different syntax for each of these cases. However, if both is needed, then the functions needs to be passed as lambda expressions instead.
@Marshall more likely in the second case: the user takes the term at face value, keeps doing user things, builds wrong mental models, and learns about the trap later
@Marshall the wiki is like the only dialect-agnostic APL information source. I assume most would assume the title of the page is the preferred name for a thing.
@dzaima It is, which is distinct from it being a bad name.
I added a header to point out that some dialects consider dfns to be defined functions (we'd need this even if the page was called Tradfn, since "defined function" would still redirected there).
@Marshall it's hard to separate the two - describing vs prescribing. new aplers will read what's described and start using the term as if it's prescribed.
@Adám I think "defined function" was always short for "user-defined function", so NARS2000 just chooses not to abbreviate. The abbreviation's more common historically though.
Also of note is that both NARS2000 and GNU APL seem to not consider the braces as part of the definition, but rather only as a syntax to delimit the definition from surrounding code, and only at definition time. If you edit a dfn in NARS2000 or GNU APL, the braces are gone.
@EliasMårtenson It allows changing syntactic role of anything simply by changing the capitalisation of the first letter and/or adding/removing leading (and optionally trailing) underscores.
@dzaima I'd claim +/ is user-defined. It isn't inherently in the language (never mind optimisations), and only exists because the user put together two arbitrary atomic building blocks to define something new.
@ngn I'd personally say that f is a user-defined function, in that f was meaningless until the user defined it. I'm not sure if it is useful to distinguish between named and anonymous functions, but it could be done.
I never claimed the definition or distinction was useful.
afaict, the only time one should need to care about this distinction is when teaching or discussing how a user can build/define/use/change things they put together themselves.
@Adám I'd still not call trains user-defined functions, they're a tree of 1-3 grouped functions. somewhat like a subset of statements in a function isn't a user-defined function
is 1+1+1+1+⊢ 4 user-defined functions?
@Adám That's asking a different question - those are statements (or variables), instead of functions. Taking +/ vs {+/⍵} alone, I would distinguish them.
@dzaima So I can conceivably build an entire functioning application, having defined numerous functions, but never having created any "user-defined functions"‽ How is that useful terminology?
@Adám this is a question about a subset of non-explicit expressions. Once you start assigning & calling stuff, there are different considerations at hand.
(and i'm fairly certain you can make some full applications with no derivations/trains too)
I don't see any reason why f←+/ shouldn't be considered a user-defined function. But that said, I don't think that is a useful category anyway. User-named function would make more sense. +/ isn't user-named by itself, of course. f←+ is user-named, and so is f←{⍵}, but + and {⍵} are not.
That doesn't really excuse the practice, as "defined" has a very different feel to it than "user-defined".
"Surely + is a defined function, otherwise I wouldn't be able to use it"
"On the other hand, % isn't a defined function in any APL I know of".
Imo, any source that only recognises a single functional form that one can associate with a name is inherently disqualified from influencing what that form should be called in a world where multiple forms exist.
@Adám I didn't intend to offer it as a justification, I was supporting the point that "user-defined" was at one time shortened to "defined" in texts covering APL
I think tradfns, dfns, and trains are all useful names to distinguish between their various constraints and capabilities. I agree that "user defined" is a decent overall heading to cover them. I don't see using that broad of a categorization to be very helpful in most cases, as they have too much to distinguish themselves from each other to be usefully grouped together all that often.
@Adám I think this principle privileges Dyalog's worldview more than you realize. If GNU APL decided to add a new kind of control structure written with ;, and for disambiguation called the : kind "tradcntrl" and the ; kind "newcntrl", we'd be pretty justified in keeping "Control structure" as a page title. I don't see any relevant differences between that and the current situation.
"Control structure" even has a similar ambiguity, in that ⍣ is also a structure you can use for program control, but the name doesn't apply.
So you can argue this case, but I don't think you can claim in general that the language with the most specific terminology wins.
It would be very different if even one other language used "tradfn" in public documents as this would imply some level of community uptake.
@Marshall I'm not saying that "tradfn" is a good term, but I'm protesting against using a misleading term, when several implementations sport alternative functional forms.
@Adám I'm just arguing against "Imo, any source that only recognises a single functional form that one can associate with a name is inherently disqualified from influencing what that form should be called in a world where multiple forms exist." now.
@dzaima That would be Function styles, but del-functions and dfns are clearly distinct, and both significant enough to have their own pages. We definitely shouldn't change the page divisions to get cleaner titles.
@Adám Well, the analogous form would be "Imo, any source that only recognises a single control form that one can associate with a name is inherently disqualified from influencing what that form should be called in a world where multiple forms exist." I don't think that argument would apply in the hypothetical GNU case, so I don't think the same kind of argument should apply to Dyalog either.
APL2 only recognises a single way for a user to create their own function. This method, which APL2 shares with most historic implementations, and many current ones, needs a name so we can speak about it. The fact that implementations that only have that form call it "defined function" is irrelevant to our needs, as their terminology never was intended to distinguish.
@Marshall The current situation would be like there being a page for "control structure" which is about Dyalog's : and GNUs : and explicitly not GNUs ;, which would have a separate page. That feels very wrong, as both : and ; are control structures.
@dzaima (of course, there's also the fact that some sources (i have no clue which) do use "defined function" only for del-functions (heh, if we add dzaima/APLs : and :←, we get a similar situation :p))
@Adám No, I think you can keep using "electricity" and "AC". More importantly, you can't make the switch to "DC" until you expect your readers to have heard of the term.
@Marshall I disagree. In that case the wiki should have three pages: AC, DC, and Electricity. The latter should give an overview, but begin with a note saying "For the traditional… see [[DC]]".
I think your viewpoint tends towards the idea that tradfn and dfn are two platonic things that must exist. That's a Dyalog-centric view. dfns are invented; APL never needed to add them (and many other kinds of definition can and have been invented). That doesn't fit with AC and DC, which are the only reasonable ways to transmit energy through electric currents in wires.
I don't think one dialect should be able to force other APLers to change the way they refer to a concept just to disambiguate from another concept they didn't even want.
@dzaima No, it'd be a page called "User-defined functions" or some such.
@Marshall Obviously neither tradfns nor dfns had to exist (evidenced by some APLs having neither), but the current state of the universe is that most APLs have one or the other or both. We need to be able to unambiguously speak about them.
@Adám You can use tradfn to speak about them if there's ambiguity; the page title doesn't influence that. The "Defined function" page uses tradfn all over the place!
Now, should these things be called "tradfns", that I don't know, but surely we can't go on calling them "defined function" when that'd just wildly misleading the innocent reader.
@Marshall I never argued for the term "tradfn". I don't like that term. Come up with something better!
But not "defined function". "Tradfn" is easy to learn. Once you hear that it means that traditional form, you won't forget. But "defined function" or "user-defined function" keeps being confusing, as every time you see it, you have to guess if the author means it as a technical term (=tradfn) or just any function the user has defined in general.
@Marshall No, that's a terrible name, since the dels are not part of the syntax, and not necessary to define such functions in any implementation used today, not to mention that dels can be used when defining dfns!
@VictorVosMottor for starters, you often need to wrap tacit code in parentheses for it to be callable (exception being in assignment). (~∘0) is currying the right argument of ~, and (f g) (f being ×/ and g being ~∘0) for any arbitrary 2 functions is equivalent to {f g ⍵} when called monadically
@dzaima cause the page is explicitly only about tradfns, while, apparently, noone actually uses it as such. It really should just be a disambiguation for dfns and [insert any non-ambiguous name for tradfns]
Yup, 'currying' is widely used, but partial application needs no prior exposure to the idea. Also POP-2 deserves te be remembered - it's a wonderful language.
@dzaima I'm with you. If I understand @Marshall correctly, he's arguing that "defined function" is widely used to mean "only tradfn" ― by those that recognise no other form.
@Adám Given that "Defined function" redirects to this page (it's the most common meaning of the term), I think the point about dfns is still needed. I've streamlined it a bit, but I'm done editing for now, so go ahead and make other changes you think are needed.