« first day (1176 days earlier)      last day (1479 days later) » 

3:09 AM
⊢/ is so much better than 0⊥ nice.
suggested APLCart addition: ⎕SE.Dyalog.Utils.repObj as keeps being mentioned :P
Gathering thoughts on type systems, but ran into this in the meantime:
- tryAPL thinks ⍬≡⍎''
- tio.run thinks ⍎'' is a 'VALUE ERROR'
- RIDE thinks ⍎'' is fine (no output printed), but ⊢⍎'' is a 'VALUE ERROR: No result was provided when the context expected one'
Does anyone have opinions on what the "correct" answer should be?
 
3:39 AM
vaguely relatedly, why does ⎕IO←0⋄{⎕IO←1}⍬⋄⍳1 yield 0, but ⎕IO←0⋄{⍎'⎕IO←1'}⍬⋄⍳1 yield 1?
 
 
2 hours later…
5:10 AM
pfft ⌈⌊÷×-| in github.com/abrudz/dyalog-apl-extended is amazing
 
 
4 hours later…
8:46 AM
The bracket matching expression {+\1 ¯1 0['()'⍳⍵]}, found in forums.dyalog.com/viewtopic.php?f=30&t=1616 is a work of art.
 
 
1 hour later…
ngn
9:52 AM
@AntonDyudin tio and ride don't "think". tio is a website that hosts multiple implementations. ride is an ide for dyalog. my opinion about the correct answer:
@AntonDyudin doesn't localise
@xpqz there's also {+\-⌿'()'∘.=⍵}
 
@ngn Nice!
Given {⍺÷⍨⍵-⍺} -- what would that look like as tacit?
 
10:32 AM
Answering my own q: (--÷⊢)
No, (--÷⊣) it should be.
 
10:55 AM
(-⍨÷⊣) is another option, with the benefit that there is no atop, and one less operation
 
Wait, you can selfie trains?
That is actually exactly like my original dfn.
 
@xpqz though i don't quite understand what you mean "selfie trains" in relation to this, the answer is "just as much as you can everywhere else" regardless of anything
 
ngn
@xpqz in this case swaps the arguments of -
 
(-⍨÷⊣) parses the same as the classical (+/÷≢) - f M f f(f M) f f. What the particular f and M are doesn't matter
 
I get it, finally
 
ngn
11:22 AM
cmc: what's the fastest way to generate permutations?
(all at once, not with an iterator)
baseline for comparisons: ⎕cy'dfns'⋄cmpx'pmat 9'
 
 
2 hours later…
RGS
1:28 PM
does anyone know if anything happened to Adam?
 
ngn
19 hours ago, by Adám
Holiday for me now. I'll be back after 20:15 UTC on Thursday. Keep the pings coming!
 
RGS
@ngn oh thanks, I missed that msg of his and was getting worried :O
 
 
4 hours later…
5:10 PM
I was being imprecise for concision sure
TryAPL, an environment executing Dyalog (17?), when queried produces the result etc; TIO set to "Dyalog Unicode" produces the other result, the Dyalog 16/17 macOS apps when queried via the REPL produce a third result. "⍎ doesn't localise" is why I had scare quotes around "correct", and your fourth suggested result of NOP definitely makes more sense to me than the existing ones; or like, a function with optional ⍺ which in its presence returns ⍺ ⍵, and absence just ⍵
 
ngn
5:22 PM
@AntonDyudin in tio it depends on where you put the ⍎'' - under "code" or "input"
 
@AntonDyudin tryAPLs result is because its is just for evaluating numbers to limit arbitrary execution, it doesn't try to follow any strange things. TIOs code box is evaluated as a :Namespace
⊢⍎'' is the same as ⊢{}2 - there's a separate "no result" result in Dyalog that appears here (imo it makes sense in this case)
 
@AntonDyudin - And you can add to the list that Dyalog 17.1 Windows 64 is consistent with RIDE.
 
huh, i'm pleasantly surprised dzaima/APL follows this same behavior
It does make perfect sense imo that {}2 and ⍎'' do the same thing - the same token list (an empty list) is evaluated, so the same thing should be returned. What is that specific behavior, however, isn't really relevant (and imo {}2 returning an identity function would be weird)
 
