Skip to content

Hacker’s Corner: Packages in Dyalog APL

Vector 18:4, page 126

programming techniques implementations

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 126

Extract taken from "SHARP APL vs. APL2 coding style" by Dan Baronet , Vector 16.2

Packages are unique to SAPL and are very useful. A series of system functions can be used with them, all of which start with ⎕p as in ⎕pack , ⎕pdef , etc. For example, to define variable ‘x’ with objects (variables, functions) ‘a’ and <f> (for example to be stored on file) you would do

x←⎕pack 'a f'

Think of them as static namespaces (found only in Dyalog). You cannot "enter" a package and run something from within it. For example, if you wish to use its contents in a local environment you must first localize the names. For example, this function <execin> will execute an expression using a package’s contents:

    ∇r←exp execin pack;f
[1]⍎⎕fx⊃('f',';',⎕pnames pack)⊃'⎕pdef pack ⋄ r←',exp
    ∇

OK, so Sharp’s APL had packages and Dyalog does not. How can I emulate them in Dyalog APL/W?

Simple, represent a package as the ⎕OR of a namespace.

Pack←{x←0 ⋄ b←⎕EX'x' ⋄ b←'x'⎕NS ⍵ ⋄ ⎕OR'x'}
Pdef←{'##'(⎕NS'').⎕NS ⍵}
Pnames←{0::'' ⋄ ⍵⍎'⎕NL ⍳9'}

That’s it, according to MS Word all done in 95 characters!

Sample Usage

   package←Pack ↓⎕nl 3

   Pnames package
Pack
Pdef
Pnames

   )erase Pack Pnames

   Pdef packages

   )fns
     Pack     Pdef     Pnames

For readers not familiar with "DFNS" I will break then down line by line.

PACK

Pack is in four parts.

Part 3 creates a namespace "x" and copies the right hand argument into it.

Pack←{ ⋄ ⋄ b←'x'⎕NS ⍵ ⋄ }

Then Part 4 returns an Object Representation as the package.

Pack←{ ⋄ ⋄   ⋄ ⎕OR'x'}

Unfortunately, some "housekeeping" is required.

The name "x" has not been localised, so I can do this by assignment in Part 1.

Pack←{x←0 ⋄ ⋄ ⋄}

Part 2 then expunged "x" so it can be re-used as a namespace.

Pack←{⋄ b←⎕EX'x' ⋄ ⋄}

(From Dyadic on-line help on Create Namespace :"The namespace x is created if it doesn’t already exist. If the name is already in use for an object other than a namespace, APL issues a DOMAIN ERROR.")

PDEF

Pdef copies the contents of the items in the package, into the current namespace.

Pdef←{''⎕NS ⍵}

Unfortunately, this fails if the current namespace is either # or ⎕SE, so I run the Create Namespace in a temporary un-named namespace, requesting to copy the items into the "outer" namespace defined by ##.

Pdef←{'##'(⎕NS'').⎕NS ⍵}

PNAMES

Pnames lists the contents of the "package", by executing the Name List system function from within the "package" via dyadic execute.

Pnames←{   ⋄ ⍵⍎'⎕NL ⍳9'}

In case of error, Pnames returns an empty vector, via the error trap.

Pnames←{0::'' ⋄ }

Challenge

Can anyone out there in Vector-land, re-write this in let’s say 42 characters?