<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7318253809178612591</id><updated>2012-01-23T00:01:40.611-08:00</updated><category term='googledocs'/><category term='mobile'/><category term='ruby'/><category term='helios'/><category term='plug-ins'/><category term='jdbc'/><category term='unit tests'/><category term='chromebook'/><category term='gtm'/><category term='sprint'/><category term='cocoa'/><category term='codepro'/><category term='objective-c'/><category term='iphone'/><category term='f#'/><category term='marketplace'/><category term='rails'/><category term='windows'/><category term='.net'/><category term='tmobile'/><category term='eclipse'/><category term='droid'/><category term='raid'/><category term='linux'/><category term='evo'/><category term='scala'/><category term='gdb'/><category term='mysql'/><category term='monotouch'/><category term='htc'/><category term='verizon'/><category term='google spreadsheets'/><category term='asm'/><category term='C#'/><category term='io2011'/><category term='bluetooth'/><category term='android'/><category term='xcode'/><category term='appengine'/><category term='irrelevant'/><category term='Éire'/><category term='wpf'/><category term='html'/><category term='nexus one'/><category term='f# fsi'/><category term='crickets'/><category term='emma'/><category term='att'/><category term='jruby'/><category term='proguard'/><category term='pde'/><category term='gmail'/><category term='googleappengine'/><title type='text'>James Moore's code blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.restphone.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>72</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2777204276117290639</id><published>2011-12-20T16:23:00.000-08:00</published><updated>2011-12-20T16:23:16.004-08:00</updated><title type='text'></title><content type='html'>Just posted a plugin to use JRuby from SBT. &amp;nbsp;Pretty limited right now, but potentially useful. &amp;nbsp;Available on &lt;a href="https://github.com/banshee/sbt-jruby"&gt;github as sbt-jruby&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2777204276117290639?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2777204276117290639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2777204276117290639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2777204276117290639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2777204276117290639'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/12/just-posted-plugin-to-use-jruby-from.html' title=''/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2120179687798232059</id><published>2011-10-26T16:35:00.001-07:00</published><updated>2011-10-26T16:35:07.109-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='chromebook'/><title type='text'>Brief review of gadgets from Google IO 2011, five months later</title><content type='html'>&lt;p&gt;At Google IO 2011, swag was received.&amp;#160; Two things really stand out:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.samsung.com/global/microsite/galaxytab/10.1/index.html" target="_blank"&gt;Samsung Galaxy Tab 10.1&lt;/a&gt;&amp;#160;&lt;strong&gt;This rocks.&lt;/strong&gt;&amp;#160; I use it constantly.&amp;#160; It’s a great dev device, too, since it’s really fast.&amp;#160; (That does require also using dev code on an el cheapo phone too – my choice for that are a couple Samsung Europas I bought in Ireland for E50.)&amp;#160; The only “problem” is that I have to compete with my wife for the device.&amp;#160; We’ve got a Fire on order that should solve that problem.&amp;#160; (I’d buy another Galaxy, but as a developer I feel like I need lots of new devices.&amp;#160; My wife laughs when she hears that.)&lt;/p&gt;  &lt;p&gt;Chromebook.&amp;#160; I can’t even be bothered to find a link to these things.&amp;#160; I tried to use it, but it’s slow and has a nasty screen.&amp;#160; Feels like an obsolete laptop I discarded a couple years ago.&amp;#160; I don’t even know where it is, and I realized I can’t even tell you how long it’s been missing.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2120179687798232059?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2120179687798232059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2120179687798232059' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2120179687798232059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2120179687798232059'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/10/brief-review-of-gadgets-from-google-io.html' title='Brief review of gadgets from Google IO 2011, five months later'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8070507460746486760</id><published>2011-09-25T12:36:00.001-07:00</published><updated>2011-09-25T12:37:49.974-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='asm'/><title type='text'>Using the jruby eclipse plugin to generate an interface implemention</title><content type='html'>I started using &lt;a href="http://asm.ow2.org/"&gt;asm&lt;/a&gt; to put together some ruby code generation scripts for the Eclipse plugin.&amp;nbsp; This one prints out a list of method definitions and their java signatures when you select an interface in the package explorer. If you select this interface&lt;br /&gt;
&lt;pre&gt;package com.restphone.jrubyeclipse;

import org.eclipse.jface.viewers.ISelection;

public interface IJrubyFilter {
  String do_filter(ISelection s);

  Integer someOtherMethod();
}&lt;/pre&gt;
You'll get this output: 

&lt;br /&gt;
&lt;pre&gt;java_signature "java.lang.String do_filter (org.eclipse.jface.viewers.ISelection a)"
def do_filter *args
end

java_signature "java.lang.Integer someOtherMethod ()"
def someOtherMethod *args
end&lt;/pre&gt;
Checked in to github as &lt;a href="https://github.com/banshee/JrubyEclipsePlugin/blob/master/jruby/ruby_filter_interface.rb"&gt;ruby_filter_interface.rb&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8070507460746486760?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8070507460746486760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8070507460746486760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8070507460746486760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8070507460746486760'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/09/using-jruby-eclipse-plugin-to-generate.html' title='Using the jruby eclipse plugin to generate an interface implemention'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-24198814201207370</id><published>2011-09-23T13:11:00.001-07:00</published><updated>2011-09-23T13:13:13.687-07:00</updated><title type='text'>More JRuby + asm</title><content type='html'>Turns out you can get this jruby from &lt;a href="http://blog.restphone.com/2011/09/jruby-asm-easy-processing-of-class.html"&gt;yesterday's post &lt;/a&gt;even more concise:&lt;br /&gt;
&lt;pre&gt;require 'java'
require 'asm-3.3.1'
require 'pp'

# This lets me type org.objectweb.asm::... instead of Java::OrgObjectwebAsm::...
def org
  Java::Org
end

class SampleVisitor
  include org.objectweb.asm::MethodVisitor
  include org.objectweb.asm::ClassVisitor
  include org.objectweb.asm::FieldVisitor
  include org.objectweb.asm::AnnotationVisitor
  include org.objectweb.asm.signature::SignatureVisitor

  def method_missing name, *args
    name_string = name.to_s
    if name_string =~ /visit.*/
      puts "#{name}\t#{args}"
      self
    else
      super
    end
  end
end

# Loop through each .class file given on the command line
ARGV.each do |classfile|
  puts " ---------------- Reading file #{classfile}"
  f = java.io.File.new classfile
  fis = java.io.FileInputStream.new f
  
  class_reader = org.objectweb.asm::ClassReader.new fis
  
  v = SampleVisitor.new
  
  class_reader.accept v, 0
  
  puts