RGS
5:39 PM
Guys, how can I use a function I defined in a .dyalog file from within another function in some other .dyalog file?
In Python I'd use an import xxx statement... But I haven't understood how APL does this type of thing.
the Help page on Dyalog APL 17.1 is confusing; can you point me to the correct page?
or to a decent link?
To be fair, I also haven't understood what is the closest thing APL has to a .py script I can just execute from my terminal (again establishing a parallel with Python)
 
ngn
a.dyalog:
 ..
 b←⎕fix'file://b.dyalog'
 b.f 123
 ..

b.dyalog:
 :namespace b
 f←{⍵+1}
 :endnamespace
 
RGS
@ngn for the b.dyalog file, should the namespace name match the name of the file?
 
ngn
@RGS not necessarily
 
RGS
alright
And is there a way to "run a script" I write? From whithin the APL terminal, or my windows terminal, or my windows powershell, ...?
 
ngn
i don't use windows. maybe somebody else can answer that.
 
RGS
5:45 PM
alright, thanks for the namespace thing.
 
@RGS afaik Dyalog only provides the -script flag (idk if it's the same in windows) to dyalog, which reads code from the stdin as pure REPL input. You'd probably want some your own written function/executable that does dyalog -script with stdin being ⎕fix'theWantedFile', emulating what you've done above
iirc Adám's also mentioned they might be getting better ways of executing files in the future
 
RGS
so in linux dyalog becomes a recognized command once you install dyalog?
 
@RGS yeah
 
RGS
@dzaima also, does that mean that if my .dyalog file has code other than function definitions and I ⎕fix it, it'll run?
 
@RGS yeah. ⎕fix'filename' is what TIO does
 
RGS
5:53 PM
Thanks!
 
@dzaima i may have lied, you still need the :namespace wrapper for any code ⎕fixed. Any code in it should get executed though
 
RGS
@dzaima Alright, thanks
I'll try those on
@dzaima if I have cube ← 3 3 3⍴⍳27 and I do ↓cube, shouldn't I get a vector where each element is a matrix?
 
@RGS "splits" dimensions in the opposite order you expect
 
RGS
Alright...
It does look weird
 
IIRC ↑¨↓↓A is what i've always done, but there must be a better way to do this..
 
6:08 PM
⊂[2 3]A does the same thing, right?
 
RGS
@dzaima the amount of ↓ you used there was depending on cube being a cube, right?
 
@RGS And amount of ↑¨ too..
 
RGS
@dzaima Then I think I prefer the ⊂[2 3] solution
 
@RGS indeed you should, i just didn't know of it.
 
RGS
:)
 
6:10 PM
@Adám if ^ can be generalized for any "split from first axis" (as opposed to "split from last axis"), could it be added to APLCart?
 
⊂⍤¯1 ?
 
@voidhawk hm, it's already there, albeit in a bit more confusing {⊂⍤¯1⊢1/⍵}Y form
 
What's the purpose of the 1/?
 
@JamesHeslip make scalars become vectors
it makes sure the result is always a vector
(i'd personally prefer an error because a scalar has no major cells, but ¯\_(ツ)_/¯)
 
@dzaima interesting. Not come across this use of replicate.
 
RGS
6:26 PM
@voidhawk I like this, thanks
 
@dzaima hah fair enough; isn't tryAPL itself arbitrary execution? What is it trying to limit?
 
@AntonDyudin i don't know, possibly file access/⎕SH/similar things? afaik there isn't any way to do anything non-APL in tryAPL
 
Right but if it's transpiling the input to error out on ⎕SH, it could just inject the same filter into a ⍎ wrapper
and I'm assuming it's a strict subset of things you could run in Dyalog
 
@AntonDyudin indeed it could, but it probably wasn't worth the effort (though, that'd probably be easier that writing a custom digit parser? maybe some other things leaked with ?)
 
{} for null pointer ("pointer to a segfault" trap representation) does make sense, presumably you can just like ⊣ not dereference it and everything would be fine
@dzaima that's my question though, how can you "leak" something beyond (sandboxed) arbitrary code execution which is the whole point of the service
 
