« first day (628 days earlier)      last day (338 days later) » 
00:00 - 17:0017:00 - 00:00

5:29 PM
⎕←cmpx '(⊢+.(-×-)⍉)↑,⍳20 20' '(⊢+.(×⍨-)⍉)↑,⍳20 20'
⎕←cmpx '(⊢+.(-×-)⍉)↑,⍳20 20' '(⊢+.(×⍨-)⍉)↑,⍳20 20'⊣'cmpx'⎕cy'dfns'
  (⊢+.(-×-)⍉)↑,⍳20 20 → 7.3E¯2 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  (⊢+.(×⍨-)⍉)↑,⍳20 20 → 8.6E¯2 | +17% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
why does ↑ happen?
why is (-×-) faster than (×⍨-)?
(the code calculates the euclidean distance between each pair of 2d points in ↑,⍳20 20)
It might be that ×⍨- is probably something like atop(derv(times,commute),minus) whereas -×- is only fork(minus,times,minus) in memory. I can't tell if the performance difference is significant though
5:46 PM
@Adám I like this.
@Cowsquack are you trying to optimise this?
the operation, yes
@H.PWiz might be coincidental, trying with ⍳40 40 shows the latter as faster by 4%
@nathanrogers Sorry, I lost internet connection there.
@Cowsquack it's better to apply primitives to whole solid arrays, inner product applies the operand element by element because it's a custom function
hang on, i'll try to rewrite it
I want it element by element
5:49 PM
@Cowsquack why?
@nathanrogers The bot only handles single lines of code at a time and does not maintain a session between executions. Use TIO or TryAPL for more complex stuff.
to calculate the force of gravity for various point masses
for which I need to find the distance
@Cowsquack yeah, but why not have ×⍨ act on the whole array?
]runtime -c "(⊢+.(-×-)⍉)↑,⍳20 20" "(⊢+.(×⍨-)⍉)↑,⍳20 20"

  (⊢+.(-×-)⍉)↑,⍳20 20 → 7.5E¯2 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  (⊢+.(×⍨-)⍉)↑,⍳20 20 → 9.0E¯2 | +19% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
5:50 PM
@Cowsquack ^^ is easier
]runtime -c "(⊢+.(-×-)⍉)↑,⍳20 20" "(⊢+.(×⍨-)⍉)↑,⍳20 20" "{+⌿×⍨⍵∘.-⍤1⊢⍵}⍉↑,⍳20 20"

  (⊢+.(-×-)⍉)↑,⍳20 20     → 7.7E¯2 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  (⊢+.(×⍨-)⍉)↑,⍳20 20     → 9.3E¯2 | +21% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  {+⌿×⍨⍵∘.-⍤1⊢⍵}⍉↑,⍳20 20 → 9.7E¯4 | -99%
@Adám thanks, do they both provide the same funtionality?
@Cowsquack Yes, only the user command takes -modifers instead of the numeric left argument to cmpx (and the defaults are slightly different as you can see).
@DyalogAPL I am trying to understand how ∘.-⍤1 works
5:54 PM
]runtime -???


Time execution of one or more expressions

Argument is a series of expressions to run

-compare will compare the expressions using the first one as base line.

-details[=spec] specifies which details to include. It may be one of the following:
    all     (default) ⎕AI and ⎕MONITOR CPU and elapsed numbers with test function results
    none    only numeric results in millisecs as a matrix of Nx2