end&lt;/pre&gt;
And the output is:&lt;br /&gt;
&lt;pre&gt;---------------- Reading file /Users/james/experimements/AsmSample/bin/com/restphone/classSignature/SampleOne.class
visit   [50, 33, "com/restphone/classSignature/SampleOne", nil, "java/lang/Object", #&amp;lt;#&amp;lt;Class:0x1144f3ba2&amp;gt;:0x2f6a23cf&amp;gt;]
visitSource     ["SampleOne.java", nil]
visitField      [9, "x", "Ljava/lang/Integer;", nil, nil]
visitEnd        []
visitMethod     [8, "&amp;lt;clinit&amp;gt;", "()V", nil, nil]
visitCode       []
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0x2b071e12&amp;gt;]
visitLineNumber [4, #&amp;lt;Java::OrgObjectwebAsm::Label:0x2b071e12&amp;gt;]
visitFieldInsn  [178, "com/restphone/classSignature/SampleTwo", "y", "Ljava/lang/Integer;"]
visitFieldInsn  [179, "com/restphone/classSignature/SampleOne", "x", "Ljava/lang/Integer;"]
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0x575c13ef&amp;gt;]
visitLineNumber [3, #&amp;lt;Java::OrgObjectwebAsm::Label:0x575c13ef&amp;gt;]
visitInsn       [177]
visitMaxs       [1, 0]
visitEnd        []
visitMethod     [1, "&amp;lt;init&amp;gt;", "()V", nil, nil]
visitCode       []
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0xc303a60&amp;gt;]
visitLineNumber [3, #&amp;lt;Java::OrgObjectwebAsm::Label:0xc303a60&amp;gt;]
visitVarInsn    [25, 0]
visitMethodInsn [183, "java/lang/Object", "&amp;lt;init&amp;gt;", "()V"]
visitInsn       [177]
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0x66869470&amp;gt;]
visitLocalVariable      ["this", "Lcom/restphone/classSignature/SampleOne;", nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0xc303a60&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x66869470&amp;gt;, 0]
visitMaxs       [1, 1]
visitEnd        []
visitMethod     [1, "doubleTheValue", "(Ljava/lang/Integer;)Ljava/lang/Integer;", nil, nil]
visitCode       []
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0x10fa706d&amp;gt;]
visitLineNumber [7, #&amp;lt;Java::OrgObjectwebAsm::Label:0x10fa706d&amp;gt;]
visitVarInsn    [25, 1]
visitMethodInsn [182, "java/lang/Integer", "intValue", "()I"]
visitInsn       [5]
visitInsn       [104]
visitMethodInsn [184, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"]
visitInsn       [176]
visitLabel      [#&amp;lt;Java::OrgObjectwebAsm::Label:0x629a99eb&amp;gt;]
visitLocalVariable      ["this", "Lcom/restphone/classSignature/SampleOne;", nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0x10fa706d&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x629a99eb&amp;gt;, 0]
visitLocalVariable      ["x", "Ljava/lang/Integer;", nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0x10fa706d&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x629a99eb&amp;gt;, 1]
visitMaxs       [2, 2]
visitEnd        []
visitEnd        []&lt;/pre&gt;
I'm including the jars on the command line:   &lt;br /&gt;
&lt;pre&gt;jruby -I /Users/james/experimements/AsmSample/libs --1.9 asm_support.rb /Users/james/experimements/AsmSample/bin/com/restphone/classSignature/SampleOne.class  | less&lt;/pre&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-24198814201207370?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/24198814201207370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=24198814201207370' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/24198814201207370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/24198814201207370'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/09/more-jruby-asm.html' title='More JRuby + asm'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2790425197773160330</id><published>2011-09-22T17:23:00.001-07:00</published><updated>2011-09-22T17:24:49.239-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>JRuby + Asm: easy processing of .class files</title><content type='html'>&lt;p&gt;I started working with &lt;a href="http://asm.ow2.org/"&gt;Asm&lt;/a&gt; this week.&amp;#160; After playing with it for a bit, it seemed obvious that JRuby would be a sweet spot for Asm code; very often, you need to implement only a small fraction of the interfaces that Asm uses.&lt;/p&gt;  &lt;p&gt;Here’s my first JRuby effort with Asm.&amp;#160; It’s straightforward and doesn’t do much yet – just outputs the contents of the .class files given on the command line.&amp;#160; Here’s the JRuby:&lt;/p&gt;  &lt;pre&gt;require 'java'
require 'asm-3.3.1'
require 'pp'

# This lets me type org.objectweb.asm::... instead of Java::OrgObjectwebAsm::...
def org
  Java::Org
end

# This lets me use ClassReader without typing out org.objectweb.asm::ClassReader
java_import org.objectweb.asm::ClassReader

# Ruby supports mixins.  Both visitor classes (class and method) use this method_missing
# call.
#
# The generic visitor just prints information for any call to a visitor* method.
module GenericVisitor
  def method_missing *args
    if args.first.to_s =~ /visit.*/
      puts &amp;quot;In type: #{self.class} call to &amp;quot; + args.to_s
    else
      super
    end
  end
end

class SampleMethodVisitor
  include org.objectweb.asm::MethodVisitor
  include GenericVisitor
end

class SampleClassVisitor
  include org.objectweb.asm::ClassVisitor
  include GenericVisitor
  
  # we need to keep a copy of our method visitor
  def initialize args
    @method_visitor = args[:method_visitor]
  end
  
  def visit_method *args
    # The output has methods seperated with an easy-to-see string
    puts &amp;quot;visit method &amp;quot; + args.to_s + &amp;quot;================================&amp;quot;
      
    # Asm wants ClassVisitor#visitMethod to return a method visitor 
    @method_visitor
  end
end

# Loop through each .class file given on the command line
ARGV.each do |classfile|
  puts &amp;quot; ---------------- Reading file #{classfile}&amp;quot;
  f = java.io.File.new classfile
  fis = java.io.FileInputStream.new f
  
  class_reader = ClassReader.new fis
  
  v = SampleClassVisitor.new method_visitor: SampleMethodVisitor.new
  
  class_reader.accept v, 0
  
  puts
end&lt;/pre&gt;

&lt;p&gt;And here’s the output:&lt;/p&gt;

&lt;pre&gt;---------------- Reading file /Users/james/experimements/AsmSample/bin/com/restphone/classSignature/SampleOne.class
In type: SampleClassVisitor call to [:visit, 50, 33, &amp;quot;com/restphone/classSignature/SampleOne&amp;quot;, nil, &amp;quot;java/lang/Object&amp;quot;, #&amp;lt;#&amp;lt;Class:0x12690ed81&amp;gt;:0x28b53b32&amp;gt;]
In type: SampleClassVisitor call to [:visitSource, &amp;quot;SampleOne.java&amp;quot;, nil]
In type: SampleClassVisitor call to [:visitField, 9, &amp;quot;x&amp;quot;, &amp;quot;Ljava/lang/Integer;&amp;quot;, nil, nil]
visit method [8, &amp;quot;&amp;lt;clinit&amp;gt;&amp;quot;, &amp;quot;()V&amp;quot;, nil, nil]================================
In type: SampleMethodVisitor call to [:visitCode]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x236954e1&amp;gt;]
In type: SampleMethodVisitor call to [:visitLineNumber, 4, #&amp;lt;Java::OrgObjectwebAsm::Label:0x236954e1&amp;gt;]
In type: SampleMethodVisitor call to [:visitFieldInsn, 178, &amp;quot;com/restphone/classSignature/SampleTwo&amp;quot;, &amp;quot;y&amp;quot;, &amp;quot;Ljava/lang/Integer;&amp;quot;]
In type: SampleMethodVisitor call to [:visitFieldInsn, 179, &amp;quot;com/restphone/classSignature/SampleOne&amp;quot;, &amp;quot;x&amp;quot;, &amp;quot;Ljava/lang/Integer;&amp;quot;]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x643f58bb&amp;gt;]
In type: SampleMethodVisitor call to [:visitLineNumber, 3, #&amp;lt;Java::OrgObjectwebAsm::Label:0x643f58bb&amp;gt;]
In type: SampleMethodVisitor call to [:visitInsn, 177]
In type: SampleMethodVisitor call to [:visitMaxs, 1, 0]
In type: SampleMethodVisitor call to [:visitEnd]
visit method [1, &amp;quot;&amp;lt;init&amp;gt;&amp;quot;, &amp;quot;()V&amp;quot;, nil, nil]================================
In type: SampleMethodVisitor call to [:visitCode]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x1d7aaa0e&amp;gt;]
In type: SampleMethodVisitor call to [:visitLineNumber, 3, #&amp;lt;Java::OrgObjectwebAsm::Label:0x1d7aaa0e&amp;gt;]
In type: SampleMethodVisitor call to [:visitVarInsn, 25, 0]
In type: SampleMethodVisitor call to [:visitMethodInsn, 183, &amp;quot;java/lang/Object&amp;quot;, &amp;quot;&amp;lt;init&amp;gt;&amp;quot;, &amp;quot;()V&amp;quot;]
In type: SampleMethodVisitor call to [:visitInsn, 177]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x13ad9b0f&amp;gt;]
In type: SampleMethodVisitor call to [:visitLocalVariable, &amp;quot;this&amp;quot;, &amp;quot;Lcom/restphone/classSignature/SampleOne;&amp;quot;, nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0x1d7aaa0e&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x13ad9b0f&amp;gt;, 0]
In type: SampleMethodVisitor call to [:visitMaxs, 1, 1]
In type: SampleMethodVisitor call to [:visitEnd]
visit method [1, &amp;quot;doubleTheValue&amp;quot;, &amp;quot;(Ljava/lang/Integer;)Ljava/lang/Integer;&amp;quot;, nil, nil]================================
In type: SampleMethodVisitor call to [:visitCode]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x9eae15f&amp;gt;]
In type: SampleMethodVisitor call to [:visitLineNumber, 7, #&amp;lt;Java::OrgObjectwebAsm::Label:0x9eae15f&amp;gt;]
In type: SampleMethodVisitor call to [:visitVarInsn, 25, 1]
In type: SampleMethodVisitor call to [:visitMethodInsn, 182, &amp;quot;java/lang/Integer&amp;quot;, &amp;quot;intValue&amp;quot;, &amp;quot;()I&amp;quot;]
In type: SampleMethodVisitor call to [:visitInsn, 5]
In type: SampleMethodVisitor call to [:visitInsn, 104]
In type: SampleMethodVisitor call to [:visitMethodInsn, 184, &amp;quot;java/lang/Integer&amp;quot;, &amp;quot;valueOf&amp;quot;, &amp;quot;(I)Ljava/lang/Integer;&amp;quot;]
In type: SampleMethodVisitor call to [:visitInsn, 176]
In type: SampleMethodVisitor call to [:visitLabel, #&amp;lt;Java::OrgObjectwebAsm::Label:0x2569a1c5&amp;gt;]
In type: SampleMethodVisitor call to [:visitLocalVariable, &amp;quot;this&amp;quot;, &amp;quot;Lcom/restphone/classSignature/SampleOne;&amp;quot;, nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0x9eae15f&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x2569a1c5&amp;gt;, 0]
In type: SampleMethodVisitor call to [:visitLocalVariable, &amp;quot;x&amp;quot;, &amp;quot;Ljava/lang/Integer;&amp;quot;, nil, #&amp;lt;Java::OrgObjectwebAsm::Label:0x9eae15f&amp;gt;, #&amp;lt;Java::OrgObjectwebAsm::Label:0x2569a1c5&amp;gt;, 1]
In type: SampleMethodVisitor call to [:visitMaxs, 2, 2]
In type: SampleMethodVisitor call to [:visitEnd]
In type: SampleClassVisitor call to [:visitEnd]&lt;/pre&gt;

&lt;p&gt;Incidentally, I used my new Eclipse plugin to send the current selection through a filter to html-escape the text.&amp;#160; Check it out on &lt;a href="https://github.com/banshee/JrubyEclipsePlugin"&gt;github&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2790425197773160330?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2790425197773160330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2790425197773160330' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2790425197773160330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2790425197773160330'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/09/jruby-asm-easy-processing-of-class.html' title='JRuby + Asm: easy processing of .class files'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-1834603229227184081</id><published>2011-08-23T14:45:00.000-07:00</published><updated>2011-08-23T14:45:53.493-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Éire'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Mobile market in Ireland - Android and iPhone</title><content type='html'>I'm on vacation in Ireland right now, and the mobile market here is interesting and different.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
First, unlike Seattle where every other storefront sells coffee, in Ireland every other shop is a mobile phone operator. &amp;nbsp;They're everywhere.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
And the really big difference is prepaid. &amp;nbsp;I picked up a Samsung Europa for €49, no contract. &amp;nbsp;"Locked" to 3, but only if you're not capable of searching "unlock" on google. &amp;nbsp;(Yes, the number 3 is an Irish telecom company.) &amp;nbsp;For €20, the "topup" includes unlimited data for a month, unlimited 3-3 calling/texting, &amp;nbsp;and 29c/minute out of network, free on weekends. &amp;nbsp;Every tiny little shop in the country sells minutes, too, so it's trivial to buy more.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If I lived here and had even a tiny bit of patience, that same Europa goes for €39 delivered. &amp;nbsp;(And they sell for more than that on ebay. &amp;nbsp;My wife said we're on vacation, and I'm not supposed to pack 200 of them in my suitcase to resell at a profit. &amp;nbsp;Shame. &amp;nbsp;I did point this out to the young guy in the 3 shop though, and he looked thoughtful.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
It's an Android 2.2 device. &amp;nbsp;It's not great (no multitouch, small screen, slow compared to my wife's Nexus One), but it's OK.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The iPhone is a nice chunk of hardware, but it's €569 - TEN TIMES the price of an Android phone. &amp;nbsp;Yes, you can get it for free on a contract, but it's a middle-class extravagance. &amp;nbsp;If you think you might be worried about cash next month, I don't see how you buy one.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I had no idea how much cheaper Android phones were over here. &amp;nbsp;I'm not seeing a whole lot of iPhones; it's not like home.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;a href="http://www.three.ie/shop/products/samsung-europa-black.html?_selectedTariff=prepay&amp;amp;_defaultPriceplan=9&amp;amp;utm_source=internal&amp;amp;utm_medium=banner&amp;amp;utm_campaign=homepage-hero-prepay-campaign"&gt;Here's the 3 deal&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Oh, and if you do bring an unlocked Android GSM phone with you, they'll tell you the unlimited data for €20 plan doesn't work for tethering. &amp;nbsp;Works great, though.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-1834603229227184081?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/1834603229227184081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=1834603229227184081' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1834603229227184081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1834603229227184081'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/08/mobile-market-in-ireland-android-and.html' title='Mobile market in Ireland - Android and iPhone'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7406664986256239415</id><published>2011-07-26T05:59:00.000-07:00</published><updated>2011-07-26T05:59:42.861-07:00</updated><title type='text'>Guice, servlets, and GWT cheatsheets</title><content type='html'>&lt;a href="https://docs.google.com/document/pub?id=1JfUN4C7yj7NL9jJwBwwoCKx0SmWjAhJHqJN6PJmI75E"&gt;Guice servlet cheatsheet&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://docs.google.com/document/pub?id=1Lz7q5LfOD6lBo9D3U6d55PSxh_uGbn4W6dZjqOfwGZ4"&gt;GWT rpc cheatsheet&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://docs.google.com/document/pub?id=1JfUN4C7yj7NL9jJwBwwoCKx0SmWjAhJHqJN6PJmI75E"&gt;Guice cheatsheet&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7406664986256239415?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7406664986256239415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7406664986256239415' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7406664986256239415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7406664986256239415'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/07/guice-servlets-and-gwt-cheatsheets.html' title='Guice, servlets, and GWT cheatsheets'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6354402205900050931</id><published>2011-05-28T19:38:00.001-07:00</published><updated>2011-05-28T21:05:19.305-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='googledocs'/><category scheme='http://www.blogger.com/atom/ns#' term='google spreadsheets'/><title type='text'>Very simple Google Spreadsheet code</title><content type='html'>&lt;p&gt;I wanted to use data from a google docs spreadsheet in a project, and the sample code all talks about how to authenticate and get lists of documents for a user.&lt;/p&gt;  &lt;p&gt;In my case, I already had a public document that I wanted to read.&amp;#160; &lt;/p&gt;  &lt;p&gt;You’ll want to read the doc &lt;a href="http://code.google.com/apis/spreadsheets/data/3.0/developers_guide.html" target="_blank"&gt;here&lt;/a&gt; first, but there were two gaps.&amp;#160; &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;It wasn’t straightforward (at least for me) to figure out exactly what the URL for a public spreadsheet should be (the doc concentrates on private documents, and assumes you’re going to be iterating through a list of available spreadsheets, not going straight to a specific one). &lt;/li&gt;    &lt;li&gt;It wasn’t clear which Java classes mapped to the URLs I had. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So here’s a very simple sample, reading data from &lt;a href="https://spreadsheets.google.com/spreadsheet/ccc?key=0AsaDhyyXNaFSdDJ2VUxtVGVWN1Yza1loU1RPVVU3OFE&amp;amp;hl=en_US&amp;amp;authkey=CLXm3-ML" target="_blank"&gt;this public spreadsheet&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;iframe style="width: 500px; height: 174px" height="140" src="https://spreadsheets0.google.com/spreadsheet/pub?hl=en_US&amp;amp;hl=en_US&amp;amp;key=0AsaDhyyXNaFSdDJ2VUxtVGVWN1Yza1loU1RPVVU3OFE&amp;amp;single=true&amp;amp;gid=0&amp;amp;output=html&amp;amp;widget=true" frameborder="0" width="500"&gt;&lt;/iframe&gt;&lt;/p&gt;  &lt;p&gt;The output:&lt;/p&gt;  &lt;pre&gt;One
1
Two
2
Three
3&lt;/pre&gt;

&lt;p&gt;The code:&lt;/p&gt;



&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:b9f9b760-806d-421e-8961-1dd2d6554616" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: java; gutter: true; first-line: 1; tab-size: 4;  toolbar: false;  width: 829px; height: 450px;" style=" width: 829px; height: 450px;overflow: auto;"&gt;package com.banshee;

import java.io.IOException;
import java.net.URL;

import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.CustomElementCollection;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.util.ServiceException;

public class SpreadsheetSucker {
  public static void main(String[] args) {
    SpreadsheetService service = new SpreadsheetService(&amp;quot;com.banshee&amp;quot;);
    try {
      // Notice that the url ends
      // with default/public/values.
      // That wasn't obvious (at least to me)
      // from the documentation.
      String urlString = &amp;quot;https://spreadsheets.google.com/feeds/list/0AsaDhyyXNaFSdDJ2VUxtVGVWN1Yza1loU1RPVVU3OFE/default/public/values&amp;quot;;

      // turn the string into a URL
      URL url = new URL(urlString);

      // You could substitute a cell feed here in place of
      // the list feed
      ListFeed feed = service.getFeed(url, ListFeed.class);

      for (ListEntry entry : feed.getEntries()) {
        CustomElementCollection elements = entry.getCustomElements();
        String name = elements.getValue(&amp;quot;name&amp;quot;);
        System.out.println(name);
        String number = elements.getValue(&amp;quot;Number&amp;quot;);
        System.out.println(number);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ServiceException e) {
      e.printStackTrace();
    }

  }
}
&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6354402205900050931?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6354402205900050931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6354402205900050931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6354402205900050931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6354402205900050931'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/05/very-simple-google-spreadsheet-code.html' title='Very simple Google Spreadsheet code'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3963911583714683528</id><published>2011-05-16T10:34:00.000-07:00</published><updated>2011-05-16T10:34:35.337-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='marketplace'/><category scheme='http://www.blogger.com/atom/ns#' term='io2011'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Notes on Android Market for Developers session at Google I/O 2011</title><content type='html'>&lt;br /&gt;
&lt;div style="background-color: transparent;"&gt;
&lt;span class="Apple-style-span" style="font-family: Arial;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;b&gt;&lt;div style="background-color: transparent; font-family: Times; font-size: medium; font-weight: normal; white-space: normal;"&gt;
&lt;span id="internal-source-marker_0.17747384123504162" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Notes on Android Market for Developers session at Google I/O 2011&lt;/span&gt;&lt;br /&gt;&lt;h1&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;(For Google I/O Show and Tell http://www.meetup.com/seattle-gtug/events/16361982/)&lt;/span&gt;&lt;/h1&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; - James Moore, james@restphone.com&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Session video is up at &lt;/span&gt;&lt;a href="http://www.google.com/events/io/2011/sessions/android-market-for-developers.html"&gt;&lt;span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;http://www.google.com/events/io/2011/sessions/android-market-for-developers.html&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;img height="398px;" src="https://lh6.googleusercontent.com/LRyn7zQAW3uxxaKlsQAFC9Cz2bgJ-oNSdmu3mhJZFYJ_aeIEjm-IbRaEOF8_aeYeRbdDosq3nEkxk-ZABDzfl4ICI8f_KNccC7IWOAz1WKNgmquGdmE" width="397px;" /&gt;&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Growth&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;400k activations/day for Android devices worldwide&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;60% of activiations are outside USA&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;He emphasized Korea and Japan&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Up from 100k/day YOY&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;App installs &lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;8x from 2009 -&amp;gt; 2010&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;2011 as of today is slightly more than all of 2010&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Charts around 3:08 in video&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Apps are used by Gingerbread and Honeycomb&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;New device users == heavy consumers of applications&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;graph at 6:30&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Recent installs of apps (trending categories)&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Games&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Entertainment&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Tools&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Media&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Travel and local&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Transportation&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Trending Paid apps categories (8:46)&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Games&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Tools&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Personalization&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Productivity&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Entertainment&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Medical&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Comics&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Shopping&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;New OS versions are most of the app downloads 10:32&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;They see two versions of Android dominant over time (the two change as new releases come out)&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Today&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;25% 2.1&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;75% 2.2&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;a href="http://developer.android.com/"&gt;&lt;span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;developer.android.com&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; has lots of numbers for things like versions, screensizes&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Major vendors committed to 18 month upgrade guarantees, announced at IO2011&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Quick demos of (14:49)&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Pulse News&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Angry Birds&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Gun Brothers&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Talked about approaches to OS version dependencies&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;90% of Android devices hitting the market have OpenGS 2.0&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;New market tools offer better targeting&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Devices, geography, screensize, etc&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Coming soon&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Multiple apks (23:01) in June&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;One app listing&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Different screen sizes, etc&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Multiple apks&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Aggregates billing, rating, comments&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Large apks 24:23&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;4GB total&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: square; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;50 meg apk plus 2 x 2GB bundles downloaded separtelly&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;One-click integration with AdMob, already launched&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Lots of new lists on Marketplace&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Trending&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Lists by market&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Better ways to show all apps from a developer&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Direct carrier billing is 50% of app sales at one (unnamed) US carrier&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;In-app upgrades are working really well&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;These notes are up at &lt;/span&gt;&lt;a href="https://docs.google.com/document/pub?id=1mWJAHkFcP_C91opc9bOKowHye3BgMwk2G-92Mia-MUA"&gt;&lt;span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;https://docs.google.com/document/pub?id=1mWJAHkFcP_C91opc9bOKowHye3BgMwk2G-92Mia-MUA&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;img height="398px;" src="https://lh3.googleusercontent.com/qQ6aiqcTBkJjMTZT3RjwU-uIHoFX43z77a_O8qCyf3pujmCi82eork2S59x37u5pglhRyaFSIcKARwsgVH8AUGQR5Pwz1lKt1LNtpHogUX1qoI1xn2c" width="398px;" /&gt;&lt;/div&gt;
&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3963911583714683528?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3963911583714683528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3963911583714683528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3963911583714683528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3963911583714683528'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/05/notes-on-android-market-for-developers.html' title='Notes on Android Market for Developers session at Google I/O 2011'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total><georss:featurename>Seattle, WA, USA</georss:featurename><georss:point>47.6062095 -122.3320708</georss:point><georss:box>47.485093 -122.4497023 47.727326 -122.2144393</georss:box></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-1763339723521010514</id><published>2011-05-03T12:32:00.000-07:00</published><updated>2011-05-03T12:32:38.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='codepro'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='emma'/><title type='text'>Android error: java.lang.Error: packaging failure: closure resource not found</title><content type='html'>If you're seeing errors like this when you start your Android application:
&lt;script src="https://gist.github.com/953947.js?file=gistfile1.txt"&gt;
&lt;/script&gt;
You've compiled with CodePro coverage enabled.  Turn it off.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-1763339723521010514?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/1763339723521010514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=1763339723521010514' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1763339723521010514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1763339723521010514'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/05/if-youre-seeing-errors-like-this-when.html' title='Android error: java.lang.Error: packaging failure: closure resource not found'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8873156424961700938</id><published>2011-04-21T15:12:00.000-07:00</published><updated>2011-04-21T15:13:30.856-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>App Engine debug project gets java.lang.NoSuchMethodError: org.mortbay.thread.Timeout</title><content type='html'>I see this error sometimes when I'm starting my Google App Engine / GWT project:

&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Exception in thread "main" java.lang.NoSuchMethodError: org.mortbay.thread.Timeout.&lt;init&gt;(Ljava/lang/Object;)V
 at org.mortbay.io.nio.SelectorManager$SelectSet.&lt;init&gt;(SelectorManager.java:306)
 at org.mortbay.io.nio.SelectorManager.doStart(SelectorManager.java:223)
 at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
 at org.mortbay.jetty.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:303)
 at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
 at org.mortbay.jetty.Server.doStart(Server.java:233)
 at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
 at com.google.gwt.dev.shell.jetty.JettyLauncher.start(JettyLauncher.java:565)
 at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:494)
 at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1058)
 at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:800)
 at com.google.gwt.dev.DevMode.main(DevMode.java:304)
&lt;/pre&gt;
&lt;br /&gt;
The simple fix is to reset the SDK for App Engine, under Properties &amp;gt; Google &amp;gt; App Engine. &amp;nbsp;Change it to something other than your current SDK, then change it back. &amp;nbsp;This doesn't happen often enough for me to figure out what the real fix might be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8873156424961700938?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8873156424961700938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8873156424961700938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8873156424961700938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8873156424961700938'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/04/app-engine-debug-project-gets.html' title='App Engine debug project gets java.lang.NoSuchMethodError: org.mortbay.thread.Timeout'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7965342034839432998</id><published>2011-03-29T06:03:00.000-07:00</published><updated>2011-03-29T06:03:30.508-07:00</updated><title type='text'>Why do we never use "spissitude" to describe software?</title><content type='html'>It's perfect! &lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.worldwidewords.org/weirdwords/ww-spi2.htm"&gt;In brief, the spissitude of a material is its density, thickness or compactness.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I had never heard it before seeing the reference &lt;a href="http://www.nakedcapitalism.com/2011/03/william-hogeland-how-john-adams-and-thomas-paine-clashed-over-economic-equality.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7965342034839432998?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7965342034839432998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7965342034839432998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7965342034839432998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7965342034839432998'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/03/why-do-we-never-use-spissitude-to.html' title='Why do we never use &quot;spissitude&quot; to describe software?'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6013868500880319966</id><published>2011-03-28T19:14:00.000-07:00</published><updated>2011-03-28T19:14:21.997-07:00</updated><title type='text'>I have an official radio phone number!</title><content type='html'>According to &lt;a href="http://ourwebhome.com/TENP/Recommended.html"&gt;Ma Bell's Officially Recommended Exchange Names&lt;/a&gt;, my cell phone number is "reserved for radio telephone numbers."&lt;br /&gt;
&lt;br /&gt;
Found this through a comment on&amp;nbsp;&lt;a href="http://thedailywtf.com/Articles/No-Letters-Allowed!.aspx"&gt;thedailywtf&lt;/a&gt;. &amp;nbsp;Hilarious.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6013868500880319966?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6013868500880319966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6013868500880319966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6013868500880319966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6013868500880319966'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/03/i-have-official-radio-phone-number.html' title='I have an official radio phone number!'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8697743022270953129</id><published>2011-03-24T15:17:00.001-07:00</published><updated>2011-03-24T15:26:08.701-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Bookstands for holding dev devices</title><content type='html'>&lt;p&gt;I’ve just had my dev devices lying on the desk, but I decided I wanted something to hold them up.&amp;#160; Ordered a couple from Amazon.&lt;/p&gt;  &lt;p&gt;I ordered the &lt;a href="http://www.amazon.com/gp/product/B00006B8MU" target="_blank"&gt;Insight&lt;/a&gt; and the Fellows.&amp;#160; I’m using the Insight regularly.&amp;#160; For iPhones, it’s got a nice slot in the back to slip the cable through.&amp;#160; I’m using a Droid as my regular Android dev device, and it’s connector is on the side, so no issues there.&amp;#160; Haven’t tried the Evo yet.&amp;#160; &lt;/p&gt;  &lt;p&gt;For the iPhone, it’s not quite stable with the cable plugged in, so I just wrapped a rubber band around it.&amp;#160; Not exactly high design, but works fine.&lt;/p&gt;  &lt;p&gt;Both of these are cheap; &amp;lt; $10.&lt;/p&gt;  &lt;p&gt;I also ordered a &lt;a href="http://www.amazon.com/gp/product/B000VRLX9Y" target="_blank"&gt;Gorillapod&lt;/a&gt;, but it’s not stable enough when you’re punching stuff on the screen.&amp;#160; I liked it enough to keep it, though, just for its intended use (camera tripod).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/B00006B8MU" target="_blank"&gt;Insight&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_3USHh0OQON0/TYvCvMHs30I/AAAAAAAAAUs/JOO94tnwNQE/s1600-h/P1010709%5B5%5D.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="P1010709" border="0" alt="P1010709" src="http://lh4.ggpht.com/_3USHh0OQON0/TYvCxPOMFjI/AAAAAAAAAUw/mWYLoBHrrmE/P1010709_thumb%5B2%5D.jpg?imgmax=800" width="574" height="450" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_3USHh0OQON0/TYvCzB401TI/AAAAAAAAAU0/XAD4uusxxv0/s1600-h/P1010708%5B5%5D.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="P1010708" border="0" alt="P1010708" src="http://lh5.ggpht.com/_3USHh0OQON0/TYvC1KS1ydI/AAAAAAAAAU4/eWD04tkr8hA/P1010708_thumb%5B2%5D.jpg?imgmax=800" width="574" height="446" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/B00004Z5QI" target="_blank"&gt;Fellows&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_3USHh0OQON0/TYvC3ef3DwI/AAAAAAAAAU8/NZWRQiGM8wI/s1600-h/P1010707%5B5%5D.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="P1010707" border="0" alt="P1010707" src="http://lh5.ggpht.com/_3USHh0OQON0/TYvC5uqTKZI/AAAAAAAAAVA/LM4huCctxUQ/P1010707_thumb%5B2%5D.jpg?imgmax=800" width="574" height="446" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8697743022270953129?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8697743022270953129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8697743022270953129' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8697743022270953129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8697743022270953129'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/03/bookstands-for-holding-dev-devices.html' title='Bookstands for holding dev devices'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_3USHh0OQON0/TYvCxPOMFjI/AAAAAAAAAUw/mWYLoBHrrmE/s72-c/P1010709_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3353416562930828180</id><published>2011-01-16T15:04:00.001-08:00</published><updated>2011-01-16T15:04:55.032-08:00</updated><title type='text'>James and Allison at La Perouse</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt;&lt;a href="http://www.flickr.com/photos/27305166@N02/5361313959/" title="photo sharing"&gt;&lt;img src="http://farm6.static.flickr.com/5201/5361313959_5215e347fb_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/27305166@N02/5361313959/"&gt;James and Allison at La Perouse&lt;/a&gt;&lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/27305166@N02/"&gt;james_in_pacific_beach&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;Having a great time on Maui.  Writing lots of code.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3353416562930828180?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3353416562930828180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3353416562930828180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3353416562930828180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3353416562930828180'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2011/01/james-and-allison-at-la-perouse.html' title='James and Allison at La Perouse'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm6.static.flickr.com/5201/5361313959_5215e347fb_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-1333738741301624145</id><published>2010-08-17T22:14:00.000-07:00</published><updated>2010-08-17T22:15:06.561-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='helios'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Problem with Eclipse/Android/Helios/XML editing</title><content type='html'>If you're seeing errors like this in Eclipse/Helios when you're editing an Android resource file, you're hitting &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=318108"&gt;this Eclipse bug&lt;/a&gt;.&amp;nbsp; The workaround is to go to Preferences &amp;gt; XML &amp;gt; XML Files &amp;gt; Editor and turn off Use inferred grammar in absense of DTD/Schema.&lt;br /&gt;
&lt;blockquote&gt;
Problems occurred when invoking code from plug-in: "org.eclipse.jface".&lt;/blockquote&gt;
&lt;br /&gt;
&lt;blockquote&gt;
java.lang.NullPointerException&lt;br /&gt;
at org.eclipse.wst.xml.core.internal.document.ElementImpl.getDefaultValue(ElementImpl.java:259)&lt;br /&gt;
at org.eclipse.wst.xml.core.internal.document.ElementImpl.getAttributeNS(ElementImpl.java:329)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode.getShortDescription(Unknown Source)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiModelTreeLabelProvider.getText(Unknown Source)&lt;br /&gt;
at org.eclipse.jface.viewers.WrappedViewerLabelProvider.getText(WrappedViewerLabelProvider.java:108)&lt;br /&gt;
at org.eclipse.jface.viewers.WrappedViewerLabelProvider.update(WrappedViewerLabelProvider.java:164)&lt;br /&gt;
at org.eclipse.jface.viewers.ViewerColumn.refresh(ViewerColumn.java:152)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:934)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer$UpdateItemSafeRunnable.run(AbstractTreeViewer.java:102)&lt;br /&gt;
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)&lt;br /&gt;
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)&lt;br /&gt;
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:1014)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable.run(StructuredViewer.java:481)&lt;br /&gt;
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)&lt;br /&gt;
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)&lt;br /&gt;
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.updateItem(StructuredViewer.java:2141)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.updateChildren(AbstractTreeViewer.java:2689)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefreshStruct(AbstractTreeViewer.java:1867)&lt;br /&gt;
at org.eclipse.jface.viewers.TreeViewer.internalRefreshStruct(TreeViewer.java:721)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1842)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1799)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1785)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer$7.run(StructuredViewer.java:1487)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1422)&lt;br /&gt;
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:403)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1383)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1485)&lt;br /&gt;
at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:537)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1444)&lt;br /&gt;
at org.eclipse.jface.viewers.ContentViewer.setContentProvider(ContentViewer.java:252)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.setContentProvider(StructuredViewer.java:1641)&lt;br /&gt;
at org.eclipse.jface.viewers.AbstractTreeViewer.setContentProvider(AbstractTreeViewer.java:2317)&lt;br /&gt;
at org.eclipse.jface.viewers.TreeViewer.setContentProvider(TreeViewer.java:972)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.changeRootAndDescriptors(Unknown Source)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.createTreeViewer(Unknown Source)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.createMasterPart(Unknown Source)&lt;br /&gt;
at org.eclipse.ui.forms.MasterDetailsBlock.createContent(MasterDetailsBlock.java:161)&lt;br /&gt;
at org.eclipse.ui.forms.MasterDetailsBlock.createContent(MasterDetailsBlock.java:142)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.resources.ResourcesTreePage.createFormContent(Unknown Source)&lt;br /&gt;
at org.eclipse.ui.forms.editor.FormPage$1.run(FormPage.java:152)&lt;br /&gt;
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)&lt;br /&gt;
at org.eclipse.ui.forms.editor.FormPage.createPartControl(FormPage.java:150)&lt;br /&gt;
at org.eclipse.ui.forms.editor.FormEditor.pageChange(FormEditor.java:471)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.pageChange(Unknown Source)&lt;br /&gt;
at org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1067)&lt;br /&gt;
at org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:603)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.selectDefaultPage(Unknown Source)&lt;br /&gt;
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.addPages(Unknown Source)&lt;br /&gt;
at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138)&lt;br /&gt;
at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348)&lt;br /&gt;
at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670)&lt;br /&gt;
at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)&lt;br /&gt;
at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2863)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2768)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2760)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2711)&lt;br /&gt;
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2707)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2691)&lt;br /&gt;
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2682)&lt;br /&gt;
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651)&lt;br /&gt;
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610)&lt;br /&gt;
at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:365)&lt;br /&gt;
at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:168)&lt;br /&gt;
at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:229)&lt;br /&gt;
at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:208)&lt;br /&gt;
at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:274)&lt;br /&gt;
at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:250)&lt;br /&gt;
at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:373)&lt;br /&gt;
at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:526)&lt;br /&gt;
at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:845)&lt;br /&gt;
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)&lt;br /&gt;
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)&lt;br /&gt;
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:843)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1131)&lt;br /&gt;
at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1235)&lt;br /&gt;
at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:264)&lt;br /&gt;
at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:258)&lt;br /&gt;
at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:298)&lt;br /&gt;
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)&lt;br /&gt;
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3776)&lt;br /&gt;
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1367)&lt;br /&gt;
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1390)&lt;br /&gt;
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)&lt;br /&gt;
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1187)&lt;br /&gt;
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3622)&lt;br /&gt;
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3277)&lt;br /&gt;
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)&lt;br /&gt;
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)&lt;br /&gt;
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)&lt;br /&gt;
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)&lt;br /&gt;
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)&lt;br /&gt;
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)&lt;br /&gt;
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)&lt;br /&gt;
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)&lt;br /&gt;
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)&lt;br /&gt;
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)&lt;br /&gt;
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)&lt;br /&gt;
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)&lt;br /&gt;
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)&lt;br /&gt;
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br /&gt;
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)&lt;br /&gt;
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)&lt;br /&gt;
at java.lang.reflect.Method.invoke(Method.java:597)&lt;br /&gt;
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)&lt;br /&gt;
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)&lt;br /&gt;
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)&lt;/blockquote&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-1333738741301624145?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/1333738741301624145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=1333738741301624145' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1333738741301624145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1333738741301624145'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/08/problem-with-androidheliosxml-editing.html' title='Problem with Eclipse/Android/Helios/XML editing'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6797863188358885511</id><published>2010-06-29T22:55:00.000-07:00</published><updated>2010-06-29T22:55:57.322-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='proguard'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>A proguard builder for Scala + Android</title><content type='html'>I just put up code for an Eclipse builder to make it simpler to build Scala projects for Android.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/banshee/AndroidProguardScala"&gt;http://github.com/banshee/AndroidProguardScala&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
It's still pretty rough, but it gets the job done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6797863188358885511?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6797863188358885511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6797863188358885511' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6797863188358885511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6797863188358885511'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/06/proguard-builder-for-scala-android.html' title='A proguard builder for Scala + Android'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-1345666836800165752</id><published>2010-06-19T11:34:00.001-07:00</published><updated>2010-06-19T11:37:02.714-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pde'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='plug-ins'/><title type='text'>Eclipse plug-ins not showing suggested templates</title><content type='html'>If you’re new to developing Eclipse templates, and you’re wondering why you’re not seeing a list of templates when you create your new project, make sure you check “This plug-in will make contributions to the UI” in this dialog: &lt;br /&gt;
&lt;a href="http://lh4.ggpht.com/_3USHh0OQON0/TB0NvMICy8I/AAAAAAAAATo/y7XcFXUdtbo/s1600-h/image%5B4%5D.png"&gt;&lt;img alt="image" border="0" height="570" src="http://lh3.ggpht.com/_3USHh0OQON0/TB0Nvvz_Y3I/AAAAAAAAATs/awp_coWGxJc/image_thumb%5B2%5D.png?imgmax=800" style="border-width: 0px; display: inline;" title="image" width="495" /&gt;&lt;/a&gt;&lt;br /&gt;
If you don’t check that, you’ll see:&lt;br /&gt;
&lt;a href="http://lh5.ggpht.com/_3USHh0OQON0/TB0NwRcefWI/AAAAAAAAATw/hyDXGTLmpkk/s1600-h/image%5B7%5D.png"&gt;&lt;img alt="image" border="0" height="244" src="http://lh4.ggpht.com/_3USHh0OQON0/TB0Nw8iXctI/AAAAAAAAAT0/uy_QFbybpaM/image_thumb%5B3%5D.png?imgmax=800" style="border: 0px none; display: inline;" title="image" width="211" /&gt;&lt;/a&gt; &lt;br /&gt;
Instead of:&lt;br /&gt;
&lt;a href="http://lh4.ggpht.com/_3USHh0OQON0/TB0NxYL1MrI/AAAAAAAAAT4/mF8OAkQtCGw/s1600-h/image%5B10%5D.png"&gt;&lt;img alt="image" border="0" height="244" src="http://lh5.ggpht.com/_3USHh0OQON0/TB0NxpjddvI/AAAAAAAAAT8/e88QQi2MOOU/image_thumb%5B4%5D.png?imgmax=800" style="border: 0px none; display: inline;" title="image" width="211" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-1345666836800165752?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/1345666836800165752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=1345666836800165752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1345666836800165752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1345666836800165752'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/06/eclipse-plug-ins-not-showing-suggested.html' title='Eclipse plug-ins not showing suggested templates'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_3USHh0OQON0/TB0Nvvz_Y3I/AAAAAAAAATs/awp_coWGxJc/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2553923081411372062</id><published>2010-06-10T08:52:00.000-07:00</published><updated>2010-06-10T08:52:23.458-07:00</updated><title type='text'>Comparing Microsoft and Google</title><content type='html'>Interesting comment on Microsoft vs Google (what it's like to work there) on the&lt;br /&gt;Mini-Microsoft blog.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
Look for the comment starting with:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
&amp;gt;&amp;gt; And how do you compare GOOG to MSFT?&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;br /&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
It's not black and white, there are advantages and disadvantages to both.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;a href="http://minimsft.blogspot.com/2010/05/thoughts-on-wrapping-up-microsofts-fy10.html?commentPage=2"&gt;http://minimsft.blogspot.com/2010/05/thoughts-on-wrapping-up-microsofts-fy10.html?commentPage=2&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2553923081411372062?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2553923081411372062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2553923081411372062' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2553923081411372062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2553923081411372062'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/06/comparing-microsoft-and-google.html' title='Comparing Microsoft and Google'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3716197777273580490</id><published>2010-06-09T06:43:00.001-07:00</published><updated>2010-06-09T06:43:27.188-07:00</updated><title type='text'>Fail Whale</title><content type='html'>Just got the Twitter Fail Whale - haven't seen that for a long time:&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://s.twimg.com/images/whale_error.gif" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3716197777273580490?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3716197777273580490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3716197777273580490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3716197777273580490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3716197777273580490'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/06/fail-whale.html' title='Fail Whale'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7054063934843519185</id><published>2010-06-08T09:32:00.000-07:00</published><updated>2010-06-08T09:32:16.666-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jdbc'/><title type='text'></title><content type='html'>&lt;br /&gt;
&lt;br /&gt;
If you're trying to use jruby on rails, and you see an error like this:&lt;br /&gt;
&lt;blockquote&gt;
GEM_HOME=~/.jrubygem jruby -S rake db:create:all&lt;/blockquote&gt;
&lt;blockquote&gt;
(in /private/tmp/fnord)&lt;/blockquote&gt;
&lt;blockquote&gt;
!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.&lt;/blockquote&gt;
&lt;blockquote&gt;
rake aborted!&lt;/blockquote&gt;
&lt;blockquote&gt;
no such file to load -- mysql&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;br /&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
(See full trace by running task with --trace)&lt;/blockquote&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
The solution is to run script/generate jdbc:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;blockquote&gt;
GEM_HOME=~/.jrubygem jruby -S script/generate jdbc&lt;/blockquote&gt;
&lt;blockquote&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;exists &amp;nbsp;config/initializers&lt;/blockquote&gt;
&lt;blockquote&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;create &amp;nbsp;config/initializers/jdbc.rb&lt;/blockquote&gt;
&lt;blockquote&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;exists &amp;nbsp;lib/tasks&lt;/blockquote&gt;
&lt;blockquote&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;create &amp;nbsp;lib/tasks/jdbc.rake&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
See&amp;nbsp;&lt;a href="http://blog.nicksieger.com/articles/2009/10/12/fresh-0-9-2-activerecord-jdbc-adapter-release"&gt;Nick Sieger's blog&lt;/a&gt;&amp;nbsp;for more detail.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7054063934843519185?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7054063934843519185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7054063934843519185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7054063934843519185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7054063934843519185'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/06/if-youre-trying-to-use-jruby-on-rails.html' title=''/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-5482083496860262780</id><published>2010-05-25T16:58:00.000-07:00</published><updated>2010-05-27T13:57:51.105-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='irrelevant'/><category scheme='http://www.blogger.com/atom/ns#' term='crickets'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Windows 7 Mobile Operating Thingy for Whatsits - does anyone care?</title><content type='html'>I was at Google IO last week. &amp;nbsp;Talk about iPhones was everywhere - people thinking about how the Android vs iPhone battle was going to play out.&lt;br /&gt;
&lt;br /&gt;
Windows 7 Mobile Operating Thingy for Whatsits (or whatever they're calling it these days) wasn't talked about. &amp;nbsp;Not at all. &amp;nbsp;Zero. Nada.&lt;br /&gt;
&lt;br /&gt;
The Kin? &amp;nbsp;Again, nothing. &amp;nbsp;Crickets.&lt;br /&gt;
&lt;br /&gt;
I hear there was trivial shakeup at Microsoft today. &amp;nbsp;Whatever.&lt;br /&gt;
&lt;br /&gt;
Do the people at Microsoft understand how bad things are? &amp;nbsp;Sure doesn't seem like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-5482083496860262780?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/5482083496860262780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=5482083496860262780' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5482083496860262780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5482083496860262780'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/05/windows-7-mobile-operating-thingy-for.html' title='Windows 7 Mobile Operating Thingy for Whatsits - does anyone care?'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2397208127220997540</id><published>2010-05-24T22:16:00.000-07:00</published><updated>2010-05-24T22:16:10.619-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='evo'/><category scheme='http://www.blogger.com/atom/ns#' term='htc'/><category scheme='http://www.blogger.com/atom/ns#' term='att'/><category scheme='http://www.blogger.com/atom/ns#' term='tmobile'/><category scheme='http://www.blogger.com/atom/ns#' term='droid'/><category scheme='http://www.blogger.com/atom/ns#' term='verizon'/><category scheme='http://www.blogger.com/atom/ns#' term='sprint'/><category scheme='http://www.blogger.com/atom/ns#' term='nexus one'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android carriers and phones - Sprint, TMobile, Verizon, ATT, Droid, Evo, iPhone, Nexus One</title><content type='html'>We're just finishing up a trip to San Francisco, Los Angeles and San Diego.  Between me and my fiancee we're carrying around four cell phones (thanks to giveaways at &lt;a href="http://code.google.com/events/io/2010/"&gt;Google IO&lt;/a&gt;):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Droid/Verizon&lt;/li&gt;
&lt;li&gt;HTC Evo/Sprint&lt;/li&gt;
&lt;li&gt;iPhone 3G/ATT&lt;/li&gt;
&lt;li&gt;Nexus One/TMobile (my fiancee's phone)&lt;/li&gt;
&lt;/ul&gt;
Our reactions to the carriers and phones so far:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Droid/Verizon&lt;/b&gt;: works great, works everywhere, but you need a forklift to carry this thing around.  The Droid is clearly an engineering prototype that someone from marketing stole from the lab.  It's just not a shipping product, no way, no how.&lt;br /&gt;
&lt;br /&gt;
However, since I'm a geek, carrying around the engineering prototype hasn't been that bad. &amp;nbsp;When I was carrying around the Droid and the iPhone 3G, I'd almost always pull out the Droid. &amp;nbsp;I'd really only pull out the iPhone for UrbanSpoon.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;HTC Evo/Sprint&lt;/b&gt;: The new hotness. &amp;nbsp;The screen is bigger than my laptop. &amp;nbsp;It's fast. &amp;nbsp; It's got some lame software on it called "Sense" - sometime soon I'll need to figure out how to disable it, but it's only mildly annoying so far.&lt;br /&gt;
&lt;br /&gt;
Sprint has been surprisingly good - no coverage problems in urban areas so far, and very good coverage on the train between LA and San Diego (with some dropouts where geography was pretty obviously terrible - Camp Pendleton for one).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;iPhone 3G/ATT&lt;/b&gt;: I'd like to tell you about ATT's coverage, but I almost never pull the iPhone out of my pocket. &amp;nbsp;It feels archaic at this point.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Nexus One/TMobile&lt;/b&gt;: Very nice phone, but as far as we can tell TMobile isn't actually in the business of providing wireless connections to cell phones with any sort of reasonable coverage. &amp;nbsp;Just pathetic. &amp;nbsp;TMobile isn't worth considering as a provider.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2397208127220997540?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2397208127220997540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2397208127220997540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2397208127220997540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2397208127220997540'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/05/android-carriers-and-phones-sprint.html' title='Android carriers and phones - Sprint, TMobile, Verizon, ATT, Droid, Evo, iPhone, Nexus One'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-5445096086874616284</id><published>2010-05-12T11:19:00.000-07:00</published><updated>2010-05-12T11:19:08.764-07:00</updated><title type='text'>Android - loading a javascript file from a web page needs internet permission</title><content type='html'>If you're trying to include javascript in an android.webkit.WebView view with a standard script tag like this:&lt;br /&gt;
&lt;blockquote&gt;
    &amp;lt;script language="javascript" src="demo.js" /&amp;gt;&lt;/blockquote&gt;
You need to add internet permissions to your manifest: &lt;br /&gt;
&lt;blockquote&gt;
&amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;&lt;/blockquote&gt;
Doesn't seem to matter that the file is local.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-5445096086874616284?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/5445096086874616284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=5445096086874616284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5445096086874616284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5445096086874616284'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/05/android-loading-javascript-file-from.html' title='Android - loading a javascript file from a web page needs internet permission'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8705878815529334569</id><published>2010-04-27T14:41:00.000-07:00</published><updated>2010-04-27T14:41:40.687-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='droid'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Liking the Droid a bit more</title><content type='html'>After using the Droid for a bit, I'm feeling more charitable.&lt;br /&gt;
&lt;br /&gt;
Just have to think of it as an engineering prototype. &amp;nbsp;It's not really a device you'd expect people to pay money for - it's far too clunky for that. &amp;nbsp;But as a limited production device just for developers, it's fine.&lt;br /&gt;
&lt;br /&gt;
I'm carrying it and my iphone around now (it's a pain), and I find that I pull out the Droid far more often. &amp;nbsp;The web browsing experience is just that much better than the iPhone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8705878815529334569?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8705878815529334569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8705878815529334569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8705878815529334569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8705878815529334569'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/04/liking-droid-bit-more.html' title='Liking the Droid a bit more'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4849676290496260545</id><published>2010-04-22T14:52:00.000-07:00</published><updated>2010-04-22T14:52:10.339-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='droid'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>New Droid arrived</title><content type='html'>Got my new Droid a few minutes ago.&lt;br /&gt;
&lt;br /&gt;
First impression: the thing feels like a tank. &amp;nbsp;Very industrial. &amp;nbsp;Not at all a warm and fuzzy feeling like the Nexus One or my iPhone.&lt;br /&gt;
&lt;br /&gt;
And the slideout keyboard is the definition of epic fail. &amp;nbsp;Useless, probably adds quite a bit of weight and complexity to the phone. &amp;nbsp;Just wrong, wrong, wrong. &amp;nbsp;This phone should never have left the lab.&lt;br /&gt;
&lt;br /&gt;
I suspect that I did this in the wrong order. &amp;nbsp;You need to experience a Droid before you play with a Nexus One. &amp;nbsp;Had I done that, I might have been more impressed.&lt;br /&gt;
&lt;br /&gt;
It's good to have a Droid though, since they're apparently the most popular Android device. &amp;nbsp;Good to have around for testing. &amp;nbsp;But I pity the people who have to use this as their primary device.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4849676290496260545?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4849676290496260545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4849676290496260545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4849676290496260545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4849676290496260545'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/04/new-droid-arrived.html' title='New Droid arrived'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2808762963780609030</id><published>2010-04-02T18:07:00.000-07:00</published><updated>2010-04-02T18:07:40.647-07:00</updated><title type='text'>ipad - thumbs down</title><content type='html'>I'm on a ski trip with a friend (teenager, from San Diego, the cultural capital of the world).

His unsolicited comments on the ipad:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
It's just a giant ipod touch. &amp;nbsp;&amp;nbsp;Go buy yourself a computer with that.

Like seriously what's the point of that?

Don't buy the ipad.  Piece of ...&lt;static...&gt;"&lt;/static...&gt;&lt;/blockquote&gt;
&lt;static...&gt;&lt;br /&gt;&lt;/static...&gt;&lt;br /&gt;
&lt;static...&gt;I'm with him.  If the thing were seriously less expensive, it'd be interesting.  It's not.&lt;/static...&gt;&lt;br /&gt;
&lt;static...&gt;&lt;br /&gt;&lt;/static...&gt;&lt;br /&gt;
Now, I should probably add that he's now chanting "looser" since I'm taking too long to type up this entry, so maybe I'm not so fond of his opinions after all...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2808762963780609030?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2808762963780609030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2808762963780609030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2808762963780609030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2808762963780609030'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/04/ipad-thumbs-down.html' title='ipad - thumbs down'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4451905771146836934</id><published>2010-03-22T12:49:00.000-07:00</published><updated>2010-03-22T12:51:11.710-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>jruby and mkdir problems with gems</title><content type='html'>If you see an error like this when you're installing gems:
&lt;pre&gt;
GEM_HOME=/Users/james/.jrubygem GEM_PATH=/Users/james/.jrubygem jruby -S gem install -V activerecord-jdbcmysql-adapter rails

ERROR:  While executing gem ... (SystemCallError)
  Unknown error - mkdir failed
&lt;/pre&gt;
Make sure you don't have a ~/.gem directory with bad permissions.  jruby wanted to use that directory for something even though I had specified a different GEM_HOME.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4451905771146836934?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4451905771146836934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4451905771146836934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4451905771146836934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4451905771146836934'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/03/jruby-and-mkdir-problems-with-gems.html' title='jruby and mkdir problems with gems'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2522205984115562524</id><published>2010-03-14T09:42:00.000-07:00</published><updated>2010-03-14T09:42:10.518-07:00</updated><title type='text'>Lá Fhéile Pádraig</title><content type='html'>Ag tiomaint na nathracha -
&lt;a href="http://nimill.blogspot.com/2010/03/ag-tiomaint-na-nathracha-as-eirinn.html"&gt;blag Dennis King&lt;/a&gt;.  "An bhfuil muid ann fos?" GOA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2522205984115562524?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2522205984115562524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2522205984115562524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2522205984115562524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2522205984115562524'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/03/la-fheile-padraig.html' title='Lá Fhéile Pádraig'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7706332162466554560</id><published>2010-03-07T18:38:00.001-08:00</published><updated>2010-03-07T18:58:15.936-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>HTML with the F# question mark operator</title><content type='html'>&lt;p&gt;I needed to create some HTML from F#.&amp;#160; I wanted something where the F# looked something the the results, and I didn’t have any need for anything other than the basics (tags, attributes, text contents).&lt;/p&gt;  &lt;p&gt;I had seen a few posts talking about the question mark operator and hadn’t used it yet.&amp;#160; It seemed like the obvious candidate – it means you can put tags into code without writing a whole lot of support for each and every tag name you’re going to need.&lt;/p&gt;  &lt;p&gt;What I ended up with is syntax that looks like this:&lt;/p&gt;  &lt;pre class="brush: fsharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;let h = com.restphone.Qml.Builder()

let exampleWithATable =
  let a =
    h?table &amp;lt;- [
      h?tr &amp;lt;- [
        h?td &amp;lt;- &amp;quot;one&amp;quot;
        h?td &amp;lt;- &amp;quot;two&amp;quot;
      ]
      h?tr
    ]
  printExample &amp;quot;a table&amp;quot; a
// a table
// -----
// &amp;lt;table&amp;gt;
//   &amp;lt;tr&amp;gt;
//     &amp;lt;td&amp;gt;one&amp;lt;/td&amp;gt;
//     &amp;lt;td&amp;gt;two&amp;lt;/td&amp;gt;
//   &amp;lt;/tr&amp;gt;
//   &amp;lt;tr /&amp;gt;
// &amp;lt;/table&amp;gt;
// &lt;/pre&gt;

&lt;p&gt;The elements after the question marks are just turned into strings then passed to a function that turns them into nodes in the HTML tree. Nesting nodes uses the &amp;lt;- operator followed by a list of items that can be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Strings get turned into content &lt;/li&gt;

  &lt;li&gt;Two-element tuples are turned into key-value attributes &lt;/li&gt;

  &lt;li&gt;Nodes (using the same h?sometag syntax) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I like the way the syntax ends up looking quite a bit like the HTML it’s producing as the final output.&lt;/p&gt;

&lt;p&gt;A couple more examples:&lt;/p&gt;

&lt;pre class="brush: fsharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;let exampleWithAttributes = 
  let a1 = 
    h?ol &amp;lt;- [
      h?li &amp;lt;- [
        &amp;quot;class&amp;quot;, &amp;quot;formattedList&amp;quot;                   // Two-element tuples are attributes
        &amp;quot;something&amp;quot;, &amp;quot;something &amp;amp; else&amp;quot;           
        {name = &amp;quot;class&amp;quot;; value = &amp;quot;listItemStyle&amp;quot;}  // Or you can use an actual Attribute object
        &amp;quot;this should have escapes: &amp;amp; &amp;lt; &amp;gt;&amp;quot;          // content will be escaped
      ];
      h?li &amp;lt;- &amp;quot;second&amp;quot;
    ]
  printExample &amp;quot;list items with content and attributes&amp;quot; a1
// list items with content and attributes
// -----
// &amp;lt;ol&amp;gt;
//   &amp;lt;li class=&amp;quot;formattedList&amp;quot; something=&amp;quot;something &amp;amp;amp; else&amp;quot; class=&amp;quot;listItemStyle&amp;quot;&amp;gt;this should have escapes: &amp;amp;amp; &amp;amp;lt; &amp;amp;gt;&amp;lt;/li&amp;gt;
//   &amp;lt;li&amp;gt;second&amp;lt;/li&amp;gt;
// &amp;lt;/ol&amp;gt;
// 

let exampleWithASpanInContent =
  let b =
    h?foo &amp;lt;- [
      &amp;quot;content text&amp;quot;
      h?span &amp;lt;- &amp;quot;something in a span&amp;quot;
      &amp;quot;more text&amp;quot;
    ]
  printExample &amp;quot;content containing a span&amp;quot; b
// content containing a span
// -----
// &amp;lt;foo&amp;gt;content text&amp;lt;span&amp;gt;something in a span&amp;lt;/span&amp;gt;more text&amp;lt;/foo&amp;gt;
// &lt;/pre&gt;

&lt;p&gt;And here’s the code:&lt;/p&gt;

&lt;pre class="brush: fsharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;namespace com.restphone.Qml

open System.Xml

// Name-value pairs
type Attribute =
  {name: string;
   value: string}

type Element =
  {tag: string;                   // The html tag; table, p, etc
   attributes: Attribute list;
   children: Node list}
and Node =
  | Element of Element
  | Content of string

type Builder() =
  static let emptyAttribute = {name = &amp;quot;&amp;quot;; value = &amp;quot;&amp;quot;}

  static let tupleToAttribute (t: System.Tuple&amp;lt;string, string&amp;gt;) =
    {emptyAttribute with name = t.Item1; value = t.Item2}

  static let builder(builder, tag, things: obj list) =
    let rec appendThings (element: Element) (xs: obj list) =
      match xs with
      | (:? Element as nextElement)::t -&amp;gt; appendThings {element with children = (List.append element.children [Element nextElement])} t
      | (:? string as content)::t -&amp;gt; appendThings {element with children = (List.append element.children [Content content])} t
      | (:? List&amp;lt;Attribute&amp;gt; as attrs)::t -&amp;gt; appendThings {element with attributes = List.append element.attributes attrs} t
      | (:? Attribute as attr)::t -&amp;gt; appendThings element ([attr] :&amp;gt; obj::t)
      | (:? System.Tuple&amp;lt;string, string&amp;gt; as p)::t -&amp;gt; appendThings element ((tupleToAttribute p) :&amp;gt; obj::t)
      | [] -&amp;gt; element
      | x -&amp;gt; element
    appendThings ((?) builder tag) things
  
  static let printAttribute (x: System.Xml.XmlWriter) (attr: Attribute) =
    x.WriteAttributeString(attr.name, attr.value)
     
  static let printAttributes x attrs =
    List.iter (printAttribute x) attrs

  static let rec printContent (x: System.Xml.XmlWriter) s =
    x.WriteString s

  static let rec printElements x e =
    let pe = function
      | Content c -&amp;gt; printContent x c
      | Element el -&amp;gt; printElement x el
    List.iter pe e
  and
    printElement (x: System.Xml.XmlWriter) e =
      x.WriteStartElement e.tag
      printAttributes x e.attributes
      printElements x e.children
      x.WriteEndElement ()
    
  static member (?) (a: Builder, tag) =
    {tag = tag; attributes = []; children = []}
  
  static member (?&amp;lt;-) (a: Builder, tag, things: obj list) = builder(a, tag, things)
  static member (?&amp;lt;-) (a: Builder, tag, content: string) = builder(a, tag, [content])
  static member (?&amp;lt;-) (a: Builder, tag, attributePair: string * string) = builder(a, tag, [attributePair])
  static member (?&amp;lt;-) (a: Builder, tag, attr: Attribute) = builder(a, tag, [attr])
  static member (?&amp;lt;-) (a: Builder, tag, e: Element) = builder(a, tag, [e])
      
  static member write elements x =
    Seq.iter (printElement x) elements

  static member ElementSeqToString (h: Element seq) = 
    let sw = new System.IO.StringWriter()
    let xtw = new XmlTextWriter(sw)
    xtw.Formatting &amp;lt;- Formatting.Indented
    Builder.write h xtw |&amp;gt; ignore
    sw.ToString()

  static member ElementToString (h: Element) = 
    Builder.ElementSeqToString [h]&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7706332162466554560?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7706332162466554560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7706332162466554560' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7706332162466554560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7706332162466554560'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2010/03/html-with-f-question-mark-operator.html' title='HTML with the F# question mark operator'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7495754871914886639</id><published>2009-12-13T21:11:00.001-08:00</published><updated>2009-12-13T21:11:48.237-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monotouch'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>rakefile for F# under MonoDevelop</title><content type='html'>I just put up a rakefile for building F# dlls for MonoTouch.&amp;nbsp; It's at &lt;a href="http://github.com/banshee/fsharp_rakefile"&gt;http://github.com/banshee/fsharp_rakefile&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7495754871914886639?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7495754871914886639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7495754871914886639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7495754871914886639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7495754871914886639'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/12/rakefile-for-f-under-monodevelop.html' title='rakefile for F# under MonoDevelop'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2868426514650710426</id><published>2009-10-25T11:52:00.000-07:00</published><updated>2009-10-25T11:52:51.435-07:00</updated><title type='text'>Ninite - bulk installer, potentially useful</title><content type='html'>This looks useful - it's a bulk installer for a bunch of things I use.&amp;nbsp; Windows 7 upgrades on a couple machines are in my very near future, so hopefully this will save some time.&lt;br /&gt;
 &lt;br /&gt;
&lt;a href="http://ninite.com/"&gt;http://ninite.com/&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2868426514650710426?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2868426514650710426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2868426514650710426' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2868426514650710426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2868426514650710426'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/10/ninite-bulk-installer-potentially.html' title='Ninite - bulk installer, potentially useful'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7173588255079874940</id><published>2009-09-29T00:07:00.001-07:00</published><updated>2009-09-29T00:09:38.489-07:00</updated><title type='text'>F# running on the iPhone</title><content type='html'>&lt;p&gt;I tried F# on the iPhone (via &lt;a href="http://monotouch.net/" target="_blank"&gt;MonoTouch&lt;/a&gt;) tonight.&amp;#160; The trivial hello-world code seemed to work just fine.&amp;#160; I used standalone to build the (trivial) fsharp code:&lt;/p&gt;  &lt;pre&gt;type Foo() =
  do System.Console.WriteLine(&amp;quot;This output brought to you by the note F#&amp;quot;);&lt;/pre&gt;

&lt;pre&gt;mono ../FSharp-1.9.6.16/bin/fsc.exe -a Foo.fs&lt;/pre&gt;

&lt;p&gt;And added a line to instantiate a Foo in FinishedLaunching().&lt;/p&gt;

&lt;p&gt;Loaded the resulting dll into MonoDevelop, along with FSharp.Core.dll, and it just worked.&amp;#160; Or at least it worked in the simulator, haven't tried the real device yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_3USHh0OQON0/SsGyMYRuraI/AAAAAAAAAQk/FvURdjH0vYo/s1600-h/fsharponiphone%5B1%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="fsharponiphone" border="0" alt="fsharponiphone" src="http://lh3.ggpht.com/_3USHh0OQON0/SsGyM9LacjI/AAAAAAAAAQo/ErqP-A9fSQM/fsharponiphone_thumb%5B1%5D.png?imgmax=800" width="244" height="154" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7173588255079874940?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7173588255079874940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7173588255079874940' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7173588255079874940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7173588255079874940'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/09/f-running-on-iphone.html' title='F# running on the iPhone'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_3USHh0OQON0/SsGyM9LacjI/AAAAAAAAAQo/ErqP-A9fSQM/s72-c/fsharponiphone_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4720546168713937543</id><published>2009-09-18T11:27:00.001-07:00</published><updated>2009-09-18T11:27:30.645-07:00</updated><title type='text'>Sequence of positions in a sequence (F#)</title><content type='html'>&lt;p&gt;&lt;a href="http://stevehorsfield.wordpress.com"&gt;Steve Horsfield's&lt;/a&gt; blog had a post on fold functions that cared about the beginning, middle and ends of the sequence they were operating on.&amp;#160; I think there’s a preprocessing step that simplifies the problem – transform the sequence into a seq&amp;lt;Position&amp;lt;'t&amp;gt;&amp;gt;, where Position tells you if the object is at the beginning, middle, or end of the sequence:&lt;/p&gt;  &lt;pre class="brush: fsharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;type Position&amp;lt;'t&amp;gt; =
| Beginning of 't
| Middle of 't
| End of 't
| Only of 't

let rec sequenceOfPositionsWithLazyList(existing: LazyList&amp;lt;'t&amp;gt;) =
  seq {
    let rec elementsAfterBeginning(s) =
      seq {
        match s with
        | LazyList.Cons(h, LazyList.Nil) -&amp;gt; yield End(h); ()
        | LazyList.Cons(h, t) -&amp;gt; yield Middle(h); yield! elementsAfterBeginning(t)
        | _ -&amp;gt; ()
      }
    match existing with
      | LazyList.Cons(h, LazyList.Nil) -&amp;gt; yield Only(h); ()
      | LazyList.Cons(h, t) -&amp;gt; yield Beginning(h); yield! elementsAfterBeginning(t)
      | LazyList.Nil -&amp;gt; ()
  }
  
let sequenceOfPositions(existing: seq&amp;lt;'t&amp;gt;) = sequenceOfPositionsWithLazyList(LazyList.of_seq existing)
  
printfn &amp;quot;%A&amp;quot; (sequenceOfPositions [1;2;3])
printfn &amp;quot;%A&amp;quot; (sequenceOfPositions [1;3])
printfn &amp;quot;%A&amp;quot; (sequenceOfPositions [1])
printfn &amp;quot;%A&amp;quot; (sequenceOfPositions [])&lt;/pre&gt;

&lt;p&gt;The output is: &lt;/p&gt;

&lt;pre class="brush: fsharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;seq [Beginning 1; Middle 2; End 3]
seq [Beginning 1; End 3]
seq [Only 1]
seq []&lt;/pre&gt;

&lt;p&gt;I think that makes following steps much easier to write.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4720546168713937543?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4720546168713937543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4720546168713937543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4720546168713937543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4720546168713937543'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/09/sequence-of-positions-in-sequence-f.html' title='Sequence of positions in a sequence (F#)'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2291724057155396009</id><published>2009-07-10T16:43:00.000-07:00</published><updated>2009-07-10T16:43:39.565-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gtm'/><category scheme='http://www.blogger.com/atom/ns#' term='cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='objective-c'/><title type='text'>error: 'GDataInputStreamLogger' undeclared (first use in this function)</title><content type='html'>If you're seeing errors like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m: In function '-[GDataHTTPFetcher(GDataHTTPFetcherLogging) logCapturePostStream]':
/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m:797: error: 'GDataInputStreamLogger' undeclared (first use in this function)
/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m:797: error: (Each undeclared identifier is reported only once
/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m:797: error: for each function it appears in.)
/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m:800: error: expected expression before ')' token
/Users/jamesmoore/dev/mba/gdata170/Source/Networking/GDataHTTPFetcherLogging.m:804: error: expected expression before ')' token
&lt;/pre&gt;
&lt;br /&gt;
Set this preprocessor macro:

STRIP_GDATA_FETCH_LOGGING=0.&lt;br /&gt;
&lt;br /&gt;
(TBD:&amp;nbsp; An actual explanation.&amp;nbsp; Unfortunately, it's not high on my priority list right now.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2291724057155396009?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2291724057155396009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2291724057155396009' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2291724057155396009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2291724057155396009'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/07/error-gdatainputstreamlogger-undeclared.html' title='error: &apos;GDataInputStreamLogger&apos; undeclared (first use in this function)'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7123279632272244317</id><published>2009-06-15T21:26:00.000-07:00</published><updated>2010-01-31T23:32:47.933-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Merging two sequences in F# using LazyList</title><content type='html'>&lt;a href="http://www.fsharp.it/2009/06/13/merging-arrays/"&gt;Claudio Cherubino&lt;/a&gt;&amp;#160; had a post about solving one of the standard Amazon interview questions, and it prompted me to finally figure out how to use sequence expressions and LazyList in F#.   &lt;br /&gt;  &lt;br /&gt;The problem is to merge two arrays into a third array in O(n) time.&amp;#160; I like the F# solution using sequences and pattern matching - it feels like a nice way to write this sort of thing.&amp;#160; &lt;br /&gt;  &lt;pre class="brush: fsharp; auto-links: false; collapse: false; first-line: 1; gutter: false; html-script: false; light: true; ruler: false; smart-tabs: false; tab-size: 2; toolbar: false;"&gt;type MergeWithLazyLists() =&lt;br /&gt;  static member merge(f, x: LazyList&amp;lt;'t&amp;gt;, y: LazyList&amp;lt;'t&amp;gt;) =&lt;br /&gt;    seq {&lt;br /&gt;      match x, y with&lt;br /&gt;      | LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) when f xh yh -&amp;gt; &lt;br /&gt;        yield xh&lt;br /&gt;        yield! MergeWithLazyLists.merge(f, xt, y)&lt;br /&gt;      | LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) -&amp;gt; &lt;br /&gt;        yield yh&lt;br /&gt;        yield! MergeWithLazyLists.merge(f, x, yt)&lt;br /&gt;      | LazyList.Nil, LazyList.Cons(_, _) -&amp;gt; yield! y&lt;br /&gt;      | LazyList.Cons(_, _), LazyList.Nil -&amp;gt; yield! x&lt;br /&gt;      | LazyList.Nil, LazyList.Nil -&amp;gt; ()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  static member merge(f, x: seq&amp;lt;'t&amp;gt;, y: seq&amp;lt;'t&amp;gt;) =&lt;br /&gt;    MergeWithLazyLists.merge(f, (LazyList.ofSeq x), (LazyList.ofSeq y))&lt;br /&gt;&lt;br /&gt;let result = MergeWithLazyLists.merge((fun x y -&amp;gt; x &amp;lt; y), (seq {2..6}), (seq {1..7..15}))&lt;br /&gt;&lt;br /&gt;printfn &amp;quot;%A&amp;quot; (Seq.toArray result)&lt;/pre&gt;

&lt;p&gt;A sequence in F# is anything that implements IEnumerable&amp;lt;'t&amp;gt;, so arrays and lists both work just fine. &lt;/p&gt;

&lt;p&gt;(An earlier version of this post used the older names for some methods – to_seq, to_array.&amp;#160; I updated this to the new methods in 1.9.7.8) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7123279632272244317?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7123279632272244317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7123279632272244317' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7123279632272244317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7123279632272244317'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/06/merging-two-sequences-in-f-using.html' title='Merging two sequences in F# using LazyList'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2998362094727380906</id><published>2009-05-27T08:56:00.000-07:00</published><updated>2009-05-27T08:56:00.259-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raid'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Recovering Linux RAID drives</title><content type='html'>I had a couple drives that used to be part of a Linux RAID setup.&amp;nbsp; The easiest way I've found to grab the data off them is &lt;a href="http://www.cgsecurity.org/wiki/TestDisk"&gt;TestDisk&lt;/a&gt; - it's a handy tool that will copy files off a drive that was part of a RAID array.&amp;nbsp; Even better, you can run it from Linux and Windows.&amp;nbsp; In my case, my new main machine is a Vista box, so I don't have to figure out how to get my VMware instance of Ubuntu to read drive image files on the Windows box.&lt;br /&gt;
&lt;br /&gt;
I found TestDisk through this article: &lt;a href="http://pario.no/2009/01/19/mount-a-disk-image/"&gt;Mounting Linux drive images&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.cgsecurity.org/wiki/TestDisk"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2998362094727380906?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2998362094727380906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2998362094727380906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2998362094727380906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2998362094727380906'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/05/recovering-linux-raid-drives.html' title='Recovering Linux RAID drives'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2871949157667548938</id><published>2009-05-13T11:37:00.000-07:00</published><updated>2009-05-13T11:37:30.985-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Link to post about iPhone table views</title><content type='html'>Useful post from Matt Gallagher about iPhone table views: &lt;a href="http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html"&gt;http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2871949157667548938?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2871949157667548938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2871949157667548938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2871949157667548938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2871949157667548938'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/05/link-to-post-about-iphone-table-views.html' title='Link to post about iPhone table views'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7693198724649233006</id><published>2009-04-21T12:50:00.000-07:00</published><updated>2009-04-21T12:50:44.534-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit tests'/><category scheme='http://www.blogger.com/atom/ns#' term='cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>GTM test suite for the iPhone - figuring out why it was hanging on startup</title><content type='html'>[Sorry about the formatting problems.  This was posted to my old blog, and I found it again when I was doing a google search for the topic.  The old blog posts are lying around somewhere, but I'm lazy so I'll just cut-and-paste from the google cache...]

I'm trying to use the &lt;b style="background-color: rgb(255, 255, 102); color: black;"&gt;GTM&lt;/b&gt; test suite, and it's just hanging.  The build window shows:
&lt;pre&gt;    2008-11-21 09:23:46.996 UnitTests[1794:10b] CFPreferences: user home directory at /Users/jamesmoore/dev/TestPlatform/build/TestPlatform.build/Debug-iphonesimulator/UnitTests.build/iPhone Simulator User Dir is unavailable. User domains will be volatile.    2008-11-21 09:23:47.012 UnitTests[1794:10b] Unable to send CPDistributedMessagingCenter message named SBRemoteNotificationClientStartedMessage to com.apple.remotenotification.server: (ipc/send) invalid destination port&lt;/pre&gt;Starting under the debugger (using option-cmd-Y to skip running the test harness shell script) isn't very informative:&lt;pre&gt;(gdb) bt#0  0x964954a6 in mach_msg_trap ()#1  0x9649cc9c in mach_msg ()#2  0x956fd0ce in CFRunLoopRunSpecific ()#3  0x956fdcf8 in CFRunLoopRunInMode ()#4  0x31699d38 in GSEventRunModal ()#5  0x31699dfd in GSEventRun ()#6  0x30a5dadb in -[UIApplication _run] ()#7  0x30a68ce4 in UIApplicationMain ()#8  0x00002a39 in main (argc=1, argv=0xbffff060) at /Users/jamesmoore/dev/TestPlatform/../google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestMain.m:30(gdb)&lt;/pre&gt;All that looks fine.

So, did the &lt;b style="background-color: rgb(153, 255, 153); color: black;"&gt;tests&lt;/b&gt; run at all? 

GTMIphoneUnitTestMain.m does:&lt;pre&gt;  int retVal = UIApplicationMain(argc, argv, nil, @"GTMIPhoneUnitTestDelegate");&lt;/pre&gt;So I set a breakpoint on the first line of  applicationDidFinishLaunching, on the call to runTests:&lt;pre&gt;- (void)applicationDidFinishLaunching:(UIApplication *)application {  [self runTests];&lt;/pre&gt;And sure enough, it's not hit.

So my next suspect is the app delegate for the regular application - inthis case, TestPlatformAppDelegate. Set a breakpoint in itsapplicationDidFinishLaunching, start up, and sure enough that's what'srunning. Why?

Turns out I had added MainWindow.xib to the &lt;b style="background-color: rgb(160, 255, 255); color: black;"&gt;unit&lt;/b&gt; test target.  For the regular (non-&lt;b style="background-color: rgb(160, 255, 255); color: black;"&gt;unit&lt;/b&gt;-test)application, MainWindow.xib has an instance of TestPlatformAppDelegate.The TestPlatformAppDelegate is attached to the File's Owner delegate.When the nib file is instantiated, it creates theTestPlatformAppDelegate, then sets the File's Owner delegate to be thenewly instantiated TestPlatformAppDelegate. That overwrites theinstance of GTMIPhoneUnitTestDelegate that used to be there, and no &lt;b style="background-color: rgb(153, 255, 153); color: black;"&gt;tests&lt;/b&gt; will run.

The next question is can something spit out a warning if this happens?

Off the top of my head, I don't know who gets called when nib files areloaded. I'm sitting at a debugger, so I slap in a new init method toGTMIPhoneUnitTestDelegate, set a breakpoint on it, and restart. Here'sthe stack:&lt;pre&gt;#0  -[TestPlatformAppDelegate init] (self=0x44fb80, _cmd=0x96d6c858) at /Users/jamesmoore/dev/TestPlatform/Classes/TestPlatformAppDelegate.m:19#1  0x30c2ca67 in -[UIClassSwapper initWithCoder:] ()#2  0x922a4940 in _decodeObjectBinary ()#3  0x922a42b5 in _decodeObject ()#4  0x30c2c615 in -[UIRuntimeConnection initWithCoder:] ()#5  0x922a4940 in _decodeObjectBinary ()#6  0x922a63cd in -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] ()#7  0x922a6849 in -[NSArray(NSArray) initWithCoder:] ()#8  0x922a4940 in _decodeObjectBinary ()#9  0x922a42b5 in _decodeObject ()#10 0x30c2bbeb in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:] ()#11 0x30c2dcf8 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:] ()#12 0x30a5df99 in -[UIApplication _loadMainNibFile] ()#13 0x30a65f42 in -[UIApplication _runWithURL:] ()#14 0x922ce5ee in __NSFireDelayedPerform ()#15 0x956fdb45 in CFRunLoopRunSpecific ()#16 0x956fdcf8 in CFRunLoopRunInMode ()#17 0x31699d38 in GSEventRunModal ()#18 0x31699dfd in GSEventRun ()#19 0x30a5dadb in -[UIApplication _run] ()#20 0x30a68ce4 in UIApplicationMain ()#21 0x00002a39 in main (argc=1, argv=0xbffff060) at /Users/jamesmoore/dev/TestPlatform/../google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestMain.m:30&lt;/pre&gt;The interesting points look like:&lt;pre&gt;#10 0x30c2bbeb in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:] ()#12 0x30a5df99 in -[UIApplication _loadMainNibFile] ()&lt;/pre&gt;Does one of those have something to hook into?

I start reading doc. The Resource Programming Guide has lots ofinformation about nib files, but the only thing I find that seemsrelevant is the bit where it points out that nib instantiation is goingto use setValue:forKey: to set the fields.

To see what happens there, I added this to GTMIphoneUnitTestMain.m:&lt;pre&gt;@interface GuardedUIApplication : UIApplication@end @implementation GuardedUIApplication- (void)setValue:(id)value forKey:(NSString *)key{ NSLog(@"Current value for key |%@| is |%@|", key, value); [super setValue: value forKey: key];}@end&lt;/pre&gt;And changed the call to UIApplicationMain to use GuardedUIApplication instead of the default UIApplication:&lt;pre&gt;  int retVal = UIApplicationMain(argc, argv, @"GuardedUIApplication", @"GTMIPhoneUnitTestDelegate");&lt;/pre&gt;Running it again, I see that the call I expected does in fact happen:&lt;pre&gt;2008-11-21 10:43:09.966 UnitTests[2841:20b] Current value for key |delegate| is |&lt;testplatformappdelegate: 0x44fbc0=""&gt;|&lt;/testplatformappdelegate:&gt;&lt;/pre&gt;Something like this might be a solution:&lt;pre&gt;@interface GuardedUIApplication : UIApplication@end@implementation GuardedUIApplication- (void)setValue:(id)value forKey:(NSString *)key{ NSLog(@"Existing value for key |%@| is |%@|", key, [self valueForKey: key]); NSLog(@"New value for key |%@| is |%@|", key, value); if ([key isEqualToString: @"delegate"] &amp;amp;&amp;amp; ![value isKindOfClass: [GTMIPhoneUnitTestDelegate class]]) {  NSException *e = [NSException failureInFile: [NSString stringWithCString: __FILE__]             atLine: __LINE__          withDescription: @"The app delegate must be a GTMIPhoneUnitTestDelegate.  Is MainWindow.nib attempting to use a different application delegate?"];  [e raise]; } [super setValue: value forKey: key];}@end&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7693198724649233006?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7693198724649233006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7693198724649233006' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7693198724649233006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7693198724649233006'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/04/gtm-test-suite-for-iphone-figuring-out.html' title='GTM test suite for the iPhone - figuring out why it was hanging on startup'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3850110003150100672</id><published>2009-04-13T15:24:00.000-07:00</published><updated>2009-04-13T15:24:36.533-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='objective-c'/><title type='text'>Objective-C basics for C programmers</title><content type='html'>&lt;h2&gt;







Objective-C is C&lt;/h2&gt;
First, if you want to learn Objective-C and you don’t know C yet, go learn C.&amp;nbsp; Come back when you’re done.&amp;nbsp; Objective-C is a set of addons to C – you must know C first.&amp;nbsp; C is a small language, and it won’t take you that long.&amp;nbsp; (Learning to use C &lt;b&gt;well&lt;/b&gt; is a different problem, of course.)&lt;br /&gt;
&lt;h2&gt;




What to read&lt;/h2&gt;
The &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html"&gt;Apple doc for Objective-C&lt;/a&gt; is pretty good, but it gets bogged down in places because it's not assuming you already know C.&amp;nbsp; It's also written as if Objective-C were a new language, instead of just some extra bits on top of C.&lt;br /&gt;
&lt;br /&gt;
(And Chapter 11 of that Apple doc tosses in this shocker: C++ is also included in Objective-C.&amp;nbsp; It's not usually necessary to use C++ on the iPhone, but it does mean you can use lots of existing C++ code if you need it.)&lt;br /&gt;
&lt;br /&gt;
This article is a stripped-down intro to thinking of Objective-C basics in terms of what they are in C.&lt;br /&gt;
&lt;h2&gt;







Square braces are just macros&lt;/h2&gt;
The best way to think about Objective-C syntax is that it’s just a new flavor of preprocessor for C.&amp;nbsp; There are some basic things you care about that are going to spit out normal C, eventually:   &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Messages.&amp;nbsp; They’re sent using square braces like this: &lt;span style="font-family: courier; font-size: small;"&gt;[targetObject theMessage]&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;Class definitions.&amp;nbsp; They’re blocks that start with @interface @implementation @protocol and end with @end. &lt;/li&gt;
&lt;li&gt;Selectors.&amp;nbsp; Selector is the Objective-C term for what most languages call “messages.”&amp;nbsp; They’re what you send to objects.&amp;nbsp; (Thinking of them as method invocations is mostly wrong and will get you in trouble later on.)&amp;nbsp; You’ll see selectors used like this: @selector(theMessage) and in square braces like this: &lt;span style="font-family: courier; font-size: small;"&gt;[targetObject theMessage] &lt;/span&gt;- that’s just syntatic sugar.&amp;nbsp; They’re going to compile down to the same thing. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;







Classes&lt;/h2&gt;
Classes are structs with some extra fields tacked on.&amp;nbsp; Here's a trivial class declaration:   &lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
@interface SmallClass : NSObject   &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
- (void) helloWorld;   &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
@end   &lt;/div&gt;
&lt;br /&gt;
This lays out the class for the compiler.&amp;nbsp; It allows the compiler to give you useful warnings if you try to send the helloWorld message to this class in the wrong way (so you'll get a warning if you try to call it with a parameter, for example).&amp;nbsp; It adds a field that's a pointer to the class itself, so at runtime you can dereference the pointer to the class type to figure out which functions correspond to which selectors.&amp;nbsp;&amp;nbsp; (And yes, this implies that at runtime a class can change its type.&amp;nbsp; That's nasty, and is used by things like key-value observing.)   &lt;br /&gt;
&lt;br /&gt;
The implementation for this would be:   &lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;
@implementation SmallClass    &lt;br /&gt;
- (void) helloWorld     &lt;br /&gt;
{     &lt;br /&gt;
&amp;nbsp; NSLog(@"Hello world.");     &lt;br /&gt;
}     &lt;br /&gt;
@end&lt;/div&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
The compiler turns this into a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;helloWorld&lt;/span&gt; function that looks something like:   &lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;
void helloWorldFunctionImplementation (SmallClass *self) {    &lt;br /&gt;
&amp;nbsp; NSLog(@"Hello world");     &lt;br /&gt;
} &lt;/div&gt;
&lt;br /&gt;
To create an instance of SmallClass and send it the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;helloWorld&lt;/span&gt; selector, you'd use the the square brackets syntax:   &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: courier;"&gt;SmallClass *sm = [[[SmallClass alloc] init] autorelease];    &lt;br /&gt;[sm helloWorld];     &lt;br /&gt;&lt;/span&gt;  &lt;br /&gt;
&lt;br /&gt;
(For now, ignore the &lt;span style="font-family: courier;"&gt;alloc/init/autorelease &lt;/span&gt;bits - they're memory management on the iPhone.)   &lt;br /&gt;
&lt;br /&gt;
Square brackets are just syntatic sugar that makes sending selectors to objects more pleasant.&amp;nbsp; What you end up with after square-bracket-procesing is a call to the function&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; objc_msgSend(receiver, selector)&lt;/span&gt;.&amp;nbsp; Calling objc_msgSend without the square brackets would do exactly the same thing:   &lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;
objc_msgSend(sm, @selector(helloWorld));&amp;nbsp; // same as [sm helloWorld]&lt;/div&gt;
&lt;br /&gt;
Or the same thing in a function:   &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;void sendHelloWorldByHand (SmallClass *target) &lt;/span&gt;  &lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;{&lt;/span&gt;   &lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;&amp;nbsp; objc_msgSend(target, @selector(helloWorld));&lt;/span&gt;   &lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;}&lt;/span&gt;   &lt;br /&gt;
&lt;br /&gt;
Notice that the call to @selector(helloWorld) couldn't care less about whether or not there's a method called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;helloWorld&lt;/span&gt; implemented by that object.&amp;nbsp; It's completely irrelevant - selectors just get translated to numbers by the compiler, and they're not tied to classes in any way.&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,courier,monospace;"&gt;@selector(helloWorld)&lt;/span&gt; becomes an int inside the compiler, and you can send that int to any instance of any class.&amp;nbsp; Whether or not the target does anything interesting with that message is an unrelated issue.   &lt;br /&gt;
&lt;br /&gt;
To put it another way: selectors aren't tied to particular objects; the selector for helloWorld on SmallClass is the same selector that you might send to AnotherClassIHaventImplementedYet.&amp;nbsp; Selectors are just a lookup mechanism so humans don't have to remember numbers - they get informative tokens to put in code.&amp;nbsp; But they're just going to turn into numbers when your code is running.   &lt;br /&gt;
&lt;br /&gt;
(And you should notice that the Apple doc says not to call objc_msgSend by hand, although I suspect this is widely ignored.)  &lt;br /&gt;
&lt;h2&gt;







Sending messages&lt;/h2&gt;
&lt;span style="font-family: courier;"&gt;objc_msgSend(target, selector)&lt;/span&gt; goes through these steps to figure out what to call:  &lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Looking at the hidden field in the struct that points to the class of the object.&amp;nbsp; &lt;/li&gt;
&lt;li&gt;Call the function matching the selector.&amp;nbsp; Classes have lookup tables that specify the selector-to-function mapping, and if there's a matching selector, that's what's called.&amp;nbsp; If there's no matching selector, check the parent of the class, and so on until you get to the root class.&amp;nbsp; &lt;/li&gt;
&lt;li&gt;If there's no match for the selector, call &lt;span style="font-family: courier;"&gt;forwardInvocation:&lt;/span&gt;. &lt;/li&gt;
&lt;/ol&gt;
#3 is important – it means that you cannot tell by looking at an object's @interface code whether or not it handles a selector.&amp;nbsp; That decision can't really be made until you're actually sending the selector to the object.&amp;nbsp; (And since &lt;span style="font-family: courier;"&gt;forwardInvocation:&lt;/span&gt; is free to do anything it feels like with a selector, there's no guarantee that a selector will do anything the same way twice.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3850110003150100672?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3850110003150100672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3850110003150100672' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3850110003150100672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3850110003150100672'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/04/objective-c-basics-for-c-programmers.html' title='Objective-C basics for C programmers'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6305011599805222549</id><published>2009-04-08T12:17:00.000-07:00</published><updated>2009-04-08T12:19:20.786-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='googleappengine'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>JRuby on Rails for Google App Engine</title><content type='html'>&lt;a href="http://olabini.com/blog/2009/04/jruby-on-rails-on-google-app-engine/"&gt;JRuby on Rails for Google App Engine&lt;/a&gt; could be very interesting.  No Active Record though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6305011599805222549?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6305011599805222549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6305011599805222549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6305011599805222549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6305011599805222549'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/04/jruby-on-rails-for-google-app-engine.html' title='JRuby on Rails for Google App Engine'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6656467767748212400</id><published>2009-04-07T14:33:00.000-07:00</published><updated>2009-04-07T14:33:36.424-07:00</updated><title type='text'>Best advice ever, from xkcd</title><content type='html'>&lt;a href="http://xkcd.com/386/"&gt;This has saved me so much time.&lt;/a&gt; Any time I'm tempted to respond to someone's opinion, I think of this comic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6656467767748212400?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6656467767748212400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6656467767748212400' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6656467767748212400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6656467767748212400'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/04/best-advice-ever-from-xkcd.html' title='Best advice ever, from xkcd'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4516971425834102644</id><published>2009-04-06T12:52:00.000-07:00</published><updated>2009-04-06T13:15:30.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>F# - Converting sequences to lists on the fly</title><content type='html'>There was a &lt;a href="http://stackoverflow.com/questions/716452/f-arraychunk-for-sequence/720331#720331"&gt;question on StackOverflow&lt;/a&gt; about chunking sequences to arrays.&amp;nbsp; The poster wanted to have the input put into three-element arrays, so something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&amp;gt; seq { for i in 1..10000 -&amp;gt; i} ;;
val it : seq&amp;lt;int&amp;gt; = seq [1; 2; 3; 4; ...]&lt;/pre&gt;
&lt;br /&gt;
would become:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&amp;gt; seq { for i in 1..10000 -&amp;gt; i} |&amp;gt; Seq.in_groups_of_n 3;;
val it : seq&amp;lt;int list&amp;gt;
= seq [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]; [10; 11; 12]; ...]
&amp;gt; &lt;/pre&gt;
&lt;br /&gt;
(I usually prefer to have my data in lists rather than arrays, so this isn't quite the answer they were looking for, but it's a trivial conversion from lists to arrays.)&lt;br /&gt;
&lt;br /&gt;
My first solution was something more like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iter&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;  let in_lists_of_length_n n f (ie : seq&amp;lt;'a&amp;gt;) = 
    use e = ie.GetEnumerator()
    let rec next_with_acc acc =
      match e.MoveNext(), acc with
      | true, a when List.length a + 1 = n -&amp;gt;  
        f(List.rev (e.Current :: a))
        next_with_acc []
      | true, _ -&amp;gt; next_with_acc (e.Current :: acc)
      | false, _ -&amp;gt;
        f(List.rev acc)
      ()
    next_with_acc []&amp;nbsp;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&amp;nbsp;&lt;/pre&gt;
That's OK, but it's pretty limited.&amp;nbsp; If what you're doing fits into something like iter, it's good enough.&lt;br /&gt;
&lt;br /&gt;
But what about just transforming the sequence into a new sequence?&amp;nbsp; That seems like a more general solution.&amp;nbsp; So:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;module Seq =  
  let in_groups_of_n n (s: seq&amp;lt;'a&amp;gt;) =
    let rec in_groups_of_n_with_acc n acc (ie: IEnumerator&amp;lt;'a&amp;gt;) =
      seq {
        match ie.MoveNext(), acc with
        | true, a when List.length a + 1 = n -&amp;gt; 
          yield List.rev (ie.Current :: a)
          yield! in_groups_of_n_with_acc n [] ie
        | true, a -&amp;gt; yield! in_groups_of_n_with_acc n (ie.Current :: a) ie
        | false, a when List.length a &amp;gt; 0 -&amp;gt; yield List.rev acc
        | false, a -&amp;gt; ()
      }
    seq {
      yield! in_groups_of_n_with_acc n [] (s.GetEnumerator())
    }    
&lt;/pre&gt;
&lt;br /&gt;
That's pretty good - it gets us to the point where we're returning a real sequence, so it's much more useful than the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iter&lt;/span&gt;-style solution.&lt;br /&gt;
&lt;br /&gt;
But why limit ourselves to lists-of-length-n?&amp;nbsp; Let's turn the accumulator into a function, so you can get any groups you want:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;module Seq =  
  let grouped_by f (s: seq&amp;lt;'a&amp;gt;)=
    let rec grouped_by_with_acc (f: 'a -&amp;gt; 'a list -&amp;gt; 'a list option * 'a list) acc (ie: IEnumerator&amp;lt;'a&amp;gt;) =
      seq {
        if ie.MoveNext()
        then 
          let nextValue, leftovers = f ie.Current acc
          if nextValue.IsSome then yield nextValue.Value
          yield! grouped_by_with_acc f leftovers ie
        else
          if not acc.IsEmpty then yield acc
      }
    seq {
      yield! grouped_by_with_acc f [] (s.GetEnumerator())
    }    

&lt;/pre&gt;
This takes a function that accepts:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The next item in the sequence&lt;/li&gt;
&lt;li&gt;Leftovers from the last run&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
And returns a tuple:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt; An optional value to yield&lt;/li&gt;
&lt;li&gt;Leftovers&lt;/li&gt;
&lt;/ul&gt;
Here's how its used:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;module TestGroupedBy =
  let GroupsOfN n newValue acc =
    let newList = newValue :: acc

    // If we have the right length, return
    // a Some as the first value.  That'll 
    // be yielded by the sequence.
    if List.length acc = n - 1
    then Some (List.rev newList), []
    // If we don't have the right length,
    // use None (so nothing will be yielded)
    else None, newList   
    
  // Note that we're going to pass a curried function - (GroupsOfN 3) is a function
  // taking two arguments, suitable for passing to grouped_by
  let resultWithInts = seq { for i in 1..100 -&amp;gt; i} |&amp;gt; Seq.grouped_by (GroupsOfN 3)
  
  printfn "int result %A" resultWithInts
  
  let resultWithChars = seq { for i in ['a'; 'b'; 'c'; 'd'; 'e'; 'f'] -&amp;gt; i} |&amp;gt; Seq.grouped_by (GroupsOfN 2)
  
  printfn "char result %A" resultWithChars  
&lt;/pre&gt;
&lt;br /&gt;
The results are:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;int result seq [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]; [10; 11; 12]; ...]
char result seq [['a'; 'b']; ['c'; 'd']; ['e'; 'f']]
&lt;/pre&gt;
&lt;br /&gt;
Let's use this with a more interesting grouping function.  Say we want the colors of all the single cows in a list:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;module TestGroupedByWithMatching =
  let Cows newValue acc =
    let newList = newValue :: acc
    match newList with
    | "cow" :: color :: "one" :: t -&amp;gt; Some [color], []
    | a :: b :: t -&amp;gt; None, [a; b]
    | l -&amp;gt; None, newList
    
  let someCows = seq { for i in ["one"; "red"; "cow"; "and"; "one"; "white"; "cow"; "and"; "three"; "green"; "cows"] -&amp;gt; i} |&amp;gt; Seq.grouped_by Cows
  printfn "some cows are %A" someCows
  
// This prints:  
// some cows are seq [["red"]; ["white"]; ["cows"; "green"]]
// &amp;gt; 

&lt;/pre&gt;
So there's a problem - at the end, we're yielding the accumulator.&amp;nbsp; That's what we wanted in the previous examples; we were looking for groups of three, plus the last group of 0, 1, or 2 items.&amp;nbsp; Here, though, if we don't get a match we don't want to see the leftovers.&amp;nbsp; Let's create a new method that takes another function that specifies what to do with the accumulator:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;  let grouped_by_with_leftover_processing f (f2: 'a list -&amp;gt; list&amp;lt;'a&amp;gt; option) (s: seq&amp;lt;'a&amp;gt;)=
    let rec grouped_by_with_acc (f: 'a -&amp;gt; 'a list -&amp;gt; 'a list option * 'a list) acc (ie: IEnumerator&amp;lt;'a&amp;gt;) =
      seq {
        if ie.MoveNext()
        then 
          let nextValue, leftovers = f ie.Current acc
          if nextValue.IsSome then yield nextValue.Value
          yield! grouped_by_with_acc f leftovers ie
        else
          let rems = f2 acc
          if rems.IsSome then yield rems.Value
      }
    seq {
      yield! grouped_by_with_acc f [] (s.GetEnumerator())
    }    
&lt;/pre&gt;
&lt;br /&gt;
Now we can specify a function to use for the leftovers.&amp;nbsp; This time we should get the right cows. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;module TestGroupedByWithMatching =
  let Cows newValue acc =
    let newList = newValue :: acc
    match newList with
    | "cow" :: color :: "one" :: t -&amp;gt; Some [color], []
    | a :: b :: t -&amp;gt; None, [a; b]
    | l -&amp;gt; None, newList
  
  let IgnoreLeftovers f = None
  
  let someCows = seq { for i in ["one"; "red"; "cow"; "and"; "one"; "white"; "cow"; "and"; "three"; "green"; "cows"] -&amp;gt; i}
  let cowColors = someCows |&amp;gt; Seq.grouped_by_with_leftover_processing Cows IgnoreLeftovers
  printfn "cowColors are %A" cowColors
  
// This prints:  
// cowColors are seq [["red"]; ["white"]]

&lt;/pre&gt;
But we've got two separate functions (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;grouped_by_with_leftover_processing and grouped_by&lt;/span&gt;) that duplicate most of their code.&amp;nbsp; grouped_by is just&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; grouped_by_with_leftover_processing &lt;/span&gt;so the final code is:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
module Seq =  
  let grouped_by_with_leftover_processing f (f2: &lt;span class="str"&gt;'a list -&amp;gt; list&amp;lt;'&lt;/span&gt;a&amp;gt; option) (s: seq&amp;lt;&lt;span class="str"&gt;'a&amp;gt;)=
    let rec grouped_by_with_acc (f: '&lt;/span&gt;a -&amp;gt; &lt;span class="str"&gt;'a list -&amp;gt; '&lt;/span&gt;a list option * &lt;span class="str"&gt;'a list) acc (ie: IEnumerator&amp;lt;'&lt;/span&gt;a&amp;gt;) =
      seq {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; ie.MoveNext()
        then 
          let nextValue, leftovers = f ie.Current acc
          &lt;span class="kwrd"&gt;if&lt;/span&gt; nextValue.IsSome then &lt;span class="kwrd"&gt;yield&lt;/span&gt; nextValue.Value
          &lt;span class="kwrd"&gt;yield&lt;/span&gt;! grouped_by_with_acc f leftovers ie
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
          let rems = f2 acc
          &lt;span class="kwrd"&gt;if&lt;/span&gt; rems.IsSome then &lt;span class="kwrd"&gt;yield&lt;/span&gt; rems.Value
      }
    seq {
      &lt;span class="kwrd"&gt;yield&lt;/span&gt;! grouped_by_with_acc f [] (s.GetEnumerator())
    }    

  let YieldReversedLeftovers (f: &lt;span class="str"&gt;'a list) = 
    if f.IsEmpty
    then None
    else Some (List.rev f)

  let grouped_by f s =
    grouped_by_with_leftover_processing f YieldReversedLeftovers s

  let group_by_length_n n s =
    let grouping_function newValue acc =
      let newList = newValue :: acc
      // If we have the right length, return
      // a Some as the first value.  That'&lt;/span&gt;ll 
      &lt;span class="rem"&gt;// be yielded by the sequence.&lt;/span&gt;
      &lt;span class="kwrd"&gt;if&lt;/span&gt; List.length acc = n - 1
      then Some (List.rev newList), []
      &lt;span class="rem"&gt;// If we don't have the right length,&lt;/span&gt;
      &lt;span class="rem"&gt;// use None (so nothing will be yielded)&lt;/span&gt;
      &lt;span class="kwrd"&gt;else&lt;/span&gt; None, newList  
    grouped_by grouping_function s
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4516971425834102644?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4516971425834102644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4516971425834102644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4516971425834102644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4516971425834102644'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/04/f-converting-sequences-to-lists-on-fly.html' title='F# - Converting sequences to lists on the fly'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4785847099373630601</id><published>2009-03-31T17:27:00.000-07:00</published><updated>2009-03-31T17:27:32.021-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bluetooth'/><title type='text'>Bluetooth headset winner – the Jawbone 2</title><content type='html'>I’m using a &lt;a href="http://www.amazon.com/Jawbone-Bluetooth-Headset-NoiseAssassin-Packaged/dp/B001AQYUWC/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=wireless&amp;amp;qid=1238545066&amp;amp;sr=8-1"&gt;Jawbone 2&lt;/a&gt; now.&amp;nbsp; I’ve had it for a couple weeks, and it’s working great.&amp;nbsp; Good sound quality on both sides, works fine outside and in the car.&amp;nbsp; (If you’re buying from Amazon, don’t buy the bulk package version.&amp;nbsp; According to the reviews, it doesn’t come with all the right extra bits.)&amp;nbsp; And make sure you’re getting a version 2, not the original Jawbone – the original is terrible.&lt;br /&gt;
&lt;br /&gt;
The previous headset I tried was a &lt;a href="http://www.amazon.com/gp/product/B001630QZE"&gt;Plantronics Discovery 925&lt;/a&gt;.&amp;nbsp; Indoors, it was fine.&amp;nbsp; Outdoors, it was useless.&amp;nbsp; A slight breeze and the person I was calling said it sounded like I was in a hurricane.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4785847099373630601?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4785847099373630601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4785847099373630601' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4785847099373630601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4785847099373630601'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/bluetooth-headset-winner-jawbone-2.html' title='Bluetooth headset winner – the Jawbone 2'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6489205541692714106</id><published>2009-03-27T16:15:00.001-07:00</published><updated>2009-03-27T17:07:03.008-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Hello, World in F# + WPF</title><content type='html'>Here’s the small version of F# + WPF Hello, world.&amp;nbsp; Note that there’s zero Xaml involved.&lt;br /&gt;
&lt;pre class="csharpcode"&gt;#light

open System
open System.Windows
open System.Windows.Controls

type MainWindow(app: Application) as self =
  inherit Window()
  do
    let button = Button(Content = "Bye")
    button.Click.Add(fun f -&amp;gt; app.Shutdown(0))
    self.Content &amp;lt;- button

type App() =
  inherit Application()
  
  static member Go() =
    let app = new App()
    app.Run(new MainWindow(app, Title = "Hello world")) 
    |&amp;gt; ignore

[&amp;lt;STAThread&amp;gt;] App.Go()&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
 font-size: small;
 color: black;
 font-family: consolas, "Courier New", courier, monospace;
 background-color: #ffffff;
 line-height: 1em;
 background-color: ltgrey;
 /*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
 background-color: #f4f4f4;
 width: 100%;
 margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;br /&gt;
The references are very similar to the C# code:&lt;br /&gt;
&lt;a href="http://lh6.ggpht.com/_3USHh0OQON0/Sc1eIGToSgI/AAAAAAAAAQU/5J4-E6Zz0QU/s1600-h/image%5B3%5D.png"&gt;&lt;img alt="image" border="0" src="http://lh3.ggpht.com/_3USHh0OQON0/Sc1eIa9U0UI/AAAAAAAAAQY/BT1Nk5CPrxM/image_thumb%5B1%5D.png?imgmax=800" style="border-width: 0px; display: inline;" title="image" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6489205541692714106?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6489205541692714106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6489205541692714106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6489205541692714106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6489205541692714106'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/hello-world-in-f-wpf.html' title='Hello, World in F# + WPF'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_3USHh0OQON0/Sc1eIa9U0UI/AAAAAAAAAQY/BT1Nk5CPrxM/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8174623177128319270</id><published>2009-03-26T17:06:00.001-07:00</published><updated>2009-03-27T16:30:43.252-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Starting out with WPF in F# – but first, C#</title><content type='html'>I've started to use F# with WPF, and thought that the best way of going about it would be to start with just bare code for the most stripped-down C# app that would do anything. 

&lt;br /&gt;

&lt;br /&gt;Most of the WPF examples out there start with too much Xaml - seems like it's just going to get in the way for now. 

&lt;br /&gt;

&lt;br /&gt;&lt;a href="http://www.dotnet-blog.com/index.php/2008/04/21/create-wpf-applications-without-xaml/"&gt;Norbert Eder's blog&lt;/a&gt; had the meat of this - I just stripped it down even more. 

&lt;br /&gt;

&lt;br /&gt;

&lt;pre class="csharpcode"&gt;&lt;span style="font-family: consolas; font-size: x-small"&gt;using System;&lt;br /&gt;using System.Windows;&lt;br /&gt;using System.Windows.Controls;&lt;br /&gt;&lt;br /&gt;public class App : Application&lt;br /&gt;{&lt;br /&gt; [STAThread]&lt;br /&gt; static void Main(string[] args)&lt;br /&gt; {&lt;br /&gt;     Application app = new Application();&lt;br /&gt;     app.Run(new MainWindow());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MainWindow : Window&lt;br /&gt;{&lt;br /&gt; public MainWindow()&lt;br /&gt; {&lt;br /&gt;     Button button1 = new Button();&lt;br /&gt;     button1.Content = &amp;quot;Bye&amp;quot;;&lt;br /&gt;     button1.Click += new RoutedEventHandler(button1_Click);&lt;br /&gt;     this.Content = button1;&lt;br /&gt;     this.Title = &amp;quot;Hello world&amp;quot;;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; void button1_Click(object sender, RoutedEventArgs e)&lt;br /&gt; {&lt;br /&gt;     Application.Current.Shutdown(0);&lt;br /&gt; }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;br /&gt;The project only needs a couple references – PresentationCore, PresentationFramework, System, and WindowsBase: 

&lt;br /&gt;

&lt;br /&gt;

&lt;pre class="csharpcode"&gt;&lt;a href="http://lh3.ggpht.com/_3USHh0OQON0/ScwYb1rXUqI/AAAAAAAAAQM/e89_KwQN8ic/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_3USHh0OQON0/ScwYcaHtcVI/AAAAAAAAAQQ/ofPY5CEoG08/image_thumb%5B1%5D.png?imgmax=800" width="505" height="319" /&gt;&lt;/a&gt;  &lt;/pre&gt;

&lt;br /&gt;

&lt;pre class="csharpcode"&gt; &lt;/pre&gt;

&lt;br /&gt;&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
 font-size: small;
 color: black;
 font-family: consolas, "Courier New", courier, monospace;
 background-color: #ffffff;
 line-height: 1em;
 background-color: ltgrey;
 /*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
 background-color: #f4f4f4;
 width: 100%;
 margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8174623177128319270?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8174623177128319270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8174623177128319270' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8174623177128319270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8174623177128319270'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/starting-out-with-wpf-in-f-but-first-c.html' title='Starting out with WPF in F# – but first, C#'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_3USHh0OQON0/ScwYcaHtcVI/AAAAAAAAAQQ/ofPY5CEoG08/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7679642253853222658</id><published>2009-03-10T13:42:00.000-07:00</published><updated>2009-04-08T12:21:14.427-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>F# useful links</title><content type='html'>&lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec2.aspx"&gt;The spec&lt;/a&gt; I use this all the time, for obvious reasons. &lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://proquest.safaribooksonline.com.ezproxy.spl.org:2048/9781590598504/mastering_types_and_generics?displaygrbooks=0"&gt;Expert F#&lt;/a&gt; (I use it on Safari - this is the incomplete/sample Google Books entry)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lorgonblog.spaces.live.com/Blog/cns%21701679AD17B6D310%21894.entry%20"&gt;The basic syntax of F# - classes, interfaces, and members &lt;/a&gt;Useful disection of an F# type declaration&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://en.wikibooks.org/wiki/F_Sharp_Programming"&gt;F Sharp Programming - Wikibooks, collection of open-content textbooks&lt;/a&gt; Occasionally useful, but somewhat out of date.&amp;nbsp; Better to turn to Expert F#.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://cs.hubfs.net/forums/default.aspx"&gt;hubFS forums&lt;/a&gt; Lots of useful information in the hubFS forums.&amp;nbsp; (Think of this as the F# mailing lists; for whatever reason, the F# community seems to prefer forums to mailing lists.)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://blogs.msdn.com/lukeh/archive/2008/09/17/f-september-2008-ctp-known-issues.aspx"&gt;Sep 2008 release known issues&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7679642253853222658?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7679642253853222658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7679642253853222658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7679642253853222658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7679642253853222658'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/f-useful-links.html' title='F# useful links'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6117698608973092612</id><published>2009-03-03T08:25:00.000-08:00</published><updated>2009-03-03T09:53:43.986-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>F#: The type 'MatchCollection' is not compatible with the type 'seq&lt;'a&gt;'.</title><content type='html'>I was trying to use regular expressions with sequences, and ran across this problem.

&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;(new Regex ".*").Matches("foo") |&amp;gt; Seq.iter (fun s -&amp;gt; printfn "s is %A" s);;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;stdin(4,36): error FS0001: The type 'MatchCollection' is not compatible with the type 'seq&amp;lt;'a&amp;gt;'.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt; (new Regex "f.*").Matches("foo") |&amp;gt; Seq.cast |&amp;gt; Seq.iter (fun s -&amp;gt; printfn "s is %A" s);;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;s is foo&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;val it : unit = ()&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&lt;/div&gt;
Turns out MatchCollection implements System.Collections.IEnumerable, not System.Collections.Generic.IEnumerable&amp;lt;T&amp;gt;.  You need to cast it with &lt;span style=";font-family:&amp;quot;;" &gt;Seq.cast&lt;/span&gt; to use it:

&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;(new Regex "f.*").Matches("foo") |&amp;gt; Seq.cast |&amp;gt; Seq.iter (fun s -&amp;gt; printfn "s is %A" s);;&lt;/div&gt;
I got the solution from &lt;a href="http://cs.hubfs.net/forums/thread/9223.aspx"&gt;hubfs &lt;/a&gt;- it's a good place for F# information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6117698608973092612?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6117698608973092612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6117698608973092612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6117698608973092612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6117698608973092612'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/f-type-matchcollection-is-not.html' title='F#: The type &apos;MatchCollection&apos; is not compatible with the type &apos;seq&lt;&apos;a&gt;&apos;.'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3737391744633240541</id><published>2009-03-03T08:07:00.000-08:00</published><updated>2009-06-15T20:28:17.065-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f# fsi'/><title type='text'>F# error talking complaining about FSharp.PowerPack.dll</title><content type='html'>If your F# code compiles, but you see errors like this from fsi: &lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;C:\Users\James\Documents\Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication1\FSharpDictionary.fs(108,13): error FS0039: The value, constructor, namespace or type 'contains' is not defined. A construct with this name was found in FSharp.PowerPack.dll, which contains some modules and types that were implicitly referenced in some previous versions of F#. You may need to add an explicit reference to this DLL in order to compile this code.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt; &lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Make sure you add PowerPack to your session:&lt;br /&gt;
&lt;blockquote&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt; #r "FSharp.PowerPack.dll" ;;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
My problem was that I had added FSharp.PowerPack to the Visual Studio project, but I had forgotten that fsi doesn't pick that up.&lt;br /&gt;
&lt;br /&gt;
And with the new 2010 release, you're going to need to add the location of PowerPack to your search path in fsi.exe:&lt;br /&gt;
 &lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;gt; #r "FSharp.PowerPack.dll" ;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt; #I "C:\Users\James\Documents\Visual Studio 10\Projects\fspowerpack"&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Watch out for quoting backspaces in strings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3737391744633240541?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3737391744633240541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3737391744633240541' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3737391744633240541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3737391744633240541'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/03/f-error-talking-complaining-about.html' title='F# error talking complaining about FSharp.PowerPack.dll'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6592604144579166117</id><published>2009-02-18T12:28:00.000-08:00</published><updated>2009-02-28T13:23:10.218-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Ad hoc documentation</title><content type='html'>So far, the best document for getting out an ad hoc release is:&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/manage/distribution/index.action"&gt;&lt;br /&gt;Program Portal &gt; Distribution &gt; Prepare App&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6592604144579166117?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6592604144579166117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6592604144579166117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6592604144579166117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6592604144579166117'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/ad-hoc-documentation.html' title='Ad hoc documentation'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2723056796931497645</id><published>2009-02-17T13:36:00.000-08:00</published><updated>2009-02-17T13:36:14.801-08:00</updated><title type='text'>Humor in Apple documentation</title><content type='html'>Found in "iPhone Dev Center &amp;gt; iPhone Reference Library &amp;gt; Topics &amp;gt; General &amp;gt; Security Overview &amp;gt; Security Services":&lt;br /&gt;
&lt;blockquote&gt;
The procedure for signing code is not time consuming and requires few resources. See Code Signing Guide for details.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2723056796931497645?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2723056796931497645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2723056796931497645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2723056796931497645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2723056796931497645'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/humor-in-apple-documentation.html' title='Humor in Apple documentation'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-968898443270559816</id><published>2009-02-13T11:05:00.000-08:00</published><updated>2009-03-31T17:20:08.030-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bluetooth'/><title type='text'>Yet another bad bluetooth headset</title><content type='html'>Just got my new &lt;a href="http://www.amazon.com/Aliph-Jawbone-Bluetooth-Headset-Packaged/dp/B000RUPEOA/ref=pd_bbs_sr_2?ie=UTF8&amp;amp;s=electronics&amp;amp;qid=1234551922&amp;amp;sr=8-2"&gt;Aliph Jawbone&lt;/a&gt; bluetooth headset.  It's not quite epic fail, but it's bad.  I could hear the other person fine, but she said I faded in and out - basically transmission quality was completely unacceptable.

It goes into the dustbin along with the Samsung WEP301 (rated "useless junk" for terrible sound quality).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-968898443270559816?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/968898443270559816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=968898443270559816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/968898443270559816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/968898443270559816'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/yet-another-bad-bluetooth-headset.html' title='Yet another bad bluetooth headset'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-1525715861292653812</id><published>2009-02-13T10:49:00.000-08:00</published><updated>2009-02-13T10:50:51.250-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gmail'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Google for domains sync to iPhone</title><content type='html'>To configure the new iPhone sync system for your Google for domains setup, use:
&lt;p&gt;&lt;a href="https://m.google.com/sync/settings/a/example.com/iconfig/" rel="nofollow"&gt;https://m.google.com/sync/settings/a/example.com/iconfig/&lt;/a&gt;&lt;/p&gt;(Where example.com is replaced with your domain)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-1525715861292653812?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/1525715861292653812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=1525715861292653812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1525715861292653812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/1525715861292653812'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/google-for-domains-sync-to-iphone.html' title='Google for domains sync to iPhone'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2847639844033333776</id><published>2009-02-03T16:49:00.000-08:00</published><updated>2009-02-03T16:59:09.453-08:00</updated><title type='text'>Building parameters strings for the iPhone from NSDictionary objects</title><content type='html'>Here's the code I use to build parameters strings for URLs on the iPhone.&amp;nbsp; It adds a method to NSDictionary to convert a dictionary to a parameters string:&lt;br /&gt;
&lt;br /&gt;
&lt;textarea cols="100" rows="40" wrap="off"&gt;@implementation NSString(CallWranglerUtilities)
- (NSString *)stringByAddingPercentEscapesForURI
{
 NSString *reserved = @":/?#[]@!$&amp;amp;'()*+,;=";
 CFStringRef s = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, (CFStringRef)reserved, kCFStringEncodingUTF8);
 return [NSMakeCollectable(s) autorelease];
}
@end

@implementation NSDictionary(CallWranglerUtilities)
- (NSString *) convertDictionaryToURIParameterString
{
 NSMutableArray *elements = [NSMutableArray array];
 for (NSString *k in [self keyEnumerator]) {
  NSString *escapedK = [k stringByAddingPercentEscapesForURI];
  if (![k isEqualToString: @""]) {
   NSString *escapedV = [[self objectForKey: k] stringByAddingPercentEscapesForURI];
   [elements addObject: [NSString stringWithFormat: @"%@=%@", escapedK, escapedV]];
  }
 }
 return [elements componentsJoinedByString:@"&amp;amp;"];
}
@end&amp;nbsp;&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2847639844033333776?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2847639844033333776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2847639844033333776' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2847639844033333776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2847639844033333776'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/parameters-strings-for-iphone.html' title='Building parameters strings for the iPhone from NSDictionary objects'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-4066263829652344282</id><published>2009-02-03T15:54:00.000-08:00</published><updated>2009-02-03T17:13:49.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gdb'/><title type='text'>What that mysterious %al means in gdb</title><content type='html'>If you're looking at Xcode's instruction pane in gdb, and you're on an Intel platform, %al is the least significant byte of the EAX register.  So code that looks like this:
&lt;pre&gt;0x0000661a  &amp;lt;+0251&amp;gt;  call   0x3c21a &amp;lt;&amp;gt;0x0000661f  &amp;lt;+0256&amp;gt;  test   %al,%al0x00006621  &amp;lt;+0258&amp;gt;  jne    0x6650 &amp;lt; -[ConfCallStatusTableViewController mergeConfCallStatusViaNotification:]+305 &amp;gt;&lt;/pre&gt;Translates to:
&lt;ol&gt;&lt;li&gt;Call dyld_stub_objc_msgSend&lt;/li&gt;&lt;li&gt;AND the least significant byte of the EAX register with itself.  The point of this is the side effect - it sets the bits in the EFLAG register that will be used in the jne instruction that's coming next.
&lt;/li&gt;&lt;li&gt;Jump-if-not-equal to -[ConfCallStatusTableViewController mergeConfCallStatusViaNotification:].  jne looks at 'equal' bit that was set in the previous step, and if that bit is set, it jumps.  If it's not set, just continue on to the next instruction.&lt;/li&gt;&lt;/ol&gt;Check out &lt;a href="http://en.wikipedia.org/wiki/X86_assembly_language"&gt;Wikipedia&lt;/a&gt; for a decent simple into to Intel assembly.  I found the note about what %al in a &lt;a href="http://web.cecs.pdx.edu/%7Ebjorn/CS200/linux_tutorial/"&gt;course tutorial&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-4066263829652344282?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/4066263829652344282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=4066263829652344282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4066263829652344282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/4066263829652344282'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/02/what-that-mysterious-al-means-in-gdb.html' title='What that mysterious %al means in gdb'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8138061023430136031</id><published>2009-01-31T08:11:00.001-08:00</published><updated>2009-02-06T19:29:27.637-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><title type='text'>Xcode questions and feature wishes</title><content type='html'>Things I don't know how to do in Xcode, or that Xcode just doesn't do and should:&lt;br /&gt;
&lt;br /&gt;
• Reindent the entire file?  I know you can select text and hit C-Shift-F, that's not quite what I'm talking about.  One button, whole file, don't move my cursor.  Or even better, just turn on the 'always indent my code' mode so I don't have to spend my time thinking about indentation.&lt;br /&gt;
&lt;br /&gt;
• When I finish with run or debug, switch the Xcode back to project mode from debug mode.  Why do I always have to hit C-0?&lt;br /&gt;
&lt;br /&gt;
• Jump through your last N edit locations, across all files?  C-q in NetBeans, I use this constantly.&lt;br /&gt;
&lt;br /&gt;
• Move the current selection (or line, if there's no selection) up/down?&lt;br /&gt;
&lt;br /&gt;
• Duplicate the current selection (or line, if there's no selection) up/down?&lt;br /&gt;
&lt;br /&gt;
• Delete the current line?   I'm aware that I can hit C-l to select the entire line, and then delete it.&lt;br /&gt;
&lt;br /&gt;
• Select by expressions?  One key combo, select my current symbol.  One more to expand it to the enclosing expression, etc, and the same thing going the other way.  I use this all the time in NetBeans.&lt;br /&gt;
&lt;br /&gt;
• Close all editor windows?  Close all closes everything - I just want editor windows to go away, leaving the project window.&lt;br /&gt;
&lt;br /&gt;
• Move to the beginning of the text on a line?  I know Cmd-leftArrow moves to character position 0.&lt;br /&gt;
&lt;br /&gt;
• Show line numbers in the gutter?  I know the line number is shown next to the filename.&lt;br /&gt;
&lt;br /&gt;
• Show an outline of the current file?  I want a navigation pane - show me the methods and fields in the file I'm editing.  Xcode has the information - I want the dropdown menu in a pane somewhere that I can see all the time.&lt;br /&gt;
&lt;br /&gt;
• Edit/create properties?  Properties are painful right now - you have to touch three different places for a single property.&lt;br /&gt;
&lt;br /&gt;
• Edit/create the signature of a method?  Give me one place to edit both the .h and the .m.&lt;br /&gt;
&lt;br /&gt;
• I want vertical editing like TextMate.&lt;br /&gt;
&lt;br /&gt;
• Show me the inheritance tree for the class I'm editing, in a pane.  Parents, siblings, children, selectable.&lt;br /&gt;
&lt;br /&gt;
• How do you use the refactoring features without Xcode blowing up?  OK, more of a rant than a question.  But refactoring crashes Xcode too often - I've stopped using it.&lt;br /&gt;
&lt;br /&gt;
• Refactoring needs to add a 'move' to move methods between classes.&lt;br /&gt;
&lt;br /&gt;
• Transform a method call between all arguments on one line/all arguments on a seperate line.&lt;br /&gt;
&lt;br /&gt;
• In the debugger, if you've set up key value observing on an object, and the object is in an array, you can't see its details.  You just get a NSKVONotifying_Whatever object that you can't drill down into.  This should be fixed.  (If the objects aren't an an array, there's no problem.)&lt;br /&gt;
&lt;br /&gt;
• NSDictionary display in the debugger.  There's no way to drill down into an NSDictionary.&lt;br /&gt;
&lt;br /&gt;
• Jump to a method or class.  In NetBeans, you hit Cmd-O, and the dialog shows you all the available classes.  There's a text box to narrow the list of classes, and you can type #methodName in the box to get methods instead of classes.  I use this constantly. [UPDATE - Dan Wright on the &lt;a href="http://lists.seattlexcoders.org/mailman/listinfo/xcoder-talk"&gt;Seattle Xcoders mailing list&lt;/a&gt; pointed out Cmd-shift-D - very handy]&lt;br /&gt;
&lt;br /&gt;
• Better support for code coverage.&amp;nbsp; Hunting around for *.gcda files isn't a great user experience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8138061023430136031?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8138061023430136031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8138061023430136031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8138061023430136031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8138061023430136031'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/xcode-questions-and-feature-wishes.html' title='Xcode questions and feature wishes'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3681543615439064240</id><published>2009-01-27T23:58:00.001-08:00</published><updated>2009-01-28T00:01:57.882-08:00</updated><title type='text'>This is not the droid you're looking for. Move along, move along.</title><content type='html'>These show up on the console doing a full iPhone restore:&lt;br /&gt;
&lt;br /&gt;
1/27/09 11:57:48 PM [0x0-0x7b07b].com.apple.iTunesHelper[1192] MobileDevice: AMDeviceConnect: This is not the droid you're looking for. Move along, move along.&lt;br /&gt;
1/27/09 11:57:48 PM [0x0-0x7b07b].com.apple.iTunesHelper[1192] MobileDevice: AMDeviceConnect: This is not the droid you're looking for. Move along, move along.&lt;br /&gt;
1/27/09 11:57:48 PM [0x0-0x8f08f].com.apple.iTunes[1288] MobileDevice: AMDeviceConnect: This is not the droid you're looking for. Move along, move along.&lt;br /&gt;
&lt;br /&gt;
Curious.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3681543615439064240?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3681543615439064240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3681543615439064240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3681543615439064240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3681543615439064240'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/this-is-not-droid-youre-looking-for.html' title='This is not the droid you&apos;re looking for. Move along, move along.'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-3567356565256777319</id><published>2009-01-26T12:54:00.000-08:00</published><updated>2009-01-26T13:16:15.646-08:00</updated><title type='text'>When you're loading from a nib file, outlets aren't connected until #loadView is called</title><content type='html'>When you're loading a nib file, the load process is supposed to connect outlets that are set in Interface Builder.  And according to the &lt;span style="font-weight: bold;"&gt;Resource Programming Guide&lt;/span&gt;, in the Nib Object Life Cycle section:
&lt;pre&gt;When you use the methods of NSNib or NSBundle to load and instantiate the objects in a nib file, the
underlying nib-loading code does the following:
...
3. It reestablishes all connections (actions, outlets, and bindings) between objects in the nib file. This
includes connections to File’s Owner and other proxy objects.
&lt;/pre&gt;Having read that bit, I assumed that initWithNibName:bundle: would count as one of those "NSNib or NSBundle" methods.

Wrong.

Instead, the outlets are connected when the view loads.  To figure that out, I just wrote the method to set the outlet I cared about (in this case, it's called editableField) and set a breakpoint in the method.  It's not until loadView happens - here's the full stack trace:
&lt;pre&gt;#0  -[EditTextField setEditableField:] (self=0x10266b0, _cmd=0x2ceb3, f=0x105afd0) at /Users/jamesmoore/dev/CallWrangler/Classes/EditTextField.m:37
#1  0x93ac2cee in -[NSObject(NSKeyValueCoding) setValue:forKey:] ()
#2  0x93b477c1 in -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] ()
#3  0x30c1f907 in -[UIRuntimeOutletConnection connect] ()
#4  0x93e5cc45 in -[NSArray makeObjectsPerformSelector:] ()
#5  0x30c1e455 in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:] ()
#6  0x30c204b8 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:] ()
#7  0x30ac6eca in -[UIViewController _loadViewFromNibNamed:bundle:] ()
#8  0x30ac72af in -[UIViewController loadView] ()
#9  0x30ac7421 in -[UIViewController view] ()
#10 0x30acb01d in -[UIViewController(UIViewControllerContentScrollView) contentScrollView] ()
#11 0x30acd415 in -[UINavigationController _startTransition:fromViewController:toViewController:] ()
#12 0x30acdd23 in -[UINavigationController pushViewController:transition:forceImmediate:] ()
#13 0x30acd95d in -[UINavigationController pushViewController:animated:] ()
#14 0x0001f157 in -[SavedListViewController pushEditingViewForListNamed:] (self=0x1035630, _cmd=0x2b9d4, name=0x1040dd0) at /Users/jamesmoore/dev/CallWrangler/Classes/SavedListViewController.m:115
#15 0x0001f72b in -[SavedListViewController tableView:didSelectRowAtIndexPath:] (self=0x1035630, _cmd=0x30c624d0, tableView=0x103a370, indexPath=0x10402f0) at /Users/jamesmoore/dev/CallWrangler/Classes/SavedListViewController.m:182
#16 0x30a8f74d in -[UITableView(_UITableViewPrivate) _sendSelectionDidChange] ()
#17 0x30a96b4c in -[UITableView touchesEnded:withEvent:] ()
#18 0x30a6790f in -[UIWindow sendEvent:] ()
#19 0x30a56ff7 in -[UIApplication sendEvent:] ()
#20 0x30a561d8 in _UIApplicationHandleEvent ()
#21 0x31563dea in SendEvent ()
#22 0x3156640c in PurpleEventTimerCallBack ()
#23 0x93dee5f5 in CFRunLoopRunSpecific ()
#24 0x93deecd8 in CFRunLoopRunInMode ()
#25 0x31564600 in GSEventRunModal ()
#26 0x315646c5 in GSEventRun ()
#27 0x30a4ec98 in -[UIApplication _run] ()
#28 0x30a5a094 in UIApplicationMain ()
#29 0x0001c620 in main (argc=1, argv=0xbffff044) at /Users/jamesmoore/dev/CallWrangler/main.m:33
(gdb)
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-3567356565256777319?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/3567356565256777319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=3567356565256777319' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3567356565256777319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/3567356565256777319'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/when-youre-loading-from-nib-file.html' title='When you&apos;re loading from a nib file, outlets aren&apos;t connected until #loadView is called'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-7211479195543818361</id><published>2009-01-26T11:36:00.000-08:00</published><updated>2009-02-17T13:23:14.244-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Useful threads on the Apple developer forum</title><content type='html'>I'm going to start collecting the URLs of particularly useful threads in the Developer Forums here.&lt;br /&gt;
&lt;br /&gt;&lt;a href="https://devforums.apple.com/message/1814#1814" onclick="'s_objectID="&gt;Bug with UITableView, Swipes and Controls in Cells&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://devforums.apple.com/message/3711#3711" onclick="'s_objectID="&gt;Loupe in scrolling UITableView&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://devforums.apple.com/message/12011#12011" onclick="s_objectID=&amp;quot;https://devforums.apple.com/message/12011#12011_1&amp;quot;;return this.s_oc?this.s_oc(e):true"&gt;Responding to view controller memory warnings&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://devforums.apple.com/message/12872#12872" onclick="s_objectID=&amp;quot;https://devforums.apple.com/message/12872#12872_1&amp;quot;;return this.s_oc?this.s_oc(e):true"&gt;code signing provisioning profile&lt;/a&gt; - information about signing and ad hoc distribution&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-7211479195543818361?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/7211479195543818361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=7211479195543818361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7211479195543818361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/7211479195543818361'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/useful-threads-on-apple-developer-forum.html' title='Useful threads on the Apple developer forum'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-5440974542321533046</id><published>2009-01-26T10:44:00.000-08:00</published><updated>2009-01-26T17:03:44.171-08:00</updated><title type='text'>Problem with copyplist (caused by an Apple bug + Ruby macports install)</title><content type='html'>I was trying to build a copy of the example code &lt;b&gt;EditableDetailView&lt;/b&gt;, and I was getting an error when the build tried to run &lt;b&gt;copyplist&lt;/b&gt;:

Building target “EditableDetailView” of project “EditableDetailView” with configuration “Debug”Checking DependenciesPBXCp build/Debug-iphonesimulator/EditableDetailView.app/appData.plist appData.plist    cd /Users/jamesmoore/dev/EditableDetailView    setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"    /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks /Users/jamesmoore/dev/EditableDetailView/appData.plist /Users/jamesmoore/dev/EditableDetailView/build/Debug-iphonesimulator/EditableDetailView.appCopyPlistFile /Users/jamesmoore/dev/EditableDetailView/build/Debug-iphonesimulator/EditableDetailView.app/appData.plist appData.plist    cd /Users/jamesmoore/dev/EditableDetailView    setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"    /Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist appData.plist --outdir /Users/jamesmoore/dev/EditableDetailView/build/Debug-iphonesimulator/EditableDetailView.apperror: can't exec '/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist' (No such file or directory)


The first check I did was to make sure I had copyplist somewhere on the system:
&lt;pre&gt;jamesmoore@james-moores-macbook-pro:~$ locate copyplist/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist&lt;/pre&gt;That's not in my normal path, but I didn't expect it to be.And anyway, XCode's build is calling copyplist from a specific location anyway - it wants &lt;span style=";font-family:&amp;quot;;" &gt;/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist&lt;/span&gt; and doesn't care about the path.

There's a file at &lt;span style=";font-family:&amp;quot;;" &gt;/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist&lt;/span&gt; and it looks fine.  But when I try to run it, I get the same thing:
&lt;pre&gt;[james-moores-macbook-pro:~/dev/EditableDetailView] jamesmoore% /Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copyplist: Command not found.&lt;/pre&gt;So I open the file, and see the problem immediately on line 1:

&lt;pre&gt;#!/usr/bin/ruby&lt;/pre&gt;
Of course there's no &lt;span style=";font-family:&amp;quot;;" &gt;/usr/bin/ruby&lt;/span&gt; - I do Ruby development, and since Apple ships a version of Ruby that was current back when dinosaurs roamed the earth, I install the macports version.  And that goes in /opt/local/bin, not /usr/bin.

It's an Apple bug - hardcoding the location of Ruby is wrong.  The line should be:

&lt;pre&gt;#!/usr/bin/env ruby&lt;/pre&gt;
The workaround is just to link the good Ruby to the old, bad location:

&lt;pre&gt;sudo ln -s /opt/local/bin/ruby /usr/bin/&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-5440974542321533046?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/5440974542321533046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=5440974542321533046' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5440974542321533046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5440974542321533046'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/problem-with-copyplist-caused-by-apple.html' title='Problem with copyplist (caused by an Apple bug + Ruby macports install)'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6960578570185946566</id><published>2009-01-19T16:45:00.000-08:00</published><updated>2009-01-19T16:47:15.032-08:00</updated><title type='text'>Installing mysql gem on MacOS</title><content type='html'>&lt;a href="http://codeintensity.blogspot.com/2007/09/installing-ruby-mysql-gem-with-macports.html"&gt;Chris Bailey's blog&lt;/a&gt; had the quick answer for how to install the mysql gem in MacOS when you're using the macports mysql:&lt;br /&gt;
 &lt;br /&gt;
sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-include=/opt/local/include/mysql5 --with-mysql-lib=/opt/local/lib/mysql5 --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6960578570185946566?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6960578570185946566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6960578570185946566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6960578570185946566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6960578570185946566'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/installing-mysql-gem-on-macos.html' title='Installing mysql gem on MacOS'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2055775591583942092</id><published>2009-01-14T07:52:00.000-08:00</published><updated>2009-01-14T07:57:18.427-08:00</updated><title type='text'>screen (as in old-school unix screen) on the mac - UTF8</title><content type='html'>I finally got around to figuring out screen - should have done it years ago. 

On a Mac, you're going to get a LANG default like this:
&lt;blockquote&gt;LANG=en_US.UTF-8
&lt;/blockquote&gt;You'll need to put this in your ~/.screenrc:
&lt;blockquote&gt;defutf8 on&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2055775591583942092?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2055775591583942092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2055775591583942092' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2055775591583942092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2055775591583942092'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/screen-as-in-old-school-unix-screen-on.html' title='screen (as in old-school unix screen) on the mac - UTF8'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-57997614149566837</id><published>2009-01-11T17:35:00.000-08:00</published><updated>2009-01-11T18:10:26.895-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>How to get symbolic stack traces on an iPhone exception</title><content type='html'>Very useful post from &lt;a href="http://rel.me/2008/12/30/getting-a-useful-stack-trace-from-nsexception-callstackreturnaddresses/"&gt;Gabriel Handford&lt;/a&gt; about getting symbolic information in stack traces.  Good followup article from &lt;a href="http://www.benchatelain.com/2009/01/04/stack-traces-for-iphone-development/"&gt;Ben Chatelain&lt;/a&gt; about some missing pieces.

Gabriel said "For me, DEBUG is set in GCC_PREPROCESSOR_DEFINITIONS via the awesome GTM &lt;a href="http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/?r=73#trunk/XcodeConfig/Project"&gt;xcconfg&lt;/a&gt; files, which you should also be using," but since I'm not using them, I just added DEBUG to the command line.  (Cmd-I on the target &gt; Build &gt; Preprocessor macros).

I hit the same issue with NSDebug that Ben had, and copying the file over seems to solve the problem with running on the device itself and not just the simulator.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-57997614149566837?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/57997614149566837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=57997614149566837' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/57997614149566837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/57997614149566837'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/how-to-get-symbolic-stack-traces-on.html' title='How to get symbolic stack traces on an iPhone exception'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2803470271386425827</id><published>2009-01-10T09:23:00.001-08:00</published><updated>2009-01-10T09:33:12.876-08:00</updated><title type='text'>Technical blogs I read regularly</title><content type='html'>&lt;script type="text/javascript" src="http://www.google.com/reader/ui/publisher-en.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://www.google.com/reader/public/javascript-sub/user/12195267060145408226/label/iPhone?callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22iPhone%20blogs%22%2Cb%3A%22true%22%7D)%3Bnew%20GRC"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="http://www.google.com/reader/ui/publisher-en.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://www.google.com/reader/public/javascript-sub/user/12195267060145408226/label/ruby?callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22Ruby%20blogs%22%2Cb%3A%22true%22%7D)%3Bnew%20GRC"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="http://www.google.com/reader/ui/publisher-en.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://www.google.com/reader/public/javascript-sub/user/12195267060145408226/label/seattle-tech?callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22Seattle%20technology%20blogs%22%2Cb%3A%22true%22%7D)%3Bnew%20GRC"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="http://www.google.com/reader/ui/publisher-en.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://www.google.com/reader/public/javascript-sub/user/12195267060145408226/label/FunctionalProgramming?callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22Functional%20programming%22%2Cb%3A%22true%22%7D)%3Bnew%20GRC"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2803470271386425827?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2803470271386425827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2803470271386425827' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2803470271386425827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2803470271386425827'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/seattle-technology-blogs.html' title='Technical blogs I read regularly'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-265113782700332454</id><published>2009-01-01T10:23:00.000-08:00</published><updated>2009-03-31T17:20:08.030-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bluetooth'/><title type='text'>Don't run your bluetooth headset through the wash</title><content type='html'>Turns out a &lt;a href="http://www.amazon.com/gp/product/B000GAO9T2/ref=pe_11540_10938070_ae_tit_a1/"&gt;Samsung WEP200&lt;/a&gt; doesn't survive a pass through the washing machine + dryer.  Second bluetooth headset I've killed that way.  You'd think I would have learned by now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-265113782700332454?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/265113782700332454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=265113782700332454' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/265113782700332454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/265113782700332454'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2009/01/dont-run-your-bluetooth-headset-through.html' title='Don&apos;t run your bluetooth headset through the wash'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2999608372524389074</id><published>2008-12-27T19:17:00.000-08:00</published><updated>2008-12-27T19:25:29.256-08:00</updated><title type='text'>Salty language</title><content type='html'>Ever need to sound really salty?&amp;nbsp; The &lt;a href="http://books.google.com/books?id=9-qcUbxKVUkC&amp;amp;pg=PA99&amp;amp;lpg=PA99&amp;amp;dq=square-rigger+point+into+the+wind&amp;amp;source=bl&amp;amp;ots=O3ydG5HTep&amp;amp;sig=bxP0mnrcaL9kEzqGOWkEYXYCI2E&amp;amp;hl=en&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;resnum=1&amp;amp;ct=result#PPA76,M1"&gt;Eagle's&lt;/a&gt; seamanship manual is on Google!&lt;br /&gt;
&lt;br /&gt;
Never forget that when a squall approaches, it is prudent to fake out the spanker.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2999608372524389074?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2999608372524389074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2999608372524389074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2999608372524389074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2999608372524389074'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/salty-language.html' title='Salty language'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-8293723392210624809</id><published>2008-12-12T17:43:00.000-08:00</published><updated>2008-12-12T18:44:19.139-08:00</updated><title type='text'>NSLog with the current selector, __LINE__, __FILE__</title><content type='html'>This is a handy bit of code I sprinkle in as a quick debug printf:&lt;br /&gt;
&lt;textarea rows=5 cols=80 wrap=off&gt;
#define NSLogHereIAm() NSLog(@"got selector %@ at line %d, file %s", \
    NSStringFromSelector(_cmd), __LINE__, __FILE__)
&lt;/textarea&gt;&lt;br /&gt;
Just put it in wherever you want to see that your code executed:&lt;br /&gt;
&lt;textarea&gt;int x = 3;
NSLogHereIAm();
[foo bar];
&lt;/textarea&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-8293723392210624809?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/8293723392210624809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=8293723392210624809' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8293723392210624809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/8293723392210624809'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/nslog-with-current-selector.html' title='NSLog with the current selector, __LINE__, __FILE__'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2492145954037964224</id><published>2008-12-11T08:38:00.001-08:00</published><updated>2008-12-12T18:49:41.006-08:00</updated><title type='text'>iPhone class at the junior college across the bay</title><content type='html'>Stanford's &lt;a href="http://www.stanford.edu/class/cs193p/cgi-bin/index.php"&gt;iPhone programming class&lt;/a&gt; - keep hearing it's useful, but haven't checked it out myself yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2492145954037964224?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2492145954037964224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2492145954037964224' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2492145954037964224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2492145954037964224'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/stanfords-iphone-programming-class-keep.html' title='iPhone class at the junior college across the bay'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-5402407561921425649</id><published>2008-12-10T10:33:00.000-08:00</published><updated>2008-12-11T09:47:30.468-08:00</updated><title type='text'></title><content type='html'>&lt;a href="http://www.se-radio.net/"&gt;http://www.se-radio.net/&lt;/a&gt; is my current favorite for technical podcasts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-5402407561921425649?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/5402407561921425649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=5402407561921425649' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5402407561921425649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/5402407561921425649'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/httpwww.html' title=''/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-2039390955914224204</id><published>2008-12-09T19:37:00.000-08:00</published><updated>2009-04-23T17:33:26.506-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Cocoa things I can never remember</title><content type='html'>&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;span style="font-size: 100%;"&gt;• UIView frame:&lt;/span&gt;&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-size: 100%;"&gt;In superview coordinates.  Changing this moves the view but doesn't redraw.&lt;/span&gt;&lt;/blockquote&gt;
&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;• UIView bounds:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-size: 100%;"&gt;From 0,0.  It's the size of the view.&lt;/span&gt;&lt;/blockquote&gt;
&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;• The indicators on things like voicemail (to tell you you have N voicemails) are &lt;span style="font-weight: bold;"&gt;badges&lt;/span&gt;.  Set them with the &lt;span style="font-weight: bold;"&gt;badgeValue&lt;/span&gt; property.&lt;br /&gt;
&lt;br /&gt;
• Nib files - most objects are going to get an &lt;span style="font-weight: bold;"&gt;initWithCoder:&lt;/span&gt; message when they're instantiated.  See the Resource Programming Guide, The Nib Object Life Cycle.&lt;br /&gt;
&lt;br /&gt;
• &lt;a href="http://iphoneincubator.com/blog/tutorial/how-to-create-an-iphone-preferences-file"&gt;Creating preference files&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-2039390955914224204?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/2039390955914224204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=2039390955914224204' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2039390955914224204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/2039390955914224204'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/cocoa-things-i-can-never-remember.html' title='Cocoa things I can never remember'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6383445486649788437</id><published>2008-12-05T10:55:00.001-08:00</published><updated>2008-12-05T12:15:36.326-08:00</updated><title type='text'>Setting up Twinkle and asterisk on the same machine</title><content type='html'>If you want to use Twinkle on the same machine as your asterisk instance, you'll need to change the SIP port that Twinkle uses.

Assuming asterisk is up an running, you'll get this error message when you start Twinkle:

&lt;span style="font-weight: bold;"&gt;Failed to create a UDP socket (SIP) on port 5060&lt;/span&gt;
&lt;span style="font-weight: bold;"&gt;Address already in use&lt;/span&gt;

Hit "System Settings" on this screen:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_3USHh0OQON0/STmJWOD2HNI/AAAAAAAAAPI/UgaoVfSxCIc/s1600-h/Screenshot-Twinkle+-+Select+user+profile.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 267px;" src="http://2.bp.blogspot.com/_3USHh0OQON0/STmJWOD2HNI/AAAAAAAAAPI/UgaoVfSxCIc/s320/Screenshot-Twinkle+-+Select+user+profile.png" alt="" id="BLOGGER_PHOTO_ID_5276399453265599698" border="0" /&gt;&lt;/a&gt;

And then choose network:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_3USHh0OQON0/STmJjKiZ3GI/AAAAAAAAAPQ/nv335289jiI/s1600-h/Screenshot-Twinkle+-+System+Settings.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 274px;" src="http://1.bp.blogspot.com/_3USHh0OQON0/STmJjKiZ3GI/AAAAAAAAAPQ/nv335289jiI/s320/Screenshot-Twinkle+-+System+Settings.png" alt="" id="BLOGGER_PHOTO_ID_5276399675658329186" border="0" /&gt;&lt;/a&gt;

Change the SIP port to 5061 and it'll start up and connect to your local asterisk instance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6383445486649788437?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6383445486649788437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6383445486649788437' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6383445486649788437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6383445486649788437'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/setting-up-twinkle-to-talk-to-asterisk.html' title='Setting up Twinkle and asterisk on the same machine'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_3USHh0OQON0/STmJWOD2HNI/AAAAAAAAAPI/UgaoVfSxCIc/s72-c/Screenshot-Twinkle+-+Select+user+profile.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7318253809178612591.post-6403917278600814056</id><published>2008-12-01T22:27:00.000-08:00</published><updated>2008-12-01T22:34:28.550-08:00</updated><title type='text'>Moving from Mephisto to Blogspot</title><content type='html'>I thought I needed to move my &lt;a href="http://blog.restphone.com/"&gt;old blog&lt;/a&gt; from Mephisto to here.&lt;br /&gt;
&lt;br /&gt;
It looks like the way to do it would be to go via WordPress using &lt;a href="http://schwuk.com/articles/2008/03/25/thy-will-be-done-m2wppy-is-released"&gt;this tool&lt;/a&gt;, and then to Blogspot using &lt;a href="http://www.codesimple.net/2007/10/wordpress-to-blogger.html"&gt;this&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Eventually I'll get around to making that happen.  But when I was going through my old posts, I realized that most of what was there dated fairly quickly.  I'll probably just move over a couple posts by hand and not worry about the others.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7318253809178612591-6403917278600814056?l=blog.restphone.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.restphone.com/feeds/6403917278600814056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7318253809178612591&amp;postID=6403917278600814056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6403917278600814056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7318253809178612591/posts/default/6403917278600814056'/><link rel='alternate' type='text/html' href='http://blog.restphone.com/2008/12/moving-from-mephisto-to-blogspot.html' title='Moving from Mephisto to Blogspot'/><author><name>James Moore</name><uri>https://profiles.google.com/110159643929963265945</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-Sb-Hj-bQxiI/AAAAAAAAAAI/AAAAAAAAAAA/-Osm_xgMyj8/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
