Shared posts

30 Jun 03:23

Rock

It traveled so far to reach me. I owed it my best.
01 May 20:02

Saturday Morning Breakfast Cereal - Jesus

by tech@thehiveworks.com


Click here to go see the bonus panel!

Hovertext:
AND THEN HE ROSE FROM THE DEAD? I CAN BARELY GET OUT OF BED FOR WORK.

New comic!
Today's News:

Let it never be said that SMBC was especially motivational.

14 Feb 01:44

Fusion Breakthrough (revised)

19 Dec 20:33

Casting vs "as" - embracing exceptions

by skeet

(I've ended up commenting on this issue on Stack Overflow quite a few times, so I figured it would be worth writing a blog post to refer to in the future.)

There are lots of ways of converting values from one type to another – either changing the compile-time type but actually keeping the value the same, or actually changing the value (for example converting int to double). This post will not go into all of those - it would be enormous - just two of them, in one specific situation.

The situation we're interested in here is where you have an expression (typically a variable) of one reference type, and you want an expression with a different compile-time type, without changing the actual value. You just want a different "view" on a reference. The two options we'll look at are casting and using the "as" operator. So for example:

object x = "foo"; 
string cast = (string) x; 
string asOperator = x as string;

The major differences between these are pretty well-understood:

  • Casting is also used for other conversions (e.g. between value types); "as" is only valid for reference type expressions (although the target type can be a nullable value type)
  • Casting can invoke user-defined conversions (if they're applicable at compile-time); "as" only ever performs a reference conversion
  • If the actual value of the expression is a non-null reference to an incompatible type, casting will throw an InvalidCastException whereas the "as" operator will result in a null value instead

The last point is the one I'm interested in for this post, because it's a highly visible symptom of many developers' allergic reaction to exceptions. Let's look at a few examples.

Use case 1: Unconditional dereferencing

First, let's suppose we have a number of buttons all with the same event handler attached to them. The event handler should just change the text of the button to "Clicked". There are two simple approaches to this:

void HandleUsingCast(object sender, EventArgs e) 

    Button button = (Button) sender; 
    button.Text = "Clicked"; 
}

void HandleUsingAs(object sender, EventArgs e) 

    Button button = sender as Button; 
    button.Text = "Clicked"; 
}

(Obviously these aren't the method names I'd use in real code - but they're handy for differentiating between the two approaches within this post.)

In both cases, when the value of "sender" genuinely refers to a Button instance, the code will function correctly. Likewise when the value of "sender" is null, both will fail with a NullReferenceException on the second line. However, when the value of "sender" is a reference to an instance which isn't compatible with Button, the two behave differently:

  • HandleUsingCast will fail on the first line, throwing a InvalidCastException which includes information about the actual type of the object
  • HandleUsingAs will fail on the second line with a NullReferenceException

Which of these is the more useful behaviour? It seems pretty unambiguous to me that the HandleUsingCast option provides significantly more information, but still I see the code from HandleUsingAs in examples on Stack Overflow... sometimes with the rationale of "I prefer to use as instead of a cast to avoid exceptions." There's going to be an exception anyway, so there's really no good reason to use "as" here.

Use case 2: Silently ignoring invalid input

Sometimes a slight change is proposed to the above code, checking for the result of the "as" operator not being null:

void HandleUsingAs(object sender, EventArgs e) 

    Button button = sender as Button; 
    if (button != null) 
    { 
        button.Text = "Clicked"; 
    } 
}

Now we really don't have an exception. We can do this with the cast as well, using the "is" operator:

void HandleUsingCast(object sender, EventArgs e) 

    if (sender is Button) 
    { 
        Button button = (Button) sender; 
        button.Text = "Clicked"; 
    } 
}

These two methods now behave the same way, but here I genuinely prefer the "as" approach. Aside from anything else, it's only performing a single execution-time type check, rather than checking once with "is" and then once again with the cast. There are potential performance implications here, but in most cases they'd be insignificant - it's the principle of the thing that really bothers me. Indeed, this is basically the situation that the "as" operator was designed for. But is it an appropriate design to start with?