@Cowsquack First ⍤1. So the result ∘.- is applied to each row corresponding of the arguments (assuming they are not vectors). ∘.- just expands into a difference table. Just remember that the rank will increase rather that the result be nested.
I see now
⎕←r←(2 3⍴'abcdef')∘.{⍺'-'⍵}⍤1⊢(2 3⍴'ABCDEF') ⋄ ⍴r
5:58 PM
⍞←⍴(2 3⍴'abcdef')∘.{⍺'-'⍵}⍤1⊢(2 3⍴'ABCDEF')
@Adám 2 3 3
]runtime -c "{+⌿×⍨⍵∘.-⍤1⊢⍵}⍉↑,⍳150 150" "{{+⌿×⍨⍵∘.-⍤1⊢⍵}⍵ ⍵⊤⍳⍵×⍵}150"
* Command Execution Failed: WS FULL
]runtime -c "{+⌿×⍨⍵∘.-⍤1⊢⍵}⍉↑,⍳100 100" "{{+⌿×⍨⍵∘.-⍤1⊢⍵}⍵ ⍵⊤⍳⍵×⍵}100"
* Command Execution Failed: WS FULL
5:59 PM
Oh well.
@Cowsquack The shape ends with 3 3 because of the 3elements ∘.- 3elements and the shape has a leading 2 because there are 2 rows (in each argument).
@arcfide TIO has a rather limited workspace size by default (and you can't change it via the bot — only on tio.run):
@Adám 134182784
@nathanrogers Do you still need help with the thing?
actually I can't get tio to work :/
6:07 PM
@nathanrogers Can you post a link?
i got it. snakes and ladders with ⍺ game ⍵ where ⍺ is board width, and ⍵ is number of players
@nathanrogers And now you want to run game until there is a 25?
1 hour later…
7:41 PM
@Adám I think that's what its doing
game ← {(⍺*2){{⍵+⊃⌽sl[⍸sl[1;]∊⍵;]}¨⍺ adddice ⍵}⍣((⍺*2)∊⊣)⍵/1}
at ⍺*2∊⊣
APL doesnt have filter operator, does it? So the best way to filter is to test the expression and use the “where” operator? But that only works if the numbers form a pattern, so how would you filter? Something like ⍺⍺⍵:⍵⋄⍬?
@Quintec {(⍺⍺¨⍵)/⍵}
i.e. {1 2∊⍨10|⍵} {(⍺⍺¨⍵)/⍵} ⍳20 for numbers ending in 1 or 2
though for that specific case {(1 2∊⍨10|⍵)/⍵} ⍳200 would work too and should probably be faster
"probably" is an understatement. That is 54x faster :D
8:07 PM
Ah, makes sense
9:06 PM
Unnecessary abstraction, particularly, in the case of functional programmers, function abstraction at the micro-level, is an anti-pattern in APL.
@arcfide elaborate?
See my Patterns v. Anti-patterns talk for a full elaboration.
Actually, I should write a blog post about that, if I haven't already.
For APL: Premature abstraction is the root of all kinds of evil.
@arcfide did you see my game
9:10 PM
I saw it, but I haven't read through it thoroughly enough to make any significant comments.
The question of a "filter operator" versus the filter function already present, and the use of {(⍺⍺¨⍵)/⍵} in any sort of real practice is a perfect example of "premature abstraction."
And @dzaima's subsequent example of performance differences between the abstracted and unabstracted versions of that filter pattern is a great example of why premature abstraction is a problem.
its snakes and ladders
10:03 PM
@arcfide Wait, what filter function?
I may have not been clear - I would never use the first abstracted version in practice. It was simply a "format", if you will, of how best to apply a filter. I wouldn't use the function itself.
10:35 PM
@Quintec I was referring to @dzaima's response to your inquiry about a filter operator.
There is, of course, the filter function in APL, but there is not an operator.
Indeed, there's actually a subtle semantic/ideological shift that one might be best served in using if coming from Functional Programming. In Functional Programming, there is often the concept of a Boolean "filter" function, a decider, or tester, or some other form of function that is seen as containing the base concept of Boolean selection.
As an example, there are many "Hook" functions in Scheme that end with ? and are considered predicates.
These are often used inside of a loop to do filtering. One might often compose a MAP or Reduction with a Filter function in order to accomplish something.
This is an example of the Pattern tensions of Data vs. Control Flow and Transparency vs. Abstraction.
In functional programming filters are often considered to be functions.
In APL, when we talk about filtering, it's better to think of a filter as a mask; that is, filtering in APL is about Boolean masking arrays, rather than Boolean predicate functions.
Thus, one does not filter using a Boolean function, but rather filters using a Boolean array.
This shifts filtration from a higher-order operation to a first-order operation.
While the difference may appear to be a matter of little distinction, I think it illustrates one of the stumbling blocks that often trips up people coming from other languages.
And it serves to illustrate the shift in thinking between the APL way and the FP way or other methods. It's also why solutions can seem "elusive" to some beginners. They can see what needs to be done, and they might know how they might go about it, but their solutions often feel like this "miss the mark" in some fashion. Often the difference between the novice solution and a more experienced APLers solution is a matter of this sort of distinction.
And if one doesn't make the shift consciously or unconsciously, the code always feels just a little bit off.
But to generate the boolean array, you must apply some sort of function to an array. And then you must apply the boolean array to the array, unless I'm missing something
10:50 PM
Instead of thinking like that, the point is to think of it as first writing an expression that gives the appropriate Boolean array, and then filtering another array using that filter array.
You don't apply one array onto another array in APL.
There's a subtle "mindset shift" between saying "apply a function to an array" and "write an expression to give an array."
The issue that I try to fight is the tendency to create some helper "predicate" function that is then applied.
It's not that this is inherently a bad thing, but it is very often the case that abstracting into a predicate function just obscures the code.
That sort of thinking leads to things like {(⍺⍺¨⍵)/⍵} as above.
And the issue with that "pattern" is the Each in there.
I would consider the Each to be the obscuring and undesirable character in that line. By removing it you have better code, and by removing it, that code becomes obviously useless at the same time, which would be precisely the point. With the Each inside of that code, one might be tempted to think that such a pattern was worth encapsulating.
However, with the Each removed from that code, it becomes obvious that the operator is itself a redundancy that can be completely done away with.
Of course, with all of this, keep in mind that I'm very concerned with how our code speaks to us, and how the code suggests, moves, and alters our methods of thinking, and with the HCI of Programming Languages.
So a little thing like whether we use Each there or not makes a big difference.
And in the case of @dzaima's response, the sentiment was that the "inlined" case was a "specific" case, and the Each based case the more general. While that might be true at a semantic level, it's not true at an User level, where in APL, the inlined case is far and away considered to be the canonical, standard case, and the Each version considered to be highly exceptional.
And this has important ramifications for performance, code clarity, conciseness, compilation, and so forth.
00:00 - 17:0017:00 - 00:00

« first day (628 days earlier)      last day (338 days later) »