Bryan Klimt
pacegallery:

Pop-up gallery: Pace Gallery is proud to announce the opening of a temporary exhibition space in Menlo Park, California from April 16 through June 30, 2014. 
Located in the former Tesla headquarters at 300 El Camino Real in the heart of Silicon Valley, Pace Menlo Park will present two exhibitions: Alexander Calder: The Art of Invention, from April 16 through May 13; and Tara Donovan: Untitled, from May 22 through June 30.

How appropriate for Silicon Valley.

pacegallery:

Pop-up gallery: Pace Gallery is proud to announce the opening of a temporary exhibition space in Menlo Park, California from April 16 through June 30, 2014.

Located in the former Tesla headquarters at 300 El Camino Real in the heart of Silicon Valley, Pace Menlo Park will present two exhibitions: Alexander Calder: The Art of Invention, from April 16 through May 13; and Tara Donovan: Untitled, from May 22 through June 30.

How appropriate for Silicon Valley.

Choosing not to be evil

I am so bad at writing Christmas cards. I sat down to write a Christmas card, and what came out instead is this essay on whether it’s acceptable to be evil in the face of an existential threat. By an existential threat, I mean anything that threatens your very existence. I have heard repeatedly throughout my life, “Yes, it’s evil, but we must do it, or we will cease to exist.” I don’t buy it.

Whenever you make a general argument like this on the Internet, people reading it are bound to think you are talking about them in particular. Am I talking about you? Probably. The truth is, I have run into this argument in some form or another in government politics, and at every single company I’ve ever worked for, and in discussions of personal morality. It’s everywhere. The line of reasonable seems to go something like this:

1. We are good.
2. Therefore, if we exist, that is good.
3. If we don’t do this thing we agree is evil, we will not exist.
4. Therefore, by doing this evil thing, we can exist, which is good.
5. Thus, we should do this evil thing.

The most striking examples of this type of thinking come from post-9/11 American foreign policy. For example, there was debate over whether we should allow torture of captured persons. The thinking went like this:

1. America is the greatest force for good in the world.
2. If we don’t torture, the terrorists will be able to destroy America.
3. Therefore, we must torture in order to continue being a force for good in the world.

There are so many flaws in this line of reasoning, that it’s hard to even know where to begin dismantling them. The biggest contradiction seems to in the very first statement. At the point that we begin doing evil, we are no longer good. Therefore, it’s no longer necessarily a good thing if we exist. In the case of a corporation, this is especially true. Corporations don’t have a fundamental right to exist. If Enron were to argue “we must use fraudulent banking, or we would go out of business”, I would say good riddance.

But oftentimes, it’s simply not enough to give up and say “Fine, let’s not exist.” That is the path toward nihilism. While it is logically sound and philosophically pure, we reject it. We choose to exist. So how do we resolve the contradiction?

One option is to drop the assertion that we are good. Then the line of thinking goes like this:

1. We choose to exist.
2. We must be evil to exist.
3. Therefore, we choose to be evil.

Again, this is logically sound and philosophically pure, but personally, I must reject it. I personally believe that we have a moral and ethical obligation to do good. I take it as a matter of faith. It is up to us to decide the meaning of our lives. I choose to be good.

So, we must find some other way to break the contradiction, and I only see one option. This assertion:

3. If we don’t do this thing we agree is evil, we will not exist.

If we can choose to exist, and we choose to be good, then this assertion must be false. Often, this isn’t nearly so difficult as one would imagine. Can the U.S. exist without torturing? Absolutely! It has for hundreds of years. If we cannot imagine a way to exist without being evil, then that surely is a failure of our imaginations. We should not accept this failure. It’s a start to simply stop doing it, and deal with the negative implications as they happen. Or, we could try literally anything else at all that isn’t evil.

There are surely a few cases where this assertion is simply inescapable. For example, if someone puts a gun to your head and tells you to murder other people, there’s not much you can do to maintain your existence that isn’t evil. In those cases, we may have to fall back and question our choice to exist at all. Fortunately, these situations are few and far between for individuals. Even in the case of military drafts, there are “conscientious objector” laws that give us other options.

So, we choose to exist, we can choose to be good, and that means rejecting any assertion that we must be evil in order to exist.

Now, some people will call this line of thinking naive. It hope it is. Being cynical is easy, but being naive in the face of adversity is a real challenge. At any rate, I don’t see how naivety undermines this argument.

And some people will say that things are rarely so black-and-white — that things that happen in real life are rarely easily classified into “good” and “evil”. That’s absolutely true. But I’m not arguing against anything in particular here. I’m arguing against a line of reasoning. I’m arguing against this type of argument. So if you come to me and say “We must do this thing we agree is evil in the face of an existential threat,” then don’t be surprised if I simply say “No.”

Phenomenauts Sprites

imageimageimageimage

Some animated sprites I made. The first three are Professor Greg Arius of the Phenomenauts, with his Streamerator. The fourth one is some kind of alien Elvis impersonator or something.

Quiz Time!

Objective-C Blocks Quiz