In this particular case, it's very unlikely that we'll have a non-Button sender unless there's been a coding error somewhere. For example, it's unlikely that bad user input or network resource issues would lead to entering this method with a sender of (say) a TextBox. So do you really want to silently ignore the problem? My personal view is that the response to a detected coding error should almost always be an exception which either goes completely uncaught or which is caught at some "top level", abandoning the current operation as cleanly as possible. (For example, in a client application it may well be appropriate to terminate the app; in a web application we wouldn't want to terminate the server process, but we'd want to abort the processing of the problematic request.) Fundamentally, the world is not in a state which we've really considered: continuing regardless could easily make things worse, potentially losing or corrupting data.

If you are going to ignore a requested operation involving an unexpected type, at least clearly log it - and then ensure that any such logs are monitored appropriately:

void HandleUsingAs(object sender, EventArgs e) 

    Button button = sender as Button; 
    if (button != null) 
    { 
        button.Text = "Clicked"; 
    } 
    else 
    { 
        // Log an error, potentially differentiating between
        // a null sender and input of a non-Button sender.
    } 
}

Use case 3: consciously handling input of an unhelpful type

Despite the general thrust of the previous use case, there certainly are cases where it makes perfect sense to use "as" to handle input of a type other than the one you're really hoping for. The simplest example of this is probably equality testing:

public sealed class Foo : IEquatable<Foo> 

    // Fields, of course

    public override bool Equals(object obj) 
    { 
        return Equals(obj as Foo); 
    } 

    public bool Equals(Foo other) 
    { 
        // Note: use ReferenceEquals if you overload the == operator
        if (other == null) 
        { 
            return false; 
        } 
        // Now compare the fields of this and other for equality appropriately.
    } 

    // GetHashCode etc
}

(I've deliberately sealed Foo to avoid having to worry about equality between subclasses.)

Here we know that we really do want to deal with both null and "non-null, non-Foo" references in the same way from Equals(object) - we want to return false. The simplest way of handling that is to delegate to the Equals(Foo) method which needs to handle nullity but doesn't need to worry about non-Foo reference.

We're knowingly anticipating the possibility of Equals(object) being called with a non-Foo reference. The documentation for the method explicitly states what we're meant to do; this does not necessarily indicate a programming error. We could implement Equals with a cast, of course:

public override bool Equals(object obj) 

    return obj is Foo && Equals((Foo) obj); 
}

... but I dislike that for the same reasons as I disliked the cast in use case 2.

Use case 4: deferring or delegating the decision

This is the case where we pass the converted value on to another method or constructor, which is likely to store the value for later use. For example:

public Person CreatePersonWithCast(object firstName, object lastName) 

    return new Person((string) firstName, (string) lastName); 
}

public Person CreatePersonWithAs(object firstName, object lastName) 

    return new Person(firstName as string, lastName as string); 
}

In some ways use case 3 was a special case of this, where we knew what the Equals(Foo) method would do with a null reference. In general, however, there can be a significant delay between the conversion and some definite impact. It may be valid to use null for one or both arguments to the Person constructor - but is that really what you want to achieve? Is some later piece of code going to assume they're non-null?

If the constructor is going to validate its parameters and check they're non-null, we're essentially back to use case 1, just with ArgumentNullException replacing NullReferenceException: again, it's cleaner to use the cast and end up with InvalidCastException before we have the chance for anything else to go wrong.

In the worst scenario, it's really not expected that the caller will pass null arguments to the Person constructor, but due to sloppy validation the Person is constructed with no errors. The code may then proceed to do any number of things (some of them irreversible) before the problem is spotted. In this case, there may be lasting data loss or corruption and if an exception is eventually thrown, it may be very hard to trace the problem to the original CreatePersonWithAs parameter value not being a string reference.

Use case 5: taking advantage of "optional" functionality

This was suggested by Stephen Cleary in comments, and is an interesting reversal of use case 3. The idea is basically that if you know an input implements a particular interface, you can take a different - usually optimized - route to implement your desired behaviour. LINQ to Objects does this a lot, taking advantage of the fact that while IEnumerable<T> itself doesn't provide much functionality, many collections implement other interfaces such as ICollection<T>. So the implementation of Count() might include something like this:

ICollection<T> collection = source as ICollection<T>;
if (collection != null)
{
    return collection.Count;
}
// Otherwise do it the long way (GetEnumerator / MoveNext)

Again, I'm fine with using "as" here.

Conclusion

