Friday, May 1, 2015

Class-free object-oriented programming in Javascript

Douglas Crockford has given another talk on the future of Javascript, with particular attention to what he now considers the Right Way to do object-oriented programming, which is quite a departure from classical thought. Years ago, he stopped using new explicitly, and came up with Object.create to use instead, for more straightforward use of Javascript's prototypal inheritance design.

Now, he has also stopped using this, which means he has effectively abandoned Javascript's notion of inheritance altogether. He calls his new style "class-free object-oriented programming", the basic feature of which is that every object actually contains its own methods, rather than sharing them in a prototype or parent object. This is "inefficient" by some measure, but if you think about it, the sharing of methods is simply an optimization, and in most cases, optimizing for space in JS is not going to make a critical difference.

It happens that this was the style I adopted when I got into programming JS, because I was not trained up in classical object-oriented languages. Ironically, more recently, I did get into the typical use of new and prototypes, but I'm going to reconsider that for a while.

Crockford's basic boilerplate for a constructor is:
function constructor(spec) {
  let {member} = spec,
      {other}  = other_constructor(spec),
      method   = function () {
        // accesses member, other, method, spec
      };

  return Object.freeze({
      method,
      other,
  });
}
Which is to say that there is no built-in inheritance; objects that are composed-in are simply member sub-objects. You can, of course, make pass-through member calls.

Danny Fritz blogged about the concept of class-free OO programming, with some helpful illustrative examples, but his techniques differ somewhat from Crockford's, notably in the use of this. Predictably, I have a take that is somewhat different from each of them, but which I think marries their best features.

Crockford uses constructors for everything, which has the code smell of boilerplate in the form of the return Object.freeze portion. Fritz has constructors and extenders, with a copy-in extend function. I have always hated such extenders, and I don't see a reason to have a distinction between constructors and extenders.

Instead, I propose that the proper separation of duties is to have a universal constructor and everything else is an initializer. This gives you freedom to inherit and allows you to avoid the security hazards of this.

The universal constructor looks like this:
Function.prototype.construct = function (spec) {
    var obj = {};
    this(obj, spec);
    return Object.freeze(obj);
}     
Almost too simple to bother with, but it takes care of the boilerplate issue. Note: I formerly had defined this as Object.construct, but this definition makes every function be a potential constructor, which seemed more appropriate.

Now, for any object type (or extension type), all you have to concern yourself with is the initialization. I will illustrate using Fritz's examples of alligator, duck, and goat objects that are defined in terms of extensions Animal, Walking, Swimming, Flying. This is a straightforward port of his alligator:
function alligator (self, spec) {
    self.name = 'alligator';
    self.word = 'grrr';
    animal(self);
    walking(self);
    swimming(self);
}
All of the extensions are just initializers called on the self object (which, being passed in, avoids the security problems of this), and the alligator function is, itself, just an initializer. spec is not used in this case, but I have kept it to show how Crockford's model fits. Most objects do have inputs to their initialization. Similarly, animal et. al. would normally take a second argument.

To create an instance:
var myAlligator = alligator.construct(spec);
It should be clear from this how duck and goat would similarly be created, but let's take a look at the extensions. Again, a straightforward port of animal:
function animal(self) {
    self.name = 'name';
    self.word = 'word';
    self.talk = function () {
        console.log(self.name + ' says ' + self.word);
    }
};
It becomes clear at this point that all the things that inherit from animal have a name and a word. Initialization of those should be done with a spec, rather than having placeholder defaults and each derived object having to know about them:
function animal(self, spec) {
    self.name = spec.name;
    self.word = spec.word;
    self.talk = function () {
        console.log(self.name + ' says ' + self.word);
    }
};
Now we can rewrite alligator:
function alligator (self, spec) {
    animal(self, spec);
    walking(self);
    swimming(self);
}
alligator.construct({name: 'alligator', word: 'grrr'});
So our alligator doesn't merely contain animal, walking, and swimming objects (as would be the case in the Crockford model), but it has been initialized to have those traits directly. This requires that all the traits play nicely with each other. If that can't be guaranteed, Crockford's model offers more security, and can obviously be implemented with pass-through methods like so:
function alligator (self, spec) {
    animal(self, spec);
    var walkTrait = walking.construct();    var swimTrait = swimming.construct();    self.walk = walkTrait.walk;
    self.swim = swimTrait.swim;
}
alligator.construct({name: 'alligator', word: 'grrr'});
Note that I have initialized the alligator self as an animal, then added the other features as traits. Whether you initialize on the object itself or create sub-objects is up to you.

