Hacker News new | ask | show | jobs
by gandercrews 2236 days ago
gnu apl is an often overlooked but extremely solid APL implementation that plays nice w/ unix.

slightly verbose example but heres gnu apl as a pipe-like interface. Often this would be abstracted to a library that gets included when you call it:

  printf "1,2,3,4\n5,6,7,8" | apl --eval "f←{4⎕CR ⍵}◊s←{⍺~⍨¨⍵⊂⍨1++\⍺⋸⍵}◊f ⊃{⍎⎕UCS ⍵}¨¨44 s¨10 s⊣⎕FIO[41] 0"
  ┏→━━━━━━┓
  ↓1 2 3 4┃
  ┃5 6 7 8┃
  ┗━━━━━━━┛

DESCRIPTION:

    --eval ≡ evaluate the text

    f ≡ formatting function for printing nested values

    s ≡ partition a line of text and remove the partition character

    ⎕FIO ≡ read stdin as byte stream (see FILE_IO.apl)

    ⎕UCS ≡ convert bytes to characters

    ⍎ ≡ execute an expression (convert characters to numbers)

SUMMARY:

  read stdin as a bytestream

  partition at newlines and commas

  convert to characters

  interpret characters as numbers

  disclose into a rank-2 array

  format to stdout
4 comments

That is indeed often overlooked, I thought it was not ready for primetime and that somehow stuck in my head all these years. I hear no-one mentioning it either usually when these conversations come up.
Thank you for taking the time to break this down!

Your description and summary blocks have started me wondering... has there been much work done on converting APL statements to more verbose explanations?

The sigil-to-meaning mapping is likely automatic for seasoned APL programmers but it might make such one liners more effective for evangelist purposes by making them somewhat more self-documenting.

it indeed becomes much easier to understand after ~ a year. this thread included some discussion about making APL-family languages easier to read for novices: https://news.ycombinator.com/item?id=20728715

I'm of the opinion that code should be documented. Short description, arguments, return, purpose etc. However rebinding primitives kindve defeats the purpose after a little familiarity. For example:

commute ← {⍵ ⍶ ⍺} ⍝ or commute ← { ⍺ ⍶⍨ ⍵ }

will get tedious quickly. Its better to lean into the terseness of the language, rather than attempt to transform it into something it isn't. There has been work done for easing the learning curve, for example https://aplcart.info/ . Keep in mind aplcart generally targets dyalog, however many of the idioms should work for alternate implementations with possibly some tweaking.

GNU APL is pretty slow and makes some controversial design decisions. Fun to play with, though, and remarkably polished.
I'd be very interested in reading more about the differentiating features of GNU APL. There is a great big announcement at the beginning of the GNU APL docs that talks of a decision needing to be made around a gap in the ISO specification. Is that the primary source of controversy or is there more discussion I could read somewhere else?

I've been looking for a good "diff" of the language differences between Dyalog APL and GNU APL, as much as to understand the extent of the progress since 'APL2' (or whatever the ISO standard name is considered equivalent to it) as any for any specific list of what GNU APL can't do relative to it's modern commercial compatriots.

(EDIT: Fixed final sentence to be a complete thought/sentence).

dyalog has a few more operators. for example @ & ⍠. It lets you use statement separators in lambdas. In gnu apl you can simulate that with '⊣'. It allows multiline lambdas. Dyalog uses ⍺⍺ & ⍵⍵ for operators vs ⍶ & ⍹. Dyalog lets you use ∘ as a composition operator. Dyalog generally has better performance, which becomes noticeable with large arrays. It has a lot more libraries available. Gnu APL behaves more like a traditional unix based interpreter. Gnu APL has erlang, python, lua, and C interfaces.
I admit, GNU APL gets sluggish when dealing with values with more than ~100k elements. For most ad-hoc work it is satisfactory and can let you sketch out ideas before attempting to push the performance characteristics.
from article "In some cases, users and developers pair program together, and the source is their common language."

from example: f←{4⎕CR ⍵}◊s←{⍺~⍨¨⍵⊂⍨1++\⍺⋸⍵}◊f ⊃{⍎⎕UCS ⍵}¨¨44 s¨10 s⊣⎕FIO[41] 0

Mmmm... I code in C, Java, PHP, CaML, Prolog... for a long time... so I guess that I'm quite used to programming. But really: I can't make any sense of these hieroglyphs !!!! And NO user I ever worked with would either...

So I guess that I'll need a lot more sugar to taste APL...

its a golfed example to show that its possible to use APL as a cli tool. I would not put any code into production that looks like this. Generally it would go into a library.

APL has an initially steep learning curve, because it is so distinct historically from other languages. But it is a quite simple language once you learn it.

1. Every statement is executed right-to-left. Statements are executed top to bottom (or left to right with ◊ as a separator).

2. The only precedence rule is parentheses

3. Functions can be called with one operand (monadic) or two (dyadic)

4. Values in APL have a shape (dimensional size), a rank (number of dimensions), and a ravel (a list of elements). Values can contain other values (nesting)

  {} define lambdas
  ⍺ is the left operand
  ⍵ is the right operand
  ⍶/⍹ are the left/right operators (higher-order functions)
  ← assignment
  ◊ statement separators
  ¨/\⌿⍀⍣⍤⍨ builtin higher order functions
After some familiarity it becomes as easy (or easier) to read as any other language. You can encode a remarkable conciseness of expression into each lambda, that you plumb together (similar to unix pipes in a way) in higher order patterns.
Do you also expect to know Russian after learning German and Chinese?