I have nothing against the "as" operator, when used carefully. What I dislike is the assumption that it's "safer" than a cast, simply because in error cases it doesn't throw an exception. That's more dangerous behaviour, as it allows problems to propagate. In short: whenever you have a reference conversion, consider the possibility that it might fail. What sort of situation might cause that to occur, and how to you want to proceed?

  • If everything about the system design reassures you that it really can't fail, then use a cast: if it turns out that your understanding of the system is wrong, then throwing an exception is usually preferable to proceeding in a context you didn't anticipate. Bear in mind that a null reference can be successfully cast to any nullable type, so a cast can never replace a null check.
  • If it's expected that you really might receive a reference of the "wrong" type, then think how you want to handle it. Use the "as" operator and then test whether the result was null. Bear in mind that a null result doesn't always mean the original value was a reference of a different type - it could have been a null reference to start with. Consider whether or not you need to differentiate those two situations.
  • If you really can't be bothered to really think things through (and I hope none of my readers are this lazy), default to using a cast: at least you'll notice if something's wrong, and have a useful stack trace.

As a side note, writing this post has made me consider (yet again) the various types of "exception" situations we run into. At some point I may put enough thought into how we could express our intentions with regards to these situations more clearly - until then I'd recommend reading Eric Lippert's taxonomy of exceptions, which has certainly influenced my thinking.

08 Jul 18:56

Settled

Well, we've really only settled the question of ghosts that emit or reflect visible light. Or move objects around. Or make any kind of sound. But that covers all the ones that appear in Ghostbusters, so I think we're good.
07 Jul 22:31

Snowden Dilemma

Suppose the government of the United States gets its hands on Edward Snowden and brings him to trial. Have you wondered what happens then?

I've predicted that no jury of Snowden's peers will convict him, regardless of how clear it is that he broke laws. I would be highly disappointed in my fellow citizens if they sided with the perpetrator (the government) over the victims (themselves) and decided to screw the whistleblower (Snowden) who is on their side. But let's consider the alternative.

If Snowden gets convicted, many of the citizens of the United States will go all Egyptian and take to the streets. It was bad enough that the government was collecting all of our private communications. But convicting the guy who blew the whistle? That's throwing a match on the gasoline. So I believe the government doesn't want to see him convicted, or at least the top people don't. It's too risky to the system.

On the other hand, the government has an absolute legal obligation to pursue criminal charges against Snowden. Society doesn't work if people think they can break laws whenever they have good reasons.

We also know there is big money involved in domestic surveillance. And while I'm late to the party on this, all evidence suggests that the government is controlled by corporate interests. So one presumes the government needs to punish the whistleblower to satisfy its corporate overlords and to keep the domestic surveillance cash cow mooing.

This puts the government in the awkward position of trying to avoid some sort of accidental competence that ends up convicting a martyr and sparking a popular uprising. They need to put Snowden on trial to satisfy their corporate sponsors. But they need to fail in getting a conviction to satisfy the public.

I think there is a 100% chance that some dark department of the government, along with its foreign proxies, is planning an "accident" for Snowden before he reaches the United States. Putin would probably do it in return for secret concessions. He might need some of his own spies freed, for example. In the end, I don't think the U.S. government will authorize a hit on Snowden because it would be too obvious. But you know they discussed it. That much seems certain.

If I were President Obama, I would start seeding the media with the idea of a trial and conviction followed by a presidential pardon. You'd want to float that idea and see what the public thought of it. A conviction and a pardon are as close as you can get to a "tie" in this situation, and that would be the best case scenario for the public. We want to know that lawbreakers are dealt with, but we also appreciate justice.

If Snowden gets a lot of attention during a trial, and somehow gains his freedom at the end, I wouldn't be surprised to see him run for President in a few years. This is the sort of situation that gives a person instant legitimacy. If Snowden ran on a platform of exposing corporate control over the government and preserving individual privacy he'd be a credible player on day one.

Things will get interesting when Snowden reaches our shores, and I'm fairly sure that will happen.

07 Jul 22:29

Snowden

The Edward Snowden case has been fascinating from the start. It has spy stuff, a man on the run, embarrassing government secrets, international gamesmanship, a model girlfriend, legal maneuvering. Wow.

But you haven't seen anything yet. Snowden isn't running and he isn't hiding; he's waiting. And he's reportedly negotiating the terms of his return through his dad. When he's ready, and it's safe, he'll come after the U.S. government in a public trial. He's the real deal. And he's on your side, even if it doesn't feel that way.

