@dzaima - What are the benefits of starting with zero (a) in the real world, and (b) in writing code to solve real-world problems? So far, the only advantages I've ever seen are for lazy language implementors.
@JeffZeitlin Some algorithms do become simpler with ⎕IO←0, especially involving abse conversions and selecting between to choices based on a condition. E.g. it is nice to be able to write condition⊃'false' 'true'
OK, that's a partial answer to b - and [most implementations of] APL offers me the option to set ⎕IO, whereas there seems to be a segment of the community that believes that it should not be an option, and ⎕IO should be forced to 0.
@ngn - I said real-world problems, not working around implementation dependencies.
@Adám not that I disagree in the general case, but a proper conditional syntax would take care of that easily. (or even allowing guards inside parentheses, which is not difficult)
One of my biggest beefs about zero-origin languages is that if I want the last element of the array, I can't just use array[array.count] to get that last element, I have to compensate for the zero origin.
Performance and complexity are not real-world problems in themselves; they are the result of using tools that are suboptimal for the problem that they are being used to solve.
@JeffZeitlin A.k.a. most APLs allow functions calling each other, each using their own ⎕IO. Tell me, which ⎕IO is used if a ⎕IO←0 function calls a function that's defined in a ⎕IO←1 namespace, but doesn't set its own ⎕IO?
@JeffZeitlin Well, it is a matter of scope. Dyalog gives ⎕IO namespace scope. Alternatives include function scope and primitive scope.
@JeffZeitlin now that's an interesting argument. do you also think that (+)←{...} should be possible? like change the definition of + to whatever makes sense for the problem at hand?
@ngn I don't think so. But I also don't think 'it gets you more performant code' is justification for a design choice in a language such as apl. Especially since the performance hit isn't pathological or algorithmic
@ngn Right, essentially ⎕IO lets you redefine a bunch of primitives. You have to change them all at once, and in a consistent manner, but still. ⎕ML is the same.
@Adám - I believe in what I guess is best called "block scope" - that is, if I were writing in Pascal, anywhere the language defines a 'block', I can localize variables. If I don't localize variables, they are inherited from the enclosing block - but libraries are not considered enclosed by the calling block.
@Adám - In a Dyalog-like context, if I'm )COPYing functions from a workspace where ⎕IO is set differently from my current workspace, I would want the )COPYed functions to carry their own ⎕IO setting - and any other relevant system variable settings.
@ngn - There is a difference between system variables, like APL's ⎕IO, and primitive functions, like +. Changing the definition of language primitives is less defensible than being allowed to change system variables.
@ngn - That is, in fact, one of the things that I don't like about operator overloading in languages like C++; there are no limitations on what you can make the operators do.
@Adám - I disagree: At best, you are changing a parameter to function primitives.
IIRC, ⎕ML is the one that makes Dyalog act like APL2 in various contexts, correct? While syntactically it's a system variable, semantically, I think it's more like a metacommand, like FreePascal's $MODE.
Now, admittedly, APL seems to blur the line between 'system variable' and 'metacommand' somewhat, and that may contribute in a small way to the 'APL is hard/confusing' mentality. I don't find it so; I am willing to admit that (a) my perceptions are not necessarily 'normal', and (b) I have a trick memory that gives me a better shot at 'keeping things straight'.
And I do not like the color of the sky in my immediate vicinity. It has no business carrying the slightest tint of green at 0555 when there is no reported storm activity in the area.
Getting back to the question of ⎕IO... I actually think that it matters less in APL than it does in other languages; in other languages, zero vs one origin confuses the issue in iterating (generally over an array); APL allows me to perform operations on every element of an array without explicitly iterating. Where it is more likely to matter in APL is in slicing an array.
Part of that is because the way the human mind tends to work confuses cardinal indices with ordinals.
@ngn - So is the sky really green? Or is it blue? Or perhaps bleen, or grue?
(It is pitch dark. You are likely to be eaten by a grue...)
@Adám - I was actually doing some conlanging with some friends a while back, and he found a reference which actually discusses which terms for colors a language typically has, if it has n color terms.
It was interesting. You "start out" with two, essentially "light" and "dark"; the third term is almost invariably "red", and I don't remember the progression from there. Blue/green is a fairly late distinction; I don't remember whether it comes before distinguishing red/yellow/orange or after.
I was about to say that I think Hebrew has a lot of colour distinction. Well, colour me (un)surprised:
> Today every natural language that has words for colors is considered to have from two to twelve basic color terms. All other colors are considered by most speakers of that language to be variants of these basic color terms. English contains eleven basic color terms: 'black', 'white', 'red', 'green', 'yellow', 'blue', 'brown', 'orange', 'pink', 'purple', and 'grey'. Italian, Russian and Hebrew have twelve, distinguishing blue and light blue.
@JeffZeitlin my personal reason is mostly that multiplication, division, and modulo by a number (also occasionally adding & subtracting two indexes) are meaningful operations, which allow for doing math with indexes (without pain). No array[array.count] is probably the most annoying thing about it, but that's easily fixable by just having a function to get the last item of the array (contrary to 3+ new functions for index-sane ÷×|)
(i'd want a function for last item either way; nth item from end is ugly in both ⎕IOs)
@dzaima - This is where I like a hack that's built into PowerShell (which is a zero-origin language) - if you index into an array with a negative number, it's the same as one-origin indexing from the end of the array - that is, array[-1] is the last item in the array, array[-2] is the next-to-last, usw.
@JeffZeitlin i wouldn't call it a hack, since it's pretty much the only sane way that could work due to modulo being sane and useful, and keeping those qualities with that extension
@dzaima - If it was symmetrical with "forward" indexing, I wouldn't call it a hack - although that would require the alternative hack of zero being signed.
(And it still wouldn't work in Pascal-family languages)
@JeffZeitlin right, not being able to negate the index for indexing from the reverse is unfortunate. (and of course it won't work with variable arbitrary ⎕IO) You can't have both modulo sanity and negating sanity outside of ⎕IO←0.5, but 1-x isn't that bad (plus, that's equal to bitwise negate if you're feeling like that needs to be shorter)
(personally i'd still prefer a separate function to get the nth element from end instead of negative indexes, regardless of ⎕IO)
one of my answers to the competition Phase I questions, number 5 (stepping) is: {⎕IO←0 ⋄ ⌽⍣(>/⍵)⊢(⌊/⍵)+⍳1+(⌈/-⌊/)⍵}
and it uses reverse with power (>/⍵) which should return 0 or 1 to know whether it's counting up or down, and that works
but if it says {⎕IO←0 ⋄ ⌽⍣>/⍵⊢(⌊/⍵)+⍳1+(⌈/-⌊/)⍵} without the parens around the test function, then Dyalog 17.1 goes into an infinite loop and locks up.
it must be being parsed differently, but I thought the use of ⊢ would separate the "power parts" from the rest?
the right operand of a dyadic operator is always a single token or parenthesized thing, and as you've removed the parenthesis, > is the token immediately to the right of ⍣ and becomes the operand. ⊢ isn't some magic thing that separates things, it's just a predefined function equivalent to {⍵}
can anyone shorten? p1←(0>⊣)⌽↑,⍥⊂↓⋄p2←⊢⊂⍨2≠∘⌊÷∘64⋄p3←26⊥1+⎕a⍳⊢⋄p4←80∘∨>50∘∨⋄p5←⊃+(⍳1+∘|-/)ׯ1*>/⋄p6←∩⍨,~⍨⋄p7←(×/≤/)2⊥⍣¯1,⋄p8←×/0>2×/2-/10⊥⍣¯1⊢⋄p9←⊢≡⌈\⌊∘⌽⌈\∘⌽⋄p10←↑∘⊃,.{↓⍉⍪⍉⍕⍵}⍨
@TessellatingHeckler when trying to parse deriving operators (and only operators), adding parenthesis from the left always works (keeping in mind the single-token-or-parenthesis rule) - e.g. f∘g/¨∘h¨ is (((((f∘g)/)¨)∘h)¨)
@dzaima single token to the right, right! keeping that in mind will help
I was a bit surprised @ngn's "move to front" answer yesterday works, the one based on set intersection; the surprise is that the output of 1 2 2 3 ∩ 1 2 3 has duplicates in it (and so isn't a set)
the tooltip for ∩ doesn't explicitly say set intersection, that was my assumption
@Ada first 3 letters of a name matching in an @ is enough for SE to consider it a ping. Apparently there's a discrepancy between the highlighter and notifier though
@Adám thinking of ngn's suggestion of collecting people's shared competition answers into a web page, would Dyalog be OK with that, or are they now copyright of Dyalog or etc.?
(not that I'm asking for an official legal answer, but "we're planning to publish them on our blog" could be a good reason not to)