<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Frank Schmitt</title>
    <subtitle>Writing on software, design, and whatever else holds still long enough.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://frankschmitt.org/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://frankschmitt.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-30T00:00:00+00:00</updated>
    <id>https://frankschmitt.org/atom.xml</id>
    <entry xml:lang="en">
        <title>What I Learned Publishing an iOS SDK for 10 Years</title>
        <published>2026-09-30T00:00:00+00:00</published>
        <updated>2026-09-30T00:00:00+00:00</updated>
        
        <author>
          <name>Frank Schmitt</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/"/>
        <id>https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/</id>
        
        <content type="html" xml:base="https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/">&lt;p&gt;Until a couple of weeks ago, I was responsible for building, maintaining, and releasing updates to an SDK for iOS apps called ApptentiveKit. It’s a customer-feedback SaaS product primarily aimed at consumer-focused apps. There’s also an Android version, as well as wrapper SDKs for Flutter, React Native, Cordova and .NET MAUI (as well as one that I recently completed but that hasn’t released yet).&lt;/p&gt;
&lt;p&gt;That SDK’s job is to connect your app to the backend API, while also presenting some user-facing UI where needed.&lt;/p&gt;
&lt;p&gt;The feature that would get customers in the door (and did legitimately make number go up) was improving app ratings by way of trying to prod normies into reviewing the app in the App Store, an activity which will otherwise be dominated by a smattering of superfans and a horde of detractors.&lt;/p&gt;
&lt;p&gt;A secondary aim was to redirect complaints and confusion from a bad App Store review (which at the time it launched couldn’t be replied to) to an actual two-way feedback mechanism. Basically the old “If you love our service, tell your friends, and if you don’t, tell us” sign in code form.&lt;/p&gt;
&lt;p&gt;The SDK has made it into roughly a thousand apps, and has run on hundreds of millions of devices. If an app on your iPhone ever asked you “Do you love $AppName”, that was probably my code. I’m sorry.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A quick note on terminology: I’m going to use our internal guideline and refer to the company paying for our SaaS as the &lt;em&gt;customer&lt;/em&gt;, and the people actually using the app (and the handful of pieces of user-facing UI in the SDK) as the &lt;em&gt;consumer&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I joined Apptentive in April of 2015 along with five other new hires, becoming part of a company that had a couple dozen employees. The SDK I inherited was a four-year-old Objective-C codebase (with manual reference counting) that had grown out of a hackathon project.&lt;/p&gt;
&lt;p&gt;It did the job, but there were some issues below the surface: it used &lt;code&gt;NSUserDefaults&lt;/code&gt; for nearly all persistence (with a smattering of Core Data), almost every internal call was routed back through the &lt;code&gt;[ApptentiveConnection sharedConnection]&lt;/code&gt; singleton, and most everything was happening on the main thread.&lt;/p&gt;
&lt;p&gt;Over the years—largely on my own but with occasional help—I was able to shore up the reliability of that SDK: a more testable persistence system using &lt;code&gt;NSCoding&lt;/code&gt;, a more observable logic engine (compared with the &lt;code&gt;NSPredicate&lt;/code&gt;-based one it replaced), and most processing taking place off the main thread.&lt;/p&gt;
&lt;p&gt;Then around 2020 I was given the opportunity to start fresh with a rewrite of the SDK in Swift. While this was costly, and required maintaining two completely separate codebases, in the intervening years it paid off handsomely in terms of reliability and ease of adding features.&lt;/p&gt;
&lt;p&gt;Over that time I’ve collected a number of observations and lessons, which I present to you here in the form of Ten Commandments of SDK publishing:&lt;/p&gt;
&lt;ol type=&quot;I&quot;&gt;
  &lt;li&gt;Don’t crash the customer’s app&lt;/li&gt;
  &lt;li&gt;Don’t break the customer’s build&lt;/li&gt;
  &lt;li&gt;The SDK should do as little as possible&lt;/li&gt;
  &lt;li&gt;Avoid development dependencies&lt;/li&gt;
  &lt;li&gt;The app-facing API should be idiomatic to the platform&lt;/li&gt;
  &lt;li&gt;Avoid third-party dependencies&lt;/li&gt;
  &lt;li&gt;Add a kill switch&lt;/li&gt;
  &lt;li&gt;Add monitoring&lt;/li&gt;
  &lt;li&gt;UI should match the platform&lt;/li&gt;
  &lt;li&gt;Customers won’t use that&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;i-don-t-crash-the-customer-s-app&quot;&gt;I: Don’t Crash the Customer’s App&lt;/h2&gt;