Monday, February 2, 2015

Exploring the smell of Javascript inheritance

In Javascript, objects inherit from other objects. By convention, the objects that are inherited from (prototypes) contain methods, while the inheriting objects contain data. This makes sense, as it is practical to share methods, but each instance must have its own data.
Given that we are interested in (only) the methods of the parent object, it strikes me as something of a code smell that inheritance is done by taking an instance of an object - including, in particular, its data members - to use as a new prototype to which we add functions. It's convenient, it's relatively low cost (what are a few unused variables, for a whole class), but you're still creating things that you will never use. For example, say we have this class:
function Button (label, position) {
  this.label = label;
  this.position = position;
}
Button.prototype = {
  // Button functions
  ...
};
You might derive a new subclass like so:
function RoundButton(size, label, position) {
  Button.call(this, label, position);
  this.size = size;
}
RoundButton.prototype = new Button();
RoundButton.prototype.newMethod = function () {
  // additional functions
  ...
};
You only create the new Button instance so you can inherit from its prototype and add methods to it. The data members don't matter at all to the prototype; you want them in the instance (hence the Button.call).
You could have the Button constructor check to see whether it receives any arguments, and if not, it doesn't create its members. That makes Button responsible for two things: constructing new buttons and constructing new prototypes for derived classes. Another approach would be to separate the prototype responsibility into another class:
function DerivedButton() {}
DerivedButton.prototype = Button.prototype;
Then RoundButton.prototype would be declared:
RoundButton.prototype = new DerivedButton();
Interestingly, because DerivedButton and Button share a prototype, deriving RoundButton from DerivedButton will make RoundButton instanceof Button yield true.
It looks like Object.create was set up to have prototypes inherit through prototypes and not through object instances (as well as to facilitate more traditional object-oriented features).

Tuesday, January 14, 2014

100 Pushups!

It finally happened today. This morning was hurried, since Maria, our housekeeper, was coming, and things were too messy to clean. If you have a housekeeper, you know what I mean. Because of this, I didn't have time to do my usual morning workout, so I decided I'd make it a pushup-test morning.

I felt pretty good, although I had taken about a week off of exercising when we went to Memphis for the Liberty Bowl, and I had definitely lost a bit of capacity in my regular routine. But I'd been back at it for two weeks, and was performing about as well as before.

It's hard to know how many you're going to be able to do, while you're doing them. They don't gradually get harder and harder until you fail, they're easy for most of the time, then they suddenly get challenging, and then you hit the wall and can't make another pushup. I felt good, though, through 50, then 60, then 70. When 80 was still not a problem, I started to think I was going to make it.

About 90 was when I started to feel like I was approaching the end. At 93, I had to pause at the top to take a breath. Up to then, it had been push-push-push, continuous, but the last 7 were individual, locking the elbows at the top each time, the way weightlifters do heavy bench-presses. To my surprise, it wasn't a great struggle to get through the last two. I probably could have done two more, but I was satisfied to make the 100 milestone.

What is my usual morning workout?

Five days a week, I do pushups and either squats or lunges. I use no weights besides my body weight. I alternate days, doing longer sets of pushups followed by stationary lunges, and shorter sets of pushups followed by slalom squats. This routine comprises all the exercise I do, although one of these days I'll get back to swimming.

I alternate the placement of my hands in pushup sets. The first set has them lower, beside my ribcage, the second in the usual shoulder-level position.

Long sets are timed at 1:30 per set; it takes about half the time to do the pushups, and the other half is resting time. I do 50, 50, 40, 40, and whatever I can manage (30-40) for a total of 210 or so.

