If you are familiar with C# or Java OOP you'll find this very familiar. Dyalog APL is an official (i.e. listed by Microsoft as a) .NET language and the object orientation is well aligned with C#.
@wizzwizz4 The syntax is identical to non .NET OO, so it doesn't really matter.
The first and most fundamental thing you need to be aware of is the APL objects are mutable, which is quite different from normal APL arrays which are immutable.
In computational mathematics, computer algebra, also called symbolic computation or algebraic computation, is a scientific area that refers to the study and development of algorithms and software for manipulating mathematical expressions and other mathematical objects. Although, properly speaking, computer algebra should be a subfield of scientific computing, they are generally considered as distinct fields because scientific computing is usually based on numerical computation with approximate floating point numbers, while symbolic computation emphasizes exact computation with expressions containing...
@Hosch250 Arrays do deep copies (apparently, it is optimised internally).
@EriktheOutgolfer Yep.
@wizzwizz4 True. But no, it is mainly based on numeric linear algebra.
@wizzwizz4 However, this only applies to usage in the machine executor (the interpreter). APL is well suited as a drop-in for conventional mathematical notation, and then it is of course symbolic. Indeed, APLers will sometimes use APL for proofs and derivations, etc.
Meanwhile, lets create the simplest APL type of object Dyalog APL has, the namespace.
A namespace is like a container for other APL items (functions, variables, and namespaces). It is very much like a JSON object.
One way to create a new empty namespace is using the system function ⎕NS. For now, we'll just use a dummy right argument; ⍬.
To assign into a namespace we use the dot-notation: namespace.name←value
We created the namespace a. Then we used its value to set b, then we set var inside a and inside b to two different values, but when we queried the two values they had become the same (the latter).
This is because APL objects are mutable. Another way to look at it is that the value isn't really the namespace itself, but rather a reference to a single object we created with a single call to ⎕NS.
Here we called ⎕NS twice, once on each of the two ⍬s. And so b and a refer to two different objects. Also note that there is no assignment arrow between b and a, but don't be fooled:
@wizzwizz4 None of the people around me know enough to answer that question. Sorry. Maybe by the end of the lesson you'll know the differences, if there actually are any.
Anyway, the last 42 42 result is of course (!) because of APL's scalar extension (vectorisation/mapping/…). Refs are scalar values, and so the scalar was distributed to both names, just like b a←42 would have done.
Namespaces are great ways to organise you code and data. But sometimes you need a better overview of the namespace content, or you want to put tradfns there (in an easy manner) or even put some comments in.
Would it be more efficient to create a sub-namespace, do everything in that, then go up one level to # to create new, almost empty (just one child & builtins) namespaces?
@wizzwizz4 Yeah. They don't matter, and the interface is such that you almost can't detect it. The underlying discussion can be found in the TIO chatroom's transcript.
@Hosch250 Each namespace has its own context. Having different states in each namespace is normal. Calling primitives from a different namespace in order to use that namespace's context is very unusual. I've never seen it in production code.
@wizzwizz4 Since APL doesn't have strings, only character vectors (lists), we translate those to JSON strings. JSON does not have a representation of a single scalar character (i.e. not a one-element character list).
Sometimes this inline way to handle namespaces is not convenient. Especially if you want to define tradfns inside the namespace. (It can be done with ⎕FX, though. See lesson 13.)
@wizzwizz4 It is, but what would you want instead? The alternative would be throuwing an error, and that isn't very useful. Also APLers will often use scalars and one-element vectors interchangeably, so this concession makes sense to APLers.
@wizzwizz4 Yes. APL's array model has many aspects which JSON just cannot represent. However, all JSON arrays can be represented in APL and be round-tripped back to JSON.
Moving on. To help you manage larger namespaces and especially code in namespaces, you can have a scripted namespace. The script is a simple text document which gets "fixed" into a namespace, much like the JSON text got converted to an APL object.
This uses a syntax similar to the control structures (lesson 15), namely :Namespace … :EndNamespace.
⎕←⎕FIX ':Namespace a' 'var←42' ':EndNamespace' ⋄ ⎕←a.var
Of course, the ⎕FIX usage is even more cumbersome (except possibly when you need to define namespaces under program control), but in an interactive APL session, you can enter )ed ⍟nyns to open the editor with a new namespace script. Since TIO isn't interactive, we've instead set it up so that you can use the "Code" field as a kind of editor to define your workspace. Text in the "Input" field correspond to what you would type into an interactive session.
… Then down in the Input field we first ask for the Name List (see lesson 14) in # (the root namespace) and again insidens and then we retrieve the value of #.var and ns.var.
By the way, from inside a namespace, you can access the parent namespace with ## and its parent with ##.## etc. # doesn't have a parent though, so #.## is the same as #.