Do you really know how blocks work in Objective-C? Take this quiz to find out.

All of these examples have been verified with this version of LLVM:

Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix

Example A

This example

Example B

This example

Example C

This example

Example D

This example

Example E

This example

Conclusions

So, what’s the point of all this? The point is always use ARC. With ARC, blocks pretty much always work correctly. If you’re not using ARC, you better defensively block = [[block copy] autorelease] any time a block outlives the stack frame where it is declared. That will force it to be copied to the heap as an NSMallocBlock.

Haha! No, of course it’s not that simple. According to Apple:

Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain.

But one of the LLVM maintainers later said:

We consider this to be a compiler bug, and it has been fixed for months in the open-source clang repository. What that means for any hypothetical future Xcode release, I cannot say. :)

So, hopefully Apple was describing a workaround for bugs that existed at the time their guide was written, and everything should work smoothly with ARC and LLVM in the future. But watch out. ;)

My progress so far.

My progress so far.

Go

I’ve been learning Go the last few days. I’ve been trying to learn the rules of the language, so that when I encounter new code, I can apply those principles and understand it quickly and thoroughly. But I’ve been having a really hard time. I get the feeling that Go was designed by System Engineers, who focus on implementation. The API Designer in me is getting frustrated with the lack of consistency in the language. There are more exceptions than rules. Here are some of the things I find the most confusing.

Instantiation

Let’s say you want to create a new instance of Foo. How do you do it? Well, first, you’ve got to know what primitive type Foo is descended from. If it happens to be an int or bool or something like that, you can do either of these:

var x Foo
y := 3

If Foo is derived from map, slice, or chan, then you use this special function called make:

hash := make(map[string]int)
slice := make([]int 100)
c := make(chan int)

Why is there this special function that construct these three random types? I don’t know.

If Foo is derived from struct, then you have to know whether the struct is usable when it’s zero-valued. I think most of them are. But watch out, because there’s nothing to stop you from making one that’s zero-valued when it’s not valid.

There’s a function called new that can create a zero-valued struct, but as far I can tell, you’re never supposed to use it, because you can use the literal syntax instead:

// Foo is valid when zero-valued. These two declarations are equivalent.
fooPtr := &Foo{}
fooPtr := new(Foo)

Why does new exist?

If Foo is derived from a struct, and it doesn’t work when zero-valued, then there should be a function somewhere called something like NewFoo. Good luck finding the right one.

foo := foopkg.NewFoo(arg1, arg2)

Value Semantics

Every type in Go uses value semantics, meaning passing it to a function will be a pass-by-value. Except maps and slices. They are passed by reference. I think it’s only those two. Despite the similarity between arrays and slices, the former is a value type, while the latter is a reference type. I think channels are value types, which is strange since it’s the only other type created with make. (Correction: Channels are reference types, so maybe that explains make; it generates the three reference types.)

Partial methods

You can add methods to types outside of the file where the type was defined. This should be incredibly powerful:

type Foo struct {
  bar string
}

// A method on Foo.
func (foo *Foo) setBar(aString string) {
  foo.bar = aString
}

Unfortunately, this feature has been neutered by only being able to extend types in your own package. You can’t add methods to built-in types like string or int. This means those types can never fulfill any new interfaces you add. You can derive a new type from those types, and extend that, but then you have to explicitly cast wherever you use it.

type ExtensibleInt int

func (x ExtensibleInt) timesTwo() int {
  return x * 2
}

var myInt extensibleInt = 3

// You have to explicitly cast it back to int.
fmt.Printf("%d", int(myInt));

Non-standard library

Unfortunately, not being able to add methods to string makes the standard library a bit wonky. For example, you have to write strings.HasPrefix(str, pre) instead of the more obvious str.HasPrefix(pre).

The standard library also seems to be missing a lot of the most common data types. As far as I can tell, there are no standard stack or queue types. But there is heap. How can a language provide an http server, but no stack type?

In-band signaling

Go has a wonderful feature that a method can return multiple values.

// ok is true iff the key is in the map.
value, ok := someMap[key]

As the designers of Go point out, this helps you avoid in-band signaling. By not conflating a special value (such as nil) with the lack of presence, you are free to have nil be a legitimately returned value.

Unfortunately, I don’t think they’ve really internalized this concept. Strings can’t nil, which is fine on its own, But lots of folks on the internet have been asking for a nullable string type, such as how nullable types work in C#, or how String works in Java. That way, you can write functions where a string is optional, but the empty string is also a valid input.

So what’s the response from Go’s designers about the requests for nullable strings? To treat the empty string as a special value. Sometimes it’s like they haven’t even read their own design justifications.

Conclusions

This post has been about my problems with learning Go, but let me be clear that I don’t think Go is a terrible language. It has some really great features, such as multiple return values and the := operator. And the results seem to be very efficient binaries that build almost instantly. It may be an awesome language once you get to know it well.

But all the inconsistencies in the language design have made learning it feel like a chore.

Another set of texts from Paige’s friends.

Another set of texts from Paige’s friends.