Short sets start every 1:00. I do 6 sets of 30, plus one set to failure, another 30-40, for (again) a total of 210 or so.

If you don't know what a stationary lunge is, Google can direct you to explanatory videos. My variation is that I do 7 lunges, then "pulse" in the down position for a count of 5, then do 5 more, before switching legs. I do 8 sets of 12 this way with no rest between sets.

Slalom squats are like regular squats, except that instead of coming straight down every time, you shift your center of gravity over each leg. I do center, right, center, left. After each 8th squat, I pulse in the down position for a count of 5. I do 12 sets of 8 with no rest between sets.

Monday, April 8, 2013

The political spectrum


The common way of discussing political views is as a single spectrum running from left to right.  People identify themselves as one or the other or "centrist", and are pretty vague about what it all means.

Some people have tried to make it a bit clearer with a two-dimensional model, but in doing so, they appropriate the terms left and right and redefine them according to their own notions of what's important. I think that's a mistake. Left and Right have useful meanings which are still applicable today.

Leftism is the belief that government should break down social inequality.
Rightism is the belief that government should preserve social hierarchies.

So that's one dimension. If you believe that the government should do some of both, you're a "centrist".

The second dimension is how much control the government should have in shaping society. The less control it has, the less far to the left or right it can be, so the shape of the spectrum is a triangle. At the top is totalitarianism, with right and left very far apart. And at the bottom?

If you do away with all the laws that are aimed at either making things more equal or keeping society from changing, you still have some laws. They are the basic rules of settling differences that arise when people form a society. Libertarians believe that government should be limited to enforcing these laws, and that society should be free to structure itself in whatever ways work best.

Then there's a little tail hanging off the bottom of the triangle. If you do away with even the basic laws of society, you arrive at anarchy, a system without government that somehow still runs in an orderly way. Which, incidentally, was what Karl Marx believed his extreme leftism would lead to. Those who advocate it tend to be smelly hippies, like Karl Marx. Science can't explain that.

Saturday, August 11, 2012

Publishing a Kindle book

Over Thanksgiving 2010, we went to Kansas to visit my family. While there, we went to an auction for an estate. I think it was my grandmother's cousin. There were several boxes of books, and we bought one. They were old novels, in hardback library editions. Swiss Family Robinson was in there, plus a couple of Horatio Alger books, and other, lesser-known things. One was a sort of memoir of childhood in Maine, A Great Year of Our Lives At The Old Squire's Farm, by C. A Stephens. Searching online, we found that most of the books were available from Project Gutenberg, but this particular one was not. Even a couple of other titles in his "Old Squire" series were available, but not this one.
We decided it would be nice if it were available, so I have been taking pictures of the pages, OCR'ing them, and then editing them into shape. I have finished 12 out of the 27 chapters so far. Assuming I get it done this year, I will dub it the "Centennial Edition", since the original publication date was 1912.
Since we have a Kindle, I will be publishing it in Kindle form on Amazon. Almost surely it will be free for a few weeks, to get some people to download it and write reviews that might make someone want to pay 99 cents for it, although I'm not sure I'll change it from free.
I'm not doing it for money; having people pay would just make me feel like there was some value in what I'd done. My primary interest is in being a little part of the vast community of people preserving these old works and making them available to new readers.

Tuesday, July 10, 2012

Killing Zombies

I like the games at Toge Productions, possibly partly because they've got a lot of zombies. In some, you create zombies; in others, you kill them. They made two games called "Days 2 Die", which are nice for being able to play a few minutes at a time. Take a break from whatever, and kill some zombies for a while.

The second of the "Days 2 Die" has a story mode that makes for a good game. It also has a "survival" mode that's more like the first game. I have used walkthroughs for other games, but I haven't seen a walkthrough for survival mode Days 2 Die: The Other Side, so I'm writing one.

I'm not a very good gamer, so if I can do this, pretty much anybody can.

Streets

Day 1

Buy: absolutely nothing in the shop. You have plenty of ammo, and your pea-shooter will do for now.
Barricades: set up two tables, horizontally end-to-end. You're going to stand on top of them, in the middle: move out to the side of one table, press "Start", and jump up on the table top and start shooting, before you even see zombies. Hold down the "E" key the whole time, which will repair your tables as you go. Your objective is to keep the zombies from destroying your tables as long as you can. Shooting them in the head kills them faster.