Is he a traitor? Yes, absolutely. But so were Washington, Adams, Hamilton, Franklin, and Jefferson, to name a few. If you think being a traitor is always bad, no matter the circumstances or motives, you're officially too dumb to vote.

I'm wondering how you find a jury that would convict Snowden. On the first day of the trial his lawyer will explain to all twelve jurors how the government spied on them personally. Every potential juror is also a victim. Good luck getting the victims to side with the perpetrator, which in this case is the government.

I think there's some sort of law that says I can't make a public statement in favor of jury nullification. Jury nullification is when jurors agree that the accused broke the law, but they feel the law itself is wrong, or that a conviction would be overkill, so they find the accused innocent. I predict that will happen. I don't recommend jury nullification because I'm not sure I have freedom of speech in this regard. I simply predict that nullification will happen.

My personal view is that if the government had asked citizens for permission to collect all communications in the country, or had stated its intentions without asking for permission, I'd be okay with it. It seems like a great tool for combatting domestic terrorism, and I don't think the government cares about my browser history.

But the government didn't ask my opinion before it collected my personal communications data. I can't give a free pass for that. And I am available for jury duty.

 

30 Jun 00:38

Extreme Boating

Zane D. Purvis

"Don't sail an aluminum boat on a gallium lake."

Extreme Boating

What would it be like to navigate a rowboat through a lake of mercury? What about bromine? Liquid gallium? Liquid tungsten? Liquid nitrogen? Liquid helium?

-Nicholas Aron

Let's take these one at a time.

Bromine and mercury are the only known pure elements that are liquid at room temperature.

Rowing a boat on a sea of mercury just might be possible.

Mercury is so dense that steel ball bearings float on the surface. Your boat would be so buoyant that you'd barely make a dent in the mercury, and you'd have to lean your weight into the paddle to get the end of it below the surface.

In the end, it certainly wouldn't be easy, and you wouldn't be able to move fast. But you could probably row a little bit.

You should probably avoid splash fights.

Bromine is about as dense as water, so a standard rowboat could in theory float on it.

However, Bromine is awful. For one thing, it smells terrible; the name "bromine" comes from the ancient Greek "brōmos", meaning "stench". If that weren't enough, it violently reacts with a lot of materials. Hopefully, you're not in an aluminium rowboat.

If that's not incentive enough to avoid it, the Materials Safety Data Sheet on bromine includes the following phrases:

  • "severe burns and ulceration"
  • "perforation of the digestive tract"
  • "permanent corneal opacification"
  • "vertigo, anxiety, depression, muscle incoordination, and emotional instability"
  • "diarrhea, possibly with blood"

You should not get in a splash fight on a bromine lake.

Liquid gallium is weird stuff. Gallium melts just above room temperature, like butter, so you can't hold it in your hand for too long.

It's fairly dense, though not anywhere near as dense as mercury, and would be easier to row a boat on.

However, once again, you'd better hope the boat isn't made of aluminium, because aluminium (like many metals) absorbs gallium like a sponge absorbs water. The gallium spreads throughout the aluminium, dramatically changing its chemical properties. The modified aluminium is so weak it can be pulled apart like wet paper. This is something gallium has in common with mercury—both will destroy aluminium.

Like my grandma used to say, don't sail an aluminium boat on a gallium lake. (My grandma was a little strange.)

Liquid tungsten is really hard to work with.

Tungsten has the highest melting point of any element. This means there's a lot we don't know about its properties. The reason for this—and this may sound a little stupid—is that it's hard to study, because we can't find a container to hold it in. For almost any container, the material in the container will melt before the tungsten does. There are a few compounds, like tantalum hafnium carbide, with slightly higher melting points, but no one has been able to make a liquid tungsten container with them.

To give you an idea of how hot liquid tungsten is, I could tell you the exact temperature that it melts at (3422°C). But a better point might be this:

Liquid tungsten is so hot, if you dropped it into a lava flow, the lava would freeze the tungsten.

Needless to say, if you set a boat on a sea of liquid tungsten, both you and the boat would rapidly combust and be incinerated.

Liquid nitrogen is very cold.

Liquid helium is colder, but they're both closer to absolute zero than to the coldest temperatures in Antarctica, so to someone floating on them in a boat, the temperature difference is not that significant.

