Saturday, March 17, 2012

Please, I'm begging you, shut up about "social media"

CNN:

CNN legal analyst Paul Callan called Friday's verdict "unprecedented," adding that it "sends a message to people across the rest of the country" about the potential consequences of unauthorized webcam use in an age of expanding social media.

New York Times:

“This reinforces that social media can cause great harm and that its misuse can be criminal,” Ms. Goldberg said.

Star Ledger:

The case has helped bring national attention to gay youth suicide and the use of the internet and social networking sites to bully young people.

This story has absolutely nothing to do with social media.

Yes, he posted about it on Twitter. But most of the people who found out about it heard it face-to-face. This happened in a dorm room, remember. Do you know how fast news travels in a dorm room? During the first month of freshman year?

What I'm really worried is that if we all believe that the theme of the tragedy is "privacy in the face of social media", we will miss all the things it's actually about. Focusing on Dharun's tweets makes him sound like the broadcaster, and everyone else like a passive audience. But remember there were several people in Molly's room to spy on Tyler. Many more heard about it later that night, and many more at breakfast the next morning. And, with a few exceptions, all of these people were also Tyler's neighbors. The lived literally down the hall from him. They could go talk to him any time they wanted. If you don't know where Tyler lives there are names on the doors.

Imagine for a moment you are Tyler. Which is more important to you: whether your roommate plays a dickish prank on you, or whether all of your neighbors, the people you see every day, implicitly support him in that dickish prank? How much would it mean to have just one person walk ten feet down the hall, knock on your door, and say, hey, man, that was pretty douchebaggy what Dharun did, are you feeling OK?