If they take them out, try to jump over zombies as they approach and keep away from them. Dodging zombies is not what you want to be doing, but you can do some of it in the first few days. After that, they'll kill you more or less instantly. Holding down the "E" key while on top of both tables, and shooting pretty well should leave your tables intact.

Day 2 + 3

Buy: nothing in the shop. If your tables are damaged, you can click the bulldozer in the barricates section and  click the tables to trade them in, then buy new ones. But they should be ok.

Exactly like Day 1, but it will be tougher. You might lose your tables and have to dodge. Good luck. Remember to hold the "E" key.

Day 4

Buy: the Desert Eagle .357 magnum. It's a much better gun. A single head shot is usually enough to kill a zombie. Remember to buy ammo! Get 200 or more rounds for it.
Barricades: Trade in your damaged table(s) and get two fresh ones.

Empty Building

Day 1

Buy: more .357 ammo. You want to have at least 200 rounds.
Barricades: None! There is a trick on this level. At setup time, go all the way to the left, where there is a pile of rubble. Jump onto the pile of rubble. The zombies cannot hit you here. Just make sure you're as far left as you can go, behind the sawhorse.

Stand there and shoot all the zombies. Goodies will pile up amusingly in front of you. It there's a lull in the zombies and you feel lucky, you can jump down to grab them, and jump back up.

Day 2

Just like Day 1, but you probably won't have a lull in the zombies. Save your money so you can buy a nice gun.

Day 3

Buy: the G36C machine gun, and 500 rounds of 5.56 ammo. Fun time! Be sure to equip it as your primary gun, and the .357 as your secondary.

Day 4

Buy: ammo so you have 500 rounds of 5.56. Fire away.

You will now be cleared to advance to the Back Alley, but you don't have to go there yet. You can choose the Empty Building again, and build up your savings. Or you can try going on.

Back Alley

Day 1

Buy: ammo, of course. Also, 3 grenades. Remember to equip the grenades as your Explosive weapon.
Barricades: Buy a stone wall, and place it horizontal, to your left. You're going to be near the extreme right of the play area. The door there does not spawn zombies.

Be sure to stand right up against the wall and keep holding the "E" key down while you shoot. If things get hairy, press "4" to choose your grenade and click to throw it, then choose "1" to go back to your gun. Sometimes grenades can blast zombies up onto your barricade. That's not good! So avoid using them if you can.

Day 2

Buy: restock your ammo and grenades.
Barricades: Two stone walls, horizontal, just like the coffee tables from the Streets. The zombies will get through one, but the second should hold out pretty well. You may find yourself having to dodge near the end.

Day 3

Buy: restock your ammo and grenades, then hire Louis the Merc.
Barricades: Two stone walls, horizontal as before, but leave a space between them where you can stand, but not big enough for Louis to follow.

Position yourself to the right of the barricades. Press Start, then jump onto the right barricade and walk to your space between them. Hold the "E" key down to make your barricade last as long as possible. When the zombies breach it, you'll hop over the second barricade and try to defend it. With Louis helping, you may find that the barricades are a lot easier to defend.

Day 4

Just like Day 3.

If you want to get high scores, at this point, you will re-play Empty Building and/or Back Alley. I don't have any strategies for getting past Burning Building.

While you're accumulating cash, you can buy some neat stuff. I really like the GLM32 High Explosive gun, which is 15000. If there's a horde mobbing your wall, you can clear them out with a couple rounds from this. And the Barret M82 sniper rifle is cool, because it shoots through zombies. You can shoot several at once, which is pretty handy when those axe-throwing zombies appear.

Tuesday, May 22, 2012

The Trayvon Martin Story

There are a limited number of story formulas for movie plots. We need a hero. We need a villain. We need plot twists. If we don't have all that, we're likely to find the movie unsatisfying. Maybe that's why so many people thought a rewrite was in order after the first draft of the Martin-Zimmerman story was submitted.