6:35 PM
@AntonDyudin a "null pointer" can't have a type though - is 2 ⊣ nullptr "apply ⊣ to 2 and nullptr" or "an (f g h) train"?
with {}2 the answer could maybe be expected to be of an array type (dzaima/APL allows dfns to return a function with no problems however), but in Dyalog can return both functions and arrays
 
yeah you're right it looks like the _only_ thing I can do with it is return it from a function / into a repl
there's some way to catch value errors right? with `::`?
 
@AntonDyudin yeah, in dfns (or some :trap thing in other places iirc)
aplcart says 6::
 
ah I see what it means by value context
"shy results" relevant, I suppose?
 
afaik this is the thing behind TryAPL
@AntonDyudin huh, i wouldn't have expected for the error guard to activate there
 
(how much of the answer to "why is an APL type system hard" that APL is very dynamically scoped, more than anything else)
 
6:45 PM
dzaima/APLs behavior. To note is that dzaima/APL doesn't have shy results, but i don't think that's what's responsible for this
 
huh the TryAPL link implies ⍕⍣¯1'⍳4' would work(in unsandboxed dyalog), which doesn't look like the case? would be aesthetic if true certainly
 
@AntonDyudin (you forgot to separate ¯1 from '⍳4') it could return '⍳4', but that'd be pretty pointless. It seems it's an limited only to stringified number vector arguments
hm, it's even more strict than that, which is expectable
 
you're right I pasted the wrong version, the one with parens (⍕⍣¯1)'⍳4' also doesn't work
oh it inverses just canonical representations nice
…wait then why put it on the TryAPL ban list? it also won't do dfns looks like
 
