(Originally posted 2011-08-23.)
Over the weekend I decided to try my hand at writing a JSON parser in REXX. I developed the technique outlined in this post to enable me to do that. I think it’s new. Certainly I’ve not seen it before.
(I don’t want at this point to get into a discussion about why JSON parsing might be a useful thing to do. Suffice it to say it is possibly going to be second only to XML as a common data format in the future.)
Consider the following code:
/* rexx */ stem="mystem" call setvars stem say "MYSTEM.A="mystem.a say "MYSTEM.B="mystem.b exit 0 setvars: parse arg stem interpret setvars2(stem) return setvars2: procedure parse arg stem return stem".A=1;"stem".B=2;"
Here’s the problem it’s illustrating a solution to: I want to call a routine that sets arbitrary REXX variables but otherwise doesn’t create any side effects.
You’ll notice the “procedure” in the setvars2 routine that avoids the side effects. That’s pretty standard, actually. But it doesn’t allow any variables to be set. And I need them set.
So I return a string from setvars2 to setvars containing assignment statements. In this case the string is “MYSTEM.A=1;MYSTEM.B=2;” and it’s immediately executed – using the interpret statement.
The setvars routine (as you’ve probably guessed) is a wrapper. While it doesn’t use procedure – as I want the variables it sets to persist – it’s pretty clean: To the caller it appears clean, anyhow – as they oughtn’t to notice setvars2 that’s doing all the work.
There’s one fly in the ointment: The variable called “stem” gets set. I consider that a minor untidiness. If you, dear reader, know of a way of removing it I’d be interested in hearing it.
So it is possible to set variables in a routine that’s otherwise protected by procedure. You’ll notice that the variables that can be set are bounded by the stem passed on.
Seasoned REXX programmers are likely to think that expose solves the problem. Actually it doesn’t 😦 : I simply don’t know what the variable names will be and expose won’t take a string I could build. I thought about that and tested it.
You’re probably still wondering about my motivation: In the actual JSON parsing code you have to handle nested structures. So my equivalent of setvars2 calls itself recursively, passing back up a string containing assignment statements, separated by semicolons. These strings are appended to each other and the interpret in the equivalent of setvars indeed executes them.
We’re talking about resulting strings like:
"s1.a=1;s1.b.c='Hello';s1.b.centre.x=-5;s1.b.centre.y=22;"
which would come from a JSON string:
{ "a":1, "b": { "c":"Hello", "centre": { "x":-5, "y":22 } } }
One of the issues here is knowing which variables got set – as we don’t know the JSON in advance (for certain). The way I can see that being handled is to set a “dictionary” variable containing the names we gathered up along the way. And then we get into the question of JSON Schemae – which I don’t intend to discuss at all here.
And the reason for mentioning all this is that I can see the technique has a wide range of applications. For me it certainly gets around a thorny problem involving recursion.
And no, it wasn’t the highlight of my weekend: Probably that was Walkway Over The Hudson which I’d wanted to do since long before it opened 2 years ago.