G'MIC Tutorial Fragments

In Post 393 of On the road to 3.0 @garagecoder sighted a line of query tangental to G’MIC Scope Fun!, My Light-Dawns-Over-Marblehead realization that, yes Virginia, command scope is indeed a contained environment: Of the parent scope’s context, the command line interpreter sees nothing save what it has been told about: images in the custom command’s selection decorator, if any, and passed arguments, if any. All else from the larger context is opaque to the command line interpreter as it walks down the custom command’s pipeline.

In particular -store. $hidyhole squirrels away the last image on the list, shortening it by one item, but should the next step on the pipeline bring the interpreter to a new custom command, when it enter’s the child’s scope the parent’s $hidyhole is hidden away and any reference to $hidyhole in the child custom command refers to a different (and new) variable in that context. So -input $hidyhole in the child context is not a clever way of sucking in some state from the parent context, but merely tells -input to open a file with an empty string name, and after the host operating system informs -input that no such file exists, it voices alarm by throwing an *** Error *** Unknown filename '' exception, which, in the absence of an -onfail block somewhere in an ancestral scope, pretty much makes all contexts go poof!

In light of selection decorators being a part of G’MIC since the antediluvian version 0, such use of store is neophyte’s work. Want to tell a child command about an image? Cite it in the child’s selection decorator; that’s what selection decorators are for. The command interpreter operating on the child pipeline will do what it will with selected images, including, — maybe! — hiding secret messages!!! in an image! Secret messages for any other command given the image in its selection, so it may also peek inside the carrying image’s guts for strictly confidential, undisclosed bits and blobs meant for the cognoscenti. Ooooooh!

Secret messages. Also known by the far more boring moniker: ‘global state’, that being the sight line along which @garagecoder’s post tangentially brushes G’MIC Scope Fun!. Is there (should there be) a (simple!) means to declare a variable ‘global’ and thereby add a bit to global state, visible to custom commands far and wide — or at least those implementing the secret access decoder ring?

Pythonistas may be pleased to write:

#! /usr/bin/python

HWORLD="Hello world"

def quiet() :
   print("Say {0:s}... in a whisper.".format(HWORLD))

def shout() :
   print("{0:s}!!!!!!!!!".format(HWORLD))

quiet()
shout()

where HWORLD, declared outside of any function definition, is visible to all functions. Slick and easy. And it won’t pass code review in my shop; probably not in yours as well, as many of us pray at the altar of separation of concerns. Global state fosters bugs of the most untraceable kind. By its nature, it is accessible to all, and All should be on their best behavior when they access it, and they are! — except when they aren’t. And with many clients using global state, inevitably someone abuses it, if only inadvertently, and it becomes devilishly complicated to figure out which of the uncounted clients is peeing in the pool. Recall too that the illustration above is childishly simple. In real life, simple global state like “Hello world!” transmogrifies into some ever-growing structure, to which various teams tack their pieces, because nobody wants to tackle the problem of how to pass around state, now that the project has seventy bazillion lines of code — but I digress.

As noted pre-digression, the place for global state in G’MIC is in a “non-image” image — where secret messages may be deposited and retrieved by any number of more-or-less cooperating commands. The antecedents for such antics have been around for a long time, the mathematical expression I[_#ind,k], addressing the kth pixel of image #ind, here linearly arranged in a vector from zero to w*h-1 and which returns an s (spectral) length vector from image #ind, which itself has s channels. On the right hand side of an assignment operator = I[_#ind,k] is a getter from the global storage image; on the left hand side it is a setter to it. This image, in practice, contains global state that any custom command can manipulate through math expressions, which notionally operate with isolated, local-only state. What I[_#ind,k] sets or gets, how the image (data structure) is organized, and how might complexity be managed, is up to the coder(s); G’MIC won’t offer protective insurance.

To this comes the newer da_*() native math functions, reflecting the earlier dar_*() macros from -math_lib in 2.9.9 and prior, coming soon as full-fledged native mathematical functions in 3.0.0; see Math evaluator: Native functions for managing Dynamic Arrays and the original discussion in Post 187 of G’MIC exercises. There is also newish examples in Post 424 of On the road to 3.0. Like their macro predecessors, the da_*() functions constitute access methods to an image and collectively project the illusion of a dynamic array, one that grows or shrinks as data are inserted or pushed, then removed. The first step is to create an image by any of the usual means. A sole 0, creating an Empty suffices: perhaps for discussion it is the first image on the list with a 0 index. Later, perhaps in a math expression in some custom command, a da_*(#0,…) inserts or pushes data-intended-for-global-visibility (née ‘pixels’) into the array; the empty image acquires pixels, but for programmatic purposes, that is a behind-the-scenes incidental. For this discussion, image [0] backing da_*(#0,…) constitutes global state that any custom command can access in a math expression through its own use of the da_*() functions, these referencing the backing store image through its index. The I[#ind,k] augments these, as it may get/set any element (née pixel) of the array, since the array is, in actuality, an image.

Now, perhaps such to-ing and fro-ing may seem finicky compared to the Python exemplar. Since I’m not a fan of global state, I don’t that much miss a slick and easy mechanism to global messes. From a tutorial writing perspective, however, a discussion on global state has many points of intersection with the discussion on scope, to wit: what is, and is not, visible to code at certain points of execution. Since posting G’MIC Scope Fun! I’ve had in mind a “Basic G’MIC Scope” article at the root of the tutorial tree, a peer of introductory topics on Images and Command Decorations. This post constitutes a first draft of that, all arms and legs and awkwardness — a tutorial fragment intended for such a thread as this.

Not sure when the final copy rattles down the ways; my Fair City called all of us civil service folk back into the trenches offices on the September Ides. My commute from Park Slope to the City Hall environs is much shorter than most, but it is still 40 minutes out of the day, to-and-fro, and that’s a bite out of recreational writing time. End-of-year vacation approaches, however. Maybe some time there to catch up.

2 Likes