First of all, workspaces don't exist as an object, in the mainline Sawfish. There are just windows (objects), which have indices associated, and saved positions (other attributes as well) for the non-current index.
So, switching to a workspace N, windows which have the index N are shown using the corresponding attrubutes, others are hidden. So, a window can be in more workspaces.
So, the indices in windows are integer numbers, ...-1, 0, 1,....
But, having data local to workspace was hard: ad-hoc lists with specific values were used: workspace-names is an example.
To get a value from one of the ad-hoc lists, one had to produce an ordinal number, workspace-id-to-logical.
So, if we have WS -1, 0, -1, the workspace -1, is logically numbered 0.
To avoid exposing users to 0 (there is no key F0 on the keyboard), when asking user for a workspace number, another domain of numbers is used: 1, 2 .... Natural numbers (in the definition w/o zero).
The core functions try to work with (accept as paramenter) the indexes, and user commands' functions (i.e. functions associated w/ commands) try to accept the Natural numbers.
Then another way to prompt for workspace was introduced: by name. The prompt function returned the ordinal. So, functions which accept the ordinal, if we have the Natural, have to be called with 1- applied.
So, to get the index i used (workspace-id-from-logical n) rather than (workspace-id-from-logical (1- n))
to be continued....