Sergio de Biasi, a Rutgers CS grad student (and one of the best TAs I've ever had), committed suicide a year after Tyler. He had this to say:

Seriously, the real problem is not some idiots doing idiotic stuff. I am reasonably sure that if the victims were convinced that the reaction of society around them would be of almost unanimous disapproval and horror towards the idiots and of support towards the victims, they would not suffer so greatly and not be so hopeless. The real problem is that when idiots do something like this to someone, the reaction of those around them should be something along the lines of “WHAT? Dude, you’re a creep and an idiot, and I don't want to have anything to do with you.” but instead for a million reasons it is not. It's not socially convenient to antagonize anyone. It doesn't really bring any profit to show support for someone who was been wronged. So people just go on and do business as usual.

In a way, it's almost inevitable that Dharun would be convicted of some serious crimes, because that lets us feel that the perpetrator has been identified, and that it is not us. I believe all of us have at some time or another been in the position of Tyler's neighbors, though perhaps no one died in the end. That's why this story makes us uncomfortable; it agitates our latent guilt. But we need to be a little more introspective. What really separates you from Dharun? Are you really a better person, or are you just more scared of exposing yourself as the ringleader?

Maybe we want to believe that this is about social media, so that we forget it all happened in one building, and that everyone who heard about it could have done something to help. "Social media" makes it sound distant, detached, one perpetrator and a bunch of innocent bystanders. It is none of those things.

Another aspect to this story that the media hasn't really picked up on is that had the events taken place in November or December or the spring semester this probably wouldn't have happened at all. There is something about the first month of freshman year where morality is elusive, and everyone goes along with the new culture. Maybe because you're in an unfamiliar environment, and you're trying to figure out what the new rules are, and the best you can do is imitate the people around you, who have no more clue than you do. When the shit hits the fan, and the fantasy ends, you suddenly realize "Oh wow, that was really mean". But until then it's almost impossible to tell.

The thing is, that, while the dorm room culture can be incredibly hurtful (as in this example), everyone imitates each other, and so the culture has an incredible internal consistency. So even if something is very wrong, it feels right. When the RA or the law comes in and says "that was really mean", it feels like an intrusion. "We have the rules figured out already! What are you bringing in these new ones for?"

I think the most important question that this story should raise for us is how we can avoided being sucked into this kind of situation. Because once you're there, it's so hard to know you're there. And sometimes someone dies as a result.

Friday, March 16, 2012

Tail recursion in Python

[Python-Dev] Proper tail recursion

If tail-call elimination is an optimization, it is the kind of optimization that you have to keep your eye on: if you've been writing your code thinking it's there, it better really be there. Tail-call elimination can make or break a program. Run a tail-recursive loop that services requests indefinitely, and you'll see it's not just an optimization whether the stack grows with each call.

Still, tail recursion is not everybody's style. As Guido says:

I don't think it's a good idea to try to encourage a Scheme-ish "solve everything with recursion" programming style in Python.

And there's the truth: Python's goal is to restrict your programming style. Why are the following awkward (albeit possible) in Python?

  • Lazy evaluation

  • Sum-of-product types (as in Haskell)

  • Enforced private members / fix the set of fields for a class

  • Tail recursion

  • User-defined control structures (as in Scala or Ruby)

  • User-defined literals, syntax, pattern matching, or any extention to the basic building blocks of the language.

They are awkward because there was another way of doing it, and, when there's more than one way of doing it, Python makes a choice.

Now, I must be honest, if every language took it upon itself to enforce a particular style I would not find that exquisitely pleasant. I am grateful that languages like Scala and C++ and Ruby exist. But I am also glad that we have at least one language we can reach for when we need a homogeneous style.

Personally, I turn to a functional style when I can. And, yes, the awkwardness of functional programming in Python does occasionally irritate me ("Python: As much Lisp as a C programmer can (under)stand." -- Nathan Sanders). But, at the end of the day, when I go to push my changes, that irritation is more than offset by a tiny feeling of confidence in the code I just wrote that someone else will understand it.

Wednesday, March 14, 2012

Agda as a Programming Language: Using Haskell for basically everything

Agda would not be useful if it had to reinvent all of its wheels. Luckily it is faily easy to use Haskell from Agda.

     wordcount.agda 

  1  module wordcount where
  2  
  3  import Foreign.Haskell as Hask
  4  open import IO.Primitive renaming (putStrLn to putStrLnCo)
  5  open import Data.List
  6  open import Data.String
  7  open import Function using (_∘_)
  8  
  9  -- Data.Nat is unary. This is terribly inefficient. Ideally
 10  -- we would use Haskell numbers, but that is not convenient.
 11  open import Data.Nat
 12  
 13  -- Data.Nat.Show was written before Agda had typeclass support.
 14  open import Data.Nat.Show renaming (show to showNat)
 15  open import Data.Char
 16  
 17  putStrLn = putStrLnCo ∘ toCostring
 18  
 19  infixl 1 _>>_
 20  postulate
 21      _>>_  : ∀ {a b} {A : Set a} {B : Set b} → IO A → (IO B) → IO B
 22  {-# COMPILED _>>_  (\_ _ _ _ -> (>>)) #-}
 23  
 24  module CmdlineArgs where
 25      {-# IMPORT System #-}
 26      postulate sysArgs : IO (List String)
 27      {-# COMPILED sysArgs (System.getArgs) #-}
 28  
 29  module FileIO where
 30      {-# IMPORT System.IO #-}
 31      postulate Handle : Set
 32      {-# COMPILED_TYPE Handle System.IO.Handle #-}
 33      postulate hGetLine : Handle -> IO String
 34      {-# COMPILED hGetLine (System.IO.hGetLine) #-}
 35      postulate hGetContents : Handle -> IO String
 36      {-# COMPILED hGetContents (System.IO.hGetContents) #-}
 37      postulate IOMode : Set
 38      {-# COMPILED_TYPE IOMode System.IO.IOMode #-}
 39      postulate ReadMode : IOMode
 40      {-# COMPILED ReadMode (System.IO.ReadMode) #-}
 41      -- This won't work if it's not universe-polymorphic. I Don't know why.
 42      postulate withFile : ∀ {u} {A : Set u} -> String -> IOMode -> (Handle -> IO A) -> IO A
 43      {-# COMPILED withFile (\_ _ -> System.IO.withFile) #-}
 44  
 45  open CmdlineArgs
 46  open FileIO
 47  
 48  wordsInString : String -> ℕ
 49  wordsInString s = ws1 (toList s) where
 50      mutual
 51          ws1 : List Char -> ℕ
 52          ws1 [] = 0
 53          ws1 (' ' ∷ rest) = ws1 rest
 54          ws1 (c ∷ cs) = suc (ws2 cs)
 55  
 56          ws2 : List Char -> ℕ
 57          ws2 [] = 0
 58          ws2 (' ' ∷ rest) = ws1 rest
 59          ws2 (c ∷ cs) = ws2 cs
 60  
 61  -- Agda does not have case expressions, so we use a local
 62  -- function to pattern match.
 63  main : IO Hask.Unit
 64  main = sysArgs >>= doArgs where
 65      -- Agda's type inference is not as good as Haskell's;
 66      -- We have to specify some amount of signature.
 67      doArgs : _ -> _
 68      doArgs (path ∷ []) =
 69          withFile path ReadMode \hl ->
 70              hGetContents hl >>= \text ->
 71              let count = wordsInString text in
 72              putStrLn (showNat count)
 73      doArgs _ =
 74          putStrLn "Usage: wordcount <filename>"

Agda as a Programming Language: Hello World

While checking out Agda, I found a lot of information on using Agda to prove things, but very little on using Agda to write programs. So I will post here what I learn, and maybe it will help someone.

As to why you would use Agda to write programs, well, I had a reason, but that's for another day.

Hello World

Agda keeps changing; the old Hello Worlds no longer compile (I have yet to find a single working example on the internet). After some struggle I managed to produce one:

     hello.agda 

  1  -- Compiles with Agda 2.3.0 and standard library 0.6
  2  -- on 2012-03-13
  3  
  4  module hello where
  5  
  6  open import IO.Primitive
  7  open import Data.String
  8  
  9  import Foreign.Haskell as Hask
 10  
 11  main : IO Hask.Unit
 12  main = putStrLn (toCostring "Hello, World!")

To run this program you will need:

Both of these can be installed with cabal.

Then run:

  1  agda -i <path to standard library source> -i . -c hello.agda
  2  ./hello

So, in my case,

  1  agda -i ~/install/lib-0.6/src -i . -c hello.agda
  2  ./hello

Peculiarities of the program

  • IO deals with Costrings rather than Strings (for some reason). A string literal is a String, so we convert it with toCostring. We could also have done:

      1  open import IO.Primitive renaming (putStrLn to putStrLnCo)
      2  
      3  putStrLn : String -> Hask.Unit
      4  putStrLn s = putStrLnCo (toCostring s)
    
    
  • putStrLn is literally just the Haskell function of the same name; as such it returns Haskell's Unit type; Agda has its own Unit type (in Data.Unit), but these are not the same. So the result of main must be IO Foreign.Haskell.Unit.

  • Agda has another IO library in IO; it might be better, but I didn't understand it, so I used IO.Primitive.

More IO

     someio.agda 

  1  module someio where
  2  
  3  import Foreign.Haskell as Hask
  4  open import IO.Primitive renaming (putStrLn to putStrLnCo)
  5  open import Data.String
  6  open import Function using (_∘_)
  7  
  8  putStrLn = putStrLnCo ∘ toCostring
  9  
 10  infixl 1 _>>_
 11  
 12  postulate
 13      _>>_  : ∀ {a b} {A : Set a} {B : Set b} → IO A → (IO B) → IO B
 14      getLine : IO String
 15  
 16  {-# COMPILED _>>_  (\_ _ _ _ -> (>>)) #-}
 17  {-# COMPILED getLine (getLine) #-}
 18  
 19  main : IO Hask.Unit
 20  main =
 21      putStrLn "Hello, World!" >>
 22      putStrLn "Whatup!" >>
 23      getLine >>= \up ->
 24      putStrLn ("Your face is " ++ up)

  • IO.Primitive does not define >>, so we do.
  • (\_ _ _ _ -> (>>)) throws away the type arguments, because Haskell does not have type arguments.
  • Agda has no do notation.

Friday, March 9, 2012

More on static typing

As I've said earlier, I find static typing aesthetically appealing but am skeptical about its practical value.

Type systems are the chemo of programming. They are designed to make things harder. You hope that most of what it does is make mistakes harder, but you know from experience that static typing introduces a grain of trickiness into everything.

What do people find so appealing about dynamic languages?:

You know, maybe the dynamic crowd just wants freedom to not have to think as carefully about what they're doing. The software might not be correct or robust, but maybe it doesn't have to be.

-- Apocalisp

The whole answer is very good, but the author has a fundamental misconception: that the only cases where a dynamic language admits a program that a static language rejects is when the program is incorrect. Consider that the following python code is perfectly correct:

a = [ ]
for i in range(0, 8, 2):
    a.append(i)
    for j in range(i): a.append('x')

print(a)

total = 0
i = 0
while i**2 < len(a):
    total += a[i**2]
    i += 1
print(total)

but that it would not pass a static type checker. You could of course struggle a long time to prove via the type system that the while loop accesses only those elements of a that happen to be numbers (you could probably do it, but it would be a long and painful journey). But more importantly, even if you don't do it, the code is still correct.

The difficulty of static type systems is not that they require your code to be more correct, but that they require you demonstrate its correctness in a certain way. That certain way is a pretty elegant one, but it is also a terribly specific one, and so there will always be correct code to which a static type system is poorly suited.

Unit testing statically typed functional code

Unit tests do introduce redundancy, which means that when requirements change, the code implementing them and the tests covering this code must both be changed. [...] given how statically typed functional programming covers a lot of the ground unit tests are intended for, it feels like it's a constant overhead one can simply reduce without penalty.

-- back2dos

Some of the bug-finding power of static typing comes from redundancy; in fact, if you want to catch inadvertant changes in behavior introduced by refactoring, you will need to specify explicit type signatures, which are redundant.

I wonder, are there any statically typed programming languages which provide tools to check whether the inferred type of a function changes across different versions of the code?

If you have specs which can be mapped directly to function declarations - fine. But typically those are two completely different levels of abstractions.

-- Doc Brown

Of course, in theory all levels of abstraction can be checked statically; but how many people are leet enough to actually do that? (Consider -- what would you need to do to write a statically verified sorting function). If unit tests can take you to 97% sure that your code is correct (and still correct after a refactoring), how much time are you willing to spend on that extra 3%?

Thursday, March 8, 2012

Thomas Carlyle on Agile

But indeed Conviction, were it never so excellent, is worthless till it convert itself into Conduct. Nay properly Conviction is not possible till then; inasmuch as all Speculation is by nature endless, formless, a vortex amid vortices: only by a felt indubitable certainty of Experience does it find any centre to revolve round, and so fashion itself into a system. ... Do the Duty which lies nearest thee, which though knowest to be a Duty! Thy second Duty will already have become clearer.

-- Thomas Carlyle in Sartor Resartus.

Thursday, November 24, 2011

Permanence

Permanence

\displaystyle\int{\sqrt{1 + \sqrt{x}}}

The Calc I problem ends with:

Comment: The latest version of the big and powerful symbolic manipulation program Maple, available on most Rutgers systems, is unable to find this antiderivative (with the default settings for the program). Maple’s major competitor, Mathematica, considers the integral and returns

Mathematica could not find a formula for your integral. Most likely this means that no formula exists.

which is amusing.

Yes, hilarious.

The author has a common problem: he wants his students to sit down and grind through a few integrals but the students are getting bored and reaching for the computer. How do you convince them that learning to integrate by hand is worth the tedium?

Well, one thing to consider is that the students may be right. I'm not saying practice isn't worth something, I'm saying you're never going to run out of things to work on even if you delegate the monotonous tasks to the machines. There's always something more to do and your students might even discover something new. If you don't have the creativity to write problems that can survive the onslaught of technology, ask someone next door.

The thing is, even the author's attempted solution -- a tricky integral -- is only halfway to actually motivating the subject. Even if Maple can't do it (it can -- I checked, and so can Maxima, but that's besides the point), it's still just one random integral nobody cares about -- it's going to vanish by tomorrow.

Students are not used to being asked to create things of permanent value. They are asked to create temporary things that are sufficient to pass the grader's eye but will not serve them later. No matter how "real worldy" you make the problem, if the solution isn't generally useful, it's just going to vanish along with all the rest.

Let me emphasise that last point again because it's usually missed: it doesn't matter at all how realistic the problem seems, if the student isn't going to use their own answer again later, it's not something permanent. And the important part isn't that it will vanish, it's that when you know it will vanish, you approach it differently.

Do you ever notice that the people around you (and you too, though I was hoping not to rely on your own introspection) seem hesitant, nervous even to really finish something? This is because we are not used to permanence. We want the problem to have finite scope from the outset and vanish when it is complete. Do you notice that people have trouble grounding their thoughts in reality? If you're not producing something that lasts, why make it complete?

There was a chimpanzee named Nim Chimpsky whom researchers tried to teach language by positive and negative reinforcement. At first Nim seemed to be learning a lot of new words, then they found out he'd just been learning to the spec, imitating enough to pass the test, and had in fact learned nothing.

This is what we have been trained to do. Hey, if people are writing software to solve integrals, that's something of permanent value... how about having the students do that? Writing a program to solve a problem is better than solving it by hand 100 times because to make your code work you have to understand the steps completely. The compiler is unforgiving. I think this is often what scares teachers away from programming as part of their class -- they think they know, and want to believe, that the students understand the material, but the compiler is too revealing.

This is why you should use the compiler, though, because it breaks your illusions.

We are transient, our memories are transient, we forget often and dislike remembering, the best we can do is produce something outside ourselves that lasts.

Tuesday, November 22, 2011

The Best Way to Squander Power

"Cops Spray Passive Protestors"

It does look pretty bad.

You can say with near certainty that the officer holding the red can is in the 99%. But now he's been made their enemy. UC Davis Chancellor called his actions "chilling", his job is at risk. He's in the 99%, but the 99% aren't helping him, they're hurting him. they're making his future uncertain, maybe worse. How did he go from being your friend to being your enemy?

Why does the video look so shocking? Because the spraying doesn't look tactical -- it looks punative. If I had to guess what was going through the officer's mind, I wouldn't say he's trying to break the circle so his colleagues can get out (though that's probably part of it); somewhere in there he's enjoying the display of pain -- or rather, he's enjoying that he has the power to inflict pain. At least he has the power to do something.

You've been protesting because the voice of the 99% has been cut off. If I had to give a picture of someone reacting badly because their voice has been cut off, it would be a middle aged man pepper-spraying college kids, walking back, and spraying them again.

What we're starting to realize, though, is that the Occupy movement is powerful, because the ideas behind it are powerful. But using that power to stick it to a lowly police officer, someone who shouldn't even be your enemy... the easiest way to squander power is to waste it on easy victims.

Look at how calmly the officer settles into his role as enemy. He knows which side he's on before he even pulls out the can. How did he find out? Who told him he was an enemy? Was it something in the way they looked at him, a message passed by eye contact, telling him what part he'd play?

You've got to stop playing it that way.

Monday, November 7, 2011

What's up with Lift

I've been using the Lift web framework for a class project. Lift is written in Scala, which is a statically typed functional language.

The philosophy in these languages tends to be that you should use the type system to prove as much of the consistency of your program as possible about your program so that you don't need to check as much at runtime.

Unfortunately, in web programming your data regularly passes through clients that you have no control over, wiping out all the consistency you so carefully checked. Most of our code is spent tediously pulling unstructured data back into a structured form -- in other words, we don't get much benefit from static types.

But what also surprised me was how many parts of the framework used reflection. Now, all in all the parts using reflection are a tiny fraction of the whole Lift code, but the thing about reflection is it is very noticeable, because it deviates from how the language is supposed to behave. I have decided something: if you want to make Scala into a really great language, find all the places Lift uses reflection, and change the language so that reflection is no longer tempting in those cases.

Managing object lifetime

A rendering snippet like

  1  class FooSnippet extends StatefulSnippet {
  2      val p = S param "p" openOr ""
  3  
  4      def render = "p *" #> p
  5  }

gets instantiated per-request, and has access, when it is instantiated, to the request environment in S. I'm not sure if this one is really Scala's fault. It would have been as easy to do

  1  renderingRules.addStatefulRenderer("FooSnippet") { in =>
  2      val p = S param "p" openOr ""
  3      in |> { "p *" #> p }
  4  }

I guess what Lift is really going for using reflection here is it lets you split the rendering rules across multiple files.

But that's not so bad because it's just managing the lifetime of the whole object. What's really tricky is managing the lifetime of things inside the object...

  1  class Foo extends StatefulSnippet {
  2      object x extends SessionVar[Int](5)
  3  }

Now that's tricky. The data held by x has a longer lifetime than the apparently enclosing object Foo. The class name of x is used as a key to lookup the stored value.

It's not a bad solution, until you realize what would happen in some situations:

  1  (1 to 10) map {_ => new Foo}

Each of the created objects refers to the same session variable. Is this right? Well I don't know! It might be but it might not be and you have no control over it, because it's all done by magic.

So what's really going on here? We're trying to decouple object lifetime from object nestedness. The problem is that if you decouple object lifetime from object nestedness you don't have any more nestedness to play with, and you actually want some kind of nestedness because x's lifetime belongs to the session lifetime.

This seems to be a symptom of the general fact that it's nearly impossible to represent two, independent tree-like structures with the same set of syntax -- either the trees will be heavily tied or you will repeat yourself.

So assuming we can't fix the problem directly let's repeat ourselves.

  1  class Foo(x: Var[Int]) {
  2  }

Now Foo takes x in as an argument so the lifetime is decoupled. Unfortunately now the fact that we want x to live in the session has been erased, and it will end up being spread around:

  1  class Session {
  2      val fooX: Var[Int]
  3  }
  4  
  5  ...
  6  new Foo(currentSession.x)

to two different places neither of which are on Foo. If we had a way to declare extention variables we could do

  1  @extention(Session) val x: Var[Int]
  2  
  3  class Foo(implicit session: Session) {
  4  }

the implicit means that even though we have to pass in the particular session in use, it mostly happens automatically. It also provides a static way to tell which objects require sessions and which don't.

Unfortunately this has got us back to requiring that

  1  (1 to 10) map {_ => new Foo}

all refer to the same x. But what that's really saying is that all the constructed Foos are part of the same FooContainer:

  1  class FooContainer {
  2  
  3      @extention(Session) val x: Var[Int]
  4  
  5      class Foo(implicit session: Session) {
  6      }
  7  }

Now the lifetime of x is tied to the product of Session and FooContainer, which is exactly what we wanted, and gives us the flexibility to chose between

  1  val c = new FooContainer
  2  (1 to 10) map {_ => new c.Foo}

and

  1  (1 to 10) map {_ =>
  2      val c = new FooContainer
  3      new c.Foo
  4  }

Making code operate on multiple levels

It would be nice if

  1  <form>
  2      <p>{textField}</p>
  3      <p>{textField}</p>
  4  </form>

could be used to build up both the HTML and the information about the data it represents. The way it is now, this will necesarily produce a plain NodeSeq and the information that two Strings should be produced on submission has been lost.

This would actually be extremely easy to do using delimited continuations, except that Scala's delimited continuations don't have terribly good type inference, so you have to type too many types to make it worth it.

Splitting up the above code isn't such a bad idea, but transforming the language syntax in this way would be generally useful. I implemented something to do this using TemplateHaskell which I will post when I get around to it. It infers types perfectly, for a reason that actually has nothing to do with Haskell having better type inference that Scala. Basically if you do the desugaring before type-checking, you get a lot of the logic of the type-checker for free. The disadvantage is that error messages become unreadable, though I think that could be solved.

Thursday, August 25, 2011

How can I convince you this is a bad idea?

AHF hosts NJ protest & ‘die-in’ over J&J’s AIDS drug prices:

"Today, thanks to the high price of AIDS drugs like J&J’s Prezista, assistance programs like ADAP can no longer afford to help those who need access to lifesaving AIDS medicines,” said Michael Weinstein, AIDS Healthcare Foundation President.

Given that Johnson & Johnson sells this drug ‘at cost’ for a few hundred dollars per year in developing countries, it can lower prices significantly and still make a huge profit

From saveadap.org/adap.html:

AHF proposes that for every dollar of additional Federal funding drug companies contribute two dollars in additional rebates or price cuts.

Sounds good, right? But consider a few things.

1. J&J has no better ability to lower the price of these drugs than you do

"But I don't hold the patent!". So? Buy the drugs at J&J's price and sell them at a price you like better. "But I'd lose money." So would J&J. "No they won't; they'll still make a profit, just not as much." Exactly -- the profit that they can make if they charge as much as they can get away with -- that's a sunk cost. It doesn't feel like it, because the money hasn't changed hands yet. But it's reflected in the book value of the patent.

When J&J decides whether to lower the price of the drugs, their reasoning doesn't go "it will still be a profit, just not as much." They consider it to be a loss, because from their perspective they already got that value when the were granted the patent (or before that even).

I can see you're resisting this line of reasoning. It feels like accounting trickery. So let's dissect it further.

If J&J is specially able/obligated to make this sacrifice, what makes them different than you?

It's not a silly question. Seriously: what makes J&J different from you?

  1. They have more money.
  2. They hold the patent on Prezista.

Let's come back to (1) later and focus on (2) for now. Why do you want a group that holds a patent on a drug to be responsible for lowering its cost?

The answer, as far as I can tell, is that it serves as a rallying cry. Governments all over the US are suffering from impotence; none of them can seem to raise the money they need to accomplish the most basic functions of government. So, unable to get enough funding the peaceful way, AHF is taking taxation into their own hands.

It's a reasoning I thoroughly approve of: most of us live in such excessive comfort, we could stand to have a few dollars bullied out of us for our friends.

But then AHF faces a new problem: it's hard to bully corporations for money. If AHF were making the same demands of Microsoft, people would be like, WTF? So they went after the company that is most directly labeled as being connected to AIDS drugs.

The problem is, while I thoroughly approve of the intent, as a behavior, this is going to backfire. Here's how I would summarize the behavior:

What you did

You've got to understand that while you're focused on short-term gains, J&J is learning a few things from your actions: they're learning what it's like to be the guy who develops an AIDS drug. What do you think they're learning? And more importantly, when they decide what to spend research money on next year, what do you think is going to look appealing? J&J can make money on all kinds of drugs, most of which won't send people into a frenzy. They could quietly remove themselves from the debate. They could become just like you.

In other words, what separates J&J from you, is you didn't happen to develop an AIDS drug. And no one's giving you heat for that. Maybe they should. If Prezista didn't exist, what would it's price be? (There is an actual numerical answer to this. And the actions of AHF cause that number to go up).

Here's what your behavior should have looked like:

What you should do

The difference is in the arrow.

2. AIDS is going to be a problem for a long time

Here's a plot from Population Council showing projected AIDS deaths up to 2030:

Projected aids deaths

(Other sources for projected AIDS deaths)

I have tried to shade in the next 4-1/2 years, which should give President Palin time to fix the economy and make AHF's demands moot, as well as that part of the indefinite future that we can see on the plot. Note I can't show the entire indefinite future, because it would obscure anything else, and no one knows if and when AIDS will be cured / eradicated / the population becomes extinct through other means.

Still, even on this graph, which area is larger?

You might think it heartless to say that some people who are alive and living with aids today will have to die for the benefit of future generations. But I'm not saying that. Remember, you can solve this problem, if all it is is money. But if you solve this problem in a way that delays the discovery of an HIV vaccine, how do you think the big blue region will feel (before they die, that is)? And there's a lot more of those people.

3. We already have a neutral way to take money from people

It's called taxes. And as much as people hate it, it's the least disruptive, least judgmental way to compel people to put money to uses that don't directly benefit them. Importantly, it doesn't punish the guys who help you.

Taxes look iffy right now. Somehow no government seems able to convince voters they're worth it. Maybe the voters are right. Either way, it's a problem, and if you really wanted to make lives better for all the people government helps, you'd work on restoring governments' credibility. You could hold a die-in for that, too, if it's more fun that way.