Scripts/WS Files
An APL workspace is a collection of names available in the runtime environment, which can be saved into a file that is also called a workspace. The memory workspace roughly corresponds to J locale, however in J there is no standard facilities to store locales in files, except for redefining the names from text.
This script provides succinct facilities for persisting J locale names in binary files in a way close to how APL commands )SAVE, )LOAD, )COPY and )LIB work.
Features
- select names by mask, type (0 1 2 3) using nl convention or verbatim list
- wsload and wssave work with selective names, providing "copy" functionality
- wsnl lists contents of workspace, filter parameters show the same names as for wsload
- protect flag prevents overwriting of existing names in file or locale
- works in current locale, specify locale _suffix_ to override, eg wssave_j_'' saves locale j
- uses keyfiles as storage backend
- stores extra info: name class and size
- nouns are saved using binary represenation 3!:1
- non-nouns are stored using atomic representation 5!:1
- affected names are returned in boxed list with "-" prefix for protected names
Applications
- ad-hoc storage for J locales
- save-restore functionality for postponed calculations, such as saved session between stateless requests in HTTP server etc.
Script
The script is based on original File:Ws orig.ijs by Eke van Batenburg posted Mar 24 1997 to comp.lang.apl.
NB. wsfiles - workspace files in J NB. works in current locale, specify _suffix_ to override NB. 04/18/08 Oleg Kobchneko - extended j60x version NB. 03/24/97 Eke van Batenburg - initial prototype NB. http://groups.google.com/group/comp.lang.apl/msg/861e2f6641b5905e require 'files jfiles' coclass 'z' WSEXT=: '.jws'
Public interface
wssave v save names (of types) x to file y
wsload v load names (of types) x from file y
wsnl v list names (of types) x in file y
NB.*wssave v save names (of types) x to file y
NB. y filename[;protect]
NB. filename with optional extension, .jws default
NB. protect names: 0 or 1 (1 default)
NB. x names pattern or types 0 1 2 3, all default
NB. eg 0 3 wssave 'work'
NB. '*bc' wssave_z_ 'work';0
NB. ('a';'bc') wssave 'work';0
wssave=: 3 : 0
'' wssave y
:
'fileName prot'=. 2{.(boxopen y),<1
if. -.fexist fileName=. wsfile fileName do.
keycreate fileName end.
dir=. nl''
if. 0=#x do. names=. dir
elseif. 32=3!:0 x do. names=. x #~ x e. dir
elseif. 2=3!:0 x do. names=. x nl ''
elseif. 1 do. names=. nl x end.
z=. ''
for_name. names do.
if. prot do.if. -. _4-:keyread fileName,name do.
z=. z,'-',&.>name continue. end. end.
z=. z,name
cls=. nc <fullName=. cofullname name
if. 0 > cls do. continue. end.
if. 0 = cls do. value=. <fullName~
else. value=. 5!:1 <fullName end.
value keywrite fileName,name
extra=. <cls;(#@(3!:1) value)
extra keywritex fileName,name
end.
z
)
NB.*wsload v load names (of types) x from file y
NB. y filename[;protect]
NB. x names pattern or types 0 1 2 3, all default
NB. eg 0 3 wsload 'work'
NB. 'bc' wsload 'work';0
NB. ('a';'bc') wsload 'work'
wsload=: 3 : 0
'' wsload y
:
'fileName prot'=. 2{.(boxopen y),<1
fileName=. wsfile fileName
names=. x wsnames fileName
z=. ''
for_name. names do.
fullName=. cofullname name
if. prot do.if. _1 < nc<fullName do.
z=. z,'-',&.>name continue. end. end.
z=. z,name
cls=. >@{.&> keyreadx fileName,name
value=. keyread fileName,name
if. 0 = cls do. (fullName)=: >value
else. (fullName)=: value 5!:0 end.
end.
z
)
NB.*wsnl v list names (of types) x in file y
NB. y filename with optional extension (.jws default)
NB. x names pattern or types 0 1 2 3, all default
NB. eg 0 3 wsnl 'work'
NB. '~bc' wsnl 'work'
NB. wsnl 'work'
wsnl=: 3 : 0
'' wsnl y
:
fileName=. wsfile >y
if. #names=. x wsnames fileName do.
extra=. >keyreadx fileName,<names
(;:'name nc size'), names ,. extra
else.''end.
)
Private helper verbs
Not intended to be used externally.
NB. =========================================================
wsnames=: 4 : 0
('File ',(>y),' not found') assert fexist y
cls=. >@{.&> keyreadx y
dir=. keydir y
if. 0=#x do. names=. dir
elseif. 32=3!:0 x do. names=. x #~ x e. dir
elseif. 2=3!:0 x do. names=. dir #~ x wsmatch dir
elseif. 1 do. names=. dir #~ cls e. x end.
)
wsfile=: 3 : '< jpath ,&WSEXT^:([:-.''.''&e.) >y'
wsmatch=: 4 : 0
if. 0=#y do. '' return. end.
if. 0=#t=. x -. ' ' do. y return. end.
'n s'=. '~*' e. t
t=. t -. '~*'
b=. t&E. &> y
if. s do. b=. +./"1 b
else. b=. {."1 b end.
n ~: b
)
Testing of available functionality. Very helpful to maintain validity during code changes.
NB. =========================================================
Note 'Test' NB. select and Ctrl+E
ferase jpath '~temp/test.jws'
erase nl''
abctst=. 1 2 3
abetsz=. 1;2;3
abdtst=. +
cd1tst=. /
cd2tsz=. "
assert 3-:# 'a'wssave '~temp/test'
assert 0-:#(;:'a')wssave '~temp/test'
assert 3-:#'*tst'wssave '~temp/test'
assert 2-:# 0 wssave '~temp/test'
assert 3-:# 0 1 wssave '~temp/test'
assert '-'*./ . = {.&> 0 wssave '~temp/test'
assert '-'*./ . ~: {.&> 0 wssave '~temp/test';0
ferase jpath '~temp/test.jws'
wssave '~temp/test';0
erase nl''
wsnl '~temp/test'
assert 4-:# 'a'wsnl '~temp/test'
assert 0-:#(;:'a')wsnl '~temp/test'
assert 4-:#'*tst'wsnl '~temp/test'
assert 3-:# 0 wsnl '~temp/test'
assert 4-:# 0 1 wsnl '~temp/test'
wsload '~temp/test'
assert abctst -: 1 2 3
assert abetsz -: 1;2;3
assert (5!:5<'abdtst') -: (,'+')
assert (5!:5<'cd1tst') -: (,'/')
assert (5!:5<'cd2tsz') -: (,'"')
erase nl''
assert 2-:# 0 wsload '~temp/test'
assert '-'*./ . = {.&> 0 wsload '~temp/test'
assert '-'*./ . ~: {.&> 0 wsload '~temp/test';0
erase nl''
ferase jpath '~temp/test.jws'
)