<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>Daniel Duan's Articles</title>
        <link>https://duan.ca/</link>
        <atom:link href="https://duan.ca/feed.xml" rel="self" type="application/rss+xml" />
            <item>
                <title>Idle coding</title>
                <description>&#60;p&#62;I&#39;ve discovered a new hobby.
It involves creating non-trivial libraries from scratch.
(Not UI slop!)
Except I don&#39;t write any code in editors.
An agent does all of it.&#60;/p&#62;
&#60;p&#62;It goes like this:&#60;/p&#62;
&#60;p&#62;Set up an infinite loop so the coding agent that...&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;has a clear guard for correctness (unit tests)&#60;/li&#62;
&#60;li&#62;has an objectively measurable, pass/fail outcome (performance benchmarks)&#60;/li&#62;
&#60;li&#62;has tools for styling (dead-code tool, formatter)&#60;/li&#62;
&#60;li&#62;leaves artifacts for future instances (commit changes on a branch, writes failure_analysis_SHA.md)&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;... and watch number go up.&#60;/p&#62;
&#60;p&#62;You&#39;ll need a robust prompt, then just feed it to a single agent, over and over. No need to convince the agent instance it needs to repeat (doesn&#39;t hurt to try, but they usually give up after a while).&#60;/p&#62;
&#60;p&#62;It&#39;s more fun if you ask for a success artifact (benchmark_success_SHA.tsv) and have a script that monitors for new ones. I run this script with @steipete&#39;s VibeTunnel so I can watch the number go up on my phone.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2026/01/idle_monitoring.jpeg&#34; alt=&#34;monitoring benchmark progress in terminal&#34; /&#62;&#60;/p&#62;
&#60;p&#62;It may take some setup to get going.
For example,
at the beginning you want to import a large number of unit tests.
You&#39;ll want to source some input for benchmarking.
You&#39;ll want some infrastructure (SwiftPM project, Scripts directory, git).&#60;/p&#62;
&#60;p&#62;But quickly,
it becomes an &#60;a href=&#34;https://en.wikipedia.org/wiki/Incremental_game&#34;&#62;idle game&#60;/a&#62;.
At first,
you&#39;ll watch the number of unit tests go from 100% fail to 100% pass.
Then,
the performance benchmarks.
Bonus points if you benchmark against existing libraries,
and beat them in performance.
This has happened on every project I&#39;ve done.&#60;/p&#62;
&#60;p&#62;Codex btw.&#60;/p&#62;
&#60;p&#62;I should clarify:
this is not serious software engineering.
The goal is having fun.
Although the end result usually is really useful,
and because of robust unit testing + benchmarking,
it might be good enough to use in production.&#60;/p&#62;
&#60;p&#62;We&#39;ll find out.&#60;/p&#62;
&#60;p&#62;My favorite idle game in 2026 so far.&#60;/p&#62;
</description>
                <pubDate>Sat, 24 Jan 2026 11:52:04 -0800</pubDate>
                <link>https://duan.ca/2026/01/24/idle-coding/</link>
                <guid isPermaLink="true">https://duan.ca/2026/01/24/idle-coding/</guid>
            </item>
            <item>
                <title>TOMLDecoder Is Now Faster Than C (Thanks to AI)</title>
                <description>&#60;p&#62;Recently,
I gave my TOML library written in Swift &#60;a href=&#34;/2025/12/10/TOMLDecoder-0.4.1/&#34;&#62;an 800% speed boost&#60;/a&#62;.
The natural question after that is:
how much faster can I push it?&#60;/p&#62;
&#60;details&#62;
&#60;summary&#62;
I&#39;m happy to report that TOMLDecoder now parses the &#60;a href=&#34;https://github.com/dduan/TOMLDecoder/blob/cea8f0bee33f37e0fcc33b566a742485c71196e7/Sources/Resources/fixtures/twitter.toml&#34;&#62;Twitter payload example&#60;/a&#62; 1.8x faster than the C library &#60;a href=&#34;https://github.com/cktan/tomlc99&#34;&#62;tomlc99&#60;/a&#62;, and 5x faster than &#60;a href=&#34;https://github.com/marzer/tomlplusplus&#34;&#62;TOML++&#60;/a&#62;.
&#60;/summary&#62;
&#60;p&#62;I tried to be as charitable as possible for the non-Swift libraries while keeping the call sites in Swift.
For example,
it takes time to create or copy the UTF-8 bytes of a &#60;code&#62;Swift.String&#60;/code&#62; into a contiguous region.
And that&#39;s not counted towards the other libraries&#39; parsing time.
TOML++ runs faster with exceptions enabled.
So that&#39;s the path I chose to benchmark.
When bridging the C++ code,
I made sure there&#39;s no allocation,
no checking for input/output, etc,
so that the bridging overhead is trivial.&#60;/p&#62;
&#60;p&#62;Here&#39;s the benchmark code run repeatedly to collect an average,
with warmups ahead of time:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func benchmarkTOMLDecoder(source: String) throws -&#38;gt; Double {
    let start = CFAbsoluteTimeGetCurrent()
    let table = try TOMLTable(source: source)
    let end = CFAbsoluteTimeGetCurrent()
    blackhole(table)
    return end - start
}

func benchmarkCTOML99(source: String) -&#38;gt; Double {
    var source = source
    var duration: Double = 0
    source.withUTF8 {
        $0.withMemoryRebound(to: CChar.self) { buffer in
            let baseAddress = UnsafeMutableRawPointer(mutating: buffer.baseAddress!)
            let start = CFAbsoluteTimeGetCurrent()
            let table = toml_parse(baseAddress, nil, 0)
            duration = CFAbsoluteTimeGetCurrent() - start
            blackhole(table)
        }
    }
    return duration
}

func benchmarkCTOMLPlusPlus(source: String) -&#38;gt; Double {
    var source = source
    var duration: Double = 0
    source.withUTF8 {
        $0.withMemoryRebound(to: CChar.self) { buffer in
            let start = CFAbsoluteTimeGetCurrent()
            let table = tomlpp_parse(buffer.baseAddress, buffer.count)
            duration = CFAbsoluteTimeGetCurrent() - start
            blackhole(table)
        }
    }
    return duration
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;where &#60;code&#62;tomlpp_parse&#60;/code&#62; is a minimal wrapper for the TOML++ library:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-cpp&#34;&#62;void *tomlpp_parse(const char *conf, size_t conf_len) {
    try {
        static toml::table table{};
        table = toml::parse(std::string_view{conf, conf_len});
        return static_cast&#38;lt;void *&#38;gt;(&#38;amp;table);
    } catch (...) {
        return nullptr;
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;If any of these measures are unfair to the C/C++ libraries,
I&#39;d love your feedback!&#60;/p&#62;
&#60;/details&#62;
&#60;p&#62;Here&#39;s the output of the benchmark program I wrote:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Benchmarking TOML parsers...
File size: 443461 bytes

Warming up...
Running 100 iterations...

Results:
═══════════════════════════════════════════════════════════
TOMLDecoder:
  Average: 1.232 ms
  Min:     1.203 ms
  Max:     1.332 ms

cTOML99:
  Average: 2.226 ms
  Min:     2.190 ms
  Max:     2.341 ms

cTOMLPlusPlus:
  Average: 6.107 ms
  Min:     6.038 ms
  Max:     6.377 ms

TOMLDecoder is 1.81x faster than cTOML99
TOMLDecoder is 4.96x faster than cTOMLPlusPlus
═══════════════════════════════════════════════════════════
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;I charted the wall clock time and instruction counts over the commit history.
You can see that the latest release is a lot faster than 0.4.1:&#60;/p&#62;
&#60;iframe id=&#34;benchmark-iframe&#34; src=&#34;/assets/2026/01/tomldecoder-0.4.3-improvements.html&#34; width=&#34;100%&#34; height=&#34;1200&#34; frameborder=&#34;0&#34; style=&#34;border: none; display: block; margin: 20px 0;&#34;&#62;&#60;/iframe&#62;
&#60;script&#62;
window.addEventListener(&#39;message&#39;, function(event) {
    if (event.data.type === &#39;resize&#39;) {
        const iframe = document.getElementById(&#39;benchmark-iframe&#39;);
        if (iframe) {
            iframe.style.height = event.data.height + &#39;px&#39;;
            iframe.style.transition = &#39;none&#39;;
        }
    }
});
&#60;/script&#62;
&#60;p&#62;... and, the majority of these commits are authored by AI! How did that happen?&#60;/p&#62;
&#60;h2&#62;It&#39;s old-fashioned engineering, baby!&#60;/h2&#62;
&#60;p&#62;I ended the &#60;a href=&#34;/2025/12/10/TOMLDecoder-0.4.1/&#34;&#62;last post&#60;/a&#62; with the following (emphasize in &#60;strong&#62;bold&#60;/strong&#62;):&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;...the project also gained a bunch of infra improvements.&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;It has a DocC-based documentation site.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The entirety of the official test suite is now programmatically imported as unit tests.&#60;/strong&#62;&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The source code style is now enforced by swiftformat&#60;/strong&#62;&#60;/li&#62;
&#60;li&#62;Platform checks are more comprehensive and modern on CI.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Benchmarks are now modernized with ordo-one/package-benchmark.&#60;/strong&#62;&#60;/li&#62;
&#60;/ul&#62;
&#60;/blockquote&#62;
&#60;p&#62;If you set out to optimize the runtime performance of a software project,
infra improvements like these will ensure that
your engineer can explore options for optimization with confidence that
they won&#39;t break the expected behavior,
and their efforts can be measured objectively.&#60;/p&#62;
&#60;p&#62;Most importantly,
as detailed in the last post,
the architecture of the TOML parser has received some significant upgrades.
This type of change is rare in a small project,
and I don&#39;t expect it to happen again in the next phase of optimization.&#60;/p&#62;
&#60;p&#62;I set up a separate project that calls into TOMLDecoder
so that I can profile it with Instruments.&#60;/p&#62;
&#60;p&#62;It was during the holidays, and
although the idea of trying my hand at micro-optimizing the code,
and gradually squeezing out performance juice sounded really fun,
I also had a bunch of travel planned.
So what else is there to do?&#60;/p&#62;
&#60;p&#62;I booted up codex.&#60;/p&#62;
&#60;h2&#62;gpt-5.2-codex, my performance engineer&#60;/h2&#62;
&#60;p&#62;For the most part,
I simply fed this prompt to codex over and over again:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;Objective: Try to make the p50 of &#38;quot;parse twitter.toml&#38;quot; benchmark improve by &#38;gt; 1.1% on instructions or retains compared to the &#60;code&#62;main&#60;/code&#62; branch. Improvements on either is acceptable as a success, but regression in either should be considered a failure. Other metrics in the benchmark does not matter.&#60;/p&#62;
&#60;p&#62;Verify iteratively:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;Make code changes&#60;/li&#62;
&#60;li&#62;Format with &#60;code&#62;make format&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Make sure all tests passes by running &#60;code&#62;swift test&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Create a branch prefixed with &#60;code&#62;cc/&#60;/code&#62; in name&#60;/li&#62;
&#60;li&#62;Commit all changes. Include description of the optimization as body of the commit message.&#60;/li&#62;
&#60;li&#62;Use Scripts/benchmark.sh to run the benchmark, recording its output in a text file&#60;/li&#62;
&#60;li&#62;If the benchmark result meets the improvement threshold, cherry-pick the change onto main. Otherwise, Commit the benchmark results file to the branch you created, switch back to main and start over.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;When you run the benchmark script, NEVER use &#60;code&#62;HEAD&#60;/code&#62; as its argument. Use explicit SHAs. Only use Scripts/benchmark.sh SHA_OF_BASE SHA_OF_TARGET to run the benchmarks. Do not try to run the underlying commands directly.&#60;/p&#62;
&#60;p&#62;You must NOT look at the content of Benchmarks/, or the content of Sources/Resources.&#60;/p&#62;
&#60;p&#62;To give you some direction, I&#39;ve profiled the parsing the twitter example, and included the inverted time profile call tree in /tmp/trace-tree.txt.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;The prompt changed gradually in these ways:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;Wording became more streamlined as I figured out how gpt-5.2-codex interprets specific things.&#60;/li&#62;
&#60;li&#62;The optimization threshold decreased as the lower-hanging fruits got picked&#60;/li&#62;
&#60;li&#62;The benchmark to optimize changed a bunch of times because they have different data profiles&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Each time the optimization threshold is met,
I collect another time profile from instruments with the latest change,
and restart the session with the same prompt.&#60;/p&#62;
&#60;p&#62;I actually started the journey with gpt-5.1-codex-max.
It would find 5-10% improvements consecutively at the beginning.
Then it would start to struggle,
then I&#39;d switch to gpt-5.2-codex with the default &#38;quot;Medium&#38;quot; setting,
then &#38;quot;High&#38;quot;, and eventually &#38;quot;Extra high&#38;quot;.
Towards the end,
the LLM could barely find any speed improvements
without regressing other benchmarks in some way.
That&#39;s when I decided it&#39;s time to cut a release.&#60;/p&#62;
&#60;h2&#62;My observations of the model&#60;/h2&#62;
&#60;p&#62;Despite occasional struggles with conventional Swift coding style,
I find that gpt-5.2-codex is good at analyzing the flow of the parser,
and finds ways to short circuit certain logic.
These types of discoveries made the parser quite a bit faster.&#60;/p&#62;
&#60;p&#62;It replaced key comparisons in a hot loop with hash value comparisons,
which brought in a significant speedup.
In retrospect, this idea seemed fairly obvious,
but, in my imagination,
I wouldn&#39;t have been bold enough to try it.&#60;/p&#62;
&#60;p&#62;The LLM has a few favorite things to try at the start of each session.&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;It would see a linear search and try to replace it with a dictionary lookup&#60;/li&#62;
&#60;li&#62;It would try unrolling loops (in a few cases, this actually helped),&#60;/li&#62;
&#60;li&#62;It would reserve array capacities ahead of time,&#60;/li&#62;
&#60;li&#62;It would eliminate copies by converting things into classes&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;But then the benchmark would regress,
which forces it to explore other paths.&#60;/p&#62;
&#60;p&#62;Although my prompt tells the model to not look at the benchmark itself,
it sometimes goes and does it anyways.
I suppose benchmark-maxing is a temptation too great to resist for it?&#60;/p&#62;
&#60;p&#62;As reported by &#60;a href=&#34;https://steipete.me/posts/2025/shipping-at-inference-speed&#34;&#62;others&#60;/a&#62;,
I also observed that gpt-5.2-codex would spend a lot of time just analyzing,
before attempting any changes.
The code change it produces is almost always one-shot.
It rarely goes back and revises the idea it&#39;s attempting to implement.&#60;/p&#62;
&#60;h2&#62;Conclusions&#60;/h2&#62;
&#60;p&#62;Good engineering practices continue to pay dividends with LLMs.&#60;/p&#62;
&#60;p&#62;TOMLDecoder reached a point where its runtime performance is itself a feature worth talking about.&#60;/p&#62;
&#60;p&#62;The setup of this project can serve as a benchmark for LLMs, I think?
Here&#39;s a prompt,
a concrete, measurable outcome represented by numbers,
a huge test suite.
How far can you push those numbers?&#60;/p&#62;
</description>
                <pubDate>Thu, 01 Jan 2026 11:07:05 -0800</pubDate>
                <link>https://duan.ca/2026/01/01/TOMLDecoder-Is-Faster-Than-C/</link>
                <guid isPermaLink="true">https://duan.ca/2026/01/01/TOMLDecoder-Is-Faster-Than-C/</guid>
            </item>
            <item>
                <title>TOMLDecoder 0.4 is 800% Faster</title>
                <description>&#60;p&#62;I just released version 0.4.1 of &#60;a href=&#34;https://github.com/dduan/TOMLDecoder&#34;&#62;TOMLDecoder&#60;/a&#62;,
a TOML 1.0 parser,
and &#60;a href=&#34;https://developer.apple.com/documentation/swift/codable&#34;&#62;decoder&#60;/a&#62; implemented in pure Swift.
When decoding a TOMLDocument such as &#60;a href=&#34;https://github.com/dduan/TOMLDecoder/blob/cea8f0bee33f37e0fcc33b566a742485c71196e7/Sources/Resources/fixtures/twitter.toml&#34;&#62;this twitter payload&#60;/a&#62;,
TOMLDecoder 0.4.1 is roughly 800% faster by wall clock time than 0.3.x.
In this post, I’ll discuss how this was achieved.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;tl;dr: among other things,
the gains comes from making the parsing algorithm lazier,
and eliminating overheads from bound checking when accessing substrings.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Update:
An earlier version of this post claimed that adopting Span eliminates cost of all bound checking
when accessing the underlying bytes of the TOML content,
that turns out to be wrong.
The reality is more interesting.
The post has been revised to discuss what really brought the performance gains
after adopting Span.&#60;/em&#62;&#60;/p&#62;
&#60;h2&#62;The Benchmark&#60;/h2&#62;
&#60;p&#62;TOMLDecoder now includes benchmarks implemented with &#60;a href=&#34;https://github.com/ordo-one/package-benchmark&#34;&#62;ordo-one/package-benchmark&#60;/a&#62;.
I plotted the median from the aforementioned benchmark results below.
Each chart includes data points for deserializing the TOML document,
and decoding it on top.
(Unsurprisingly, decoding takes a bit longer.)&#60;/p&#62;
&#60;p&#62;The results show
wall clock time,
CPU instructions,
as well as retain count all trending down significantly.&#60;/p&#62;
&#60;p&#62;In addition to the before and after,
there&#39;s an extra data point measured specifically prior to adopting Swift&#39;s &#60;code&#62;Span&#60;/code&#62;.
More on that later.&#60;/p&#62;
&#60;iframe id=&#34;benchmark-iframe&#34; src=&#34;/assets/2025/12/tomldecoder-0.4.0-benchmark-charts.html&#34; width=&#34;100%&#34; height=&#34;1200&#34; frameborder=&#34;0&#34; style=&#34;border: none; display: block; margin: 20px 0; min-height: 1200px;&#34;&#62;&#60;/iframe&#62;
&#60;script&#62;
window.addEventListener(&#39;message&#39;, function(event) {
    if (event.data.type === &#39;resize&#39;) {
        const iframe = document.getElementById(&#39;benchmark-iframe&#39;);
        if (iframe) {
            iframe.style.height = event.data.height + &#39;px&#39;;
            iframe.style.transition = &#39;none&#39;;
        }
    }
});
&#60;/script&#62;
&#60;h2&#62;How to make a parser go fast&#60;/h2&#62;
&#60;h3&#62;Improving data structure and algorithms&#60;/h3&#62;
&#60;p&#62;... also known as cheating.
Yes, really.&#60;/p&#62;
&#60;p&#62;In 0.3.x, &#60;code&#62;TOMLDecoder&#60;/code&#62; behaves like &#60;a href=&#34;https://developer.apple.com/documentation/foundation/jsonserialization&#34;&#62;JSONSerialization&#60;/a&#62;.
When you ask it to decode TOML data,
with &#60;code&#62;TOMLDecoder.tomlTable(from:)&#60;/code&#62;
it goes through the entire document,
creates matching container structures within it.
For each TOML table, it creates a &#60;code&#62;[String: Any]&#60;/code&#62;,
for each TOML array, it creates a &#60;code&#62;[Any]&#60;/code&#62;.
When a table contains an array,
for example,
a corresponding &#60;code&#62;[&#38;quot;key&#38;quot;: [...]]&#60;/code&#62; entry is created to match.
Along the way, the parser also validates the leaf types,
so things like a ill-formed date causes an error to be thrown.
The end result is a &#60;code&#62;[String: Any]&#60;/code&#62; in which
everything is known to be valid.&#60;/p&#62;
&#60;p&#62;A number of things are slow in this process:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;The frequent creation and subsequent usage of intermediary Swift arrays and dictionaries require heap allocations.&#60;/li&#62;
&#60;li&#62;Validating every leaf value takes time.&#60;/li&#62;
&#60;li&#62;Retrieved values are &#60;code&#62;Any&#60;/code&#62;s, so you have to cast it to the expected type to consume them.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;TOMLDecoder 0.4 does away with all of that.&#60;/p&#62;
&#60;p&#62;To represent the containers,
and leaf values,
0.4 introduces some light-weight structs,
These structs don&#39;t manage the actual memory used to store their contents.
As the parser work through the bytes of a TOML document,
it creates these light weight data types to record the shape of the document,
as well as the byte-offsets of the leaf values.
These intermediary data are stored in a centralized location
to avoid unnecessary heap allocations.&#60;/p&#62;
&#60;p&#62;Here&#39;s what I mean by &#38;quot;cheating&#38;quot;:
during this phase,
the parser doesn&#39;t do much validation of the leaf values.
What it does is more akin to &#38;quot;lexing&#38;quot;,
it finds the tokens that could represent a leaf value,
and remembers where they are.
No work is done to actually validate and create the leaf values.&#60;/p&#62;
&#60;p&#62;To retrieve any values from the result,
you must state what type is expected:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// a valid TOML document is always a table at the root level
let serverIP = try TOMLTable(source: tomlString)
	.string(forKey: &#38;quot;ip&#38;quot;) // validate this token as a `String`
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is an API change.
It delays the validation work,
and helps avoid conversions from &#60;code&#62;Any&#60;/code&#62;.
If you only need one field,
no validation is necessary on the rest of the leaf values in the entire document.&#60;/p&#62;
&#60;p&#62;Swift&#39;s decoding APIs ask for typed access:
if your &#60;code&#62;Codable&#60;/code&#62; type has a &#60;code&#62;Date&#60;/code&#62; field,
you ask the container for a &#60;code&#62;Date&#60;/code&#62;,
if the matching value at the spot is of a different type,
an error is thrown.
So the more efficient access pattern benefits the decoding process as well.&#60;/p&#62;
&#60;h3&#62;Eliminating bound checks&#60;/h3&#62;
&#60;p&#62;A major source of slowness in TOMLDecoder 0.3.x
comes from inefficient patterns when the underyling bytes of a TOML document.&#60;/p&#62;
&#60;p&#62;The parser holds a reference to the original string,
and hands &#60;code&#62;String.UTF8View.SubSequence&#60;/code&#62;s to small functions to descend on.
A typical piece of the parser might look like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func skipWhitespaces(_ text: inout String.UTF8View.SubSequence) {
    let bytes = text.utf8
    var i = bytes.startIndex
    while i &#38;lt; bytes.endIndex {
        if !isWhitespace(bytes[i]) { // very slow!
            break
        }
        bytes.formIndex(after: &#38;amp;i)
    }
    text = bytes[i...]
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Using UTF8View makes sure that we aren&#39;t dealing with &#60;code&#62;Character&#60;/code&#62;s,
which could have variable lengths.
However,
accessing the bytes in this way introduces multiple rounds of bound checks
that ends up being super expensive in the hot path of the parser:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;The standard library needs to check that a index is valid for the &#60;code&#62;SubSequence&#60;/code&#62; aka &#60;code&#62;Substring&#60;/code&#62;
by comparing it against the start and end indices.&#60;/li&#62;
&#60;li&#62;Then, the index is used to access the underlying &#60;code&#62;UTF8View&#60;/code&#62;, at this point,
the standard library checks whether the index is out of bound again.&#60;/li&#62;
&#60;li&#62;A the end, the library goes into the buffer pointer of the string to retrieve the actual byte.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;(All of that assumes that the string&#39;s buffer is contiguously stored in memory.
There&#39;s a even slower path that I could eliminate by ensuring the string is native.)&#60;/p&#62;
&#60;p&#62;A parser does a whole lot of such accesses.
The cost of these bound checks seriously adds up.&#60;/p&#62;
&#60;p&#62;Since the release of TOMLDecoder 0.3.0,
Swift has gained a whole set of features that led to the introduction of &#60;a href=&#34;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md&#34;&#62;Span&#60;/a&#62;.
&#60;code&#62;Span&#60;/code&#62; is built on compile-time lifetime checks.
These checks guarantee the safety when accessing its content.
The same function updated for &#60;code&#62;Span&#60;/code&#62; looks extremely similar to the original:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func skipWhitespace(
    bytes: Span&#38;lt;UTF8.CodeUnit&#38;gt;, // aka Span&#38;lt;UInt8&#38;gt;
    remainingBytes: inout Range&#38;lt;Int&#38;gt;,
) {
    var i = remainingBytes.lowerBound
    while i &#38;lt; bytes.count {
        if !isWhitespace(bytes[i]) { break }
        i += 1
    }
    remainingBytes = i ..&#38;lt; remainingBytes.upperBound
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Here,
the subscript access of &#60;code&#62;bytes&#60;/code&#62; does not incur multiple rounds of bound checks!
Rather, it skips step 1,
which eliminates 2 integer comparisons per access,
a 2/3 reduction in bound check overhead.
Further, the compiler can see the access pattern more clearly,
it can heuristically eliminate even the final remaning bound checks in some casse.&#60;/p&#62;
&#60;p&#62;Not having to perform all the bound checks
in the tight loop of the parser results significant performance gains
as shown in the benchmark results.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Here&#39;s the kicker&#60;/em&#62;.
With &#60;code&#62;Span&#60;/code&#62;,
the bound checks are eliminated
because the compiler is confident that the access is safe by construction.
If you make a mistake that would lead to unsafe access,
Swift will refuse to compile your code.
But &#60;code&#62;Span&#60;/code&#62; is a language feature that requires new language runtime.
You cannot use it on older operating systems.
There&#39;s other, older ways to avoid bound checks,
using &#60;code&#62;UnsafeBufferPointer&#60;/code&#62;s.
The problem of doing so is that you are responsible for ensuring that the access is safe.
In particular, the point of access must occur in a valid scope for the pointer.
A piece of parser using such API may look like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func skipWhitespace(
    bytes: UnsafeBufferPointer&#38;lt;UTF8.CodeUnit&#38;gt;,
    remainingBytes: inout Range&#38;lt;Int&#38;gt;,
) {
    var i = remainingBytes.lowerBound
    while i &#38;lt; bytes.count {
        if !isWhitespace(bytes[i]) { break }
        i += 1
    }
    remainingBytes = i ..&#38;lt; remainingBytes.upperBound
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;But WAIT!  This code using the buffer pointer look extremely similar to the &#60;code&#62;Span&#60;/code&#62; version!
And if you think carefully,
the requirement for maintaining valid scope for the &#60;code&#62;UnsafeBufferPointer&#60;/code&#62; is already &#60;em&#62;enforced&#60;/em&#62; for any &#60;code&#62;Span&#60;/code&#62;s, syntactically!&#60;/p&#62;
&#60;p&#62;Enter &#60;a href=&#34;https://nshipster.com/swift-gyb/&#34;&#62;gyb&#60;/a&#62;. A script that Swift uses to generate repetitive code in the complier.
In TOMLDecoder 0.4,
the parser implementation uses it to generate 2 version of the same set of parsing logic:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;configs = [
    (&#38;quot;Span&#38;lt;UInt8&#38;gt;&#38;quot;, &#38;quot;@available(iOS 26, macOS 26, watchOS 26, tvOS 26, visionOS 26, *)&#38;quot;),
    (&#38;quot;UnsafeBufferPointer&#38;lt;UInt8&#38;gt;&#38;quot;, &#38;quot;@available(iOS 13, macOS 10.15, watchOS 6, tvOS 13, visionOS 1, *)&#38;quot;),
]
}%
% for byte_type, availability in configs:
${availability}
func parse(bytes: ${byte_type}) throws -&#38;gt; TOMLTable {
	// same code
}
% end
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... and there&#39;s a single place that checks for the OS at runtime:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let source: String = ... // TOML string
if #available(iOS 26, macOS 26, watchOS 26, tvOS 26, visionOS 26, *) {
    let bytes = source.utf8Span.span
    try parse(bytes: bytes)
} else {
    try source.withUTF8 { try parse(bytes: $0) }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The beauty here,
is that the compiler does all the work to ensure the access to the &#60;code&#62;Span&#60;/code&#62;
as well as the buffer pointer are safe,
because the logic that does the accessing are identical thanks to &#60;code&#62;gyb&#60;/code&#62;.&#60;/p&#62;
&#60;h2&#62;Conclusion&#60;/h2&#62;
&#60;p&#62;In reality, there are a ton of other optimizations applied in TOMLDecoder 0.4.
For example,
instead of doing dictionary look ups,
looking up things from a TOMLDocument actually involves a linear search.
I know, I know, this goes against what we were taught in CS.
But in modern computers,
and for typical sizes of TOML documents,
a linear search is often faster that computing a hash value,
and the subsequent lookups.&#60;/p&#62;
&#60;p&#62;As part of the release,
the project also gained a bunch of infra improvements.&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;It has a &#60;a href=&#34;https://www.swift.org/documentation/docc/&#34;&#62;DocC&#60;/a&#62;-based &#60;a href=&#34;https://dduan.github.io/TOMLDecoder/main/documentation/tomldecoder/&#34;&#62;documentation site&#60;/a&#62;.&#60;/li&#62;
&#60;li&#62;The entirety of the &#60;a href=&#34;https://github.com/toml-lang/toml-test&#34;&#62;official test suite&#60;/a&#62; is now programmatically imported as unit tests.&#60;/li&#62;
&#60;li&#62;The source code style is now enforced by &#60;a href=&#34;https://github.com/nicklockwood/SwiftFormat&#34;&#62;swiftformat&#60;/a&#62;.&#60;/li&#62;
&#60;li&#62;Platform checks are more comprehensive and modern on CI.&#60;/li&#62;
&#60;li&#62;Benchmarks are now modernized with &#60;a href=&#34;https://github.com/ordo-one/package-benchmark&#34;&#62;ordo-one/package-benchmark&#60;/a&#62;&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;I think of this release as a preparation for a eventual 1.0 release,
which will support the &#60;a href=&#34;https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585/171&#34;&#62;new deserialization APIs from Swift&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;Even through I went through some optimizations for speed in this post,
I still have a bunch of ideas I want to try to squeeze out more performance gains.
That&#39;s exciting.&#60;/p&#62;
</description>
                <pubDate>Wed, 10 Dec 2025 17:44:34 -0800</pubDate>
                <link>https://duan.ca/2025/12/10/TOMLDecoder-0.4.1/</link>
                <guid isPermaLink="true">https://duan.ca/2025/12/10/TOMLDecoder-0.4.1/</guid>
            </item>
            <item>
                <title>Padding a Squircle in FreeCAD 1.0</title>
                <description>&#60;p&#62;&#60;em&#62;I bought a 3D printer, and, as a result, got into 3D modeling recently. I&#39;m still super new to everything. From experience, this means I should write down things I&#39;m learning. The beginner&#39;s perspective is valuable to other beginners!&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;A &#60;a href=&#34;https://en.wikipedia.org/wiki/Squircle&#34;&#62;squircle&#60;/a&#62; is a square who&#39;s corners are replaced by curves with g3 continuity, which can be thought of as &#60;em&#62;really hecking smooth&#60;/em&#62; curves where the derivatives of the curve must also be smooth. In &#60;a href=&#34;https://www.freecad.org/&#34;&#62;FreeCAD&#60;/a&#62; 1.0.x, it&#39;s not immediately obvious how to sketch such a shape, in order to create solid shapes out of it. With the help of ChatGPT, and the internet, I figured out a somewhat cohesive way to do this recently. Now I need to write it down lest I forget!&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2025/06/squircle-00-finished.png&#34; alt=&#34;Finished 3D shape with a squircle front profile&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Our goal is to have a sketch of a squircle that we can use to pad or pocket to create 3D shapes. In the sketch, we want to first create the sides of the square that&#39;s straight, and connect them with the g3 curve, which can be done via the Curves workbench.&#60;/p&#62;
&#60;p&#62;But first, let&#39;s break down the squircle&#39;s geometry a bit. A squircel is both a square and a circle. Each side of the square has a straight line, it ends at a specific point, let&#39;s call it &#60;strong&#62;A&#60;/strong&#62;, where the curve of the circle begins. From this point, if you draw a line perpendicluar to the straight part, and repeatly draw it on every such point, the new lines will intercect at point &#60;strong&#62;B&#60;/strong&#62;. The length of the line &#60;strong&#62;AB&#60;/strong&#62; is the &#60;em&#62;radius&#60;/em&#62; of the squircle.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2025/06/squircle-01-radius.png&#34; alt=&#34;Image illustrating the radius of a squircle&#34; /&#62;&#60;/p&#62;
&#60;p&#62;In FreeCAD, we want to include these &#60;strong&#62;AB&#60;/strong&#62; lines as guides. They will define both the straight lines on the side, as well as the correct space for the curves. The guide lines and the sides will form a cross shape. Make sure everything is symmetrical, and the &#60;strong&#62;AB&#60;/strong&#62; lines all have the same size.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2025/06/squircle-02-sketch-cross-shape.png&#34; alt=&#34;Screenshot of the FreeCAD sketch of a cross outline&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Note that the &#60;strong&#62;AB&#60;/strong&#62; lines are in construction mode represented by dashes.&#60;/p&#62;
&#60;p&#62;Exit the Sketch. Switch to the Curves workbench, and select 2 of the 4 concrete edges from the sketch. Use the Blend Curve option from the workbench. And you&#39;ll get some funky looking curves connecting the straight lines, and it&#39;s represented by a &#38;quot;Blend_Curve&#38;quot; in the object tree.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2025/06/squircle-03-curve-unfixed.png&#34; alt=&#34;Screenshot of adding the blend curve&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Select the &#38;quot;Blend_Curve&#38;quot; in the tree and tweak its Data fields.&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;Set &#60;code&#62;Auto Scale&#60;/code&#62; to &#60;code&#62;true&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Set &#60;code&#62;Parameter&#60;/code&#62; to &#60;code&#62;0mm&#60;/code&#62; for both edges.&#60;/li&#62;
&#60;li&#62;The new curve should smoothely connect with the ends of the sides that&#39;s close to the other straight side. If not, set &#60;code&#62;Reverse&#60;/code&#62; to &#60;code&#62;true&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Most importantly, set &#60;code&#62;Continuity&#60;/code&#62; for both edges to &#60;code&#62;G3&#60;/code&#62;.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2025/06/squircle-04-curve-fixed.png&#34; alt=&#34;Screenshot of fixed blend curve&#34; /&#62;&#60;/p&#62;
&#60;p&#62;That completes 1 of the 4 corners. Repeat for the other 3. And now you have a 2D squircle!&#60;/p&#62;
&#60;p&#62;There should be 4 &#38;quot;Blend_Curve&#38;quot;s in the object tree, as well as the original sketch.&#60;/p&#62;
&#60;p&#62;Now things get a little convoluted. Although things on screen look like a closed wire, we can&#39;t use it to create a 3D shape for 2 reasons:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;the &#38;quot;Blend_Curve&#38;quot;s aren&#39;t part of any body.&#60;/li&#62;
&#60;li&#62;the curves and the straights don&#39;t belong to the same geometry.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;There&#39;s a easy way to fix both problems, thanks to the fact that multiple shapes in FreeCAD 1.0 can comine into a single sub-objects shape binder.&#60;/p&#62;
&#60;p&#62;Switch back to the Part Design workbench. Activate the body you want the final 3D shape in (can be an existing or new body). Select all 4 blend curves in the object tree, and the sketch. You should see the entire wire highlighted in a uniform color. Then use the sub-objects shape binder tool, which gets you a single binder in the tree of the active body.&#60;/p&#62;
&#60;p&#62;You should see the binder on screen. Hide other things if they are distracting you. Now, select the edges in the binder -- all 8 of them! After that, you can use the Pad tool to create a 3D shape. And that&#39;s it!&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;Obviously, a squircle is the simpliest shape to incorporate a g3 continous curve. But once we have the curve as a wire, anything is possible in FreeCAD.&#60;/p&#62;
</description>
                <pubDate>Sun, 15 Jun 2025 16:00:00 -0800</pubDate>
                <link>https://duan.ca/2025/06/15/padding-a-squircle/</link>
                <guid isPermaLink="true">https://duan.ca/2025/06/15/padding-a-squircle/</guid>
            </item>
            <item>
                <title>GRPC Status With Error Details in Swift</title>
                <description>&#60;h2&#62;Introduction&#60;/h2&#62;
&#60;p&#62;In GRPC, one could define an RPC that, in addition to the normal
request-response messages, it also defines a custom message to represent errors:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-proto&#34;&#62;message SignUpWithEmailRequest {
  string email = 1;
  string password = 2;
  string referral_code = 3;
}

message SignUpWithEmailResponse {
  AccessTokenDTO token = 1;
}

message SignUpWithEmailErrorResponse {
  enum Kind {
    KIND_UNKNOWN = 0;
    KIND_EMAIL_ALREADY_REGISTERED = 1;
    KIND_INVALID_PASSWORD = 2;
    KIND_INVALID_EMAIL = 3;
    KIND_INVALID_CODE = 4;
  }

  Kind kind = 1;
  repeated string reasons = 2;
}

service AuthenticationService {
  rpc SignUpWithEmail(SignUpWithEmailRequest) returns (SignUpWithEmailResponse) {}
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... in this example, &#60;code&#62;SignUpWithEmailErrorResponse&#60;/code&#62; is not directly referenced
in by &#60;code&#62;AuthenticationService&#60;/code&#62;. But a server can use it as GRPC status with
details. In Go the code might look like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-go&#34;&#62;import (
	&#38;quot;google.golang.org/grpc/codes&#38;quot;
	&#38;quot;google.golang.org/grpc/status&#38;quot;
)

// ...

_, err = queries.GetUserByEmail(ctx, email)
if err == nil {
    response := &#38;amp;SignUpWithEmailErrorResponse{
        Kind:    SignUpWithEmailErrorResponse_KIND_EMAIL_ALREADY_REGISTERED,
        Reasons: []string{},
    }

    st := status.New(codes.AlreadyExists, &#38;quot;Email already registered&#38;quot;)
    stWithDetails, err := st.WithDetails(response)
    if err != nil {
        return nil, err
    }

    return nil, stWithDetails.Err()
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is all very type-safe, very demure, until you realize that in grpc-swift
1.X there&#39;s no API to retrieve this &#38;quot;status with detail&#38;quot;. When the information
is transimitted over the wire, you will have to dig it out manually. In this
post, I&#39;ll document how I did this with a client-side interceptor.&#60;/p&#62;
&#60;h2&#62;The Swift interceptor&#60;/h2&#62;
&#60;p&#62;In Swift, when you make the RPC request, you&#39;ll get a standard error code and
error message if the server returns an error with the code shown earlier:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Use the generated client code to make the gRPC request
var request = SignUpWithEmailRequest()
request.email = // ...
request.password = // ...
request.referralCode = // ...
do {
    let response = try await client.signUpWithEmail(request)
} catch {
    guard let error = error as? GRPCStatus else {
        print(&#38;quot;Error: \(error)&#38;quot;)
        return
    }
    print(error.code) // AlreadyExists
    print(error.message) // &#38;quot;Email already registered&#38;quot;
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;But, you, being a responsible client developer/tech lead/CTO, want to use the
type-safe enum from the protobuf definition so that you can display the error in
the right context, or perhaps localize it properly.&#60;/p&#62;
&#60;p&#62;Here&#39;s the big picture: there may be many such custom RPC error types. Our
solution should be universal, and flexible to handle each of them. Enter
interceptors! I mean, chances are, you know about them because you are working
with gRPC. Let&#39;s write one to get our type-safe status details. Starting with
a custom receive method, for the &#38;quot;.end&#38;quot; part of the response:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;final class GRPCErrorDetailsInterceptor&#38;lt;Request, Response&#38;gt;:
  ClientInterceptor&#38;lt;Request, Response&#38;gt;, @unchecked Sendable
{
  override func receive(
    _ part: GRPCClientResponsePart&#38;lt;Response&#38;gt;,
    context: ClientInterceptorContext&#38;lt;Request, Response&#38;gt;
  ) {
    switch part {
    case .end(var status, let headers):
      // extract the error details, and forward it.
    default:
      context.receive(part)
    }
  }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... the &#38;quot;end&#38;quot; part contains the error status, as well as some trailing metadata.
The metadata includes our status details under the key &#60;code&#62;grpc-status-details-bin&#60;/code&#62;.
It&#39;s base64 encoded, so we&#39;ll need to decode it...&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;switch part {
case .end(var status, let headers):
    guard
        // grab the status details
        let statusDetails = headers[&#38;quot;grpc-status-details-bin&#38;quot;].first,
        // decode to data
        let data = Data(base64Encoded: statusDetails),
    // ...
default:
  context.receive(part)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;At this point, with some experience with GRPC in Swift, you might think it&#39;s
time to instantiate your custom error type with &#60;code&#62;.init(seralizedData:)&#60;/code&#62;. But
there&#39;d be 2 problems:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;You don&#39;t want each custom types from protobuf to make an appearance in an
interceptor.&#60;/li&#62;
&#60;li&#62;This data would not be in the right shape, despite what the metadata key
says.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;In fact, the data is of the well-known type &#60;code&#62;Google_Rpc_Status&#60;/code&#62;. And our stutus
details, well, one its &#60;code&#62;.details&#60;/code&#62; element. So:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;switch part {
case .end(var status, let headers):
    guard
        let statusDetails = headers[&#38;quot;grpc-status-details-bin&#38;quot;].first,
        let data = Data(base64Encoded: statusDetails),
        // the data, despite being under &#38;quot;grpc-status-details-bin&#38;quot;, is
        // indeed not the status detail, but the statu itself:
        let googleStatus = try? Google_Rpc_Status(serializedData: data)
        // and the `details` field contains the actual status detail:
        let details = googleStatus.details.first,
    else {
        context.receive(part)
        break
    }
    // ...
default:
  context.receive(part)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... &#60;code&#62;details&#60;/code&#62; is of type &#60;code&#62;Google_Protobuf_Any&#60;/code&#62;. It is indeed a payload with the
content for &#60;code&#62;SignUpWithEmailErrorResponse&#60;/code&#62; as defined in the Protobuf. One
question remains: how do we pass it from our intereceptor to the RPC call site?&#60;/p&#62;
&#60;p&#62;Look at the call site from earlier: we have 2 code paths. If the call succeeds,
we get a &#60;code&#62;SignUpWithEmailResponse&#60;/code&#62;. If it fails, we get a &#60;code&#62;GRPCStatus&#60;/code&#62; as the
thrown error. Lucky for us, &#60;code&#62;GRPCStatus&#60;/code&#62; has an unused field, &#60;code&#62;cause&#60;/code&#62;. In my
version of &#60;code&#62;grpc-swift&#60;/code&#62;, the field has the following docstring:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;/// The cause of an error (not &#39;ok&#39;) status. This value is never transmitted
/// over the wire and is **not** included in equality checks.
public var cause: Error? { ... }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It seems like a perfect vessel for our status details!&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;switch part {
case .end(var status, let headers):
    guard
        let statusDetails = headers[&#38;quot;grpc-status-details-bin&#38;quot;].first,
        let data = Data(base64Encoded: statusDetails),
        let googleStatus = try? Google_Rpc_Status(serializedData: data)
        let details = googleStatus.details.first,
    else {
        context.receive(part)
        break
    }
    // isn&#39;t it convenient that we declared `status` as a `var` ealier 😉?
    status.cause = details
    // forward to the caller, yay!
    context.receive(.end(status, headers))
default:
  context.receive(part)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now our client will get the details of type &#60;code&#62;Google_Protobuf_Any&#60;/code&#62; from the
&#60;code&#62;.cause&#60;/code&#62; field of the thrown error. The client can proceed to decode it using
the protobuf-generated specific type with its built-in &#60;code&#62;.init(decodingAny:)&#60;/code&#62;
initializer:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Use the generated client code to make the gRPC request
var request = SignUpWithEmailRequest()
request.email = // ...
request.password = // ...
request.referralCode = // ...
do {
    let response = try await client.signUpWithEmail(request)
} catch {
    guard let error = error as? GRPCStatus else {
        print(&#38;quot;Error: \(error)&#38;quot;)
        return
    }

    // let&#39;s be type-safe, finally!
    guard
        let details = error.cause as? Google_Protobuf_Any,
        let signUpError = try? SignUpWithEmailErrorResponse(decodingAny: details)
    else {
        print(&#38;quot;Error: \(error)&#38;quot;)
        return
    }

    // 🎉
    switch signUpError.kind {
    // ...
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;h2&#62;Conclusion&#60;/h2&#62;
&#60;p&#62;I find this to be clean, targeted solution. Knowing the error detail&#39;s
transmission format is key to making this work. The fact that we also got
a clean architecture from exploiting an unused field is also very cool.&#60;/p&#62;
</description>
                <pubDate>Sat, 25 Jan 2025 19:53:30 -0800</pubDate>
                <link>https://duan.ca/2025/01/25/grpc-status-with-details-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2025/01/25/grpc-status-with-details-in-swift/</guid>
            </item>
            <item>
                <title>Notes on Using the MLIR C API in Swift</title>
                <description>&#60;p&#62;For curiosity&#39;s sake, I decided I want to play with MLIR&#39;s C API with Swift.
I spent quite some time to get a skeleton project up and running on my Mac.
Here&#39;s my notes for future reference. (If you find this useful, I&#39;d be curious
to know what you&#39;re working on!).&#60;/p&#62;
&#60;p&#62;Modern LLVM comes shipped with MLIR. At the time of writing, all I had to do to
get it is &#60;code&#62;brew install llvm&#60;/code&#62;. If you used the default Homebrew installation
options, you&#39;ll find &#60;code&#62;libMLIR.dylib&#60;/code&#62; and friends under
&#60;code&#62;/opt/homebrew/opt/llvm/&#60;/code&#62;. Building MLIR following the
&#60;a href=&#34;https://mlir.llvm.org/getting_started/&#34;&#62;instructions&#60;/a&#62; on the website is also
fairly straightforward.&#60;/p&#62;
&#60;p&#62;You&#39;ll want &#60;code&#62;llvm-config&#60;/code&#62; from your version of LLVM to be in your path. For the
Homebrew-installed version, you want &#60;code&#62;/opt/homebrew/opt/llvm/bin/&#60;/code&#62; to be one of
the place the shell looks.&#60;/p&#62;
&#60;p&#62;Now, it&#39;s time to make the project. With CMake, of course. Because I couldn&#39;t
figure out how to tell SwiftPM to link the right dylib :) But worry not, CMake
ain&#39;t that bad.&#60;/p&#62;
&#60;p&#62;Like with SwiftPM, we want to make a module for the MLIR C API. I call the module
&#60;code&#62;cmlir&#60;/code&#62;. Make a directory with that name, and create 2 text files:&#60;/p&#62;
&#60;p&#62;First, &#60;code&#62;module.modulemap&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;module cmlir [system] {
  header &#38;quot;shim.h&#38;quot;
  export *
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Second, &#60;code&#62;shim.h&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;#include &#38;lt;mlir-c/IR.h&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Amazing.&#60;/p&#62;
&#60;p&#62;Let&#39;s assume we want to have a Swift library that uses &#60;code&#62;cmlir&#60;/code&#62;. And a executable
that depends on the library. You can organize the Swift source files for these
as you like (yay CMake!).&#60;/p&#62;
&#60;p&#62;The sample library has one file, &#60;code&#62;lib.swift&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;import cmlir

public func makeAContext() -&#38;gt; MlirContext {
    mlirContextCreate()
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The sample app is just a &#60;code&#62;main.swift&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;import MLIRSwift

print(makeContext())
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... as you can see, through these targets, we are expecting to properly execute
some code from MLIR.&#60;/p&#62;
&#60;p&#62;All that&#39;s left is to build all these stuff. AKA, the hard part! But the
&#60;code&#62;CMakeLists.txt&#60;/code&#62; really isn&#39;t that bad. I&#39;ll just leave it here with comments:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-cmake&#34;&#62;cmake_minimum_required(VERSION 3.22)

# Note we include &#38;quot;C&#38;quot; here, without it there&#39;d be a build error 🤷
project(swift-mlir LANGUAGES C CXX Swift)

# This is where llvm-config comes to play
find_package(MLIR REQUIRED CONFIG)

include_directories(${MLIR_INCLUDE_DIRS})

# Include our modulemap
include_directories(cmlir)

# I can&#39;t believe this is all it takes to make a Swift dylib!
add_library(MLIRSwift SHARED lib.swift)

# Wasted a lot of time on figuring out the right library to link T-T
target_link_libraries(MLIRSwift PRIVATE MLIRCAPIIR)

# Nothing special here
add_executable(myapp main.swift)
target_link_libraries(myapp PRIVATE MLIRSwift)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;And there you have it. Here&#39;s the file structure in the end:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;.
├── CMakeLists.txt
├── cmlir
│   ├── module.modulemap
│   └── shim.h
├── lib.swift
└── main.swift
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;For completeness, I&#39;ll also include commands that produces the final
executables. It&#39;s just the simplest cmake commands. But it may not be obvious
for Swift programmers:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;make build # make a bulid direcory anywhere, make sure you .gitignore it if necessary
cd build
cmake -G Ninja ..
cmake --build .
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;With this sample project, running &#60;code&#62;build/myapp&#60;/code&#62; should get you this output:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;MlirContext(ptr: Optional(0x0000600001784180))
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;And that&#39;s just exciting, isn&#39;t it?&#60;/p&#62;
</description>
                <pubDate>Sat, 31 Aug 2024 18:44:48 -0700</pubDate>
                <link>https://duan.ca/2024/08/swift-mlir-cmake/</link>
                <guid isPermaLink="true">https://duan.ca/2024/08/swift-mlir-cmake/</guid>
            </item>
            <item>
                <title>AI Coding</title>
                <description>&#60;p&#62;I tried out GitHub Copilot this weekend. I&#39;ve &#60;a href=&#34;/2023/03/03/qualia-that-was-coding/&#34;&#62;been thinking&#60;/a&#62;, and talking, about AI like your average technology person. So here we are: what&#39;s my reaction to LLMs getting better and better at coding?&#60;/p&#62;
&#60;p&#62;LLMs are great at information retrieval. Copilot or GPT read a lot of code from GitHub, StackOverflow, Reddit, etc. And now, given some context (code in the file I&#39;m editing, its surrounding project info, etc), it can &#60;em&#62;retrieve&#60;/em&#62;, by probability, the best snippet of code that could come next. I posted this example on social media recently:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;Me: imports my own file system library Pathos (first time in this code base). Types name of computed property using it.&#60;/p&#62;
&#60;p&#62;Copilot: suggests an implementation that uses the library, slightly incorrectly.&#60;/p&#62;
&#60;p&#62;Me: Accepts suggestion, fixes error.&#60;/p&#62;
&#60;p&#62;Me: Types in name of second computed property.&#60;/p&#62;
&#60;p&#62;Copilot: suggests correct implementation using different parts of my library.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;Fantastic! I&#39;d like to think that the open-source code I put on GitHub made some small contribution to this specfic interarction of programming in Swift. If this is true, then I&#39;ve contributed to everyone who is going to use Copilot to write Swift. So did everyone who posted their questions, answers, examples, musings, tests, libraries, apps ... about Swift on the internet. Copilot is the child of our collective labor. Before these LLM programming tools, we didn&#39;t interact. Now, we have a hive mind.&#60;/p&#62;
&#60;p&#62;Will LLMs take our jobs?&#60;/p&#62;
&#60;p&#62;I can&#39;t wait for that to happen. But, so far, I just don&#39;t see it. Programming is, barely, superfacially, about information retrieval. When it is, it&#39;s usually in the context of studying, training, interviewing, or some type of product grind. Sure, that covers a lot of of reason for writing code. BUT, here&#39;s the thing: I hate writing code for all of those reasons. If you had some time working in tech, you&#39;d have heard the saying along the lines of &#38;quot;programmer should try their best to replace themselves&#38;quot;. This is partially about working with people around you, but it also serves as a lens to evaluate programming tasks: if you are doing simple things over and over again, it means you are stuck at a place of stagnation. You are not growing, and probably not creating as much values as you &#60;em&#62;deserve&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;LLMs are going to replace some of the things we do as programmers. The parts that are boring, repetitive, stagnating. Will some people lose their jobs because of it? Maybe. At first, these will be, for the sake of simplicity, &#38;quot;low-level&#38;quot; jobs (I&#39;m going to deliberatly leave &#38;quot;low-level&#38;quot; undefined here). For those who get to stay, however, our lives are going to become more fun and creative. Why yes, I included myself in this group because I&#39;m &#60;a href=&#34;https://en.wikipedia.org/wiki/Egocentric_bias&#34;&#62;egocentrically biased&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;Let&#39;s say I&#39;m wrong, these AI models, very quickly, grew super capable, to such degree that it&#39;s no longer commercially viable to hire humans for programming tasks. Well, it would be a kick in the butt for me to have to find a new career. But a kick in the butt is often the right thing to move us along in life, yes? When your comfort zone comes with a biweekly paycheck, it&#39;s extra hard to grow outside of it. But I should love to live in the post-progammer world as a software &#60;em&#62;user&#60;/em&#62;. Chances are, there&#39;d be less bugs?&#60;/p&#62;
&#60;p&#62;Anyways, this has been my super unscientific, totally biased, very personal musings about AI this week.&#60;/p&#62;
</description>
                <pubDate>Mon, 27 Mar 2023 20:10:14 -0700</pubDate>
                <link>https://duan.ca/2023/03/27/ai-coding/</link>
                <guid isPermaLink="true">https://duan.ca/2023/03/27/ai-coding/</guid>
            </item>
            <item>
                <title>Don&#39;t Say That</title>
                <description>&#60;p&#62;&#60;em&#62;Alice: Hey, did you know that COVID virus was leaked from a lab?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Bob: No no, you don’t know that. Don’t be racist!&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Alice: Oh, sorry I didn’t know. How so?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Bob: Because the lab is in China.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Alice: Ok, so where DID the virus come from?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Bob: It jumped from bats to pangolin, and then to humans in a wet market.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Alice: A what market?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Bob: Wet market in China. People buy animals from there.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Alice: Who would want to buy a bat. or a … what’s the other one?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Bob: They eat bats. It&#39;s normal for them.&#60;/p&#62;
</description>
                <pubDate>Sat, 11 Mar 2023 22:03:03 -0800</pubDate>
                <link>https://duan.ca/2023/03/11/do-not-say-that/</link>
                <guid isPermaLink="true">https://duan.ca/2023/03/11/do-not-say-that/</guid>
            </item>
            <item>
                <title>The Qualia that was Coding</title>
                <description>&#60;p&#62;As of this writing, I&#39;m deeply skeptical of LLM replacing our needs for skilled programmers. Problem solving is a creative process. When a new tool takes away the repetitive part of a job, the worker can focus more on being creative.&#60;/p&#62;
&#60;p&#62;However, if one believes that LLM, or some alternative models, will bring about the end of programming as a wide-spread human activity, then we&#39;ll have a problem (well, probably a few problems) at hand.&#60;/p&#62;
&#60;p&#62;Programming is a lonely activity. Yes, let&#39;s acknowledge the existence of peer programming, code reviews, design meetings, etc. But the deep work -- exploring the problem space, grappling with known/unknown constraints, iterating on the design… these things happen in the programmer&#39;s own head. When the satisfying answer emerges in the end, so many paths has been traveled that the traveler can&#39;t even retread them in themselves, let alone sharing it with others. This is blatantly obvious to anyone who&#39;s accomplished non-trivial programming tasks.&#60;/p&#62;
&#60;p&#62;The end of programming means the end of such experience.&#60;/p&#62;
&#60;p&#62;I have no doubt that people will keep writing code even if machines are more capable of doing it wholesale. To what degree would those people share the level of challenges, passion, skill, or, let&#39;s face it, pain in writing code, I cannot predict. But it seems abundantly clear that, those people would amass to a small fraction of the total number of programmers today.&#60;/p&#62;
&#60;p&#62;If you believe you are the last generation of human programmers, the human experience, the &#60;em&#62;qualia&#60;/em&#62; of programming is yours to lose.&#60;/p&#62;
&#60;p&#62;Does that make sense? When AI models can replace us, we will forget what&#39;s like to write code without them &#60;em&#62;really&#60;/em&#62; soon. Maybe the literal we, who lived through it won&#39;t, but future generations may never truly know it. Difficult as it is, it might be worth your time to leave records of what it&#39;s like to be in the flow state, what it&#39;s like to feel stuck, what it&#39;s like to steadily traverse and eliminate alternative theories for a bug, what it&#39;s like to perform mastery with primitive tools to generate clues, what it&#39;s like to critic a working prototype, what it&#39;s like to lay out a suite of tests, what it&#39;s like to replace a huge amount of code with better, shorter code...&#60;/p&#62;
&#60;p&#62;If God is coming, the least we can do is to give future anthropologist a helping hand, and document what it was like to be a human.&#60;/p&#62;
</description>
                <pubDate>Fri, 03 Mar 2023 23:42:34 -0800</pubDate>
                <link>https://duan.ca/2023/03/03/qualia-that-was-coding/</link>
                <guid isPermaLink="true">https://duan.ca/2023/03/03/qualia-that-was-coding/</guid>
            </item>
            <item>
                <title>The Lazy Programmer&#39;s Guide to Single-user Mastodon</title>
                <description>&#60;p&#62;As of today, my identity in the &#38;quot;fediverse&#38;quot; has become &#60;code&#62;@daniel@duan.ca&#60;/code&#62;. This post was originally published
on &#60;code&#62;duan.ca&#60;/code&#62;. Pretty neat, eh? I achieved this by hosting a private instance of the open-source Mastodon
project. Here&#39;s my experience setting that up, and why it seemed harder than it is.&#60;/p&#62;
&#60;h2&#62;What exactly did I achieve?&#60;/h2&#62;
&#60;p&#62;I own the domain &#60;code&#62;duan.ca&#60;/code&#62;, which serves as the root of an existing website. I set up an functioning
instance of Mastodon with a single user &#60;code&#62;@daniel&#60;/code&#62;. This user is discoverable in other Mastodon instances as
&#60;code&#62;@daniel@duan.ca&#60;/code&#62;.&#60;/p&#62;
&#60;h2&#62;How did I do it?&#60;/h2&#62;
&#60;p&#62;As someone who barely touch server-side programming, running a Mastodon instance seemed very daunting to me.
What database to use? How? What&#39;s the best way to host a Rails app? I need a email server? Where to host the
media files I post?&#60;/p&#62;
&#60;p&#62;There are a lot of step-by-step set-up tutorials on the internet. This post is, definitively, not one of
those. But having gone through the process of &#60;a href=&#34;https://web.archive.org/web/20221219043954/https://marketplace.digitalocean.com/apps/mastodon&#34;&#62;setting up an instance on DigitalOcean&#60;/a&#62;, I end up with a few
tips and tricks to share! Let&#39;s through them:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;If you have a DigitalOcean account, setting a server up is as simple as searching up &#38;quot;Mastodon&#38;quot; in their
market place as a step in creating your Droplet.&#60;/li&#62;
&#60;li&#62;You &#60;em&#62;do not&#60;/em&#62; need an email server for a single-user instance. Think about it, you have root access to the
database, what do you need email for? Verify your own identity? Spam yourself?&#60;/li&#62;
&#60;li&#62;That said, Sendgrid is free for low-volume emails.&#60;/li&#62;
&#60;li&#62;Ok, you ssh into your Droplet, the first thing you see is a guided CLI experience for setting things up.
Don&#39;t go through it just yet! For me, my root domain &#60;code&#62;duan.ca&#60;/code&#62; hosts an entirely different site. So I have
to pick a subdomain to host Mastodon. Make sure you set up an A record in your website&#39;s DNS for your
chosen subdomain. If this record isn&#39;t read, the guided setup will fail when it tries to get an certificate
from Let&#39;s Encrypt.&#60;/li&#62;
&#60;li&#62;Unless you want to buy a new DNS service from DigitalOcean, your A record should be configured with your
existing DNS server provider! I needed a few minutes to un-confuse myself about this fact. DigitalOcean&#39;s
documentation makes it really hard to discover this fact.&#60;/li&#62;
&#60;li&#62;The only thing you need to get right is your subdomain, and the DNS record for it. In the rest of the
guided setup, you can make mistakes, and you can fix them later.&#60;/li&#62;
&#60;li&#62;I used an s3 bucket for media. s3&#39;s UX is kind of terrible, so if you are doing it for the first time, good
luck.&#60;/li&#62;
&#60;li&#62;Instead of &#38;quot;admin&#38;quot;, choose your Mastodon username in the setup guide. This user does not have special
privilege for the site anyways, despite what the default name suggests. After this step, the guide will
provide you with a password, take note of that if you want to log in with this user later :)&#60;/li&#62;
&#60;li&#62;Again, you could figure out how to get an STMP server to send emails on your Mastodon instance&#39;s behalf.
But you are the only user, right? So you can just make some value up for all things SMTP/email related. At
the end, when the guide asks whether to send a test Email, choose &#38;quot;no&#38;quot;.&#60;/li&#62;
&#60;li&#62;The Mastodon code is located at &#60;code&#62;/home/mastodon/live&#60;/code&#62;. Most of the information is stored in
&#60;code&#62;.env.production&#60;/code&#62; in that directory. This is where you can change your mind/fix your mistake from the
guided setup. You can use Vim instead of Nano. (Although if you like Vim, you&#39;d probably find out
anyways).&#60;/li&#62;
&#60;li&#62;Mastodon ships with an admin &#60;a href=&#34;https://docs.joinmastodon.org/admin/tootctl/&#34;&#62;CLI tool&#60;/a&#62; &#60;code&#62;tootctl&#60;/code&#62;. It&#39;s located in &#60;code&#62;bin/tootctl&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Before attempting to run this tool, switch to user &#60;code&#62;mastodon&#60;/code&#62; by running &#60;code&#62;su mastodon&#60;/code&#62;. Otherwise, you&#39;d
be confused as to why you need to install Ruby stuff, and can&#39;t connect to the Postgres database.&#60;/li&#62;
&#60;li&#62;If the guide didn&#39;t tell you an error, and your values in &#60;code&#62;.env.production&#60;/code&#62; are all right, you will be
able to type your subdomain in a browser and see Mastodon! Log in with your username and password from
the guide. Upload a profile photo to test whether your media service is set up correctly.&#60;/li&#62;
&#60;li&#62;(DO NOT DO THIS until you finish the next step!) At this point, you&#39;d be able to go to an existing
Mastodon instance, and look yourself up! If your subdomain is &#60;code&#62;social.duan.ca&#60;/code&#62;, username &#60;code&#62;daniel&#60;/code&#62;, you
should be discoverable as &#60;code&#62;@daniel@social.duan.ca&#60;/code&#62; on a site such as &#60;a href=&#34;https://mastodon.social&#34;&#62;mastodon.social&#60;/a&#62; now. But if you
do this, that site may get confused, and permanently consider &#60;code&#62;@daniel@social.duan.ca&#60;/code&#62; as your fediverse
identity. So don&#39;t do that! Finish the next step.&#60;/li&#62;
&#60;li&#62;To use your root domain instead of this subdomain, you 301 redirect &#60;code&#62;/.well-known/host-meta*&#60;/code&#62; from root to
the real location. &#60;a href=&#34;https://masto.host/mastodon-usernames-different-from-the-domain-used-for-installation/&#34;&#62;this article&#60;/a&#62; explains it very well. Make sure to both set up the URL
redirect, as well as &#60;code&#62;LOCAL_DOMAIN&#60;/code&#62;, and &#60;code&#62;WEB_DOMAIN&#60;/code&#62; in &#60;code&#62;.env.production&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Make your user the owner of the site (RTFM). You&#39;ll see additional, site-wide settings afterwards. Make
sure to disable signup, either in the GUI, or with &#60;code&#62;tootctl&#60;/code&#62;.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;That it! These may seem like a lot of tips, but I think, as a smart programmer, you can eventually figure all
of these things out pretty easily. I put them down here because, had I known these, I would&#39;ve saved a bunch
of times in the end.&#60;/p&#62;
&#60;h2&#62;Why?&#60;/h2&#62;
&#60;p&#62;Why spend the time, and money, to go through all of this?&#60;/p&#62;
&#60;p&#62;This is a really good question. I &#60;a href=&#34;https://duan.ca/2022/11/20/the-social-graph/&#34;&#62;wished&#60;/a&#62; less people would
leave Twitter. I host my personal site/blog on my own domain, as opposed to using a Medium site or something.
So, if I have to &#38;quot;federate&#38;quot; my microblogs, why shouldn&#39;t I try to gain more independence? How many of these
mastodon instances can do better than Twitter, in terms of site maintenance, and content moderation? Instinct
tells me, something between self-hosting, and Twitter, might be the right balance. But I&#39;m here for the long
haul, and, if self-hosting proves to be the wrong direction, I&#39;ll pivot.&#60;/p&#62;
&#60;p&#62;Until then, this has been fun.&#60;/p&#62;
</description>
                <pubDate>Sat, 10 Dec 2022 18:21:11 -0800</pubDate>
                <link>https://duan.ca/2022/12/10/lazy-mastodon/</link>
                <guid isPermaLink="true">https://duan.ca/2022/12/10/lazy-mastodon/</guid>
            </item>
            <item>
                <title>The Social Graph</title>
                <description>&#60;p&#62;From a purely personal perspective, connecting with people via the internet is good. I&#39;m grateful that services such as Twitter exist. Since the year 2008, a significant amount of my life happened on Twitter. The only important component of Twitter is the connections. I&#39;m lucky that some people like what I post. I&#39;m used to a small stream of thoughts from those I follow.&#60;/p&#62;
&#60;p&#62;These days, those I follow aren&#39;t posting much. They are posting on other websites. The connection I so depend on are broken. It saddens me. Therefore, I&#39;m forced to move to maintain the connections.&#60;/p&#62;
&#60;p&#62;I have many thoughts. A tweet storm? Well, if the cool people are there to read it, sure. Knowing myself, I&#39;ll probably cross-post it to the many places where my people are. That&#39;s a hustle that I don&#39;t have the patience for. That saddens me, too.&#60;/p&#62;
&#60;p&#62;So, here we are, the good old blog post. Cross-posting a link is doable.&#60;/p&#62;
&#60;h2&#62;The Twexit&#60;/h2&#62;
&#60;p&#62;Remember when we make Brexit jokes about everything on Twitter? Good times! Here&#39;s what I think about the &#38;quot;Twexit&#38;quot;.&#60;/p&#62;
&#60;p&#62;Thanks to email archive and 1Password, I found my mastodon.social login credentials. According to the site, I joined in 2018 (coincidentally, an exact decade later that me joining Twitter). 4 years ago was when me, and, more importantly, a lot of the people I follow on Twitter, first learned about Mastodon. They had their reasons to give it a try. They were my reason to give it a try. We did.&#60;/p&#62;
&#60;p&#62;I honestly can&#39;t tell if this time is more different than that last time. We were, and are, voting with our feet.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Warning: the following is a cynical take.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;We are leaving this time, partially, because a lot of Twitter employee were forced to leave. They built the site for us, we are grateful for their work. We find them getting laid off / forced to change life style unacceptable, so much so that we... abandon the product they built for lesser ones.&#60;/p&#62;
&#60;p&#62;Of course, that illogicality was based on some superficial analysis. An easier, logical path to follow, but also a harder truth to swallow, is that the Twexit, both times, were motivated by hate. Hate over a person that possess outsized influence on the platform.&#60;/p&#62;
&#60;p&#62;To hate is not wrong. Again, I don&#39;t have this reason to leave. Simply, I want to maintain my connections. I wish I shared the hate, though. Because that would&#39;ve made me less sad.&#60;/p&#62;
&#60;p&#62;(Perhaps &#38;quot;hate&#38;quot; is too strong of a word. Substitute it with the word you associate with the big personalities that drove you or your followees off to other platforms).&#60;/p&#62;
&#60;p&#62;Will Twexit succeed this time?&#60;/p&#62;
&#60;p&#62;I&#39;ve observed (to my relief!) that my timeline on Twitter hasn&#39;t completely died. It would&#39;ve been chilling to see it die (remember those empty streets during early COVID? NOT great, no). I hold out hope that better the user experience will ultimately prevail (more on that in the next section); and negative emotions alone won&#39;t sustain this round of Twexit.&#60;/p&#62;
&#60;h2&#62;A Better Social Graph&#60;/h2&#62;
&#60;p&#62;That is not to say &#38;quot;I hope everyone return to Twitter&#38;quot;. If Mastodon in late 2022 turns out to be a better product, I&#39;m happy to migrate/establish new connections there.&#60;/p&#62;
&#60;p&#62;Now, I, the master of the Daniel-verse, will tell you what the best user experience for &#38;quot;social media&#38;quot;
could/should have been.&#60;/p&#62;
&#60;p&#62;This text you are reading is originally published on a personal website composed of purely static assets
(mainly HTML, minimal amount of CSS, and essentially, no JavasSript). Critically, it also includes this
advanced technology called an RSS feed.&#60;/p&#62;
&#60;p&#62;If I have to psyco-analyze the young Danial from early 2010s (why not?), an important reason he became
hopelessly dependent on Twitter was the death of Google Reader. Prior to that event, the web service he
habitually check was not predominately Twitter.&#60;/p&#62;
&#60;p&#62;Some of us remember how the connections were built prior to Facebook and Twitter. There were many sites that served similar purposes, sure. But there&#39;s also a community that subscribed to each others&#39; RSS feed. We commented on others&#39; posts, we linked and reposted, and commented on the comments. There were conversations, connections. An event that stood out for me during that era was when &#60;a href=&#34;https://en.wikipedia.org/wiki/Larry_Wall&#34;&#62;Larry Wall&#60;/a&#62; commented on my post about his Perl book. You see, the connections included cool people, too.&#60;/p&#62;
&#60;p&#62;So, Google Reader. What if a API for posting comments for a web link became standardized? What if the RSS readers includes a text box for that API? What if everyone also include comments (ignore spams for now) in their feeds?&#60;/p&#62;
&#60;p&#62;Yeah, that would be, arguably, a similar experience to Twitter or Mastodon today. In fact, this isn&#39;t even
a new idea. The &#60;a href=&#34;https://indieweb.org/&#34;&#62;IndieWeb&#60;/a&#62; folks did their Twexit before Google Reader was killed. In
retrospect, they were smart as hell. We didn&#39;t follow their footsteps because Twitter turned out to be
a better user experience for people that don&#39;t own a website. Things could easily have played out differently,
though. Blogging and RSS could&#39;ve become more mainstream sooner. Web 2.0 could&#39;ve improved interactivity of
these blogs and feeds. Facebook and Twitter wouldn&#39;t have become so big of a deal.&#60;/p&#62;
&#60;p&#62;Oh well.&#60;/p&#62;
&#60;h2&#62;We Are All Indie Web&#60;/h2&#62;
&#60;p&#62;That&#39;s an inspirational statement. In this moment, I&#39;m more convinced of this inspiration than ever. More
Mastodon-like open-source software, more protocols such as ActivityPub, smarter economic structures for
content ownership. All of these, and more.&#60;/p&#62;
&#60;p&#62;In late 2022, this opening prose from the ancient Chinese book Romance of the Three Kingdoms keeps echoing
in my mind:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;...分久必合，合久必分&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;Literally, it means &#38;quot;Long periods of division precede unity and long periods of unity precede division.&#38;quot;&#60;/p&#62;
&#60;p&#62;From Google Reader to Twitter to Mastodon, this tension between centralization and decentralization is oh-so-familiar. An equilibrium that could stabilize, IMHO, is a centralized user experience running on a decentralized infrastructure. Naively, that&#39;s a software thing. Realistically, it all rely on the collective mind of our social graph. Our connections forms the graph, the graph funnels in money, the money makes the good user experience. Sorry, money plays a role in the real world, like it or not.&#60;/p&#62;
&#60;p&#62;For now, though, I&#39;m happy to work to maintain my connections. I&#39;ll use many sites. I&#39;ll also try to become &#38;quot;indie&#38;quot;. Maybe I&#39;ll set up a feed for &#38;quot;microblogging&#38;quot;, and write some service to cross-post to those sites. Maybe I&#39;ll write my own mastodon-compatible ActivityHub implementation. Maybe these will turn out to be some more ill-fated personal projects -- that sounds awfully fun.&#60;/p&#62;
</description>
                <pubDate>Sun, 20 Nov 2022 13:06:48 -0800</pubDate>
                <link>https://duan.ca/2022/11/20/the-social-graph/</link>
                <guid isPermaLink="true">https://duan.ca/2022/11/20/the-social-graph/</guid>
            </item>
            <item>
                <title>Control</title>
                <description>&#60;p&#62;For whatever reason, a dialogue from the Matrix trilogy stuck with me. I&#39;ve never heard anyone else talk
about these quotes. Maybe they aren&#39;t that deep and I have been over-projecting meanings. Anyways, Neo (&#60;strong&#62;N&#60;/strong&#62;)
and Councillor Hamann (&#60;strong&#62;H&#60;/strong&#62;) are in the last human city Zion, looking at a vast array of machines. They had
this exchange about &#60;em&#62;control&#60;/em&#62;:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;&#60;strong&#62;H&#60;/strong&#62;: Down here, sometimes I think about all those people still plugged into the Matrix and when I look at these machines I can&#39;t help thinking that in a way we are plugged into them.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;N&#60;/strong&#62;: But we control these machines; they don&#39;t control us.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;H&#60;/strong&#62;: Of course not. How could they? The idea is pure nonsense. But… it does make one wonder… just… what is control?&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;N&#60;/strong&#62;: &#60;em&#62;If we wanted, we could shut these machines down.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;H&#60;/strong&#62;: Of course. That&#39;s it. You hit it. That&#39;s control, isn&#39;t it? If we wanted we could smash them to bits. Although, if we did, we&#39;d have to consider what would happen to our lights, our heat, our air…&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;It is scary how often this definition of (lack of) control applies in life.&#60;/p&#62;
&#60;p&#62;Figured I&#39;d share.&#60;/p&#62;
</description>
                <pubDate>Wed, 22 Jun 2022 13:13:09 -0700</pubDate>
                <link>https://duan.ca/2022/06/22/control/</link>
                <guid isPermaLink="true">https://duan.ca/2022/06/22/control/</guid>
            </item>
            <item>
                <title>Pro-Science, Anti Research</title>
                <description>&#60;p&#62;Science discussion in the mainstream always focus on the reductive &#38;quot;pro&#38;quot; vs &#38;quot;anti&#38;quot; dynamic. While there are
a lot of people in the world who flat-out &#60;em&#62;deny&#60;/em&#62; the existence of established science, making the mainstream
conversation a worthy discourse, that&#39;s not what I&#39;m trying to participate here.&#60;/p&#62;
&#60;p&#62;Within the &#38;quot;for-science faction&#38;quot;, there are two seemingly compatible points of view:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;We should save humanity from distinction.&#60;/li&#62;
&#60;li&#62;We should improve the human condition.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;See the difference? Some do, others blind themselves to it.&#60;/p&#62;
&#60;p&#62;Surely, distinction is a worse human condition?&#60;/p&#62;
&#60;p&#62;Correct!&#60;/p&#62;
&#60;p&#62;... therefore, we shouldn&#39;t get distracted by things like making rockets, digitizing our minds, creating suns
on earth. Oh, we still need basic science research but... if we could spend money on saving ourselves, those
far-out ideas should take a chill pill. Survival is the most important thing!&#60;/p&#62;
&#60;p&#62;The argument is around austerity: &#60;a href=&#34;https://en.wikipedia.org/wiki/Roulette&#34;&#62;why put the chips on 21, when we can put it on black&#60;/a&#62;?&#60;/p&#62;
&#60;p&#62;It&#39;s strange, isn&#39;t it? The crowd that wants dirty energy sources gone, also dislike space exploration? The
&#38;quot;progressives&#38;quot; wants nothing but to conserve?&#60;/p&#62;
&#60;p&#62;Scientific research &#60;em&#62;should&#60;/em&#62; be expensive, because, in order to improve our lives in unimaginable ways, &#38;quot;the
science&#38;quot; must &#60;em&#62;actuate&#60;/em&#62;. Knowing an asteroid&#39;s existence is not the same as harvesting the resource from it;
knowing how the sun works is not the same as replicating it here; knowing a monkey can play pong with brain
probes is not the same as humans doing it safely. (Some may categorize these things as &#38;quot;engineering&#38;quot; or
&#38;quot;commercialization&#38;quot;: yes, all of that.)&#60;/p&#62;
&#60;p&#62;The austerity argument is anti-scientific research. Saying we should save money on fusion to spend more money
on solar panels is the same as &#38;quot;but children are starving in Africa!&#38;quot;.&#60;/p&#62;
&#60;p&#62;The world sucks in multiple ways. You may feel overwhelmed that, as a whole, humanity is under siege for one
reason or another. But others may feel differently. They want to put their limited chips on a riskier bet for
bigger returns. They &#60;a href=&#34;https://en.wikipedia.org/wiki/Expected_value&#34;&#62;are no less rational&#60;/a&#62; than you. And (thank god) we don&#39;t have a world dictator that
forces us to take their bet, or yours.&#60;/p&#62;
&#60;p&#62;I&#39;m at peace with that.&#60;/p&#62;
</description>
                <pubDate>Fri, 20 May 2022 15:33:25 -0700</pubDate>
                <link>https://duan.ca/2022/05/20/pro-science-yet-anti-research/</link>
                <guid isPermaLink="true">https://duan.ca/2022/05/20/pro-science-yet-anti-research/</guid>
            </item>
            <item>
                <title>Visceral</title>
                <description>&#60;p&#62;Growing up in China, I remember using google.cn daily. At some point in my teens, it stopped working, and I had to use google.com.hk . Then ... I left. The first time I got off the plane in the US, and got on a computer, google.com was the browser homepage.&#60;/p&#62;
&#60;p&#62;Now, this is not a story about how important Google is to me (to the dismay of the fully adult version of me, it is). Around the same time, there were other, perhaps less relatable things happening to the internet that was once niche, and open to Chinese users (small website hosting services got shut down one by one, blog posts got deleted a few days later, all websites forced to have government approval to exist). As a teen, I didn&#39;t like that feeling of spaces closing around me. I didn&#39;t have money, the freedom to explore virtually was precious.&#60;/p&#62;
&#60;p&#62;Most people on Twitter never had visceral experience of censorship like mine. It&#39;s not something that happens to some asshole spewing hate on a website; not a sinister plot that aims at your group with some shared some beliefs. True censorship feels like environment decay, like oxygen leaving the air. It&#39;s quite, gradual, steady. It happens to everyone, and no one. It happens to &#60;em&#62;you&#60;/em&#62;, whether you know it or not.&#60;/p&#62;
&#60;p&#62;The thing about &#38;quot;visceral&#38;quot; tho, is that it&#39;s personal by definition. These words won&#39;t duplicate my experience in you. But maybe you will pause and smell the roses, and the subtle decrease of oxygen in your air.&#60;/p&#62;
</description>
                <pubDate>Tue, 26 Apr 2022 10:42:58 -0700</pubDate>
                <link>https://duan.ca/2022/04/26/visceral/</link>
                <guid isPermaLink="true">https://duan.ca/2022/04/26/visceral/</guid>
            </item>
            <item>
                <title>Using Instruments on Non-macOS, Non-iOS Executables</title>
                <description>&#60;p&#62;How do you use use Instruments, the instrumentation tool distributed alongside Xcode? It&#39;s easy if you are
profiling a macOS or iOS app. No so with a regular old command-line tool built, say, with SwiftPM. To do so,
you&#39;ll need to codesign the target binary. Otherwise Instruments will give you a &#60;code&#62;&#38;quot;Failed to gain authorization&#38;quot;&#60;/code&#62; error message.&#60;/p&#62;
&#60;p&#62;Here&#39;s the steps:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;Create a entitlement file with &#60;code&#62;com.apple.security.get-task-allow&#60;/code&#62; set to true:&#60;/li&#62;
&#60;/ol&#62;
&#60;pre&#62;&#60;code class=&#34;language-xml&#34;&#62;&#38;lt;?xml version=&#38;quot;1.0&#38;quot; encoding=&#38;quot;UTF-8&#38;quot;?&#38;gt;
&#38;lt;!DOCTYPE plist PUBLIC &#38;quot;-//Apple//DTD PLIST 1.0//EN&#38;quot; &#38;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#38;quot;&#38;gt;
&#38;lt;plist version=&#38;quot;1.0&#38;quot;&#38;gt;
    &#38;lt;dict&#38;gt;
        &#38;lt;key&#38;gt;com.apple.security.get-task-allow&#38;lt;/key&#38;gt;
        &#38;lt;true/&#38;gt;
    &#38;lt;/dict&#38;gt;
&#38;lt;/plist&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Let&#39;s call it &#60;code&#62;Entitlements.plist&#60;/code&#62;&#60;/p&#62;
&#60;ol start=&#34;2&#34;&#62;
&#60;li&#62;
&#60;p&#62;Build the executable.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Codesign your executable with the entitlement file&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;pre&#62;&#60;code&#62;codesign -s - -f --entitlements path/to/Entitlements.plist path/to/executable
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now proceed with your profiling in Instruments.&#60;/p&#62;
&#60;p&#62;Not sure where this is officially documented. So I&#39;m officially documenting it here.&#60;/p&#62;
</description>
                <pubDate>Thu, 31 Mar 2022 20:39:05 -0700</pubDate>
                <link>https://duan.ca/2022/03/31/instrumenting-commandline-executables/</link>
                <guid isPermaLink="true">https://duan.ca/2022/03/31/instrumenting-commandline-executables/</guid>
            </item>
            <item>
                <title>Flake For Non-Nix Projects</title>
                <description>&#60;p&#62;The ideal outcome of using Nix or home-manager is to have as many things as possible under their control.
Among these things are developer tools for coding. You may need &#60;code&#62;cargo&#60;/code&#62;, and &#60;code&#62;rust-analyzer&#60;/code&#62; for Rust projects;
&#60;code&#62;ipython&#60;/code&#62;, and &#60;code&#62;python-lsp-server&#60;/code&#62; for Python projects, etc.&#60;/p&#62;
&#60;p&#62;Of course, the simplest solution is to have them all installed and configured in home-manager or the OS level.
But, over time, you&#39;ll end up with a ton of stuff.&#60;/p&#62;
&#60;p&#62;Maybe that won&#39;t bother you. Fine, but this approach is at odds with some convention of the Nix community. You
see, there&#39;s this command called &#60;code&#62;nix-shell&#60;/code&#62;, or &#60;code&#62;nix develop&#60;/code&#62;, which sets up a environment with certain
packages, with the expectation that you only need them sometimes, usually within the context of developing
a certain software project.&#60;/p&#62;
&#60;p&#62;So, arguably, a better alternative to installing everything you possibly need is to keep only the essential
tools you always need, regardless of what you are working on. Things like &#60;code&#62;neovim&#60;/code&#62;, &#60;code&#62;git&#60;/code&#62;, &#60;code&#62;ripgrep&#60;/code&#62;, etc.
When a project demands things such as &#60;code&#62;rust-analyzer&#60;/code&#62;, running &#60;code&#62;nix develop&#60;/code&#62; should set it up for you.&#60;/p&#62;
&#60;p&#62;How do we implement that? In a imaginary world where every single software project is built with a flake.nix,
the &#60;code&#62;devShell&#60;/code&#62; property should provide everything the software project owner expect you to need. And you just
&#60;code&#62;cd&#60;/code&#62; into the root of the project, run &#60;code&#62;nix develop&#60;/code&#62;, and you are off to the races.&#60;/p&#62;
&#60;p&#62;Several problems:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;running &#60;code&#62;nix develop&#60;/code&#62; is repetitive, and therefore, annoying.&#60;/li&#62;
&#60;li&#62;the owner of a flake.nix may have drastically different taste for the best dev tools for their project
(bet!).&#60;/li&#62;
&#60;li&#62;we don&#39;t live in a world built with Nix flakes.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Yikes.&#60;/p&#62;
&#60;p&#62;To solve &#60;code&#62;1&#60;/code&#62;, enter &#60;a href=&#34;https://github.com/nix-community/nix-direnv&#34;&#62;direnv&#60;/a&#62;. It&#39;s a piece of software that let you create a environment for a directory,
and automatically switch to it when you enter said directory. The &#38;quot;environment&#38;quot; could contain envvars, and,
you guessed it: a Nix developer shell. If you have a flake.nix, add &#60;code&#62;use flake&#60;/code&#62; in your project directory&#39;s
&#60;code&#62;.envrc&#60;/code&#62; file, direnv will automatically call &#60;code&#62;nix develop&#60;/code&#62; the next time you &#60;code&#62;cd&#60;/code&#62; in. Neat!&#60;/p&#62;
&#60;p&#62;To make this work in practice, you&#39;ll want to add &#60;code&#62;.envrc&#60;/code&#62; and &#60;code&#62;.direnv/&#60;/code&#62; to your global git ignore list, as
they are personal preferences that probably shouldn&#39;t end up in git history.&#60;/p&#62;
&#60;p&#62;Ok, we are so close to solve problem &#60;code&#62;2&#60;/code&#62;, and &#60;code&#62;3&#60;/code&#62; now. In short, &#60;code&#62;nix develop&#60;/code&#62; may set up &#60;strong&#62;a&#60;/strong&#62; environment,
but it may not be &#60;strong&#62;the&#60;/strong&#62; environment that suits you the best. &#60;a href=&#34;https://github.com/nix-community/nix-direnv&#34;&#62;nix-direnv&#60;/a&#62; extends direnv to save us:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;use flake path/to/flake#target
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... with this in &#60;code&#62;.envrc&#60;/code&#62;, direnv will set up the Nix environment according to &#60;code&#62;path/to/flake#target&#60;/code&#62;. That
could point to any location on your hard drive! You can have a flake.nix whose &#60;code&#62;devShell&#60;/code&#62; has &#60;code&#62;cargo&#60;/code&#62;, and
&#60;code&#62;rust-analyzer&#60;/code&#62;. You can have another with &#60;code&#62;ipython&#60;/code&#62;, and &#60;code&#62;python-lsp-server&#60;/code&#62;. Mix and match to your liking to
the infinite degree...&#60;/p&#62;
&#60;p&#62;For now, I&#39;ve decided to give nix-direnv a try. Alongside my home-manager configuration, I&#39;ve also included
extra flakes for generic Python/Rust projects, and specific projects that may require a mix of tools. A lot of
the project I work on don&#39;t use flake as their package manager. With this approach, I get to customize my
setup for them each, and stay in the comfort of Nix and home-manager.&#60;/p&#62;
&#60;p&#62;direnv and nix-direnv can be configured together with home-manager. To achieve everything mentioned in this
article, including direnv&#39;s shell integration (Fish, for me), it&#39;s as simple as&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-Nix&#34;&#62;# In home manager config...
programs.direnv = {
  enable = true;
  nix-direnv = {
    enable = true;
    enableFlakes = true;
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To recap, having the snippet above in my home-manager setup, I now can enter any project&#39;s root directory and
add a &#60;code&#62;.envrc&#60;/code&#62; file with the content &#60;code&#62;use flake ~/src/dotfiles/direnvs/python&#60;/code&#62;.
&#60;code&#62;~/src/dotfiles/direnvs/python&#60;/code&#62; contains a &#60;code&#62;flake.nix&#60;/code&#62; (and a &#60;code&#62;flake.lock&#60;/code&#62;) that has the &#60;code&#62;devShell&#60;/code&#62; value
I like for all Python projects. When I &#60;code&#62;cd&#60;/code&#62; into this project, &#60;code&#62;(nix-)direnv&#60;/code&#62; will read from that &#60;code&#62;devShell&#60;/code&#62;
and set every tool listed under there. The tools are cached in a &#60;code&#62;.direnv&#60;/code&#62; directory so when I return here,
the setup is basically instantaneous. Since I make &#60;code&#62;git&#60;/code&#62; to ignore &#60;code&#62;.envrc&#60;/code&#62;, and &#60;code&#62;.direnv&#60;/code&#62; no matter where
they are, this project I&#39;m working on is unaffected by all this.&#60;/p&#62;
</description>
                <pubDate>Sat, 19 Mar 2022 00:37:01 -0700</pubDate>
                <link>https://duan.ca/2022/03/19/nix-dirnev/</link>
                <guid isPermaLink="true">https://duan.ca/2022/03/19/nix-dirnev/</guid>
            </item>
            <item>
                <title>Flake, Home Manager, and Extra Packages</title>
                <description>&#60;p&#62;So, you use a standalone home-manager, it&#39;s set up with flake, tracking a particular nixpkgs channel. How do
you use a package from another channel? This seemingly simple task took me, a Nix noob, quite a bit of
research to solve. Here&#39;s how I did it.&#60;/p&#62;
&#60;p&#62;A simple flake.nix for home-manager might look like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  inputs = {
    nixpkgs.url = &#38;quot;github:nixos/nixpkgs/nixos-21.11&#38;quot;;
    home-manager.url = &#38;quot;github:nix-community/home-manager/release-21.11&#38;quot;;
    home-manager.inputs.nixpkgs.follows = &#38;quot;nixpkgs&#38;quot;;
  };
  outputs = { self, nixpkgs, home-manager }: {
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      username = &#38;quot;dan&#38;quot;;
      system = &#38;quot;x86_64-darwin&#38;quot;;
      homeDirectory = &#38;quot;/home/dan&#38;quot;;
      configuration = { config, pkgs ... }: {
          home.packages = [
            pkgs.hello
          ];
      };
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;A few things of note:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;home manager is set to follow &#60;code&#62;nixpkgs&#60;/code&#62;, which tracks &#60;code&#62;nixos-21.11&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;&#60;code&#62;pkgs.hello&#60;/code&#62; refers to the package in &#60;code&#62;nixos-21.11&#60;/code&#62; as well.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;To put things in concrete terms, our goal is to put a package from a channel other than &#60;code&#62;nixos-21.11&#60;/code&#62;
alongside &#60;code&#62;pkgs.hello&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;The key to my solution is the &#60;code&#62;extraModules&#60;/code&#62; in &#60;code&#62;home-manager.lib.homeManagerConfiguration&#60;/code&#62;&#39;s argument set.
We&#39;ll leverage it to modify the environment made available to its sibling, &#60;code&#62;configuration&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;First, add the new channel as input &#60;code&#62;nixpkgs-unstable&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  inputs = {
    # ...
    nixpkgs-unstable.url = &#38;quot;github:nixos/nixpkgs&#38;quot;;
  };
  ...
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Then, add a small module to &#60;code&#62;extraModules&#60;/code&#62;. In it we make &#60;code&#62;nixpkgs-unstable&#60;/code&#62; an argument to &#60;code&#62;_module&#60;/code&#62;.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  input = { ... };
  outputs = { self, nixpkgs, nixpkgs-unstable, home-manager }: { # Note we also pass in nixpkgs-unstable here
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      extraModules = [
        ({ pkgs, ... }: rec {
          _module.args.nixpkgs-unstable = import nixpkgs-unstable { inherit system; };
        })
      ];
      # ...
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... now that we added &#60;code&#62;args.nixpkgs-unstable&#60;/code&#62;, it becomes available in the configuration:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  input = { ... };
  outputs = { self, nixpkgs, nixpkgs-unstable, home-manager }: { # Note we also pass in nixpkgs-unstable here
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      # ...
      configuration = { config, pkgs, nixpkgs-unstable, ... }:
          home.packages = [
            pkgs.hello
            nixpkgs-unstable.python39Packages.python-lsp-server
          ];
      };
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;There, we made &#60;code&#62;python39Packages.python-lsp-server&#60;/code&#62; from nixpkgs&#39;s master branch appear alongside our
standard, default channel.&#60;/p&#62;
&#60;p&#62;And that&#39;s how you add packages from a different channel in a flake setup for standalone home-manager.&#60;/p&#62;
</description>
                <pubDate>Tue, 15 Mar 2022 18:53:59 -0700</pubDate>
                <link>https://duan.ca/2022/03/15/standalone-home-manager-flake-channels/</link>
                <guid isPermaLink="true">https://duan.ca/2022/03/15/standalone-home-manager-flake-channels/</guid>
            </item>
            <item>
                <title>An Invisible Chasm</title>
                <description>&#60;p&#62;In the journey of growing software systems, there comes a point where certain engineering decision will create
a chasm so large that it&#39;s practically impossible to go back. The initial crossing of this chasm is so easy
that it often happens without anyone noticing. Nonetheless, it is a costly mistake.&#60;/p&#62;
&#60;p&#62;On one side of this chasm, any member of the engineering team can answer the question &#38;quot;how, exactly, is my
code being consumed in our engineering org?&#38;quot;. Here lies clarity. Your team fearlessly delete dead code. Legacy
logic has their days marked. Lacking documentation? Not ideal, but you can always find how an API gets used
in all scenarios easily.&#60;/p&#62;
&#60;p&#62;On the other side, no one has the answer. The corpses pile up. Deprecating things comes with uncertainty. You
warn your team &#38;quot;please carefully consider adding things here, because we&#39;ll keep it around forever&#38;quot;. Need to
respond to an incident? Better hope your monitoring system is good. Trying to trace the code path won&#39;t get
you answers in time. We&#39;ll leave that for the post-mortem.&#60;/p&#62;
&#60;p&#62;Tooling, yes, exactly what decision leads to the chasm depends on the state of tooling for your technology
stack. The programming languages, build system, repository setup, coding style guides, IDEs, linters, search
engine ... all factor into the final answer. A statically typed language compiler won&#39;t help you look up
users in a different micro-service. State-of-art symbol lookup may exist for a dynamically typed system
because some companies have thrown enormous amount of money to solve it. Maybe your kick-ass style guides
enforced by linters across multiple languages makes it possible to locate anything by text. You see, it is
a quantitative matter: it is always &#60;em&#62;possible&#60;/em&#62; to revert to the good old days. But it will be &#60;em&#62;expensive&#60;/em&#62; in
terms of dollars, and/or will power.&#60;/p&#62;
&#60;p&#62;When did you cross the chasm?&#60;/p&#62;
&#60;p&#62;Beware of the chasm.&#60;/p&#62;
</description>
                <pubDate>Thu, 17 Feb 2022 13:40:27 -0800</pubDate>
                <link>https://duan.ca/2022/02/17/invisible-chasm/</link>
                <guid isPermaLink="true">https://duan.ca/2022/02/17/invisible-chasm/</guid>
            </item>
            <item>
                <title>Building IndexStoreDB on Linux: The Portable Technique</title>
                <description>&#60;h2&#62;The problem&#60;/h2&#62;
&#60;p&#62;As of writing of this article, when you attempt to use Apple&#39;s Swift library &#60;a href=&#34;https://github.com/apple/indexstore-db&#34;&#62;IndexStoreDB&#60;/a&#62; on Linux as
a normal SwiftPM dependency, it won&#39;t build successfully:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-fish&#34;&#62;❯ cat Package.resolved
{
  &#38;quot;object&#38;quot;: {
    &#38;quot;pins&#38;quot;: [
      {
        &#38;quot;package&#38;quot;: &#38;quot;IndexStoreDB&#38;quot;,
        &#38;quot;repositoryURL&#38;quot;: &#38;quot;https://github.com/apple/indexstore-db&#38;quot;,
        &#38;quot;state&#38;quot;: {
          &#38;quot;branch&#38;quot;: &#38;quot;swift-5.5.2-RELEASE&#38;quot;,
          &#38;quot;revision&#38;quot;: &#38;quot;e771994778265c2efe8d33a7ca30adf5f3d2065a&#38;quot;,
          &#38;quot;version&#38;quot;: null
        }
      }
    ]
  },
  &#38;quot;version&#38;quot;: 1
}

❯ swift build &#38;gt; /dev/null

❯ echo $status
1
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The issue is documented in the build instruction for Linux:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;The C++ code in the index requires &#60;code&#62;libdispatch&#60;/code&#62;, but unlike Swift code, it cannot find it automatically on Linux. You can work around this by adding a search path manually.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;pre&#62;&#60;code&#62;$ swift build -Xcxx -I&#38;lt;path_to_swift_toolchain&#38;gt;/usr/lib/swift -Xcxx -I&#38;lt;path_to_swift_toolchain&#38;gt;/usr/lib/swift/Block
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Okay, so, how would my package build in Linux environments where the Swift toolchain&#39;s setup is unknown? How
do we avoid building with one toolchain while mixing in &#60;code&#62;libdispatch&#60;/code&#62; from another toolchain somewhere? Here&#39;s
what I did for my command-line tool &#60;a href=&#34;https://github.com/dduan/Clue&#34;&#62;Clue&#60;/a&#62;.&#60;/p&#62;
&#60;h2&#62;The solution&#60;/h2&#62;
&#60;p&#62;The essence of the problem is about the installation location of the Swift toolchain. Our solution makes the
following assumptions:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;A Swift toolchain is installed on the file system on Linux (duh!).&#60;/li&#62;
&#60;li&#62;The toolchain is at least similar to the one distributed on Swift.org. So &#60;code&#62;libdispatch&#60;/code&#62; is distributed
alongside the other binaries, in a stable relative directory.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Having the &#60;code&#62;swift&#60;/code&#62; command available (assumption #1), we can just let it tell us about itself with the
&#60;code&#62;-print-target-info&#60;/code&#62; flag:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-fish&#34;&#62;❯ swift -print-target-info
{
  &#38;quot;compilerVersion&#38;quot;: &#38;quot;Swift version 5.5.2 (swift-5.5.2-RELEASE)&#38;quot;,
  &#38;quot;target&#38;quot;: {
    &#38;quot;triple&#38;quot;: &#38;quot;x86_64-unknown-linux-gnu&#38;quot;,
    &#38;quot;unversionedTriple&#38;quot;: &#38;quot;x86_64-unknown-linux-gnu&#38;quot;,
    &#38;quot;moduleTriple&#38;quot;: &#38;quot;x86_64-unknown-linux-gnu&#38;quot;,
    &#38;quot;compatibilityLibraries&#38;quot;: [ ],
    &#38;quot;librariesRequireRPath&#38;quot;: false
  },
  &#38;quot;paths&#38;quot;: {
    &#38;quot;runtimeLibraryPaths&#38;quot;: [
      &#38;quot;/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift/linux&#38;quot;
    ],
    &#38;quot;runtimeLibraryImportPaths&#38;quot;: [
      &#38;quot;/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift/linux&#38;quot;,
      &#38;quot;/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift/linux/x86_64&#38;quot;
    ],
    &#38;quot;runtimeResourcePath&#38;quot;: &#38;quot;/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift&#38;quot;
  }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Great! We see where the runtime is installed. Now we can invoke assumption #2, that &#60;code&#62;libdispatch&#60;/code&#62; is at
a relative location to the rest of the runtime. In the output from above, the value for &#60;code&#62;runtimeResourcePath&#60;/code&#62;
happens to be the parent directory for &#60;code&#62;libdispatch&#60;/code&#62;&#39;s headers. The &#60;code&#62;&#38;lt;path_to_swift_toolchain&#38;gt;&#60;/code&#62; value in
&#60;a href=&#34;https://github.com/apple/indexstore-db&#34;&#62;IndexStoreDB&#60;/a&#62;&#39;s official instruction in this particular setup would be
&#60;code&#62;/home/dan/.swiftenv/versions/5.5.2&#60;/code&#62;.  So the following command would have worked:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;swift build -Xcxx -I/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift -Xcxx -I/home/dan/.swiftenv/versions/5.5.2/usr/lib/swift/Block
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;All we need to do is parse this information at build time, and it should work on every Linux setup! Choose
whatever parsing method you like. Here&#39;s (more or less) the &#60;code&#62;Makefile&#60;/code&#62; for &#60;a href=&#34;https://github.com/dduan/Clue&#34;&#62;Clue&#60;/a&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-make&#34;&#62;SHELL = /bin/bash
ifeq ($(shell uname),Darwin)
EXTRA_SWIFT_FLAGS = &#38;quot;--disable-sandbox&#38;quot;
else
SWIFT_TOOLCHAIN = &#38;quot;$(shell swift -print-target-info | grep runtimeResourcePath | cut -f 2 -d &#39;:&#39; | cut -f 2 -d &#39;&#38;quot;&#39;)&#38;quot;
EXTRA_SWIFT_FLAGS = -Xcxx -I${SWIFT_TOOLCHAIN} -Xcxx -I${SWIFT_TOOLCHAIN}/Block
endif

define build
	@swift build --configuration $(1) -Xswiftc -warnings-as-errors ${EXTRA_SWIFT_FLAGS}
endef

.PHONY: build
build:
	$(call build,release)

.PHONY: test
test:
	@swift test ${EXTRA_SWIFT_FLAGS}

.PHONY: debug
debug:
	$(call build,debug)
&#60;/code&#62;&#60;/pre&#62;
&#60;ol&#62;
&#60;li&#62;&#60;code&#62;make build&#60;/code&#62; / &#60;code&#62;make test&#60;/code&#62; / &#60;code&#62;make debug&#60;/code&#62; all work as expected, building IndexStoreDB successfully.&#60;/li&#62;
&#60;li&#62;As-is, this snippet is project-agnostic. So you can throw it in your SwiftPM project and it should &#38;quot;just
work&#38;quot;.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Alright!&#60;/p&#62;
</description>
                <pubDate>Wed, 09 Feb 2022 15:58:41 -0800</pubDate>
                <link>https://duan.ca/2022/02/09/building-indexstoredb-on-linux/</link>
                <guid isPermaLink="true">https://duan.ca/2022/02/09/building-indexstoredb-on-linux/</guid>
            </item>
            <item>
                <title>Making of a TOML parser</title>
                <description>&#60;p&#62;During the holidays, I spent some time on the parser that underlies &#60;a href=&#34;https://github.com/dduan/TOMLDecoder&#34;&#62;TOMLDecoder&#60;/a&#62;. The original
implementation targeted TOML&#39;s spec version 0.5. A few release-candidates for version 1.0 has come
out since then. So it&#39;s a good time to give this project attention.&#60;/p&#62;
&#60;p&#62;Back in the 0.5 days, the TOML spec was (well) written in English with a few examples for each
element in the language. The spec document both:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;how a TOML document should be spelled out (table header should have a &#60;code&#62;[&#60;/code&#62;, followed by 0 or more
whitespace, then, a key, 0 or more whitespace, then &#60;code&#62;]&#60;/code&#62;).&#60;/li&#62;
&#60;li&#62;rules for detecting conflicts in a syntactically correct document (if &#60;code&#62;a.b&#60;/code&#62; is a table, then it&#39;s
invalid to set its value to be a date in the same document).&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;My memory of hand-rolling a recursive-descent scanner that conforms to both of the above
requirements was unpleasant. My lesser understanding of the markup language, the vagueness for the
validation rules in the spec, as well as (I think?) poorer skill for writing parsers all contributed
to the unpleasantness. TOML has gained an ABNF for its syntax since then, making it less necessary
to reply on the English descriptions. It&#39;s the holidays, maintaining existing code is hard.&#60;/p&#62;
&#60;p&#62;So, I decided to have some fun, and re-write the parser from scratch. The rest of this post contains
notable things from the rewrite.&#60;/p&#62;
&#60;p&#62;I translated the ABNF with parser combinators. The recent &#60;a href=&#34;https://pointfree.co&#34;&#62;Pointfree&#60;/a&#62; video series made me curious
about the performance of this parsing style in Swift. At the end of the rewrite, I added benchmarks
to find out. Here&#39;s benchmark for parsing an example TOML document&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;name                    time          std        iterations
-----------------------------------------------------------
example-toml.decoder    454840.000 ns ±   3.63 %       3045
example-toml.combinator 422721.500 ns ±   4.28 %       3266
example-toml.scanner     82232.000 ns ±   9.39 %      16793
example-toml.c            5901.000 ns ±  24.72 %     216140
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;example-toml.decoder&#60;/code&#62; is time spent on parsing + decoding. &#60;code&#62;example-toml.scanner&#60;/code&#62; is the time spent
by the old parser. &#60;code&#62;example-toml.c&#60;/code&#62; is the performance of a C library.&#60;/p&#62;
&#60;p&#62;So, the new parser is much much slower! However, I know from debugging through 200+ unit tests that,
the new parser fixed a few serious bugs compared to the old. It also conforms to diffs between
version 0.5 and 1.0 of the TOML spec. Speed alone is not good enough of a reason to throw this work
away! There&#39;s another reason the new parser is superior, but I&#39;ll talk about it later.&#60;/p&#62;
&#60;p&#62;To be fair to parser combinators, I made several decisions that preferred development speed over
runtime speed during development. These were conscious decisions. There were no benchmarks at
time so I didn&#39;t want to worry about it pre-maturely. Point is, there are rooms for significant
runtime speed improvements. Perhaps I&#39;ll write a follow-up post detailing my journey to make the
parser go fast later; the C library is part of the benchmark for a reason!&#60;/p&#62;
&#60;p&#62;I was also inspired by Joe Groff&#39;s blog post &#60;a href=&#34;http://duriansoftware.com/joe/Constructing-human-grade-parsers.html&#34;&#62;Constructing human-grade parsers&#60;/a&#62;. Instead of
stopping at the first syntax error, a parser (any parser!) should treat the error as part of its
successful output, deal with the erroneous part of the input, and recover from it. This approach
means the portion of the input after the first error gets parsed, and any error it may contain can
be found and reported, too! Joe&#39;s post explains this well.&#60;/p&#62;
&#60;p&#62;To talk about this further, let&#39;s dive into some details.&#60;/p&#62;
&#60;p&#62;As mentioned earlier, to validate a TOML document, there are rules for both syntax and semantics to
consider. TOML has a few top-level constructs: table header, array-table header, and key-value
pairs. Each of these alone can be validated purely based on syntax. On a high level, a TOML parser
can do the following:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;parse a list of top-level constructs&#60;/li&#62;
&#60;li&#62;iterate over this list, gradually assembly the complete TOML object&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Errors could exist from each of these two steps To make the parser &#60;em&#62;human-grade&#60;/em&#62;, the errors must
not propagate by disrupting the parsing logic. In Swift, this means the code don&#39;t throw the
(conceptual) errors, instead, the top-level constructs include error as a possible value:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum TopLevel: Equatable {
    case table(Key)
    case arrayTable(Key)
    case keyValue(KeyValuePair)
    case error(Reason)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Upon evaluating a &#60;code&#62;TopLevel&#60;/code&#62; value, the parser must not stop if it generates a conflict according to
TOML&#39;s requirement. We take note of this error, and move on to consume the next &#60;code&#62;TopLevel&#60;/code&#62;. Errors
from this step will join the error from &#60;code&#62;TopLevel.error&#60;/code&#62; at the end for users to see. Therefore, the
second step&#39;s code roughly does this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;var errors = [Error]()

for value in topLevelValues {
    switch value {
    case .error(let reason):
        errors.append(reason)
    default:
        do {
            evaluate(value)
        } catch {
            errors.append(error)
        }
    }
}

if !errors.isEmpty {
    throw UserFacingError(details: errors)
}

// no error! parsing succeeded
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This code &#38;quot;synchronizes&#38;quot; the errors from both the syntactical, and semantical level. With some
additional effort to make the errors &#60;code&#62;CustomStringConvertible&#60;/code&#62;, a erroneous TOML document such as&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-TOML&#34;&#62;a = &#38;quot;Hello
b = 43
[b]
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;makes the parser generate the following error message:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Deserialization failure:
    * Value |1, 5| Missing closing character `&#38;quot;` in string
    * Conflict |3, 2| Conflicting value at [b] Existing value is 43
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The explanation I presented above is simplified by a lot. In reality, the &#38;quot;human-grade&#38;quot; upgrade can
go a lot further. For example, if the definition of &#60;code&#62;a&#60;/code&#62; has a syntax error, instead of rejecting it,
as long as we can figure out what the intent is, we can pretend it&#39;s a good value. That way, any
semantic issues related to &#60;code&#62;a&#60;/code&#62; can be discovered. Improvements like this can be added to the parser
in many places still.&#60;/p&#62;
&#60;p&#62;Anyways, here&#39;s where I abruptly stop the story of my new TOML parser. There are a lot of exciting
space for improvment. So this article might be a &#38;quot;part 1&#38;quot;. No promises, though.&#60;/p&#62;
</description>
                <pubDate>Sun, 03 Jan 2021 14:56:10 -0800</pubDate>
                <link>https://duan.ca/2021/01/03/human-grade-toml-parser-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2021/01/03/human-grade-toml-parser-in-swift/</guid>
            </item>
            <item>
                <title>Installing Nix on macOS 11 Big Sur</title>
                <description>&#60;p&#62;&#60;em&#62;Note: as of Feburary, 2022, the steps written below has been incorporated by the official Nix install script for macOS. This article is, therefore, obsolete.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Here are the steps for installing nix on macOS 11 Big Sur.&#60;/p&#62;
&#60;h3&#62;Preparation&#60;/h3&#62;
&#60;p&#62;Decide on which disk the nix store is to be installed. By end of this process, you&#39;ll have a disk
name like &#60;code&#62;disk4&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;Personally, I like looking it up in the Disk Utility app:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/12/disk-utility.png&#34; alt=&#34;Disk Utility&#34; /&#62;&#60;/p&#62;
&#60;p&#62;You can also use other methods, such us the &#60;code&#62;diskutil list&#60;/code&#62; command.&#60;/p&#62;
&#60;p&#62;Have this disk name ready.&#60;/p&#62;
&#60;h3&#62;Installation&#60;/h3&#62;
&#60;h4&#62;1. Create the path &#60;code&#62;/nix&#60;/code&#62; the macOS way.&#60;/h4&#62;
&#60;p&#62;Edit or create the file &#60;code&#62;/etc/synthetic.conf&#60;/code&#62;, adding this line:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;nix
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Reboot the Mac.&#60;/p&#62;
&#60;h4&#62;2. Create a APFS volume for the nix store.&#60;/h4&#62;
&#60;pre&#62;&#60;code&#62;sudo diskutil apfs addVolume diskX APFS &#39;Nix Store&#39; -mountpoint /nix
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Make sure to replace &#60;code&#62;diskX&#60;/code&#62; with the disk you identified in the preparation step.&#60;/p&#62;
&#60;h4&#62;3. Mount the volume.&#60;/h4&#62;
&#60;p&#62;Edit or create the file &#60;code&#62;/etc/fstab&#60;/code&#62;, adding this line:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;LABEL=Nix\040Store /nix apfs rw,nobrowse
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Reboot the Mac.&#60;/p&#62;
&#60;h4&#62;4. Install Nix the &#38;quot;normal&#38;quot; way&#60;/h4&#62;
&#60;pre&#62;&#60;code&#62;sh &#38;lt;(curl -L https://nixos.org/nix/install)
&#60;/code&#62;&#60;/pre&#62;
&#60;h4&#62;5. You are done! Try it out. I ran this little &#60;a href=&#34;https://web.archive.org/web/20201130222947/https://nix.dev/tutorials/dev-environment.html&#34;&#62;example&#60;/a&#62; as a test and things appears to work as expected.&#60;/h4&#62;
&#60;h3&#62;Bonus: using Nix in Fish shell&#60;/h3&#62;
&#60;p&#62;As a fish user, I&#39;m used to fixing things up myself since software from non-fish users usually
pretends fish doesn&#39;t exist. Anyways, in the final steps of its installation, Nix sets up a few
environment variables in a bash script. I&#39;ve adapted these specifically for fish on macOS. Add these
to your config.fish:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;set -x NIX_PROFILES &#38;quot;/nix/var/nix/profiles/default $HOME/.nix-profile&#38;quot;
set -x NIX_SSL_CERT_FILE &#38;quot;$HOME/.nix-profile/etc/ssl/certs/ca-bundle.crt&#38;quot;
set -x NIX_PATH /nix $HOME/.nix-defexpr/channels
set -x PATH $HOME/.nix-profile/bin $PATH
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It shouldn&#39;t be to hard to do this on other OSes. The relevant information is in
&#60;code&#62;~/.nix-profile/etc/profile.d/nix.sh&#60;/code&#62;.&#60;/p&#62;
</description>
                <pubDate>Sun, 13 Dec 2020 12:00:52 -0800</pubDate>
                <link>https://duan.ca/2020/12/13/nix-on-macos-11-big-sur/</link>
                <guid isPermaLink="true">https://duan.ca/2020/12/13/nix-on-macos-11-big-sur/</guid>
            </item>
            <item>
                <title>Markra 1.0</title>
                <description>&#60;p&#62;I&#39;ve never been patient enough to learn the JIRA plain-text syntax, depite being
a frequent user throughout the years. So a while ago I wrote this little utility
that lets me compose JIRA ticket in Markdown. Some thoughts were put into
whether this should be an OSS and free (as in beer) app, or something
I distribute via the Mac App Store. Ultimately, the first option prevailed. So,
without further adiue, here&#39;s the repo for &#60;a href=&#34;https://github.com/dduan/Markra&#34;&#62;Markra&#60;/a&#62; with &#60;a href=&#34;https://github.com/dduan/Markra/releases/tag/1.0&#34;&#62;version 1.0 macOS
app download in the release page&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/11/markra-screenshot.png&#34; alt=&#34;A Marka macOS app screenshot&#34; /&#62;&#60;/p&#62;
&#60;p&#62;As far as I&#39;m concerned, the app is pretty much done. And its feature set is
small and self-explanatory. So I don&#39;t expect more releases other than minor
bug fix in the future.&#60;/p&#62;
&#60;p&#62;I hope some find it as useful as I do.&#60;/p&#62;
</description>
                <pubDate>Sun, 22 Nov 2020 12:53:52 -0800</pubDate>
                <link>https://duan.ca/2020/11/22/marka/</link>
                <guid isPermaLink="true">https://duan.ca/2020/11/22/marka/</guid>
            </item>
            <item>
                <title>Fantastic Beasts in C and Where To Find Them in Swift</title>
                <description>&#60;p&#62;Swift has a pretty decent C-interoperability story. But C has many features! Today, I&#39;ll tell you
a story involving a few not-so-well supported C features and Swift.&#60;/p&#62;
&#60;p&#62;It all started when I decided to re-write &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62; with Windows support. One of the library&#39;s
offering is reading the literal target of a symbolic link: if &#60;code&#62;b&#60;/code&#62; is a link to &#60;code&#62;a&#60;/code&#62;, then
&#60;code&#62;Path(&#38;quot;b&#38;quot;).readSymlink()&#60;/code&#62; should return a another path that&#39;s equivalent to &#60;code&#62;Path(&#38;quot;a&#38;quot;)&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;The Windows API that returns this information is &#60;a href=&#34;https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol&#34;&#62;DeviceIoControl&#60;/a&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;BOOL DeviceIoControl(
  HANDLE       hDevice,
  DWORD        dwIoControlCode,
  LPVOID       lpInBuffer,
  DWORD        nInBufferSize,
  LPVOID       lpOutBuffer,
  DWORD        nOutBufferSize,
  LPDWORD      lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Notice anything weird? Hint: &#60;code&#62;LPVOID&#60;/code&#62; is &#60;code&#62;void *&#60;/code&#62; in standard C.&#60;/p&#62;
&#60;p&#62;This function is, for the lack of better words, polymorphic: depending on your input, it can intake
and output different types. As a caller, it is your responsibility to look up what type is needed
and cast them to and from those &#60;code&#62;void *&#60;/code&#62;s. The size of the data structure is returned as well. We&#39;ll
have a lot to talk about that later.&#60;/p&#62;
&#60;p&#62;Perhaps, surprisingly, this is not too hard to deal with in Swift. In my &#60;a href=&#34;/2020/09/09/free-c-strings&#34;&#62;last article&#60;/a&#62;,
I detailed how we can use an Swift API to work with C buffers:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;/// get the file `handle`...
/// now call `DeviceIoControl`
var data = ContiguousArray&#38;lt;CChar&#38;gt;(
    unsafeUninitializedCapacity: kMax
) { buffer, count in
    var size: DWORD = 0
    DeviceIoControl(
        handle,
        FSCTL_GET_REPARSE_POINT,
        nil,
        0,
        buffer.baseAddress,
        DWORD(buffer.count),
        &#38;amp;size,
        nil
    )
    count = Int(size)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;So this fills the array of &#60;code&#62;CChar&#60;/code&#62;s with the necessary bytes for out result. I named the variable
&#60;code&#62;data&#60;/code&#62; because it is exactly the same concept as &#60;code&#62;Foundation&#60;/code&#62;&#39;s Data, as most Swift programmers
know.&#60;/p&#62;
&#60;p&#62;As promised, we&#39;ll cast this data to the actual type so that we can retrieve information from its
bytes. Side note: casting in this context is a documented usage, So it really is more awkward rather
than bad. And there&#39;s a safe way to do it:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;withUnsafePointer(to: data) {
    $0.withMemoryRebound(
        to: [ReparseDataBuffer].self,
        capacity: 1
    ) { buffer in
        // first element in `buffer` is 
        /// a `ReparseDataBuffer`! Yay
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;em&#62;It&#39;s very important to note that &#60;code&#62;ReparseDataBuffer&#60;/code&#62; is a struct with fixed, predictable layout,
that the API &#60;code&#62;DeviceIoControl&#60;/code&#62; promises to return. In practice, this means it is defined in C. Swift
does not currently guarantee struct layout. So unless you really know what you are doing and don&#39;t
care about forward compatibility, you should not do this with Swift structs.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;So far this story has been boring for avid Swift programmers. Fear not, things will get spicy now.&#60;/p&#62;
&#60;p&#62;Let&#39;s talk about this &#60;code&#62;ReparseDataBuffer&#60;/code&#62;. It&#39;s an imported C type with a few notable features.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;typedef struct {
  unsigned long  ReparseTag;
  unsigned short ReparseDataLength;
  unsigned short Reserved;
  union {
    struct {
      unsigned short SubstituteNameOffset;
      unsigned short SubstituteNameLength;
      unsigned short PrintNameOffset;
      unsigned short PrintNameLength;
      unsigned long  Flags;
      wchar_t  PathBuffer[1];
    } SymbolicLinkReparseBuffer;
    struct {
      unsigned short SubstituteNameOffset;
      unsigned short SubstituteNameLength;
      unsigned short PrintNameOffset;
      unsigned short PrintNameLength;
      wchar_t  PathBuffer[1];
    } MountPointReparseBuffer;
    struct {
      unsigned char DataBuffer[1];
    } GenericReparseBuffer;
  };
} ReparseDataBuffer;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Feature #1: it has a &#60;em&#62;union member&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;A &#60;code&#62;union&#60;/code&#62; in C is an area in memory that could be any of the types specified in the union:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;// X.a is a `char` and X.b is a `uint64_t`. 
// And they occupy the same memory because
// only 1 of them exists at a time.
typedef union {
    char a;
    uint64_t b;
} X;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Swift does not own a direct analog for this. So if we import this &#60;code&#62;ReparseDataBuffer&#60;/code&#62; definition,
there wouldn&#39;t be a good way to access the data inside the union.&#60;/p&#62;
&#60;p&#62;As I pointed out in the comment, members of a union occupy the same space in memory. The largest
member defines the size of that space, so everyone can fit inside of it. Each union member
interprets the same bytes according to their own definition. Given this knowledge, we can derive
a solution that works around Swift&#39;s limitations: break up the union (sorry, this whole paragraph
reads super suggestive of the real world union. It&#39;s probably why this word is picked for this data
structure in the first place. But I do not intend to say anything about the real world here)!&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;typedef struct {
  unsigned long reparseTag;
  unsigned short reparseDataLength;
  unsigned short reserved;
  unsigned short substituteNameOffset;
  unsigned short substituteNameLength;
  unsigned short printNameOffset;
  unsigned short printNameLength;
  unsigned long flags;
  wchar_t pathBuffer[1];
} SymbolicLinkReparseBuffer;

typedef struct {
  unsigned long reparseTag;
  unsigned short reparseDataLength;
  unsigned short reserved;
  unsigned short substituteNameOffset;
  unsigned short substituteNameLength;
  unsigned short printNameOffset;
  unsigned short printNameLength;
  wchar_t pathBuffer[1];
} MountPointReparseBuffer;

// we don&#39;t care about the 3rd union
// member in this use case
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Conveniently for us, the union member in &#60;code&#62;ReparseDataBuffer&#60;/code&#62; is at the end. So we don&#39;t need to
worry about padding the unused space for smaller alternatives. Back in Swift, instead of dealing
with &#60;code&#62;ReparseDataBuffer&#60;/code&#62; directly, we can work with &#60;code&#62;SymbolicLinkReparseBuffer&#60;/code&#62; or
&#60;code&#62;MountPointReparseBuffer&#60;/code&#62;, depending on our expectation of which union member to read.&#60;/p&#62;
&#60;p&#62;Yeah, this is a good time to mention that, &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62; has to include copies of these definition in a
separate C module. Not only because we need to &#38;quot;break up the union&#38;quot;, the original definition is also
only accessible after importing some headers in the NT kernel. So the standard &#60;code&#62;import WinSDK&#60;/code&#62; won&#39;t
suffice.&#60;/p&#62;
&#60;p&#62;Moving on to notable feature #2. The last member of both &#60;code&#62;SymbolicLinkReparseBuffer&#60;/code&#62; and
&#60;code&#62;MountPointReparseBuffer&#60;/code&#62; &#60;code&#62;pathBuffer&#60;/code&#62; is a 1-character long array...why?&#60;/p&#62;
&#60;p&#62;In C, this is a &#60;em&#62;flexible array member&#60;/em&#62;. Such member must always appear at the end of a struct.
The word &#38;quot;flexible&#38;quot; in this context refers to the amount of memory allocated for this type of
structs : it can vary according to the length of the array as needed. The member such as
&#60;code&#62;pathBuffer&#60;/code&#62; is here to provide access to the beginning of the buffer.&#60;/p&#62;
&#60;p&#62;To Swift, &#60;code&#62;pathBuffer&#60;/code&#62; looks like a single &#60;code&#62;UInt16&#60;/code&#62;. The language obviously don&#39;t have a good idea
of this C feature. So how to we get the rest of the data from this array?&#60;/p&#62;
&#60;p&#62;Once again, we have to lean on our understanding of memory layout in C structs.&#60;/p&#62;
&#60;p&#62;As is common in APIs for flexible array members, the length of the array trailing the struct is
provide to us. Let&#39;s call it &#60;code&#62;flexibleLength&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/09/flexible_array_member.png&#34; alt=&#34;Illustration of memory layout for a C struct with flexible array member&#34; /&#62;&#60;/p&#62;
&#60;p&#62;We already have the memory for these structs in bytes (remember &#60;code&#62;data&#60;/code&#62;?). And we can get the size
for the fixed potion of the structs with&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let fixedStructSize = MemoryLayout&#38;lt;
    SymbolicLinkReparseBuffer
&#38;gt;.stride
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Putting it all together, we can get the full content of the array by&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;chopping off the content for struct itself,&#60;/li&#62;
&#60;li&#62;casting the rest of the raw buffer to the expected element type, and&#60;/li&#62;
&#60;li&#62;include the last member in this struct as the first element in the array&#60;/li&#62;
&#60;/ol&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Include the first element, which is at
// the end of the fixed struct potion.
let arrayStart = fixedStructSize - 1
// Cast the data buffer so it&#39;s composed 
// of `wchar_t` aka `UInt16`s.
let array = withUnsafePointer(to: data) {
    $0.withMemoryRebound(
        to: [UInt16].self,
        capacity: data.count / 2
    ) { sixteenBitData in
        // chop off the non-array potion
        sixteenBitData.pointee[
            arrayStart ..&#38;lt; (arrayStart + flexibleLength)
        ]
    }
}

// now, go nuts on the array! You earned it!
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Considerations such as error handling are intentionally left out in this article. You can checkout
the source code of &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62; (on the &#60;code&#62;next&#60;/code&#62; branch) for the full glory.&#60;/p&#62;
&#60;p&#62;Anyways, the flexible array member turns out to be the literal target of the symbolic link. So here
is the end of our story. I&#39;m interested to hear about alternative approaches for dealing with union
members and flexible array members in Swift. Let me know on &#60;a href=&#34;https://twitter.com/daniel_duan&#34;&#62;Twitter&#60;/a&#62;, or &#60;a href=&#34;&#34;&#62;Twitch&#60;/a&#62; when I&#39;m
streaming!&#60;/p&#62;
</description>
                <pubDate>Sat, 12 Sep 2020 23:11:48 -0700</pubDate>
                <link>https://duan.ca/2020/09/12/fantastic-c-beasts-and-where-to-find-them-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2020/09/12/fantastic-c-beasts-and-where-to-find-them-in-swift/</guid>
            </item>
            <item>
                <title>Faster C Strings in Swift</title>
                <description>&#60;p&#62;One of the goals in the re-write of my VFS library &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62; is to make it go
fast. What does that mean when most of the time users are hitting the hard
drive when running your code? Well, let&#39;s not dwell on that for now.&#60;/p&#62;
&#60;p&#62;A library like this passes &#60;em&#62;file paths&#60;/em&#62; back and forth with C APIs from the OS
a lot. So one way to go fast is to keep the original representation of the paths
as they are provided to us. On macOS and Linux (and other OSes that Swift
doesn&#39;t officially support yet), paths are bought and sold in the so called
&#38;quot;C strings&#38;quot;: &#60;code&#62;NUL&#60;/code&#62;-terminated bytes (8-bit integers) with POSIX APIs and 16-bit
values on Windows with &#60;code&#62;UNICODE&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;Let&#39;s walk over a couple of examples. Here&#39;s how to get the current working
directory:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;// POSIX
char *getcwd(char *buf, size_t size);

// Windows
// LPTSTR (with right environment) is `wchar_t *`
DWORD GetCurrentDirectory(
    DWORD nBufferLength,
    LPTSTR lpBuffer
);
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The expected steps for using APIs like this are the following:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;you allocate a buffer large enough to store any result you expect.&#60;/li&#62;
&#60;li&#62;you give the buffer to the C function.&#60;/li&#62;
&#60;li&#62;the C function fills the buffer with some characters, and a &#60;code&#62;NUL&#60;/code&#62; (or &#60;code&#62;0&#60;/code&#62;)
right after the last character in the result.&#60;/li&#62;
&#60;li&#62;the function use a separate variable to tell you the size of the actual
result, not counting the &#60;code&#62;NUL&#60;/code&#62;.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;It&#39;s very generous of these functions to give us the size of the result. Because
the point of using &#60;code&#62;NUL&#60;/code&#62; to terminate &#38;quot;strings&#38;quot; is to avoid having to use
a separate size. Let&#39;s use &#60;em&#62;setting the current working directory&#60;/em&#62; as the next
example:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;// POSIX
int chdir(const char *path);

// Windows
BOOL SetCurrentDirectory(LPCTSTR lpPathName);
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Yup, these APIs don&#39;t need you to tell them the content size of your buffer. But
if your content doesn&#39;t end with a &#60;code&#62;NUL&#60;/code&#62;, they&#39;ll happily read beyond your
intended stopping point until it finds a random &#60;code&#62;0&#60;/code&#62; in memory.&#60;/p&#62;
&#60;p&#62;Anyways, this is pretty classic C stuff. Now let&#39;s talk about Swift!&#60;/p&#62;
&#60;p&#62;The default option to store a file path for most should be a &#60;code&#62;Swift.String&#60;/code&#62;,
which is a encoding-agnostic, Unicode glyph based list of characters. But as
I mentioned earlier, I want to avoid the cost of decoding and encoding in the
case where the path is only passing through the Swift code from C to C, without
being analyzed or modified. (If you need a refresher, &#60;a href=&#34;https://youtu.be/Vy2r21kli0Q&#34;&#62;I recently made a video
on Unicode and encoding&#60;/a&#62;.) So I chose to use an
&#60;a href=&#34;https://developer.apple.com/documentation/swift/contiguousarray&#34;&#62;ContiguousArray&#60;/a&#62; to store these C values:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Simplified for POSIX
struct Path {
    let storage: ContiguousArray&#38;lt;CChar&#38;gt;
    // ...
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;ContiguousArray&#60;/code&#62; (and &#60;code&#62;Array&#60;/code&#62;) provides an excellent way to interact with C
APIs we encountered earlier:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;init(
    unsafeUninitializedCapacity: Int,
    initializingWith initializer: (
        inout UnsafeMutableBufferPointer&#38;lt;Element&#38;gt;,
        inout Int
    ) throws -&#38;gt; Void
) rethrows
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Don&#39;t let the complex-looking signature intimidate you. Essentially, it gives
you write access to the array&#39;s memory right after its allocation, but before
Swift does standard initialization to it. It works really well with the C APIs
we looked at earlier:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Store the current directory in a ContiguousArray
// Using the Windows API
let storage = ContiguousArray(
    unsafeUninitializedCapacity: Int(MAX_PATH)
) { buffer, count
    let length = GetCurrentWorkingDirectoryW(
        DWORD(MAX_PATH),
        buffer.baseAddress // C API writes in the allocated memory
    )

    count = length // you are responsible for setting size of the array
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Read the steps 1-4 again from earlier, it&#39;s easy to see how this initializer is
designed to fit that pattern. The resulting array will have all the characters
as its content, and carries the correct size.&#60;/p&#62;
&#60;p&#62;When it&#39;s time to pass the array back to C, we can provide a pointer easily:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;storage.withUnsafeBufferPointer {
    SetCurrentDirectory($0.baseAddress!)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is not great, because we don&#39;t have a &#60;code&#62;NUL&#60;/code&#62; at the end of our array.  The
C function that read our array will sometimes read over the contents memory
until it finds a 0! Yikes.&#60;/p&#62;
&#60;p&#62;So here&#39;s an easy fix:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;(storage + [0]).withUnsafeBufferPointer {
    SetCurrentDirectory($0.baseAddress!)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Instead of using the memory of &#60;code&#62;storage&#60;/code&#62;, we construct a new array with an 0 as
its last value. This lets C APIs pick the right place to stop reading.
(Incidentally, Swift includes a built-in version of this &#60;a href=&#34;https://developer.apple.com/documentation/swift/string/2430818-utf8cstring&#34;&#62;for converting String
to UTF-8 (8-bit) C strings&#60;/a&#62;,
which includes the &#60;code&#62;NUL&#60;/code&#62; and it&#39;s possible to further encode with different
encodings.)&#60;/p&#62;
&#60;p&#62;Although we&#39;ve fixed the correctness bug, doing this defeats the purpose of
storing the C string directly somewhat: constructing a new array each time we
want to call a C API is kind of expensive. It involves allocating new memories
and copying over the content, etc.&#60;/p&#62;
&#60;p&#62;Alright. How about we carry around the &#60;code&#62;NUL&#60;/code&#62; in our array? Let&#39;s update the
construction code:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let storage = ContiguousArray(
    unsafeUninitializedCapacity: Int(MAX_PATH) + 1
) { buffer, count
    let length = GetCurrentWorkingDirectoryW(
        DWORD(MAX_PATH),
        buffer.baseAddress
    )

    buffer[length] = 0
    count = length + 1
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;We add 1 every time we have a say in size. Then we manually set a 0 at the end
of the stuff from C. Having done this, we&#39;ve solved both the correctness problem
and performance concern from earlier!&#60;/p&#62;
&#60;p&#62;The last bit of of this journey is ergonomics. Carrying an extra &#60;code&#62;NUL&#60;/code&#62; is fine
if you never look at the array&#39;s content. But when you do, it&#39;s important to
remember that the content we care about is &#60;em&#62;almost&#60;/em&#62; all of the array, except for
the &#60;code&#62;NUL&#60;/code&#62; at the end. In other words, simply don&#39;t make off-by-1 mistakes and
everything will be fine.&#60;/p&#62;
&#60;p&#62;Alright, that&#39;s easier said than done. To alleviate this off-by-1 painfulness,
I ended up exposing a &#38;quot;view&#38;quot; into the array storage that excludes the last
element. Here&#39;s the actual definition in &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;struct CString&#38;lt;Unit: BinaryInteger&#38;gt;: Equatable, Hashable {
    private var storage: ContiguousArray&#38;lt;Unit&#38;gt;
    var content: ContiguousArray&#38;lt;Unit&#38;gt;.SubSequence {
        storage[0 ..&#38;lt; storage.count - 1]
    }

    public func c&#38;lt;T&#38;gt;(
        action: (UnsafePointer&#38;lt;Unit&#38;gt;) throws -&#38;gt; T) throws -&#38;gt; T
    {
        try content.withUnsafeBufferPointer {
            try action($0.baseAddress!)
        }
    }

    init(cString: UnsafePointer&#38;lt;Unit&#38;gt;) {
       var length = 0
       while cString.advanced(by: length).pointee != 0 {
           length += 1
       }

       storage = ContiguousArray(
           unsafeUninitializedCapacity: length + 1
       ) { buffer, count in
           for offset in 0 ..&#38;lt; length {
               buffer[offset] = cString.advanced(by: offset).pointee
           }

           buffer[length] = 0
           count = length + 1
       }
    }

    // ... more stuff
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;storage&#60;/code&#62; in this solution is an private implementation detail. &#60;code&#62;content&#60;/code&#62; is
the primary access to the content of the string. And finally, this type
interops with C APIs correctly and efficiently because of the extra &#60;code&#62;NUL&#60;/code&#62; we put
at the end of &#60;code&#62;storage&#60;/code&#62;.&#60;/p&#62;
</description>
                <pubDate>Wed, 09 Sep 2020 01:21:26 -0700</pubDate>
                <link>https://duan.ca/2020/09/09/free-c-strings/</link>
                <guid isPermaLink="true">https://duan.ca/2020/09/09/free-c-strings/</guid>
            </item>
            <item>
                <title>Fall Guys are Among Us</title>
                <description>&#60;p&#62;I noticed a lot of people are playing these two games on Twitch recently: Fall Guys and Among Us.
Personally, I think Fall Guys is a pretty fun game to play and Among Us is an entertaining game to
watch. I&#39;m glad these games are out and popular in this strange year, even though I&#39;m not
playing either frequently (perhaps that&#39;s a mistake).&#60;/p&#62;
&#60;p&#62;Anyways, I want to write about this observation that seems unique from me: that the in-game
characters in these two games are both blob-y, short and colorful. This similarity stuck in my head
for a while, and I&#39;m getting increasingly anxious because those who frequently play these games
aren&#39;t making similar remarks &#60;em&#62;at all&#60;/em&#62;. So, in this Sunday evening, I just had to get it out of my
head:&#60;/p&#62;
&#60;video id=&#34;video-tag&#34; width=&#34;100%&#34; autoplay muted loop playsinline&#62; 
    &#60;source src=&#34;/assets/2020/08/FallGuysAmongUs.mov&#34; type=&#34;video/quicktime&#34; /&#62;  
&#60;/video&#62;
&#60;img id=&#34;img-tag&#34; width=&#34;100%&#34; src=&#34;/assets/2020/08/FallGuysAmongUs.mov&#34;&#62;
&#60;script type=&#34;text/javascript&#34;&#62;
    function BrowserDetection() {
        //Check if browser is Safari, if it is, hide the &#60;video&#62; tag, otherwise hide the &#60;img&#62; tag
        if (navigator.userAgent.search(&#34;Safari&#34;) &#62;= 0 &#38;&#38; navigator.userAgent.search(&#34;Chrome&#34;) &#60; 0) {
            document.getElementById(&#39;video-tag&#39;).style.display= &#34;none&#34;;
        } else {
            document.getElementById(&#39;img-tag&#39;).style.display= &#34;none&#34;;
        }
    }

    //And run the script. Note that the script tag needs to be run after HTML so where you place it is important. 
    BrowserDetection();
&#60;/script&#62;
&#60;p&#62;This animation is made from Pixelmator and Keynote. Those two along with Sketch and Final Cut Pro
make me feel invincible these days.&#60;/p&#62;
</description>
                <pubDate>Sun, 16 Aug 2020 23:42:44 -0700</pubDate>
                <link>https://duan.ca/2020/08/16/fall-guys-and-among-us/</link>
                <guid isPermaLink="true">https://duan.ca/2020/08/16/fall-guys-and-among-us/</guid>
            </item>
            <item>
                <title>Taking Screenshots On Linux</title>
                <description>&#60;p&#62;Having used macOS for a number of years, I&#39;ve formed some habit that I&#39;m never
going to shake. Among them is taking screenshots with &#60;code&#62;Alt-Shift-3&#60;/code&#62; and
&#60;code&#62;Alt-Shift-4&#60;/code&#62;, follow up with area or window selection. So, when I bought a PC
and put Linux on it, it&#39;s time to mess with it for these habits!&#60;/p&#62;
&#60;p&#62;And, it didn&#39;t take too long to solve. I&#39;ve found &#60;a href=&#34;https://github.com/naelstrof/maim&#34;&#62;maim&#60;/a&#62;. Writing this down
for mine and maybe, yours, future reference.&#60;/p&#62;
&#60;p&#62;To capture the entire screen:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;bash -c &#38;quot;maim ~/Screenshots/fullscreen_$(date +%s).png&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To active area/windows selection for the capture:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;bash -c &#38;quot;maim -s ~/Screenshots/area_$(date +%s).png&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Here&#39;s how the latter in action (with keybinds via Ubuntu 20.20 desktop&#39;s
Settings app).&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/06/18/area-screenshot-on-ubuntu.gif&#34; alt=&#34;How selecting an area with maim works on Ubuntu&#34; /&#62;&#60;/p&#62;
</description>
                <pubDate>Thu, 18 Jun 2020 13:22:01 -0700</pubDate>
                <link>https://duan.ca/2020/06/18/taking-linux-screenshots/</link>
                <guid isPermaLink="true">https://duan.ca/2020/06/18/taking-linux-screenshots/</guid>
            </item>
            <item>
                <title>StreamLogger</title>
                <description>&#60;p&#62;After turning off stream on &#60;a href=&#34;https://twitch.tv/daniel_duan&#34;&#62;Twitch&#60;/a&#62;, the first thing I normally do is
exporting the stream video to YouTube, so that the stream has an archive that
survives Twitch&#39;s short-ish retain policy.&#60;/p&#62;
&#60;p&#62;These videos, perhaps surprisingly, get a few views! It&#39;s not a lot by any
measures, but I&#39;m conscientious of the fact that a typical stream archive is
a multi-hour long video with no content curation, no clear schedule, and
it sometimes contains breaks. Needless to say, watching them after-the-fact
requires some (or a lot of) fast-forwarding.&#60;/p&#62;
&#60;p&#62;So, last week &#60;a href=&#34;https://twitch.tv/daniel_duan&#34;&#62;on stream&#60;/a&#62;, I set out to improve the fast-forwarding
experience. YouTube has this feature that lets you jump to specific timestamp
in the video through a URL parameter in the video&#39; link. Further, they generate
this parameter for text in video&#39;s description, if the text is in the right
format. This is handy for generating a &#38;quot;table of content&#38;quot; for the video so that
viewers can click the timestamp in the description to jump to the section they
are most interested in.&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/dduan/StreamLogger&#34;&#62;StreamLogger&#60;/a&#62; is a little utility that lets me note down what happened while
I&#39;m streaming. It&#39;s kind of like writing a commit message, except the message
describes what happened since the last &#38;quot;commit&#38;quot;. These messages, along with
their associated timestamps, will be used by StreamLogger to generate the &#38;quot;table
of content&#38;quot;. Using it in command line looks like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-bash&#34;&#62;# Turn on stream, maybe check signs of being live, etc. Then
slog start # start a new log

# Do stuff, when it comes to a natural conclusion point...
slog -- &#39;I did stuff&#39;

# Do more stuff...
slog -- &#39;some other stuff&#39;

# Some time later... end stream
# No action is required to end the stream as far as StreamLogger is concerned.

# Now, to generate the table-of-content
slog stamp -s 1:32
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;That last command outputs&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;0:01:32 I did stuff
1:41:59 some other stuff
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... which goes to the video&#39;s description.&#60;/p&#62;
&#60;p&#62;There&#39;s a few subtleties in this overall simple tool.&#60;/p&#62;
&#60;p&#62;Whenever a message is added, it gets associated with the time at which the
&#60;em&#62;previous&#60;/em&#62; message was add. So the act of logging marks both the end of
a chapter and the beginning of the next.&#60;/p&#62;
&#60;p&#62;In reality, there&#39;s always going to be a gap between the start of the stream and
the time the log is initialized. That&#39;s what the &#60;code&#62;-s 1:32&#60;/code&#62; in the last command
is trying to correct. It tells StreamLogger the length of the gap. Now the
absolute time associated with each event has a relationship with the archive
video.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;I chose to write this in Rust because I&#39;m going to need the final product on
Linux, macOS, and Windows since I stream on all 3 platforms. (fun fact: I never
built it directly on my PC running Linux. Instead, I simply downloaded the
musl-based build from the GitHub release, which was built by GitHub Actions. It
works beautifully.) Maybe one day I&#39;ll add a GUI for it that works across these
platforms, too, so that it&#39;s more friendly to wider group of users.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;The more I use and think about StreamLogger, the more I like it. You can see
me working its entirety in the following archives ;)&#60;/p&#62;
&#60;p&#62;Part 1: https://youtu.be/xWRcdaEjir4
Part 2: https://youtu.be/RS-ZMBzu9Dg&#60;/p&#62;
</description>
                <pubDate>Sat, 13 Jun 2020 12:36:55 -0700</pubDate>
                <link>https://duan.ca/2020/06/13/stream-logger/</link>
                <guid isPermaLink="true">https://duan.ca/2020/06/13/stream-logger/</guid>
            </item>
            <item>
                <title>Introducing Dye</title>
                <description>&#60;p&#62;&#60;em&#62;Recently, I got a PC. And I started writing some code on Windows for the
giggles. Naturally, I gravitate towards stuff I use on macOS and Linux when it
comes to tooling. To my delight, NeoVim, ripgrep and fzf all work out of the box
in terminal simulators, which brings us to todays main topic...&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;I made a terminal coloring library for Swift that works on Windows,
&#60;a href=&#34;https://github.com/dduan/Dye/releases/tag/0.0.1&#34;&#62;Dye 0.0.1 is available now&#60;/a&#62;!&#60;/p&#62;
&#60;h2&#62;So, why?&#60;/h2&#62;
&#60;p&#62;When I started working on &#60;a href=&#34;https://github.com/dduan/tre&#34;&#62;tre&#60;/a&#62;, I search in the
Rust ecosystem for a CLI interface library that supports as many platforms as
possible. Eventually I found &#60;a href=&#34;https://github.com/BurntSushi/termcolor&#34;&#62;termcolor&#60;/a&#62; among an ocean of options. As
a result, tre, like a lot of other CLI tools (like rg) written in Rust, has
a consistent UI on Windows and Unix. This experience has brought lots of joy, as
a user of both the library, and the app. I want to pay it forward to my fellow
Swift CLI makers, and their users.&#60;/p&#62;
&#60;p&#62;Zooming out slightly, success of Swift on Windows makes Swift as a skill more
valuable. And &#60;a href=&#34;https://duan.ca/2019/01/20/kick-ass-cli-tools-in-swift/&#34;&#62;I want more CLI tools written in Swift&#60;/a&#62;. So it&#39;s
a double-win, really.&#60;/p&#62;
&#60;p&#62;Lastly, it&#39;s a small library, all things considered. Being able to get it to
a shippable state on a weekend is a key reason I decided to work on it.&#60;/p&#62;
&#60;h2&#62;Technical tidbits&#60;/h2&#62;
&#60;p&#62;I love Max Howell&#39;s &#60;a href=&#34;https://github.com/mxcl/Chalk&#34;&#62;Chalk&#60;/a&#62; library. It&#39;s a 100-line Swift file that
implements &#60;a href=&#34;https://en.wikipedia.org/wiki/ANSI_escape_code&#34;&#62;ANSI escape code&#60;/a&#62; with Swift&#39;s custom string interpolation
API. It demonstrates well how simple it is to customize your terminal output.&#60;/p&#62;
&#60;p&#62;Enter Windows, where ANSI sequences are ignored by built-in terminal simulators
from the past. The console is customized via a entirely separate, stateful,
imperative APIs (Newer simulators such as the freshly released &#60;a href=&#34;&#34;&#62;Terminal&#60;/a&#62;
actually supports ANSI codes pretty well). This is our lowest common API
denominator, which ultimately dictated the design of Dye.&#60;/p&#62;
&#60;p&#62;Dye&#39;s API is centered around Swift&#39;s built-in protocol &#60;code&#62;TextOutputStream&#60;/code&#62;. You
create a stream object and mutate the style need for upcoming output:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let output = OutputStream.standardOutput()
output.color.foreground = .blue
print(&#38;quot;blue text&#38;quot;, to &#38;amp;stream) // blue text is blue
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;If the stream is redirected to something other than the terminal, styling gets
automatically disabled. There are various options to customize this behavior.&#60;/p&#62;
&#60;p&#62;Take a look at this &#60;a href=&#34;https://github.com/dduan/Dye/blob/master/Examples/main.swift&#34;&#62;sample app&#60;/a&#62; to get a more concrete picture of
how things work.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;I&#39;ll end with a screenshot of the sample app running in Command Prompt:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/06/01/windows-example-screenshot.jpg&#34; alt=&#34;Dye sample app running in Windows Command Prompt&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Let&#39;s build more.&#60;/p&#62;
</description>
                <pubDate>Mon, 01 Jun 2020 15:08:01 -0700</pubDate>
                <link>https://duan.ca/2020/06/01/dye/</link>
                <guid isPermaLink="true">https://duan.ca/2020/06/01/dye/</guid>
            </item>
            <item>
                <title>Naive NixOS Rust Development</title>
                <description>&#60;p&#62;tl;dr: To work on Rust project with nix-shell, rls and extensions such as
&#60;code&#62;rust-analysis&#60;/code&#62;, &#60;code&#62;rust-src&#60;/code&#62;, without caring too much about specific Rust
toolchain version (except for it being &#60;code&#62;stable&#60;/code&#62;), use the following &#60;code&#62;shell.nix&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  nixpkgs = import &#38;lt;nixpkgs&#38;gt; {
    overlays = [ moz_overlay ];
  };
  ruststable = (nixpkgs.latest.rustChannels.stable.rust.override {
    extensions = [ &#38;quot;rust-src&#38;quot; &#38;quot;rust-analysis&#38;quot; ];}
  );
in
  with nixpkgs;
  stdenv.mkDerivation {
    name = &#38;quot;rust&#38;quot;;
    buildInputs = [ rustup ruststable ];
  }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;When you have a Nix hammer, everything looks like a Nix expression.&#60;/p&#62;
&#60;p&#62;Having used NixOS on a real PC for a number of days, this is the impression
I get from the world of Nix. Unfortunately, so far, it&#39;s been a negative for me.&#60;/p&#62;
&#60;p&#62;One of the most exciting thing I want to use Nix for is to bootstrap development
environment with &#60;code&#62;nix-shell&#60;/code&#62;. I imagined it to be similar to using &#60;a href=&#34;https://pipenv-fork.readthedocs.io/en/latest/&#34;&#62;pipenv&#60;/a&#62;
with Python, except for everything. Well, I&#39;ve since learned that it&#39;s not true
(yet?) for many reasons.&#60;/p&#62;
&#60;p&#62;Modern programming languages come with their own attempt at &#60;em&#62;reproducibility&#60;/em&#62;.
Some does it better than others. To make it concrete, I&#39;m talking about things
like &#60;a href=&#34;https://haskellstack.org&#34;&#62;Stack&#60;/a&#62; for Haskell or &#60;a href=&#34;https://rustup.rs/&#34;&#62;rustup&#60;/a&#62; for Rust: given the source code, how do
I make it build in the way the project intended? What&#39;s the correct version of
the compiler, runtime, and tools that works best with this revision of the
source code? The common solution usually follows this pattern: as author of
a project, specify as much as you can, the environment best suited for the
current state of the project. As a &#38;quot;builder&#38;quot;, use a &#60;em&#62;single program&#60;/em&#62; that&#39;s
capable of updating itself, as well as ensuring that the project builds exactly
as specified, including managing the compiler/runtime/tooling versions, etc.&#60;/p&#62;
&#60;p&#62;This &#60;em&#62;single program&#60;/em&#62;&#39;s role is very much the same as the Nix system, except the
latter is independent of programming languages: &#60;code&#62;rustup&#60;/code&#62; installs Rust, so does
Nix. That&#39;s a bad thing. As a package manager, Nix either have to tightly
integrate with each of these other package managers, leveraging their evolving
behaviors to give its user the build environment; or, it must replace them.
The former is impractical; the latter, well, sucks.&#60;/p&#62;
&#60;p&#62;Back to reality. This is the experience I want to have with NixOS: Some programs
I use daily such as Alacritty, NeoVim, Firfox, etc, are installed globally and
readily available. They are part of my &#60;code&#62;/etc/nixos/configuration.nix&#60;/code&#62;. So far so
good. Now, I regularly program in a few languages. For each of the project, I&#39;d
like to have a &#60;code&#62;shell.nix&#60;/code&#62; that brings in its compilers, libraries, LSP servers,
etc. This is what &#60;code&#62;nix-shell&#60;/code&#62; is supposed to give me! This is known as the &#38;quot;per
project&#38;quot; setup.&#60;/p&#62;
&#60;p&#62;Let&#39;s see: with Rust, that means &#60;code&#62;rustc&#60;/code&#62; (compiler), &#60;code&#62;cargo&#60;/code&#62; (package manager),
&#60;code&#62;rls&#60;/code&#62;, &#60;code&#62;rust-src&#60;/code&#62; and &#60;code&#62;rust-analysis&#60;/code&#62; (LSP). In macOS, I&#39;d install all of these
globally with &#60;code&#62;rustup&#60;/code&#62;. In NixOS...well, I can ask for &#60;code&#62;rustup&#60;/code&#62; for my project:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;with import &#38;lt;nixpkgs&#38;gt; {};

stdenv.mkDerivation {
  name = &#38;quot;rust&#38;quot;;
  nativeBuildInputs = [ rustup ];
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;...which gives me &#60;code&#62;rustup&#60;/code&#62; and nothing else. That&#39;s right, you don&#39;t even get
a &#60;code&#62;rustc&#60;/code&#62; after running &#60;code&#62;nix-shell&#60;/code&#62;. But &#60;code&#62;rustup&#60;/code&#62; can get you everything else,
all I need to do is ask. Hmm, do I need to run a series of set-up commands with
&#60;code&#62;rustup&#60;/code&#62; every time I enter the environment? No? I just need to run it the first
time? Until the cached tools get deleted by some garbage collection mechanism?
That seems unsatisfying, doesn&#39;t it?&#60;/p&#62;
&#60;p&#62;Instead of &#60;code&#62;rustup&#60;/code&#62;, I could also ask Nix to use the &#60;code&#62;rustc&#60;/code&#62;/&#60;code&#62;cargo&#60;/code&#62;/&#60;code&#62;rls&#60;/code&#62; it
knows about directly. This is marginally better. Except I still need &#60;code&#62;rust-src&#60;/code&#62;
and &#60;code&#62;rust-analysis&#60;/code&#62; for my needs. As far as I can tell, these &#60;a href=&#34;https://github.com/rust-lang/rls&#34;&#62;RLS&#60;/a&#62; components
are out of Nix&#39;s control (as of today).&#60;/p&#62;
&#60;p&#62;Everywhere on the internet I looked, for every problem that
Nix-the-package-manager doesn&#39;t work out-of-the-box, there&#39;s someone responding
along the line of &#38;quot;you can write some Nix expression yourself&#38;quot;. In other words,
Nix-the-language is powerful enough to solve it, probably. In the case of Rust,
luckily, Mozilla wrote enough Nix expressions for us and provides them via an
&#60;a href=&#34;https://github.com/mozilla/nixpkgs-mozilla&#34;&#62;overlay&#60;/a&#62;. These expressions are rich enough to meet my needs.
As you can see in the tl;dr at the top, when entering the development
environment, nix-shell would: download the overlay&#39;s source code (from the
internet, or local cache), load the expression it includes, mix in my
customization, and execute it.&#60;/p&#62;
&#60;p&#62;That marks the end of my search. I like the final solution because it&#39;s mostly
&#38;quot;vanilla&#38;quot; Nix and doesn&#39;t require me to mess with a bunch of other tools. For
solutions that do, read &#60;a href=&#34;https://xeiaso.net/blog/how-i-start-nix-2020-03-08/&#34;&#62;this&#60;/a&#62;.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;At end of the day, my needs are pretty basic: consistency from rustup and
convenience from nix-shell. I didn&#39;t need to pin the compiler to a specific Rust
release, or checksum the final build output.&#60;/p&#62;
&#60;p&#62;I&#39;m very new to both technologies so there may be a follow-up post sometime in
the future.&#60;/p&#62;
</description>
                <pubDate>Thu, 07 May 2020 11:04:58 -0700</pubDate>
                <link>https://duan.ca/2020/05/07/nix-rust-development/</link>
                <guid isPermaLink="true">https://duan.ca/2020/05/07/nix-rust-development/</guid>
            </item>
            <item>
                <title>Site Improvements 2020</title>
                <description>&#60;p&#62;I took back my website.&#60;/p&#62;
&#60;p&#62;I took it back from the claws of Jekyll and Ruby. I took it back from some
random template among a few that were immediately available. I took it back
from my own ignorance of modern web technology.&#60;/p&#62;
&#60;p&#62;This time, I rewrote the hole effing thing from scratch.&#60;/p&#62;
&#60;h3&#62;The Why&#60;/h3&#62;
&#60;p&#62;The &#60;a href=&#34;/2017/01/16/site-changes/&#34;&#62;last time&#60;/a&#62; I ended with&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;I wrote the most Ruby in my life today. Yay?&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;That question mark turned out to be prescient. Ruby is not my thing. No
judgement against the language per ce. But the Ruby ecosystem is not friendly to
a casual user who needs it once every few months. No really, when I write an
article, it&#39;s a toss-up whether I can deploy it without being forced to mess
with Ruby/Gems/Jekyll/Homebrew etc. I&#39;m almost certain there&#39;s a set of best
practices I could learn to improve this. But it&#39;d be a skill that I barely need
and probably forget a few times. Meanwhile I just want to translate a new
Markdown file to HTML and put it on Github.&#60;/p&#62;
&#60;p&#62;As a teen, one of my favorite things about the web is how accessible it is.
I could sit in front of anyone&#39;s computer, open Notepad.exe and type in some
tags, and open the file with a browser to see the result. That simple bootstrap
process, however repetitive, never got old for me.&#60;/p&#62;
&#60;p&#62;In the last decade, my professional work is focused on native, mobile
applications. This experience biased me in a few ways. &#38;quot;Native&#38;quot; made me
appreciate the closeness to &#38;quot;the metal&#38;quot;: you have an OS; you get the executable;
you launch strace, and boom, everything the OS thinks what your code does is
revealed to you. &#38;quot;Mobile&#38;quot; forced me to reckon with the reality: desktop
experience has become a niche. It&#39;s nowhere near as important as it was prior to
the iPhone. Not making your software run well on mobile devices is a particular
kind of choice that come with some severe trade-offs.&#60;/p&#62;
&#60;p&#62;And, finally, I subscribe to the idea that &#60;em&#62;plain text is supreme&#60;/em&#62;. Yes, even
more supreme than the web. This website is a derivative of the articles I write
in Markdown. Plain text as a format will out-last the web in the long run (not
necessarily &#60;em&#62;these&#60;/em&#62; texts). So it really bothers me when I have to put &#38;quot;front
matter&#38;quot; in YAML/TOML/whatever in front of the real Markdown. Yes, if you want
reasonable HTMLs, these metadata is necessary. But the text is &#60;em&#62;Supreme&#60;/em&#62;. The
text is to be readable directly. Succumbing the supreme to the derivative is
&#60;em&#62;wrong&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;Okay, so where does all that leave me? In this iteration of this website,
I wrote every single line of CSS and HTML (there&#39;s barely any JavaScript) which
look decent on mobile. It&#39;s generated by portable Linux and Darwin executables
that are part of the website. As long as the OSes stay relatively stable, the
site will build without any dependencies, in a matter of milliseconds. The best
part?  It&#39;ll stay like this unless I wish it otherwise.&#60;/p&#62;
&#60;h3&#62;The Frontend&#60;/h3&#62;
&#60;p&#62;A few words on the design of the site.&#60;/p&#62;
&#60;p&#62;This site gained the concept of &#38;quot;links&#38;quot; the &#60;a href=&#34;/2017/01/16/site-changes/&#34;&#62;last time&#60;/a&#62;. It has since become
clear that I don&#39;t use this feature (blame Twitter). It&#39;s gone, for now. The old
&#38;quot;about&#38;quot; page is replaced by the home page.&#60;/p&#62;
&#60;p&#62;When I decided the site needed a rewrite, I fantasized a place with only HTML.
Perhaps users who want a better reading experience can simply put it in Reader
mode. Alas, if browsers (with the exception of Safari) implemented automatic
dark mode with a &#60;a href=&#34;https://drafts.csswg.org/css-color-adjust-1/#color-scheme-meta&#34;&#62;color-scheme meta&#60;/a&#62; tag, it&#39;d almost be a working idea.&#60;/p&#62;
&#60;p&#62;So, that&#39;s my starting point.&#60;/p&#62;
&#60;p&#62;The site is a list of articles organized by tags and dates, and a few web pages.
&#60;em&#62;I want you to read the site, not navigate it&#60;/em&#62;. So text is the point. It&#39;s the
only design element. The site uses 2 fonts and 2 text-color (not counting
highlighted code). Links are always underscored (because you can&#39;t hover in
mobile browsers to find something clickable).&#60;/p&#62;
&#60;p&#62;The site is responsive to mobile layout, and dark mode. It&#39;s aware that it could
be added to the home screen of a mobile device, or linked to some external site
that wants to generate a preview.&#60;/p&#62;
&#60;p&#62;I did end up using &#60;a href=&#34;https://ethanschoonover.com/solarized/&#34;&#62;solarized&#60;/a&#62; theme for code highlighting, which lead to 2
static CSS files. Other than that, all CSS and HTML are hand-written. There&#39;s no
build step for them, farm to table, Vim to your browser.&#60;/p&#62;
&#60;p&#62;It turned out standardized CSS variable is game-changing. Combined with media
queries, I barely needed any class to support dark mode/mobile layout. More
importantly, it makes my programmer brain happy. Oh, yes I&#39;m talking about them
here because this is the first time I truly attempted to catch up since they
were introduced to the world. It&#39;s freeing to let go of constrains of an
read-to-use theme, or some CSS frameworks.&#60;/p&#62;
&#60;h3&#62;The Backend&#60;/h3&#62;
&#60;p&#62;This site is a collection of static files. The so-called backend is a program
that assembles these files from some HTML templates and Markdown files. In the
past, this program had been &#60;a href=&#34;https://jekyllrb.com/&#34;&#62;Jekyll&#60;/a&#62;. This time around, I replaced it with
some Rust code.&#60;/p&#62;
&#60;p&#62;Boy, this thing is cool, if I say so myself. I&#39;m going to refer to it as &#38;quot;the
generator&#38;quot;.&#60;/p&#62;
&#60;p&#62;The biggest &#38;quot;feature&#38;quot; is the fact that it doesn&#39;t pretend to be re-usable.
The generator is as part of this site as the articles.&#60;/p&#62;
&#60;p&#62;Thanks to Rust, the programs are built into executable binaries. On macOS, it
requires libSystem to run. On Linux, I can (and prefer) build with &#60;a href=&#34;https://www.musl-libc.org/&#34;&#62;musl&#60;/a&#62;. The
binaries for these two OSes are checked in with the content of the site. So
it requires zero installation to &#38;quot;build&#38;quot; the site. (I may need to
include a 3rd executable for the upcoming ARM-based Macs soon).&#60;/p&#62;
&#60;p&#62;The generator spits out the final content of the website. It&#39;s deployed without
further modification.&#60;/p&#62;
&#60;p&#62;The build process is pretty fast. As of this writing, it averages around 250 ms.
I could probably make it faster by avoiding some repeated reads when it comes to
article inputs.&#60;/p&#62;
&#60;p&#62;The generator handles HTML/XML templating with a library named &#60;a href=&#34;https://github.com/djc/askama&#34;&#62;Askama&#60;/a&#62;.
Learning it had been an eye opening experience. Askama is built atop Rust&#39;s
macro system. For each template (e.g. web page), it requires users to write
a Rust data structure that fulfills its variable requirements.  Here&#39;s the
kicker: in this data structure, you &#60;em&#62;cannot&#60;/em&#62; miss any variable the corresponding
template requires.  When you do, the Rust project won&#39;t compile! Rust&#39;s tooling
is so good that these errors were surfaced in my editor as I wrote this part
in real time. This level of type-safety for template language felt like magic.&#60;/p&#62;
&#60;p&#62;Syntax highlighting is powered by &#60;a href=&#34;https://github.com/trishume/syntect&#34;&#62;syntect&#60;/a&#62;, the library behind &#60;a href=&#34;https://github.com/sharkdp/bat&#34;&#62;bat&#60;/a&#62;. But
the interesting bit here is how the syntax definitions are embedded within the
final executable. To support a particular syntax, syntect takes the syntax&#39;s
SublimeText definition. So this is a configurable, extendible system. The
generator includes 118 syntax definitions. Uncompressed, their files take up 5MB
of disk space. As one can imagine, loading 5MB from 118 files each time the
program runs is quite slow. Turns out, Rust has a standard library macro
&#60;a href=&#34;https://doc.rust-lang.org/std/macro.include_bytes.html&#34;&#62;include_bytes!&#60;/a&#62; that solves this problem. &#60;a href=&#34;https://doc.rust-lang.org/std/macro.include_bytes.html&#34;&#62;include_bytes!&#60;/a&#62; embeds
contents of a file as literals in source code, as if it&#39;s hand-written. syntect
takes advantage of this feature by supporting serialization of its in-memory
representation of syntaxes into bytes, and accepting in-line byte literals in
reverse in order to create these representations. This system solves two
problems for me:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;I no longer need to ship the SublimeText syntax files along with the
generator.&#60;/li&#62;
&#60;li&#62;The generator doesn&#39;t need to perform all that disk I/O, so it runs
significantly faster.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Overall, the Rust ecosystem delivered. Although a lot of library are still in
rough shape/early stage, there usually are multiple alternatives for roughly the
same purpose. Gluing a few of them together for this generator project had been
fun.&#60;/p&#62;
&#60;p&#62;Finally, let&#39;s talk metadata, I can&#39;t realistically manage to generate the site
without them.  Articles and static pages each define their URL by their file
locations relative to the root. For example, &#60;code&#62;/articles/2020/04/23/hello.md&#60;/code&#62;
means the URL is &#60;code&#62;/2020/04/23/hello/&#60;/code&#62;. Each article still has a front matter.
But I made the text version look as &#38;quot;natural&#38;quot; as possible. There&#39;s no markers
for beginning and end of the metadata since I know exactly what&#39;s needed. The
title is marked as an H1. Date is in RFC3339 format. Tags are comma-separated
values. So an example of an article&#39;s beginning looks like:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-markdown&#34;&#62;# Site Improvements 2020
2020-04-22T21:58:03-07:00
tags: Rust, HTML, CSS, Ruby, Jekyll, Markdown

I took back my website...
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Text supremacy! Glory!&#60;/p&#62;
&#60;h3&#62;Onward&#60;/h3&#62;
&#60;p&#62;Over the course of roughly 15 years, I&#39;ve had blogs of quite a few variates.
I wish I&#39;d done a better job archiving them as I moved on from one to the next.
This is not the first time I attempted to gain full control over the theming,
generating, hosting, and deployment of a site. But I&#39;m hopeful that it&#39;ll last
longer. You could say that&#39;s what I optimized for. And who knew, maybe my
experience from past failures counts for something.&#60;/p&#62;
&#60;p&#62;Here&#39;s to less stressful deploys and more writing!&#60;/p&#62;
</description>
                <pubDate>Wed, 22 Apr 2020 21:58:03 -0700</pubDate>
                <link>https://duan.ca/2020/04/22/site-improvements-2020/</link>
                <guid isPermaLink="true">https://duan.ca/2020/04/22/site-improvements-2020/</guid>
            </item>
            <item>
                <title>Git Commit Message, Vim, and Markdown</title>
                <description>&#60;p&#62;It&#39;s been bothering me for years.&#60;/p&#62;
&#60;p&#62;That is, &#60;code&#62;#&#60;/code&#62; is both the start of a comment in a git commit message, but also
the syntax for headings in Markdown.&#60;/p&#62;
&#60;p&#62;Personally, I prefer using commit messages to populate pull request descriptions
whenever possible. On GitHub, This happens automatically when the pull request
contains a single commit. But I can&#39;t type, say an H3 as &#60;code&#62;### Heading&#60;/code&#62; in the
commit message (in Vim, most of the time) because it gets treated as a comment!&#60;/p&#62;
&#60;p&#62;But thanks to this twitter interaction with &#60;a href=&#34;https://twitter.com/dmartincy&#34;&#62;@dmartincy&#60;/a&#62;, I finally solved
this problem:&#60;/p&#62;
&#60;blockquote class=&#34;twitter-tweet&#34;&#62;&#60;p lang=&#34;en&#34; dir=&#34;ltr&#34;&#62;I haven&#38;#39;t found myself in that situation, but maybe you could do &#38;#39;git config core.commentChar &#38;quot;;&#38;quot;&#38;#39; before creating the commits? That will change the default git commit marker (#) to something that won&#38;#39;t conflict with Markdown titles.&#60;/p&#62;&#38;mdash; Daniel Martín (@dmartincy) &#60;a href=&#34;https://twitter.com/dmartincy/status/1247271508420026368?ref_src=twsrc%5Etfw&#34;&#62;April 6, 2020&#60;/a&#62;&#60;/blockquote&#62; &#60;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&#62;&#60;/script&#62;
&#60;p&#62;As mentioned by Daniel, Git has introduced a setting called &#60;code&#62;core.commentChar&#60;/code&#62;,
documented &#60;a href=&#34;https://git-scm.com/docs/git-config#Documentation/git-config.txt-corecommentChar&#34;&#62;here&#60;/a&#62;, which lets us control which character
becomes the start of a comment line. Let&#39;s say we want to replace the default
&#60;code&#62;#&#60;/code&#62; with &#60;code&#62;;&#60;/code&#62;, we can edit &#60;code&#62;~/.gitconfig&#60;/code&#62; to include this preference:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;[core]
	commentChar = &#38;quot;;&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;… and this will affect every Git repository on this computer.&#60;/p&#62;
&#60;p&#62;For me, though, this broke git commit syntax highlighting in Vim: the comments,
beginning with &#60;code&#62;;&#60;/code&#62;, are no longer recognized as comments. To fix this, I updated
Vim&#39;s syntax for file type &#60;code&#62;gitcommit&#60;/code&#62;. In your Vim setting directory
(&#60;code&#62;~/.config/nvim/&#60;/code&#62; for me), create a file &#60;code&#62;syntax/gitcommit.vim&#60;/code&#62; file (unless
you already have one), add the following line:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;syn match gitcommitComment	&#38;quot;^;.*&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Note &#60;code&#62;;&#60;/code&#62; matches my preferred &#60;code&#62;core.commentChar&#60;/code&#62; for Git.&#60;/p&#62;
&#60;p&#62;Et voilà! Git commit message looks tippy-top in Vim again!&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2020/04/gitcommit.png&#34; alt=&#34;editing git commit in vim, with alternative character being the beginning of a comment&#34; /&#62;&#60;/p&#62;
</description>
                <pubDate>Mon, 13 Apr 2020 13:41:02 -0700</pubDate>
                <link>https://duan.ca/2020/04/13/git-commit-comment/</link>
                <guid isPermaLink="true">https://duan.ca/2020/04/13/git-commit-comment/</guid>
            </item>
            <item>
                <title>On the Subject of Interface Hygiene</title>
                <description>&#60;p&#62;In a purly reactive world, your entire program merge into a single stream. Now,
close your eyes, and envision: your project as one, beautiful, stream.&#60;/p&#62;
&#60;p&#62;Now open your eyes. Yeah, it&#39;s not. Your project is a Mac or iOS app. It&#39;s full
of your memories, sweat, and blood. And you are ready to sweat and bleed some
more by putting some Combine and SwiftUI into it. You watched the WWDC19
sessions and learned that &#38;quot;Subjcets are super powerful&#38;quot;. You looked into your
code and realized you can&#39;t really do anything with Combine without &#60;code&#62;Subject&#60;/code&#62;s
at the current state of the project.&#60;/p&#62;
&#60;p&#62;Well…&#60;/p&#62;
&#60;p&#62;Here are a few habits that help keeping your project that prevasively uses
&#60;code&#62;Combine.Subject&#60;/code&#62; &#60;em&#62;sane&#60;/em&#62;. They should seem obvious to anyone who understands
Murphy&#39;s law and the value of minialism in interfaces. If you already are using
some reactive stream implementation, substitute the types with their
counterparts in your framework and these rules should seem down right &#60;strong&#62;basic&#60;/strong&#62;.&#60;/p&#62;
&#60;h2&#62;Vend &#60;code&#62;Subject&#60;/code&#62;s as &#60;code&#62;Publisher&#60;/code&#62;s&#60;/h2&#62;
&#60;p&#62;&#60;code&#62;Subject&#60;/code&#62;s help bridge from the imperitive to the reactive world. Somewhat
paradoxically, sharing them is not very &#38;quot;RX-y&#38;quot;. This is akin to prefering &#60;code&#62;let&#60;/code&#62;s
over &#60;code&#62;var&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;Most of the time, what you want to share is the values pumped into the stream,
not the privilage to mutate it. Because Subjects conform to &#60;code&#62;Publisher&#60;/code&#62;, it&#39;s
easy to hide from the users the fact that your stream is backed by them.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Bad: now anyone who get a hold of it can mess with your stream!
public enum GreatInts {
    public var updates = CurrentValueSubject&#38;lt;Int, Never&#38;gt;(0)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;With Combine this conversion happens via type-erasure:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Better: all your users care is the stream (publisher), so give them that!
public enum GreatInts {
    // Internally, it&#39;s backed by a subject.
    var subject = CurrentValueSubject&#38;lt;Int, Never&#38;gt;(0)
    // Externally, it&#39;s just a Publisher. 
    public var subject: AnyPublisher&#38;lt;Int, Never&#38;gt; {
        subject.eraseToAnyPublisher()
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;h2&#62;CurrentValueSubject natually caches the latest value&#60;/h2&#62;
&#60;p&#62;RX theorists will hate this: sometimes it&#39;s just practical to expose
a synchronous interface to the latest vaule in the stream!&#60;/p&#62;
&#60;p&#62;Two things.&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;It might be tempting to expose the subject and let your user use its
&#60;code&#62;.value&#60;/code&#62;. Well, you shouldn&#39;t (as explained in the previous section).
A separate interface dedicated to the latest value prevents people from
polluting your stream.&#60;/li&#62;
&#60;/ol&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// (Still) bad
public final class GreatInts {
    public var updates = CurrentValueSubject&#38;lt;Int, Never&#38;gt;(0)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;ol start=&#34;2&#34;&#62;
&#60;li&#62;Remember &#60;code&#62;CurrentValueSubject&#60;/code&#62; has that &#60;code&#62;.value&#60;/code&#62; property! It may seem
surprising, but I&#39;ve seen folks transitioning to RX clinging to the old ways:&#60;/li&#62;
&#60;/ol&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;public final class GreatInts {
    // well, at least it&#39;s not a public subject...
    var subject = CurrentValueSubject&#38;lt;Int, Never&#38;gt;(0) // &#38;lt;- initial value 0
    public var updates: AnyPublisher&#38;lt;Int, Never&#38;gt; {
        subject.eraseToAnyPublisher()
    }

    // Wait, there&#39;s that 0 again
    public var latest: Int = 0 {
        didSet {
            subject.send(latest) // ?
        }
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;First, you&#39;ll notice that &#60;code&#62;0&#60;/code&#62;, the initial value, is duplicated as both the
subject&#39;s initial value, as well as the value of a stored property. And these
duplicated sources of truth persist throughout the parent&#39;s life time. Weird,
right?&#60;/p&#62;
&#60;p&#62;Here&#39;s a slightly better version:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;public final class GreatInts {
    var subject = PassthroughSubject&#38;lt;Int, Never&#38;gt;()
    public var updates: AnyPublisher&#38;lt;Int, Never&#38;gt; {
        subject.eraseToAnyPublisher()
    }

    public var latest: Int = 0 {
        didSet {
            subject.send(latest) // ?
        }
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now there&#39;s no two copy of the latest value in memory anymore. But in my opinion
it does not embrace the full power of Combine. Here&#39;s the most natual way to do
this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;public final class GreatInts {
    /// This is a CurrentValueSubject again.
    var subject = CurrentValueSubject&#38;lt;Int, Never&#38;gt;(0)
    public var updates: AnyPublisher&#38;lt;Int, Never&#38;gt; {
        subject.eraseToAnyPublisher()
    }

    public var latest: Int {
        subject.value
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Essentially, you create separate public interface, each vends a little piece of
&#60;code&#62;CurrentValueSubject&#60;/code&#62;&#39;s power.&#60;/p&#62;
&#60;h2&#62;No really, don&#39;t use &#60;code&#62;Subject&#60;/code&#62;s&#60;/h2&#62;
&#60;p&#62;Even a well-scoped &#60;code&#62;Subject&#60;/code&#62; (properly being private or internal, depending on
your tool of choice for access control) still has a mutable state that you
probably don&#39;t want: its stream can go from &#38;quot;alive&#38;quot; to &#38;quot;complete&#38;quot;. And, again,
anyone with access can make this state transition happen, leaving you in the
undefensible position of … hoping everyone on your team to not misuse your
stuff?&#60;/p&#62;
&#60;p&#62;Lucky for you (and me), a &#38;quot;incompletable&#38;quot; subject is a established concept -- a
&#38;quot;Relay&#38;quot;. I&#39;ve put together a repo for you to look and/or use:&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/dduan/relay&#34;&#62;https://github.com/dduan/relay&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;Yeah, ban all Subjects in your project with a linter. Seriously.&#60;/p&#62;
&#60;h2&#62;Fin&#60;/h2&#62;
&#60;p&#62;That&#39;s all for now. I&#39;m not an expert with RX myself. Hopefully these
perspective can help you avoid some nasties.&#60;/p&#62;
</description>
                <pubDate>Mon, 01 Jul 2019 20:22:48 -0700</pubDate>
                <link>https://duan.ca/2019/07/01/combine-hygiene/</link>
                <guid isPermaLink="true">https://duan.ca/2019/07/01/combine-hygiene/</guid>
            </item>
            <item>
                <title>TOML Decoder Playlist</title>
                <description>&#60;p&#62;I enjoyed making &#60;a href=&#34;https://github.com/dduan/TOMLDeserializer&#34;&#62;TOMLDeserializer&#60;/a&#62; and &#60;a href=&#34;https://github.com/dduan/TOMLDecoder&#34;&#62;TOMLDecoder&#60;/a&#62; recently. Let&#39;s hope
some projects will pick them up and TOML as a configuration format will start to
spead in Swift communities.&#60;/p&#62;
&#60;p&#62;What&#39;s outstanding about these projects is that I started working on them while
&#60;a href=&#34;https://twitch.tv/daniel_duan&#34;&#62;streaming&#60;/a&#62;. Personally, I consume a lot of content like this. So now people
can watch me writing Swift, too.&#60;/p&#62;
&#60;p&#62;I&#39;ve been archiving recordings of these streams as much as I can. Here are the
links to these videos, each is around 1-1.5 hours long:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/XLLlCEfuFLw&#34;&#62;Turn TOML Test Fixtures Into XCTests With Vim Macros&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/Ztq3K3cq8f0&#34;&#62;Passing TOML Deserialization Tests&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/GTCYSIc6n3U&#34;&#62;Finishing TOML Invalidation Tests&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/HP2Wzh8MVvg&#34;&#62;TOML Decoder: The Beginning&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/EZ7VpbrLkH0&#34;&#62;TOML Decoder: Filling In Missing Implementation Pieces&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/bISMVVWOHKg&#34;&#62;TOML Decoder: Adding The First TOML Decoding Strategy!&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/oOOS4bnhwx4&#34;&#62;TOML Decoder: Project Overview And Data Decoding Support&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/9yDtXsrMtbU&#34;&#62;TOML Decoder: Key Decoding Strategies&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;https://youtu.be/g1V872HL4Dk&#34;&#62;TOML Decoder: Project Updates&#60;/a&#62;&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;The TOMLDecoder projects would&#39;ve been capture on camera entirely if I weren&#39;t
such a streaming n00b and messed up a few streams. Hilarious.&#60;/p&#62;
</description>
                <pubDate>Sun, 10 Mar 2019 20:32:37 -0700</pubDate>
                <link>https://duan.ca/2019/03/10/toml-decoder/</link>
                <guid isPermaLink="true">https://duan.ca/2019/03/10/toml-decoder/</guid>
            </item>
            <item>
                <title>Kick-ass CLI Tools In Swift</title>
                <description>&#60;p&#62;As someone who lives in a terminal simulator, I&#39;m pleasantly surprised by the
new toys we get in recent years such as &#60;a href=&#34;https://github.com/junegunn/fzf&#34;&#62;fzf&#60;/a&#62;, &#60;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&#62;ripgrep&#60;/a&#62;, &#60;a href=&#34;https://github.com/sharkdp/fd&#34;&#62;fd&#60;/a&#62;, etc.
A great number of these are written in relatively young programming languages
such as Go and Rust. But, noticibly, none of them are written in Swift.&#60;/p&#62;
&#60;p&#62;In this post, I&#39;ll try to explain why that is.&#60;/p&#62;
&#60;h2&#62;POSIX Ergonomics&#60;/h2&#62;
&#60;p&#62;Unix-like virtual file systems has been around for decades. API that manupulates
such systems has standardized a long time ago and exists in most computers
running Linux/BSD/macOS today (and, to a large extend, smart phones). To Swift
users, Using these APIs is straight-forward (&#60;code&#62;rmdir(&#38;quot;path/to/dir&#38;quot;)&#60;/code&#62;).&#60;/p&#62;
&#60;p&#62;So Swift programmers are all happy campers (re-)inventeing all sorts of file
system utilities, right?&#60;/p&#62;
&#60;p&#62;Well, not quite.&#60;/p&#62;
&#60;p&#62;Okay, I lied about POSIX APIs being &#38;quot;straight-forward&#38;quot; in Swift. Or rather, this
is very subjective.&#60;/p&#62;
&#60;p&#62;Continuing with the &#60;code&#62;rmdir&#60;/code&#62; example, we must first import it from either &#60;code&#62;Glibc&#60;/code&#62;
or &#60;code&#62;Darwin&#60;/code&#62;, depending on your OS. To know whether the operation is successful,
we need to see whether it returned integer 0. To learn &#60;em&#62;why&#60;/em&#62; 0 was not returned,
we need to read the &#38;quot;magical&#38;quot; variable &#60;code&#62;errno&#60;/code&#62;. &#60;code&#62;errno&#60;/code&#62; could be written to by
other APIs so we&#39;d better capture it in time…&#60;/p&#62;
&#60;p&#62;And that&#39;s one of the simpler APIs in POSIX calls!&#60;/p&#62;
&#60;p&#62;Programmers whine about ergonomics partially because we are previlidged and
spoiled. But mostly because our attention is a limited resources. Mixing API
conventions distracts us from solving the problem at hand. Bad ergonomics,
therefore, drives away a good potion of users who cares about quality of their
tools.&#60;/p&#62;
&#60;h2&#62;Culture and History&#60;/h2&#62;
&#60;p&#62;As of this writing, the release of Swift 5 is imminent. The vast majority of
existing Swift code is written to run on iOS. The concept of a file, or the
traditional virtal file system, is hidden to iOS users, and sandboxed for
developers. I bet most Swift users rarely think about the fact that there&#39;s
a entire set of POSIX API at their disposal.&#60;/p&#62;
&#60;p&#62;&#60;code&#62;Foundation&#60;/code&#62; alleviates the need to deal with files and directories: &#60;code&#62;Bundle&#60;/code&#62;
locates the files; &#60;code&#62;CoreData&#60;/code&#62;, &#60;code&#62;UserDefaults&#60;/code&#62; or the keychain is your primary
way to persist data; &#60;code&#62;Data&#60;/code&#62;, &#60;code&#62;String&#60;/code&#62; or &#60;code&#62;NSCoding&#60;/code&#62; has methods to read and
write to files.  And finally, if you really need to deal with files,
&#60;code&#62;NSFileManager&#60;/code&#62; has everything you&#39;ll ever need.&#60;/p&#62;
&#60;p&#62;Why would a productive Swift programmer think about POSIX in this environment?
Why would a tutor teach POSIX over the useful/practical/&#38;quot;native&#38;quot; alternatives?&#60;/p&#62;
&#60;p&#62;We can trace &#38;quot;riding on the Apple platform&#38;quot; mentality back to the pre-iPhone
days, where a very small Mac developer community labors on on a niche platform
(compared to iOS today) and they &#60;em&#62;loved&#60;/em&#62; it. However, I&#39;m sure they used more
POSIX stuff back then than the average iOS developers today.&#60;/p&#62;
&#60;p&#62;Having a great library such as Foundation on the most popular developer
platform where the language thrives means it&#39;ll take longer for &#38;quot;subcultures&#38;quot;
to emerge, if they do at all.&#60;/p&#62;
&#60;h2&#62;The Standard Library And Its Influence on New Users&#60;/h2&#62;
&#60;p&#62;File system APIs being in &#60;code&#62;Foundation&#60;/code&#62; as opposed to the standard library is
probably a temporary condition. Nevertheless, it has at least the following
implications:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;Its quality of implementation is not held on the same standard that those
APIs in the standard library. This is especially true for the separate,
open-source &#60;code&#62;Foundation&#60;/code&#62; implementation. Getting consistent and correct
behaviors across macOS and Linux is hard.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;A person learning Swift won&#39;t explore the language with a file system API.
This I suspect, is &#60;strong&#62;the most important reason many of these great CLI
utilites are written in other programming languages&#60;/strong&#62;. Programmers seek
instant gratification when they learn. And they usually stay in a limited
domain (like iOS) at first. This is where the built-in library is special: no
matter which domain is chosen, it&#39;s always available. Languages such as Go
and Rust include things like paths and files in their built-in library.
Playing with these APIs while learning the lanugage plants a seed for future,
serious, projects. There are less users of these languages compared to Swift,
but there are more people thinking about projects that involves file systems
in thoes communities. (Note I don&#39;t have statistics here, just a guess.)&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;h2&#62;Conclusion&#60;/h2&#62;
&#60;p&#62;The next killer CLI tool is still more likely to be written in Go or Rust,
than in Swift. Hopefully, somewhere in these speculations is a true cause of
this phenomena. Maybe someone reading this will be inspired to accelerate change
that will eventually revert the condition. (I&#39;m &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;trying&#60;/a&#62;).&#60;/p&#62;
</description>
                <pubDate>Sun, 20 Jan 2019 16:09:38 -0800</pubDate>
                <link>https://duan.ca/2019/01/20/kick-ass-cli-tools-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2019/01/20/kick-ass-cli-tools-in-swift/</guid>
            </item>
            <item>
                <title>Magical Interactions</title>
                <description>&#60;p&#62;I want to talk about this little function:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func interact(_ process: (String) -&#38;gt; String) {
    var input = &#38;quot;&#38;quot;
    while let line = readLine() {
        input += line
    }

    print(process(input))
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Brief explanation: it reads all the input from stdin as a &#60;code&#62;String&#60;/code&#62;, feeds it
into a closure &#60;code&#62;process&#60;/code&#62;, which it takes in as its only argument, and prints
&#60;code&#62;process&#60;/code&#62;&#39;s output.&#60;/p&#62;
&#60;p&#62;Here&#39;s how one might use it:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// counts characters from stdin and prints result to stdout
interact { String($0.count) }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Got that? Well, now I&#39;m going to rewrite it in a slightly less Swift-y way:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let count: (String) -&#38;gt; String = {
    return String($0.count)
}

interact(count)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The argument for &#60;code&#62;interact&#60;/code&#62; got defined with a name and an explicit type
signature.&#60;/p&#62;
&#60;p&#62;So, what&#39;s so special about this &#60;code&#62;interact&#60;/code&#62; function? Two words: &#60;em&#62;side effects&#60;/em&#62;.
More precisely, it took away the concern of side-effects from the user. &#60;code&#62;count&#60;/code&#62;
belongs in the realm of &#60;em&#62;pure&#60;/em&#62; functions. It has no worries about file handles
or operating systems. It&#39;s &#60;code&#62;(String) -&#38;gt; String&#60;/code&#62;. I wanted to emphasize this with
the rewrite. Look at that empty line. Now you see a boundary between 2 worlds.&#60;/p&#62;
&#60;p&#62;This may all seem contrived. But when I learned about &#60;a href=&#34;http://hackage.haskell.org/package/base-4.11.1.0/docs/Prelude.html#v:interact&#34;&#62;this function in
Haskell&#60;/a&#62;, I was blown away.&#60;/p&#62;
&#60;p&#62;It&#39;s like a great magic trick: you are presented a scenario, say, writing
a little script. Maybe you need to process some CLI output and print out a CSV
or JSON string (literally 90% of the script I write).  A Haskell programmer
would jump into the bottom level of the problem and start writing these little
pure functions: one to split the string, one to convert some numbers, one to
manipulate a list, one to match some patterns...gradually the broken-down
absractions get built back up via function composition. You can see the light at
the end of the tunnel, yes, yes! If you feed this list into that function that
returns a string you&#39;ll have the right value to print out!  Okay, now the
problem is solved in the pure functional world! The only thing left to do is...&#60;/p&#62;
&#60;p&#62;Now, the setup of the magic is complete. Now, you are onboard with the solution,
you thought the problem through with the magician...you are distracted. The
ending came so...quickly, but unexpected. What? You just feed your solution to
this &#60;code&#62;interact&#60;/code&#62; function and...that&#39;s it? I was expecting some &#60;code&#62;readLine&#60;/code&#62;s or
&#60;code&#62;print&#60;/code&#62;s (okay, at least 1 &#60;code&#62;print&#60;/code&#62; statement)!&#60;/p&#62;
&#60;p&#62;That&#39;s the thing: &#60;code&#62;interact&#60;/code&#62; deals with &#60;em&#62;two&#60;/em&#62; side effects, the input and the
output. But its user deals with &#60;em&#62;zero&#60;/em&#62;. It&#39;s as if the two effects &#38;quot;cancel&#38;quot; each
other out! It&#39;s a &#60;em&#62;neat&#60;/em&#62; trick, really. Small, low-key, easy to miss. But I&#39;m
glad I noticed it and come to appreciate its power and simplicity.&#60;/p&#62;
</description>
                <pubDate>Sat, 01 Sep 2018 11:08:57 -0700</pubDate>
                <link>https://duan.ca/2018/09/01/magical-interaction/</link>
                <guid isPermaLink="true">https://duan.ca/2018/09/01/magical-interaction/</guid>
            </item>
            <item>
                <title>A Tale of Two Dates</title>
                <description>&#60;p&#62;Recently, I discovered a curious thing about &#60;code&#62;Date&#60;/code&#62;s in two large projects
I work on. Simply put, both projects receives, from various HTTP endpoints, the
same object component: a timestamp, and a duration. Combining these two pieces,
both projects derives two &#60;code&#62;Foundation.Date&#60;/code&#62;s to represent a time range. So far,
so good.&#60;/p&#62;
&#60;p&#62;However, project &#60;code&#62;A&#60;/code&#62; uses &#60;code&#62;Fonudation.DateInterval&#60;/code&#62; to represent this concept,
while project &#60;code&#62;B&#60;/code&#62; uses &#60;code&#62;Range&#38;lt;Date&#38;gt;&#60;/code&#62;. But why? Why represent the same component
differently? What a gigantic waste of brain power for everyone on both projects!&#60;/p&#62;
&#60;p&#62;So I set out to unify this thing. Wherever a &#60;code&#62;Range&#60;/code&#62; literal is used, I swap in
&#60;code&#62;DateInterval.init(start:end:)&#60;/code&#62;; &#60;code&#62;Range.lowerBound&#60;/code&#62; becomes
&#60;code&#62;DateInterval.start&#60;/code&#62;; &#60;code&#62;Range.upperBound&#60;/code&#62; becomes &#60;code&#62;DateInterval.end&#60;/code&#62;, etc. It
didn&#39;t take long to complete the conversion to &#60;code&#62;DateInterval&#60;/code&#62; in project &#60;code&#62;B&#60;/code&#62;,
now it builds and runs!&#60;/p&#62;
&#60;p&#62;Oh, wait, why are some tests failing in project &#60;code&#62;B&#60;/code&#62;? Shouldn&#39;t this just be an
mechanical change?&#60;/p&#62;
&#60;p&#62;I spent time investigating. The failing tests are for some very specific
business logic that I&#39;m not familiar with. So things took a while to become
clear. What felt like a long time later, I realized my mistake.&#60;/p&#62;
&#60;p&#62;(I&#39;m sorry if this has been obvious to you. You are a better Swift programmer!)&#60;/p&#62;
&#60;p&#62;Somewhere in project &#60;code&#62;B&#60;/code&#62; is the following:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;struct Item {
    let range: Range&#38;lt;Date&#38;gt;
}

struct Container {
    let items: [Item]
}

func containerFactory(range: Range&#38;lt;Date&#38;gt;, items: [Item]) -&#38;gt; Container {
    /// pretend there&#39;s more code here

    return Conatiner(items: items.filter { $0.range.contains(range.lowerBound) })
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;And of course, after my &#38;quot;refactor&#38;quot;, it became&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;struct Item {
    let range: DateInterval
}

struct Container {
    let items: [Item]
}

func containerFactory(range: DateInterval, items: [Item]) -&#38;gt; Container {
    /// pretend there&#39;s more code here

    return Conatiner(items: items.filter { $0.range.contains(range.start) })
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Tests for &#60;code&#62;containerFactory&#60;/code&#62; failed. And here&#39;s why: &#60;strong&#62;&#60;code&#62;DateInterval.contains&#60;/code&#62;
is inclusive for its upper bound (&#60;code&#62;.end&#60;/code&#62;), whereas &#60;code&#62;Range.contains&#60;/code&#62; isn&#39;t!&#60;/strong&#62; You
can see it plainly by running the following&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;import Foundation

let sooner = Date(timeIntervalSince1970: 0)
let later = sooner.addingTimeInterval(1000)

DateInterval(start: sooner, end: later).contains(later) // true
(sooner..&#38;lt;later).contains(later)                        // false
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;So here&#39;s what stumped me:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;The 2 projects chose to interpret the same component differently, which
I didn&#39;t not expect.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;I didn&#39;t know how &#60;code&#62;Foundation.DateInterval&#60;/code&#62; works.&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Well, today I learned.&#60;/p&#62;
</description>
                <pubDate>Sat, 25 Aug 2018 17:11:43 -0700</pubDate>
                <link>https://duan.ca/2018/08/25/a-tale-of-two-dates/</link>
                <guid isPermaLink="true">https://duan.ca/2018/08/25/a-tale-of-two-dates/</guid>
            </item>
            <item>
                <title>Supporting Foundation.Data Without Depending On It</title>
                <description>&#60;p&#62;While implementing some file I/O APIs in &#60;a href=&#34;https://github.com/dduan/Pathos&#34;&#62;Pathos&#60;/a&#62;, I decided reading/writing
file content as &#60;code&#62;Foundation.Data&#60;/code&#62; is kind of important (can you blame me?). But
Pathos, by accident, does not depend on Swift &#60;code&#62;Foundation&#60;/code&#62;. Now what?&#60;/p&#62;
&#60;p&#62;After browsing the &#60;a href=&#34;https://developer.apple.com/documentation/foundation/data&#34;&#62;documentation&#60;/a&#62;, a pretty good solution emerged: &#60;code&#62;Data&#60;/code&#62; is
a sequence of bytes! Lets say we hand our users some bytes, they can easily
construct a &#60;code&#62;Data&#60;/code&#62; from it:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let content: [UInt8] = try readBytes(fromPath &#38;quot;/tmp/test&#38;quot;)
Data(bytes: content)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Okay, so this built-in initializer makes &#60;code&#62;[UInt8]&#60;/code&#62; an acceptable substitute for
returning &#60;code&#62;Data&#60;/code&#62;. What can we do about about &#60;code&#62;Data&#60;/code&#62; as input? Well, turns out,
&#60;code&#62;Data&#60;/code&#62; is a &#60;code&#62;Collection&#60;/code&#62; of &#60;code&#62;UInt8&#60;/code&#62;s! So we can accept &#60;code&#62;Data&#60;/code&#62; indirectly like
so:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func write&#38;lt;Bytes&#38;gt;(_ bytes: Bytes)
    where Bytes: Collection, Bytes.Element == UInt8
{
    // blah
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;User can pass in a &#60;code&#62;Data&#60;/code&#62; as argument and it just works™.&#60;/p&#62;
&#60;p&#62;The only disadvantage of supporting &#60;code&#62;Data&#60;/code&#62; in these ways is that it requires
your user to discover it either via your excellent documentation, or through
their super good knowledge of &#60;code&#62;Foundation&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Update: this could also &#60;a href=&#34;https://mastodon.social/@helge/100573358160444340&#34;&#62;be&#60;/a&#62; &#60;a href=&#34;https://twitter.com/daniel_dunbar/status/1030938273047179264&#34;&#62;slower&#60;/a&#62; than using Data directly. Luckily
I&#39;m only doing file I/O here.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;But this is pretty nice, regardless.&#60;/p&#62;
</description>
                <pubDate>Sat, 18 Aug 2018 11:00:41 -0700</pubDate>
                <link>https://duan.ca/2018/08/18/supporting-data-without-depending-on-it/</link>
                <guid isPermaLink="true">https://duan.ca/2018/08/18/supporting-data-without-depending-on-it/</guid>
            </item>
            <item>
                <title>Unix File Permissions In Swift</title>
                <description>&#60;p&#62;Wrap file permissions from &#60;code&#62;stat&#60;/code&#62; and &#60;code&#62;chmod&#60;/code&#62; in an &#60;code&#62;OptionSet&#60;/code&#62; in Swift.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/1ZrouR_F-AU&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
</description>
                <pubDate>Sun, 06 May 2018 16:43:20 -0700</pubDate>
                <link>https://duan.ca/2018/05/06/unix-file-permissions-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2018/05/06/unix-file-permissions-in-swift/</guid>
            </item>
            <item>
                <title>An Interpreter Without A Language</title>
                <description>&#60;p&#62;From the &#60;a href=&#34;/2018/01/13/coding-without-a-language/&#34;&#62;AST&#60;/a&#62; and &#60;a href=&#34;/2018/01/20/scopes/&#34;&#62;scopes&#60;/a&#62;, come a simple interpreter. This intepreter can &#38;quot;execute&#38;quot; the fibonacci
function AST and produce a correct results.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/C16PD44qyOY&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen=&#34;&#34;&#62;&#60;/iframe&#62;
&#60;/div&#62;
</description>
                <pubDate>Tue, 30 Jan 2018 12:53:38 -0800</pubDate>
                <link>https://duan.ca/2018/01/30/an-interpreter-without-a-language/</link>
                <guid isPermaLink="true">https://duan.ca/2018/01/30/an-interpreter-without-a-language/</guid>
            </item>
            <item>
                <title>Scopes Without A Language</title>
                <description>&#60;p&#62;A short video on the concept of static scope.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/o0jwyd8nUK4&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
</description>
                <pubDate>Sat, 20 Jan 2018 19:50:24 -0800</pubDate>
                <link>https://duan.ca/2018/01/20/scopes/</link>
                <guid isPermaLink="true">https://duan.ca/2018/01/20/scopes/</guid>
            </item>
            <item>
                <title>Coding Without A Language</title>
                <description>&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/OKjQtn_Gvug&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen=&#34;&#34;&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;p&#62;Sorry for the click-baity title. I actually really like this one.&#60;/p&#62;
</description>
                <pubDate>Sat, 13 Jan 2018 12:07:19 -0800</pubDate>
                <link>https://duan.ca/2018/01/13/coding-without-a-language/</link>
                <guid isPermaLink="true">https://duan.ca/2018/01/13/coding-without-a-language/</guid>
            </item>
            <item>
                <title>Scripting A &#39;cat&#39; Under 1 Minute</title>
                <description>&#60;p&#62;This video demonstrates a few things: the &#60;code&#62;readLine&#60;/code&#62; standard library function, scripting with Swift, and
pattern matching as loop conditions. Enjoy!&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/8rAqzvChbak&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
</description>
                <pubDate>Sat, 06 Jan 2018 18:34:39 -0800</pubDate>
                <link>https://duan.ca/2018/01/06/cat-under-1-minute/</link>
                <guid isPermaLink="true">https://duan.ca/2018/01/06/cat-under-1-minute/</guid>
            </item>
            <item>
                <title>Raw Coding Sessions</title>
                <description>&#60;p&#62;Planning, recording and editing a video is something I find very enjoyable to
do. However, I enjoy just working on stuff as well. So I&#39;ll occassionally post
videos of me doing just that: writing code, mumbling, with all my verbal ticks
and bad habits left unedited. Not sure who these videos are for but why the heck
not, amiright?&#60;/p&#62;
&#60;p&#62;The first one was scheduled to publish today, so I guess I should post something
about it.&#60;/p&#62;
&#60;iframe width=&#34;560&#34; height=&#34;315&#34;
src=&#34;https://www.youtube.com/embed/videoseries?list=PLuQ4I4VwboBw58RmXDbPGOUh4FQxyZ4UA&#34;
frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34;
allowfullscreen&#62;&#60;/iframe&#62;
</description>
                <pubDate>Sat, 06 Jan 2018 14:44:13 -0800</pubDate>
                <link>https://duan.ca/2018/01/06/raw-coding-session-videos/</link>
                <guid isPermaLink="true">https://duan.ca/2018/01/06/raw-coding-session-videos/</guid>
            </item>
            <item>
                <title>Hello World In WebAssembly</title>
                <description>&#60;p&#62;Every now and then, I check on the progress of Web Assembly. I did it again
around the time of this post and finally found enough tutorials, examples, and
working software to get myself started in this area. In doing so, I made a video
to demo some progress. (&#60;em&#62;this article includes all the same information and
more, so just read on if you don&#39;t have 15 minutes for YouTube&#60;/em&#62;).&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/yEYtwmI7bDg&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;br&#62;
&#60;h2&#62;Our goal:&#60;/h2&#62;
&#60;ol&#62;
&#60;li&#62;Use as much built-in tools on a Mac as possible. The web development
toolchain scares me.&#60;/li&#62;
&#60;li&#62;Target the browser. That&#39;s where the value of WebAssembly is. (Node supports
it as well. BUT, WHY THO?)&#60;/li&#62;
&#60;li&#62;Build from scratch. In the video I started from &#60;code&#62;mkdir&#60;/code&#62; a folder. We should
strive to understand details on every level whenever possible. Boilerplates
and dependencies should come later.&#60;/li&#62;
&#60;/ol&#62;
&#60;h2&#62;Things you&#39;ll need:&#60;/h2&#62;
&#60;ol&#62;
&#60;li&#62;Safari 11+&#60;/li&#62;
&#60;li&#62;Xcode. More specifically, you should be able to run &#60;code&#62;clang&#60;/code&#62; in a shell.&#60;/li&#62;
&#60;/ol&#62;
&#60;h2&#62;The Workflow&#60;/h2&#62;
&#60;p&#62;Having these things installed, get a copy of &#60;a href=&#34;https://github.com/WebAssembly/wabt&#34;&#62;The WebAssembly Binary
Toolkit&#60;/a&#62; (wabt). Build it. The README has detailed instructions. I just went
into the folder and ran&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;make clang-release
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This will generate a bunch of binary files in &#60;code&#62;out/clang/Release&#60;/code&#62; and you need
to make sure you can run them from wherever you want to work on WebAssembly
project (so either copy them into a folder included in your &#60;code&#62;PATH&#60;/code&#62; environment
variable or add the absolute path to &#60;code&#62;out/clang/Release&#60;/code&#62; to &#60;code&#62;PATH&#60;/code&#62;).&#60;/p&#62;
&#60;p&#62;Among the binaries &#38;quot;wabt&#38;quot; builds, &#60;code&#62;wat2wasm&#60;/code&#62; takes a &#60;code&#62;.wat&#60;/code&#62; file and compiles it
to a WebAssembly binary. A &#60;code&#62;.wat&#60;/code&#62; is a source file in the &#60;a href=&#34;https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format&#34;&#62;text format&#60;/a&#62; for
WebAssembly, which is in the form of S-expressions. So&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;wat2wasm main.wat -o main.wasm
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;…will compile your WebAssembly module in &#60;code&#62;main.wat&#60;/code&#62; to generate &#60;code&#62;main.wasm&#60;/code&#62;, the
binary file. For now, &#60;code&#62;main.wat&#60;/code&#62; can be the simplest WebAssembly program:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-lisp&#34;&#62;(module)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Running the binary in a browser demands the bulk of the work. First, we&#39;ll need
a web page. It doesn&#39;t need any content other than invoking some JavaScript
code.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-html&#34;&#62;&#38;lt;!DOCTYPE html&#38;gt;
&#38;lt;html lang=&#38;quot;en&#38;quot;&#38;gt;
&#38;lt;head&#38;gt;
    &#38;lt;meta charset=&#38;quot;UTF-8&#38;quot;&#38;gt;
    &#38;lt;title&#38;gt;&#38;lt;/title&#38;gt;
&#38;lt;/head&#38;gt;
&#38;lt;body&#38;gt;
    &#38;lt;!-- The only thing that matters is the following line,
    although having a valid HTML5 page is nice. --&#38;gt;
    &#38;lt;script src=&#38;quot;play.js&#38;quot;&#38;gt;&#38;lt;/script&#38;gt;
&#38;lt;/body&#38;gt;
&#38;lt;/html&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;First, the Javascript logic needs to &#60;em&#62;fetch and instantiate the compiled
WebAssembly module&#60;/em&#62;. Since this is not a JS or WebAssembly tutorial, I&#39;ll point
you to the docmuntation for &#60;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&#34;&#62;Fetch API&#60;/a&#62;, &#60;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&#34;&#62;Promises&#60;/a&#62;, and &#60;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly&#34;&#62;the WebAssembly
object&#60;/a&#62; for details:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-javascript&#34;&#62;fetch(&#38;quot;main.wasm&#38;quot;).then(reponse =&#38;gt;
    reponse.arrayBuffer()
).then(bytes =&#38;gt;
    WebAssembly.instantiate(bytes, {})
).then(result =&#38;gt;
    result.instance
).then(main);

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This snippet fetches &#60;code&#62;main.wasm&#60;/code&#62; (adjust this URL according to your choosing),
instantiate it, then pass it into a function named &#60;code&#62;main&#60;/code&#62;, we can put
a placeholder logic for it for now:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-javascript&#34;&#62;function main(wasm) {
    console.log(wasm);
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Before we move on, you&#39;ll find that simply opending your HTML file in browser
and looking at developer console won&#39;t work. Safari would complain about
cross-domain request error for &#60;code&#62;fetch&#60;/code&#62;. So we need to serve these resources
locally. I usually use the built in server module from Python standard library
for this kind of things:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;# In your source folder, run
python -m SimpleHTTPServer
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now go to &#60;a href=&#34;http://localhost:8000&#34;&#62;http://localhost:8000&#60;/a&#62; and click on your HTML file. If everything
went well, you should see a WebAssembly instance logged in the developer
console.&#60;/p&#62;
&#60;p&#62;Congratulations! You can start writing WebAssembly locally. Just remember to
re-compile &#60;code&#62;main.wat&#60;/code&#62; with &#60;code&#62;wat2wasm&#60;/code&#62; whenever you want to test things out in
browser.&#60;/p&#62;
&#60;h2&#62;An Actual &#38;quot;Hello, World!&#38;quot; Implementation&#60;/h2&#62;
&#60;p&#62;This is my implementation:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-lisp&#34;&#62;(module
  ;; Allocate a page of linear memory (64kb). Export it as &#38;quot;memory&#38;quot;
  (memory (export &#38;quot;memory&#38;quot;) 1)

  ;; Write the string at the start of the linear memory.
  (data (i32.const 0) &#38;quot;Hello, world!&#38;quot;) ;; write string at location 0

  ;; Export the position and length of the string.
  (global (export &#38;quot;length&#38;quot;) i32 (i32.const 12))
  (global (export &#38;quot;position&#38;quot;) i32 (i32.const 0)))
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In other words, we expose information of the linear memory we manipulated to the
JavaScript environment. Things that has been &#60;code&#62;export&#60;/code&#62;ed will show up as
properties of &#60;code&#62;exports&#60;/code&#62; of the &#60;code&#62;WebAssembly&#60;/code&#62; instance. We can access them in the
&#60;code&#62;main&#60;/code&#62; JavaScript functions:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-javascript&#34;&#62;function main(wasm) {
    const memory   = wasm.exports.memory;
    const length   = wasm.exports.length;
    const position = wasm.exports.position;
    ...
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Then it&#39;s just plain-old Javascript (tho I had to steal it from tutorials).
&#60;code&#62;memory.buffer&#60;/code&#62; is of type &#60;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer&#34;&#62;ArrayBuffer&#60;/a&#62;. We need to convert it into a string
and log it to the console:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-javascript&#34;&#62;function main(wasm) {
    const memory   = wasm.exports.memory;
    const length   = wasm.exports.length;
    const position = wasm.exports.position;

    const bytes = new Uint8Array(memory.buffer, position, length);
    const s = new TextDecoder(&#39;utf8&#39;).decode(bytes);

    console.log(s);
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Et, voilà! &#60;code&#62;Hello, World!&#60;/code&#62; hot off a Web Assembly module in your developer
console. To conclude, I personally like to use a &#60;code&#62;Makefile&#60;/code&#62; to streamline some
of the typing. Here&#39;s what I used for this demo:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-makefile&#34;&#62;compile:
	wat2wasm main.wat -o main.wasm

serve:
	python -m SimpleHTTPServer
&#60;/code&#62;&#60;/pre&#62;
&#60;h2&#62;Conclusion&#60;/h2&#62;
&#60;p&#62;No fancy schmancy Javascript build stack, no 3rd-party code dependency. Write
code, compile, run on your (virtual, in browser) machine, repeat. That sounds like
&#38;quot;assembly&#38;quot; to me!&#60;/p&#62;
</description>
                <pubDate>Sat, 30 Dec 2017 18:43:49 -0800</pubDate>
                <link>https://duan.ca/2017/12/30/hello-world-in-webassembly/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/30/hello-world-in-webassembly/</guid>
            </item>
            <item>
                <title>Building &#39;pwd&#39; Under 1 Minute In Swift</title>
                <description>&#60;p&#62;I guess I&#39;m starting a series of minute-long videos. In this first video, I built &#60;code&#62;pwd&#60;/code&#62; out of &#60;code&#62;getcwd&#60;/code&#62;. The
code turned out shorter than I imagined (1 line). Which is a good demonstration of Swift&#39;s great C-interop
capability.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/YR4MCcMnHrI&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;p&#62;Some details are lost in this video, however. For example, the POSIX standard actually says &#60;code&#62;getcwd&#60;/code&#62;&#39;s 2nd
argument being &#60;code&#62;0&#60;/code&#62; is undefined. Luckily, both macOS and Linux define it the way we want (allocate as much
memory as needed). Swift&#39;s handling of &#60;code&#62;char *&#60;/code&#62; aka &#60;code&#62;UnsafeMutablePointer&#38;lt;CChar&#38;gt;&#60;/code&#62; in context of a &#60;code&#62;var&#60;/code&#62; array
is also very cool.&#60;/p&#62;
</description>
                <pubDate>Wed, 27 Dec 2017 01:13:07 -0800</pubDate>
                <link>https://duan.ca/2017/12/27/building-pwd-under-1-minute-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/27/building-pwd-under-1-minute-in-swift/</guid>
            </item>
            <item>
                <title>Contributing To Open-Source Swift</title>
                <description>&#60;p&#62;I discover, report, fix and merge a bug in the open-source Foundation project. And why, yes, on YouTube.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/rwuj80W8TtI&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;ul&#62;
&#60;li&#62;Pull request: &#60;a href=&#34;https://github.com/apple/swift-corelibs-foundation/pull/1376&#34;&#62;https://github.com/apple/swift-corelibs-foundation/pull/1376&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;SR-6647: &#60;a href=&#34;https://bugs.swift.org/browse/SR-6647&#34;&#62;https://bugs.swift.org/browse/SR-6647&#60;/a&#62;&#60;/li&#62;
&#60;/ul&#62;
</description>
                <pubDate>Sat, 23 Dec 2017 13:21:10 -0800</pubDate>
                <link>https://duan.ca/2017/12/23/contributing-to-open-source-foundation/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/23/contributing-to-open-source-foundation/</guid>
            </item>
            <item>
                <title>Smart Color Invert And Your iOS Apps</title>
                <description>&#60;ol&#62;
&#60;li&#62;&#60;a href=&#34;#introduction&#34;&#62;Introduction&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;#the-basics&#34;&#62;The Basics&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;#compatibility-with-older-ios-versions&#34;&#62;Compatibility with older iOS versions&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;#how-to-screenshot-with-inverted-color-settings&#34;&#62;How to screenshot with inverted color settings&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;#conclusion&#34;&#62;Conclusion&#60;/a&#62;&#60;/li&#62;
&#60;/ol&#62;
&#60;h2&#62;Introduction&#60;/h2&#62;
&#60;p&#62;Apple sneakily shipped a &#38;quot;dark mode&#38;quot; in iOS 11, native apps looks &#60;em&#62;gorgeous&#60;/em&#62; in this mode (especially on
iPhone X with it&#39;s OLED display):&#60;/p&#62;
&#60;img src=&#34;/assets/2017/12/native-ios-apps-with-smart-invert.png&#34; srcset=&#34;/assets/2017/12/native-ios-apps-with-smart-invert.png 2x&#34; alt=&#34;iOS 11 apps in smart invert mode&#34;/&#62;
&#60;p&#62;To see it for yourself, go to &#60;em&#62;Settings -&#38;gt; General -&#38;gt; Accessibility Display Accommodations -&#38;gt; Invert Colors&#60;/em&#62;
and toggle the switch to on (I personally set triple tap of the power buttton to toggle this on/off):&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/invert-color-settings.png&#34; alt=&#34;turn on smart invert mode in Settings&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Note that in Apple&#39;s first-party apps, not every view&#39;s color is inverted (hence, &#38;quot;smart&#38;quot;). For apps that we
built, that would not be the case automatically. Instead, we get the full color inversion under this setting:&#60;/p&#62;
&#60;img src=&#34;/assets/2017/12/third-party-app-no-change.png&#34; srcset=&#34;/assets/2017/12/third-party-app-no-change.png 2x&#34; alt=&#34;default third party app before and after smart color&#34;/&#62;
&#60;p&#62;In this article, we&#39;ll see how to best adapt our apps so they look just as good as first-party iOS apps under
the smart invert setting.&#60;/p&#62;
&#60;h2&#62;The Basics&#60;/h2&#62;
&#60;p&#62;&#60;em&#62;TL;DR: use &#60;a href=&#34;https://developer.apple.com/documentation/uikit/uiview/2865843-accessibilityignoresinvertcolors&#34;&#62;accessibilityIgnoresInvertColors&#60;/a&#62; on your &#60;code&#62;UIView&#60;/code&#62;s to prevent their color to be
inverted.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;iOS 11 introduced &#60;code&#62;accessibilityIgnoresInvertColors&#60;/code&#62;, a property on &#60;code&#62;UIView&#60;/code&#62;. From the &#60;a href=&#34;https://developer.apple.com/documentation/uikit/uiview/2865843-accessibilityignoresinvertcolors&#34;&#62;offical
documentation&#60;/a&#62;:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;If inverting the colors would have a negative impact on your view&#39;s content, set this property to true to
prevent it from inverting its colors. Setting the property to true prevents the system from inverting the
colors of the view and all of its subviews.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;So, for views containing photos or videos with real-world content, we probably want to set it to &#60;code&#62;true&#60;/code&#62;. In
our sample app&#39;s source code:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/setting-accessibilityIgnoresInvertColors-to-true-in-code.png&#34; alt=&#34;setting accessibilityIgnoresInvertColors to true in code&#34; /&#62;&#60;/p&#62;
&#60;p&#62;This gives us the desired effect for that view 🎉:&#60;/p&#62;
&#60;img src=&#34;/assets/2017/12/smart-invert-in-code-result.png&#34; srcset=&#34;/assets/2017/12/smart-invert-in-code-result.png 2x&#34; alt=&#34;result of supporting invert color in code&#34;/&#62;
&#60;p&#62;The same can be done in Interface Builder. Let&#39;s fix the other view by setting a runtime attribute:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/setting-accessibilityIgnoresInvertColors-to-true-in-interface-builder.png&#34; alt=&#34;setting accessibilityIgnoresInvertColors to true in Interface Builder&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Result:&#60;/p&#62;
&#60;img src=&#34;/assets/2017/12/smart-invert-in-interface-builder-result.png&#34; srcset=&#34;/assets/2017/12/smart-invert-in-interface-builder-result.png 2x&#34; alt=&#34;result of supporting invert color in interface builder&#34;/&#62;
&#60;p&#62;Tada!&#60;/p&#62;
&#60;h2&#62;Compatibility with older iOS versions&#60;/h2&#62;
&#60;p&#62;The story gets slightly complicated when your app need to run on older iOS versions. For one, our code won&#39;t
compile:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/compile-error-on-older-oses.png&#34; alt=&#34;compile error on older iOS versions&#34; /&#62;&#60;/p&#62;
&#60;p&#62;But that&#39;s nothing new to iOS developers, really. We can fix that with a &#60;code&#62;#available&#60;/code&#62;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/fix-compile-error.png&#34; alt=&#34;fix compile error on older iOS versions&#34; /&#62;&#60;/p&#62;
&#60;p&#62;When you run the app in older iOS devices or simulators, Xcode will complain about our runtime attribute as
well:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/xcode-complain-about-runtime-attirbute.png&#34; alt=&#34;Xcode complains about runtime attribute on older iOS&#34; /&#62;&#60;/p&#62;
&#60;p&#62;If that bothers you, I recommend writing your own wrapper for this property as an extension to &#60;code&#62;UIView&#60;/code&#62;. To
put a cherry on top, make it &#60;code&#62;@IBInspectable&#60;/code&#62;!&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;extension UIView {
    /// Whether or not to set accessibilityIgnoresInvertColors to true for iOS 11.
    /// For older OS, this value is false and setting it has no effect.
    @IBInspectable
    public var ignoreColorInversion: Bool {
        get {
            if #available(iOS 11, *) {
                return self.accessibilityIgnoresInvertColors
            }

            return false
        }

        set {
            if #available(iOS 11, *) {
                self.accessibilityIgnoresInvertColors = newValue
            }
        }
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Having this snippet in the project, we set it in interface builder to any view with a couple of clicks:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/set-custom-invert-property-in-interface-builder.png&#34; alt=&#34;set custom invert color properties in Interface Builder&#34; /&#62;&#60;/p&#62;
&#60;h2&#62;How to screenshot with inverted color settings&#60;/h2&#62;
&#60;p&#62;Here&#39;s a bonus hint: screenshots taken on device won&#39;t have their color inverted even if you have the setting
set to &#38;quot;on&#38;quot;! Go ahead, try it :).&#60;/p&#62;
&#60;p&#62;To show off our handy work for supporting smart invert color, we&#39;ll need
some other means to take screenshots. All screenshots in this article is taken using QuickTime on a Mac. So
plug in your iOS device, open QuickTime Player, in menu select &#60;em&#62;File -&#38;gt; New Movie Recording&#60;/em&#62; and select your
device from the drop-down menu by clicking the arrow next to the record button:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/12/select-ios-device-in-quicktime-player.png&#34; alt=&#34;Select iOS device for screenshots in QuickTime Player&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Now you can screen shot the QuickTime Player window the normal way.&#60;/p&#62;
&#60;h2&#62;Conclusion&#60;/h2&#62;
&#60;p&#62;You can &#60;a href=&#34;/assets/2017/12/SmartInvert.zip&#34;&#62;download the sample project&#60;/a&#62; and play with it.&#60;/p&#62;
&#60;p&#62;Smart invert is awesome and I personally wish all 3rd-party apps will update their apps for it as time goes
on. If your favorite app (including your own!) doesn&#39;t support it properly, please consider informing the
developer about &#60;a href=&#34;https://developer.apple.com/documentation/uikit/uiview/2865843-accessibilityignoresinvertcolors&#34;&#62;accessibilityIgnoresInvertColors&#60;/a&#62;, or just send this article their way!&#60;/p&#62;
</description>
                <pubDate>Wed, 20 Dec 2017 13:17:44 -0800</pubDate>
                <link>https://duan.ca/2017/12/20/smart-invert-support-for-you-app/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/20/smart-invert-support-for-you-app/</guid>
            </item>
            <item>
                <title>BitArray The Final Act</title>
                <description>&#60;p&#62;Alas, there&#39;s the 3rd and last video about &#60;code&#62;BitArray&#60;/code&#62;, originated on my spark of inspiration on a Caltrain
ride home. This makes my first YouTube playlist as well, even tho the first 2 videos were planned to be
completely separate.&#60;/p&#62;
&#60;p&#62;We added more standard library functionalities to BitArray (ExpressibleByArrayLiteral,
CustomStringConvertible, Equatable, etc). Then, we added documentation and other open-source things left
undone from &#38;quot;episode 2&#38;quot;.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/ckrd_FoFMl0&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
</description>
                <pubDate>Tue, 19 Dec 2017 12:17:49 -0800</pubDate>
                <link>https://duan.ca/2017/12/19/bitarray-final-act/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/19/bitarray-final-act/</guid>
            </item>
            <item>
                <title>Making An Open-Source Swift Project</title>
                <description>&#60;p&#62;This video shows what it takes to open source a Swift project. Starting from some code in a playground,
I created a framework that supports distribution via Swift Package Manager, CocoaPods, Xcode project and
Carthage. The framework can be used across iOS, macOS, watchOS, tvOS and Linux. In addition, we also added
SwiftLint to the project, added a Makefile, put everything on GitHub and set up continuous integration via
Travis. README, COC, LICENSE and CHANGELOG are stubbed in as well.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/pA0T1CdqMt8&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;p&#62;This is not at all a comprehensive list of things a good Open Source project should have. We are still missing
the version tag, documentation generation, automatic Carthage binary generation, test coverage...&#60;/p&#62;
&#60;p&#62;Anyways, here&#39;s some stuff mentioned in the video:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;Sample project from the video: &#60;a href=&#34;https://github.com/dduan/BitArray&#34;&#62;https://github.com/dduan/BitArray&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;Video of me writing the code in this project: &#60;a href=&#34;https://www.youtube.com/watch?v=-k_jrIoD56k&#34;&#62;https://www.youtube.com/watch?v=-k_jrIoD56k&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;Swift Package Manager: &#60;a href=&#34;https://swift.org/package-manager/&#34;&#62;https://swift.org/package-manager/&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;CocoaPods: &#60;a href=&#34;https://cocoapods.org&#34;&#62;https://cocoapods.org&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;Carthage: &#60;a href=&#34;https://github.com/Carthage/Carthage&#34;&#62;https://github.com/Carthage/Carthage&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;Xcconfigs for universal framework: &#60;a href=&#34;https://github.com/mrackwitz/xcconfigs&#34;&#62;https://github.com/mrackwitz/xcconfigs&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;SwiftLint: &#60;a href=&#34;https://github.com/realm/SwiftLint&#34;&#62;https://github.com/realm/SwiftLint&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;Travis CI: &#60;a href=&#34;https://travis-ci.org&#34;&#62;https://travis-ci.org&#60;/a&#62;&#60;/li&#62;
&#60;/ul&#62;
</description>
                <pubDate>Sun, 17 Dec 2017 21:24:43 -0800</pubDate>
                <link>https://duan.ca/2017/12/17/making-an-open-source-swift-project/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/17/making-an-open-source-swift-project/</guid>
            </item>
            <item>
                <title>Let&#39;s Build A BitArray In Swift</title>
                <description>&#60;p&#62;In this video, I build a space-efficient BitArray that confirms to &#60;code&#62;RandomAccessCollection&#60;/code&#62; in Swift in
a playground. It involves some basic (but neat!) bitwise manipulation tricks.&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;https://www.youtube.com/embed/-k_jrIoD56k&#34; frameborder=&#34;0&#34; gesture=&#34;media&#34; allow=&#34;encrypted-media&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;p&#62;I guess I&#39;m a YouTuber now. You can subscribe to my &#60;a href=&#34;https://www.youtube.com/channel/UCkBVC0dMgyUnxzettP7qE-A&#34;&#62;channel&#60;/a&#62; 😛.&#60;/p&#62;
</description>
                <pubDate>Tue, 12 Dec 2017 22:51:04 -0800</pubDate>
                <link>https://duan.ca/2017/12/12/lets-build-a-bitarray-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/12/lets-build-a-bitarray-in-swift/</guid>
            </item>
            <item>
                <title>List Comprehension In Swift</title>
                <description>&#60;p&#62;Let&#39;s explore ways to add list comprehension to Swift.&#60;/p&#62;
&#60;h2&#62;Motivation&#60;/h2&#62;
&#60;p&#62;&#60;a href=&#34;https://en.wikipedia.org/wiki/List_comprehension&#34;&#62;List comprehension&#60;/a&#62; should be no stranger to a Python or (and?) Haskell user. It&#39;s a really compact syntax
that deals with &#60;a href=&#34;https://en.wikipedia.org/wiki/Cartesian_product&#34;&#62;Cartesian product&#60;/a&#62; of lists. In the case of Python, it&#39;s probably responsible for the lack
of evolution of lambda expressions, since it&#39;s much nicer to write one-liners with it in place of &#60;code&#62;map&#60;/code&#62;s and
&#60;code&#62;filter&#60;/code&#62;s.&#60;/p&#62;
&#60;p&#62;Here&#39;s an example of an list comprehension in Haskell from Wikipedia:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-haskell&#34;&#62;a = [(x,y) | x &#38;lt;- [1..5], y &#38;lt;- [3..5]]
-- [(1,3),(1,4),(1,5),(2,3),(2,4) ...
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In this example, a list of pair of integers is constructed from 2 lists of integers.&#60;/p&#62;
&#60;p&#62;Here is what that example would be in Python:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-python&#34;&#62;a = [(x, y) for x in range(1,6) for y in range(3, 6)]
# [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4) ...
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Here&#39;s what it would be in mathematics (except we are dealing with sets, not lists, but I&#39;ll only refer to
lists from here on.):&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Let (a, b) be an ordered list of elements

{(x, y)|x ∈ {1,2,3,4,5}, y ∈ {3,4,5}}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;One can filter out unwanted elements with predicates, and apply arbitrary functions to elements of the
result. Let&#39;s say we only want even numbers from the first list, and we want the sum of x and y, continuing on
our examples:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-haskell&#34;&#62;a = [x+y | x &#38;lt;- [1..5], y &#38;lt;- [3..5], x `mod` 2 == 0]
&#60;/code&#62;&#60;/pre&#62;
&#60;pre&#62;&#60;code class=&#34;language-python&#34;&#62;a = [x + y for x in range(1,6) for y in range(3, 6) if x % 2 == 0]
&#60;/code&#62;&#60;/pre&#62;
&#60;pre&#62;&#60;code&#62;{x+y|x ∈ {1,2,3,4,5}, y ∈ {3,4,5}, x is even}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In theory, this syntax can be applied to an arbitrary number of lists. Putting aside how often this need comes
up in day-to-day programming in your domain, it should be obvious that it&#39;s alternative, be it nested loops or
&#60;code&#62;map&#60;/code&#62;s and &#60;code&#62;filter&#60;/code&#62;s, is pretty clumsy in comparison.&#60;/p&#62;
&#60;h2&#62;Adding List Comprehension in Swift&#60;/h2&#62;
&#60;p&#62;A comprehension can be considered in 3 parts:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;some lists, each may contain a different type of elements.&#60;/li&#62;
&#60;li&#62;a predicate (or a series of them joined logically) to filter out elements.&#60;/li&#62;
&#60;li&#62;a function to process the combination of elements into results.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;In Swift, if our input is only one list, there&#39;s a pretty sweet way to achieve that:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;list.filter(predicate).map(processor)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To make comprehension work with more lists, we have some syntax options.&#60;/p&#62;
&#60;h3&#62;Option One&#60;/h3&#62;
&#60;p&#62;The &#38;quot;brute force&#38;quot; option would be a function that parameterize all 3 parts of the comprehension. Such as&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// going with order of appearance in Python/Haskell syntax
func comprehension&#38;lt;Element, List, Result&#38;gt;(
    predicate: (Element) -&#38;gt; Bool,
    list: List,
    processor: (Element) -&#38;gt; Result
) where
    List: Sequence, List.Element == Element

{
    // implementation
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To supporting more than one list, just add more parameters to both types and the function itself.&#60;/p&#62;
&#60;p&#62;(Can&#39;t wait until we can have &#60;a href=&#34;https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#variadic-generics&#34;&#62;variadic generic parameters&#60;/a&#62;!)&#60;/p&#62;
&#60;h3&#62;Option Two&#60;/h3&#62;
&#60;p&#62;Deploy more syntax tricks. Somehow make it visually similar to the math/Haskell/Python notation. If we can
accept some temporary data structure and introduce/implement some operators, there&#39;d be many possibilities.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;/// Just an example of the infinite possibilities.
processor | list0 &#38;amp;&#38;amp;&#38;amp; list1 | predicate
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;I&#39;ll leave the implementation of this example as an exercise to the reader.&#60;/p&#62;
&#60;h3&#62;Option That I Like&#60;/h3&#62;
&#60;p&#62;I spent quite some time exploring the realm of possibilities in &#38;quot;option two&#38;quot;. However, introducing data
structures and custom operators just to do what &#38;quot;option one&#38;quot; offers seems really unappealing. It&#39;s not
entirely clear that doing so would be &#38;quot;Swift-y&#38;quot; anyways! Eventually, I did find an arrangement that fits in
Swift, and requires no fancy syntax trickery.&#60;/p&#62;
&#60;p&#62;The result of list comprehension is a list. The goal of this operation is to &#60;em&#62;construct&#60;/em&#62; a list. Yep, thinking
along this line, it became obvious that using a &#38;quot;list&#38;quot;&#39;s initializer is just natural:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let a = Array(1..&#38;lt;5, 3..&#38;lt;5, where: { n, _ in n % 2 == 0 }) { ($0, $1) }
// [(2,3),(2,4),(2,5) ...
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The processing function is at the end to take advantage of the trailing closure syntax. It&#39;s nicer when
there&#39;s not predicate:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;let a = Array(1..&#38;lt;5, 3..&#38;lt;5) { ($0, $1) }
// [(1,3),(1,4),(1,5),(2,3),(2,4) ...
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This syntax seems both succinct and Swift-y.&#60;/p&#62;
&#60;p&#62;I put an implementation on &#60;a href=&#34;https://github.com/dduan/Comprehension&#34;&#62;github&#60;/a&#62;, in case you find it useful.&#60;/p&#62;
&#60;h2&#62;Parting Thoughts&#60;/h2&#62;
&#60;p&#62;There&#39;s no doubt that the conclusion in this post is imperfect. Though it feels more Swift-y, it deviates from
the mathematical syntax by a lot. We can only implement it for finite number of lists. When many lists are
involved, using a embedded closure as the predicate would make the compiler complain that the expression is
too complex. We suffer from the normal woes with Swift closures where anonymous arguments (&#60;code&#62;$0&#60;/code&#62;, &#60;code&#62;$1&#60;/code&#62;, etc)
won&#39;t work unless the last one is mentioned in the closure&#39;s body. Overloading &#60;code&#62;Array&#60;/code&#62; initializer may
negatively affect compilation speed in large projects.&#60;/p&#62;
&#60;p&#62;Not all of these issues are temporary.&#60;/p&#62;
&#60;p&#62;Does list comprehension warrant a language change in Swift? Can you think of better ways to implement it
with the current compiler?&#60;/p&#62;
</description>
                <pubDate>Sat, 09 Dec 2017 12:26:30 -0800</pubDate>
                <link>https://duan.ca/2017/12/09/list-comprehension-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2017/12/09/list-comprehension-in-swift/</guid>
            </item>
            <item>
                <title>Building Swift Projects In Source Compatibility Mode</title>
                <description>&#60;p&#62;It&#39;s a few weeks before WWDC, so naturally¹ it&#39;s time to try build your Swift
projects in the compiler&#39;s compatibility mode!&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;Download and install a snapshot for the next major version &#60;a href=&#34;https://swift.org/download/&#34;&#62;on
Swift.org&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/05/download-swift-snapshot.png&#34; alt=&#34;download swift toolchain&#34; /&#62;
&#60;img src=&#34;/assets/2017/05/install-swift-snapshot.png&#34; alt=&#34;install swift toolchain&#34; /&#62;&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Choose the newly installed toolchain in Xcode.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/05/choose-toolchain.png&#34; alt=&#34;choose swift toolchain in Xcode&#34; /&#62;&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Ask the compiler to use compatibility mode. This means using the complier
flag &#60;code&#62;-swift-version X&#60;/code&#62;, where &#38;quot;X&#38;quot; is the &#60;em&#62;current&#60;/em&#62; major Swift version.&#60;/p&#62;
&#60;p&#62;In project&#39;s &#38;quot;Build Settings&#38;quot;, value for &#38;quot;Other Swift Flags&#38;quot; should
contain &#60;code&#62;-swift-version X&#60;/code&#62;. This could mean setting it in Xcode, in
&#60;code&#62;.xcconfig&#60;/code&#62; files you are using and/or in your dependency managers such
as Cocoapods.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/05/compat-mode-flag.png&#34; alt=&#34;compatibility flag in xcode&#34; /&#62;&#60;/p&#62;
&#60;p&#62;For example, with Cocoapods, you&#39;ll need to add the following in your
&#60;code&#62;Podfile&#60;/code&#62; to compile 3rd party libraries in compatibility mode:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62; post_install do |installer|
     installer.pods_projects.targets.each do |target|
         target.build_configurations.each do |config|
             config.build_settings[&#38;quot;OTHER_SWIFT_FLAGS&#38;quot;] = &#38;quot;$(inherited) -swift-version 3&#38;quot;
         end
     end
 end
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Build your project! This is where things start to get exciting.&#60;/p&#62;
&#60;p&#62;You should expect some warnings. Hopefully they are self-explanatory
enough. Most of them should correspond to &#60;a href=&#34;https://apple.github.io/swift-evolution/&#34;&#62;a swift-evolution
proposal&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;Improvement to the language or compiler usually means some of these
warnings tell you problems in your code that has been ignored by the
compiler previously. Fix them today!&#60;/p&#62;
&#60;p&#62;The project should compile successfully in compatibility mode (despite
warnings). This where you can stop reading. Go celebrate with your
coworkers, friends, and family!&#60;/p&#62;
&#60;p&#62;Things could go wrong for compiler snapshots, of course. Read on if see
errors or crashes (whaaaaat 😸).&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;It&#39;s time to tell the compiler team about the error or crash you encountered.&#60;/p&#62;
&#60;p&#62;Reduce the error or crash to a state that your are comfortable reporting in
public. Then go to &#60;a href=&#34;https://bugs.swift.org&#34;&#62;bugs.swift.org&#60;/a&#62; and file a JIRA
ticket describing the error or compiler crash.&#60;/p&#62;
&#60;p&#62;During the process of code reduction you may find ways to work around the
compile error or crash. Make the changes for the workaround and repeat
steps 4-5. Maybe your project will compile this time.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;The issue you discovered will be fixed in the official Swift release come
fall. You&#39;ve ensured a smooth Swift upgrade for your project and contributed
to the Swift community 🎉!&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;hr /&#62;
&#60;p&#62;¹ source compatibility mode is a thing starting with Swift 4. As new
major version of Swift is released, code written in the previous version should
compile without change in compatibility mode.&#60;/p&#62;
</description>
                <pubDate>Mon, 22 May 2017 09:04:01 -0700</pubDate>
                <link>https://duan.ca/2017/05/22/build-in-swift-compatibility-mode/</link>
                <guid isPermaLink="true">https://duan.ca/2017/05/22/build-in-swift-compatibility-mode/</guid>
            </item>
            <item>
                <title>Replying To Old Mailing List Threads</title>
                <description>&#60;p&#62;&#60;em&#62;One common complains on the Swift Evolution mailing list is about its
inscrutable interface. If you see an inactive thread on the web archive but
haven&#39;t subscribed, there seems to be no way to participate or &#38;quot;revive&#38;quot; it
since you never received any of its emails.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;&#60;em&#62;With a &#60;a href=&#34;https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031537.html&#34;&#62;hint&#60;/a&#62; and some experiments, I&#39;ve discovered that there is
a way. This post reveals the magic step by step (without commenting on the
merits of email or this solution).&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Like HTTP, Email is a text-based &#60;a href=&#34;https://tools.ietf.org/html/rfc2822&#34;&#62;protocol&#60;/a&#62;. Unlike HTTP, we directly
consume payloads of this protocol and, as a consequence, don&#39;t think much about
that very fact.&#60;/p&#62;
&#60;p&#62;Like HTTP, each email includes headers hidden by normal email clients. Each
header is essentially two strings, a key and a value, separated by a colon.
Among these headers are &#60;code&#62;Message-Id&#60;/code&#62; and &#60;code&#62;In-Reply-To&#60;/code&#62;. When we tell our email
client applications to start a reply, they take the value from &#60;code&#62;Message-Id&#60;/code&#62;
and use it as value for &#60;code&#62;In-Reply-To&#60;/code&#62; automatically.&#60;/p&#62;
&#60;p&#62;To observe all this in action, we can open some emails with our favorite text
editors and look for these headers. Of course, this require us to know where the
emails exist as files. On macOS, an easy thing to do is to drag from Mail.app to
Finder/Desktop and open the resulting .eml file:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/02/open-email.gif&#34; alt=&#34;Open an email in text editors&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Among the (perhaps overwhelming amount of) headers, we&#39;ll find the two fields we
are looking for:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/02/email-headers.png&#34; alt=&#34;Email Headers Message-Id and In-Reply-To&#34; /&#62;&#60;/p&#62;
&#60;p&#62;… I&#39;ll leave the clients&#39; reply behavior regarding these fields for the reader
to verify.&#60;/p&#62;
&#60;p&#62;Mailing list software such as GNU Mailman, which &#60;a href=&#34;https://swift.org&#34;&#62;swift.org&#60;/a&#62; and &#60;a href=&#34;http://llvm.org&#34;&#62;llvm.org&#60;/a&#62;
use to host various mailing lists, associate emails in threads by chaining them
with the headers explained above, among other things. As long as we have
a message&#39;s &#60;code&#62;Message-Id&#60;/code&#62;, we can reply to it &#38;quot;officially&#38;quot; by adding its value to
the &#60;code&#62;In-Reply-To&#60;/code&#62; header in our email, regardless of whether we have received
that email ourselves previously.&#60;/p&#62;
&#60;p&#62;So here are the steps to reply retroactively to a mailing list thread.&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;&#60;strong&#62;find &#60;code&#62;Message-Id&#60;/code&#62; of the mailing list message we want to reply to.&#60;/strong&#62;&#60;/p&#62;
&#60;p&#62;This value is contained in the mailing list web archive&#39;s &#60;code&#62;mailto&#60;/code&#62; link.
Unfortunately Mail.app doesn&#39;t recognize it. It&#39;s easy enough to find it
ourselves though:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2017/02/find-message-id.gif&#34; alt=&#34;Finding Message-Id on mailman archive&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Note the &#60;code&#62;&#38;lt;&#60;/code&#62;, &#60;code&#62;&#38;gt;&#60;/code&#62;, &#60;code&#62;@&#60;/code&#62; characters are percent-quoted. We have to recover the
id values to the format
&#60;code&#62;&#38;lt;alphanumerics-potentially-separated-by-dash@address.com&#38;gt;&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;Another way to acquire this value is from the gzip&#39;d archive. There they
just exist as plain text. The downside is you have to dig out the message
itself first.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;&#60;strong&#62;Add &#60;code&#62;In-Reply-To&#60;/code&#62; header to our email.&#60;/strong&#62;&#60;/p&#62;
&#60;p&#62;Draft a new email, make its title the same as our email chain&#39;s title (this
is a good idea because lots of email &#60;em&#62;clients&#60;/em&#62; do use the title to thread
messages). Set the appropriate recipients, and CCs, including the mailing
list&#39;s address. Now save this email as draft and open it in a text editor as
we did in our investigations.  Add in the line
&#60;code&#62;In-Reply-To: &#38;lt;id-we-found-in-step-one.address.com&#38;gt;&#60;/code&#62;, save it. Then send this
email (for example, open it with Mail.app and use Message-&#38;gt;Send Again in the
menu).&#60;/p&#62;
&#60;p&#62;Of course, some email client &#60;a href=&#34;http://www.pixelbeat.org/docs/thunderbird-threading.html&#34;&#62;supports&#60;/a&#62; adding it
from their GUI.&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;You&#39;ll find the in addition to functioning as an normal message to the
recipients, the mailing list will properly put your message to the original
thread (in the case of swift-evolution, only if your reply is within the same
week).&#60;/p&#62;
</description>
                <pubDate>Tue, 07 Feb 2017 10:21:19 -0800</pubDate>
                <link>https://duan.ca/2017/02/07/replying-to-old-mailing-list-threads/</link>
                <guid isPermaLink="true">https://duan.ca/2017/02/07/replying-to-old-mailing-list-threads/</guid>
            </item>
            <item>
                <title>Site Improvements</title>
                <description>&#60;p&#62;I spent a whole day making changes to this site.&#60;/p&#62;
&#60;p&#62;You may notice a new section is now added: &#60;a href=&#34;/links&#34;&#62;links&#60;/a&#62;. Yes,
I want a link list format for this site. Often I find stuff that&#39;s insightful
and not always visible. I want to collect those and bookmark them here.
Modelling after &#60;a href=&#34;http://daringfireball.net&#34;&#62;Daring Fireball&#60;/a&#62;, I&#39;ve added a new
&#60;a href=&#34;http://duan.ca/articles/feed.xml&#34;&#62;feed&#60;/a&#62; which only contains long-form,
original articles. I&#39;ll be tagging the links so that they show up along side my
normal posts in tag pages. Each tag page now gets its own feed! You can read
about it in the &#60;a href=&#34;/&#34;&#62;about page&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;A few small issues has been fixed.&#60;/p&#62;
&#60;p&#62;I wrote the most Ruby in my life today. Yay?&#60;/p&#62;
</description>
                <pubDate>Mon, 16 Jan 2017 23:24:13 -0800</pubDate>
                <link>https://duan.ca/2017/01/16/site-changes/</link>
                <guid isPermaLink="true">https://duan.ca/2017/01/16/site-changes/</guid>
            </item>
            <item>
                <title>Making TUI Applications In Swift</title>
                <description>&#60;p&#62;One of my fondest memory in programming is writing the game Snake on one of
these:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2016/12/e-dictionary.jpg&#34; alt=&#34;An Electronic/Digital Dictionary&#34; /&#62;&#60;/p&#62;
&#60;p&#62;At the time, I was in a very restrictive school where a real computer wasn&#39;t
permited in class. The actual thing (that&#39;s an &#38;quot;electronic dictionary&#38;quot; by the
way) was probably older, slower and of a different brand than the one in the
photo. In fact, I didn&#39;t know how to make a copy of the code, and the device
wasn&#39;t even mine. So the game just stayed there when the device was returned to
the owener and its fate unknown.&#60;/p&#62;
&#60;p&#62;But I love it nontheless. Design the game, write it, playing it, showing it off&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;everything.&#60;/li&#62;
&#60;/ul&#62;
&#60;br /&#62;
&#60;p&#62;Fastforward to today. I use and write software applications for a living.
Programs I use directly range from terminal commands to GUI apps and web apps in
a browser.&#60;/p&#62;
&#60;p&#62;Some programs, however, don&#39;t belong to those categories: vim, tig, irssi, etc.
They run in a terminal like CLI commands. But unlike commands like &#60;code&#62;ls&#60;/code&#62;, they
take over the entire buffer to offer different modes of interaction. You can
use hotkeys to navigate menus, trigger functions and so on.  Sometimes you can
use mouse, too. Their layout often resemble that of a GUI application running in
it&#39;s own &#38;quot;window&#38;quot;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2016/12/tig.png&#34; alt=&#34;tig&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Just to make things painfully clear, these apps&#39;s interface is composed
exclusively of text. We can vaguely categorize them as &#38;quot;Text-based User
Interface(TUI)&#38;quot; application.&#60;/p&#62;
&#60;p&#62;There are many reasons to like TUI applications. Compared to a CLI program,
they can display information in 2-dimentional, more organized layout (aka more
like a GUI app). Unlike a GUI application, they almost only require a terminal
to run. If you ssh onto a Linux server on your iPad, they&#39;d work the same as
running locally on a Mac. For people who live in terminal simulators, it&#39;s nice
to run apps that don&#39;t open a new Window. Oh, they often tend to look the same
no matter how your OS changes.&#60;/p&#62;
&#60;p&#62;Most importantly, they remind me of the programs I built on that electronic
dictionary. I want to make them today, with my favorite programming language
Swift!&#60;/p&#62;
&#60;br /&#62;
&#60;p&#62;The go-to library for writing TUI apps is &#60;a href=&#34;https://www.gnu.org/software/ncurses/&#34;&#62;ncurses&#60;/a&#62;. Classics such as vim,
emacs and mutt were written with it to some degree. But I find it hard to dive
into: it has a large number of strange legacy function names and offers
pre-built UI elements like panels, menus, forms etc. The terminal in my mind is
a spread of characters that can be updated by me. That sounds fun. Ncurses seems
more like UIKit :P.&#60;/p&#62;
&#60;p&#62;Luckily, I found the fun library: &#60;a href=&#34;https://github.com/nsf/termbox&#34;&#62;termbox&#60;/a&#62; by &#60;a href=&#34;https://github.com/nsf&#34;&#62;nsf&#60;/a&#62;. Termbox offers around
a dozen functions that gives us size of the terminal, a way to update text at
a row/column coordinates, and user inputs in forms of key-presses and
mouse-clicks. And that&#39;s it!&#60;/p&#62;
&#60;p&#62;After making &#60;a href=&#34;https://github.com/dduan/Termbox&#34;&#62;a Swift wrapper&#60;/a&#62;, I was able to build a painter app in
&#60;a href=&#34;https://github.com/dduan/TerminalPaint&#34;&#62;a handleful of lines&#60;/a&#62;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2016/12/terminal-paint.png&#34; alt=&#34;terminal paint&#34; /&#62;&#60;/p&#62;
&#60;p&#62;So that&#39;s an TUI app drawing according to mouse clicks built with only a few
primitives from termbox. Awww yeah! Here&#39;s the code with the comment stripped,
to give you a taste:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;import Termbox
func printAt(x: Int32, y: Int32, text: String,
    foreground: Attributes = .default,
    background: Attributes = .default)
{
    let border = Termbox.width

    for (c, xi) in zip(text.unicodeScalars, x ..&#38;lt; border) {
        Termbox.put(x: xi, y: y, character: c,
            foreground: foreground, background: background)
    }
}

func updateHelp(drawing: UnicodeScalar) {
    let lastY = Termbox.height - 1
    let content = [
        &#38;quot;Drawing [\(drawing)]&#38;quot;,
        &#38;quot;Press other character to change&#38;quot;,
        &#38;quot;Use mouse to draw&#38;quot;,
        &#38;quot;Press &#39;q&#39; to quit&#38;quot;
    ].joined(separator: &#38;quot; | &#38;quot;)

    let filler = String(repeating: &#38;quot; &#38;quot;,
        count: Int(Termbox.width) - content.unicodeScalars.count)

    printAt(x: 0, y: lastY, text: content + filler,
        foreground: .white, background: .blue)
}

func paint() {
    do {
        try Termbox.initialize()
    } catch let error {
        print(error)
        return
    }
    Termbox.inputModes = [.esc, .mouse]

    var drawingCharacter: UnicodeScalar = &#38;quot;.&#38;quot; {
        didSet {
            updateHelp(drawing: drawingCharacter)
        }
    }

    updateHelp(drawing: drawingCharacter)

    Termbox.present()

    outer: while true {
        guard let event = Termbox.pollEvent() else {
            continue
        }

        switch event {
        case let .character(_, value):
            if value == &#38;quot;q&#38;quot; {
                break outer
            }

            drawingCharacter = value

        case let .key(_, value):
            if value == .space {
                drawingCharacter = &#38;quot; &#38;quot;
            }

        case let .mouse(x, y):
            Termbox.put(x: x, y: y,
                character: drawingCharacter,
                foreground: .red)
        default:
            continue
        }

        Termbox.present()
    }

    Termbox.shutdown()
}

paint()
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/dduan/Termbox&#34;&#62;Library&#60;/a&#62; and this &#60;a href=&#34;https://github.com/dduan/TerminalPaint&#34;&#62;app&#60;/a&#62; are both on Github. Go and
have fun :)&#60;/p&#62;
</description>
                <pubDate>Mon, 26 Dec 2016 21:39:05 -0800</pubDate>
                <link>https://duan.ca/2016/12/26/making-tui-programs-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2016/12/26/making-tui-programs-in-swift/</guid>
            </item>
            <item>
                <title>Rebase And Sign Multiple Git Commits</title>
                <description>&#60;p&#62;I never bothered &#60;a href=&#34;https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work&#34;&#62;signing&#60;/a&#62; my git commits until Github started putting
those shiny badges on them. Since then I&#39;ve encountered a problem: rebased
commits lose their hash and their signed-ness.&#60;/p&#62;
&#60;p&#62;That&#39;s not a big deal for a single commit. Just run &#60;code&#62;git commit -S --amend --no-edit&#60;/code&#62; after rebase. And that commit, which is at &#60;code&#62;HEAD&#60;/code&#62; will have a new
hash and be signed.&#60;/p&#62;
&#60;p&#62;What if we have more than one commit to rebase? My instinctive answer was sign
the one on &#60;code&#62;HEAD&#60;/code&#62;, then use interactive rebase to rotate the next one on top and
sign it, repeat until each one is signed and reorder them. But that doesn&#39;t work
at all because a commit&#39;s position in history is part of its content. That means
after a commit is rebased, it and every commits following it will have a new
hash and git doesn&#39;t give us an oppurtunity to say &#38;quot;include my signature,
please&#38;quot;. You cannot rebase and keep the commits signed!&#60;/p&#62;
&#60;p&#62;Well, that kind of sucks. But you are reading about it here, so I&#39;d better give
you something to help, right?&#60;/p&#62;
&#60;p&#62;There is, at least, one way to achieve &#60;em&#62;rebase and sign multiple commits&#60;/em&#62;:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;Run interactive rebase: &#60;code&#62;git rebase -i branch&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Mark all commits and &#38;quot;edit&#38;quot; or &#38;quot;e&#38;quot;.&#60;/li&#62;
&#60;li&#62;Git now stops at every commit for you to make changes. This is an oppurtunity
to sign it! &#60;code&#62;git commit -S --amend --no-edit&#60;/code&#62;, just like how you would sign
&#60;code&#62;HEAD&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;&#60;code&#62;git rebase --continue&#60;/code&#62;, move on the next commit until all every one is
edited.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;There&#39;s virtually nothing you cannot do with git. Hence the reputation for it&#39;s
glorious UI, ya know?&#60;/p&#62;
</description>
                <pubDate>Sat, 24 Dec 2016 01:31:14 -0800</pubDate>
                <link>https://duan.ca/2016/12/24/rebase-multiple-git-commits-with-signing/</link>
                <guid isPermaLink="true">https://duan.ca/2016/12/24/rebase-multiple-git-commits-with-signing/</guid>
            </item>
            <item>
                <title>How To Omit Needless Words</title>
                <description>&#60;p&#62;A typical experience in adopting Swift 3 may look like this:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;Run the migrator.&#60;/li&#62;
&#60;li&#62;Fix up what the migrator left undone so your project complies.&#60;/li&#62;
&#60;li&#62;Remove artifacts that migrator added to ensure successful compilation (you
know what this means if you finished previous step in a mildly sized code
base).&#60;/li&#62;
&#60;li&#62;Fix bugs caused by mechanical changes.&#60;/li&#62;
&#60;li&#62;Try to adapt your code base to the new style: lowercased static members, etc.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;The last step is particularly challenging in a team environment because it
involves naming things. Luckily we have (IMHO) the best &#38;quot;features&#38;quot; in Swift
3 for help: the &#60;a href=&#34;https://swift.org/documentation/api-design-guidelines/&#34;&#62;API Design Guidelines&#60;/a&#62;.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;&#60;a href=&#34;https://swift.org/documentation/api-design-guidelines/#omit-needless-words&#34;&#62;Omit needless words&#60;/a&#62; is one of the most differentiating
guideline for function names between Swift 2 and 3. In Swift 2 we used to name
things like so…&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;func doStuffWithThing(thing: Thing) { … }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;… and use it like …&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;doStuffWithThing(someThing)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;That&#39;s a lot of &#38;quot;thing&#38;quot;s, have you noticed?&#60;/p&#62;
&#60;p&#62;Since the word &#38;quot;Thing&#38;quot; is &#60;em&#62;merely repeating&#60;/em&#62; the type information, we can omit
it in Swift 3:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;// declare
func doStuff(with thing: Thing) { … }

// use
doStuff(with: someThing)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It&#39;s clear at both declaration and use site what we are doing stuff to.&#60;/p&#62;
&#60;p&#62;So … you should go through you code base and make this change! In the next
section, we&#39;ll discuss one way to make it happen.&#60;/p&#62;
&#60;hr /&#62;
&#60;h2&#62;Step 1: Automate&#60;/h2&#62;
&#60;p&#62;A good indicator of &#38;quot;merely repeating type information&#38;quot; is repetition of words.
If you have been disciplined about naming your functions in Swift 2, finding
such repetition should take no more than one or two good regular expressions.
After the migrator, your code may contain a mixture of these:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func doStuffWithX(_: X) { … }
func doStuff(forY y: Y) { … }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In other words, the repeating word (&#60;code&#62;X&#60;/code&#62; or &#60;code&#62;Y&#60;/code&#62;) is preceded by a
&#60;a href=&#34;https://web.archive.org/web/20161006012135/https://www.englishclub.com/grammar/prepositions-list.htm&#34;&#62;preposition&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;Finding these in a large code base is quite fun. If you don&#39;t feel like writing
the scripts yourself, I&#39;ve made a little tool for it &#60;a href=&#34;https://github.com/dduan/needless&#34;&#62;here&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;(Sometimes the repeating words aren&#39;t a exact match because of prefixes such as
&#38;quot;CG&#38;quot; in &#60;code&#62;CGSize&#60;/code&#62;. That&#39;s covered by the tool as well.)&#60;/p&#62;
&#60;h2&#62;Step 2: Update&#60;/h2&#62;
&#60;p&#62;You can further rearrange the pieces in function name mechanically to:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func doStuff(preposition originalArgName: Type) { … }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The &#60;a href=&#34;https://github.com/dduan/needless&#34;&#62;tool&#60;/a&#62; I wrote can suggest alternatives like this. Applying them
is technically automatable. But I find manually doing tasks such as fixing up
indentation for multi-line functions or updating their use site to be easier.
Your conclusion may depend the size of your code base and your patience.&#60;/p&#62;
&#60;h2&#62;Step 3: Audit&#60;/h2&#62;
&#60;p&#62;The main goal for the API Design Guidelines is &#38;quot;clarity at the point of use&#38;quot;.
Our automated process will yield some undesirable results. I&#39;ll list a few
scenarios here.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;Poorly named function name becomes poorer&#60;/strong&#62;. Example:
&#60;code&#62;alertForScreenSize(_ size CGRize)&#60;/code&#62; becomes &#60;code&#62;alert(forScreen size: CGSize)&#60;/code&#62;.
Obviously, &#38;quot;for screen&#38;quot; is misleading since a &#60;code&#62;CGSize&#60;/code&#62; is not a screen. The
problem here is the &#38;quot;alert&#38;quot; is not for a &#38;quot;size&#38;quot; to begin with. We as human
intuitively pick up that it&#39;s for a &#38;quot;screen with a certain size&#38;quot;. So the correct
renaming here should be &#60;code&#62;alertForScreen(with size: CGSize)&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;Awkward literal values results in ungrammatical phrases&#60;/strong&#62;. Imagine our
argument is a enum:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Mode {
  case add
  case edit
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;… and we renamed a function &#60;code&#62;updateUIForMode(mode: Mode)&#60;/code&#62; to
&#60;code&#62;update(for mode: Mode)&#60;/code&#62;. The call site, therefore, becomes
&#60;code&#62;update(for: .add)&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;What makes it feels wrong? Well, a preposition followed by a verb (&#38;quot;for add&#38;quot;)
is not very grammatical. Normally we would say &#38;quot;update UI for &#60;em&#62;adding&#60;/em&#62;&#38;quot;. So here
we need to update the literals in that enum to &#38;quot;adding&#38;quot; and &#38;quot;editing&#38;quot;.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;Type information becomes too weak&#60;/strong&#62;. This can happen very often with enum
literals. We often name enum values with an adjective to qualify its name:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum UIControlState {
    case automatic // which state? the *automatic* state!
    …
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;After renaming, we&#39;ll have functions that simply becomes too generic and
mysterious at call site:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;update(for: .automatic) // automatic what? 😂
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is where we need to be flexible and use our own good judgement. Perhaps
it&#39;s simply better to keep the qualifying postfix:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;update(forControlState: .automatic) // better
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;In the guideline&#39;s parlance, this is &#60;a href=&#34;https://swift.org/documentation/api-design-guidelines/#weak-type-information&#34;&#62;compensate for weak type
information&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;Other argument labels needs updates too&#60;/strong&#62;. A function at call site should read
like a sentence as much as possible. We removed words at beginning of the
&#38;quot;sentence&#38;quot;, it&#39;s important to take a look at labels for the rest of the sentence
and ensure the whole thing fits together.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;There are &#60;em&#62;many&#60;/em&#62;, &#60;em&#62;many&#60;/em&#62; other fallouts from mechanically omitting needless
words that I didn&#39;t cover in this post. There are many many other things in the
API Design Guidelines that are worth conforming to. There will be much much bike
shedding among your team members.&#60;/p&#62;
&#60;p&#62;Just remember, the API guidelines don&#39;t provide an answer to every naming
decision. Following it means your code base will fit in with the rest of the
community and APIs from Foundation/Swift standard library. But find what feels
right for your team is the most important thing. In the end, you should be glad
that everyone cares so much about your code base&#39;s &#38;quot;Swiftness&#38;quot; and it&#39;ll be all
worth it!&#60;/p&#62;
</description>
                <pubDate>Sat, 22 Oct 2016 17:08:41 -0700</pubDate>
                <link>https://duan.ca/2016/10/22/how-to-omit-needless-words/</link>
                <guid isPermaLink="true">https://duan.ca/2016/10/22/how-to-omit-needless-words/</guid>
            </item>
            <item>
                <title>Distribution Tests</title>
                <description>&#60;p&#62;There are several ways to build dependencies for a Swift 3 project:
Swift Package Manager, Cocoapods, Carthage, etc. Many have an opinion on which
is the best choice for their projects. As a library author who want to help as
many people as possible, however, they can&#39;t ignore any of them.&#60;/p&#62;
&#60;p&#62;I sometimes question the sanity of that conclusion: instead of becoming an
export in each package manager, I find myself a novice of all. Did I break
support for any of them with this project change? Is it still working on
a particular platform, say, tvOS? Can I &#60;em&#62;really&#60;/em&#62; know?&#60;/p&#62;
&#60;p&#62;The only way to &#60;em&#62;really&#60;/em&#62; know is to verify yourself: both Cocoapods and
Carthage support four platforms -- iOS, macOS, watchOS, tvOS; Swift Package
Manager only works on Mac or Linux. So that&#39;s 2*4+1=9 targets. All these
targets need is have the library in question fetched and imported. Every Swift
library author should have such verification before publishing updates of
their project.&#60;/p&#62;
&#60;p&#62;The steps to verify can be triggered with commands: fetch and build
dependencies, build Xcode/Swift project. To automate the process, put these
commands in a script or a Makefile. But wait, there&#39;s more! One shouldn&#39;t have
to create these dummy projects every time they create a new library. If all
these projects do is importing a library and attempt to build, they should
work for &#60;em&#62;any&#60;/em&#62; library. The config in &#60;code&#62;Package.swift&#60;/code&#62;/&#60;code&#62;Cocoapods&#60;/code&#62;/&#60;code&#62;Cartfile&#60;/code&#62;
and the &#60;code&#62;import&#60;/code&#62; statements just needs some strings replaced: name of the next
library, URL for its git repository, etc. And that&#39;s a scriptable process as
well!&#60;/p&#62;
&#60;p&#62;To recap, one could, in theory, copy in some dummy projects, run a command to
inject information about a new library, run another command to build all these
project, verifying that support for those package managers remain functional.&#60;/p&#62;
&#60;p&#62;In reality, I have created &#60;a href=&#34;https://github.com/dduan/DistributionTests&#34;&#62;DistributionTests&#60;/a&#62; and put it
on &#60;a href=&#34;https://github.com/dduan/DistributionTests&#34;&#62;Github&#60;/a&#62; 😉.&#60;/p&#62;
&#60;p&#62;The script &#60;code&#62;customize&#60;/code&#62; requires 3 pieces of information of the library: its
import name, its git repository URL and a major version number. The assumption
here is the library generates uniformly named artifacts: the file name for
&#60;code&#62;.framework&#60;/code&#62; and the name users use to import it are the same. Testing
distribution of a library is as simple as:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;clone the project.&#60;/li&#62;
&#60;li&#62;customize the project with &#60;code&#62;customize&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;run &#60;code&#62;make&#60;/code&#62;.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;If you do step 1 and 2, include the projects in library&#39;s repository, then
only step 3 is necessary! This makes testing distribution methods trivial on
a continuous integration server.&#60;/p&#62;
&#60;p&#62;Go forth and create fearlessly!&#60;/p&#62;
</description>
                <pubDate>Mon, 10 Oct 2016 10:34:49 -0700</pubDate>
                <link>https://duan.ca/2016/10/10/distribution-tests/</link>
                <guid isPermaLink="true">https://duan.ca/2016/10/10/distribution-tests/</guid>
            </item>
            <item>
                <title>A Case For OOP?</title>
                <description>&#60;p&#62;Python&#39;s standard library includes a very handy &#60;code&#62;defaultdict&#60;/code&#62;. It behaves
almost exactly like the standard dictionary except it&#39;ll supply a pre-defined
value for any non-existence keys. It is, unsurpringly, a subclass of &#60;code&#62;dict&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;I find my self missing this handy container in Swift. Especially when I use
a normal &#60;code&#62;Dictionary&#60;/code&#62; to accumulate/coalesce values under distinct keys. So I
wrote my own:&#60;/p&#62;
&#60;script src=&#34;https://gist.github.com/dduan/31ed39c4c98ecb88290f0743cb394c20.js&#34;&#62;&#60;/script&#62;
&#60;p&#62;There are a few noticable things about this implementation:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;It does not conform to the &#60;code&#62;DictionaryLiteralConvertible&#60;/code&#62; protocol, for no
good reasons, really. The initializer in this protocol takes a varadic
argument. There&#39;s no conevient way to forward this array to a normal
dictionary&#39;s initializer (incidentally, this is a Swift feature I really
want). Plus, I don&#39;t need &#60;code&#62;DefaultDictionary&#60;/code&#62; to be a literal convertible.&#60;/li&#62;
&#60;li&#62;Most of the code, including the imaginary &#60;code&#62;init&#60;/code&#62; mentioned in previous
point, simply reuses stuff from &#60;code&#62;Dictionary&#60;/code&#62;: asscociated type, indexes,
generator, subscript, etc.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;In comparison, Python implements &#60;code&#62;defaultdict&#60;/code&#62; in a more intuitive way -- via
inheritance.&#60;/p&#62;
&#60;p&#62;But do we want inheritance for &#60;code&#62;struct&#60;/code&#62;s and &#60;code&#62;enum&#60;/code&#62;s in Swift? What does that
even mean? Is it simply a case that will go away when protocols become more
powerful?&#60;/p&#62;
</description>
                <pubDate>Thu, 19 May 2016 12:03:02 -0700</pubDate>
                <link>https://duan.ca/2016/05/19/a-case-for-oop/</link>
                <guid isPermaLink="true">https://duan.ca/2016/05/19/a-case-for-oop/</guid>
            </item>
            <item>
                <title>Cheap Orders</title>
                <description>&#60;p&#62;How to create order? If the second law of thermal dynamics tells us anything,
we&#39;d better get to work, right?
{: .lead}&#60;/p&#62;
&#60;p&#62;Before going full existential, let&#39;s limit &#38;quot;order&#38;quot; to Swift&#39;s set and
dictionaries -- there is none. Of course, you can take values/keys out and
sort them. But what if all you care about is &#60;em&#62;some&#60;/em&#62; order?&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;Recently, I wrote&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Token {
  static let all = [
    &#38;quot;=&#38;quot;: .Equal,
    &#38;quot;-&#38;quot;: .Minus,
    // more token mappings …
  ]
  case Equal
  case Minus
  // more tokens …
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;… in the hope that I can take each value from &#60;code&#62;Token.all.keys&#60;/code&#62; and see if
a prefix of a string is a matching token. It started to fail as the tokens
expands to multiple characters:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Token {
  static let all = [
    &#38;quot;=&#38;quot;: .Equal,
    &#38;quot;-&#38;quot;: .Minus,
    // more token mappings …
    &#38;quot;==&#38;quot;: .Equality,
    &#38;quot;-&#38;gt;&#38;quot;: .Arrow,
    // more token mappings …
    &#38;quot;===&#38;quot;: .Identity,
    // more token mappings …
  ]
  case Equal
  case Minus
  case Equality
  case Arrow
  case Identity
  // … more tokens …
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;-&#38;gt;&#60;/code&#62; could get a match with &#60;code&#62;-&#60;/code&#62; and &#60;code&#62;===&#60;/code&#62; would match to either &#60;code&#62;==&#60;/code&#62; or &#60;code&#62;=&#60;/code&#62;,
etc.&#60;/p&#62;
&#60;p&#62;Since the tokens in this exercise have at most 3 characters, I decided to
group them by length and match from the longer group first. The groups became:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Token {
  static private let group1 = [
    &#38;quot;=&#38;quot;: .Equal,
    &#38;quot;-&#38;quot;: .Minus,
    // more token mappings …
  ]

  static private let group2 = [
    &#38;quot;==&#38;quot;: .Equality,
    &#38;quot;-&#38;gt;&#38;quot;: .Arrow,
    // more token mappings …
  ]

  static private let group3 = [
    &#38;quot;===&#38;quot;: .Identity,
    // more token mappings …
  ]
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now I can choose which group to take values first. There&#39;s a way to do it
without adding some control flow logic:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;[group3.keys, group2.keys, group3.keys].flatten()
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Even better, I&#39;ll make it a lazy property…&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Token {
  static var all = {
    [group3.keys, group2.keys, group3.keys].flatten()
  }()
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;…except an important piece of information is missing from the property: what&#39;s
&#60;code&#62;all&#60;/code&#62;&#39;s type? Turns out, it&#39;s become&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;FlattenCollection&#38;lt;Array&#38;lt;LazyMapCollection&#38;lt;Dictionary&#38;lt;String, Token&#38;gt;, String&#38;gt;&#38;gt;&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Ahh, it seems that in the pursue of cheap, lazy creation of these structures,
we are forced to deal with a bunch of type wrappers, each having a good reason
to be here!&#60;/p&#62;
&#60;p&#62;But I really just need something like &#60;code&#62;Array&#38;lt;String&#38;gt;&#60;/code&#62; for the consumer. If
only there&#39;s a way to make all this stuff go away from my type signature, as
if they are &#60;a href=&#34;http://robnapier.net/erasure&#34;&#62;erased&#60;/a&#62; :).&#60;/p&#62;
&#60;p&#62;Okay, I&#39;m talking about &#60;code&#62;AnySequence&#60;/code&#62; now. Rob Napier has an excellent post on
this topic &#60;a href=&#34;http://robnapier.net/erasure&#34;&#62;here&#60;/a&#62; if you need to catch up. Our
code eventually end up like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Token {
  static var all: AnySequence&#38;lt;String&#38;gt; = {
    AnySequence(
      [group3.keys, group2.keys, group3.keys]
        .flatten())
  }()
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Instead of &#60;code&#62;Array&#38;lt;String&#38;gt;&#60;/code&#62;, we have an &#60;code&#62;AnySequence&#38;lt;String&#38;gt;&#60;/code&#62;. Our tokens now
gets checked with the correct order. We didn&#39;t need to sort the entire set of
tokens, nor did we do any heavy data massage upfront, making a bunch of copies
along the way.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;Looking back, this post really failed to capture the eureka moment as I came
up with the erasure method. I discovered a series of small challenges and got
help from Swift&#39;s designers in each step. Everything fell together in the end.&#60;/p&#62;
</description>
                <pubDate>Sun, 15 May 2016 17:42:27 -0700</pubDate>
                <link>https://duan.ca/2016/05/15/cheap-orders/</link>
                <guid isPermaLink="true">https://duan.ca/2016/05/15/cheap-orders/</guid>
            </item>
            <item>
                <title>Deploy Jekyll Site To Github With Make</title>
                <description>&#60;p&#62;At risks of being too meta, I want to talk about how this post is going to go
from my computer to a repository on Github on both the &#60;code&#62;master&#60;/code&#62; and &#60;code&#62;gh-pages&#60;/code&#62;
branch. The former contains the file I&#39;m typing, and the latter an updated
HTML site generated by Jekyll.&#60;/p&#62;
&#60;p&#62;Here&#39;s how: I type &#60;code&#62;make deploy&#60;/code&#62; once I commit this file in my local
repository.&#60;/p&#62;
&#60;p&#62;I spent a day to set up a Jekyll site. The last part involves deploying it to
Github, my preferred way to host a static site. There are a lot of posts and
scripts on how to achieve it. And Github seems to have an &#38;quot;afficial&#38;quot; support
for Jekyll site that disables plugin scripts (understandably so).&#60;/p&#62;
&#60;p&#62;But having worked with git and make for all these years made me immune to all
the fanciness the Internet tries to sell.&#60;/p&#62;
&#60;p&#62;Here&#39;s my script for deploying a Jekyll project to Github pages:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;DEPLOY_PATH=/tmp/jekyll_deploy
build:
	jekyll build

deploy:
	git checkout -f gh-pages
	git clean -d -x -f
	git pull
	git checkout master
	jekyll build
	rm -rf ${DEPLOY_PATH}
	mkdir ${DEPLOY_PATH}
	cp -R .git ${DEPLOY_PATH}
	cd ${DEPLOY_PATH}; git checkout gh-pages; git clean -d -x -f
	cp -R _site/* ${DEPLOY_PATH}
	cd ${DEPLOY_PATH}; git add .; git commit -m &#38;quot;`curl whatthecommit.com/index.txt`&#38;quot;
	cd ${DEPLOY_PATH}; git push -f origin gh-pages
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Drop it into root of your Jekyll project, commit all changes (including the
&#60;code&#62;Makefile&#60;/code&#62;). And type &#60;code&#62;make deploy&#60;/code&#62;. BOOM, done.&#60;/p&#62;
&#60;p&#62;There are a couple of assumptions:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;You build the site in the &#60;code&#62;_site&#60;/code&#62; folder&#60;/li&#62;
&#60;li&#62;You store Jekyll source on &#60;code&#62;master&#60;/code&#62; and have the &#60;code&#62;gh-pages&#60;/code&#62; branch up.&#60;/li&#62;
&#60;li&#62;You can build the site by running &#60;code&#62;jekyll build&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;You don&#39;t care about commit message on the deploy branch.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;I like it better than other methods because it does not require installing
additional software/scripts and there&#39;s no restriction on plugins.&#60;/p&#62;
</description>
                <pubDate>Sun, 15 May 2016 01:00:00 -0700</pubDate>
                <link>https://duan.ca/2016/05/15/deploy-jekyll-to-github/</link>
                <guid isPermaLink="true">https://duan.ca/2016/05/15/deploy-jekyll-to-github/</guid>
            </item>
            <item>
                <title>char ** in Swift</title>
                <description>&#60;p&#62;A &#38;quot;string&#38;quot; in C is just a continuous chunk of &#60;code&#62;char&#60;/code&#62; values in memory with
&#60;code&#62;\0&#60;/code&#62; at the end. To reference it, a variable of type &#60;code&#62;char *&#60;/code&#62; is used to store
the address of the first &#60;code&#62;char&#60;/code&#62; (commonly known as a pointer 😉).  It&#39;s common
to have string manipulating functions take this form:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;void foo(char **errorMessage) {
    // ...
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To mutate the arugment &#60;code&#62;errorMessage&#60;/code&#62; of type &#60;code&#62;char *&#60;/code&#62;, &#60;code&#62;foo&#60;/code&#62; takes a pointer
to it, &#60;code&#62;(char *)*&#60;/code&#62;.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;How do we call &#60;code&#62;foo&#60;/code&#62; in Swift?&#60;/p&#62;
&#60;p&#62;Here&#39;s the tl;dr. We can wrap it in a Swift function that have the same
interface:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func fooSwift(inout errorMessage: String?) {
    var message: UnsafeMutablePointer&#38;lt;CChar&#38;gt; = nil

    foo(&#38;amp;message)
    errorMessage = String.fromCString(message)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;errorMessage&#60;/code&#62; will contain whatever our C function &#60;code&#62;foo&#60;/code&#62; assigns to it.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;So, what&#39;s really going on here?&#60;/p&#62;
&#60;p&#62;Inspecting &#60;code&#62;foo&#60;/code&#62;&#39;s signature in Swift, we see&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func foo(errorMessage: UnsafeMutablePointer&#38;lt;UnsafeMutablePointer&#38;lt;CChar&#38;gt;&#38;gt;)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;… okey, &#60;code&#62;errorMessage&#60;/code&#62;&#39;s type is little intimidating to someone who doesn&#39;t
use C functions in Swift everyday (like me)!&#60;/p&#62;
&#60;p&#62;Let&#39;s break it down. Swift does a ton of work for us to interoperate with C:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;&#60;code&#62;CChar&#60;/code&#62; is Swift&#39;s name for &#60;em&#62;&#60;code&#62;char&#60;/code&#62; in C&#60;/em&#62; (shocking, amiright?)&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;&#60;code&#62;UnsafeMutablePointer&#38;lt;Type&#38;gt;&#60;/code&#62; roughly translates to &#60;code&#62;Type *&#60;/code&#62;, so
syntactically, we can see why
&#60;code&#62;UnsafeMutablePointer&#38;lt;UnsafeMutablePointer&#38;lt;CChar&#38;gt;&#38;gt;&#60;/code&#62; is used to bridge the
C type &#60;code&#62;(char *)*&#60;/code&#62;.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;A function that takes &#60;code&#62;UnsafeMutablePointer&#38;lt;Type&#38;gt;&#60;/code&#62; argument accepts
&#60;code&#62;inout Type&#60;/code&#62; values. Therefore, we can look at &#60;code&#62;foo&#60;/code&#62; as&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;foo(inout errorMessage: UnsafeMutablePointer&#38;lt;CChar&#38;gt;)
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Swift acknowledge C&#39;s string representation and provides convenient
methods for converting &#60;code&#62;char *&#60;/code&#62; / &#60;code&#62;UnsafeMutablePointer&#38;lt;CChar&#38;gt;&#60;/code&#62; to its own
&#60;code&#62;String&#60;/code&#62; type (&#60;code&#62;String.fromCString()&#60;/code&#62;).&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Hopefully you can see how &#60;code&#62;fooSwift&#60;/code&#62; works now.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;Taking a step back, to deal with &#60;code&#62;char **&#60;/code&#62; in Swift, we overcame 2 obstacles:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;The difference in string representation between C and Swift.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Compared to C pointers, Swift&#39;s &#60;code&#62;inout&#60;/code&#62; expresses mutability of function
arguments in a more restricted way. We can&#39;t nest &#60;code&#62;inout&#60;/code&#62;s to represent
the infinite layers of indirections that pointers achieve.&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
</description>
                <pubDate>Sun, 01 Nov 2015 11:18:40 -0800</pubDate>
                <link>https://duan.ca/2015/11/01/char-star-star-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2015/11/01/char-star-star-in-swift/</guid>
            </item>
            <item>
                <title>Let&#39;s Play LLVM in Swift: Setup</title>
                <description>&#60;p&#62;&#60;em&#62;The prospect of Swift being open-source excites me. In preparation for it, I
decided to learn a little bit about LLVM. In the offical &#60;a href=&#34;http://llvm.org/docs/tutorial/index.html&#34;&#62;tutorial&#60;/a&#62;, C++
and OCaml are used to create a programming language. So I asked myself: why not
Swift? As you&#39;ll see in this post, Swift is as good as any language when it
comes to leveraging LLVM.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;LLVM is an &#38;quot;compiler infrastructure&#38;quot;. As a user, that translates to &#38;quot;a set of
libraries to help us create programming language and tools&#38;quot;. Since this is
not an introduction to the LLVM project, it suffices to say that LLVM makes
creating programming language easy: give your language in &#60;a href=&#34;http://llvm.org/docs/LangRef.html&#34;&#62;LLVM IR&#60;/a&#62; form
and you get the rest of a native/JIT language for free, optimization included!&#60;/p&#62;
&#60;p&#62;LLVM&#39;s default API is in C++. In addition, it officially offers a C wrapper.
Lucky for us, Swift is C-interoperable – no bridging necessary :)&#60;/p&#62;
&#60;p&#62;Now we arrive at our goal for this post: create an Xcode project that can make
calls into LLVM&#39;s C API, aka to compile this single line of code:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;let module = LLVMModuleCreateWithName(&#38;quot;my_module&#38;quot;)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;I assume you have Xcode 7.1 installed on OS X 10.11, but no more.&#60;/p&#62;
&#60;h2&#62;1. Getting LLVM&#60;/h2&#62;
&#60;p&#62;There are a lot of materials on the internet dedicated to setting up an LLVM
environment. As we are not working &#60;em&#62;on&#60;/em&#62; LLVM itself, and we are not on some
crazy custom Linux environment (to be fair, it&#39;s trivial to set LLVM up on
most major Linux distributions), the &#60;a href=&#34;http://llvm.org/releases/download.html&#34;&#62;pre-built Clang binaries&#60;/a&#62; is good
enough. Download and unpack the .tar file somewhere handy in on your hard
drive. For example, I put it at &#60;code&#62;$(HOME)/usr/local/clang-3.4&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;Aaaand we&#39;re done. We have LLVM.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;Sidenote: Xcode installs clang the compiler, but a lot of LLVM tools are
missing. That&#39;s why we need a separate LLVM/Clang setup.&#60;/em&#62;&#60;/p&#62;
&#60;h2&#62;2. Create an Xcode Project&#60;/h2&#62;
&#60;p&#62;Create a new OS X - Command Line Tool Xcode project, choose Swift as it&#39;s
language.&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/10/llvm-swift-01-create-cmd-project.png&#34; alt=&#34;Create A Command Line Xcode Project For LLVM&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Accessing C stuff in Swift is the same as using your Objective-C
classes. So we need to &#60;a href=&#34;https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html&#34;&#62;create a bridging header&#60;/a&#62;. (I usually create
a Objective-C class so that Xcode prompts me for creating the header, then I
delete the .h and .m files). The project layout is now:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/10/llvm-swift-02-bridging-header.png&#34; alt=&#34;Create a bridging header to import LLVM C libraries&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Import the LLVM headers for its C interface. For our example, this is the
entire bridging header:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;#import &#38;lt;llvm-c/Core.h&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It&#39;s probably a good time to replace content of &#60;code&#62;main.swift&#60;/code&#62; with our awesome
LLVM IR-generating code:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;let module = LLVMModuleCreateWithName(&#38;quot;my_module&#38;quot;)
&#60;/code&#62;&#60;/pre&#62;
&#60;h2&#62;3. Teach Xcode About LLVM&#60;/h2&#62;
&#60;p&#62;Our code would not compile at this point. Xcode complains that the LLVM header
can not be found. Before you jump to the target build settings, allow me
introduce &#60;code&#62;llvm-config&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;It turns out that the compliler flags for building a compiler can get complex
pretty quickly. So LLVM comes with a command that generates them. For me it
lives under &#60;code&#62;$(HOME)/usr/local/clang-3.4/bin&#60;/code&#62;. We can ask it for flags that
compiles standard C++, links standard and core libraries like so:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;llvm-config --cxxflags --ldflags --system-libs --libs core
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;(As we use more and more LLVM libraries in the future, the list following
&#60;code&#62;--libs&#60;/code&#62; will grow. &#60;code&#62;core&#60;/code&#62; is all we need to compile our example). To anyone
who&#39;s used GCC/Clang in command line, the output should be pretty
self-explanatory:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;-I/Users/drchrono/local/clang-3.4/include  -DNDEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -O3  -std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -fno-common -Wcast-qual
-L/Users/drchrono/local/clang-3.4/lib 
-lLLVMCore -lLLVMSupport
-lz -lpthread -ledit -lcurses -lm
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;I&#39;ll walk through how to ask Xcode to respect these.&#60;/p&#62;
&#60;p&#62;First, go to build settings and set search paths for header files and
libraries according to output from &#60;code&#62;llvm-config&#60;/code&#62;. For me that means:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/10/llvm-swift-03-header-search-path.png&#34; alt=&#34;Set LLVM header search path in Xcode&#34; /&#62;
&#60;img src=&#34;/assets/2015/10/llvm-swift-04-library-search-path.png&#34; alt=&#34;Set LLVM library search path in Xcode&#34; /&#62;&#60;/p&#62;
&#60;p&#62;If you try to compile, now Xcode tells you some #define is missing. Again,
we can find them in &#60;code&#62;llvm-config&#60;/code&#62;&#39;s result. Navigate to &#38;quot;Preprocessing&#38;quot; in
build setting and add those values starting with &#60;code&#62;-D&#60;/code&#62;, with out the &#60;code&#62;-D&#60;/code&#62;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/10/llvm-swift-05-macros.png&#34; alt=&#34;Set preprocessor macros&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Remember to add these for both &#38;quot;Debug&#38;quot; and &#38;quot;Release&#38;quot;.&#60;/p&#62;
&#60;p&#62;The last step is asking Xcode to link againt the LLVM libraries. Paste in the
&#60;code&#62;-l&#60;/code&#62; flags from &#60;code&#62;llvm-config&#60;/code&#62; at &#38;quot;Other Linker Flags&#38;quot;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/10/llvm-swift-06-link-libraries.png&#34; alt=&#34;Ask Xcode to link against LLVM libraries&#34; /&#62;&#60;/p&#62;
&#60;h2&#62;4. Conclusion&#60;/h2&#62;
&#60;p&#62;Now our Swift LLVM code compiles! Looking back, setting LLVM up with Xcode is
no more special than setting up with any C libraries. Hopefully this post will
cut down research time for some. Now go create awesome natively languages in
Swift!&#60;/p&#62;
</description>
                <pubDate>Sun, 25 Oct 2015 11:53:15 -0700</pubDate>
                <link>https://duan.ca/2015/10/25/lets-play-llvm-in-swift-setup/</link>
                <guid isPermaLink="true">https://duan.ca/2015/10/25/lets-play-llvm-in-swift-setup/</guid>
            </item>
            <item>
                <title>Swift Algebraic Data Types</title>
                <description>&#60;h2&#62;The Basics&#60;/h2&#62;
&#60;p&#62;&#60;a href=&#34;https://en.wikipedia.org/wiki/Algebraic_data_type&#34;&#62;Algebraic Data Type&#60;/a&#62; is a fancy name for &#38;quot;a type creaded by combining other
types&#38;quot; in programming languages. One aspect of the &#38;quot;algebraic-ness&#38;quot; is how
many potential new values there are for the new type, given a set of type as
its building block.&#60;/p&#62;
&#60;p&#62;To better illustrate this, consider the following example in Swift.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum StarkChild { case Rickon, Bran, Arya, Sansa, Robb, Jon }

enum Direwolf { case Shaggydog, Summer, Nymeria, Lady, Greywind, Ghost }

enum Actor {
    case Wolf(Direwolf)
    case Person(StarkChild)
}

struct Parters {
    var wolf: Direwolf
    var person: StarkChild
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;code&#62;StarkChild&#60;/code&#62; and &#60;code&#62;Direwolf&#60;/code&#62; each has 6 potential values. Combining them, we
get two new types.&#60;/p&#62;
&#60;p&#62;Question: how many potentiol values are there for &#60;code&#62;Actor&#60;/code&#62;? How many for
&#60;code&#62;Parters&#60;/code&#62;?&#60;/p&#62;
&#60;hr&#62;
&#60;p&#62;An &#60;code&#62;Actor&#60;/code&#62; can be either a &#60;code&#62;StarkChild&#60;/code&#62; or a &#60;code&#62;DireWolf&#60;/code&#62;, therefore it has `6&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;6 = 12&#60;code&#62;potential values – the *sum* of&#60;/code&#62;Child&#60;code&#62;&#39;s and &#60;/code&#62;DireWolf`&#39;s values.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;A &#60;code&#62;Partners&#60;/code&#62; requires us to select one value from &#60;code&#62;Child&#60;/code&#62; and one from
&#60;code&#62;DireWolf&#60;/code&#62;, resulting in &#60;code&#62;6 * 6 = 36&#60;/code&#62; potential values – the &#60;em&#62;product&#60;/em&#62; of
&#60;code&#62;Child&#60;/code&#62;&#39;s and &#60;code&#62;DireWolf&#60;/code&#62;&#39;s values.&#60;/p&#62;
&#60;p&#62;&#60;code&#62;Actor&#60;/code&#62;, an &#60;code&#62;enum&#60;/code&#62;, is a &#60;em&#62;sum&#60;/em&#62; type. &#60;code&#62;Parters&#60;/code&#62;, a &#60;code&#62;struct&#60;/code&#62;, is a &#60;em&#62;product&#60;/em&#62;
type. Here, &#60;code&#62;Parters&#60;/code&#62; could easily be defined as a &#60;code&#62;class&#60;/code&#62; or a &#60;code&#62;tuple&#60;/code&#62; and
remain a &#60;em&#62;product&#60;/em&#62; type. Because we can create product or sum types in these
direct ways, we can say Swift has first class support for Algebraic Data
Types.&#60;/p&#62;
&#60;h2&#62;The Crossovers&#60;/h2&#62;
&#60;p&#62;However, the story doesn&#39;t stop here. In Swift, an &#60;code&#62;enum&#60;/code&#62;&#39;s option can have
multiple values. If it happens to be the only option, then this
&#60;code&#62;enum&#60;/code&#62;effectively becomes a &#60;em&#62;product&#60;/em&#62; type:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// there are 6 * 6 = 36 potential values for Parters
enum Parters {
    case Value(wolf: DireWolf, person: StarkChild)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Incidentally, this makes &#60;code&#62;enum&#60;/code&#62; similar to &#60;code&#62;data&#60;/code&#62; in Haskell, where &#60;em&#62;product&#60;/em&#62;
and &#60;em&#62;sum&#60;/em&#62; types can be created with a unified construct – &#60;code&#62;data&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;In C and C++, &#60;code&#62;union&#60;/code&#62;s are the closest thing to &#60;em&#62;sum&#60;/em&#62; types. However, &#60;code&#62;union&#60;/code&#62;
is hardly used to combine arbitrary types due to its lack of associated
values. What do people do in need of &#60;em&#62;sum&#60;/em&#62; types? They make do with product
types. Here&#39;s one way to achive that in Swift:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;// Actor.value can have only 6 + 6 = 12 potential values thanks to
// manual enforcement
class Actor {
    var child: StarkChild?
    var wolf: Direwolf?

    var value: Any {
        get {
            return child == nil ? wolf! : child!
        }
        set(newValue) {
            if newValue is StarkChild {
                child = (newValue as! StarkChild)
                wolf = nil
            }
            if newValue is Direwolf {
                wolf = (newValue as! Direwolf)
                child = nil
            }
        }
    }

    init(wolf: Direwolf) {
        self.wolf = wolf
    }
    init(child: StarkChild) {
        self.child = child
    }
    init() {
        fatalError(&#38;quot;must initialize with a child or a wolf&#38;quot;)
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It&#39;s… ugly.&#60;/p&#62;
&#60;h2&#62;Recursion Types&#60;/h2&#62;
&#60;p&#62;Besides &#60;em&#62;sum&#60;/em&#62; and &#60;em&#62;product&#60;/em&#62;, another common class of algebraic type is
recursion types. The interesting bit here is that Swift struggles to support
it. In WWDC 2015, it was announced that &#60;code&#62;enum&#60;/code&#62;s can be defined recursively in
Swift 2:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;enum Tree {
    case Empty
    indirect case Node(Tree, Tree)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;As of this writing, Xcode 7 beta 3 has not delivered this feature yet.
Also, it&#39;s a good bet that &#60;code&#62;indirect&#60;/code&#62; is not going to be available in tuple
aliases, such as:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;typealias Node = (indirect Node, indirect Node)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;I hope this is on the Swift team&#39;s (understandably) gigantic todo list 😉.&#60;/p&#62;
</description>
                <pubDate>Sun, 12 Jul 2015 15:51:27 -0700</pubDate>
                <link>https://duan.ca/2015/07/12/swift-algebraic-data-types/</link>
                <guid isPermaLink="true">https://duan.ca/2015/07/12/swift-algebraic-data-types/</guid>
            </item>
            <item>
                <title>Dynamic Swift Framework Without Xcode</title>
                <description>&#60;p&#62;I came up with this question recently:&#60;/p&#62;
&#60;blockquote class=&#34;twitter-tweet&#34; lang=&#34;en&#34;&#62;&#60;p lang=&#34;en&#34; dir=&#34;ltr&#34;&#62;Can we even use Frameworks with &#60;a href=&#34;https://twitter.com/hashtag/Swiftlang?src=hash&#34;&#62;#Swiftlang&#60;/a&#62; on Linux?&#60;/p&#62;&#38;mdash; Daniel Duan (@daniel_duan) &#60;a href=&#34;https://twitter.com/daniel_duan/status/617470929241706496&#34;&#62;July 4, 2015&#60;/a&#62;&#60;/blockquote&#62; &#60;script async src=&#34;//platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&#62;&#60;/script&#62;
&#60;p&#62;And I&#39;m going to give the answer in this post (spoiler alert: yes, sort of).&#60;/p&#62;
&#60;p&#62;Here&#39;s the content of a framework created by Xcode:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/07/just-framework-structure.png&#34; alt=&#34;Just Framework Structure&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Some of the files, such as &#60;code&#62;Info.plist&#60;/code&#62;, are obviously construct of Xcode.
Play with &#60;code&#62;swiftc&#60;/code&#62; long enough, one would find that the &#60;code&#62;.swiftdoc&#60;/code&#62;s, the
&#60;code&#62;.swiftmodule&#60;/code&#62;s and the one binary file came from the Swift compiler.&#60;/p&#62;
&#60;p&#62;Instead of listing the relevant &#60;code&#62;swiftc&#60;/code&#62; command options, I&#39;ve created a &#60;a href=&#34;https://github.com/dduan/Swift-Framework-Without-Xcode&#34;&#62;sample project&#60;/a&#62; to demonstrate how one can complie and link to frameworks so that they can be &#60;code&#62;import&#60;/code&#62;ed in the application code. The key ingredient for achieving it lies in &#60;em&#62;Makefile&#60;/em&#62;. In summary, &#60;code&#62;swiftc&#60;/code&#62; can do these for us:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;generate a binary as a library/framework&#60;/li&#62;
&#60;li&#62;emit a &#60;code&#62;.swiftmodule&#60;/code&#62; file, which Swift needs to understand that binary.&#60;/li&#62;
&#60;li&#62;assign a path the Swift runtime needs to locate this framework.&#60;/li&#62;
&#60;li&#62;compile source code that imports the framework, given that they exist in the paths relative to the app binary in step 3.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Based on these observations, it&#39;s not hard to imagine more sophisticated build systems, such as IDEs and package/dependency management systems.&#60;/p&#62;
</description>
                <pubDate>Sun, 05 Jul 2015 22:36:09 -0700</pubDate>
                <link>https://duan.ca/2015/07/05/dynamic-swift-framework-without-xcode/</link>
                <guid isPermaLink="true">https://duan.ca/2015/07/05/dynamic-swift-framework-without-xcode/</guid>
            </item>
            <item>
                <title>Let&#39;s Build A &#39;cat&#39; In Swift 2</title>
                <description>&#60;p&#62;As a homework in one of the early college classes, I was asked to write unix
commands such as &#60;code&#62;cat&#60;/code&#62; in C. Let&#39;s do that in Swift today! To make things
interesting, let&#39;s pretend we are on Linux. That means no Xcode nor Foundation
can be used.&#60;/p&#62;
&#60;p&#62;It&#39;s hard to find a simpler unix program than &#60;code&#62;cat&#60;/code&#62;: It takes a list of file
names from the shell and write the content of each file to &#60;code&#62;stdout&#60;/code&#62;. When no
argument is given, it uses &#60;code&#62;stdin&#60;/code&#62; as the source of its output.&#60;/p&#62;
&#60;p&#62;Writing it in C is trivial. Swift has exellent support for leveraging C. But
to call even the standard C functions, we need to import them first.&#60;/p&#62;
&#60;p&#62;The &#60;code&#62;swiftc&#60;/code&#62; command can compile a pure Swift source file like this:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;swiftc cat.swift -o cat
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;We can add Objective-C bridging headers with the argument
&#60;code&#62;-import-objc-header&#60;/code&#62;.  But to import the standard C functions, we also need
to specify path to an SDK:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;swiftc -sdk $(xcrun --show-sdk-path --sdk macosx)\
       -import-objc-header bridge.h\
       cat.swift\
       -o cat
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Instead of typing/copying that command, save this &#60;code&#62;Makefile&#60;/code&#62; to the same
directory as &#60;code&#62;cat.swift&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;SDKPATH = $(shell xcrun --show-sdk-path --sdk macosx)
CBRIDGEHEADER = bridge.h
TARGETS := cat

.PHONY : all $(TARGETS)

all: $(TARGETS)

$(TARGETS):
    swiftc -sdk $(SDKPATH) $@.swift -import-objc-header $(CBRIDGEHEADER) -o $@
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now &#60;code&#62;make cat&#60;/code&#62; should take care of the compilation.&#60;/p&#62;
&#60;p&#62;Since file I/O is the only concern, we&#39;ll need C APIs from &#60;code&#62;stdio.h&#60;/code&#62;, so
&#60;code&#62;bridge.h&#60;/code&#62; is a one liner:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;#import &#38;lt;stdio.h&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The standard C function for opening a file is &#60;code&#62;fopen&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;FILE * fopen ( const char *filename, const char *mode );
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Hmmmm, how do we deal with all those pesky &#39;*&#39;s?&#60;/p&#62;
&#60;p&#62;To reference a certain C &#60;code&#62;Type&#60;/code&#62; in Swift, we can use &#60;code&#62;UnsafePointer&#38;lt;Type&#38;gt;&#60;/code&#62; or
&#60;code&#62;UnsafeMutablePointer&#38;lt;Type&#38;gt;&#60;/code&#62;. To make our lives easier, Swift &#60;code&#62;String&#60;/code&#62;s
automatically bridge to &#60;code&#62;const char *&#60;/code&#62;. In other words, we can treat the
signature of &#60;code&#62;fopen&#60;/code&#62; as if it&#39;s the following:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;func fopen( filename: String, mode: String ) -&#38;gt; UnsafeMutablePointer&#38;lt;FILE&#38;gt;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;A character in C is represented by a byte in memory. Therefore Swift sees
a &#60;code&#62;char&#60;/code&#62; as of type &#60;code&#62;Int8&#60;/code&#62; (8-bit integer).  So a &#60;code&#62;char *&#60;/code&#62; would be referenced
as &#60;code&#62;UnsafeMutablePointer&#38;lt;Int8&#38;gt;&#60;/code&#62; in Swift. So &#60;code&#62;getline&#60;/code&#62;, a function from POSIX&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;ssize_t getline( char **lineptr, size_t *n, FILE *stream );
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;would look like this in Swift:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;func getline(
    inout lineptr: UnsafeMutablePointer&#38;lt;Int8&#38;gt;,
    inout n: UInt,
    stream: UnsafeMutablePointer&#38;lt;FILE&#38;gt;
) -&#38;gt; Int
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It returns the number if characters it finds.&#60;/p&#62;
&#60;p&#62;We now can open a file, read and print its content line by line, and close it
with:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-c&#34;&#62;func fclose(stream: UnsafeMutablePointer&#38;lt;FILE&#38;gt;)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Repeat this on each file specified in &#60;code&#62;Process.arguments&#60;/code&#62;, or simply read from
&#60;code&#62;stdin&#60;/code&#62;, and we have a &#60;code&#62;cat&#60;/code&#62;! Here&#39;s a screenshot of it displaying its own
code:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/07/swift-cat.png&#34; alt=&#34;Swift cat&#34; /&#62;&#60;/p&#62;
&#60;p&#62;The code is also available in this &#60;a href=&#34;https://gist.github.com/dduan/f6d359019db8b0b55962&#34;&#62;gist&#60;/a&#62;.&#60;/p&#62;
</description>
                <pubDate>Sat, 04 Jul 2015 20:56:19 -0700</pubDate>
                <link>https://duan.ca/2015/07/04/lets-build-a-cat-in-swift-2/</link>
                <guid isPermaLink="true">https://duan.ca/2015/07/04/lets-build-a-cat-in-swift-2/</guid>
            </item>
            <item>
                <title>NeoVim, Swift and Make</title>
                <description>&#60;p&#62;When it comes to Swift source code editing, nothing beats Xcode 6.3! That
includes Xcode 6.2, which drove me to good&#39;O Vim for a while.&#60;/p&#62;
&#60;p&#62;Except it&#39;s not the old Vim, I&#39;m trying out &#60;a href=&#34;http://neovim.org&#34;&#62;NeoVim&#60;/a&#62;. The
most noticable difference in NeoVim compared to Vim is its recent
addition of a built-in terminal.&#60;/p&#62;
&#60;p&#62;With the help of syntax highlighting and a Makefile, working with Swift this
way turns out to be a fine alternative.&#60;/p&#62;
&#60;p&#62;(As a side benefit, I&#39;m forced to use only local-context autocompletion. Now
I can actually spell out full UIKit APIs 😉.)&#60;/p&#62;
&#60;p&#62;Here&#39;s a gif:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2015/04/demo.gif&#34; alt=&#34;Make Swift NeoVim Demo&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Some details are easy to miss. I pressed &#60;code&#62;,m&#60;/code&#62;, &#60;code&#62;,&#60;/code&#62; being my binding for
&#60;code&#62;&#38;lt;leader&#38;gt;&#60;/code&#62;. A terminal session launched with the &#60;code&#62;make&#60;/code&#62; command running. When
that&#39;s done, I could press any key and the terminal pane was dismissed. Since
&#60;code&#62;test&#60;/code&#62; is the default target in my &#60;code&#62;Makefile&#60;/code&#62;, the test suit for my Swift
codes actually ran.&#60;/p&#62;
&#60;p&#62;Here&#39;s how the shortcut is set in &#60;code&#62;.nvimrc&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;if has(&#39;nvim&#39;)
    nnoremap &#38;lt;leader&#38;gt;m :rightbelow vertical split &#38;lt;bar&#38;gt; :term make&#38;lt;cr&#38;gt;
endif
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The makefile is pretty straightforword if you&#39;ve worked with &#60;code&#62;xcodebuild&#60;/code&#62;.&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;test :
    @xcodebuild test -project ProjectName.xcodeproj -scheme SchemeName -destination &#39;platform=iOS Simulator,name=iPhone 6&#39; | xcpretty

clean :
    @xcodebuild clean
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/supermarin/xcpretty&#34;&#62;xcpretty&#60;/a&#62; is a nifty script that
makes &#60;code&#62;xcodebuild&#60;/code&#62;s output much more readable.&#60;/p&#62;
&#60;p&#62;Happy vimming, Swifties :)&#60;/p&#62;
</description>
                <pubDate>Wed, 22 Apr 2015 11:46:17 -0700</pubDate>
                <link>https://duan.ca/2015/04/22/neovim-swift-and-make/</link>
                <guid isPermaLink="true">https://duan.ca/2015/04/22/neovim-swift-and-make/</guid>
            </item>
            <item>
                <title>Swift Function Fun Facts</title>
                <description>&#60;p&#62;You love Swift. You want to write a class that does HTTP, it might have
methods like the following:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func get(URLString:String, params:[String:AnyObject],
    headers:[String:String])
func post(URLString:String, params:[String:AnyObject],
    headers:[String:String])
func put(URLString:String, params:[String:AnyObject],
    headers:[String:String])
// and more for HEAD, OPTIONS …

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;But you don&#39;t want to force your user to supply all arguments each time. You
know that Swift supports default arguments, so you added some. Take GET as an
example:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func get(URLString:String, params:[String:AnyObject]=[:],
    headers:[String:String]=[:])

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Now users can do things like&#60;/p&#62;
&#60;p&#62;{% highlight swift %}
get(&#38;quot;http://github.com&#38;quot;)
get(&#38;quot;http://httpbin.org/get&#38;quot;, headers:[&#38;quot;Answer&#38;quot;:42])
{% endhighlight %}&#60;/p&#62;
&#60;p&#62;That&#39;s flexible! Woohoo!&#60;/p&#62;
&#60;p&#62;After you thought about implementing these, though, you realize that
&#60;code&#62;HTTPMethod&#60;/code&#62; is merely a property on &#60;code&#62;NSURLRequest&#60;/code&#62;. In other words, all of
the previous methods can share the same implementation. In honor of the DRY
principle, you write a function that accepts the method as an arguments and
the previous functions each forwards the arguments to this function:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func impl(method:String, URLString:String,
    params:[String:AnyObject],
    headers:[String:String])
{
    // …
}

func get(URLString:String, params:[String:AnyObject]=[:],
    headers:[String:String]=[:])
{
    impl(&#38;quot;GET&#38;quot;, URLString:URLString, params:params,
        headers:headers)
}

func post(URLString:String, params:[String:AnyObject]=[:],
    headers:[String:String]=[:])
{
    impl(&#38;quot;POST&#38;quot;, URLString:URLString, params:params,
        headers:headers)
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This seems like a sensible solution. Except that later you realize that there
needs to be more parameters for each function, so in the end, each function
looks like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func post(
    URLString             : String,
    params                : [String:AnyObject]       = [:],
    json                  : [String:AnyObject]?      = nil,
    headers               : [String:AnyObject]       = [:],
    auth                  : (String,String)?         = nil,
    allowRedirects        : Bool                     = true,
    requestBody           : NSData?                  = nil,
    URLQuery              : String?                  = nil,
    asyncCompletionHandler: ((HTTPResult!) -&#38;gt; Void)? = nil
    ) -&#38;gt; HTTPResult {
    return impl(
        &#38;quot;POST&#38;quot;,
        URLString             : URLString,
        params                : params,
        json                  : json,
        headers               : headers,
        auth                  : auth,
        data                  : requestBody,
        URLQuery              : URLQuery,
        redirects             : allowRedirects,
        asyncCompletionHandler: asyncCompletionHandler
    )
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Remembering that your goal is to respect DRY, and there are now giant blocks
of code that all look the same except that first argument to &#60;code&#62;impl()&#60;/code&#62;, you
became determined to find a better alternative.&#60;/p&#62;
&#60;p&#62;Well, why not give currying a try? This example of currying with Swift comes
to your mind:&#60;/p&#62;
&#60;p&#62;{% highlight swift %}
func add(a:Int)(b:Int) -&#38;gt; Int { return a + b }
let add3 = add(3)
add3(b:2) // 5
{% endhighlight %}&#60;/p&#62;
&#60;p&#62;If we apply this technique and treat &#60;code&#62;method&#60;/code&#62; in &#60;code&#62;impl()&#60;/code&#62; as &#60;code&#62;a&#60;/code&#62; in the
example, we would get:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func impl(method:String)(
    URLString:String,
    params:[String:AnyObject],
    headers:[String:String],
    …)
{
    // …
}
let get = impl(&#38;quot;GET&#38;quot;)
let post = impl(&#38;quot;POST&#38;quot;)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;right?  However, you are forcing users to supply each argument again. To make
things worse, the number of arguments is a lot larger.&#60;/p&#62;
&#60;p&#62;Hmm, but that&#39;s a solved problem, just add default values to &#60;code&#62;impl()&#60;/code&#62;&#39;s
parameters:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func impl(method:String)(
    URLString:String,
    params:[String:AnyObject] = [:],
    headers:[String:String] = [:],
    …)
{
    // …
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Ta-da! Wait a minute, Xcode now refuse to compile you code! &#60;code&#62;Default argument is only permitted for a non-curried function parameter&#60;/code&#62;, it saids.&#60;/p&#62;
&#60;p&#62;Stubborn as you are, you decide that perhaps the Swift team hasn&#39;t got around
to implementing this feature for curry syntax yet. Functions are first-class
citizens! Surely if you return a function with default arguments…?&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-swift&#34;&#62;func methodFactory(method:String)
    -&#38;gt; (params:[String:AnyObject] = [:],
        headers:[String:String] = [:], …)
    -&#38;gt; Void
{
    return {(params, headers, …) in
        impl(method, params:params, headers:headers, …)
    }
}

let get = methodFactory(&#38;quot;GET&#38;quot;)
let post = methodFactory(&#38;quot;POST&#38;quot;)
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Turns out, this manual form of currying only works when default arguments
aren&#39;t involved!&#60;/p&#62;
&#60;p&#62;Now, you hate Swift.&#60;/p&#62;
&#60;p&#62;(Just to be clear, I don&#39;t really hate Swift as in, uh, &#60;em&#62;hate&#60;/em&#62; Swift. Judgning
from some comments, I might have failed to convey the lightheartedness that
I felt writing this up. It&#39;s really like saying to a friend &#38;quot;I hate you&#38;quot; after
he/she pulls a prank on you.)&#60;/p&#62;
</description>
                <pubDate>Sat, 18 Apr 2015 16:20:16 -0700</pubDate>
                <link>https://duan.ca/2015/04/18/swift-function-fun-facts/</link>
                <guid isPermaLink="true">https://duan.ca/2015/04/18/swift-function-fun-facts/</guid>
            </item>
            <item>
                <title>When Default Parameter Values Fall Short In Swift</title>
                <description>&#60;p&#62;Swift supports default value for function parameters:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    func f(x=1, y=2, z=3) { return x * y + z }

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Functions defined in this way is extremely flexible as they allows the user to arbitrarily omit any parameters:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    f(y:6) // 9

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Today, however, I ran into a scenario where default values stopped working.&#60;/p&#62;
&#60;p&#62;imagine a group of functions who share the same implementation function by supplying different values as its parameters. Furthermore, each of these functions also expose a same set of parameters.&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    func impl(x:String, a:Int, b:Int, c:Int, d:Int, f:Int, e:Int)

&#60;/code&#62;&#60;/pre&#62;
</description>
                <pubDate>Sat, 18 Apr 2015 00:00:00 -0800</pubDate>
                <link>https://duan.ca/2015/04/18/when-default-parameter-values-fall-short-in-swift/</link>
                <guid isPermaLink="true">https://duan.ca/2015/04/18/when-default-parameter-values-fall-short-in-swift/</guid>
            </item>
            <item>
                <title>The Two Swifts</title>
                <description>&#60;p&#62;onpatient 2.0 went live in App Store on September 27th 2014, 10 days after iOS
8 was officially released. For the next few months, it was featured for
HealthKit intergration on the App Store front page. In conversations during
that period, people would ask me &#38;quot;what was the experience like?&#38;quot; What they
referred to, of course, was the fact that I wrote that version in 100% Swift.&#60;/p&#62;
&#60;p&#62;I have a very different answer to that question now compared to the standard
one I gave back then. I hope to explain to you, my dear readers, how my view
on Swift has evolved since the beginning.&#60;/p&#62;
&#60;h2&#62;Swift The Puller&#60;/h2&#62;
&#60;blockquote&#62;
&#60;p&#62;After you get used to a few nuances, it&#39;s Cocoa Touch after all.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;People kind of went &#38;quot;huh&#38;quot;, and didn&#39;t know how to respond to this answer, at
the time when iOS 8 was just out. I think they were expecting horror stories.&#60;/p&#62;
&#60;p&#62;Well, they would have been right. One day &#60;code&#62;UIStoryboardSegue&#60;/code&#62; would have an
&#60;code&#62;identifier&#60;/code&#62; of type &#60;code&#62;String!&#60;/code&#62;, the next day it would become a &#60;code&#62;String?&#60;/code&#62;. And
the incomprehensible error message from Xcode made sure you woundn&#39;t figure it
out with ease. This kind of changes would happen to your entire codebase each
time a beta Xcode was released. Compunding with these implementation bugs,
API changes and poor tooling, was the fact that you had to learn a new
programming lanauge. If you and your family&#39;s livelihood depends direclty on
the software you put out, avoiding that whole situation was (and is) the
correct &#60;em&#62;business choice&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;To me, however, all that was just plain &#60;em&#62;fun&#60;/em&#62;. Within about a week, the
strangeness of having &#60;code&#62;optional&#60;/code&#62;s went away. It&#39;s kind of nice to have the
compiler bark at you when something was unintialized. My old friends never
left: ARC, auto-synthesized properties, blocks, protocols…&#60;/p&#62;
&#60;p&#62;As for the beta changes, they were only as often as the Xcode releases. Reading
the release notes and a few careful inspections of the compile errors usually
was enough to help you &#38;quot;fix&#38;quot; everything.&#60;/p&#62;
&#60;p&#62;A couple weeks in, Swift &#60;em&#62;disappeared&#60;/em&#62;. I was just writing a brand new Cocoa
Touch app. My attention was on architecture, user experience and patterns that
works well with varies iOS APIs, business logic … We submitted the app on the
first day it became possible.&#60;/p&#62;
&#60;p&#62;Turning back the clock to the ancient days when the world was &#60;a href=&#34;http://arstechnica.com/apple/2010/06/copland-2010-revisited/&#34;&#62;blissfully
unaware&#60;/a&#62; of Swift&#39;s existence. If one wanted to become a Mac
or iOS developer, he/she would have gotten the advice along the lines of
&#38;quot;learning the Objective-C is easy, knowing the system API is harder&#38;quot;. Well,
that hasn&#39;t changed post-Swift. My experience building software with
UIKit/Cocoa Touch applied 100% in building the 100% Swift App.&#60;/p&#62;
&#60;p&#62;Things did change when I went back to Objective-C after a couple months of
writing Swift exclusively, however. The lack of type inference made typing
cumbersome. The worst part is the missing concept of optionality on data
types. &#60;em&#62;Every&#60;/em&#62; object suddenly were &#60;code&#62;optional&#60;/code&#62; in my eyes. I exprienced a
sense of insecurity, as if I was driving in a foregn country with simular but
significantly less respected traffic rules.&#60;/p&#62;
&#60;h2&#62;Swift The Pusher&#60;/h2&#62;
&#60;blockquote&#62;
&#60;p&#62;I&#39;m humbled and excited by the future because of what it&#39;s teaching me.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;By the time I shipped a few major feature updates in Swift, something had
been lurking on the back of my mind: I had left a whole bunch of its features
untouched, yet I seemed to have worked with it to some degree of success. What
gives? The emerging Swift community has shown me the way since. Observe:&#60;/p&#62;
&#60;p&#62;Exhibit A, the following Swift function is frequently found in
&#60;a href=&#34;https://github.com/typelift/Swiftz/blob/master/Sources/Swiftz/Curry.swift&#34;&#62;libraries&#60;/a&#62; and &#60;a href=&#34;http://www.objc.io/books/&#34;&#62;books&#60;/a&#62;, if not shipping code:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;func curry&#38;lt;A, B, C&#38;gt;(f: (A, B) -&#38;gt; C) -&#38;gt; A -&#38;gt; B -&#38;gt; C {
    return { x in { y in f(x,y)  }  }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Currying is a simple concept. The fact that you can do it in Swift is nothing
to write home about.&#60;/p&#62;
&#60;p&#62;What&#39;s striking to me, is how &#60;em&#62;succinct&#60;/em&#62;, or, dare I say, &#60;em&#62;elegant&#60;/em&#62; this can
be expressed in Swift. In this short piece of code, you see generics, higher
order functions, closures, type inference expressed on top of a strong type
system…to form this basic construct found in functional programming. It&#39;s as
if the language has been designed to enable it…&#60;/p&#62;
&#60;p&#62;which leads us to exhibit B:&#60;/p&#62;
&#60;p&#62;In a job &#60;a href=&#34;http://clang-developers.42468.n3.nabble.com/ADVERTISEMENT-open-positions-in-Apple-s-Swift-compiler-team-td4039949.html&#34;&#62;posting&#60;/a&#62; for Apple&#39;s Swift compiler team, the following
qualities are listed for Swift core library engineers (emphasis mine):&#60;/p&#62;
&#60;blockquote&#62;
&#60;ul&#62;
&#60;li&#62;A passion for making a difference in the lives of other programmers&#60;/li&#62;
&#60;li&#62;A deep understanding of generic programming principles&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Experience with functional programming languages and/or idioms&#60;/strong&#62;&#60;/li&#62;
&#60;li&#62;Experience bridging languages, especially bridging dynamic languages with static ones&#60;/li&#62;
&#60;li&#62;Exposure to innovative and/or comprehensive library designs&#60;/li&#62;
&#60;/ul&#62;
&#60;/blockquote&#62;
&#60;p&#62;So in the Swift team&#39;s mind, an ideal &#38;quot;customer&#38;quot; of the language, the standard
library authors being the most intimate ones, should be &#38;quot;exploiting&#38;quot; the
language features to practice functional idioms. This detail stuck and
ultimately inspired me to pick up &#60;a href=&#34;http://www.objc.io/books/&#34;&#62;Functional Programming in Swift&#60;/a&#62;.
The evidence piled on: &#60;a href=&#34;http://www.objc.io/issue-16/&#34;&#62;articles&#60;/a&#62;, &#60;a href=&#34;http://2014.funswiftconf.com&#34;&#62;talks&#60;/a&#62;
and &#60;a href=&#34;https://medium.com/swift-programming/2-functional-swift-c98be9533183&#34;&#62;Blog&#60;/a&#62; &#60;a href=&#34;http://ijoshsmith.com/2014/11/30/getting-into-functional-programming-with-swift/&#34;&#62;posts&#60;/a&#62;. I realized that the
language I&#39;ve been using for several month has introduced the possiblity to do
what the Haskell/Ocaml/Scala/F# folks do all day long (I won&#39;t discuss much
functional programming in this post). The introduction has been gentle and
could be safely ignored, but things like
&#60;a href=&#34;https://github.com/jeffh/Fox&#34;&#62;automatically generated tests&#60;/a&#62; and parser combinators got me
hooked.&#60;/p&#62;
&#60;p&#62;I believe anyone who write code can benefit from knowing and appreciating the
funtional paradigm. What&#39;s unique about Swift is that it&#39;s presented on
Apple&#39;s huge developer eco-system. That means a huge part of our industry will
benefit as Swift spread futher and futher. In that sense, it really stands out
among all the other languages that enables functional programming.&#60;/p&#62;
</description>
                <pubDate>Tue, 10 Feb 2015 10:50:16 -0800</pubDate>
                <link>https://duan.ca/2015/02/10/the-two-swifts/</link>
                <guid isPermaLink="true">https://duan.ca/2015/02/10/the-two-swifts/</guid>
            </item>
            <item>
                <title>My Xcode 6.2 And 6.3 Prediction</title>
                <description>&#60;p&#62;We have a situation here: three versions of Xcode are available to devleopers as of this writing.&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;Xcode 6.1.1&#60;/li&#62;
&#60;li&#62;Xcode 6.2 beta&#60;/li&#62;
&#60;li&#62;Xcode 6.3 beta&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;6.2 is released with the purpose of making WatchKit availale.&#60;/p&#62;
&#60;p&#62;6.3, so far, has been focused on Swift 1.2 and new Objective-C features, and a
few non-language related features.&#60;/p&#62;
&#60;p&#62;The fact that there are two betas indicates to me each will be followed up by
an official release. So how?&#60;/p&#62;
&#60;p&#62;My guess: there will be an official Xcode 6.2 release after Watch release. It doesn&#39;t make much sense to skip a minor version.&#60;/p&#62;
&#60;p&#62;Then things get interesting. Watch is coming out in April. Shortly after that, we&#39;ll have WWDC. Usually, WWDC comes with major Xcode beta release. So ... what happens to version 6.3?&#60;/p&#62;
&#60;p&#62;My guess: either we&#39;ll never get Xcode 6.3, or we won&#39;t get Xcode 7 this year.&#60;/p&#62;
&#60;p&#62;The former make sense in the context that &#60;a href=&#34;http://9to5mac.com/2015/02/09/apples-ios-9-to-have-huge-stability-and-optimization-focus-after-years-of-feature-additions/&#34;&#62;Apple Is Focused on Stablity&#60;/a&#62;. Xcode needs some love on that front, let&#39;s face it!&#60;/p&#62;
&#60;p&#62;On the other hand, no harm would be done if Apple market 6.3 as version 7 come WWDC. Afterall, Swift 1.2 is significant enough to justify a major version.&#60;/p&#62;
</description>
                <pubDate>Tue, 10 Feb 2015 02:09:50 -0800</pubDate>
                <link>https://duan.ca/2015/02/10/my-xcode-62-and-63-prediction/</link>
                <guid isPermaLink="true">https://duan.ca/2015/02/10/my-xcode-62-and-63-prediction/</guid>
            </item>
            <item>
                <title>Build And Run iOS Apps In Commmand Line</title>
                <description>&#60;p&#62;Xcode is slow. Enough said. What&#39;s worse, sometimes I find myself
relying too much on auto-completion with Cocoa Touch, a blessing and a curse!&#60;/p&#62;
&#60;p&#62;So I searched for an alternative workflow in command line. The result was
rather confusing: there are posts about using &#60;code&#62;xctool&#60;/code&#62; or &#60;code&#62;xcodebuild&#60;/code&#62; to
build Xcode targets, using &#60;code&#62;ios-sim&#60;/code&#62;, &#60;code&#62;simctl&#60;/code&#62;  or &#60;code&#62;instruments&#60;/code&#62; to manage and
manage or launch simulators. Most of the information is out of date.&#60;/p&#62;
&#60;p&#62;Eventually though, I was able to piece together an answer for my needs.
That is, given an iOS project set up with Xcode 6, I want to&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;build a target.&#60;/li&#62;
&#60;li&#62;launch a iOS simulator.&#60;/li&#62;
&#60;li&#62;install the built .app bundle to the launched simulator.&#60;/li&#62;
&#60;li&#62;run the installed app.&#60;/li&#62;
&#60;li&#62;uninstall the app from the simulator.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;All in command line, with Xcode &#60;em&#62;closed&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;Before we proceed to the steps, you need to gather a few pieces of information:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;the Xcode build scheme of your choice (e.g. &#38;quot;AwesomeApp&#38;quot;).&#60;/li&#62;
&#60;li&#62;your app bundle ID (e.g. &#38;quot;com.awesome.app&#38;quot;).&#60;/li&#62;
&#60;li&#62;name of an existing simulator (e.g. &#38;quot;iPhone 6 Plus&#38;quot;). If you don&#39;t want to
look it up in Xcode GUI, look for it in output of command &#60;code&#62;xcrun simctl list&#60;/code&#62; .&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Ready? Here we go.&#60;/p&#62;
&#60;p&#62;(These commands should be run in the project folder).&#60;/p&#62;
&#60;p&#62;Build the target:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;xcodebuild -scheme AwesomeApp -destination &#39;platform=iphonesimulator,name=iPhone 6 Plus&#39; -derivedDataPath build
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Launch the simulator:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;xcrun instruments -w &#39;iPhone 6 Plus&#39;
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Install the bundle (after simulator is launched and target is built with
previous commands):&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;xcrun simctl install booted build/Build/Products/Debug-iphonesimulator/AwesomeApp.app
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Launch the app in simulator (after it&#39;s installed with the previous command):&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;xcrun simctl launch booted com.awesome.app
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Uninstall the bundle:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;xcrun simctl uninstall booted com.awesome.app
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Quite a few parameters needs to be added for the build step if you have
a comlex project. Please RTFMs. Write some script to automate the steps, if
are a lazy typiest like me.&#60;/p&#62;
</description>
                <pubDate>Sat, 07 Feb 2015 20:35:02 -0800</pubDate>
                <link>https://duan.ca/2015/02/07/build-and-run-ios-apps-in-commmand-line/</link>
                <guid isPermaLink="true">https://duan.ca/2015/02/07/build-and-run-ios-apps-in-commmand-line/</guid>
            </item>
            <item>
                <title>tableView:didSelectRowAtIndexPath: In Two Lines</title>
                <description>&#60;p&#62;You have a &#60;code&#62;UITableViewController&#60;/code&#62; with a couple of static cells, you want to
invoke some code for each cell in the delegate. Here&#39;s a quick way to do it:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        
        SEL action = (SEL[]){@selector(method1), @selector(method2)}[indexPath.row];
        ((void (*)(id, SEL))[self methodForSelector: action])(self, action);
    }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It&#39;s got everything you love about C and Objective-C: array literals, function
pointers, casting, selectors and something called &#60;a href=&#34;http://www.cocoawithlove.com/2008/02/imp-of-current-method.html&#34;&#62;IMPs&#60;/a&#62;.&#60;/p&#62;
&#60;p&#62;This piece of code maps selected cells to methods by putting methods by
indexing selectors in a C array.&#60;/p&#62;
&#60;p&#62;Why all the fuss on the second line? wouldn&#39;t a simple &#60;code&#62;performSelector:&#60;/code&#62;
work? The short answer is: to show the compiler that we are responsible
adults. You can read more about it [here](SO Answer);&#60;/p&#62;
</description>
                <pubDate>Sat, 03 May 2014 13:42:00 -0600</pubDate>
                <link>https://duan.ca/2014/05/03/tableview58didselectrowatindexpath58-in-two-lines/</link>
                <guid isPermaLink="true">https://duan.ca/2014/05/03/tableview58didselectrowatindexpath58-in-two-lines/</guid>
            </item>
            <item>
                <title>One Weird Trick To Make Vim Go Faster On Your Mac</title>
                <description>&#60;p&#62;I noticed something strange today.&#60;/p&#62;
&#60;p&#62;While playing with Ubuntu on a VirtualBox hosted by OS X Mavericks, Vim
&#60;em&#62;seems&#60;/em&#62; much faster than it being in iTerms2. How could that be? So I took the
following steps to test things out:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;Installed exact configurations with Vundle on the VM.&#60;/li&#62;
&#60;li&#62;Vim in Terminal.app&#60;/li&#62;
&#60;li&#62;MacVim with GUI.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;Nope, Vim is still more responsive on Ubuntu. In fact, text input seem more
responsive on this VM than the host OS in general! I thought I came to the
light switching to OS X after using Linux as desktop for years, and now this?
&#60;em&#62;&#60;a href=&#34;http://developer.android.com/reference/android/util/Log.html#wtf(java.lang.String,%20java.lang.Throwable)&#34;&#62;WTF&#60;/a&#62;?&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Defeat and confused, I went to the Internet, and found &#60;a href=&#34;http://stackoverflow.com/questions/4489885/how-can-i-increase-cursor-speed-in-terminal&#34;&#62;something close to an
answer&#60;/a&#62;. Under &#60;em&#62;System Preferences-Keyboard&#60;/em&#62;, drag the two slide
widget (&#38;quot;Key Repeat&#38;quot; and &#38;quot;Deley Until Repeat&#38;quot;) to the right most. Suddenly,
Vim become faster!&#60;/p&#62;
&#60;p&#62;Turns out, key repeating is very important for Vim users.&#60;/p&#62;
</description>
                <pubDate>Fri, 02 May 2014 10:25:00 -0600</pubDate>
                <link>https://duan.ca/2014/05/02/one-weird-trick-to-make-vim-go-faster-on-your-mac/</link>
                <guid isPermaLink="true">https://duan.ca/2014/05/02/one-weird-trick-to-make-vim-go-faster-on-your-mac/</guid>
            </item>
            <item>
                <title>Installing PyQt5 with Python 3 On OS X</title>
                <description>&#60;p&#62;Today I installed PyQt5 on OS X 10.9. Turns out, it&#39;s not as straight-forward
as one would think.&#60;/p&#62;
&#60;p&#62;Using &#60;code&#62;homebrew&#60;/code&#62; will &#60;strong&#62;not&#60;/strong&#62; work:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    brew install PyQt5 --with-python3
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is because of &#60;a href=&#34;https://github.com/Homebrew/homebrew/issues/25735&#34;&#62;an unfortunate choice&#60;/a&#62; made by the
homebrew maintainer regarding Python 3.&#60;/p&#62;
&#60;p&#62;So installing from &#60;a href=&#34;http://pyqt.sourceforge.net/Docs/PyQt5/installation.html&#34;&#62;source&#60;/a&#62; is the way to go. Following the
installing instruction, you would download and install &#60;a href=&#34;https://web.archive.org/web/20140410074945/http://pyqt.sourceforge.net/Docs/sip4/installation.html&#34;&#62;sip&#60;/a&#62;
first, the install &#60;a href=&#34;http://pyqt.sourceforge.net/Docs/PyQt5/installation.html&#34;&#62;PyQt5&#60;/a&#62; itself.&#60;/p&#62;
&#60;p&#62;Except that&#39;s not enough. When you run &#60;code&#62;python configure.py&#60;/code&#62;, you see this
error:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    error: Use the --qmake argument to explicitly specify a working Qt
    qmake.
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It&#39;s pretty self-explanatory. &#60;code&#62;qmake&#60;/code&#62;, the build tool for qt is needed here.
Install qt5 with homebrew and proceed:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    brew install qt5
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Afterwards, you should be able to import &#60;code&#62;PyQt5&#60;/code&#62; in a Python 3 REPL.&#60;/p&#62;
</description>
                <pubDate>Wed, 23 Apr 2014 10:36:00 -0600</pubDate>
                <link>https://duan.ca/2014/04/23/installing-pyqt5-with-python-3-on-os-x/</link>
                <guid isPermaLink="true">https://duan.ca/2014/04/23/installing-pyqt5-with-python-3-on-os-x/</guid>
            </item>
            <item>
                <title>Generating Xcode Build Number From Git</title>
                <description>&#60;p&#62;The build version number in an Xcode project (CFBundleVersion in Info.plist)
must be a monotonically increasing string for each archive submitted to the
App Store. Neglection of this requirement will result in an error during the
binary upload. Some automation will help avoiding this issue.&#60;/p&#62;
&#60;p&#62;First, we want to generate this version number from our version (&#60;em&#62;duh&#60;/em&#62;)
control system (VCS) each time our target gets built. My VCS of choice is Git,
users of other systems just need to get a increasing number from their code
history. On a *nix system, this command will count the number of commits on
&#39;develop&#39; branch up until HEAD:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    git rev-list develop | wc -l
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is a very good candidate for our build number, for longer history
generally correlates to later builds.&#60;/p&#62;
&#60;p&#62;Next, we make Xcode automatically run this command and use its result as the
build number.&#60;/p&#62;
&#60;p&#62;Go to project navigator, select your build target under the project icon,
click &#60;em&#62;Build Phases&#60;/em&#62;, select &#60;em&#62;Editor→Add Build Phase→Add Run Script Build
Phase&#60;/em&#62; in the menu. Remove the content in editor of the new &#60;em&#62;Run Script&#60;/em&#62;
phase and replace it with:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;revnum=`git rev-list develop | wc -l`
echo &#38;quot;#define BUILD_NUMBER $revnum&#38;quot; &#38;gt; InfoPlist.h
touch InfoPlist.h
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Go to build settings, change value of &#60;em&#62;Preprocess Info.plist File&#60;/em&#62; to &#38;quot;YES&#38;quot;.
Add &#38;quot;InfoPlist.h&#38;quot; to &#60;em&#62;Info.plist Preprocessor Prefix File→release&#60;/em&#62;.&#60;/p&#62;
&#60;p&#62;We ask Xcode to run our command and save its result as a &#38;quot;#define&#38;quot; in a header
file when it builds the project. This is done so that we can replace the
&#38;quot;hardcoded&#38;quot; build number with the name of the constant:&#60;/p&#62;
&#60;p&#62;Open Info.plist, Double click the value of &#60;em&#62;Bundle Version&#60;/em&#62; and replace it with&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;BUILD_NUMBER
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;There&#39;s only one issue left: &#60;code&#62;BUILD_NUMBER&#60;/code&#62; is now saved in &#60;em&#62;InfoPlist.h&#60;/em&#62;. Its
value comes from our commit history. So we want to exclude this piece of
information as part of our commit history (I&#39;ll leave the reason as an exercise
for the reader). Ignore this file by adding &#38;quot;InfoPlist.h&#38;quot; to &#60;em&#62;.gitignore&#60;/em&#62; (or
that of your other VCS).&#60;/p&#62;
&#60;p&#62;To recap, when you build the project now, Xcode will find out how many commits
are in the history, define it in a header file as &#60;code&#62;BUILD_NUMBER&#60;/code&#62;, which gets
used as the build number. As long as you keep with with version control, the
build number problem goes away.&#60;/p&#62;
</description>
                <pubDate>Sun, 29 Sep 2013 15:50:50 -0600</pubDate>
                <link>https://duan.ca/2013/09/29/generating-xcode-build-number-from-git/</link>
                <guid isPermaLink="true">https://duan.ca/2013/09/29/generating-xcode-build-number-from-git/</guid>
            </item>
            <item>
                <title>Sencha Touch 2 and PhoneGap integration</title>
                <description>&#60;p&#62;As one of my pet Sencha Touch project gets close to finish, I started
looking into distribute it as native apps with Phonegap/Cordova.&#60;/p&#62;
&#60;p&#62;One of the concerns in do so is the &#39;deviceready&#39; event provided by Phonegap,
according to the documentation:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;This is a very important event that every Cordova application should use.&#60;br /&#62;
...&#60;/p&#62;
&#60;/blockquote&#62;
&#60;blockquote&#62;
&#60;p&#62;The Cordova deviceready event fires once Cordova has fully loaded.
After the device has fired, you can safely make calls to Cordova function.&#60;/p&#62;
&#60;p&#62;Typically, you will want to attach an event listener with
document.addEventListener once the HTML document&#39;s DOM has loaded.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;In particular, the nice Sencha Touch microloader complicate the matter by
being the sole Javascript file that&#39;s supposed to be included in &#60;code&#62;index.html&#60;/code&#62;
and is in charge of starting the actual code of our apps. Yet we need the
starting point of the code be a response to the &#60;code&#62;deviceready&#60;/code&#62; event.&#60;/p&#62;
&#60;p&#62;After some googling, I found that most information on this matter is either
inaccurate, incomplete or outdated, that is until I found &#60;a href=&#34;http://stackoverflow.com/a/10457158/243798&#34;&#62;this answer&#60;/a&#62; by
&#60;a href=&#34;http://dougan.me&#34;&#62;Robert Dougan&#60;/a&#62; on StackOverflow:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;Sencha Touch 2 will listen to that event and call your onReady/launch methods&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;therefore if you try listening to them in the launch method,
it has already been fired.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;Just put your logic inside the launch method in your application.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;To verify this claim, I dug into &#60;code&#62;sencha-touch-debug.js&#60;/code&#62; distributed with
Sencha Touch 2.2 and found the following code:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;if (Ext.browser.is.PhoneGap &#38;amp;&#38;amp; !Ext.os.is.Desktop) {
    if (!Ext.readyListenerAttached) {
        Ext.readyListenerAttached = true;
        document.addEventListener(&#39;deviceready&#39;, triggerFn, false);
    }
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;It appears that the &#60;code&#62;deviceready&#60;/code&#62; event is taken into account here as long as
&#60;code&#62;Ext.browser.is.PhoneGap&#60;/code&#62; is true in a mobile browser envronment, which, in the
same source code, means:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;if (typeof window.PhoneGap != &#39;undefined&#39; ||
    typeof window.Cordova != &#39;undefined&#39;  ||
    typeof window.cordova != &#39;undefined&#39;) {
    isWebView = true;
    this.setFlag(&#39;PhoneGap&#39;);
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Here, the global variable PhoneGap, cordova or Cordova needs to be defined to
satisfy Sencha Touch 2&#39;s expectation of PhoneGap environment. Those globals
are defined in the &#60;code&#62;cordova-x.y.x.js&#60;/code&#62; file included in the PhoneGap/Cordova
project files.&#60;/p&#62;
&#60;p&#62;So what needs to be done for the integration is simple (if not clear):&#60;/p&#62;
&#60;p&#62;include &#60;code&#62;cordova-x.y.x.js&#60;/code&#62; in the js section of &#60;code&#62;app.json&#60;/code&#62; project file so that
the microloader knows to load it up early:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;&#38;quot;js&#38;quot;: [
    {
        &#38;quot;path&#38;quot;: &#38;quot;path/to/cordova-x.y.z.js&#38;quot;,
    },
    {
        &#38;quot;path&#38;quot;: &#38;quot;touch/sencha-touch.js&#38;quot;,
        &#38;quot;x-bootstrap&#38;quot;: true
    },
    {
        &#38;quot;path&#38;quot;: &#38;quot;app.js&#38;quot;,
        &#38;quot;bundle&#38;quot;: true, 
        &#38;quot;update&#38;quot;: &#38;quot;delta&#38;quot;
    }
],
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Run &#60;code&#62;sencha app build package&#60;/code&#62; and drop the files it produces to the &#60;code&#62;www&#60;/code&#62;
folder in the PhoneGap project.&#60;/p&#62;
&#60;p&#62;Compile, ship.&#60;/p&#62;
</description>
                <pubDate>Tue, 28 May 2013 15:24:30 -0600</pubDate>
                <link>https://duan.ca/2013/05/28/sencha-touch-2-and-phonegap-integration/</link>
                <guid isPermaLink="true">https://duan.ca/2013/05/28/sencha-touch-2-and-phonegap-integration/</guid>
            </item>
            <item>
                <title>Sencha Touch Workflow with GNU Make and Tmux</title>
                <description>&#60;p&#62;I throw this Makefile to the root directory of my Sencha Touch 2 projects for
workflow automation.&#60;/p&#62;
&#60;p&#62;Assuming you write in CoffeeScript and run Tmux in a terminal:&#60;/p&#62;
&#60;p&#62;&#60;code&#62;make develop&#60;/code&#62; will put &#60;code&#62;compass&#60;/code&#62; and &#60;code&#62;coffee&#60;/code&#62; to watch mode, in addition to
spawning a local web server with Python 3. The three commands will run in three
separate Tmux panes.&#60;/p&#62;
&#60;p&#62;&#60;code&#62;make watch&#60;/code&#62; does the same thing sans the server spawning.&#60;/p&#62;
&#60;p&#62;&#60;code&#62;make&#60;/code&#62; simply compile coffee script files and sass files.&#60;/p&#62;
&#60;p&#62;You can figure out the granular commands with some minimal knowledge of GNU
Make.&#60;/p&#62;
&#60;script src=&#34;https://gist.github.com/DaNmarner/5659003.js&#34;&#62;&#60;/script&#62;
</description>
                <pubDate>Mon, 27 May 2013 15:00:00 -0600</pubDate>
                <link>https://duan.ca/2013/05/27/sencha-touch-workflow-with-gnu-make-and-tmux/</link>
                <guid isPermaLink="true">https://duan.ca/2013/05/27/sencha-touch-workflow-with-gnu-make-and-tmux/</guid>
            </item>
            <item>
                <title>Dynamic Height for List Item in Sencha Touch 2</title>
                <description>&#60;p&#62;tl;dr: Set the &#60;code&#62;itemHeight&#60;/code&#62; value to &#60;code&#62;auto&#60;/code&#62; and you&#39;ll get list items
with dynamic height in Sencha Touch 2.&#60;/p&#62;
&#60;p&#62;In the Ext.List component provided by Sencha Touch 2, all SimpleListItem
(or ListItem) has the same height. This means if your items each has content
of different height, the list would look awkward.&#60;/p&#62;
&#60;p&#62;Fear not! Here&#39;s a solution (and its discovery).&#60;/p&#62;
&#60;p&#62;Load up a Ext.List and inspect one of the item element with Chrome/Safari
developer tool, you&#39;ll find its &#60;code&#62;element.style&#60;/code&#62; has &#60;code&#62;height: 47px !important;&#60;/code&#62;:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2013/05/height.png&#34; alt=&#34;Default Height on List Item in Sencha Touch 2&#34; /&#62;&#60;/p&#62;
&#60;p&#62;Here&#39;s the key: CSS properties under &#60;code&#62;element.style&#60;/code&#62; are set by Javascript.
In other words, any attempt to override this property in stylesheet will fail.
(Try it by specifying a height value on &#60;code&#62;div.x-list-item&#60;/code&#62;, or any other class
you suspect, if you need some convincing).&#60;/p&#62;
&#60;p&#62;So, how do we fix this with Javascript? If you examine the documentaion,
Ext.List has a config option &#60;code&#62;itemHeight&#60;/code&#62; with a default value. You can set it
to a value that works best with all potential heights of your item content,
resulting in items with identical heights. Setting &#60;code&#62;itemHeight&#60;/code&#62; to &#60;code&#62;auto&#60;/code&#62;,
however, will make each item container flow with its inner element, thus
achive dynamic height.&#60;/p&#62;
</description>
                <pubDate>Sun, 19 May 2013 16:03:30 -0600</pubDate>
                <link>https://duan.ca/2013/05/19/dynamic-height-for-list-item-in-sencha-touch-2/</link>
                <guid isPermaLink="true">https://duan.ca/2013/05/19/dynamic-height-for-list-item-in-sencha-touch-2/</guid>
            </item>
            <item>
                <title>Sencha Touch 2.2 Alpha Sass Bug Workaround</title>
                <description>&#60;p&#62;Sencha &#60;a href=&#34;http://cdn.sencha.com/touch/alpha/touch-2.2.0-alpha.zip&#34;&#62;released&#60;/a&#62; a new version Sencha Touch with Windows Phone 8 support.
But since it&#39;s an alpha, there are a few more things to do than what the
&#60;a href=&#34;http://cdn.sencha.com/touch/alpha/2.2.0.52/release-notes.html&#34;&#62;release note&#60;/a&#62; says to get it working.&#60;/p&#62;
&#60;p&#62;One thing I&#39;ve noticed is that when you generate a new app with&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;sencha generate app Foo path/to/foo
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;and make the changes to &#60;code&#62;resources/sass/app.scss&#60;/code&#62; according to the release
note, &#60;code&#62;compass compile path/to/foo/resources/sass&#60;/code&#62; fails complaining a font
file is missing:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;File not found or cannot be read: path/to/foo/resources/sass/stylesheets/fonts/pictos/pictos-web.woff
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To fix this, copy the needed fonts to where it supposed to be:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;cd path/to/foo
mkdir -p resources/sass/stylesheets/fonts/pictos
cp touch/resources/themes/fonts/pictos/pictos-web.* resources/sass/stylesheets/fonts/pictos/
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The next error you&#39;ll see from &#60;code&#62;compass compile&#60;/code&#62; is caused by the name changes
to a few sass files in the framework. Long-story short, you need to change
&#60;code&#62;resources/sass/app.scss&#60;/code&#62; to the following:&#60;/p&#62;
&#60;script src=&#34;https://gist.github.com/4533833.js&#34;&#62;&#60;/script&#62;
&#60;p&#62;and &#60;code&#62;compass&#60;/code&#62; should be happy from there.&#60;/p&#62;
&#60;p&#62;While you are at it, why not checkout the magical Windows Phone 8 theme
included in Sencha Touch 2.2 alpha.&#60;/p&#62;
</description>
                <pubDate>Mon, 14 Jan 2013 13:47:00 -0600</pubDate>
                <link>https://duan.ca/2013/01/14/sencha-touch-22-alpha-sass-bug-workaround/</link>
                <guid isPermaLink="true">https://duan.ca/2013/01/14/sencha-touch-22-alpha-sass-bug-workaround/</guid>
            </item>
            <item>
                <title>Windows Phone 8 Theme in Sencha Touch 2.2</title>
                <description>&#60;p&#62;Sencha Touch 2.2 Alpha shipped with Windows Phone 8/IE 10 support.
And it&#39;s pretty impressive! Just take a look at the starter app under the
original theme and the Windows Phone 8 theme:&#60;/p&#62;
&#60;p&#62;The Default Theme:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2013/01/original-theme.png&#34; alt=&#34;Sencha Touch 2.2 default theme&#34; /&#62;&#60;/p&#62;
&#60;p&#62;WP8 Theme:&#60;/p&#62;
&#60;p&#62;&#60;img src=&#34;/assets/2013/01/wp8-theme.png&#34; alt=&#34;Sencha Touch 2.2 windows phone 8 theme&#34; /&#62;&#60;/p&#62;
&#60;p&#62;And it only takes a minute or two to get to the second screen.
(if you have Sencha Cmd and Sencha Touch SDK 2.2 alpha ready). Here&#39;s how.&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;In SDK folder, generate the app with &#60;code&#62;sencha generate app Foo path/to/foo&#60;/code&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;/2013/01/14/Sencha-Touch-22-Alpha-Sass-Bug-Workaround.html&#34;&#62;Workaround&#60;/a&#62; the bug shipped in this alpha version. This won&#39;t be
necessary once the bug has been fixed in the next release&#60;/li&#62;
&#60;li&#62;Open &#60;code&#62;resources/sass/app.scss&#60;/code&#62; in the generated project folder )it should
look like &#60;a href=&#34;https://gist.github.com/4533833&#34;&#62;this&#60;/a&#62; after step 2).
Replace every appearance of the word &#60;em&#62;default&#60;/em&#62; to &#38;quot;windows&#38;quot;. Then run
&#60;code&#62;compass compile resources/sass&#60;/code&#62; in the project root.&#60;/li&#62;
&#60;li&#62;Serve the project in a web server (I usually do
&#60;code&#62;python -m SimpleHTTPServer&#60;/code&#62;), fire up its url (localhost:800) and...&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Boom!&#60;/p&#62;
</description>
                <pubDate>Mon, 14 Jan 2013 13:45:00 -0600</pubDate>
                <link>https://duan.ca/2013/01/14/windows-phone-8-theme-in-sencha-touch-22/</link>
                <guid isPermaLink="true">https://duan.ca/2013/01/14/windows-phone-8-theme-in-sencha-touch-22/</guid>
            </item>
            <item>
                <title>&#34;Hello, World!&#34; The Hard Way with Sencha Touch</title>
                <description>&#60;p&#62;When I first got into the amazing Sencha Touch HTML5 framwork, it came across
as a compilation of visual components that looks mobile, &#60;a href=&#34;http://compass-style.org&#34;&#62;easily themable&#60;/a&#62;,
leverage the latest HTML5 technology to be efficient and, best
of all, are created within the Javascript code as oppose to being shoved
in to an HTML file and demand DOM tinkering later.&#60;/p&#62;
&#60;p&#62;But a closer look would reveal a lot more goodies beyond those handy
components in Sencha Touch. It offers &#60;a href=&#34;https://web.archive.org/web/20130117172701/http://docs.sencha.com/touch/2-1/#!/guide/class_system&#34;&#62;a class system&#60;/a&#62;, a &#60;a href=&#34;https://web.archive.org/web/20130120111258/http://www.sencha.com/learn/architecting-your-app-in-ext-js-4-part-1/&#34;&#62;M&#60;/a&#62;&#60;a href=&#34;https://web.archive.org/web/20130106185309/http://www.sencha.com/learn/architecting-your-app-in-ext-js-4-part-2&#34;&#62;V&#60;/a&#62;&#60;a href=&#34;https://web.archive.org/web/20130124092547/http://www.sencha.com/learn/architecting-your-app-in-ext-js-4-part-3/&#34;&#62;C&#60;/a&#62;&#60;a href=&#34;https://web.archive.org/web/20130109001131/http://www.sencha.com/blog/architecting-your-app-with-sencha-touch-2-mvc/&#34;&#62;pattern&#60;/a&#62;, tools that handles code dependency, compression and native
packaging, etc. Albeit daunting, learning and embracing all of those offerings
makes a quite enjoyable coding experience and rewards me with development
effieciency overall.&#60;/p&#62;
&#60;p&#62;Sometimes though, I need complete control of a visual component that doesn’t
exist in the framework. How to make this work with everything mentioned above
is implied in various tutorials posted by the Sencha team, but I couldn’t find
a clear illustration of that, which is why I decided to write one here.&#60;/p&#62;
&#60;p&#62;Here’s our goal: make a component that displays data from a model with our own
custom HTML; manage it along with some provided components from the framework
and follow the MVC pattern.&#60;/p&#62;
&#60;p&#62;I assume you have the basics set up. I’m using Sencha Cmd 3.0.0.250, Sencha
Touch SDK 2.1.0 and OS X Mountain Lion as of this writing.&#60;/p&#62;
&#60;p&#62;Let’s start by generating a MVC-ready skeleton project called HelloWorld. Go to
the SDK’s folder and type:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    sencha generate app HelloWorld ~/helloworld

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;replace the last parameter with the path you would like for the project files
to stay. We’ll be working in this folder from now on.&#60;/p&#62;
&#60;p&#62;In the skeleton project, a main view was created under &#60;code&#62;app/view/Main.js&#60;/code&#62; and
declared as dependency for &#60;code&#62;app.js&#60;/code&#62;. An instance of it is created when the app
finished loading. We’ll keep this setup as our main view. Let’s reduce&#60;code&#62;app/view/Main.js&#60;/code&#62; to a simplest possble form for our purposes:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    Ext.define(&#39;HelloWorld.view.Main&#39;, {
      extend: &#39;Ext.Container&#39;,
      config: {
        items: [ { xtype: &#39;helloview&#39; } ]
      }
    });

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Following the convention, we name the class in corrispondance with its
filepath within the &#60;code&#62;app&#60;/code&#62; folder (‘view/Main.js’ =&#38;gt; ‘view.Main’). All
classes created with &#60;code&#62;Ext.define&#60;/code&#62; should follow this convention so that Sencha
tools can relate code dependencies to file structure and do its magic for us.
We’ll circle back to this.&#60;/p&#62;
&#60;p&#62;Our main view will be a plain container and has a &#60;code&#62;helloview&#60;/code&#62; in it. An&#60;code&#62;Ext.Container&#60;/code&#62; has the ability to … contain stuff. Specifically, it can
organize &#60;code&#62;Ext.Component&#60;/code&#62;s visually. &#60;code&#62;helloview&#60;/code&#62; will be that component. Let’s
define it next.&#60;/p&#62;
&#60;p&#62;Create the file &#60;code&#62;app/view/HelloView.js&#60;/code&#62; as the following:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    Ext.define(&#39;HelloWorld.view.HelloView&#39;, {
      extend: &#39;Ext.Component&#39;,
      xtype: &#39;helloview&#39;,
      config: {
        tpl: &#39;&#38;lt;div class=&#38;quot;greeting&#38;quot;&#38;gt;Hello, {name}!&#38;lt;/div&#38;gt;&#39;
      }
    });

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;As promised, &#60;code&#62;HelloWorld.view.HelloView&#60;/code&#62; is a &#60;code&#62;Ext.Component&#60;/code&#62;. We declare its&#60;code&#62;xtype&#60;/code&#62; to be the one we used in the main view. The really interesting part is
its &#60;code&#62;tpl&#60;/code&#62; configuration. This is where our customization integrates with the
rest of the Sencha Touch framework, so it’s worth dive into a bit deeper.&#60;/p&#62;
&#60;p&#62;(&#60;em&#62;Caution&#60;/em&#62;: &#60;code&#62;tpl&#60;/code&#62; can not be mixed with &#60;code&#62;items&#60;/code&#62;, if you want standard components
mixed in with yours, make them share a container and arrange a proper layout
there.)&#60;/p&#62;
&#60;p&#62;Take a look at the official &#60;a href=&#34;https://web.archive.org/web/20130117172701/http://docs.sencha.com/touch/2-1/#!/api/Ext.Component-cfg-tpl&#34;&#62;documentation for &#60;code&#62;tpl&#60;/code&#62;&#60;/a&#62;. It accepts an&#60;a href=&#34;https://web.archive.org/web/20130117172701/http://docs.sencha.com/touch/2-1/#!/api/Ext.XTemplate&#34;&#62;&#60;code&#62;Ext.XTemplate&#60;/code&#62;&#60;/a&#62;, which is basically free-range HTML plus some syntax to
insert data provided to the component. Apply all your HTML skills here! For
illustration purposes, we only throw in a basic &#60;code&#62;&#38;lt;div&#38;gt;&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;The &#60;code&#62;{name}&#60;/code&#62; part will be replaced by the actual data, which every&#60;code&#62;Ext.Component&#60;/code&#62; has as a configuration option by default. Being such option
means two things:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;1. You can specify its value in the class definition, as we did for `tpl`.
2. It gets a &#38;quot;getter/setter&#38;quot; that let you query/change its value at anytime
    through the instance&#39;s existence.

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;We’ll use the setter for &#60;code&#62;data&#60;/code&#62; – &#60;code&#62;setData()&#60;/code&#62; to populate this field in the
template later. &#60;code&#62;setData()&#60;/code&#62; accept one raw Javascript object and make its
properties accessible to the template.&#60;/p&#62;
&#60;p&#62;Next, let’s make a simplistic model in &#60;code&#62;app/model/Greetee.js&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    Ext.define(&#39;HelloWorld.model.Greetee&#39;, {
      extend: &#39;Ext.data.Model&#39;,
      config: {
        fields: [&#39;name&#39;]
      }
    });

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;A model, with a field ‘name’. Hey, that’s &#60;code&#62;as simple as possible, but no simpler&#60;/code&#62;, Einstein would endorse it!&#60;/p&#62;
&#60;p&#62;We won’t use any proxy or store in conjunction with the model because we
only need to show how a customized view works within the Sencha Touch MVC
pattern. Speaking of which, a controller does just that. So to tie everything
togeter, here’s &#60;code&#62;app/controller/Main.js&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    Ext.define(&#39;HelloWorld.controller.Main&#39;, {
      extend: &#39;Ext.app.Controller&#39;,
      config: {
        models: [&#39;Greetee&#39;],
        views: [&#39;HelloView&#39;],
        refs: {
          helloView: &#39;.helloview&#39;
        }
      },
      launch: function() {
        var m = Ext.create(&#39;HelloWorld.model.Greetee&#39;, { name: &#39;World&#39; });
        return this.getHelloView().setData(m.getData());
      }
    });

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To get reference to the view components, Sencha Touch provide &#60;code&#62;refs&#60;/code&#62; in
controllers, through which we map &#60;code&#62;hello&#60;/code&#62; to our customized component’s xtype.
There are more details about this in the &#60;a href=&#34;https://web.archive.org/web/20130117172701/http://docs.sencha.com/touch/2-1/#!/guide/controllers&#34;&#62;offical documentation&#60;/a&#62;. We now
can use &#60;code&#62;getHelloView()&#60;/code&#62; in other methods. &#60;code&#62;launch()&#60;/code&#62; gets invoked after
everything gets loaded, and we tie the model and the view together here.&#60;/p&#62;
&#60;p&#62;Again, a little imagination might help. By that I mean the data source of the
model could be from a RESTful network API, a picture from a phone camera via
Phonegap, a record from browser’s localstorage, etc. We simply created one in
memory for illustration.&#60;/p&#62;
&#60;p&#62;We use &#60;code&#62;getHelloView()&#60;/code&#62; to get reference to our &#60;code&#62;helloview&#60;/code&#62; instance, then use
its &#60;code&#62;setData()&#60;/code&#62; to populate its template field. But we can’t pass in the model
object directly (as mentioned above, a raw Javascript object is needed), so
we convert it with its &#60;code&#62;getData()&#60;/code&#62; method.&#60;/p&#62;
&#60;p&#62;Finally, we specify the &#60;code&#62;models&#60;/code&#62; and &#60;code&#62;views&#60;/code&#62; involved with this controller in&#60;code&#62;config&#60;/code&#62; so that the files of these classes gets loaded properly. For the same
purpose, we need to open &#60;code&#62;app.js&#60;/code&#62; and add the following line into the object
passed to &#60;code&#62;Ext.application()&#60;/code&#62; (which is a controller too):&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    controllers: [&#39;Main&#39;],

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This makes the framework aware of our &#60;code&#62;HelloWorld.controller.Main&#60;/code&#62;. It’s
unnecessary to use the full class name becaue we followed the naming
convention.&#60;/p&#62;
&#60;p&#62;At this point, our code is complete. Go to the project folder in terminal
and fire up a web server:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    python -m SimpleHTTPServer

&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Open &#60;a href=&#34;http://localhost:8000&#34;&#62;http://localhost:8000&#60;/a&#62; in your browser and take a gander!&#60;/p&#62;
&#60;p&#62;A screenshot of this app would be an overkill, if you follow along correctly,
the phrase “Hello, World!” will show, and that’s all.&#60;/p&#62;
&#60;p&#62;So this long-winded excercise results in not much. But I hope you won’t find
it pointless. When I try to construct my app UI with Sencha Touch, I first try
my best to make the Senche component work with the design. When breaking out
and customize is inevitable, I try to stay within the framwork as much as
possible to make the most out of it. What’s described in this article is a
common way to do that.&#60;/p&#62;
</description>
                <pubDate>Fri, 11 Jan 2013 00:00:00 -0700</pubDate>
                <link>https://duan.ca/2013/01/11/hello-world-the-hard-way-with-sencha-touch/</link>
                <guid isPermaLink="true">https://duan.ca/2013/01/11/hello-world-the-hard-way-with-sencha-touch/</guid>
            </item>
            <item>
                <title>MongoDB, PHP And Mountain Lion</title>
                <description>&#60;p&#62;Here are the necessary steps to make PHP work with MongoDB on vanilla
Mac OS X 10.8 (Mountain Lion):&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;Install &#60;a href=&#34;https://developer.apple.com/downloads/index.action&#34;&#62;Command Lion Tools for Xcode&#60;/a&#62;&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install Homebrew:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;ruby -e &#38;quot;$(curl -fsSkL raw.github.com/mxcl/homebrew/go)&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Prioritize Homebrew&#39;s binaries in $PATH:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;echo &#38;quot;export /usr/local/bin:$PATH&#38;quot; &#38;gt;&#38;gt; ~/.bash_profile
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install PHP 5.4 with Homebrew:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;# Setup the tap for dependencies
brew tap homebrew/dupes
# This is the best 
brew tap josegonzalez/homebrew-php
# And install
brew install php54
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install MongoDB with Homebrew&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;brew install mongodb
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install &#38;quot;PHP Driver&#38;quot; for MongoDB:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;sudo pecl install mongo
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Done.&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Now go run some PHP-MongoDB scripts with the build-in web server from
PHP 5.4 like you normally would (don&#39;t forget to start &#60;code&#62;mongod&#60;/code&#62;) and everything
should work.&#60;/p&#62;
</description>
                <pubDate>Thu, 29 Nov 2012 09:37:30 -0600</pubDate>
                <link>https://duan.ca/2012/11/29/mongodb-php-and-mountain-lion/</link>
                <guid isPermaLink="true">https://duan.ca/2012/11/29/mongodb-php-and-mountain-lion/</guid>
            </item>
            <item>
                <title>CoffeeScript And Mountain Lion</title>
                <description>&#60;p&#62;Here are the necessary steps to install CoffeeScript on
Mac OS X 10.8 (Mountain Lion):&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;Install &#60;a href=&#34;https://developer.apple.com/downloads/index.action&#34;&#62;Command Lion Tools for Xcode&#60;/a&#62;&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install Homebrew:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;ruby -e &#38;quot;$(curl -fsSkL raw.github.com/mxcl/homebrew/go)&#38;quot;
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install Node.js with Homebrew:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;brew install node
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install npm (the version comes with node doesn&#39;t install CoffeeScript
properly for some reason):&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;curl https://npmjs.org/install.sh | sh
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Install CoffeeScript with npm:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;npm install -g coffee-script
# add environment variable to ~/.bashrc
echo &#38;quot;export NODE_PATH=/usr/local/lib/node_modules&#38;quot;
. ~/.bashrc
&#60;/code&#62;&#60;/pre&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Done!&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;I had to google around to figure out the environment variable and the issue
with npm. Hopefully this will help some folks in the similar need.&#60;/p&#62;
</description>
                <pubDate>Wed, 28 Nov 2012 15:11:00 -0600</pubDate>
                <link>https://duan.ca/2012/11/28/coffeescript-and-mountain-lion/</link>
                <guid isPermaLink="true">https://duan.ca/2012/11/28/coffeescript-and-mountain-lion/</guid>
            </item>
            <item>
                <title>Keep Git Social</title>
                <description>&#60;p&#62;&#60;em&#62;A project I&#39;m working on uses &#60;a href=&#34;http://about.gitlab.com&#34;&#62;GitlabHQ&#60;/a&#62;, I think it is a cool open source
project and the developers are doing an excellent job of making a sweet web
interface for Git projects. However, as I found out today, &#60;a href=&#34;https://github.com/gitlabhq/gitlabhq/issues/1298&#34; title=&#34;Gitlab Issue: Closed&#34;&#62;my one issue&#60;/a&#62;
with it was closed without fixing. And that&#39;s what finally propelled me to
writing this airticle.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;Do you know, the Linux kernel is broken by hundreds of commited patches
everyday?&#60;/p&#62;
&#60;p&#62;That, of course, is a trick question. Yes, &#60;em&#62;technically&#60;/em&#62;, hundreds (if not
thousands) of patches were commited to &#60;em&#62;a&#60;/em&#62; git repository of the Linux kernel
that isn&#39;t different in anyway from &#60;em&#62;the&#60;/em&#62; repository. What makes the
repository &#38;quot;conanical&#38;quot; is the fact that Linus Torvalds owns it. If the world
lost access to his hard drive because Linus was hit by a bus (I would never
wish this to happen) today, all the Linux community need to do is figure out
who is next BDFL. Then his/hers would become &#60;em&#62;the&#60;/em&#62; Linux repository.&#60;/p&#62;
&#60;p&#62;In other words, what makes the difference is purely social.&#60;/p&#62;
&#60;p&#62;&#60;strong&#62;Not trying to fit the social structure of a software project into a
repository is the biggest strength of git.&#60;/strong&#62; This is why I frown everytime
I see a discussion about locking down branches of a Git repository.&#60;/p&#62;
&#60;p&#62;Making developers &#38;quot;own&#38;quot; branches on a shared repository is a pratice
inheritated from the days of centralized version control. Git doesn&#39;t provide
built-in support for this, for good reasons.&#60;/p&#62;
&#60;p&#62;With Subversion, the ultimate goal of branch-wise access control is to keep
out
bad changes made by developers while give them the benefits of version
control, namely:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;provide a backup of the change history&#60;/li&#62;
&#60;li&#62;let others to follow his/her progress so that they can contribute via
patches or collaborate if they have write access.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;With Git, these are easily achieved by a personal repository read-accessible
for the team.&#60;/p&#62;
&#60;p&#62;Meanwhile, write access is granted at the repository level, but only to very
few or, more preferably, one person. This is possible because each team member
can have and only push to his/her own repositories. No change made by others
will make their way to the &#38;quot;conanical&#38;quot; repository unless its owner(s) activaly
pulls them in. Bad changes therefore is kept out.&#60;/p&#62;
&#60;p&#62;Additionally, Git has &#60;a href=&#34;http://git-scm.com/book/en/Git-Branching&#34;&#62;features&#60;/a&#62; flexible enough to support all kinds of
&#60;a href=&#34;http://nvie.com/posts/a-successful-git-branching-model&#34;&#62;development process&#60;/a&#62;es, partially because its branches, by design, are not
responsible for enforcing access permissions.&#60;/p&#62;
&#60;p&#62;Consider developer John working on a shared git repository with locked
branches: where would he push his temporary branch to for backup, if he can
only write to &#60;code&#62;feature42&#60;/code&#62; and &#60;code&#62;johns_branch&#60;/code&#62;? How does he get
&#60;code&#62;emergency_bugfix_14159&#60;/code&#62; pair reviewed at 4am? If he uses his own repo for
those, does it mean he has to force the whole team to know about it?  How does
it affect work when a &#60;code&#62;git branch --all&#60;/code&#62; produces a phone book?&#60;/p&#62;
&#60;p&#62;Break Git&#39;s design gets you no where nice.&#60;/p&#62;
&#60;p&#62;And no, Git&#39;s social model doesn&#39;t add work to the owner of the &#38;quot;official&#38;quot;
repository. Afterall, Git was designed with he linux kernel in mind!  Linus
himself explains it the best (summary provided below):&#60;/p&#62;
&#60;div class=&#34;video-container&#34;&#62;
    &#60;iframe src=&#34;http://www.youtube.com/embed/4XpnKHJAok8&#34; frameborder=&#34;0&#34; allowfullscreen&#62;&#60;/iframe&#62;
&#60;/div&#62;
&#60;p&#62;In short, Linus only review pull requests from a few &#38;quot;lieutenants&#38;quot; he trusts,
and they each follow the same process with their trusted few.  And the pyramid
trickles all the way down. Here agian, Git solves a problem by getting out of
the way of the project&#39;s social stucture, instead of trying to encapsulate it.&#60;/p&#62;
&#60;p&#62;Git was the first version control system I&#39;ve ever used starting in 2008.
I&#39;ve since gradually realized that not everyone is lucky like me, in the sense
that svn has been working just fine for a lot of people. When their project
switches to Git, emulating the svn/old workflow with functionality provided by
projects like &#60;code&#62;gitolite&#60;/code&#62; is only natural. But if you are one of them, and want
more creativity from your team, perhaps embracing the social aspect of Git by
breaking the shackles on their hand is a good thing to try.&#60;/p&#62;
</description>
                <pubDate>Wed, 31 Oct 2012 10:02:30 -0600</pubDate>
                <link>https://duan.ca/2012/10/31/keep-git-social/</link>
                <guid isPermaLink="true">https://duan.ca/2012/10/31/keep-git-social/</guid>
            </item>
            <item>
                <title>Windows 8 First Impression</title>
                <description>&#60;p&#62;I use KDE on Arch Linux for 80% of the time, OS X the other 20%. But I
got a copy of Windows 8 Pro for free as student so I decided to install it
along with Visual Studio 2012 Ultimate so that if I ever need to develop on any
Microsoft platforms, I&#39;ll have the environment ready. I jogged down these
impression after about a 30 minutes trial.&#60;/p&#62;
&#60;p&#62;What I didn&#39;t like:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;I have to use a .iso file the hardway (in my case, burning it to an
usb drive)even if I only wanted to upgrade from Windows 7.&#60;/li&#62;
&#60;li&#62;When upgrading from Windows 7, only the free space is counted as usable
for the new system, which means upgrading is not an option for I have a
mere 26G partition reserved for Windows.&#60;/li&#62;
&#60;li&#62;The old Mobile ATI graphic card driver stopped working after installation.&#60;/li&#62;
&#60;li&#62;Apps don&#39;t share same session between the tile and deskop interface.&#60;/li&#62;
&#60;li&#62;Contacts from different accounts (in my case, facebook and twitter) are
mixed together and there doesn&#39;t seem to be an easy way to filter them.&#60;/li&#62;
&#60;li&#62;I signed in with a Mircrosoft account for the operating system. But when
I started Visual Studio, it asked me to sign in with the same account.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;What I did like:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;The tile interface looked nice.&#60;/li&#62;
&#60;li&#62;IE10 is fast. Looked particularly smooth under the tile interface.&#60;/li&#62;
&#60;li&#62;For an old machine I installed it on, the whole system is very responsive.&#60;/li&#62;
&#60;li&#62;The tile interface is not unintuitive. When in doubt, one of these actions
always gets me where I wanted:
&#60;ol&#62;
&#60;li&#62;Mouse to upper-right corner.&#60;/li&#62;
&#60;li&#62;Mouse to upper-left corner and then move down.&#60;/li&#62;
&#60;li&#62;Press the Win key on keyboard.&#60;/li&#62;
&#60;/ol&#62;
&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;I&#39;m not going to speculate on whether the general public will love or hate
this version of Windows. But one thing is for sure: there is going to be an
reaction. I can see it go both ways.&#60;/p&#62;
</description>
                <pubDate>Sat, 27 Oct 2012 23:59:59 -0600</pubDate>
                <link>https://duan.ca/2012/10/27/windows-8-first-impression/</link>
                <guid isPermaLink="true">https://duan.ca/2012/10/27/windows-8-first-impression/</guid>
            </item>
            <item>
                <title>Testing Method Within Constructor With Jasmine.js</title>
                <description>&#60;p&#62;How do you test whether a method is called witin the constructor of an object
with Jasmine.js?&#60;/p&#62;
&#60;p&#62;Turns out, you need to &#60;code&#62;spyOn()&#60;/code&#62; the &#38;quot;raw&#38;quot; reference of the &#38;quot;method&#38;quot;, which
really just a function on the &#60;code&#62;prototype&#60;/code&#62; of your &#38;quot;class&#38;quot; object. An example
will make it clear:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;// is &#39;load()&#39; getting called during construction?
describe(&#38;quot;MyObject&#38;quot;, function() {
  it(&#38;quot;should call load() during construction&#38;quot;, function() {
    spyOn(MyObject.prototype, &#39;load&#39;);
    new MyObject();
    expect(MyObject.prototype.load).toHaveBeenCalled();
  });
}
&#60;/code&#62;&#60;/pre&#62;
</description>
                <pubDate>Sun, 30 Sep 2012 00:00:00 -0600</pubDate>
                <link>https://duan.ca/2012/09/30/testing-method-within-constructor-with-jasminejs/</link>
                <guid isPermaLink="true">https://duan.ca/2012/09/30/testing-method-within-constructor-with-jasminejs/</guid>
            </item>
            <item>
                <title>Integrating Sencha Touch 2 and Cordova (pre-2.0)</title>
                <description>&#60;h2&#62;&#38;quot;The Goals&#60;/h2&#62;
&#60;ol&#62;
&#60;li&#62;
&#60;p&#62;Use Sencha Command to create and package an MVC-structured Sencha Touch 2
project.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Use Cordova/PhoneGap (1.9) to wrap the project to deliver it in the App
Store.&#60;/p&#62;
&#60;/li&#62;
&#60;li&#62;
&#60;p&#62;Leverage the APIs provided by Cordova/PhoneGap to give Sencha Touch 2
project more native capabilities.&#60;/p&#62;
&#60;/li&#62;
&#60;/ol&#62;
&#60;h2&#62;The Process&#60;/h2&#62;
&#60;p&#62;Goal #1 and #2 can be achieved by &#60;a href=&#34;http://robertdougan.com/posts/packaging-sencha-touch-2-with-phonegap-cordova&#34; title=&#34;Packaging Sencha Touch 2 with PhoneGap (Cordova)&#34;&#62;these steps well described by Robert Dougan
&#60;/a&#62;. In essence, you need to create a normal Sencha Touch 2 project
using Sencha Command; a Cordova (1.7 in Roberts post, but works fine with 1.9)
project. Then tell Sencha Command to build in the &#60;code&#62;www&#60;/code&#62; folder, where Cordova
looks for the HTML5 assets to package. Finally, build and deploy the Cordova
project the usual way.&#60;/p&#62;
&#60;p&#62;That, of course, is not the end of the story, otherwise you wouldn&#39;t be
reading this. When you try to achive goal #3, that is, when you use the
Cordova API in the Sencha Touch project, such as:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    navigator.notification.alert(
        &#39;Winter is coming!&#39;,
        noted, // callback function
        &#39;be warned&#39;,
        &#38;quot;&#38;quot;Yes M&#39;lord&#38;quot;&#38;quot;
    );
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Sencha Command will report error and refuse to &#38;quot;&#38;quot;compile&#38;quot;&#38;quot; if you run&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    sencha app build package
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;because of the unknown namespace introduced by Cordova.&#60;/p&#62;
&#60;p&#62;One way to workaround this problem is manually replacing the command, which
involves compiling the SASS files, consolidate all Javascript dependencies
into a single file, minify everything and move the result to the &#60;code&#62;www&#60;/code&#62;
folder.&#60;/p&#62;
&#60;p&#62;Doesn&#39;t sound fun, does it?&#60;/p&#62;
&#60;p&#62;So, here&#39;s a trick to put Sencha Command back on track, use&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    if (!Ext.os.is.Desktop) {
    }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;to wrap around the Cordova API calls, so the previous example becomes&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;    if (!Ext.os.is.Desktop) {
        navigator.notification.alert(
            // ...
        );
    }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This way, Sencha Command will ignore the conditioned code block since its
running on the desktop environment, therefore compiles like a charm. And the
code will work as intended in emulator/device environment.&#60;/p&#62;
&#60;p&#62;You are welcome.&#60;/p&#62;
&#60;h2&#62;The Bonus&#60;/h2&#62;
&#60;p&#62;Now that you are using Sencha Touch 2 and Cordova API (like a boss!), here&#39;s
another tip to improve your workflow. When I&#39;m developing hybrid apps, I spend
the majority of time editing Java(Coffee)script/(S)CSS files. But surely
enough, there will come a period where I have to debug the packaged app in the
emulator. Switching from my text editor (Vim) to Xcode and hitting ⌘r
REALLY gets old.&#60;/p&#62;
&#60;p&#62;Luckily, Cordova provides some command line alternatives. If
you generate a Cordova project as described in
&#60;a href=&#34;https://web.archive.org/web/20161025042756/http://robertdougan.com/posts/packaging-sencha-touch-2-with-phonegap-cordova&#34; title=&#34;Cordova Command-Line Documentaion&#34;&#62;Cordova&#39;s documentaion&#60;/a&#62; like so:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;./path/to/cordova-ios/bin/create /path/to/project com.example.name Project
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;There&#39;ll be a folder called &#60;code&#62;cordova&#60;/code&#62; in the newly created project, which won&#39;t
be in your project if you create it with Xcode with &#60;a href=&#34;http://robertdougan.com/posts/packaging-sencha-touch-2-with-phonegap-cordova&#34; title=&#34;Packaging Sencha Touch 2 with PhoneGap (Cordova)&#34;&#62;Robert&#39;s method&#60;/a&#62;.
In &#60;code&#62;cordova&#60;/code&#62; folder are three lovely Bash scripts that let&#39;s you compile the
Xcode project (&#60;code&#62;debug&#60;/code&#62;, which also does the next thing), run the result in  an
ios emulator (&#60;code&#62;emulate&#60;/code&#62;) and watch the logging information (&#60;code&#62;log&#60;/code&#62;).&#60;/p&#62;
&#60;p&#62;Copy the folder to the path of &#60;code&#62;YourProject.xcodeproj&#60;/code&#62;, and boom! You can now
quit Xcode and run the scripts in there directly from your terminal. (What I like to
do is to use GNU Make to combine Sencha commands with those scripts so that
I could just hit ⌘b in MacVim to make my latest code run in the simulator.)&#60;/p&#62;
&#60;p&#62;Happy coding!&#60;/p&#62;
</description>
                <pubDate>Mon, 20 Aug 2012 19:09:34 -0600</pubDate>
                <link>https://duan.ca/2012/08/20/integrating-sencha-touch-2-and-cordova-pre-20/</link>
                <guid isPermaLink="true">https://duan.ca/2012/08/20/integrating-sencha-touch-2-and-cordova-pre-20/</guid>
            </item>
    </channel>
</rss>