@AntonDyudin probably because of bugs - (don't) try (⍕⍣¯1)''
 
noice
it's okay my session log was backed up ^-^
 
7:25 PM
pulling on one thread of this, the needing a variable type table to drive parsing
there's definitely something I'm fundamentally failing to grasp about the- operator precedence, in e.g. `8 9@2 3⊢⍳4`
like obviously it does what it looks like it's trying to do (`1 8 9 4`) but, what are the rules, ---I thought APL didn't have PEMDAS---
Especially since, x←8⋄ x 9@2 3⊢⍳4 is x←8⋄ (x 9)@(2 3)⊢⍳4, f←(2×⊢)⋄ f 8 9@2 3⊢⍳4 is f←(2×⊢)⋄ f ((8 9)@(2 3)⊢⍳4), so how can fixing {(⍎⍺)8 9@(⍳⍵)⍳4} possibly work?
it does, tbc
    ↑'7-'{(⍎⍺)8 9@(⍳⍵)⍳4}¨3 2
 7  8  9  4
¯8 ¯9 ¯3 ¯4
 
@AntonDyudin fixing only tokenizes the function, there's no AST; binding operators, creating strands, figuring out whether a thing is monadic or dyadic happens at runtime
 
…even in the co-dfns GPU case??
I guess that might not have (/have deoptimization on) ⍎
 
@AntonDyudin i don't know what that does, but it probably can't both have perfect Dyalog interoperability and compilation at the same time.
 
strand creation = 1 2 3 from 1 and 2 and 3?
 
Dyalog does have a compiler to bytecode, but it only works when a function doesn't use things defined outside & only handles operator arguments being functions
 
7:33 PM
ah so vaguely train shaped thigns
 
@AntonDyudin (at least in the first version in Dyalog ~14) it, funnily enough, didn't handle trains. ¯\_(ツ)_/¯
@AntonDyudin yeah. A more complex case being 1 f 3 - if f were 2, then it'd be a strand, if it were a function, dyadic application. (monadic operator - binding left & evaluating on 3, dyadic operator - bind both args. you get the idea)
 
figuring out whether things are dyadic or monadic = whether 1f2 is (⊂1),⊂(f2) or 1 is an argument?
right
oh huh APL is _evaluated_ right to left but presumably parsed left to right
is how you can do the operator thing
 
@AntonDyudin it's still parsed right-to-left
@AntonDyudin i was more thinking along f + 2 - either f (+ 2) or + applied to the arrays f and 2
 
okay so for 8 9@2 3⊢⍳4
can you step me through right-to left when the 2 3 gets "reassigned" from to @?
like first you have 4 which is 4, then you apply to it which is at present presumed monadic,
 
@AntonDyudin dzaima/APLs debug output
 
7:37 PM
then you see which "seals"? the monadicity
 
@RGS What is the big picture of what you would like to accomplish?
For example, are you trying to develop a set of functions that work together?
 
@AntonDyudin exactly. To determine whether a thing is dyadic or monadic, you need to know what's on its left
@dzaima it skips over strand creation unfortunately, i haven't added logging for that. it's handled separately from everything else
 
Afaik J for example does not evaluate until it sees the thing on the left
 
I mean yeah you literally can't know if ⊃ has an index or defaults to 1
and it sounds like you need to grab unboundedly many things on the left bc they might be an input to an operator
 
this is the place in my impl where the actual patterns are checked - for example that one - "D!|NFN" - means "match 'noun func noun' and either have the expression end there ('|') or have something that's not ('!') a dyadic operator ('D')
 
7:42 PM
in e.g.
      7 8 9@3 (2×2) 5⊢⍳6
1 2 7 8 9 6
      7 8 9 '@' 3 (2×2) 5⊢⍳6
1 2 3 4 5 6
^ the whole thing on the left is an argument to ⊢ which gets to be dyadic after all
 
@AntonDyudin it actually turns out you need to only look at the 4 most recent things (to the left), from those you can make all the decisions. The stack to the right of those 4 can get arbitrarily large though
 
but yes if a strand is a "thing" that makes sense
 
@AntonDyudin Not APL, but parsing J should work the same way: jsoftware.com/help/dictionary/dicte.htm
 
@voidhawk thanks, i meant to link that, but forgot :|
 
tbh I find J's parsing rules quite neat (idk apl though)
 
7:55 PM
@dzaima uhmm, i linked that to the LPA branch.. this is the proper place
(my way of parsing is definitely not optimal and shouldn't be thought of as anything good; it's ~100-200x slower than an equivalent train/Dyalogs impl)
 
RGS
@PaulMansour Also this, yes.
But say I wanted to make a parser for a calculator, I'd like to "run" a file in some way and then give expressions as input, for example. Or just a single expression.
 
8:12 PM
how inaccurate would it be to model all dyadic functions as "variant, but if no ⍺ is provided throw" and all monadic functions as "dyadic, if ⍺ is provided strand it with the result"?
just like… hoist the runtime application semantics into the definition of "a function", in a kinda operator-overloady way
hides FORTH under a rug
 
@RGS I take it you specifically do not want to be in an APL session and interactively work there? You want to be on the command line. Correct?
 
@AntonDyudin what do you mean by "monadic functions"? Only monadic-only "function" i can think of in dyalog is +\
 
ah okay I see even something like ⍎ which is defined as "monadic" will happily take an ⍺ and just complain about having done so, the second part definitely doesn't hold then!
 
@AntonDyudin can actually have a valid left argument - a namespace. e.g. m←⎕ns⍬ ⋄ m.a←2 ⋄ m⍎'a+2'
 
RGS
@PaulMansour either go to the command line and run APL's analogue to "python my_script_name.py" or open the Dyalog interpreter and, hopefully, type a command/call a function/wtv and then run my "script"
 
8:25 PM
…things the mouseover docs don't tell you
then yeah on +\ you get SYNTAX ERROR: The function does not take a left argument
which makes sense as a special case
getting a "syntax error" on the ⍺⍺ in +\{1 ⍺⍺ 2}⍬ is somewhat disconcerting but I see where it's coming from given all the tree-rewriting (stack-rewriting?)
 
@AntonDyudin indeed they don't seem to. @Adám?
@AntonDyudin it would be nice if that error message noted which function does not take a left argument
 
@dzaima Especially if ⍺⍺\ is literally the only (built in) function in the system that doesn't
 
@AntonDyudin +∘2 is another case, albeit has a bit more specific requirements
 
@RGS For the second option, have you looked at Link or Acre? If you have a project (a folder full of code) you simply open it, all the code is fixed, and you run your script (just a function really) So you can use your code, and also trace/edit create new functions, refactor, etc, all within the interpreter.
 
ah okay yeah, in general will produce functions that "syntax" error on being given
 
8:32 PM
@dzaima obligatory mention of dzaima/APL (ignoring the fact that my ⍺⍺ and ⍵⍵ are and and that i have some actual function for dyadic f\)
 
yup those look super helpful!
(what do you get if you dyadically apply to functions, wouldn't the resulting train still have problems of eventually passing in an ?)
¯1 f\ ⍵ = linear runtime dangit? ;)
 
@AntonDyudin dyadically apply what?
 
like it's saying 1 (+∘2) 3 is bad bc 1 and 3 aren't functions
what do you get from + (+∘20) +
 
@AntonDyudin my regular monadic f\ is linear, left-to-right. Dyadic A f\ B is f¨ A ,/ B
@AntonDyudin this. No checking is done at train building time as the only way of knowing whether a function has a dyadic definition in my impl is by executing it and possibly receiving an error, but it does get checked at evaluation
 
bc in Dyalog you get a pointer to a segfault a delayed-action function-which-errors-with-"no left args >:("-when-you-call-it, for arbitrary args
ah bc the left arg check is in the implementation of and not the like language
still feel like "try applying this dyadically to functions" is not a suggestion the error message should contain ;)
 