George Zimmerman's story was that he had been attacked and beaten by someone he was watching as a suspicious character, and that he had shot his attacker in self-defense. Too straightforward. And the villain is a kid. That's not very satisfying. There's got to be a hidden after-school-special to be teased out here.

How about this? "White racist predator hunts and kills black teen. Police assist in cover-up."

Oh, I can smell ratings, baby! That's a narrative that will get an emotional response. Let's run with it. Get some photos of Martin as a smiling little boy, and Zimmerman as a hulking inmate. Push the idea that Zimmerman outweighed Martin by 100 pounds. Mention "Skittles" a lot.

President Obama weighed in, suggesting that what Trayvon looked like is relevant to his status as victim. Good, good.

The storyline hit a small hitch when it turned out Zimmerman wasn't white. No problem, we'll call him a "white Hispanic" and roll with it. The media were on board. They have space to fill and a need to attract attention from the public to get money from advertisers. ABC pushed the notion that George Zimmerman "seemed" uninjured in the police station video. To help that along, they obscured the portion of the video where his head was most clearly visible.

Emotions got ginned up. People got beat up in Trayvon's name. An unrelated Zimmerman family got harrassed thanks to Spike Lee's tweet of their address. The New Black Panther Party called for a race war. And all the people who were wringing their hands over the potential violence of the Tea Party were completely silent.

To help things along further, MSNBC edited both the 911 audio and the associated transcript to make it appear that Zimmerman was racially profiling Martin. Actually, that was so easily exposed, their motivation may have been simply to become more like Fox News rather than to actually push the narrative. Nevertheless, it does suggest what narrative they favored. Those who criticize Fox News for such shenanigans were silent.

The New Black Panther Party helpfully put up "Dead or Alive" bounty posters offering $10,000 for the capture (or, it seems, killing) of a man who hasn't been charged with anything. The Tea Party phobics (including the Department of Justice) found this not at all disturbing.

While public pressure mounted for the Florida special prosecutor to charge Zimmerman, the Martin family's attorney (why do they have an attorney?) expressed their fear of his being a flight risk and asked for increased bail. He was in hiding, after all. It turns out there was no need: the prosecutor quickly came back with a murder 2 charge, and Zimmerman immediately turned himself in. At the press conference, the prosecutor promised that new information would be released about the case, but nothing new seems to have come from there.

More recently, new information did come out. It wasn't particularly helpful to the narrative. On the same day the the coroner announced that the only injuries to Martin were the gunshot wound and lacerations to his knucklesGawker asserted that Martin "was chased, beaten and shot by a self-appointed neighborhood watchman named George Zimmerman," in what was apparently the least successful beating ever. The speculation that Zimmerman initiated contact with Martin is continually asserted as fact despite there being zero evidence of it. Alan Dershowitz says the case has no merit and "The prosecution has already admitted that it has no evidence that Zimmerman started the actual fight."

Meanwhile, Mansfield Frazier wrote in the Daily Beast in favor of appeasing those who threaten violent responses.
"America can only dodge so many racial bullets, and a not-guilty verdict in this case could very easily turn the racial cold war into a very hot one."
He then goes on to argue for Zimmerman's lawyers to go for a plea deal, purely to prevent a violent response. Brilliant! "Justice" by expedience! Don't arrest the people promising violence, just give them what they want. They're not a problem, they're entertaining! Frazier dubs them "The Three Stooges." You don't arrest the Three Stooges! (Note: Ironically, a month later, he argues that the case must go to trial. He takes the opportunity to assert that Zimmerman initiated contact, but "Even if Zimmerman is found not guilty, if those dangerous laws are changed, society will have won a victory."  I guess he evolved.)

Thomas Sowell notes that we're not even reporting on race war activities as they happen. It appears the terrorists really have won, but they aren't the ones we were fighting.

Every bit of evidence says that the police handled this case fine initially. It is possible that some heretofore unknown facts will surface, justifying a murder two conviction, but it sure doesn't look likely. What looks likely to me is an acquittal, followed by violence. And far too many people see the former as the more problematic of the two. That is certainly the position of our Justice Department. Plot twist indeed.