A Dartmouth engineering page on liquid nitrogen safety includes the following phrases:

  • "violent reactions with organic materials"
  • "it will explode"
  • "displace oxygen in the room"
  • "severe clothing fire"
  • "suffocation without warning"

Liquid nitrogen has a density similar to that of water, so a rowboat would float on it, but if you were in it, you wouldn't survive for long.

If the air above the nitrogen was room temperature when you started, it would cool rapidly, and you and the boat would be smothered in a thick fog as the water condensed out of the air. (This is the same effect that causes steam when you pour out liquid nitrogen.) The condensation would freeze, quickly covering your boat in a layer of frost.

The warm air would cause the nitrogen on the surface to evaporate. This would displace the oxygen over the lake, causing you to asphyxiate.

If the air (or the nitrogen) were cold enough to avoid immediate evaporation, you would instead develop hypothermia and die of exposure.

Liquid helium would be worse.

For one thing, it's only about one-eighth as dense as water, so your boat would have to be eight times larger to support a given weight.

But helium has a trick. When cooled to within two degrees of absolute zero, it becomes a superfluid, which has the odd property that it crawls up and over the walls of containers by capillary forces.

It advances up the walls at about 20 centimeters per second, so it would take the liquid helium less than 30 seconds to start collecting in the bottom of your boat.

This would, as in the liquid nitrogen scenario, cause rapid death from hypothermia.

If it's any consolation, as you lay dying, you would be able to observe an odd phenomenon.

Superfluid helium films, like the one rapidly covering you, carry the same types of ordinary sound waves that most materials do. But they also exhibit an additional type of wave, a slow-moving ripple that propagates gates along thin films of helium. It's only observed in superfluids, and has the mysterious and poetic name "third sound."

Your eardrums may no longer function, and wouldn't be able to detect this type of vibration anyway, but as you froze to death in the floor of a giant boat, your ears would be filled—literally—with a sound no human can ever hear: The third sound.

And that, at least, is pretty cool.

27 Jun 15:25

The Paula Deen Context

Warning: This blog is written for a rational audience that likes to have fun wrestling with unique or controversial points of view. It is written in a style that can easily be confused as advocacy for one sort of unpleasantness or another. It is not intended to change anyone's beliefs or actions. If you quote from this post or link to it, which you are welcome to do, please take responsibility for whatever happens if you mismatch the audience and the content.

 ------

I hadn't heard of Paula Deen, the so-called Southern cooking star, until her recent string of "controversies." Now I'm all in. This is one of the most interesting stories in a long time, from a psychology point of view.

I was casually following the headlines last year when it came out that Deen was promoting less-than-healthy food while she developed Type 2 diabetes, presumably from eating similar crap, while secretly negotiating a promotional deal with Novartis to pimp their diabetes drug. None of that sounds good.

The diabetes issue got her on the front page. But the recent "racism" controversy has pretty much ended her career, I would expect. That stain doesn't go away.

So I thought I would wade in and offer some context because I haven't gotten myself in enough trouble lately. My personal view of Deen, based on incomplete knowledge, is that she was a product of her environment, just like the rest of us. She did things she rightfully regrets, was honest about it and took responsibility, learned from her experiences, apologized in ways that looked sincere to me, and evolved. Hollywood makes movies about that sort of thing: Flawed person learns lessons the hard way. So now that Deen and her critics are on the same side, in terms of both healthy eating and race, that's the end of the story, right?

Not in this world. And that's the part that fascinates me.

I was watching some low-budget entertainment show the other night on which so-called "media personality" Keli Goff was ripping Deen apart while grinning in a most disturbing way. Goff, if you don't already know, is your signal that something is wrong with the context of a story. She's associated with the bottom-feeding media that includes The Huffington Post and the like. Those outlets don't just report the news; they create it by leaving out context. So, when I saw Goff, I got interested. And I wasn't disappointed.

The show I watched went like this. The host played a clip of Deen issuing an emotional, raw, awkward apology that literally included begging for forgiveness. The host and the pundits talked about Deen's apology at length. Five minutes later, on the same show, with the same pundits, the conversation turned to Deen's lack of an apology, as if they had not just watched and discussed that very thing.