&lt;p&gt;The likelihood that your SDK is the thing standing between your customer and untold riches is slim. The likelihood that your SDK is the reason a &lt;em&gt;consumer&lt;/em&gt; installed the app on their phone is basically zilch.&lt;/p&gt;
&lt;p&gt;This means that the SDK going into a failsafe do-nothing mode is &lt;em&gt;vastly&lt;/em&gt; preferable to something in the SDK crashing the whole app.&lt;/p&gt;
&lt;p&gt;There are of course easy-to-avoid sources of potential crashes, like force unwrapping an optional, and slightly more subtle ones like array out-of-bounds and—now largely a thing of the past—&lt;code&gt;UITableView&lt;/code&gt; internal inconsistency exceptions. But there’s also that innocent-looking view-sizing code with a divide-by-zero condition that’s only triggered when an image fails to load.&lt;/p&gt;
&lt;h2 id=&quot;ii-don-t-break-the-customer-s-build&quot;&gt;II: Don’t Break the Customer’s Build&lt;/h2&gt;
&lt;p&gt;Again, aside from conscientiousness, this only requires a bit of self-awareness on the part of the SDK developer to realize that their SDK is at best an ancillary feature of the customer’s app.&lt;/p&gt;
&lt;p&gt;We strove to make our SDK respect the conventions of semantic versioning, but there were a few times when we fell short: a new API added during a patch release, or that one time the new guy corrected the spelling of a property without preserving a deprecated copy with the incorrect spelling (and I didn’t catch it in my code review).&lt;/p&gt;
&lt;p&gt;Customers’ developers want to think about your SDK as little as possible, and the best way to avoid their ire is for a minor or patch version upgrade to Just Work.&lt;/p&gt;
&lt;h2 id=&quot;iii-the-sdk-should-do-as-little-as-possible&quot;&gt;III: The SDK Should Do as Little as Possible&lt;/h2&gt;
&lt;p&gt;Some parts of an SDK need to run on the device. Things like consumer-facing UI, offline capability, persistence, and the client-side code involved in communicating with an API.&lt;/p&gt;
&lt;p&gt;At the same time some parts of the overall system only really make sense to run on a server, quite possibly one that you control.&lt;/p&gt;
&lt;p&gt;There’s a third category of code that could theoretically run on either the device or the server (for example, assembling the instructions for how to answer a survey question), and the rule for this is almost always that it should run on the server.&lt;/p&gt;
&lt;p&gt;The reason for this is twofold: First, SDK Code is Forever.&lt;/p&gt;
&lt;p&gt;If you publish an app with any appreciable reach, chances are excellent that there will be a version installed somewhere that will literally never be updated. If your product is an SDK, the situation is several times worse: you have to publish a release of your SDK with the updated code, your customer has to migrate their app to your new SDK version, and then release an updated version of their app, and finally the consumer has to be convinced to install the updated app. Any one of these steps could simply never happen, and all but the first are out of your control. This sucks if there’s a minor UI glitch. This &lt;em&gt;really&lt;/em&gt; sucks if there’s a runaway condition that hammering your server or requires an ugly workaround.&lt;/p&gt;
&lt;p&gt;Secondly, few SDKs are published for a single platform. Chances are your iOS SDK will have an Android counterpart, and quite possibly even a web version. If you want to avoid development dependencies (see below) this means you’ll be writing the same code at least twice (and possibly several times) in different languages and with standard libraries that have significantly different capabilities.&lt;/p&gt;
&lt;p&gt;Both the lack of updatability and the likely requirement to reimplement features in several languages point to erring on the side of server-side code whenever it’s in question.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fn-1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;iv-avoid-development-dependencies&quot;&gt;IV: Avoid Development Dependencies&lt;/h2&gt;
&lt;p&gt;There exist a few tools that promise the ability to ship the same code on multiple platforms: from cross-platform app development tools like Flutter and React Native, to compilation tools like Kotlin Multiplatform and Swift Android.&lt;/p&gt;
&lt;p&gt;If you publish an app, it’s worth considering whether these sorts of tools make sense (although again, it’s preferable to just run on your server wherever that’s practical).&lt;/p&gt;
&lt;p&gt;If you publish an SDK, one of the hardest problems is getting customers to actually integrate with your SDK (we had customers with a signed contract and monthly/annual payments flowing who might wait &lt;em&gt;months&lt;/em&gt; to actually get around to integrating).&lt;/p&gt;
&lt;p&gt;Even customers with a sophisticated web presence might lack the in-house expertise to publish or update a mobile app, so often their mobile development work is outsourced. In that case any friction in integrating your SDK may well show up as actual billable hours in your customer’s outsourcing contract, and that’s likely to color their opinion of your product at renewal time.&lt;/p&gt;
&lt;p&gt;One way to greatly complicate the integration process is, for example, to require an iOS developer to install a Kotlin toolchain simply to continue to build their app after your SDK is integrated.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fn-2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; But even something as commonplace as Fastlane or CocoaPods can be a stumbling block if your customer doesn’t have a working Ruby environment.&lt;/p&gt;
&lt;p&gt;You should strive to have your SDK integrate cleanly on a development machine with nothing installed other than the typical toolchain used by a developer of the platform in question.&lt;/p&gt;
&lt;h2 id=&quot;v-your-api-should-be-idiomatic-to-the-platform&quot;&gt;V: Your API Should be Idiomatic to the Platform&lt;/h2&gt;
&lt;p&gt;As a corollary to the previous, the folks integrating your SDK likely live and breathe the platform they’re developing for, and can sniff out an awkward or non-idiomatic API from a mile away. They’ll expect your API to be similar to first-party APIs on their favored platform, and appreciate using platform-specific language features (like Swift’s subscripting).&lt;/p&gt;
&lt;p&gt;This sometimes means compromising on cross-platform consistency. For example our SDK’s methods were almost all static methods on a class for Android, and instance methods on a singleton on iOS.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fn-3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;vi-avoid-third-party-dependencies&quot;&gt;VI: Avoid Third-Party Dependencies&lt;/h2&gt;
&lt;p&gt;Another excellent way to frustrate a developer trying to integrate your SDK is to introduce some flavor of “dependency hell” alongside your SDK.&lt;/p&gt;
&lt;p&gt;This isn’t a hard-and-fast rule, but if there’s a straightforward way to just reimplement something simple that you might (in the context of an app) just use a library for, it’s probably worth just reimplementing it (and hopefully leaving out any expensive bits of generality). Particularly with agentic coding, it’s often easier to generate a small piece of what might otherwise be library code than to introduce a dependency that your customers will have to manage.&lt;/p&gt;
&lt;h2 id=&quot;vii-add-a-kill-switch&quot;&gt;VII: Add a Kill Switch&lt;/h2&gt;
&lt;p&gt;This is one that we learned (and acted on) relatively late. The best time to add a kill switch to your SDK is before you publish the first version. The second best time is now.&lt;/p&gt;
&lt;p&gt;There will likely come a day when a customer does something unexpected, or simply reaches a scale that your infrastructure will struggle under, where you’ll be well-served by an ability to throttle or even disable your SDK’s functionality remotely.&lt;/p&gt;
&lt;p&gt;This is doubly true if the customer has churned and—often only through the fault of consumers who don’t update their app—is still sending traffic.&lt;/p&gt;
&lt;h2 id=&quot;viii-add-monitoring&quot;&gt;VIII: Add Monitoring&lt;/h2&gt;
&lt;p&gt;By successfully obeying the first commandment (don’t crash), you do sacrifice one channel for conveying the fact that something went wrong in your code, namely crash reports.&lt;/p&gt;
&lt;p&gt;In place of crashing, the SDK will likely simply log the failure and continue on its way.&lt;/p&gt;
&lt;p&gt;This has two downsides: first, customers or consumers could be experiencing frustrating failures—with no indication as to the cause—and you might very well be completely unaware of it happening.&lt;/p&gt;
&lt;p&gt;The second is that a change to your server could abruptly break a large fraction of your SDK’s installed base (possibly even causing crashes), and you’ll only learn about this after your customers start complaining. Having an early warning that something went wrong is extremely valuable.&lt;/p&gt;
&lt;h2 id=&quot;ix-ui-should-match-the-platform&quot;&gt;IX: UI should match the platform&lt;/h2&gt;
&lt;p&gt;There’s a widespread tendency among product and design folks to attempt to make user-facing interface elements be as identical as possible across platforms. I suspect this is because this is pretty explicitly the goal when developing for web: customers might very well access your website from different browsers, and will be confused if things look or work differently.&lt;/p&gt;
&lt;p&gt;But users switching platforms (either hour-to-hour or, really, ever) is pretty rare compared with users who expect the UI to work like every other app on their phone.&lt;/p&gt;
&lt;p&gt;A desire for brand consistency across platforms is perfectly natural, but consumers are much more likely to have used other apps on their platform than your app on another platform.&lt;/p&gt;
&lt;h2 id=&quot;x-customers-won-t-use-that&quot;&gt;X: Customers won’t use that&lt;/h2&gt;
&lt;p&gt;This last one is a bit of a downer, but one of the hard lessons that I learned over the last decade is that a cool new capability I added to the SDK is most often met by customers’ developers staying away in droves.&lt;/p&gt;
&lt;p&gt;When I did the Big Swift Rewrite one of the shortcomings of the Objective-C SDK that we wanted to address was the difficulty of customizing the consumer-facing interface elements beyond the basics of fonts and colors.&lt;/p&gt;
&lt;p&gt;So we designed the UI around an MVVM design pattern, with the goal that customer with heavy customization needs could reimplement (or subclass) our view controllers and use our view models to drive them. This would allow extreme freedom in customization without requiring the customer to fork our SDK.&lt;/p&gt;
&lt;p&gt;While this enforced some useful discipline in architecting our user interface code, in the end not a single customer even expressed the desire to use the capability.&lt;/p&gt;
&lt;p&gt;This is just one example but the pattern repeated itself often. As an SDK author you’re often reminded that what you live and breathe all day every day is just a small part of the code your customers write for a living, and it pays to have some self-awareness about that.&lt;/p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;The common thread here is that your SDK is a guest in someone else’s app, and should aim to be as unobtrusive as possible: minimal integration steps, keeps working silently in the background, and requires zero attention until a new feature makes the upgrade worthwhile.&lt;/p&gt;
&lt;p&gt;The best compliment an SDK author can get is silence—no crash reports, no integration questions, no GitHub issues, and nothing overloading our server.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;There is a potential way to sidestep both of these—but until recently it required violating the commandment against third-party dependencies. That is to ship your business logic as JavaScript code. JavaScript runs natively on the web, and via a built-in framework (&lt;code&gt;JavaScriptCore&lt;/code&gt;) on iOS, and Android recently added decent first-party support for doing this. This avoids the “SDK code is forever” because the code can be updated in flight, and avoids the need to “write everything twice” by being able to run on almost every platform of interest. &lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fr-1-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Of course if your SDK—or at least parts of it—ship as a binary, you may be able to use cross-platform tools without inflicting them on your customers’ developers. &lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fr-2-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;When I rewrote the original Objective-C SDK in Swift, I made sure that it was an “incidental singleton”—with no internal references to the shared instance—which did wonders for making things easier to test. &lt;a href=&quot;https://frankschmitt.org/blog/publishing-an-ios-sdk-for-10-years/#fr-3-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Chaining vs. Nesting</title>
        <published>2010-01-16T01:30:10+00:00</published>
        <updated>2010-01-16T01:30:10+00:00</updated>
        
        <author>
          <name>Frank Schmitt</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://frankschmitt.org/blog/chaining-v-nesting/"/>
        <id>https://frankschmitt.org/blog/chaining-v-nesting/</id>
        
        <content type="html" xml:base="https://frankschmitt.org/blog/chaining-v-nesting/">&lt;p&gt;Any UNIX sysadmin who’s been around the block a few times has probably written a line something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;netstat -n | grep tcp | awk &amp;#39;{ print $5}&amp;#39; | sort | uniq -c | sort -n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each command in this line produces output, and the end of the line, since it’s not shunted off to a file anywhere, prints to &lt;code&gt;stdout&lt;/code&gt;. Every command (other than the first) accepts input on its &lt;code&gt;stdin&lt;/code&gt; and has its output directed into the next command to the right.&lt;/p&gt;
