Sunday, 3 April 2022

Emulating the past

“It’s no use going back to who I was yesterday, because I was a different person then”
Lewis Carroll

For so long, now, it's very fashionable to go back to how things were, that retro is almost passé.

It's computing that makes it all possible, of course. Computers today are so powerful that they can emulate older computers even faster than full speed.

Even in my lifetime, new computers became so fast that they weren't slow enough to properly run some of the older programs that they were supposedly compatible with. That's always fun telling the user "It's because your computer is so powerful it crashed the program". It's quite something to watch them dilute their own frustration with a mingling of pride and awe.

My history with computers started as a pre-teenage child when I traded a pair of opera glasses (that I had got from a friend whose dad ran a waste processing business) with a school teacher, to get an old electric school bell. I used to wake up at night from realistic dreams of the electric shocks that I inflicted on myself during the day.

Around the same time, my dad brought a bunch of old Bakelite telephones home from where he worked. I'm not sure what he did with them, but when he'd finished, I knew enough to fix them up with my old train transformer and make some kind of an intercom system (incurably suffused with a 50hz hum loud enough to give you a headache).

It went on from there. What pocket money I didn't spend on sweets I'd spend on the Maplin Electronics catalog and look at all the things I could build, and all the things I could build them with, if only I wouldn't spend all my money on sweets.

And that was the problem. Apart from the odd FM transmitter, I didn't build very much because electronics is an expensive hobby - all those parts to buy. I used to get by filing components from old transistor radio circuit boards before I was given leave to use the antique soldering iron. I still have a scar on my wrist from that!

But one day as I was walking home from school along the main road, that we all traveled, I heard some crazy talk, and that made all the difference.

My brother was talking to a friend about a computer program that he had written at computer club, which made a man walk across the screen, getting lower and lower, and leaving some dots behind him. It sounded fantastic, but yet his ideas intrigued to me.

I don't know what I had been doing instead of going to the computer club, but the very next time I did go to the computer club and asked the computer teacher:

Please write me a program that makes a man walk across the screen getting lower and lower and tell me how it does what it does.

Even now I am as impressed by my ability to synthesize that request as I am of my ability to understand the program.