8:40 PM
@AntonDyudin is handled like any other operator, always, so a manual implementation of should work just the same, and asserting that that will always error if passed an array operand and is in the center of a train is way more complicated
 
I guess the itself is the thing you want to dyadically apply to functions if you want to dyadically apply it later, hmm
 
@AntonDyudin should doing f←{⎕SIGNAL 11} not be allowed because any call to f will result in an error? :p
 
hah can you manually check if something is a function or not? I guess that's kinda important for doing anything fancy
 
@AntonDyudin ⎕NC'varNameOfThing'
 
ah yes the "should {~2} be a type error" debate. I think my claim is "aborts should be clearly intentionally marked"
ooh nice
      ⊢{a←⍺⍺⋄⎕NC'a'}⍬
3
      1{a←⍺⍺⋄⎕NC'a'}⍬
2
(not sure why ⎕NC'⍺⍺' didn't work, but I suppose it's not a ~dynamic~ name)
 
8:46 PM
@AntonDyudin these kind of statically determinable always-errors is what i'd expect a static analyzer to check, not the language itself, especially at runtime
 
@dzaima - That only works if 'varNameOfThing' is a user-defined name. If you pass it an arbitrary string that contains a built-in, e.g., '+', it will return ¯1, 'Invalid Name'.
 
@JeffZeitlin hence why i said varNameOfThing
if there was a generic type checker, should ⎕type'{⍵}' work? Should ⎕type'⎕←1 2 3'?
 
yup the thing I meant by "gradual typing" earlier is "at fix time, where feasible"
not like absolute certainty on the type of everything, or any runtime overhead(here excepting the repl / ⍎ from "runtime"), or trying to do abstract dynamic dispatch(types should imo be fully erasable)
 
(that said, i can understand wanting a thing that'd also be able to tell types of builtins, however pointless in practice that'd be)
 
I mean you can tell the type of builtins just fine
      '\'{x←⍎⍺⍺⋄⎕NC'x'}⍬
3
 
8:51 PM
@AntonDyudin Jeff Zeitlin noted that ⎕NC'+' doesn't work, which i was responding to
 
@dzaima - It would depend on what the acceptable return values for ⎕type would be - in the first case, ⎕type '{⍵}', I'd want it to return function, subtype dfn; the second case, ⎕type '⎕←1 2 3', should either error or produce executable statement.
 
it's "okay but what does the operator do in terms of domain to range set-of-possible-values" that's nontrivial
 
ngn
@AntonDyudin that doesn't have to be an operator
 
@JeffZeitlin that'd require a separate execution system that can specifically separate "executing" expressions and "non-executing" ones (even more confusion arising with niladic functions)
 
