A couple of years ago I worked on a non-trivial APL application with one of my university professors and another student. We were trying to build a CPU simulator flexible enough to handle stuff ranging from PDP-11 up to Intel x86. The goal was to run some analysis on memory accesses performed by the x86 architecture. Quite an interesting project in which I worked on for around two year.
The code is still available if you're interested: https://github.com/emlautarom1/PDP_11_Simulator
The first implementation was done in APL using a book which I don't remember as reference. We had a couple of meetings where we learned APL and the general idea behind the design. Pretty soon we started to deal with a lot of issues like:
- We only found two implementations for the APL interpreter: GNU and Dyalog. GNU is free but pretty much abandoned. Support for Windows was (is?) nonexistent. Dyalogs version is proprietary so we couldn't use that (even when a "student" version was available).
- You had to use a special keyboard layout since APL uses non ascii characters, which was only available for Linux. Every time you wanted to write some operator I had to look it up in a paper sheet. Eventually you start memorizing, but it was a pain in the earlier days.
- There is literally no community support. You can't just 'StackOverflow' some APL stuff.
- Dynamic scoping + dynamic typing make working on a large codebase pretty much impossible. You don't know when things are defined, and you don't know what they are.
- The language is extremely terse. I remember that a single line of code was able to fetch, decode and execute instructions. You're incentivized to write this kind of code, and even if you're able to understand all operators you still need to figure out the semantics of the code. For reference, I work with Haskell everyday and it looks like Java compared to APL.
- The code tends to be very hacky. You (ab)use the fact that most things are arrays and solve all problems using some form of indexing/map/reduce. You tend to forget about proper conditionals or custom data types. Domain modeling is pretty much non-existent.
- There is no built in support for test, and we could not figure out how to use a third party library for that (is it even possible to use third party code?). Our tests consisted in a lot of code that checked some conditionals, and then we printed "Pass" or "Fail" on each. Very primitive stuff.
- No debugging at all. You run the code and pray for the best.
A year after we started my classmate decided to drop the project since he felt he couldn't keep up with the complexity: each line of code was non-trivial and really hard to understand.
Eventually we had to rewrite the whole project because GNUs interpreter didn't support big integers, and trying to circumvent that resulted in very poor performance. The new version was written in Julia (https://github.com/emlautarom1/Julia_Simulator), so we were able to reuse a lot of "array code". The project got cancelled in the middle of the rewrite and we kind of forgot about it.