Let me repeat that. They played a tape of Deen's apology, discussed the apology then complained that there had been no apology. I watched carefully to see if they meant the apology was lacking a necessary element, but that didn't seem to be the case. The apology looked sincere and heartfelt to me, albeit awkward. The problem, said the pundits, was that the very thing they just watched and discussed didn't actually happen. You rarely see confirmation bias play out that vividly. Once it had been decided that Deen was a monster, it couldn't also be true that she issued a sincere apology even if you just finished watching it. The whole thing was fascinating.

I don't know what is in Deen's soul, and I certainly don't know all the facts behind the allegations, so I neither support nor defend her. But I'd like to add some context because the bottom-feeding media is doing the opposite.

1.      Every alleged example of Deen's racism involves either a good friend of hers who is African-American, an African-American chef or general manager that she or her brother hired for their restaurants, and in one case a preference for hiring African-American servers for a particular event. (More on that later.) That's a strange pattern for a racist.

2.      I owned two restaurants. Restaurants are unusually fertile breeding grounds for bogus lawsuits and employment claims. You can't compare restaurants to other businesses in that way. You should assume 90% of employee discrimination claims in the restaurant industry are complete bullshit even if the stats are opposite in the standard corporate world. That's the context in which you should view the employee claims against Deen. Remember, she's an easy target, and any lawyer would know she has deep pockets and a need to settle quickly. I don't know the facts in her case, nor do you. I'm just giving context.

3.      Deen claims her use of the N-word was in the context of jokes long ago and not representative of her current thinking. I don't know where her critics grew up, but during my youth in upstate New York it seemed as if all jokes were at the expense of one ethnic group or another, blonde women, farmer's daughters, lepers, dead babies, and folks with disabilities. The wrongness of the so-called humor was the whole point. That was the style of the day, as despicable as it seems by today's standards. When Deen admits to being part of that culture, and evolving out of it, that sounds more like naïve honesty than racism. If you didn't live through that era, you are missing some important context.

4.      One of the most damning allegations is that Deen once suggested a slave-themed event that would feature only professional servers who were African-American. To me that sounds laughably implausible. It's the sort of thing one could only believe if you already bought into the idea that Deen is a racist, diabetes-promoting monster. It reminds me of the recent Internet hoax showing a photo of Heineken banners over a dog fight. A lot of folks on the Internet believed Heineken was advertising at a dog fight, as if that was even slightly plausible. (The Heineken signs were left over from some earlier event at the same location.)

I'll reiterate that I don't support Deen, or condone anything that she did, allegedly or otherwise. It's not my job to judge anyone. I'm just adding context.

22 Jun 05:32

Comic for June 22, 2013

Dilbert readers - Please visit Dilbert.com to read this feature. Due to changes with our feeds, we are now making this RSS feed a link to Dilbert.com.
20 Jun 15:38

Comic for June 20, 2013

Dilbert readers - Please visit Dilbert.com to read this feature. Due to changes with our feeds, we are now making this RSS feed a link to Dilbert.com.
19 Jun 19:18

Subversion 1.8 Released But Will You Still Use Git?

by Unknown Lamer
darthcamaro writes "Remember back in the day when we all used CVS? Then we moved to SVN (subversion) but in the last three yrs or so everyone and their brother seems to have moved to Git, right? Well truth is Subversion is still going strong and just released version 1.8. While Git is still faster for some things, Greg Stein, the former chair of the Apache Software Foundation, figures SVN is better than Git at lots of things. From the article: '"With Subversion, you can have a 1T repository and check out just a small portion of it, The developers don't need full copies," Stein explained. "Git shops typically have many, smaller repositories, while svn shops typically have a single repository, which eases administration, backup, etc."'" Major new features of 1.8 include switching to a new metadata storage engine by default instead of using Berkeley DB, first-class renames (instead of the CVS-era holdover of deleting and recreating with a new name) which will make merges involving renamed files saner, and a slightly simplified branch merging interface.

Share on Google+

Read more of this story at Slashdot.



19 Jun 02:46

Wi-Fi Light Bulbs to run the Open Source Contiki OS

by donotreply@osnews.com ()
The open source Contiki operating system and its commercial Thingsquare distribution are making strides towards the connected home. According to a Computerworld article, a new LED light bulb manufacturer is putting small computers into their light bulbs. Each computer runs the Contiki OS, which gives each bulb an IP address and allows them to be controlled with a smartphone application. To connect the bulbs to the application, the bulbs use both Wi-Fi and the much lower power IEEE 802.15.4 mesh technology.