Tags: ror

54

sparkline

Sunday, August 4th, 2019

The Flawed Reasoning Behind the Replication Crisis — Nautilus

Bayesian analysis vs. statistical significance, clearly explained.

Tuesday, July 2nd, 2019

The trimCache function in Going Offline …again

It seems that some code that I wrote in Going Offline is haunted. It’s the trimCache function.

First, there was the issue of a typo. Or maybe it’s more of a brainfart than a typo, but either way, there’s a mistake in the syntax that was published in the book.

Now it turns out that there’s also a problem with my logic.

To recap, this is a function that takes two arguments: the name of a cache, and the maximum number of items that cache should hold.

function trimCache(cacheName, maxItems) {

First, we open up the cache:

caches.open(cacheName)
.then( cache => {

Then, we get the items (keys) in that cache:

cache.keys()
.then(keys => {

Now we compare the number of items (keys.length) to the maximum number of items allowed:

if (keys.length > maxItems) {

If there are too many items, delete the first item in the cache—that should be the oldest item:

cache.delete(keys[0])

And then run the function again:

.then(
    trimCache(cacheName, maxItems)
);

A-ha! See the problem?

Neither did I.

It turns out that, even though I’m using then, the function will be invoked immediately, instead of waiting until the first item has been deleted.

Trys helped me understand what was going on by making a useful analogy. You know when you use setTimeout, you can’t put a function—complete with parentheses—as the first argument?

window.setTimeout(doSomething(someValue), 1000);

In that example, doSomething(someValue) will be invoked immediately—not after 1000 milliseconds. Instead, you need to create an anonymous function like this:

window.setTimeout( function() {
    doSomething(someValue)
}, 1000);

Well, it’s the same in my trimCache function. Instead of this:

cache.delete(keys[0])
.then(
    trimCache(cacheName, maxItems)
);

I need to do this:

cache.delete(keys[0])
.then( function() {
    trimCache(cacheName, maxItems)
});

Or, if you prefer the more modern arrow function syntax:

cache.delete(keys[0])
.then( () => {
    trimCache(cacheName, maxItems)
});

Either way, I have to wrap the recursive function call in an anonymous function.

Here’s a gist with the updated trimCache function.

What’s annoying is that this mistake wasn’t throwing an error. Instead, it was causing a performance problem. I’m using this pattern right here on my own site, and whenever my cache of pages or images gets too big, the trimCaches function would get called …and then wouldn’t stop running.

I’m very glad that—witht the help of Trys at last week’s Homebrew Website Club Brighton—I was finally able to get to the bottom of this. If you’re using the trimCache function in your service worker, please update the code accordingly.

Management regrets the error.

Tuesday, April 2nd, 2019

Idiosyncrancies of the HTML parser - The HTML Parser Book

This might just be the most nerdily specific book I’ve read and enjoyed. Even if you’re not planning to build a web browser any time soon, it’s kind of fascinating to see how HTML is parsed—and how much of an achievement the HTML spec is, for specifying consistent error-handling, if nothing else.

The last few chapters are still in progress, but you can read the whole thing online or buy an ePub version.

Thursday, February 21st, 2019

Mirrorworld

Over on the Failed Architecture site, there’s a piece about Kevin Lynch’s 1960 book The Image Of The City. It’s kind of fun to look back at a work like that, from today’s vantage point of ubiquitous GPS and smartphones with maps that bestow God-like wayfinding. How much did Lynch—or any other futurist from the past—get right about our present?

Quite a bit, as it turns out.

Lynch invented the term ‘imageability’ to describe the degree to which the urban environment can be perceived as a clear and coherent mental image. Reshaping the city is one way to increase imageability. But what if the cognitive map were complemented by some external device? Lynch proposed that this too could strengthen the mental image and effectively support navigation.

Past visions of the future can be a lot of fun. Matt Novak’s Paleofuture blog is testament to that. Present visions of the future are rarely as enjoyable. But every so often, one comes along…

Kevin Kelly has a new piece in Wired magazine about Augmented Reality. He suggests we don’t call it AR. Sounds good to me. Instead, he proposes we use David Gelernter’s term “the mirrorworld”.

I like it! I feel like the term won’t age well, but that’s not the point. The term “cyberspace” hasn’t aged well either—it sounds positively retro now—but Gibson’s term served its purpose in prompting discussing and spurring excitement. I feel like Kelly’s “mirrorworld” could do the same.

Incidentally, the mirrorworld has already made an appearance in the William Gibson book Spook Country in the form of locative art:

Locative art, a melding of global positioning technology to virtual reality, is the new wrinkle in Gibson’s matrix. One locative artist, for example, plants a virtual image of F. Scott Fitzgerald dying at the very spot where, in fact, he had his Hollywood heart attack, and does the same for River Phoenix and his fatal overdose.

Yup, that sounds like the mirrorworld:

Time is a dimension in the mirror­world that can be adjusted. Unlike the real world, but very much like the world of software apps, you will be able to scroll back.

Now look, normally I’m wary to the point of cynicism when it comes to breathless evocations of fantastical futures extropolated from a barely functioning technology of today, but damn, if Kevin Kelly’s enthusiasm isn’t infectious! He invokes Borges. He acknowledges the challenges. But mostly he pumps up the excitement by baldly stating possible outcomes as though they are inevitabilities:

We will hyperlink objects into a network of the physical, just as the web hyperlinked words, producing marvelous benefits and new products.

When he really gets going, we enter into some next-level science-fictional domains:

The mirrorworld will be a world governed by light rays zipping around, coming into cameras, leaving displays, entering eyes, a never-­ending stream of photons painting forms that we walk through and visible ghosts that we touch. The laws of light will govern what is possible.

And then we get sentences like this:

History will be a verb.

I kind of love it. I mean, I’m sure we’ll look back on it one day and laugh, shaking our heads at its naivety, but for right now, it’s kind of refreshing to read something so unabashedly hopeful and so wildly optimistic.

Tuesday, August 7th, 2018

Console methods

Whenever I create a fetch event inside a service worker, my code roughly follows the same pattern. There’s a then clause which gets executed if the fetch is successful, and a catch clause in case anything goes wrong:

fetch( request)
.then( fetchResponse => {
    // Yay! It worked.
})
.catch( fetchError => {
    // Boo! It failed.
});

In my book—Going Offline—I’m at pains to point out that those arguments being passed into each clause are yours to name. In this example I’ve called them fetchResponse and fetchError but you can call them anything you want.

I always do something with the fetchResponse inside the then clause—either I want to return the response or put it in a cache.

But I rarely do anything with fetchError. Because of that, I’ve sometimes made the mistake of leaving it out completely:

fetch( request)
.then( fetchResponse => {
    // Yay! It worked.
})
.catch( () => {
    // Boo! It failed.
});

Don’t do that. I think there’s some talk of making the error argument optional, but for now, some browsers will get upset if it’s not there.

So always include that argument, whether you call it fetchError or anything else. And seeing as it’s an error, this might be a legitimate case for outputing it to the browser’s console, even in production code.

And yes, you can output to the console from a service worker. Even though a service worker can’t access anything relating to the document object, you can still make use of window.console, known to its friends as console for short.

My muscle memory when it comes to sending something to the console is to use console.log:

fetch( request)
.then( fetchResponse => {
    return fetchResponse;
})
.catch( fetchError => {
    console.log(fetchError);
});

But in this case, the console.error method is more appropriate:

fetch( request)
.then( fetchResponse => {
    return fetchResponse;
})
.catch( fetchError => {
    console.error(fetchError);
});

Now when there’s a connectivity problem, anyone with a console window open will see the error displayed bold and red.

If that seems a bit strident to you, there’s always console.warn which will still make the output stand out, but without being quite so alarmist:

fetch( request)
.then( fetchResponse => {
    return fetchResponse;
})
.catch( fetchError => {
    console.warn(fetchError);
});

That said, in this case, console.error feels like the right choice. After all, it is technically an error.

Thursday, July 5th, 2018

The trimCache function in Going Offline

Paul Yabsley wrote to let me know about an error in Going Offline. It’s rather embarrassing because it’s code that I’m using in the service worker for adactio.com but for some reason I messed it up in the book.

It’s the trimCache function in Chapter 7: Tidying Up. That’s the reusable piece of code that recursively reduces the number of items in a specified cache (cacheName) to a specified amount (maxItems). On page 95 and 96 I describe the process of creating the function which, in the book, ends up like this:

 function trimCache(cacheName, maxItems) {
   cacheName.open( cache => {
     cache.keys()
     .then( items => {
       if (items.length > maxItems) {
         cache.delete(items[0])
         .then(
           trimCache(cacheName, maxItems)
         ); // end delete then
       } // end if
     }); // end keys then
   }); // end open
 } // end function

See the problem? It’s right there at the start when I try to open the cache like this:

cacheName.open( cache => {

That won’t work. The open method only works on the caches object—I should be passing the name of the cache into the caches.open method. So the code should look like this:

caches.open( cacheName )
.then( cache => {

Everything else remains the same. The corrected trimCache function is here:

function trimCache(cacheName, maxItems) {
  caches.open(cacheName)
  .then( cache => {
    cache.keys()
    .then(items => {
      if (items.length > maxItems) {
        cache.delete(items[0])
        .then(
          trimCache(cacheName, maxItems)
        ); // end delete then
      } // end if
    }); // end keys then
  }); // end open then
} // end function

Sorry about that! I must’ve had some kind of brainfart when I was writing (and describing) that one line of code.

You may want to deface your copy of Going Offline by taking a pen to that code example. Normally I consider the practice of writing in books to be barbarism, but in this case …go for it.

Update: There was another error in the code for trimCache! Here’s the fix.

Friday, April 6th, 2018

‘Black Mirror’ meets HGTV, and a new genre, home design horror, is born - Curbed

There was a time, circa 2009, when no home design story could do without a reference to Mad Men. There is a time, circa 2018, when no personal tech story should do without a Black Mirror reference.

Black Mirror Home. It’s all fun and games until the screaming starts.

When these products go haywire—as they inevitably do—the Black Mirror tweets won’t seem so funny, just as Mad Men curdled, eventually, from ha-ha how far we’ve come to, oh-no we haven’t come far enough.

Thursday, April 5th, 2018

Turning a MacBook into a Touchscreen with $1 of Hardware · cat /var/log/life

Well now, this is a clever bit of hardware hacking.

Surfaces viewed from an angle tend to look shiny, and you can tell if a finger is touching the surface by checking if it’s touching its own reflection.

Wednesday, March 7th, 2018

Frequently Asked Questions [CSS Working Group Wiki]

Rebuttals to the most oft-asked requests for browsers to change the way they handle CSS.

Thursday, December 28th, 2017

Rated zero. — Ethan Marcotte

Ethan points out the tension between net neutrality and AMP:

The more I’ve thought about it, I think there’s a strong, clear line between ISPs choosing specific kinds of content to prioritize, and projects like Google’s Accelerated Mobile Project. And apparently, so does the FCC chair: companies like Google, Facebook, or Apple are choosing which URLs get delivered as quickly as possible. But rather than subsidizing that access through paid sponsorships, these companies are prioritizing pages republished through their proprietary channels, using their proprietary document formats.

Tuesday, November 28th, 2017

Nosediving

Nosedive is the first episode of season three of Black Mirror.

It’s fairly light-hearted by the standards of Black Mirror, but all the more chilling for that. It depicts a dysutopia where people rate one another for points that unlock preferential treatment. It’s like a twisted version of the whuffie from Cory Doctorow’s Down And Out In The Magic Kingdom. Cory himself points out that reputation economies are a terrible idea.

Nosedive has become a handy shortcut for pointing to the dangers of social media (in the same way that Minority Report was a handy shortcut for gestural interfaces and Her is a handy shortcut for voice interfaces).

“Social media is bad, m’kay?” is an understandable but, I think, fairly shallow reading of Nosedive. The problem isn’t with the apps, it’s with the system. A world in which we desperately need to keep our score up if we want to have any hope of advancing? That’s a nightmare scenario.

The thing is …that system exists today. Credit scores are literally a means of applying a numeric value to human beings.

Nosedive depicts a world where your score determines which seats you get in a restaurant, or which model of car you can rent. Meanwhile, in our world, your score determines whether or not you can get a mortgage.

Nosedive depicts a world in which you know your own score. Meanwhile, in our world, good luck with that:

It is very difficult for a consumer to know in advance whether they have a high enough credit score to be accepted for credit with a given lender. This situation is due to the complexity and structure of credit scoring, which differs from one lender to another.

Lenders need not reveal their credit score head, nor need they reveal the minimum credit score required for the applicant to be accepted. Owing only to this lack of information to the consumer, it is impossible for him or her to know in advance if they will pass a lender’s credit scoring requirements.

Black Mirror has a good track record of exposing what’s unsavoury about our current time and place. On the surface, Nosedive seems to be an exposé on the dangers of going to far with the presentation of self in everyday life. Scratch a little deeper though, and it reveals an even more uncomfortable truth: that we’re living in a world driven by systems even worse than what’s depicted in this dystopia.

How about this for a nightmare scenario:

Two years ago Douglas Rushkoff had an unpleasant encounter outside his Brooklyn home. Taking out the rubbish on Christmas Eve, he was mugged — held at knife-point by an assailant who took his money, his phone and his bank cards. Shaken, he went back indoors and sent an email to his local residents’ group to warn them about what had happened.

“I got two emails back within the hour,” he says. “Not from people asking if I was OK, but complaining that I’d posted the exact spot where the mugging had taken place — because it might adversely affect their property values.”

Monday, November 20th, 2017

Happier HTML5 Form Validation - daverupert.com

Dave uses just a smidgen of JavaScript to whip HTML5’s native form validation into shape.

Instead of being prescriptive about error messaging, we use what the browser natively gives us.

Tuesday, October 3rd, 2017

Robtober 2017 | Rob Weychert

What an excellent example of a responsive calendar!

Sunday, June 4th, 2017

Aurora

I remember when I was first recommended to read Kim Stanley Robinson. I was chatting with Jon Tan about science fiction, and I was bemoaning the fact that dystopias seem to be the default setting. Asking "what’s the worst that could happen?" is the over-riding pre-occupation of most sci-fi. Black Mirror is the perfect example of this. Mind you, that’s probably why the ambiguous San Junipero is one of my favourites—utopia? dystopia? dystutopia? You decide.

Anyway, Jon told me I should check out Kim Stanley Robinson’s Three Californias; one book describes a dystopia, one book describes a utopia, and the other—his debut, The Wild Shore—is more ambiguous. I liked the sound of that, but I decided that if I were going to read Kim Stanley Robinson, I should start with his most famous work, the Mars trilogy.

So I read Red Mars. I liked it, but I found it tough going. It’s not exactly a light read. I still haven’t read Green Mars or Blue Mars, though I plan to. I can see why Red Mars is regarded as a classic of hard sci-fi, but it left me somewhat cold. Jessica read The Years of Rice and Salt and had a similar reaction—good premise, thoroughly researched, but tough going.

When I heard about 2312, I couldn’t resist its promise of a jaunt around the solar system. Again, I enjoyed it, but the plot—such as it was—didn’t grab me. I loved the ideas presented in the book. Heck, it inspired one of my Science Hack Day projects. Still, I found that its literary conceit wasn’t enough to carry the book—a character from Saturn who’s saturnian in nature meets a character from Mercury who’s mercurial in nature.

So I was kind of bracing myself for Aurora. Again, the subject matter really appealed to me. I’m a sucker for generation starships. Brian Aldiss’s Non-Stop was a fun read, although in typical Aldiss style, it was weird to the point of psychedelia (even if it looks positively tame next to the batshit crazy world of Hothouse). I was looking forward to reading Robinson’s hard science take on the space ark idea, but I was worried about how much of a slog the writing might be. I read some reviews and listened to some podcasts, and my heart sank when I heard about how the story is partly told by the ship’s AI, who is simultaneously trying to work out how to tell a story. It sounded just like one of those ideas that would be fine for a brief period, but which I could imagine Kim Stanley Robinson dragging out for hundreds of page.

Imagine my surprise when Aurora turned out to be an absolute pleasure. Not only does it have the thoroughly-researched hard science angle of Robinson’s other books, it’s also a rip-roaring tale, in my opinion. I had read of misgivings with the structure of the book—complaints that the story climaxes before the book is halfway done—but I think that misses the point of the story. This is not your typical tale of colonisation. Far from it. Kim Stanley Robinson is quite open about the underlying idea here, that there are certain endeavours that are simply beyond our capacity.

I know that sounds like a very pessimistic view, but I found the book to be a real testament to human ingenuity. But it certainly ruffled quite a few feathers. Like I said, the default setting for most sci-fi is to go negative, but for a sci-fi writer to claim outright that something cannot be done is audacious, and flies in the face of sci-fi tradition.

Gregory Benford wrote a review over on one of my favourite blogs, Centauri Dreams. He takes Robinson to task for stacking the deck against the crew of the ship in Aurora—an inversion of the usual deus ex machina plot devices. I find that criticism puzzling when another review, also on Centauri Dreams, by Stephen Baxter, James Benford and Joseph Miller, takes the book to task for being scientifically naïve.

For me, Aurora was perfectly balanced. It simultaneously captured the wonder of scientific exploration and our own insignificance in the universe. Best of all, it featured central characters that I was utterly invested in—one human, and one artificial. Given my previous experiences with Kim Stanley Robinson books, that was perhaps its greatest achievement. Whereas I might have previously recommended something like 2312, I would have certainly caveated the recommendation. But I wholeheartedly recommend Aurora. It’s easily the best Kim Stanley Robinson book I’ve read so far, and one of the finest science fiction books of recent years. It makes a great companion piece to Neal Stephenson’s Seveneves—not only are they both dealing with space arks, they’ve also got some in-depth descriptions of angular momentum in action, and they’re both thoroughly enjoyable stories that stretch beyond a single human lifespan.

I’m looking forward to digging back through Kim Stanley Robinson’s back catalogue, and I’m very intrigued by his newest book, New York 2140. From listening to his Long Now talk at The Interval, it sounds like the book has as much to say about near-future economics as it does about climate change.

It’s ironic though. Kim Stanley Robinson was first recommended to me because he was one of the few sci-fi writers unafraid to depict a utopia. But his writing never clicked with me until I read Aurora, whose central message sounds like the ultimate downer …that some scientific achievements will forever remain out of reach for humanity.

Wednesday, November 16th, 2016

Usability Testing of Inline Form Validation: 40% Don’t Have It, 20% Get It Wrong - Articles - Baymard Institute

I saw Christian speak on this topic at Smashing Conference in Barcelona. Here, he takes a long hard look at some of the little things that sites get wrong when doing validating forms on the fly. It’s all good sensible stuff, although it sounds a bit medical when he takes about “Premature Inline Validation.”

Tuesday, November 1st, 2016

What’s wrong with big data? | New Humanist

The view that more information uncritically produces better decisions is visibly at odds with our contemporary situation.

A superb piece of research and writing by James, skewering the technological determinism that underlies the current faith in “big data.” At best, this misplaced trust is inaccurate; at worst, it is deadly.

To the algorithmic imagination, the practice of journalism and the practice of terrorism appear to be functionally identical.

Wednesday, March 9th, 2016

Styling Broken Images

This is really, really clever. You can’t use generated content (:before and :after) on replaced content. The img element is replaced content …but only when the image actually loads. So if the image fails to load, you can apply specific fallback styles (using :before and :after).

Sunday, January 3rd, 2016

Simple inline error message pattern

This is my go-to method for adding validation messages to forms—I think I first heard about it from Derek—so it’s nice to see it corroborated by Steve:

Add the error message as a child of the label element associated with an input.

Sunday, November 29th, 2015

Our Generation Ships Will Sink / Boing Boing

Kim Stanley Robinson pours cold water on the premise of generation starships for crewed interstellar travel.

The more I hear about Aurora, the more I think I might enjoy reading it.

Sunday, April 12th, 2015

Sound Mirrors

Before there was radar, there were acoustic mirrors along the coast of England—parabolic structures designed to funnel the distant sound of approaching aircraft.