&lt;p&gt;If we were to write this in C-like pseudocode, it would look something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print(sort_n(uniq_c(sort(awk(grep(netstat_n(), &amp;quot;tcp&amp;quot;), 5)))));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or we could use the Lisp convention of including the function name as the first element of an S-expression:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(print (sort_n (uniq_c (sort (awk (grep (netstat_n) &amp;quot;tcp&amp;quot;) 5)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is essentially the same functionality as the command line, but this time each function passes its output to the enclosing function. Each function takes input from one of its arguments and optionally modifiers from the rest of its arguments. To the untrained eye it looks almost inside-out. You could reverse the order like so:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(((((((netstat_n) grep &amp;quot;tcp&amp;quot;) awk 5) sort) uniq_c) sort_n) print)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which makes it read from left to right but doesn’t make it any more readable: the problem is that you’ve got the primary parameter, followed by the function name, followed by any secondary parameters. We can change it once more and loop very nearly back to the original command by translating it into a method-chaining style, as is common in Ruby or jQuery:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;puts netstat_n.grep(&amp;quot;tcp&amp;quot;).awk(5).sort.uniq_c.sort_n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is certainly shorter (although I’ve cheated by omitting optional parentheses as allowed in Ruby) and arguably more readable. There is some evidence that non-programmers basically don’t really grok hierarchies, and I, for one, &lt;em&gt;definitely&lt;/em&gt; have an easier time thinking about sequences than about hierarchies.&lt;/p&gt;
&lt;p&gt;But making this happen is a bit more subtle than it appears at first glance. &lt;code&gt;netstat_n&lt;/code&gt; would produce an array object, which would have a &lt;code&gt;grep&lt;/code&gt; method that takes one argument (the expression to search for), and would output an array of the objects that match. &lt;code&gt;awk&lt;/code&gt; would be another method on an array that would take an array of strings and return an array of substrings. &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;uniq_c&lt;/code&gt;, and &lt;code&gt;sort_n&lt;/code&gt; would similarly be methods of the array object.&lt;/p&gt;
&lt;p&gt;So at the very least you’re muddying up your array class with a bunch of things that are only peripherally related to arrays. Ruby solves this by making your write the more application-specific functionality as a block that gets passed to, say, the &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;collect&lt;/code&gt; methods on array. So things are kept &lt;em&gt;relatively&lt;/em&gt; in order.&lt;/p&gt;
&lt;p&gt;Another to keep in mind is that the Lisp syntax may be easier for a program to manipulate: because the whole program consists of a giant nested list, any program with a nested-list-processing facility is able to manipulate the program with ease (it is likely, however, that one could define a relatively straightforward transformation from one form to the other).&lt;/p&gt;
&lt;p&gt;Method chaining’s sweet spot seems to be in areas where functions have one dominant input (plus zero or more modifiers) and an equally obvious single output. Where the method chaining approach breaks down is in areas where two inputs have roughly the same importance. For instance, a conditional:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(if (&amp;gt; price 50) &amp;quot;expensive&amp;quot; &amp;quot;cheap&amp;quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You almost have to introduce some kind of special syntax, e.g.:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(price &amp;gt; 50) ? &amp;quot;expensive&amp;quot; : &amp;quot;cheap&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is the sort of muddling of statements and expressions that makes the Baby McCarthy cry. You could introduce a new syntax, for instance using a comma to separate two inputs that should be directed to a single consumer:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;expensive&amp;quot;,&amp;quot;cheap&amp;quot;.if(price &amp;gt; 50)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But I’m not sure if that’s unfamiliar or just plain ugly. The way this would work is that &lt;code&gt;if&lt;/code&gt; would be a method of a two-element tuple object that would return the first value if its parameter were true or the second if it were false.&lt;/p&gt;
&lt;p&gt;It would make more sense to have &lt;code&gt;if&lt;/code&gt; be a method on a boolean expression, but I can’t think of a clean way to encode that without having a clean way to feed a function multiple inputs.&lt;/p&gt;
&lt;p&gt;So it’s certainly doable, but that last code snippet is a good deal less readable (for both man and machine) than the Lisp version. A language based almost completely on method chaining might make for an interesting academic exercise, but it looks like it won’t buy too much in practice.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Coldest Point in the Universe is in Burnaby, BC</title>
        <published>2007-02-16T11:07:00-08:00</published>
        <updated>2007-02-16T11:07:00-08:00</updated>
        
        <author>
          <name>Frank Schmitt</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://frankschmitt.org/blog/coldest-point-in-the-universe/"/>
        <id>https://frankschmitt.org/blog/coldest-point-in-the-universe/</id>
        
        <content type="html" xml:base="https://frankschmitt.org/blog/coldest-point-in-the-universe/">&lt;p&gt;I attended a presentation yesterday at the Telus Sphere of Science Word of Telus World, or whatever they’re calling it these days, by &lt;a rel=&quot;external&quot; href=&quot;http://www.dwavesys.com/&quot;&gt;D-Wave systems&lt;/a&gt;, The Quantum Computing Company™. These are the folks who surprised a lot people, myself included, by announcing their plans to have a commercial quantum computer ready to complete real work by 2008. The crowd lined up outside the sphere was overwhelmingly male, but other than that a good cross-section of the lower-mainland population. We picked up our pre-registration nametags and were herded into a smallish theater on the second floor.&lt;/p&gt;
&lt;p&gt;There was a lot of congratulatory talk and thank-yous for investors and employees, and then the CTO of the company, &lt;a rel=&quot;external&quot; href=&quot;http://dwave.wordpress.com/&quot;&gt;Geordie Rose&lt;/a&gt; took the floor to explain a little bit about the proof-of-concept that they’ve developed. The computer is a 5-millimeter-square chunk of niobium cooled to a temperature of four millikelvins (hence the title of this post). The 16-qubit proof-of-concept is roughly a hundred times slower than a thousand-dollar PC, but apparently it works, and the company is confident that they can scale it up rapidly to the 1000-qubit mark, where the device will become notably faster for certain classes of problems than existing digital computers.&lt;/p&gt;
&lt;p&gt;While most people that know a little bit about computing technologies have predicted that quantum computers are about fifty years away from commercialization, something that is technically a five-qubit computer is available for sale right now. The fifty-year number is basically a wild-ass guess of the people trying to develop so-called “gate model” quantum computers, which mimic the functionality of a conventional microprocessor using quantum devices rather than transistors. D-Wave is using an entirely different approach: an analog computer. Not analog in the sense of “continuously varying,” but analog in the sense that the manifestation on their four-by-four grid of qubits is &lt;em&gt;analog&lt;/em&gt;ous to a graph that represents the problem they are trying to solve.&lt;/p&gt;
&lt;p&gt;What sorts of problems might those be? They are currently targeting applications in the life sciences (drug database searches and protein folding), molecular simulations, and more general database searches. In mathematical terms, they hope to dramatically speed up the classes of problems known by mathematicians as &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/NP-complete&quot;&gt;NP-complete&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/NP-hard&quot;&gt;NP-hard&lt;/a&gt;. As an example he used a graph of the shortest path that visits every city in Sweden (no bork jokes, please). With current technology it would take a state-of-the-art PC about 85 years to solve, but it could potentially be solved in minutes by a quantum computer. One of the things any crypto-geek who’s seen &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Sneakers_%28film%29&quot;&gt;&lt;em&gt;Sneakers&lt;/em&gt;&lt;/a&gt; would ask is can it be used to quickly factor large numbers*. The answer is “yes, it can,” although this fact was strongly downplayed by Mr. Rose when someone brought it up in the post-presentation question period. Apparently saying that accelerating NP-complete problem solving was a good way of getting funding for QC research back in the ’90’s, since that sort of acceleration could have a significant impact on the field of public-key cryptology.&lt;/p&gt;
&lt;p&gt;The way that the system is configured is that each of the sixteen qubits is connected by a variable link to each of it’s eight nearest neighbors (or five in edge-cases and three in corner cases). Each qubit and each connection is biased in a certain direction, and over time they assume the lowest (or second-lowest) energy state, which represents the best (or second-best) solution to the problem, which is then read and transmitted back to the user. If the qubits represent wedding guests (one of the demonstrations), and Joanne really wants to sit near a window, but not at the same table that John is sitting, that fact is represented in a the set of initial biases, and the lowest-energy state that results is the optimal arrangement of guests at the wedding.&lt;/p&gt;
&lt;p&gt;Future work, aside from ramping up the number of qubits also involves connecting each qubit in the array to every other qubit. The other piece of the puzzle, and the reason for the public demo, is to generate interest and get people thinking of interesting optimization problems that a future commercial implementation of this type of computer could support.&lt;/p&gt;
&lt;p&gt;The problems that were demonstrated were a molecule search (which can be represented as a &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Independent_set_problem&quot;&gt;max independent set&lt;/a&gt; problem), the aforementioned seating plan, and a round of SudoQ. However, the fact that the solutions were obtained about one hundred times &lt;em&gt;slower&lt;/em&gt; than a modern PC coupled with the fact that the machine, residing a few kilometers away in Burnaby, was accessed through a somewhat hollywood-OS like interface means that I could not swear in a court of law that they actually had a working quantum computer. But my gut feeling is that they have something working at the level that most early-stage demos do, with a bit of sleight of hand and selective choice of subject matter making the thing appear about as functional as it is, though much, much friendlier.&lt;/p&gt;
&lt;p&gt;After the question period was closed, I grabbed a fancy poster of their device in its sample holder on the way out and made my way to the SkyTrain.&lt;/p&gt;
&lt;p&gt;* I was a bit chagrined that the question that was actually asked was whether a QC could accelerate the factoring of large prime numbers. I will go on record as saying that I can factor any large prime number in only very slightly more time than it takes you to tell me what the number is.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Diesel Wins at Le Mans</title>
        <published>2006-06-22T06:24:35-05:00</published>
        <updated>2006-06-22T06:24:35-05:00</updated>
        
        <author>
          <name>Frank Schmitt</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://frankschmitt.org/blog/diesel-wins-at-le-mans/"/>
        <id>https://frankschmitt.org/blog/diesel-wins-at-le-mans/</id>
        
        <content type="html" xml:base="https://frankschmitt.org/blog/diesel-wins-at-le-mans/">&lt;p&gt;Over the past weekend, in front of a record 235,000 spectators, the &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Audi_R10&quot;&gt;Audi R10&lt;/a&gt; took first place in the 24 hours at Le Mans, arguably the world’s premier endurance racing event. This marks the most significant victory yet for a diesel-powered car in a major racing event, and possibly an important turning point in the perception (held by many Americans) that diesels are noisy, stinky, and slow: the Audis were the quietest, cleanest, and fastest cars in the race. Significantly, they were also the most fuel efficient.&lt;/p&gt;
&lt;p&gt;On average, the Audi drivers refueled only every 14 laps, considerably less often than the petrol-powered entries. At one point a record-setting 16 laps were driven on a single 90-liter fuel load. By the end of the 24-hour race, the winning R10 was on its 380th lap, a new record for the event.&lt;/p&gt;
&lt;p&gt;Unveiled late in 2005, the R10 is Audi Motorsport’s most expensive project ever, costing an estimated 70 million Euros per year. It is an all-new design that nonetheless looks remarkably like its predecessor, the massively successful gasoline-fueled R8. It is powered by a turbocharged all-aluminum 90° V12 with common-rail direct injection that generates 650bhp and 811 lb-ft of torque in competition form. The power band lies between 3000 to 5000 RPM, a range so low as to be virtually unheard of in modern race cars. But its primary weakness is weight: the engine is rumored to weigh upwards of 200 kilograms, about 50% more than a comparable petrol-powered engine.&lt;/p&gt;
&lt;p&gt;This is not the first diesel to enjoy racing success. In 1931 Dave Evans became the first driver to complete the Indianapolis 500 without refueling. BMW and VW have raced touring cars, the former winning the 24 hours Nürburgring event based primarily on the extended range afforded by its diesel powerplant. Nor is this the first diesel to run at Le Mans. That honor belongs to a Lola powered by a Caterpillar-badged VW V10 that ran in 2004. But there is little doubt that both Audi’s TDI brand and the Diesel cycle scored a major coup last weekend.&lt;/p&gt;
&lt;p&gt;But does this race represent the &lt;a rel=&quot;external&quot; href=&quot;http://www.muhs.acsu.k12.vt.us/physics/HighJump/fosburyflop.htm&quot;&gt;Fosbury Flop&lt;/a&gt; of endurance racing, or was it an artifact of this year’s rules? The answer, more than likely, is a bit of both.&lt;/p&gt;
&lt;p&gt;The concessions afforded diesel-powered cars at Le Mans this year are numerous. Compared with a turbocharged gasoline-fueled car, the diesels enjoy a 50-percent larger displacement limit, a 52-percent larger intake restrictor, and an absolute boost pressure limit nearly twice as high. Additionally, the diesels are allowed variable nozzle turbines in their turbochargers. It is also rumored that Audi successfully lobbied to raise the minimum weight to accommodate the R10’s massive powerplant.&lt;/p&gt;
&lt;p&gt;While diesels in the wild enjoy significant fuel savings over equivalent petrol cars, the differences largely diminish when operating at full throttle (the so-called pumping losses incurred by a petrol engine sucking air past a partly closed throttle goes away when that throttle is wide open). The differences in fuel consumption nearly vanish when one takes into account the higher energy density of diesel fuel: gallon-for-gallon diesel packs about twelve percent more heat energy.&lt;/p&gt;
&lt;p&gt;At the same time, the lean-burn character of a diesel engine requires it to pass more air through the engine for every unit of energy sent out the crankshaft. Coupled with the extremely low maximum engine speed (limited by the speed of combustion inherent in compression-ignition engines), a corresponding increase in displacement and/or boost pressure is needed to achieve the same power output as a smaller, higher-strung petrol powerplant. As for the rule against VNTs in turbo-petrol cars, it is likely a cost-saving measure (their much higher exhaust gas temperatures make engineering a reliable variable-nozzle arrangement an expensive endeavor). So from a first-order numbers perspective, the rule changes are perfectly fair, except for that twelve percent number: we might well see eighty-liter fuel tanks on next year’s slate of diesel-powered entries.&lt;/p&gt;
&lt;p&gt;In any case, it could be argued that this year’s race is as much an underestimation of diesel’s potential by the rules-making committee as it is an affirmation of diesel’s capabilities by Audi’s win. But to draw a meaningful conclusion one really has to go back to why racing events have rules, and what results the rule-setting bodies are attempting to achieve.&lt;/p&gt;
&lt;p&gt;Broadly speaking, racing organizers aim to hold a safe and affordable event (by their own admittedly skewed standards) that is either technically interesting, compelling for spectators, or (ideally) both. To keep Le Mans technically interesting, a wide variety of technologies are allowed. At the same time, some “correction factors” have to be applied to ensure that the race isn’t a field day for certain technologies leaving others in the dust; in other words, to keep the race somewhat interesting to watch&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;https://frankschmitt.org/blog/diesel-wins-at-le-mans/#fn-1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. In any case, the addition of diesels to the mix certainly made this year’s race noteworthy.&lt;/p&gt;
&lt;p&gt;Audi, for its part, is using this race to cement its TDI brand of assorted turbocharged direct-injection diesel engines as not just an economy brand, but a performance one as well. And evidently they are willing to spend upwards of $100 million to do it. Presumably any technological advances that fall out of the project are gravy.&lt;/p&gt;
&lt;p&gt;At one point in automotive history it was believed—perhaps rightly so—that racing enhanced the state of the art in such a way as to be applicable to road cars. While this is ever less the case, it is still a secondary aim of many racing events that the race cars should, first and foremost, be cars. In Europe, where 55% of new cars are diesel, it is only logical that such cars be fielded, and that the Le Mans event should put the pinnacle of diesel technology to the test in the way that only the premier 24-hour endurance race can.&lt;/p&gt;
&lt;p&gt;Sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Audi_R10&quot;&gt;Wikipedia entry on the R10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://teams.lemans.org/admin/24%20HEURES%20DU%20MANS%202006/audi_motorsport-060618-0219-e.pdf&quot;&gt;Audi’s Press Release&lt;/a&gt; (PDF link)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.lemans.org/sport/sport/reglements/ressources/auto_2006/Regl_2006_prototype_ACO_fr_gb.pdf&quot;&gt;Official Rules for the Le Mans series&lt;/a&gt; (PDF link)&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This is the genius of NASCAR, which almost universally elicits wrinkled noses from automotive technical enthusiasts: while the cars are restricted to 1950’s-state-of-the-art configurations, they are so evenly matched that “turning left 1000 times” becomes more fun to watch than many Formula One races. &lt;a href=&quot;https://frankschmitt.org/blog/diesel-wins-at-le-mans/#fr-1-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
    </entry>
</feed>
