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 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 keyfiles misc' 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'
)