I'd describe the ⎕type of ⎕←1 2 3 as the same type as 1 2 3 namely 3⍴⌊(⊃⍣≡)
(idioms WIP obviously that's not concise enough to be usable)
 
8:54 PM
@AntonDyudin but should it also output 1 2 3 while getting the type?
 
no, I claim it's possible to build such a system without allowing side effects aborts etc :P
 
@dzaima - I recognize that there would be issues, which is why I'd accept an error for the second case.
 
(inexpressibility of infinite/exponential loops I can't promise)
 
@JeffZeitlin that still requires something to separate the cases, not reducing complexity at all
 
I would not accept an error in the second case, any input ⍵ that would ⍎ in the current namespace (and its ⎕IO ⎕FR etc) should ⎕type to what the result would be
the result type might be "any", i.e. (⍎'⊢')
 
8:58 PM
@AntonDyudin ⎕type'⍎(?2)⊃''+2'''?
 
(where ⍎ is being used as a "black hole" where, as far as the type inferencer is concerned, what came out could have been a value of any sort or an operator or a function)
getting there :)
oh that's easy ⎕type'⍎whatever' is (⍎'⊢') i.e. "not even going to try to typecheck this"
 
⎕type'÷0'? imo Dyalogs ⎕NC'var' is a pretty acceptable compromise
 
⎕type'⍣(?3)' is going to be a fork type between the possible powers
⎕type'÷0' is ⎕type'~2' is "can never compute"
 
@AntonDyudin aaand you've got to make a proper type system in APL while not providing a proper type system.. Then, ⎕type'⊂⍣(?⌊÷?0)⍬' would be an infinitely big fork type?
 
(DOMAIN ERROR technically, but like, not actually that interested in tracking which exceptions might happen tbh. I guess you do need to model ::…)
⍳10e10 is for practical purposes an infinitely big list yet dyalog manages to it just fine
…or it doesn't? TIL
that's not even very big of an infinite fork tho, it's just ⍬∪⊂∇
but yes in the general case you have
- a lack of guarantee that you can't get the typechecker into an infinite loop, any more than there's a guarantee that evaluating ~⍣≡ 1 won't infinite loop, types are programs (though on both sides WS FULL is more likely than true infinity)
- some heuristics for assigning something a more general type than you can strictly prove it can contain, (2×≢⍞)⍴1 just gets you "unknown-length vector of 1s" (or "of 83⎕DR") not "unknown even length"
Like, the core insight of gradual typing as applied in Typescript and mypy
is you already _have_ a strong typesystem, it's the runtime one, you don't need to worry about pointers running amok or w/e
so the static one can afford to be weak and pliant (one operator you'd almost certainly need is "treat ⍵ as type ⍺⍺ because I said so, don't bother checking anything at runtime bc that would be too expensive")
also, any syntactically valid APL program _without_ type annotations should typecheck, just to less than helpful outputs like "function from array to array"
except in cases where the checker can prove there will be a crash(and the crash looks vaguely unintentional), contrast "conventional" static type discipline where it is your job to prove to the typechecker that there won't be one
 
9:19 PM
seems this conversation about separating functions from arrays has devolved into full-out type systems
 
(and relatedly "didn't typecheck" isn't "refuse to parse the rest of your workspace", it's "never type with annotation for why it's a never" - though you do want to print those as warnings if they get dropped from "definitely crash" checking by being e.g. in a branch)
@Adám is the context here yup!
 
if i were to make a type system for APL i'd enforce it everywhere and it'd be very very much all symbolic - so would be of type "vector of characters with length X", so (2×≢⍞)⍴1 would be "vector of 1s with length 2×X"
 
Like my MVP proposition was described as "on the ⍴ and ⎕DR level"
operators have the type "operator with this implementation", functions have the type "function with this implementation", function or operator names that are reassigned get fork types, values have a ⎕dr number and a ⍴ type and both of them can be forks
I get the criticism about abstraction making it impossible to follow code in haskell, which is why I'm explicitly omitting type-based dispatch: I am also mindful of the criticism that "type annotations take 5-7x more space than the code itself", but that's not a showstopper it's a ~design constraint~
 
@dzaima also probably no fork types, so ⊂⍣(?3) would either just not compile, or be of type "simple scalar to simple scalar" if i'd be crazy
 
which guides decisions like which things are too obnoxious to get a detailed type for
in my system "code which produces the desired result at runtime but the typechecker outright rejects" is forbidden, that's what any is for ^-^
(carving out a space for "we're defining 2 2+3 3 3 LENGTH ERROR as not a possibly desirable result at runtime, if the analysis can prove you'll hit it", which does add any annotational burden if you were relying on it. but like, >50% more characters in typed than in all-type-annotations-erased code would be considered a failure, and ideally I'd want to stay much under that)
50% after hypothetical type-oriented operators like ∆type and ∆like and ∆or and ∆and and ∆rhotype and ∆assert and ∆assume get stabilized and assigned glyphs that is ;)
(tho in the "types are runtime validators" scheme ∆and at least is just composition)
 
9:33 PM
and that's only the monadic case..
 
hmm that sounds like the symbolic logic you were describing earlier
while I'm trying to go for "only values have types" (but functions and operators are kinda values)
 
@AntonDyudin that is what i was going for. You do need to have known types of functions though, otherwise how will you know how 2∘⊃ changes the type of its argument?
 
like, my vision of a type inference pass is an APL interpreter except at every step you have to consider all possible input values instead of just one
an APL interpreter is not a _simple_ beast but it feels… buildable
 
@AntonDyudin that would explode quickly, but is probably the most feasible
 
it explodes and then you notice where it explodes and say "sigh just drop that to any" and then you iterate
function "¿": "forget the type of ⍵". Pretend they're everywhere nontrivial, then slowly remove them to brings the types into focus
(runtime semantics (⍎'⊢') except ideally also not binding to operators)
runtime semantics '' I guess :P
monadic meta-operator applies ⍵⍵⍵ to ⍺⍺
 
9:50 PM
@AntonDyudin hyperator?
 
sounds right, the type annotations have to bind tighter than anything else so you can insert them anywhere basically
or well, so you can type operators, type annotations for functions can be just operators and type annotations for values just functions
alternately you can give up on typing non-builtin operators and only have opinions on their output functions, but that's no fun ^-^
 
RGS
@PaulMansour I don-t know those options!
 
ngn
10:37 PM
no takers for this little cmc to show off their optimisation skills?
 
@ngn calculating permutations efficiently in APL requires a very specialized algorithm, which i don't know, and searching for one would just be showing off my googling skills..
and i couldn't myself come up with any semi-efficient algorithm that i would've thought was worth trying to implement
 
ngn
@dzaima there's a simple recursive algorithm: generate permutations for n-1, make n copies and adjust the numbers in them (p+p≥i for the i-th copy p), and concatenate
the hard part is optimising it
 
@ngn and just that implemented lazily already beats the dfns version? o.O
 
ngn
@ngn forgot to mention: also prepend i to each in p
@dzaima the dfns version is pretty slow
@dzaima can i see your code and maybe suggest improvements / steal ideas?
 
10:54 PM
@ngn this is that very lazy version, i've already got ideas how to improve it
 
ngn
ok
cmpx says -72%, not bad
 
that was 240ms, i've now got 16.7ms, but that's also all of my idea applied
i'm surprised to say the least
that's that. now to test performance gain/loss on going more vector-y (this is only a ~3x improvement in dzaima/APL, possibly because i had to do ↑2⌿↓ because i haven't implemented 2⌿matrix+)
definitely an improvement going more eachy (that's the word i was looking for)
 
ngn
@dzaima that's -89% and another -47% :)
it may be better to switch to n=10 for timing
 
11:10 PM
previous was 80ms in dzaima/APL, that's 60ms, but now i have no excuses for being 25x slower (as it should be)
that ⍪/ on the last iteration alone takes 35ms due to copying everything 9 times ¯\_(ツ)_/¯
@dzaima actually i don't need that first r⌽¨..
that's a surprisingly huge improvement
 
ngn
@dzaima yes, and you're pretty close to my own best
 
ngn
11:25 PM
@dzaima i generate the permutations as the columns of a matrix and they are lexicographically sorted, so it's not entirely apples-to-apples
 
meanwhile i just got a syserror 999 :)
can't reproduce, but have the aplcore saved
 
ngn
^one for @Adám
 
(maybe it wasn't 999 actually, i autoclicked off. definitely an interpreter crash)
 
11:49 PM
 
ngn
@dzaima i trust cmpx more than ]runtime
 

« first day (1176 days earlier)      last day (1479 days later) »