The program is something like this (Try it on the Beeb Emulator at https://bbc.godbolt.org/):
10 CLS
20 FOR Y=0 T0 25
30 FOR X=0 T0 40
40 PRINT TAB(X,Y) "*";
50 PRINT TAB(X,Y);
60 A$=INKEY$(10)
70 PRINT TAB(X,Y) " ";
80 NEXT X
90 NEXT Y
The teacher explained how it worked but it was pretty obvious. He was a kind and good teacher, so rather than answer my questions all night, he gave me the user programming guide (for those were the days when the users did the programming).


One misspent youth later, including the notable event of being dragged out of the computer room by the invigilator so that I could sit what was left of my french exam, I had written the following computer software:
  1. The school email program (BBC Micro, on the eNet network system)
  2. Decode morse code (including punctuation) (Sinclair ZX81)
  3. Various programming tools (music output, read-data-&-restore) (Sinclair ZX81)
  4. Database (Amstrad CPC6128) where I learned that adults will answer personal questions posed by a child if a computer is used.
  5. 3-player personal computer implementation of electronic game Detective Shoestring originally by Grandstand, which involved a cardboard separator on the screen, and added a helpful detectives dog as the third player. (Amstrad CPC6128)
  6. Much much more, and I also learned the futility of adding "-on-a-computer" to various other specialist tasks of the time. My attempt at scenery design on a BBC micro was doomed.
I think I only paid for 1 computer, my ZX81, and the seller gave me many a sleepless Friday night as he repeatedly forgot to bring it on Saturday each week. Christmas eve excitement was nothing to getting my first computer. My Dad then bought me a portable TV to stop me hogging the one in the front room.

Through kindness and good fortune I was lent/borrowed/given the following: 
  • ZX Spectrum 48K
  • Amstrad CPC6128
  • TRS80 II with dual disk drive
  • 80286 with 2MB RAM and Hercules Graphics Card
  • 397SX16 with 4MB
After which I was able to buy a 386DX40 motherboard and 4MB RAM with Crystal sound card, and a second hand 540MB hard disk for £40

Such glorious memories.

And now -- the computers of the past return in the form of an emulator. All of them. Most of them will even run in a web browser.

I've installed some of them, but mostly I just look and stare in a daze.

What do I want to make it do? 

Nothing. I did it all already. 

I can't go back to my childhood, I'm not a child anymore.

I seek not to follow in my footsteps of old, I attained those things I sought.

Saturday, 2 April 2022

Frozen Lemons

“When life gives you lemons, make lemonade or freeze them and throw them at the people that are making your life difficult”
- Unknown

Blessed children skip along scattering sunshine and petals wherever they go, delighting to bless each life they touch for good.

Other children have never heard of such a thing. Being occupied with weightier matters, they receive their parents' duty and love as a matter of course, and get on with their own obsessive labours while the day yet remains.

My brother and I had mastered all of the necessary arts for young children and made it our labour to engage these daily for our enjoyment and delight. 

We knew the secrets of overlapping lego brings to bring strength to a wall. 

We could put a water pistol to hours of judicious use until the inevitable blister on our trigger finger burst and ripped open, but we could also use a knife to split open a water pistol to extract the pump mechanism to serve as the essential core of a fire engine yet to be built.

We knew the secrets of a beach ball, both to inflate it and deflate it, despite the anti-deflation mechanism.

We could slide down the stairs in our sleeping bags without injury but we could also climb up the green and yellow "beanstalk" blanket which hung from the balustrade above the bottom of the stairs. 

Life was worth living, and we lived it with rarely a thought for those who made it so worthwhile.

One long summer day ended too soon. I don't know if we had been sent to bed early, but if so, we probably deserved it. We might have accepted this, but it wasn't dark, and one of us saw a water pistol. 

Now one brother will not be left unarmed in a water fight, and will use all his ingenuity to overcome the lack of a second water piston. And there never was nor will be a water fight that did not escalate beyond all reason.

The water pistol had not been put to very much use before the soap dish was involved as both a carrier and dispenser of water.  As an efficiency improvement in the art war it is only a minor footnote, and interesting only in relation to the subsequent escalation of which it was the direct cause: the inflatable beach ball.

Your imagination is only faulty in one respect. The inflatable beach ball was not entirely inflated with water.

The inflatable beach ball is a dispenser of water to exceed all in those days before the pump-action super-soaker, but one could suffer a lot of hits in the time it takes to fill. To be well used it doesn't need to hold that much more than the water pistol. And if not fully filled it may also serve as a sort of bowl to hold more water.

This was peak escalation - and there were two beach balls.

From the child's point of view, we were having unpermitted quantities of fun, but the parent would think: "What are they doing up there? They are supposed to be going to sleep!"

Despite all these details being true, I'm not aware that any of the bedding actually got wet.

Our mother, on the other hand, observed that it all needed hanging out on the washing line to dry, and as there was no other bedding to hand we would have to go and play outside in our pyjamas and bare feet! 

See how we like that!

We liked that. 

We rode around the "lawn" on our tricycles in our pyjamas and bare feet, our fun a form of defiance at our supposed punishment.

What to do when your lemons are returned to you, frozen? 
If it's summer, make lovely chilled lemonade.

Thursday, 24 March 2022

Unless you broke a window

“It is usually best to admit mistakes when they occur, and to seek to restore honor”. Unless you just broke a window and a really large gentleman is threatening to beat you up. In that case, run!
- Uncle Iroh

I remember that as a child, it was always important to own up when you did something wrong. It was a good theory, but the practice was not so good.

I never was a big fan of using the toilet as a young child. It was a lot of faff that required breaking off the concentration of whatever I was doing at the time. It was prime for procrastination. Why go to the toilet now when I can go later? So I procrastinated. Why procrastinate tomorrow when I can procrastinate right now!? I procrastinated with vigour, right away, with exceeding great diligence.

But you know how it is. If you procrastinate this sort of thing once, you have to procrastinate it again five minutes later, and then again soon after that. Such procrastination requires increasing and more-intrusive concentration to sustain. A slight lapse of mental effort can be followed by instant regret, and a young child then needs help to clean up the mess.

Even after months of careful practice, a young lad can misjudge when he is no longer going to be able to sustain the necessary concentration.

On one occasion I remembered that my mum had told I should just tell her, and not try to hide it, so I told her.

In return for my frank forthrightness, I received a smack on the bottom. I wasn't impressed and reminded my mum what she told me. I wasn't convinced by her response though I could see the logic: "Well I would have smacked you twice if you hadn't told me!" 

Even the best parents have their off-days.

But the problem with owning up, is that if you don't do it right away, you also get in trouble for not owning up, with the inquisition: "Why didn't you own up?" and you have to own up to that if you can understand why you didn't.

The answer which I can articulate only now but which I knew instinctively then was: because I wanted to avoid the sort of inquisition you are now putting me to.

Yes, if you don't own up right away you are better off sticking to your story, and just don't do whatever it was next time. 

And then there is the time I actually broke the glass, of a picture, of Jesus, praying.

I broke it with a ball. I didn't commit the common-or-garden sin of playing with a ball in the house.

I simply had the ball in my hand. I was cross at something, something so trivial compared with the self-inflicted mental trauma which followed, that I can't remember what it was.

But whatever it was helped me justify expressing my annoyance by striking the picture on the wall with the ball in my hand. There!

And the glass cracked. And I was probably over the age of eight so I wasn't going to get any kind of free pass.

And no amount of pleas or entreaties, or vain promises to never be naughty again for the rest of my life persuaded Heavenly Father to mend the picture. He could do it if he wanted to. I suppose he didn't want to. Didn't he know what a bargain he was missing?

And so it stayed broken. And there I was! Ketched!

I don't think Heavenly Father had any difficulty fixing glass or getting as much glass as he wanted. 

I think what he wanted was for me to learn to trust my parents.

I think the kindest thing my parents did then was to fix the picture without the inquisition.

Friday, 18 March 2022

The chocolate room


“Reality leaves a lot to the imagination.”
― John Lennon

As a young father I wanted to give my young children a real treat, something wondrous and amazing that they would never forget.

One Saturday lunchtime an idea came to mind and  I immediately announced it.

I would take them to the Cholocate Room.

Doubtless inspired by Charlie and the Chocolate Factory (book or movie, I couldn't be sure) it was full of all kinds of chocolate goodies that they could take.

They key was that they should be blindfolded, and I would take them the secret way and they would grab what they could.

And so it was.

They would be blindfolded, I carried them up and down the stairs, turned around, and again until as I imagined they did not know where they were, and then carried them down to the cellar where, while still blindfolded, they could choose whatever they wanted from the selection of chocolate that was , unbeknownst to them, continually held in front of their blindfolded face whichever way they turned.

It was a huge success. All the excitement of a real chocolate room but only needing a small stock of chocolate. All the benefit of having a secret passage in the house leading to somewhere wonderful without having to have the trouble of actually digging a secret passage, or laying out the wonderful place.

Except... I found that the wandering about with a blindfold did not confuse them as to where they were. They were smart kids, and with a sense of direction as well as a sense of the ambience of the rooms.

So what had happened? Did they imagine that they had actually been to an actual chocolate room? Or were they just imagining that they had to play along, for free chocolate?

We never went to the chocolate room again, despite multiple requests.

I want to, I long to, but if they don't actually believe that I can take them to an actual chocolate room, then what am I doing?

Am I running upstairs and downstairs as an excuse to give them free chocolate? 

If they want free chocolate, then they can find it in the cupboard.

I was looking to give them a sense of wonder and amazement. Is that what they thought they were doing for me?

Tuesday, 1 March 2022

monotony and solitude

“The monotony and solitude of a quiet life stimulates the creative mind.”
Albert Einstein

  "I'm bored!" he says.

  "Agghh! Why are you bored? How can you be bored? I was never board!" I think, but it isn't strictly true. When I was bored my mum always had jobs for me to do. So I learned not to be. "When I was a kid, I used to...." what did I used to do?
  "I used to make my own lego movies using a video camera and stop-motion animation."

I think that it was about four frames per second, with jolly street organ music forming the accompaniment to a lego man being run down on a crossing multiple times. Our sense of humour back that was more slapstick than dark, and being run over was the most we had to fear in life.

But we don't have a video camera... and we don't need one! We have a digital camera that takes jpeg images. Some of my misspent time on the computers taught me about the motion-jpeg video codec, so it's going to be pretty easy,

I teach the young complainant the basic principles of stop-motion animation. Keep the camera steady, move only a little bit, and have enough light. They can get a basic view of their work just by flipping through the photo history on the camera.

He sets to work with the camera and his lego pieces while I write a shell script to invoke mplayer and mencoder on a folder full of images. In the end we end up with a short script which processes the images in order based on the image name (which is a 4 digit serial number). 

But it gets tedious (that's a posh word for boredom without me having to resolve the contradiction of being bored during a period of intense creativity) having to copy a title frame ten or twenty times in order to make it show long enough for the audience to read, so we add the feature that the images can be renamed to contain extra data such as the number of frames to be shown for. We also allow symbolic links to a folder of images to allow re-use of some sections.

This is all used to produce a list of images (some repeated) to pass to mencoder to produce the final movie which is then combined with a sound track.

The images to form the movie (along with sub-folders and links) are stuffed into a top level project project folder, and the entire user interface consists of dragging the project folder onto a desktop icon shortcut for the main script, and out pops an image named after the project folder.

And what was the result? The boy was busy, creating animations for fun and entertainment. His younger siblings had their turn. Lego movies for home. Lego movies for talent contents, clay motion movies for course credit at Leeds College of Art, and through that exponential curve of interest so technique improved from a camera held steady against a fluffy carpet, through use of a board, a tripod, additional lighting (to avoid shadows you know), and finally a shutter-release button on the end of a wire to avoid shaking the camera! So far we had come. It was he, of course, but I'm determined to claim some of the credit for I was there at the start, and it was my idea!

Any future cries of boredom (from any of them) were swiftly dealt with by threats of stop motion animation. The work involved in creativity had become apparent. But they all resort to it from time to time, to stave off the boredom.

Monday, 28 February 2022

bottles to make me well

Thank you, kind parents, for giving me bottles to make me well.
Mr Darling in "Peter Pan" by J. M. Barrie

Every parent wishes to raise their child to be capable, independent, and yet still remain appreciative enough to visit once in a while in those declining autumn years, so that every longing look from the window shall not be in vain, and most of those that are will be sufficiently trimmed with happy memories, and with happy anticipations of many more to come.

Are any of us wise or foresightful enough to choose each experience that would develop and improve our natural situation and abilities, while eschewing every experience that would do damage to the same? Few of us are wise enough to even think upon wishing that we were so.

There is time enough for early morning study on every other blessed early morning yet to rise, it is the mornings in bed that are in short supply. Does this homework assignment really matter among so many?

It is not the tomorrows that multiply all those good intentions, for they are all born of the now which says wait and not yet, and so it is the now, in the moment, that the unyielding twig must be unbent for the sake of the tree. There will be other shining moments to improve, says the youth to the parent attempting to incline him towards improving on any of them.

The debate between can't and won't is a narrow distraction and often chosen by a schoolmaster as a more familiar and a less exerting strategy and almost as effective as combining all their wit with honeyed words, which makes only a very small helm by which to steer reluctant pupils. The schoolmaster has been beaten back by a never-ending sea of youths, wave upon wave, year upon year, dashing his castles in the sand, and leaving a pristine shore as they depart to whence they came.

The parent is a specialist craftsman, with a lifetime commitment, and with no end in view so narrow as mere matriculation, which is only one possible stepping stone of many on a carefully consulted route.

When the young lad won't go in and make so many friends for life from a group of strangers his age, what is a father to do? Where reason and determined entreaties may fail, force is futile and will only cultivate immunity against all the more gentle influences in the future.

Complete capitulation can't be countenanced -- who wants the present problem to persist permanently?

Do you know how to make a donkey turn around on a narrow staircase? It's very easy when you know the trick, which I am at liberty to reveal to you at some future time in the form of a song. The refrain is based upon the idea that a donkey will do what a donkey wants to do, and when the donkey wants to do it; and it goes like this: you got to make him want to.

It is a strategy that has often succeeded. Children will often want to do what they should when they realise that everything else is more boring. 

I was once losing influence due to constant brow-beating. My over-used arguments were losing their force. The lad and I were getting fed up, and I was blowed if I was going to carry on like that all night. I needed something to strengthen the relationship, to give a distraction to clear the mind, to give time for everyone to think, while not removing the choice or obligation.

Inspiration spoke, and the solution was to go for a walk up a steep hill in the summer evening, away from the present pressing problem. Time to explore, time to talk - and if about nothing else, then about what we explore, about what we might find next, whether there will be a chip shop, and which road leads back. If the troublesome topic became too touchy, we temporarily talk of trivial things.

It was an activity that would require exertion, rewarded by a quite predictable though somewhat novel experience, and new sights of minor interest.

It was also sure to be just as steep next time, and slightly less interesting.

There were worse ways to spend the evening, and time for one to conclude (who knows?) as dread dissipates in the daylight outdoors, that going in and meeting new people might actually be better than this.

The obligation to overcome the obstacle remains. Any paths that ultimately lead back to this fearsome obstacle would be a blessing, for any steps which did not would need to be retraced.

The parent's duty is to create an environment that reflects this truth: The way out is the way through. 

The boy became the master. Such situations cannot dominate him. Having paid the price, he knows their secret, and one secret more: 

By paying the price, man may know the secret, and overcome.

Wednesday, 24 November 2021

BASH inline functions or macros

Sometimes you want to write bash macros instead of bash functions.

You want to write some bash which can declare local variables in the caller context.

Maybe it parses some data and creates a bunch of hashes with a known prefix (that's as much namespace management as bash gives you) and populates a named list with the names of those hashes.

And then you need to use that twice so you want to factor it into a function. Only you can't these aren't meant to be global variables.

So you have a few solutions, all using source in one way or another

You could put it into a separate file and source it whenever you need it.

You could define it in a string or here document and source it when needed (but you loose bash syntax support in the editor).

You can call the function using command substitution and have it execute declare -p on the variables you want to export.

e.g. source <( my-function args )

Or to enjoy all the side effects directly, you can export the function body using declare -f and strip the first line (which is the function declaration) my masking it with a comment, and then execute the rest directly, using source.

First iteration

Hint: this one is reliable.
function-body() {
echo -n '#'
declare -f "$1"
}

And to invoke it:

source <( function-body my-function ) arg1 arg2 arg3

Example

my-function()
{
echo "my-function $*";
echo a=$1;
a=$1
}
test-my-function() {
local a
source <( function-body my-function ) "$@"
echo "test says a=$a"
}

$ a=nothing ; test-my-function something ; echo "shell says a=$a"
my-function something
a=something
test says a=something
shell says a=nothing

Maybe  source <( function-body my-function ) "$@"  is a bit verbose when calling a function inline every time.

Bugs

The first iteration is fine which makes sense as eval is not used:
$ v='$thing' ; a=nothing ; test-my-function '$v $v' ; echo "shell says a=$a"
my-function $v $v
a=$v $v
test says a=$v $v
shell says a=nothing

Second iteration

Hint: this one is not reliable.
Let's create a function to invoke the function inline. But that's not going to work for the same reason, so let's invoke something that looks like a function. How about this? $inline my-function args

The printf '\x23' is an easy way to avoid # taking effect in the wrong level of the eval context.

declare -- inline="eval eval \"\$_inline\" <<<"
declare -- _inline="source <( read && printf '\x23' && declare -f \$REPLY )"

Example

my-function()
{
echo "my-function $*";
echo a=$1;
a=$1
}
test-my-function() {
local a
$inline my-function args "$@"
echo "test says a=$a"
}
$ a=nothing ; test-my-function something ; echo "shell says a=$a"
my-function something
a=something
test says a=something
shell says a=nothing

Note the double-eval mechanism so that <<< can be used to read the function name on stdin while the remaining arguments are applied to the body as $@ for the lifetime of the body (thanks, bash)

Bugs

The second iteration surprisingly appears to work fine despite the double eval:
$ v='$thing' ; a=nothing ; test-my-function '$v $v' ; echo "shell says a=$a"
my-function $v $v
a=$v $v
test says a=$v $v
shell says a=nothing

but bafflingly, if thing is defined then suddenly a double evaluation is exposed:
$ thing=xxx; v='$thing' ; a=nothing ; test-my-function '$v $v' ; echo "shell says a=$a"
my-function xxx xxx
a=xxx
test says a=xxx
shell says a=nothing
how was '$v' preserved when thing wasn't defined?

Third Iteration

Hint: this one is not reliable.
It's a shame that a fork has to be incurred each time for the command substitution to generate the code to be sourced from the function body.

Maybe, rather than $inline my-function ... we could do $my-function except that variable naming has stricter rules than function naming.

But still, that's a minor inconvenience

We can extract the function body using the current technique and assign that to a variable to be sourced, and declare another variable as syntactic sugar to source it.

It gets a little more awkward trying to find a file descriptor or device name from which to source the function without blatantly destroying stdin (which to be fair, we may be doing in the other examples -- it needs testing), so skipping that for now:

make-macro() {
declare -g "_$1" "$1"
{ read -r ; IFS="" read -d '' -r _$1 ; } < <( declare -f "$2" )
printf -v "$1" 'eval source /dev/stdin <<<"$_my_function"'
}

Example

my-function()
{
echo "my-function $*";
echo a=$1;
a=$1
}
test-my-function() {
local a
$my_function "$@"
echo "test says a=$a"
}

$ make-macro my_function my-function
$ a=nothing ; test-my-function something ; echo "shell says a=$a"
my-function something
a=something
tast says a=something
shell says a=nothing

Bugs

Third iteration has arguments subject to one extra evaluation:
$ v='$thing' ; a=nothing ; test-my-function '$v $v' ; echo "shell says a=$a"
my-function $thing $thing
a=$thing
test says a=$thing
shell says a=nothing

To prevent argument evaluation, source must be invoked first, and any eval done within what is sourced.

Bugs

We aren't being careful to make sure we don't destroy stdin. Maybe the function needs stdin. 

Writing hygenic macros is hard and using eval right is harder. The arguments are subject to a varying amount of eval evaluation.

eval had been required so that <<< could be used to paste a here-string and there is no way around that using source from a string with a command defined in a variable, as <<< is not part of a command list

we could work around this by sourcing from an actual file instead of a here doc.

Fourth Iteration

Hint: this one is reliable.
We can avoid here-strings and here-docs and the associated redirections without the need for a file to source, by declaring a temporary file as a here doc, like this:

exec {_source_}<<<'source /dev/stdin <<<"${!1}" "${@:2}"'

Now we can refer to that here-string as /dev/fd/${_source_} and read it as often as we like
source /dev/fd/${_source_} f '$v $v'
my-function $v $v
a=$v $v

So the fuller solution based on the third iteration is
make-macro() {
declare -g _macro_
test -z "$_macro_" && exec {_macro_}<<<'source /dev/stdin <<<"${!1}" "${@:2}"'
declare -g "_$1" "$1"
{ read -r ; IFS="" read -d '' -r _$1 ; } < <( declare -f "$2" )
printf -v "$1" 'source /dev/fd/%d %s' "${_macro_}" "_$1"
}

Example

my-function()
{
echo "my-function $*";
echo a=$1;
a=$1
}
test-my-function() {
local a
$my_function "$@"
echo "test says a=$a"
}

make-macro my_function my-function
thing=xxx ; v='$thing' ; a=nothing ; test-my-function '$v $v' ; echo "shell says a=$a"
my-function $v $v
a=$v $v
test says a=$v $v
shell says a=nothing

And that's enough nastyness for one day