<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programming | AkitaOnRails.com</title><link>https://akitaonrails.github.io/en/tags/programming/</link><description>Fabio Akita's blog — tech, career, and assorted geek topics. English edition.</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 19 Oct 2026 23:20:52 +0000</lastBuildDate><atom:link href="https://akitaonrails.github.io/en/tags/programming/index.xml" rel="self" type="application/rss+xml"/><item><title>VS Code Is the New Punch Card</title><link>https://akitaonrails.github.io/en/2026/04/11/vs-code-is-the-new-punch-card/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/04/11/vs-code-is-the-new-punch-card/</guid><pubDate>Sat, 11 Apr 2026 12:00:00 -0300</pubDate><description>&lt;p&gt;Every time someone asks whether juniors are going to stop learning how to program because LLMs can write code for them, I have the same reaction: you&amp;rsquo;re asking the wrong question.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re confusing &lt;strong&gt;code input&lt;/strong&gt; with &lt;strong&gt;software engineering&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Those are not the same thing. They never were.&lt;/p&gt;
&lt;p&gt;There was a time when programming meant knowing how to convert numbers into binary in your head and jam instructions straight into memory addresses, bit by bit, by hand. There was a time when programming meant knowing how to organize a punched-card deck, knowing whether the deck order was right, knowing where one bad hole wrecked execution, and knowing how to debug visually without the modern fantasy of infinite backspace. There was a time when real programming meant knowing 6502, Z80, and Assembly because computers had so few resources that every byte actually mattered, not as a figure of speech.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Every time someone asks whether juniors are going to stop learning how to program because LLMs can write code for them, I have the same reaction: you&rsquo;re asking the wrong question.</p>
<p>You&rsquo;re confusing <strong>code input</strong> with <strong>software engineering</strong>.</p>
<p>Those are not the same thing. They never were.</p>
<p>There was a time when programming meant knowing how to convert numbers into binary in your head and jam instructions straight into memory addresses, bit by bit, by hand. There was a time when programming meant knowing how to organize a punched-card deck, knowing whether the deck order was right, knowing where one bad hole wrecked execution, and knowing how to debug visually without the modern fantasy of infinite backspace. There was a time when real programming meant knowing 6502, Z80, and Assembly because computers had so few resources that every byte actually mattered, not as a figure of speech.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/altair-8800-computer.jpg" alt="Altair 8800, symbol of the era when programming still meant physical panels and manual instruction entry"  loading="lazy" /></p>
<p><em>Front panel and switches: before editors, before IDEs, before comfortable terminals.</em></p>
<p>And there were phases of computing that were even worse than punch cards. The video below shows someone programming an LGP-21, one of the oldest personal computers ever made (the second oldest, after the 1950s Bendix G15). Starts at the 5-minute mark:</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/TJjRCCetyo4?start=300"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>Imagine what that was: you typed the program in binary directly on a typewriter, looking at the accumulator, instruction by instruction, then physically flipped a switch to execute, and the result got typed back onto paper. The metric wasn&rsquo;t framerate. It was characters per minute. An operation you can do today in the blink of an eye inside any app used to take hours of human work, typing bit by bit, verifying, testing, verifying again.</p>
<p>It&rsquo;s the same thing happening with typing code in a text editor today versus an AI agent running in your place. The manual way still works, the same way the Altair front panel kept working for years after compilers became common. But the tool of choice shifted, and the gap in speed and effort is the same order of magnitude that separated the LGP-21 from a modern text editor. Our generation is watching this transition happen in slow motion, and a lot of people don&rsquo;t want to see it.</p>
<p>Then compilers got better. C showed up. Machines got fatter, consoles moved into the 32/64-bit era, PCs got more decent, and Assembly stopped being the center of everything. It became what it should be: a low-level tool, local optimization, critical routines, bootstrapping, drivers, that sort of thing. Nobody serious looked at that transition and said, &ldquo;well, that&rsquo;s it, programming is over because the compiler writes machine instructions for you now.&rdquo;</p>
<p>The 21st century brought the Web and shoved an entire generation into HTML, CSS, and a pile of markup bureaucracy that adds very little intellectual value while demanding a ton of manual labor just to get it mostly right. I still think the industry dragged that model out way too long. For way too many years, programmers became glorified form operators, CRUD assemblers, <code>div</code> aligners, priests of front-end frameworks that all do the same thing with slightly different syntax.</p>
<p>Then the 2010s bubble made it worse.</p>
<p>I&rsquo;ve already written about that in <a href="/en/2026/02/08/rant-ai-killed-programmers/">RANT: Did AI Kill Programmers?</a> and also in <a href="/en/2026/03/05/37-days-of-vibe-coding-immersion-conclusions-on-business-models/">37 Days of Vibe Coding Immersion</a>. The startup bubble, cheap money, and the hiring frenzy produced a legion of very bad programmers, coming out of two-month bootcamps and sketchy online courses promising Google salaries with no foundation, no education, and no depth. The market spent a decade pretending that was normal. It wasn&rsquo;t. Same story as always: lots of volume, little value, and a whole lot of people confusing inflated employability with actual competence.</p>
<p>And when the layoffs started in 2022, that did not come out of nowhere. I spent years warning that the bubble would pop. It&rsquo;s all there in the playlist <a href="https://www.youtube.com/watch?v=wpPv1dJWjDs&amp;list=PLdsnXVqbHDUehzKjiRruy--gncHz9Injy&amp;pp=sAgC"target="_blank" rel="noopener">EU AVISEI</a>. The message was always the same: once the cheap money dried up, the bar would go back up, and the only people with a real shot would be the ones who had made the effort to actually learn Computer Science. The next economic cycle was always going to be less about hiring volume and more about efficiency. That&rsquo;s exactly what happened.</p>
<h2>What really changed<span class="hx:absolute hx:-mt-20" id="what-really-changed"></span>
    <a href="#what-really-changed" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>LLMs went mainstream at the end of 2022. That&rsquo;s true. But mainstream is not the same thing as useful for serious work.</p>
<p>Throughout 2023 and 2024, I was already using AI to write code. Did it work? Sure, it worked. But it was still full of nonsense: too many hallucinations, too many agent loops, context getting lost too easily, tooling breaking too often, too much cost for too little reliability. It was useful for experienced programmers who knew how to keep the thing on a leash. It still wasn&rsquo;t a mature tool for day-to-day heavy lifting.</p>
<p>For me, the turn came at the end of 2025. That&rsquo;s when the combination of better models, prompt caching, decent tool calling, inference optimizations, context windows that were actually useful in practice, and above all real agent interfaces made the whole thing stop feeling like conference-demo theater and start feeling like an actual work tool.</p>
<p>That was the point where Claude Code, Codex, OpenCode, and the rest stopped being &ldquo;autocomplete on steroids&rdquo; and became a different category of interface.</p>
<p>To me, Claude Code is already the new terminal. The editor has moved into the background.</p>
<p>I talked about that in <a href="/en/2026/03/31/migrating-my-home-server-with-claude-code/">Migrating my Home Server with Claude Code</a>, too. I simply have no patience left to burn attention on Linux shell busywork when the problem is mundane: installing a server, bringing up and organizing Docker services, hardening a firewall, reviewing security rules, tuning kernel parameters, auditing <code>dmesg</code>, digging through systemd logs, that kind of thing. I let Claude do the heavy lifting, and I review direction and risk. Ironically, my Linux machines have never felt more stable, faster, or more robust.</p>
<p>Today, if you spend your day building software, going back to the raw combo of text editor plus terminal and doing everything manually starts to feel like regression. Not because typing became impossible. Of course not. I&rsquo;ve been typing code for decades. The problem is something else: it became a waste of attention.</p>
<p>If I can describe an intent, ask an agent to inspect the codebase, edit twenty files, run tests, compile, fix the fallout, and bring me back a proposed change in minutes, why exactly am I supposed to feel nostalgic about hand-typing boilerplate inside VS Code?</p>
<p>I don&rsquo;t.</p>
<p>And this is where a distinction a lot of people still don&rsquo;t get matters. You should not use a coding agent like some dumb editor extension, the kind of thing where you say &ldquo;generate this file here&rdquo; and then spend the next half hour micromanaging every line in a tiny corner pane. That&rsquo;s using a Ferrari to go buy bread around the block. The big gain does not come from treating Claude Code, Codex, or similar tools like glorified autocomplete inside VS Code. The gain comes when you drop the editor-operator mindset and start treating the agent like an actual pair programmer.</p>
<p>Instead of acting like a professional typist, you move up a level. You act more like a tech lead, product owner, QA, manager of the flow. You define intent, explain context, demand criteria, ask for a plan, ask it to run tests, ask for refactors, ask for alternative approaches, ask it to review its own change. You leave the manual code labor to the agent and use your own brain to judge direction, priority, risk, and quality.</p>
<p>But there is a balance there, and I&rsquo;ve already covered it in other Agile Vibe Coding posts. You do not hand over the wheel and let the LLM <code>git push</code> everything blind. And you also don&rsquo;t swing to the opposite extreme and turn into a comma cop, nitpicking every tiny detail until the agent becomes one more layer of bureaucracy and kills the speed advantage. Both extremes are bad. In one, you outsource responsibility. In the other, you strangle productivity.</p>
<p>The right point on that pendulum is somewhere else: use XP and actual engineering discipline to sustain the speed. Continuous refactoring. Tests. CI. Review. Fast feedback. Small code. Incremental change. That&rsquo;s exactly what I documented in posts like <a href="/en/2026/02/20/zero-to-post-production-in-1-week-using-ai-on-real-projects-behind-the-m-akita-chronicles/">From Zero to Post-Production in 1 Week - How to Use AI on Real Projects</a> and <a href="/en/2026/03/01/software-is-never-done-4-projects-life-after-deploy-one-shot-prompt-myth/">Software Is Never &lsquo;Done&rsquo;</a>. The 10x multiplier does not come from model magic. It comes from the model plus a sane process.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/cursor-homepage-crop.png" alt="Modern coding-agent interface, representing the shift from the traditional editor to an intent-driven, execution-assisted workflow"  loading="lazy" /></p>
<p><em>The interface changed. The need for judgment did not.</em></p>
<h2>VS Code is the new punch card<span class="hx:absolute hx:-mt-20" id="vs-code-is-the-new-punch-card"></span>
    <a href="#vs-code-is-the-new-punch-card" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>That&rsquo;s what the title means.</p>
<p>VS Code did not &ldquo;become bad.&rdquo; That&rsquo;s not the point. Punch cards weren&rsquo;t &ldquo;bad&rdquo; in their own historical context either. They were a massive step up from toggling bits by hand or rewiring a board. The point is that they were the mechanism of their era for feeding instructions into the machine.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/punched-card-program-deck.jpg" alt="Punched-card deck, from an era when the profession demanded more discipline in preparing input than comfort in the interface"  loading="lazy" /></p>
<p><em>VS Code is not the enemy. It&rsquo;s just becoming the input mechanism of the previous era.</em></p>
<p>Today, text editors are becoming that again: an input mechanism that still works, will still be around for a long time, but is no longer the center of the activity.</p>
<p>If you&rsquo;ve never looked at those older eras of computing, I already went through it in <a href="/2020/10/23/akitando-86-o-computador-de-turing-e-von-neumann-por-que-calculadoras-nao-sao-computadores/">Akitando #86 - The Turing and Von Neumann Computer</a>:</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/G4MvFT8TGII"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>And if you want a refresher on why 6502, Z80, and old machines forced a different kind of discipline, go back to the <a href="/2020/06/04/akitando-80-o-guia-hardcore-de-introducao-a-computacao/">Hardcore Guide to Computing Fundamentals</a> and <a href="/2020/06/18/akitando-81-aprendendo-sobre-computadores-com-super-mario-do-jeito-hardcore/">Learning About Computers with Super Mario (Hardcore++)</a>. That wasn&rsquo;t old-man nostalgia. It was there to show that in every era the interface changes, but the machine still demands precision.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/akitando-80-6502.jpg" alt="Thumbnail from Akitando #80, part of the series built to teach computing fundamentals through the 6502 and the microcomputer era"  loading="lazy" /></p>
<p><em>This is what a good part of Akitando existed for: teaching what still holds when the fashionable tool changes.</em></p>
<p>And it&rsquo;s worth remembering something a lot of people forget: the 146 videos on <a href="https://www.youtube.com/@Akitando"target="_blank" rel="noopener">Akitando</a>, more than 96 hours of material, were built precisely to teach this kind of foundation to Computer Science students, juniors, and people trying to stop being framework button-pushers. I recorded all of that because I could already see the industry pushing too many people toward manual busywork and not enough understanding. Ironically, now that agents are here, that archive is more relevant than ever.</p>
<p>The interface changed again.</p>
<p>First you needed to know how to type the instruction.
Then you needed to know how to organize the deck.
Then you needed to know how to convince the compiler.
Then you needed to know how to stitch together frameworks, HTML, CSS, YAML, CI, containers, cloud, ORMs, queues, observability, and fifty other layers of junk.</p>
<p>Now you need to know how to <strong>orchestrate an agent</strong>.</p>
<p>And again, that does not eliminate foundations. It only changes where the manual labor ends and the intellectual work begins.</p>
<h2>&ldquo;So we don&rsquo;t need Computer Science anymore?&rdquo;<span class="hx:absolute hx:-mt-20" id="so-we-dont-need-computer-science-anymore"></span>
    <a href="#so-we-dont-need-computer-science-anymore" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quite the opposite.</p>
<p>Now you need it more.</p>
<p>Someone with no foundation looks at an agent issuing a <code>SELECT * FROM table</code>, sees the thing working locally against 300 fake rows, and assumes everything is fine. In production the query pulls a million rows, blows memory, degrades latency, backs up a queue, congests connections, and the person has no clue why &ldquo;it works on my machine&rdquo; but melts in production.</p>
<p>That&rsquo;s the real problem.</p>
<p>The agent does not know your system&rsquo;s context the way an experienced engineer does. It doesn&rsquo;t know which tables are going to grow tenfold next quarter. It doesn&rsquo;t know which endpoint needs to answer in 80 ms and which one can take 2 seconds. It doesn&rsquo;t know which flow needs a transaction, which one needs idempotency, which one needs a pessimistic lock, which one needs async compensation, which one needs auditing, which one can never leak sensitive data.</p>
<p>It may get the syntax right.</p>
<p>But syntax was never the hardest part.</p>
<p>I already said that in <a href="/en/2026/02/24/rant-akita-caved-to-ai/">RANT: Did Akita Bend Over for AI??</a>: what AI is really good at is removing the mundane work. And thank God for that. I did not get into computing to become an IDE operator. I have no romantic attachment to formatting HTML, fighting CSS, assembling the same old CRUD, gluing one more framework onto an old stack, or writing the same pile of infrastructure code for the hundredth time when any decent machine should be able to produce that by now.</p>
<p>So what is left after that mundane layer disappears?</p>
<p>Exactly the part that separates amateurs from real programmers:</p>
<ul>
<li>domain modeling</li>
<li>architecture</li>
<li>trade-offs</li>
<li>performance</li>
<li>scalability</li>
<li>security</li>
<li>observability</li>
<li>maintainability</li>
<li>readability</li>
<li>operational cost</li>
<li>product decisions</li>
</ul>
<p>All of that still exists. All of that is still hard. All of that still depends on judgment.</p>
<h2>The mistake people make when they think programming was typing<span class="hx:absolute hx:-mt-20" id="the-mistake-people-make-when-they-think-programming-was-typing"></span>
    <a href="#the-mistake-people-make-when-they-think-programming-was-typing" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Some people genuinely think that if the machine writes the code, then the need to understand software is gone.</p>
<p>That is the same stupidity as thinking the compiler killed the need to understand computers.</p>
<p>It didn&rsquo;t.</p>
<p>It only killed the need to write everything in Assembly.</p>
<p>And thank God for that too.</p>
<p>Same thing here: coding agents do not kill the need to understand software. They kill the need for you to be a syntax typist.</p>
<p>And good riddance.</p>
<p>There is a nice irony here too: for years the industry sold the fantasy that programming meant &ldquo;learning a framework.&rdquo; Then it sold the fantasy that programming meant &ldquo;learning React.&rdquo; Then it sold the fantasy that programming meant &ldquo;learning the stack of the month.&rdquo; Now it&rsquo;s going to sell the fantasy that programming means &ldquo;learning prompt engineering.&rdquo;</p>
<p>It doesn&rsquo;t.</p>
<p>Prompts are an interface.
Frameworks are an interface.
IDEs are an interface.
Punch cards were an interface.</p>
<p>Programming is still the act of instructing a machine to compute something useful under real constraints.</p>
<p>People who understand that survive every tool shift.
People who don&rsquo;t become operators of whatever the trendy tool is, and when the trend changes, they go down with it.</p>
<h2>What I think is going to happen to juniors<span class="hx:absolute hx:-mt-20" id="what-i-think-is-going-to-happen-to-juniors"></span>
    <a href="#what-i-think-is-going-to-happen-to-juniors" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>So let&rsquo;s answer the original question properly.</p>
<p>Juniors are not going to stop learning.</p>
<p>But they are going to have to learn <strong>something else</strong>.</p>
<p>If the junior of 2015 could spend years hiding ignorance behind low-value manual tasks, tweaking views, adjusting CSS, assembling dumb endpoints, copying Stack Overflow snippets, and making it all look like &ldquo;productivity,&rdquo; that hiding place is going away.</p>
<p>The junior of the agent era is either going to level up faster or get exposed faster. There isn&rsquo;t much middle ground.</p>
<p>If they use agents and actually study fundamentals, they&rsquo;ll be able to test hypotheses faster, read more code, compare more solutions, iterate more, make mistakes earlier and fix them earlier. They&rsquo;ll learn more in less time.</p>
<p>But if they use agents without foundations, all they&rsquo;ll do is outsource their own ignorance. They&rsquo;ll become reviewers who cannot review. They&rsquo;ll accept patches they do not understand. They&rsquo;ll approve decisions they do not know how to measure. They&rsquo;ll confuse &ldquo;passed locally&rdquo; with &ldquo;ready for production.&rdquo;</p>
<p>That kind of professional is dangerous.</p>
<p>Far more dangerous than the old junior who was at least limited by their own speed.</p>
<h2>The post-bubble world<span class="hx:absolute hx:-mt-20" id="the-post-bubble-world"></span>
    <a href="#the-post-bubble-world" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The good news is that this comes right after the collapse of the dumbest phase of the hiring bubble.</p>
<p>It&rsquo;s past time for the market to stop rewarding labor-intensive stupidity as if it were competence. It&rsquo;s past time to stop treating stack bureaucracy as technical depth. It&rsquo;s past time to stop confusing commit volume with engineering value.</p>
<p>If the new era wipes out a good chunk of that theater, great.</p>
<p>In a post-bubble, post-miracle-bootcamp, post-CSS-as-a-career, post-CRUD-as-a-profession world, foundations go back to being what they should always have been: the main asset.</p>
<p>People who understand operating systems, databases, networking, data structures, compilers, computer architecture, profiling, debugging, concurrency, consistency, security, and cost will use agents as an exoskeleton.</p>
<p>People who understand none of that will use agents as a crutch.</p>
<p>An exoskeleton amplifies strength.
A crutch only tries to hide weakness.</p>
<h2>&ldquo;But this isn&rsquo;t sustainable&rdquo;<span class="hx:absolute hx:-mt-20" id="but-this-isnt-sustainable"></span>
    <a href="#but-this-isnt-sustainable" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>There is always someone with the same excuse: &ldquo;well, I don&rsquo;t think this is sustainable, the data centers can&rsquo;t keep up, the prices are too heavily subsidized, there&rsquo;s no way this can keep going like this.&rdquo;</p>
<p>And to be fair, that person is not entirely wrong.</p>
<p>It just doesn&rsquo;t change a thing about what I have to do tomorrow morning.</p>
<p>This kind of concern might be great for bar talk or an X thread, but it doesn&rsquo;t help me decide anything useful. Me, you, none of us are going to sit down with Anthropic or OpenAI leadership and redesign data-center capex, renegotiate power contracts, decide subsidy margins, or plan the next GPU generation. There is no concrete action for us that comes out of this besides repeating that &ldquo;someday this will be a problem.&rdquo;</p>
<p>It&rsquo;s the same mindset as the person in the 1990s saying, &ldquo;let&rsquo;s not use the internet too much, it&rsquo;s too slow, the limits are too low, the price per kilobyte is absurd, better wait until someone fixes it.&rdquo; Or the person in the early 2000s looking at mobile data and saying, &ldquo;2G is too slow, too limited, better not depend on it.&rdquo; Why exactly would you want to be that person?</p>
<p>Thank God OpenAI, Anthropic, and the rest are fighting like hell and heavily subsidizing this race. I&rsquo;m taking full advantage of it. I&rsquo;ve already burned through my entire Claude Max 20x, already hit the extra-usage ceiling, already burned through my Codex plan, and upgraded to Pro so I can keep using it this weekend. People paying a monthly subscription and barely touching it are, in practice, subsidizing me to use as much as I can. I have no intention of slowing down. Why would you?</p>
<p>If prices change tomorrow, if infrastructure gets tighter, if the game changes, then I reassess tomorrow. That&rsquo;s how technology has always worked. While the window is open, the rational move is not to slow yourself down in advance. The rational move is to learn as much as possible, extract as much as possible, and build an advantage while everybody else is busy explaining why they still haven&rsquo;t started.</p>
<h2>The decision is still human<span class="hx:absolute hx:-mt-20" id="the-decision-is-still-human"></span>
    <a href="#the-decision-is-still-human" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>At the end of the day, nothing that matters actually changed.</p>
<p>Someone still has to look at the result and decide:</p>
<ul>
<li>can this go to production?</li>
<li>can this handle load?</li>
<li>is this readable?</li>
<li>is this secure?</li>
<li>is this maintainable?</li>
<li>does this fit the rest of the system?</li>
<li>does this solve the right problem?</li>
</ul>
<p>If the answer is no, someone still has to know <strong>why</strong> it&rsquo;s no.</p>
<p>More importantly, someone still has to know <strong>how to fix it</strong>.</p>
<p>That&rsquo;s why, in the age of agents, foundational knowledge did not become less important. It became more expensive to be wrong without it.</p>
<p>VS Code is the new punch card.</p>
<p>Not because it became useless.</p>
<p>But because we&rsquo;re finally entering an era where the act of typing code by hand stops being the center of the profession.</p>
<p>And honestly? About time.</p>
<blockquote>
  <p><strong>AI reflects who you are.</strong></p>
<p>If you&rsquo;re good, it accelerates good code.</p>
<p>If you&rsquo;re bad, it accelerates technical debt at industrial speed.</p>
<p>AI is not going to take a bad programmer and turn them into a good one. It never did, it doesn&rsquo;t, and it won&rsquo;t.</p>

</blockquote>
<p>That&rsquo;s why foundations matter more now than they did before.</p>
<p>The agent can write. You&rsquo;re still the one who has to know whether what it wrote is any good.</p>
]]></content:encoded><category>coding-agents</category><category>programming</category></item><item><title>Elixir 101 - Introducing the Syntax</title><link>https://akitaonrails.github.io/en/2015/11/25/elixir-101-introducing-the-syntax/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2015/11/25/elixir-101-introducing-the-syntax/</guid><pubDate>Wed, 25 Nov 2015 17:25:00 -0200</pubDate><description>&lt;p&gt;I&amp;rsquo;ve been posting a lot of articles in the last few weeks, check out the &lt;a href="http://www.akitaonrails.com/elixir"target="_blank" rel="noopener"&gt;&amp;ldquo;Elixir&amp;rdquo; tag&lt;/a&gt; to read all of them.&lt;/p&gt;
&lt;p&gt;Many tutorial series start introducing a new language by its syntax. I subverted the order. Elixir is not interesting because of its syntax. Erlang is interesting all by itself, because of its very mature, highly reliable, highly concurrent, distributed nature. But its syntax is not for the faint of heart. It&amp;rsquo;s not &amp;ldquo;ugly&amp;rdquo;, it&amp;rsquo;s just too different for those of us from the C school to easily digest. It derives from Prolog, and this is one small example of a Prolog exercise:&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ve been posting a lot of articles in the last few weeks, check out the <a href="http://www.akitaonrails.com/elixir"target="_blank" rel="noopener">&ldquo;Elixir&rdquo; tag</a> to read all of them.</p>
<p>Many tutorial series start introducing a new language by its syntax. I subverted the order. Elixir is not interesting because of its syntax. Erlang is interesting all by itself, because of its very mature, highly reliable, highly concurrent, distributed nature. But its syntax is not for the faint of heart. It&rsquo;s not &ldquo;ugly&rdquo;, it&rsquo;s just too different for those of us from the C school to easily digest. It derives from Prolog, and this is one small example of a Prolog exercise:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-prolog" data-lang="prolog"><span class="line"><span class="cl"><span class="c1">% P03 (*): Find the K&#39;th element of a list.</span>
</span></span><span class="line"><span class="cl"><span class="c1">%     The first element in the list is number 1.</span>
</span></span><span class="line"><span class="cl"><span class="c1">%     Example:</span>
</span></span><span class="line"><span class="cl"><span class="c1">%     ?- element_at(X,[a,b,c,d,e],3).</span>
</span></span><span class="line"><span class="cl"><span class="c1">%     X = c</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">% The first element in the list is number 1.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">% element_at(X,L,K) :- X is the K&#39;th element of the list L</span>
</span></span><span class="line"><span class="cl"><span class="c1">%    (element,list,integer) (?,?,+)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">% Note: nth1(?Index, ?List, ?Elem) is predefined</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">element_at</span><span class="p">(</span><span class="nv">X</span><span class="p">,[</span><span class="nv">X</span><span class="p">|</span><span class="k">_</span><span class="p">],</span><span class="mi">1</span><span class="p">).</span>
</span></span><span class="line"><span class="cl"><span class="nf">element_at</span><span class="p">(</span><span class="nv">X</span><span class="p">,[</span><span class="k">_</span><span class="p">|</span><span class="nv">L</span><span class="p">],</span><span class="nv">K</span><span class="p">)</span> <span class="p">:-</span> <span class="nv">K</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">,</span> <span class="nv">K1</span> <span class="o">is</span> <span class="nv">K</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nf">element_at</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">L</span><span class="p">,</span><span class="nv">K1</span><span class="p">).</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Erlang has a similar syntax, with the idea of phrases divided by commas and ending with a dot.</p>
<p>José Valim played it very smart: he chose the best of the available mature platforms and coated it with a layer of modern syntax and easier-to-use standard libraries. This is the same problem implemented in Elixir:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defmodule</span> <span class="no">Exercise</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="o">[</span><span class="n">found</span><span class="o">|</span><span class="n">_</span><span class="o">]</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="k">do</span><span class="p">:</span> <span class="n">found</span>
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="o">[</span><span class="n">_</span><span class="o">|</span><span class="n">rest</span><span class="o">]</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span> <span class="k">when</span> <span class="n">position</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">element_at</span><span class="p">(</span><span class="n">rest</span><span class="p">,</span> <span class="n">position</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>If I copy and paste the code above in an IEx shell I can test it out like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(7)&gt; Exercise.element_at([&#34;a&#34;, &#34;b&#34;, &#34;c&#34;, &#34;d&#34;, &#34;e&#34;], 3)
&#34;c&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This simple exercise shows us some of the powerful bits of Erlang that Elixir capitalizes upon, such as pattern matching and recursion.</p>
<p>First of all, every function <strong>must</strong> be defined inside a module, which you name with <tt>defmodule My.Module do .. end</tt>. Internally it becomes the atom &ldquo;Elixir.My.Module&rdquo;. Nesting modules is just a longer name concatenated with dots.</p>
<p>Then you can define a public function with the <tt>def my_function(args) do .. end</tt> block, which is just a macro for the same <tt>def my_function(args), do: &hellip;</tt> construct. Private functions are declared with <tt>defp</tt>.</p>
<p>A function is actually identified by the pair of its name and its arity. So above we have <tt>element_at/2</tt> which means it accepts 2 arguments. But we have 2 functions with the same arity: the difference is the <strong>pattern matching</strong>.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="o">[</span><span class="n">found</span><span class="o">|</span><span class="n">_</span><span class="o">]</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="k">do</span><span class="p">:</span> <span class="n">found</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Here we are saying: the first argument will be an array, decompose it. The first element of the array will be stored in the &ldquo;found&rdquo; variable, the rest &ldquo;_&rdquo; will be ignored. And the second argument must be the number &ldquo;1&rdquo;. This is the description of the so-called &ldquo;pattern&rdquo;, and it should &ldquo;match&rdquo; the input arguments received. This is <strong>&ldquo;call-by-pattern&rdquo;</strong> semantics.</p>
<p>But what if we want to pass a position other than &ldquo;1&rdquo;? That&rsquo;s why we have this second definition:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>def element_at([_|rest], position) when position &gt; 1 do</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Now, the first argument again <strong>needs</strong> to be an array, but this time we don&rsquo;t care about the first element, just the rest of the array without the first element. And any position other than &ldquo;1&rdquo; will be stored in the &ldquo;position&rdquo; variable.</p>
<p>But this function is special: it is <strong>guarded</strong> to only allow a <tt>position</tt> that is larger than 1. What if we try a negative position?</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(8)&gt; Exercise.element_at([&#34;a&#34;, &#34;b&#34;, &#34;c&#34;, &#34;d&#34;, &#34;e&#34;], -3)
** (FunctionClauseError) no function clause matching in Exercise.element_at/2
    iex:7: Exercise.element_at([&#34;a&#34;, &#34;b&#34;, &#34;c&#34;, &#34;d&#34;, &#34;e&#34;], -3)</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>It says that none of the arguments we passed match any of the clauses defined above. We could have added a third definition just to catch those cases:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="n">_list</span><span class="p">,</span> <span class="n">_position</span><span class="p">),</span> <span class="k">do</span><span class="p">:</span> <span class="kp">nil</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Adding the underscore &ldquo;_&rdquo; before the variable name is the same as having just the underscore, but we are naming it just to make it more readable. Any arguments passed will just be ignored. And this is the more generic case if the previous 2 don&rsquo;t match.</p>
<p>The previous line is the same as writing:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>def element_at(_list, _position) do
  nil
end</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>I won&rsquo;t dive into macros for now. Just know that there is more than one way of doing things in Elixir and you can define those different ways using Erlang&rsquo;s built-in support for macros, dynamic code that is compiled at runtime. It&rsquo;s the way of doing metaprogramming in Elixir.</p>
<p>Now, going back to the implementation, the first function can still look weird; let&rsquo;s review it:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="o">[</span><span class="n">_</span><span class="o">|</span><span class="n">rest</span><span class="o">]</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span> <span class="k">when</span> <span class="n">position</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="n">element_at</span><span class="p">(</span><span class="n">rest</span><span class="p">,</span> <span class="n">position</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>What happens is: when we call <tt>Exercise.element_at([&ldquo;a&rdquo;, &ldquo;b&rdquo;, &ldquo;c&rdquo;, &ldquo;d&rdquo;, &ldquo;e&rdquo;], 3)</tt> the first argument will pattern match with <tt>[_|rest]</tt>. The first element &ldquo;a&rdquo; is discarded and the new list <tt>[&ldquo;b&rdquo;, &ldquo;c&rdquo;, &ldquo;d&rdquo;, &ldquo;e&rdquo;]</tt> is stored as &ldquo;<tt>rest</tt>&rdquo;.</p>
<p>Finally, we recurse the call, decrementing the &ldquo;<tt>position</tt>&rdquo; variable. So it becomes <tt>element_at([&ldquo;b&rdquo;, &ldquo;c&rdquo;, &ldquo;d&rdquo;, &ldquo;e&rdquo;], 2)</tt>. And it repeats until position becomes &ldquo;1&rdquo;, in which case the pattern matching falls to the other function defined as:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>def element_at([found|_], 1), do: found</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>In this case the rest of the array is pattern matched and the first element, &ldquo;c&rdquo;, is stored in the &ldquo;<tt>found</tt>&rdquo; variable; the rest of the array is discarded. It only got here because the position matched as &ldquo;1&rdquo;, so it just returns the variable &ldquo;found&rdquo;, which contains the 3rd element of the original array, &ldquo;c&rdquo;.</p>
<p>This is all nice and fancy, but in Elixir we could have just done this other version:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defmodule</span> <span class="no">Exercise</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">element_at</span><span class="p">(</span><span class="n">list</span><span class="p">,</span> <span class="n">position</span><span class="p">),</span> <span class="k">do</span><span class="p">:</span> <span class="no">Enum</span><span class="o">.</span><span class="n">at</span><span class="p">(</span><span class="n">list</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And we are done! Several tutorials will talk about how recursion and pattern matching to decompose lists solve a lot of problems, but Elixir gives us the convenience of treating lists as Enumerables and provides us a rich <a href="http://elixir-lang.org/docs/stable/elixir/Enum.html"target="_blank" rel="noopener">Enum</a> module with very useful functions such as <tt>at/2</tt>, <tt>each/2</tt>, <tt>take/2</tt>, and so on. Just pick what you need and you&rsquo;re managing lists like a boss.</p>
<p>Oh, and by the way, there is something called a <a href="http://elixir-lang.org/getting-started/sigils.html"target="_blank" rel="noopener">Sigil</a> in Elixir. Instead of writing the List of Strings explicitly, we could have done it like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(8)&gt; ~w(a b c d e f)
[&#34;a&#34;, &#34;b&#34;, &#34;c&#34;, &#34;d&#34;, &#34;e&#34;, &#34;f&#34;]</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Or, if we wanted a List of Atoms, we could do it like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(9)&gt; ~w(a b c d e f)a
[:a, :b, :c, :d, :e, :f]</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Lists, Tuples and Keyword Lists<span class="hx:absolute hx:-mt-20" id="lists-tuples-and-keyword-lists"></span>
    <a href="#lists-tuples-and-keyword-lists" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Well, this was too simple. You really need the idea of pattern matching and basic types in your mind to make it flow. Let&rsquo;s get another snippet from the <a href="http://www.akitaonrails.com/en/2015/11/18/ex-manga-downloadr-um-exercicio-com-elixir"target="_blank" rel="noopener">Ex Manga Downloadr</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defp</span> <span class="n">parse_args</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="n">parse</span> <span class="o">=</span> <span class="no">OptionParser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">args</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">switches</span><span class="p">:</span> <span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="ss">:string</span><span class="o">]</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">aliases</span><span class="p">:</span> <span class="o">[</span><span class="ss">n</span><span class="p">:</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">u</span><span class="p">:</span> <span class="ss">:url</span><span class="p">,</span> <span class="ss">d</span><span class="p">:</span> <span class="ss">:directory</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">case</span> <span class="n">parse</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="n">manga_name</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="n">url</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="n">directory</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="n">manga_name</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="n">directory</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="p">}</span> <span class="o">-&gt;</span> <span class="n">process</span><span class="p">(</span><span class="ss">:help</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The first part may puzzle you:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="no">OptionParser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">args</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">switches</span><span class="p">:</span> <span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="ss">:string</span><span class="o">]</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="ss">aliases</span><span class="p">:</span> <span class="o">[</span><span class="ss">n</span><span class="p">:</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">u</span><span class="p">:</span> <span class="ss">:url</span><span class="p">,</span> <span class="ss">d</span><span class="p">:</span> <span class="ss">:directory</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The <tt>OptionParser.parse/2</tt> receives just 2 arguments: 2 arrays. If you come from Ruby it feels like it&rsquo;s a Hash with optional brackets, translating to something similar to this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="c1"># this is wrong</span>
</span></span><span class="line"><span class="cl"><span class="no">OptionParser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">args</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="ss">switches</span><span class="p">:</span> <span class="p">{</span><span class="nb">name</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="ss">:string</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="ss">aliases</span><span class="p">:</span> <span class="p">{</span><span class="ss">n</span><span class="p">:</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">u</span><span class="p">:</span> <span class="ss">:url</span><span class="p">,</span> <span class="ss">d</span><span class="p">:</span> <span class="ss">:directory</span><span class="p">}</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This works in Ruby, but it is not the case in Elixir. There are optional brackets, but not where you think they are:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="c1"># this is the correct, more explicit version</span>
</span></span><span class="line"><span class="cl"><span class="no">OptionParser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">args</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="ss">:switches</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="o">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:string</span><span class="p">},</span> <span class="p">{</span><span class="ss">:url</span><span class="p">,</span> <span class="ss">:string</span><span class="p">},</span> <span class="p">{</span><span class="ss">:directory</span><span class="p">,</span> <span class="ss">:string</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">]</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="ss">aliases</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="o">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span><span class="ss">:n</span><span class="p">,</span> <span class="ss">:name</span><span class="p">},</span> <span class="p">{</span><span class="ss">:u</span><span class="p">,</span> <span class="ss">:url</span><span class="p">},</span> <span class="p">{</span><span class="ss">:d</span><span class="p">,</span> <span class="ss">:directory</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">]</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>WHAT!?!?</p>
<p>Yep, the second argument is actually an array with elements that are <strong>Tuples</strong> paired with an atom key and value, and some of the values are themselves arrays with tuples.</p>
<ol>
<li>
<p>in Elixir, Lists are what we usually call an Array, a Linked-List of elements. Linked-Lists, as you know from your Computer Science classes, make it easy to insert and remove elements.</p>
</li>
<li>
<p>in Elixir, Tuples are immutable fixed lists with fixed positions, with elements delimited by the brackets &ldquo;{}&rdquo;</p>
</li>
</ol>
<p>If the previous example was just too much, let&rsquo;s step back a little:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defmodule</span> <span class="no">Teste</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">teste</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span><span class="p">{</span><span class="ss">:hello</span><span class="p">,</span> <span class="n">world</span><span class="p">},</span> <span class="p">{</span><span class="ss">:foo</span><span class="p">,</span> <span class="n">bar</span><span class="p">}</span><span class="o">]</span> <span class="o">=</span> <span class="n">opts</span>
</span></span><span class="line"><span class="cl">    <span class="no">IO</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">world</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">bar</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Now we can call it like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(13)&gt; Teste.teste hello: &#34;world&#34;, foo: &#34;bar&#34;
world bar</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Which is the same as calling like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(14)&gt; Teste.teste([{:hello, &#34;world&#34;}, {:foo, &#34;bar&#34;}])
world bar</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This may confuse you, but it&rsquo;s very intuitive. You can just think of this combination of Lists (&quot;[]&quot;) with Tuple elements containing a pair of atom and value (&quot;{:key, value}&quot;) as behaving almost like Ruby Hashes being used for optional named arguments.</p>
<p>Then, we have the Pattern Match section in both previous examples:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">case</span> <span class="n">parse</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span><span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="n">manga_name</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="n">url</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="n">directory</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span><span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="n">manga_name</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="n">directory</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span><span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="p">}</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="n">process</span><span class="p">(</span><span class="ss">:help</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="o">[</span><span class="p">{</span><span class="ss">:hello</span><span class="p">,</span> <span class="n">world</span><span class="p">},</span> <span class="p">{</span><span class="ss">:foo</span><span class="p">,</span> <span class="n">bar</span><span class="p">}</span><span class="o">]</span> <span class="o">=</span> <span class="n">opts</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The last example is just decomposition. The previous example is pattern matching and decomposition. You match based on the atoms and positions within the tuples within the list. You match from the more narrow case to the more generic case. And in the process, the variables in the pattern are available for you to use in the matching case clause.</p>
<p>Let&rsquo;s understand the meaning of this line:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="p">{</span><span class="o">[</span><span class="nb">name</span><span class="p">:</span> <span class="n">manga_name</span><span class="p">,</span> <span class="ss">url</span><span class="p">:</span> <span class="n">url</span><span class="p">,</span> <span class="ss">directory</span><span class="p">:</span> <span class="n">directory</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>It is saying: given the results of the <tt>OptionParser.parse/2</tt> function, it must be a tuple with 3 elements. The second and third elements don&rsquo;t matter. But the first element must be a List with at least 3 tuples. And the keys of each tuple must be the atoms <tt>:name</tt>, <tt>:url</tt>, and <tt>:directory</tt>. If they&rsquo;re there, store the values of each tuple in the variables <tt>manga_name</tt>, <tt>url</tt>, and <tt>directory</tt>, respectively.</p>
<p>This may really confuse you in the beginning, but this combination of a List of Tuples is what&rsquo;s called a <a href="http://elixir-lang.org/getting-started/maps-and-dicts.html#keyword-lists"target="_blank" rel="noopener"><strong>Keyword List</strong></a>, and you will find this pattern many times, so get used to it.</p>
<p>Keyword Lists feel like a Map, but a Map has a different syntax:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">list</span> <span class="o">=</span> <span class="o">[</span><span class="ss">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="ss">b</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="ss">c</span><span class="p">:</span> <span class="mi">3</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="n">map</span> <span class="o">=</span> <span class="sx">%{:a =&gt; 1, :b =&gt; 2, :c =&gt; 3}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This should summarize it:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(1)&gt; list = [a: 1, b: 2, c: 3]
[a: 1, b: 2, c: 3]
iex(2)&gt; map = %{:a =&gt; 1, :b =&gt; 2, :c =&gt; 3}
%{a: 1, b: 2, c: 3}

iex(3)&gt; list[:a]
1
iex(4)&gt; map[:a]
1

iex(5)&gt; list.a
** (ArgumentError) argument error
    :erlang.apply([a: 1, b: 2, c: 3], :a, [])
iex(5)&gt; map.a
1

iex(6)&gt; list2 = [{:a, 1}, {:b, 2}, {:c, 3}]
[a: 1, b: 2, c: 3]
iex(7)&gt; list = list2
[a: 1, b: 2, c: 3]</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Keyword Lists are convenient as function arguments or return values. But if you want to process a collection of key-value pairs, use a dictionary-like structure, in this case a Map, especially if you need to search the collection using the key. They look similar, but the internal structures are not the same. A Keyword List is not a Map; it&rsquo;s just a convenience for a static list of tuples.</p>
<p>Finally, if this pattern matches the <tt>parse</tt> variable passed to the <tt>case</tt> block, it executes the statement <tt>process(manga_name, url, directory)</tt>, passing the 3 variables captured in the match. Otherwise it proceeds to try the next pattern in the <tt>case</tt> block.</p>
<p>The idea is that the &ldquo;=&rdquo; operator is not an &ldquo;assignment&rdquo;, it&rsquo;s a matcher: you match one side with the other. Read the error message when a pattern is not matched:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(15)&gt; [a, b, c] = 1
** (MatchError) no match of right hand side value: 1</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This is a matching error, not an assignment error. But if it succeeds this is what we have:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>iex(15)&gt; [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(16)&gt; a
1
iex(17)&gt; c
3</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This is List decomposition. It so happens that in the simple case it feels like a variable assignment, but it&rsquo;s much more complex than that.</p>
<h3>Pipelines<span class="hx:absolute hx:-mt-20" id="pipelines"></span>
    <a href="#pipelines" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>We use exactly those concepts of pattern matching on the elements returned from the HTML parsed by Floki in my Manga Downloadr:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="no">Floki</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">html</span><span class="p">,</span> <span class="s2">&#34;#listing a&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">|&gt;</span> <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">fn</span> <span class="p">{</span><span class="s2">&#34;a&#34;</span><span class="p">,</span> <span class="o">[</span><span class="p">{</span><span class="s2">&#34;href&#34;</span><span class="p">,</span> <span class="n">url</span><span class="p">}</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span> <span class="n">url</span> <span class="k">end</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The <tt>find/2</tt> takes an HTML string from the fetched page and matches against the CSS selectors in the second argument. The result is a List of Tuples representing the structure of each HTML Node found, in this case, this pattern: <tt>{&ldquo;a&rdquo;, [{&ldquo;href&rdquo;, url}], _}</tt></p>
<p>We can then <tt>Enum.map/2</tt>. A map is a function that receives each element of a list and returns a new list with new elements. The first argument is the original list and the second argument is a function that receives each element and returns a new one.</p>
<p>One of the main features of the Elixir language that most languages don&rsquo;t have is the <strong>Pipe</strong> operator (&quot;|&gt;&quot;). It behaves almost like UNIX&rsquo;s pipe operator &ldquo;|&rdquo; in any shell.</p>
<p>In UNIX we usually do stuff like &ldquo;<tt>ps -ef | grep PROCESS | grep -v grep | awk &lsquo;{print $2}&rsquo; | xargs kill -9</tt>&rdquo;</p>
<p>This is essentially the same as doing:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>ps -ef &gt; /tmp/ps.txt
grep mix /tmp/ps.txt &gt; /tmp/grep.txt
grep -v grep /tmp/grep.txt &gt; /tmp/grep2.txt
awk &#39;{print $2}&#39; /tmp/grep2.txt &gt; /tmp/awk.txt
xargs kill -9 &lt; /tmp/awk.txt</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Each UNIX process can receive something from standard input (STDIN) and output something to standard output (STDOUT). We can redirect the output using &ldquo;&gt;&rdquo;. But instead of doing all those extra steps and creating all those extra garbage temporary files, we can simply &ldquo;pipe&rdquo; the STDOUT of one command to the STDIN of the next command.</p>
<p>Elixir uses the same principles: we can simply use the returning value of a function as the <strong>first argument</strong> of the next function. So the first example of this section is the same as doing this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">results</span> <span class="o">=</span> <span class="no">Floki</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">html</span><span class="p">,</span> <span class="s2">&#34;#listing a&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">results</span><span class="p">,</span> <span class="n">fn</span> <span class="p">{</span><span class="s2">&#34;a&#34;</span><span class="p">,</span> <span class="o">[</span><span class="p">{</span><span class="s2">&#34;href&#34;</span><span class="p">,</span> <span class="n">url</span><span class="p">}</span><span class="o">]</span><span class="p">,</span> <span class="n">_</span><span class="p">}</span> <span class="o">-&gt;</span> <span class="n">url</span> <span class="k">end</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>In the same ExMangaDownloadr project we have this snippet:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defp</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="no">File</span><span class="o">.</span><span class="n">mkdir_p!</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">url</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">chapters</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">pages</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">images_sources</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">process_downloads</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">optimize_images</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">compile_pdfs</span><span class="p">(</span><span class="n">manga_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">|&gt;</span> <span class="n">finish_process</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And we just learned that it&rsquo;s the equivalent of doing the following (I&rsquo;m cheating a bit because the 3 final functions of the workflow are not transforming the input &ldquo;directory&rdquo;, just passing it through):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl">  <span class="n">defp</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="no">File</span><span class="o">.</span><span class="n">mkdir_p!</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">chapters</span>  <span class="o">=</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">chapters</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">pages</span>     <span class="o">=</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">pages</span><span class="p">(</span><span class="n">chapters</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">sources</span>   <span class="o">=</span> <span class="no">Workflow</span><span class="o">.</span><span class="n">images_sources</span><span class="p">(</span><span class="n">pages</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="no">Workflow</span><span class="o">.</span><span class="n">process_downloads</span><span class="p">(</span><span class="n">sources</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="no">Workflow</span><span class="o">.</span><span class="n">optimize_images</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="no">Workflow</span><span class="o">.</span><span class="n">compile_pdfs</span><span class="p">(</span><span class="n">directory</span><span class="p">,</span> <span class="n">manga_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">finish_process</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Or this much uglier version that we must read in reverse:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">defp</span> <span class="n">process</span><span class="p">(</span><span class="n">manga_name</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">directory</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="no">File</span><span class="o">.</span><span class="n">mkdir_p!</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">finish_process</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="no">Workflow</span><span class="o">.</span><span class="n">compile_pdfs</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="no">Workflow</span><span class="o">.</span><span class="n">optimize_images</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="no">Workflow</span><span class="o">.</span><span class="n">images_sources</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">          <span class="no">Workflow</span><span class="o">.</span><span class="n">pages</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="no">Workflow</span><span class="o">.</span><span class="n">chapters</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">),</span> <span class="n">manga_name</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>We can easily see how the Pipe Operator &ldquo;|&gt;&rdquo; makes any transformation pipeline much easier to read. Anytime you are starting from a value and passing the results through a <strong>chain of transformations</strong>, you will use this operator.</p>
<h3>Next Steps<span class="hx:absolute hx:-mt-20" id="next-steps"></span>
    <a href="#next-steps" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The concepts presented in this article are the ones I think most people will find the most challenging upon first glance. If you understand Pattern Matching and Keyword Lists, you will understand all the rest.</p>
<p>The official website offers a great <a href="http://elixir-lang.org/getting-started/introduction.html"target="_blank" rel="noopener">Getting Started</a> that you must read entirely.</p>
<p>From intuition you know most things already. You have &ldquo;do .. end&rdquo; blocks, but you may not yet know that they are just convenience macros to pass a list of statements as an argument inside a Keyword List. The following blocks are equivalent:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">if</span> <span class="kp">true</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">+</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="kp">true</span><span class="p">,</span> <span class="k">do</span><span class="p">:</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">+</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="kp">true</span><span class="p">,</span> <span class="o">[</span><span class="p">{</span><span class="ss">:do</span><span class="p">,</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">  <span class="n">a</span> <span class="o">+</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="p">)}</span><span class="o">]</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Mind-blowing, huh? There are many macros that add syntactic sugar using the primitives behind it.</p>
<p>For the most part, Valim made the powerful Erlang primitives more accessible (Lists, Atoms, Maps, etc.) and added higher abstractions using macros (do .. end blocks, the pipe operator, keyword lists, shortcuts for anonymous functions, etc.). This precise combination is what makes Elixir very enjoyable to learn. It&rsquo;s like peeling an onion: you start with the higher abstractions and discover macros of simpler structures underneath. You see a Keyword List first and discover Lists of Tuples. You see a block and discover another Keyword List disguised by a macro. And so on.</p>
<p>So you have a low barrier to entry and you can go as deep as you want into the rabbit hole, all the way to extending the language.</p>
<p>Elixir provides a very clever language design on top of the 25-year-old mature Erlang core. This is not just clever, it&rsquo;s the intelligent choice. Keep learning!</p>
]]></content:encoded><category>tutorials</category><category>elixir-and-erlang</category><category>programming</category></item><item><title>My first week learning Elixir</title><link>https://akitaonrails.github.io/en/2015/11/03/my-first-week-learning-elixir/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2015/11/03/my-first-week-learning-elixir/</guid><pubDate>Tue, 03 Nov 2015 11:07:00 -0200</pubDate><description>&lt;p&gt;I set myself to try to learn enough Elixir to be comfortable tackling some small projects. After 1 entire week of studying close to 6 hours a day (around 42 hours) I&amp;rsquo;m still not entirely comfortable, but I think the main concepts have been able to sink in and I can fully appreciate what Elixir has to offer.&lt;/p&gt;
&lt;p&gt;This is not my first time touching Erlang though. I was fortunate enough to be able to participate in a small workshop at QCon San Francisco 2009 with no other than &lt;a href="http://www.oreilly.com/pub/au/3373"target="_blank" rel="noopener"&gt;Francesco Cesarini&lt;/a&gt;. Thanks to him I was able to understand some of Erlang&amp;rsquo;s exquisite syntax, the correct concept of Erlang processes, how immutability and pattern matching govern their programming flow. It was very enlightening. Unfortunately I couldn&amp;rsquo;t see myself doing Erlang full time. I just hoped those mechanisms were available in a language such as Ruby &amp;hellip;&lt;/p&gt;</description><content:encoded><![CDATA[<p>I set myself to try to learn enough Elixir to be comfortable tackling some small projects. After 1 entire week of studying close to 6 hours a day (around 42 hours) I&rsquo;m still not entirely comfortable, but I think the main concepts have been able to sink in and I can fully appreciate what Elixir has to offer.</p>
<p>This is not my first time touching Erlang though. I was fortunate enough to be able to participate in a small workshop at QCon San Francisco 2009 with no other than <a href="http://www.oreilly.com/pub/au/3373"target="_blank" rel="noopener">Francesco Cesarini</a>. Thanks to him I was able to understand some of Erlang&rsquo;s exquisite syntax, the correct concept of Erlang processes, how immutability and pattern matching govern their programming flow. It was very enlightening. Unfortunately I couldn&rsquo;t see myself doing Erlang full time. I just hoped those mechanisms were available in a language such as Ruby &hellip;</p>
<p>Between 2007 and 2009 Erlang had a renaissance among language aficionados because of the <a href="https://pragprog.com/book/jaerlang/programming-erlang"target="_blank" rel="noopener">&ldquo;Programming Erlang&rdquo;</a> book released by The Pragmatic Programmers, written by no other than Joe Armstrong himself, Erlang&rsquo;s creator. Dave Thomas <a href="http://pragdave.me/blog/2007/04/15/a-first-erlang-program/"target="_blank" rel="noopener">tried to push Erlang</a> a lot in 2007, but even he wasn&rsquo;t able to sell Erlang&rsquo;s powerful engine because of the strange presentation of the syntax.</p>
<p>After 2009, José Valim had a long run to release the controversial Rails 3.0 big rewrite (which was fortunately a success) and he decided to step aside and try something else. His own research led him to Erlang for the reasons I mentioned above, but he decided that he could solve the &ldquo;quirky syntax&rdquo; problem. You can see some of his very first talks about Elixir in the Rubyconf Brasil <a href="https://www.eventials.com/locaweb/jose-valim-vamos-falar-sobre-concorrencia/"target="_blank" rel="noopener">2012</a> and <a href="https://www.eventials.com/locaweb/elixir-uma-aproximacao-pragmatica-e-concorrente-a-programacao/"target="_blank" rel="noopener">2013</a> recordings. The very early beta was released in 2012 and he finally released the stable 1.0 in 2015. Chris McCord was able to release Phoenix stable soon after.</p>
<p>When I first heard about this, Elixir found its place under my radar. I didn&rsquo;t jump right in though, between 2009 and 2015 we had a surge in &ldquo;functional programming&rdquo; interest because of the JavaScript renaissance, the release of Scala, Go Lang, Clojure, the promise of Rust, and so on. So I waited, carefully following every one of them.</p>
<p>Then 2014 came and suddenly everybody else found out about Erlang, with its spartan infrastructure that enabled WhatsApp to serve half a billion users with absurdly low costs and made Facebook buy them for a hefty USD 19 billion! We all knew about the WhatsApp case since at least 2011, but it was not until 2014 that everybody noticed. But not even this was able to steer Erlang to the forefront just yet.</p>
<p>When Elixir stable was released this year, followed by Phoenix stable, I knew it was time for me to start investing some quality time with it. Erlang&rsquo;s core sells itself: everybody else is doing concurrency by means of immutability and lightweight threads (or green threads, NxM strategy between green threads and real threads). It is actually quite trivial to max out the machine just by spawning millions of light processes nowadays. What makes it difficult is to create a system that has the potential to actually achieve <a href="http://stackoverflow.com/questions/8426897/erlangs-99-9999999-nine-nines-reliability"target="_blank" rel="noopener">99.9999999% reliability</a>. Spawning processes is easy, how do you coordinate them in the same machine? How do you coordinate them between different machines? How do you update a living system without bringing it down? How do you handle failures? How do you supervise everything?</p>
<p>These are the questions that Erlang solved decades ago (<a href="http://www.erlang.org/download/armstrong_thesis_2003.pdf"target="_blank" rel="noopener">20 years ago</a>) with the now famous OTP, Ericsson&rsquo;s Open Telecom Platform. Something that was created to meet the performance and reliability needs of telecommunications at large scale. When we say it like this it feels like it will be a royal pain to learn, something akin to the JEE (Java Enterprise Edition), but worse.</p>
<p>And I can tell you that learning enough OTP to be productive is actually <strong>very</strong> easy (you won&rsquo;t achieve the legendary 99.9999999% reliability out of the blue, but you&rsquo;ll be able to build something reliable enough). Think of it as a collection of half a dozen modules, with a couple of function interfaces to implement, a few words of configuration and you&rsquo;re basically done. It&rsquo;s so easy and lightweight that in fact many small libraries are written with OTP in mind and it&rsquo;s easy to just &ldquo;plug and play&rdquo;. It&rsquo;s not a heavyweight server-side only thing.</p>
<p>To harness that power you will need to learn Elixir, unofficially, a language that has an uncanny resemblance to Ruby, built to spill out Erlang bytecode for its BEAM virtual machine. You can&rsquo;t find a better combination.</p>
<h3>One Week<span class="hx:absolute hx:-mt-20" id="one-week"></span>
    <a href="#one-week" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Having said all that, let&rsquo;s cut to the chase. You definitely want to get acquainted with the Functional Programming concepts such as immutability, higher order functions, pattern matching. I made a list of links for those concepts in <a href="http://www.akitaonrails.com/2015/10/28/personal-thoughts-on-the-current-functional-programming-bandwagon"target="_blank" rel="noopener">my previous post</a>, I recommend you read it.</p>
<p>Assuming you&rsquo;re already a programmer in a dynamic language (Ruby, Python, JavaScript, etc.) and you want the fast crash course, start by buying <a href="https://pragprog.com/book/elixir/programming-elixir"target="_blank" rel="noopener">&ldquo;Programming Elixir&rdquo;</a> by Dave Thomas and actually do each piece of code and the exercises in order. It&rsquo;s a book so easy to read that you will be able to finish it in less than a week. I did it in 3 days. The Elixir-Lang official website has <a href="http://elixir-lang.org/getting-started/introduction.html"target="_blank" rel="noopener">very good documentation</a> as well and they link many <a href="http://elixir-lang.org/learning.html"target="_blank" rel="noopener">good books</a> you want to read later.</p>
<p>Then subscribe to Josh Adams&rsquo; <a href="http://elixirsips.com"target="_blank" rel="noopener">Elixir Sips</a>. If you&rsquo;re a Rubyist, it&rsquo;s like watching Ryan Bates&rsquo; Railscasts from the beginning all over again. Although it&rsquo;s more akin to Avdi Grimm&rsquo;s RubyTapas show, with very short episodes just for you to have your weekly fix on Elixir.</p>
<p>You can watch some of the episodes for free in low resolution, but I highly recommend you subscribe and watch the HD versions. It&rsquo;s well worth it. There are more than 200 episodes. I&rsquo;ve watched more than 130 in 12 hours :-) So I figure I&rsquo;d take another 2 days to watch everything.</p>
<p>You should definitely watch everything if you can, but if you can&rsquo;t, let me list the ones I think are the essentials. First of all, keep in mind that Josh has been doing this for quite a while, when he started Elixir was version 0.13 or below and Erlang was version 17 or below.</p>
<p>For example, episode <a href="https://elixirsips.dpdcart.com/subscriber/post?id=815"target="_blank" rel="noopener">171 - Erlang 18 and time</a> highlights the new Time API. You must know about this. Episode <a href="https://elixirsips.dpdcart.com/subscriber/post?id=460"target="_blank" rel="noopener">056 - Migrating Records to Maps</a> shows a new feature in Erlang 17 and Elixir where it makes Maps more preferable than the previous Records. Maps are explained in episodes <a href="https://elixirsips.dpdcart.com/subscriber/post?id=453"target="_blank" rel="noopener">054</a> and <a href="https://elixirsips.dpdcart.com/subscriber/post?id=454"target="_blank" rel="noopener">055</a>. If you learn the Phoenix web framework, it uses the ORM Ecto underneath and Ecto models are Maps, so you must know this.</p>
<p>It means that the first 180 episodes, at least, are using previous versions of Erlang, Elixir, Phoenix, etc and you must keep in mind that new versions will have different APIs. This was one of the reasons I waited for the stable releases, because it was only natural that projects evolve and take time to reach stable APIs, and chasing several moving targets is really difficult for the uninitiated.</p>
<p>Having said that, watch this list first:</p>
<ul>
<li>001 - Introduction and Installing Elixir.mp4</li>
<li>002 - Basic Elixir.mp4</li>
<li>003 - Pattern Matching.mp4</li>
<li>004 - Functions.mp4</li>
<li>005 - Mix and Modules.mp4</li>
<li>006 - Unit Testing.mp4</li>
<li>010 - List Comprehensions.mp4</li>
<li>011 - Records.mp4</li>
<li>012 - Processes.mp4</li>
<li>013 - Processes, Part 2.mp4</li>
<li>014 - OTP Part 1_ Servers.mp4</li>
<li>015 - OTP Part 2_ Finite State Machines.mp4</li>
<li>016 - Pipe Operator.mp4</li>
<li>017 - Enum, Part 1.mp4</li>
<li>018 - Enum, Part 2.mp4</li>
<li>019 - Enum, Part 3.mp4</li>
<li>020 - OTP, Part 3 - GenEvent.mp4</li>
<li>022 - OTP, Part 4_ Supervisors.mp4</li>
<li>023 - OTP, Part 5_ Supervisors and Persistent State.mp4</li>
<li>024 - Ecto, Part 1.mp4</li>
<li>025 - Ecto, Part 2_ Dwitter.mp4</li>
<li>026 - Dict, Part 1.mp4</li>
<li>027 - Dict, Part 2.mp4</li>
<li>028 - Parsing XML.mp4</li>
<li>031 - TCP Servers.mp4</li>
<li>032 - Command Line Scripts.mp4</li>
<li>033 - Pry.mp4</li>
<li>041 - File, Part 1.mp4</li>
<li>042 - File, Part 2.mp4</li>
<li>044 - Distribution</li>
<li>045 - Distribution, Part 2</li>
<li>054 - Maps, Part 1.mp4</li>
<li>055 - Maps, Part 2_ Structs.mp4</li>
<li>056 - Migrating Records To Maps.mp4</li>
<li>059 - Custom Mix Tasks.mp4</li>
<li>060 - New Style Comprehensions.mp4</li>
<li>061 - Plug.mp4</li>
<li>063 - Tracing.mp4</li>
<li>065 - SSH.mp4</li>
<li>066 - Plug.Static.mp4</li>
<li>067 - Deploying to Heroku.mp4</li>
<li>068 - Port.mp4</li>
<li>069 - Observer.mp4</li>
<li>070 - Hex.mp4</li>
<li>073 - Process Dictionaries.mp4</li>
<li>074 - ETS.mp4</li>
<li>075 - DETS.mp4</li>
<li>076 - Streams.mp4</li>
<li>077 - Exceptions and Errors.mp4</li>
<li>078 - Agents.mp4</li>
<li>079 - Tasks.mp4</li>
<li>081 - EEx.mp4</li>
<li>082 - Protocols.mp4</li>
<li>083 - pg2.mp4</li>
<li>086 - put_in and get_in.mp4</li>
<li>090 - Websockets Terminal.mp4</li>
<li>091 - Test Coverage.mp4</li>
<li>106 - Text Parsing.mp4</li>
<li>109 - Socket.mp4</li>
<li>112 - Benchfella.mp4</li>
<li>113 - Monitoring Network Traffic.mp4</li>
<li>124 - Typespecs.mp4</li>
<li>125 - Dialyzer.mp4</li>
<li>126 - Piping Into Elixir.mp4</li>
<li>127 - SSH Client Commands.mp4</li>
<li>131 - ExProf.mp4</li>
<li>132 - Randomness in the Erlang VM.mp4</li>
<li>135 - Benchwarmer.mp4</li>
<li>138 - Monitors and Links.mp4</li>
<li>139 - hexdocs.mp4</li>
<li>141 - Set.mp4</li>
<li>142 - escript.mp4</li>
<li>144 - Erlang&rsquo;s <code>calendar</code> module.mp4</li>
<li>145 - good_times.mp4</li>
<li>153 - Phoenix APIs and CORS.mp4</li>
<li>155 - OAuth2_ Code Spelunking.mp4</li>
<li>156 - Interacting with Amazon&rsquo;s APIs with erlcloud.mp4</li>
<li>157 - Playing with the Code Module Part 1 - eval_string.mp4</li>
<li>159 - Simple One for One Supervisors.mp4</li>
<li>160 - MultiDef.mp4</li>
<li>171 - Erlang 18 and Time.mp4</li>
<li>172 - Arc File Uploads.mp4</li>
<li>174 - ElixirFriends_ Saving Tweets with Streams and Filters.mp4</li>
<li>175 - Pagination with Ecto and Phoenix using Scrivener.mp4</li>
<li>176 - Prettying Up ElixirFriends.mp4</li>
<li>178 - Memory Leaks.mp4</li>
<li>179 - Rules Engine.mp4</li>
<li>180 - Collectable.mp4</li>
<li>182 - Phoenix API.mp4</li>
<li>183 - React with Phoenix.mp4</li>
<li>184 - React with Phoenix Channels.mp4</li>
<li>185 - Mix Archives.mp4</li>
<li>186 - Automatically Connecting Nodes.mp4</li>
<li>187 - Compiling a Custom AST Into Elixir Functions.mp4</li>
<li>190 - Testing Phoenix Channels.mp4</li>
<li>193 - Linting with Dogma.mp4</li>
<li>194 - Interoperability_ Ports.mp4</li>
<li>196 - Crashing the BEAM.mp4</li>
<li>200 - Custom Types in Ecto.mp4</li>
<li>201 - Tracing and Debugging with erlyberly.mp4</li>
<li>202 - Exception Monitoring with Honeybadger.io.mp4</li>
<li>203 - plug_auth.mp4</li>
<li>204 - Behaviours.mp4</li>
</ul>
<p>This is roughly half of what&rsquo;s available in Elixir Sips. All the other episodes are also interesting, but if you&rsquo;re just getting started, this list should be enough to get your feet wet in the language.</p>
<p>Railers will enjoy Phoenix and the ecosystem that is growing around it. You can already authenticate through <a href="https://github.com/scrogson/oauth2"target="_blank" rel="noopener">OAuth2</a>, do will_paginate-style pagination with <a href="https://github.com/drewolson/scrivener"target="_blank" rel="noopener">Scrivener</a>, do CarrierWave-style file uploads with <a href="https://github.com/stavro/arc"target="_blank" rel="noopener">Arc</a>, deploy to <a href="http://wsmoak.net/2015/07/05/phoenix-on-heroku.html"target="_blank" rel="noopener">Heroku</a>.</p>
<p>For more exercises, you can easily connect to HTTP endpoints using <a href="https://github.com/edgurgel/httpoison"target="_blank" rel="noopener">HTTPoison</a>, parse HTML with <a href="https://github.com/philss/floki"target="_blank" rel="noopener">Floki</a>, parse JSON with <a href="https://github.com/devinus/poison"target="_blank" rel="noopener">Poison</a>. For more libraries, you can follow this Github page called <a href="https://github.com/h4cc/awesome-elixir"target="_blank" rel="noopener">Awesome Elixir</a> which lists many new Elixir packages that you can use. But make sure you walk yourself through the basic concepts first. Elixir has a Rake-like task management system with built-in Mix, you can add dependencies in a Gemfile-like file called Mix.exs, which every project has. You can add dependencies through Github urls or from <a href="https://hex.pm"target="_blank" rel="noopener">Hex.pm</a> which is like Rubygems.org.</p>
<p>In this learning process, the concepts that I find more important to learn first are:</p>
<ul>
<li>Elixir basic syntax and concepts (pattern matching, loops through recursion, immutable state, primitive types including Maps, the pipe operator)</li>
<li>The concept of processes, nodes, and intercommunication between processes and nodes, including Monitors and Links.</li>
<li>OTP Basics, learn what GenServer, GenEvent, GenFSM are.</li>
</ul>
<p>After you learn that, you can figure out how to build OTP applications and do something practical for the Web using Phoenix. In particular, you will want to learn everything about Phoenix&rsquo;s Channels, the infrastructure for robust, fast and <a href="http://www.akitaonrails.com/2015/10/29/phoenix-experiment-holding-2-million-websocket-clients"target="_blank" rel="noopener">highly concurrent</a> WebSockets.</p>
<p>That&rsquo;s it. This is my first week learning Elixir, and my next step is to train myself by doing more exercises and also learning more about Phoenix. Even though Phoenix is inspired by Rails, it is not a clone, it has its own set of unique concepts to learn and this is definitely going to be a very interesting ride.</p>
<p>If you have more tips and tricks for beginners, feel free to comment below.</p>
]]></content:encoded><category>learning</category><category>elixir-and-erlang</category><category>programming</category></item><item><title>Brazilian Portuguese Can Confuse Us: Standard vs Pattern</title><link>https://akitaonrails.github.io/en/2013/05/10/a-lingua-portuguesa-brasileira-e-pessima-standard-vs-pattern/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2013/05/10/a-lingua-portuguesa-brasileira-e-pessima-standard-vs-pattern/</guid><pubDate>Fri, 10 May 2013 19:18:00 -0300</pubDate><description>&lt;p&gt;&lt;strong&gt;Original from 4/27/2011&lt;/strong&gt;: &lt;a href="http://web.archive.org/web/20160709143544/http://info.abril.com.br/noticias/rede/gestao20/software/a-lingua-portuguesa-brasileira-e-pessima-standard-vs-pattern/"target="_blank" rel="noopener"&gt;Gestão 2.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My last translation article, on &amp;ldquo;Standards: Excellence vs. Mediocrity,&amp;rdquo; spun off an interesting side discussion specifically about &amp;ldquo;Design Patterns.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;For those not in programming: the term &amp;ldquo;Design Pattern&amp;rdquo; emerged in the 70s and was reinforced in the 90s by the &amp;ldquo;Gang of Four book.&amp;rdquo; According to Wikipedia, in software engineering a design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It&amp;rsquo;s a description or template for how to solve a problem that can be used in many different situations.&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>Original from 4/27/2011</strong>: <a href="http://web.archive.org/web/20160709143544/http://info.abril.com.br/noticias/rede/gestao20/software/a-lingua-portuguesa-brasileira-e-pessima-standard-vs-pattern/"target="_blank" rel="noopener">Gestão 2.0</a></p>
<p>My last translation article, on &ldquo;Standards: Excellence vs. Mediocrity,&rdquo; spun off an interesting side discussion specifically about &ldquo;Design Patterns.&rdquo;</p>
<p>For those not in programming: the term &ldquo;Design Pattern&rdquo; emerged in the 70s and was reinforced in the 90s by the &ldquo;Gang of Four book.&rdquo; According to Wikipedia, in software engineering a design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It&rsquo;s a description or template for how to solve a problem that can be used in many different situations.</p>
<p>For us in Brazil there&rsquo;s a <em>huge</em> problem, and it only clicked for me because of the discussion in the comments of that article. The complaint was that I translated &ldquo;Design Patterns Standards&rdquo; as &ldquo;Padrões de Design.&rdquo; Ronald, the one who raised it, made a correct point: the English words <em>&ldquo;default&rdquo;</em>, <em>&ldquo;standard&rdquo;</em> and <em>&ldquo;pattern&rdquo;</em> all translate to the same word &ldquo;padrão&rdquo; in Portuguese.</p>
<p>But the 3 words have very different meanings:</p>
<p><strong>Default</strong> – a pre-selected option adopted by a computer program or other mechanism when no other alternative is specified by the user or programmer. Example: the &ldquo;default&rdquo; is 50 lines</p>
<p><strong>Pattern</strong> – 1) a repetitive decorative design (as in color &ldquo;patterns&rdquo; on clothing). A regular arrangement or sequence in comparable objects or events. A regular and intelligible form or discernible sequence in certain actions or situations. 2) a model or design used as a guide in embroidery or other craft activities.</p>
<p><strong>Standard</strong> – 1) a level of quality or accomplishment. A required or agreed-upon level of quality or accomplishment. 2) an idea or thing used as a measure, norm, or model in comparative evaluations. Principles of conduct informed by notions of honor and decency. A form of language that is widely recognized as the correct one.</p>
<p>In summary:</p>
<p><strong>Default</strong> – a pre-selected choice when no other is selected.</p>
<p><strong>Pattern</strong> – a model that can be observed as recurring, with no value of right or wrong.</p>
<p><strong>Standard</strong> – a norm, something everyone agrees on as a basis of comparison or minimum requirements to be followed.</p>
<p>The problem is that the word &ldquo;padrão,&rdquo; in Portuguese, is used much more often with the sense of &ldquo;standard.&rdquo; And many times what we&rsquo;re translating is the word &ldquo;pattern.&rdquo;</p>
<p>That is, when someone says &ldquo;Design Pattern,&rdquo; they&rsquo;re only saying there&rsquo;s a &ldquo;form&rdquo; used more frequently than others in solving software problems. It isn&rsquo;t necessarily the most correct one, and there&rsquo;s no statement that it&rsquo;s the conclusive form. It&rsquo;s just the observation that it&rsquo;s frequent, regularly used. The image below shows padrões in the sense of &ldquo;patterns&rdquo; (&ldquo;more patterns&rdquo;):</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/350/complex-repeating-patterns-.jpg" alt="Pattern"  loading="lazy" /></p>
<p>But translating to &ldquo;Padrões de Design&rdquo; brings in the Portuguese sense of &ldquo;padrão&rdquo; as the most correct, or minimally correct, form, and one that, being a &ldquo;norm,&rdquo; should be followed. The word &ldquo;padrão&rdquo; comes across like <em>&ldquo;obligation to follow standard Decree No. 288/2005,&rdquo;</em> that is, <em>&ldquo;obligation to follow the norm or regulation Decree No. 288/2005.&rdquo;</em></p>
<p>Then &ldquo;Design Patterns&rdquo; gains the connotation of a norm or regulation, which is exactly the wrong meaning. Pattern is Pattern, Standard is Standard, they&rsquo;re completely different things.</p>
<p>And that&rsquo;s where the misunderstanding between so many people lives. Whoever understood Design Patterns in the sense of &ldquo;Pattern&rdquo; complains about whoever understood it in the sense of &ldquo;Standard.&rdquo; Both translate as &ldquo;padrão,&rdquo; and the discussion between these two people ends up sounding like a crazy conversation: <em>&ldquo;But this is just a padrão (pattern), it doesn&rsquo;t have to be mandatorily followed.&rdquo;</em> – <em>&ldquo;No! This is a padrão (standard), so it must be mandatorily followed!&rdquo;</em></p>
<p>Note: I noticed some people didn&rsquo;t really like the title, but I put it that way on purpose, to draw attention to the subject. I&rsquo;m not claiming Portuguese is essentially bad and other languages are better. Every language has nuances and differences that depend on context, local culture, colloquialisms, neologisms, fashion, and so on.</p>
<p>Precisely for that reason we always have to stay alert, so we don&rsquo;t take things literally and apply them without thinking, starting from false premises.</p>
]]></content:encoded><category>programming</category><category>communication</category><category>off-topic</category></item><item><title>[Objective-C] Distributing your Static Library</title><link>https://akitaonrails.github.io/en/2011/04/24/objective-c-distributing-your-static-library/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2011/04/24/objective-c-distributing-your-static-library/</guid><pubDate>Sun, 24 Apr 2011 00:46:00 -0300</pubDate><description>&lt;p&gt;If you didn&amp;rsquo;t read my &lt;a href="http://www.akitaonrails.com/2011/04/23/objective-c-it%27s-a-unix-system-i-know-this"target="_blank" rel="noopener"&gt;last&lt;/a&gt; &lt;a href="http://www.akitaonrails.com/en/2011/04/23/objective-c-categories-static-libraries-e-pegadinhas"target="_blank" rel="noopener"&gt;two articles&lt;/a&gt; I recommend you do so before going any further because I am using the same pet project, &lt;a href="http://www.akitaonrails.com/2011/04/23/objective-c-it%27s-a-unix-system-i-know-this"target="_blank" rel="noopener"&gt;ObjC Rubyfication&lt;/a&gt; as an example for this article. The point is: you are writing reusable code that you want in more than one project.&lt;/p&gt;
&lt;p&gt;Most of this was based on &lt;a href="http://www.cocoanetics.com/2010/04/universal-static-libraries/"target="_blank" rel="noopener"&gt;Cocoanetics&lt;/a&gt; article about universal static libraries. So, if you&amp;rsquo;ve paid attention to my &lt;a href="http://www.akitaonrails.com/en/2011/04/23/objective-c-categories-static-libraries-e-pegadinhas"target="_blank" rel="noopener"&gt;previous article&lt;/a&gt;, you saw this screenshot:&lt;/p&gt;
&lt;!-- broken image (host offline/expired): http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2011.41.27%20PM_original.png --&gt;
&lt;p&gt;I said that I only had these targets configured: CocoaOniguruma, Kiwi, Rubyfication and RubyficationTests. But there are 3 others: CocoaOniguruma SIM, Rubyfication SIM, and Build &amp;amp; Merge Libraries. The reason is simple:&lt;/p&gt;</description><content:encoded><![CDATA[<p>If you didn&rsquo;t read my <a href="http://www.akitaonrails.com/2011/04/23/objective-c-it%27s-a-unix-system-i-know-this"target="_blank" rel="noopener">last</a> <a href="http://www.akitaonrails.com/en/2011/04/23/objective-c-categories-static-libraries-e-pegadinhas"target="_blank" rel="noopener">two articles</a> I recommend you do so before going any further because I am using the same pet project, <a href="http://www.akitaonrails.com/2011/04/23/objective-c-it%27s-a-unix-system-i-know-this"target="_blank" rel="noopener">ObjC Rubyfication</a> as an example for this article. The point is: you are writing reusable code that you want in more than one project.</p>
<p>Most of this was based on <a href="http://www.cocoanetics.com/2010/04/universal-static-libraries/"target="_blank" rel="noopener">Cocoanetics</a> article about universal static libraries. So, if you&rsquo;ve paid attention to my <a href="http://www.akitaonrails.com/en/2011/04/23/objective-c-categories-static-libraries-e-pegadinhas"target="_blank" rel="noopener">previous article</a>, you saw this screenshot:</p>
<!-- broken image (host offline/expired): http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2011.41.27%20PM_original.png -->
<p>I said that I only had these targets configured: CocoaOniguruma, Kiwi, Rubyfication and RubyficationTests. But there are 3 others: CocoaOniguruma SIM, Rubyfication SIM, and Build &amp; Merge Libraries. The reason is simple:</p>
<ul>
<li>The &ldquo;CocoaOniguruma&rdquo; Target builds the <tt>libCocoaOniguruma.a</tt> binary that&rsquo;s compatible with the ARM processor for iOS</li>
<li>The &ldquo;CocoaOniguruma SIM&rdquo; Target builds the <tt>libCocoaOnigurumaSimulator.a</tt> binary that&rsquo;s compatible with the i386 processor for the local iPhone Simulator</li>
<li>The &ldquo;Rubyfication&rdquo; Target builds the <tt>libRubyfication.a</tt> binary that&rsquo;s compatible with the ARM processor for iOS</li>
<li>The &ldquo;Rubyfication SIM&rdquo; Target builds the <tt>libRubyficationSimulator.a</tt> binary that&rsquo;s compatible with the i386 processor for the local iPhone Simulator</li>
<li>The &ldquo;Build &amp; Merge Libraries&rdquo; Target merges the corresponding particular binaries of each target into a single Universal (Fat) Binary that we can easily distribute and reuse.</li>
</ul>
<h2>Concepts and History<span class="hx:absolute hx:-mt-20" id="concepts-and-history"></span>
    <a href="#concepts-and-history" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Some explanation is in order. When you&rsquo;re developing iOS applications, you can test it directly on your iPhone device or within the Simulator. Now, Apple was very clever: any other vendor in the market will try to first create an ARM processor emulator to run on top of your i386 processor. Then it will get all the binaries for ARM and run within this emulator. The OS itself will remain compiled for ARM processors and run within the emulator.</p>
<p>Now, this is dead slow, impractical. Anyone that has experienced an emulation environment like this knows how ridiculous it is. Don&rsquo;t confuse it for VMWare or Parallels solutions, which are fast because they are an emulated environment for <strong>the same processor</strong> , so you can run Windows on top of your Mac because the processors and operating systems now support VT-x, which means you mostly don&rsquo;t have to emulate the processor. Now, every smartphone and tablet on the market uses an ARM processor, which has nothing to do with i386.</p>
<p>So, how did Apple deliver a super-fast iPhone/iPad emulator that runs at real-time speed on your Mac? Simple, it didn&rsquo;t. It is called &ldquo;Simulator&rdquo; and not &ldquo;Emulator&rdquo; for a reason: everything that runs within the Simulator is compiled for i386, not for ARM. So what you&rsquo;re running is an actual binary that runs natively over your Mac! No emulation required. The iOS is very portable. The same way Mac OS X was able to transition from the Power PC to Intel back in 2005, the iOS can do the same trick as they are basically the very same operating system.</p>
<p>When you choose the iPhone scheme in XCode, it compiles for ARM and uploads the bits to your iPhone device to run the application. When you choose the Simulator scheme in XCode, it compiles for i386, uploads the bits to your Simulator and runs natively as any other application in your Mac.</p>
<p>Now, going back to the main issue: when I distribute a binary of my Static Library, I have to remember that the developer will be linking against my library to deploy for both the ARM device (iPhone/iPad) and the Simulator (i386). So I would have to deliver at least 2 binary files. But Apple is even smarter than that. Actually, NeXT was. When they first transitioned the NeXTStep operating system from Motorola to Intel processors back in the late 80&rsquo;s, they created <a href="http://en.wikipedia.org/wiki/Fat_binary"target="_blank" rel="noopener">Fat Binaries</a>, which is essentially one binary that contains both processor-specific bits in one single package. When Apple transitioned from the Power PC to Intel they renamed it to <a href="http://en.wikipedia.org/wiki/Universal_binary"target="_blank" rel="noopener">Universal Binaries</a>. And that&rsquo;s essentially what we need to build now.</p>
<h2>Operations<span class="hx:absolute hx:-mt-20" id="operations"></span>
    <a href="#operations" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>We now understand what a Universal Binary is. To make it easier, I right-clicked over the &ldquo;Rubyfication&rdquo; and &ldquo;CocoaOniguruma&rdquo; targets and duplicated them. They will be created as &ldquo;Rubyfication copy&rdquo; and &ldquo;CocoaOniguruma copy&rdquo;. We can change the &ldquo;Product Name&rdquo; in the build settings of each for a more reasonable name:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.21.02%20AM_original.png?1303615270" alt=""  loading="lazy" /></p>
<p>In my case I renamed them to &ldquo;RubyficationSimulator&rdquo; and &ldquo;CocoaOnigurumaSimulator&rdquo;. That will give me both &ldquo;libRubyficationSimulator.a&rdquo; and &ldquo;libCocoaOnigurumaSimulator.a&rdquo;. As you can see in the Products group:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.23.16%20AM_original.png?1303615348" alt=""  loading="lazy" /></p>
<p><strong>Important:</strong> remember that the Rubyfication target had CocoaOniguruma as a target dependency. You will need to change the &ldquo;Rubyfication SIM&rdquo; target to point to the new &ldquo;CocoaOniguruma SIM&rdquo; target! The other thing is that you will need to force both new targets to compile to &ldquo;Latest Mac OS X&rdquo; in the <tt>&ldquo;Base <span class="caps">SDK</span>&quot;</tt> option in the Build Settings of each, and &ldquo;32-bit Intel&rdquo; in the <tt>&ldquo;Architectures&rdquo;</tt> build option. This will make them compile for i386 processors. The original targets should have their <tt>&ldquo;Base <span class="caps">SDK</span>&quot;</tt> to &ldquo;Latest iOS&rdquo; and <tt>&ldquo;Architectures&rdquo;</tt> to &ldquo;Standard (armv6 armv7)&rdquo;.</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.54.21%20AM_original.png?1303617223" alt=""  loading="lazy" /></p>
<p>Now, we need to create a new target of the kind &ldquo;Aggregate&rdquo; :</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.24.00%20AM_original.png?1303615407" alt=""  loading="lazy" /></p>
<p>I named it &ldquo;Build &amp; Merge Libraries&rdquo;. In the &ldquo;Build Phases&rdquo; tab you will start with just the &ldquo;Target Dependencies&rdquo; phase. You just need to add the new &ldquo;Rubyfication SIM&rdquo; and &ldquo;CocoaOniguruma SIM&rdquo; targets. Then you need to add 3 more phases, one for &ldquo;Run Script&rdquo;, another to &ldquo;Copy Files&rdquo; and a last &ldquo;Run Script&rdquo;.</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.25.13%20AM_original.png?1303615678" alt=""  loading="lazy" /></p>
<p>In the &ldquo;Copy Files&rdquo; phase I have just added all the public headers that I want to distribute together with the universal binary library. This is because the other developers will need to add those header files into their projects in order to be able to compile against my library. Now notice that I am copying them to an &ldquo;Absolute Path&rdquo; that states <tt>${TARGET_BUILD_DIR}/../Rubyfication</tt>.</p>
<p>That&rsquo;s where we come to the previous &ldquo;Run Script&rdquo; phase that should have the following code:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 1. make a new output folder</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span>/../Rubyfication
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. combine lib files for various platforms into one</span>
</span></span><span class="line"><span class="cl">lipo create <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span><span class="s2">/../Debug-iphoneos/libRubyfication.a&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span><span class="s2">/../Debug-iphonesimulator/libRubyfication.a&#34;</span> -output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span><span class="s2">/../Rubyfication/libRubyfication</span><span class="si">${</span><span class="nv">BUILD_STYLE</span><span class="si">}</span><span class="s2">.a&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The first thing it does is create this new &ldquo;Rubyfication&rdquo; directory. The second command uses the <a href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/lipo.1.html"target="_blank" rel="noopener">lipo</a> command that merges 2 processor-dependent binaries into a universal binary. Pay attention to the PATHs if you&rsquo;re reusing this script somewhere else. At least with XCode 4 that&rsquo;s where it creates the binaries of each target:</p>
<ul>
<li>${TARGET_BUILD_DIR}/../Debug-iphoneos/libRubyfication.a – the ARM version</li>
<li>${TARGET_BUILD_DIR}/../Debug-iphonesimulator/libRubyfication.a – the i386 version</li>
<li>${TARGET_BUILD_DIR}/../Rubyfication/libRubyfication-Debug.a – the resulting universal binary we created</li>
</ul>
<p>Finally, the last &ldquo;Run Script&rdquo;, after the &ldquo;Copy Files&rdquo; phase described above, requires the following script:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ditto c -k --keepParent <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span><span class="s2">/../Rubyfication&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TARGET_BUILD_DIR</span><span class="si">}</span><span class="s2">/../Rubyfication.zip&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>&ndash;</p>
<p>It just creates a ZIP file with the universal binary library and its companion public header files. Any other developer can get this zip file, unzip it and add the files to their own projects now. If you want to find where this ZIP file is, the easiest way is to go to the project viewer (the left side pane) in XCode, open the &ldquo;Products&rdquo; group, right-click over the &ldquo;libRubyfication.a&rdquo; file (or any other resulting file) and choose &ldquo;Show in Finder&rdquo;. Then you can navigate one folder up in the hierarchy (to the &ldquo;Products&rdquo; folder) and you will see something like this:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.39.02%20AM_original.png?1303616300" alt=""  loading="lazy" /></p>
<p>And there you go: there&rsquo;s your ZIP file with your brand new redistributable universal binary!</p>
<h2>Using the Universal Binary<span class="hx:absolute hx:-mt-20" id="using-the-universal-binary"></span>
    <a href="#using-the-universal-binary" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In order to demonstrate how to use this distributable ZIP file, I have created a very simple, bare-bone iOS project called <a href="https://github.com/akitaonrails/ObjC_OnigurumaDemo"target="_blank" rel="noopener">ObjC_OnigurumaDemo</a> that you can download from Github and run in your own iOS device.</p>
<p>As you can see in the screenshot below, I just unzipped the ZIP within a &ldquo;Dependencies&rdquo; folder in my iOS project and added the universal binary &ldquo;libRubyfication-Debug.a&rdquo; within the Library Linking Build Phase:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.42.09%20AM_original.png?1303616506" alt=""  loading="lazy" /></p>
<p>This allows me to just use anything from this library in my project, in particular a piece of code that uses the Oniguruma regular expressions:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">-</span> <span class="p">(</span><span class="kt">IBAction</span><span class="p">)</span><span class="nf">runRegex:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">OnigRegexp</span><span class="o">*</span> <span class="n">regex</span> <span class="o">=</span> <span class="p">[</span><span class="n">OnigRegexp</span> <span class="nl">compile</span><span class="p">:[</span><span class="n">regexPattern</span> <span class="n">text</span><span class="p">]];</span>
</span></span><span class="line"><span class="cl">    <span class="n">OnigResult</span><span class="o">*</span> <span class="n">res</span> <span class="o">=</span> <span class="p">[</span><span class="n">regex</span> <span class="nl">match</span><span class="p">:[</span><span class="n">initialText</span> <span class="n">text</span><span class="p">]];</span>
</span></span><span class="line"><span class="cl">    <span class="n">NSMutableString</span><span class="o">*</span> <span class="n">tmpResult</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableString</span> <span class="nl">stringWithString</span><span class="p">:</span><span class="s">@&#34;&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="p">[</span><span class="n">res</span> <span class="n">count</span><span class="p">];</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">tmpResult</span> <span class="nl">appendString</span><span class="p">:</span><span class="s">@&#34;(&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">tmpResult</span> <span class="nl">appendString</span><span class="p">:[</span><span class="n">res</span> <span class="nl">stringAt</span><span class="p">:</span><span class="n">i</span><span class="p">]];</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">tmpResult</span> <span class="nl">appendString</span><span class="p">:</span><span class="s">@&#34;)&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="n">result</span> <span class="nl">setText</span><span class="p">:</span><span class="n">tmpResult</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>This demonstration application has a text-field called &ldquo;initialText&rdquo;, where you can type any string. Then you can prepare a Regular Expression in the &ldquo;regexPattern&rdquo; text-field and when you hit the &ldquo;Run&rdquo; button, it will trigger the action above that will run the Regular Expression against the initial text and write the matches within parenthesis in the &ldquo;result&rdquo; text view. The application looks like this:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/24/Screen%20shot%202011-04-24%20at%2012.46.19%20AM_original.png?1303616748" alt=""  loading="lazy" /></p>
<p>And, <em>voilá</em>! Ruby 1.9-like Regular Expression, directly from Oniguruma, within an iOS Application!</p>
]]></content:encoded><category>apple</category><category>programming</category><category>tutorials</category></item><item><title>[Objective-C] Categories, Static Libraries and Gotchas</title><link>https://akitaonrails.github.io/en/2011/04/23/objective-c-categories-static-libraries-and-gotchas/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2011/04/23/objective-c-categories-static-libraries-and-gotchas/</guid><pubDate>Sat, 23 Apr 2011 23:44:00 -0300</pubDate><description>&lt;p&gt;As some of you may know, I have this small pet project called &lt;a href="https://github.com/akitaonrails/ObjC_Rubyfication"target="_blank" rel="noopener"&gt;ObjC Rubyfication&lt;/a&gt;, a personal exercise in writing some Ruby-like syntax within Objective-C. Most of this project uses the fact that we can reopen Objective-C standard classes – very much like Ruby, unlike Java – and insert our own code – through &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20"target="_blank" rel="noopener"&gt;Categories&lt;/a&gt;, similar to Ruby&amp;rsquo;s modules.&lt;/p&gt;
&lt;p&gt;The idea of this pet project is to be a Static Library that I can easily add to any other project and have all of its features. In this article I&amp;rsquo;d like to present how I am organizing its many subprojects within one project (and I am accepting any suggestions and tips to make it better as I am just learning how to organize things within Obj-C projects) and talk about a gotcha that took me hours to figure out and might help someone else.&lt;/p&gt;</description><content:encoded><![CDATA[<p>As some of you may know, I have this small pet project called <a href="https://github.com/akitaonrails/ObjC_Rubyfication"target="_blank" rel="noopener">ObjC Rubyfication</a>, a personal exercise in writing some Ruby-like syntax within Objective-C. Most of this project uses the fact that we can reopen Objective-C standard classes – very much like Ruby, unlike Java – and insert our own code – through <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20"target="_blank" rel="noopener">Categories</a>, similar to Ruby&rsquo;s modules.</p>
<p>The idea of this pet project is to be a Static Library that I can easily add to any other project and have all of its features. In this article I&rsquo;d like to present how I am organizing its many subprojects within one project (and I am accepting any suggestions and tips to make it better as I am just learning how to organize things within Obj-C projects) and talk about a gotcha that took me hours to figure out and might help someone else.</p>
<p>To make this exercise even more fun, I also added a separate target for my unit testing suite (and see how XCode supports tests), then another target for the <a href="http://kiwi-lib.info/"target="_blank" rel="noopener">Kiwi</a> BDD testing framework for Obj-C, and another one for <a href="http://limechat.net/cocoaoniguruma/"target="_blank" rel="noopener">CocoaOniguruma</a> as I have just explained in my <a href="http://www.akitaonrails.com/2011/04/23/objective-c-it%27s-a-unix-system-i-know-this"target="_blank" rel="noopener">previous article</a>.</p>
<p>I&rsquo;ve been playing with ways of reorganizing my project and I realized that I was doing it wrong. I was adding all the source files from my &ldquo;Rubyfication&rdquo; target into my Specs target. So everything was compiling fine, the specs were all passing, but the way I defined dependencies was wrong. It is kind of complicated to understand at first, but it should be something like this:</p>
<ul>
<li>CocoaOniguruma Target: should be a static library, with no target dependencies and no binary libraries to link against, just a dependency to the standard Foundation framework. It exposes the OnigRegexp.h, OnigRegexpUtility.h and oniguruma.h as public headers.</li>
<li>Kiwi Target: should be another static library, with no target dependencies and no binary libraries to link against, just having the Foundation and UIKit framework dependencies.</li>
<li>Rubyfication: should be another static library, with CocoaOniguruma as a target dependency, linking against the libCocoaOniguruma.a binary and depending on the Foundation framework as well. It exposes all of its <tt>.h</tt> files as public headers.</li>
<li>RubyficationTests: should be a Bundle which was created together with the Rubyfication target (you can specify whether you want a unit test target when you create new targets), with both Kiwi and Rubyfication targets as dependencies, linking against the libKiwi.a and libRubyfication.a binaries, and the Foundation and UIKit frameworks as well.</li>
</ul>
<p>If you keep creating new targets manually, XCode 4 will also create a bunch of Schemes that you don&rsquo;t really need. I keep mine clean with just the Rubyfication scheme. You can access the &ldquo;Product&rdquo; menu and the &ldquo;Edit Scheme&rdquo; option. Then my Scheme looks like this:</p>
<!-- broken image (host offline/expired): http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2011.26.25%20PM_original.png -->
<p>I usually configure all my build settings to use &ldquo;LLVM Compiler 2.0&rdquo; for the Debug settings and &ldquo;LLVM GCC 4.2&rdquo; for the Release settings (actually, I do that for precaution as I am not aware if people are actually deploying binaries in production compiled from LLVM).</p>
<p>I also set the <tt>&ldquo;Targeted Device Family&rdquo;</tt> to &ldquo;iPhone/iPad&rdquo; and I try to make the <tt>&ldquo;iOS Deployment Target&rdquo;</tt> to &ldquo;iOS 3.0&rdquo; whenever possible. People usually leave the default one which will be the latest release – now at 4.3. Be aware that your project may not run on older devices that way.</p>
<p>Finally I also make sure that the <tt>&ldquo;Framework Search Paths&rdquo;</tt> are pointing to these options:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>&#34;$(SDKROOT)/Developer/Library/Frameworks&#34;  
&#34;${DEVELOPER_LIBRARY_DIR}/Frameworks&#34;  </code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Everything compiles just fine that way. Then I can press &ldquo;Command-U&rdquo; (or go to the &ldquo;Product&rdquo; menu, &ldquo;Test&rdquo; option) to build the &ldquo;RubyficationTests&rdquo; target. It builds all the target dependencies, links everything together and runs the final script to execute the tests (you must make sure that you are selecting the &ldquo;Rubyfication – iPhone 4.3 Simulator&rdquo; in the Scheme Menu). It will fire up the Simulator so it can run the specs.</p>
<p>But then I was receiving:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>Test Suite &#39;/Users/akitaonrails/Library/Developer/Xcode/DerivedData/Rubyfication-gfqxbgyxicfpxugauehktilpmwzv/Build/Products/Debug-iphonesimulator/RubyficationTests.octest(Tests)&#39; started at 2011-04-24 02:16:27 &#43;0000  
Test Suite &#39;CollectionSpec&#39; started at 2011-04-24 02:16:27 &#43;0000  
Test Case &#39;-[CollectionSpec runSpec]&#39; started.  
2011-04-23 23:16:27.506 otest[40298:903] [__NSArrayI each:]: unrecognized selector sent to instance 0xe51a30  
2011-04-23 23:16:27.508 otest[40298:903] ***** Terminating app due to uncaught exception &#39;NSInvalidArgumentException&#39;, reason: &#39;[__NSArrayI each:]: unrecognized selector sent to instance 0xe51a30&#39;  </code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>It says that an instance of <tt>NSArray</tt> is not recognizing the selector <tt>each:</tt> sent to it in the <tt>CollectionSpec</tt> file. It is probably this snippet:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="cp"># import &#34;Kiwi.h&#34;  
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp"># import &#34;NSArray+functional.h&#34;  
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp"># import &#34;NSArray+helpers.h&#34;  
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp"># import &#34;NSArray+activesupport.h&#34;
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">SPEC_BEGIN</span><span class="p">(</span><span class="n">CollectionSpec</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">describe</span><span class="p">(</span><span class="s">@&#34;NSArray&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">__block</span> <span class="n">NSArray</span><span class="o">*</span> <span class="n">list</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">context</span><span class="p">(</span><span class="s">@&#34;Functional&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span> <span class="n">beforeEach</span><span class="p">(</span><span class="o">^</span><span class="p">{</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithObjects</span><span class="p">:</span><span class="s">@&#34;a&#34;</span><span class="p">,</span> <span class="s">@&#34;b&#34;</span><span class="p">,</span> <span class="s">@&#34;c&#34;</span><span class="p">,</span> <span class="nb">nil</span><span class="p">];</span> <span class="p">});</span> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">it</span><span class="p">(</span><span class="s">@&#34;should iterate sequentially through the entire collection of items&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span> <span class="n">NSMutableArray</span><span class="o">*</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSMutableArray</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">list</span> <span class="nl">each</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="kt">id</span> <span class="n">item</span><span class="p">)</span> <span class="p">{</span> <span class="p">[</span><span class="n">output</span> <span class="nl">addObject</span><span class="p">:</span><span class="n">item</span><span class="p">];</span> <span class="p">}];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="n">theValue</span><span class="p">([</span><span class="n">output</span> <span class="n">count</span><span class="p">])</span> <span class="n">should</span><span class="p">]</span> <span class="nl">equal</span><span class="p">:</span><span class="n">theValue</span><span class="p">([</span><span class="n">list</span> <span class="n">count</span><span class="p">])];</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="err">…</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reference: <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/RubyficationTests/CollectionSpec.m#L1-22"target="_blank" rel="noopener">CollectionSpec.m</a></p>
<p>Notice that at Line 3 there is the correct import statement where the <tt>NSArray(Helpers)</tt> category is defined with the correct <tt>each:</tt> method declared. The error is happening at the spec in line 18 in the above snippet.</p>
<p>Now, this was not a compile time error, it was a runtime error. So the import statement is finding the correct file and compiling but something in the linking phase is not going correctly and at runtime the <tt>NSArray(Helpers)</tt> category, and probably other categories, are not available.</p>
<p>It took me a few hours of research but I finally figured out one simple flag that changed everything, the <a href="http://developer.apple.com/library/mac/#qa/qa1490/_index.html"target="_blank" rel="noopener">-all_load</a> linker flag. As the documentation states:</p>
<blockquote>
  <p><strong>Important:</strong> For 64-bit and iPhone OS applications, there is a linker bug that prevents <tt>-ObjC</tt> from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the <tt>-all_load</tt> or <tt>-force_load</tt> flags.</p>
<p><tt>-all_load</tt> forces the linker to load all object files from every archive it sees, even those without Objective-C code. <tt>-force_load</tt> is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each <tt>-force_load</tt> option must be followed by a path to an archive, and every object file in that archive will be loaded.</p>

</blockquote>
<p>So every target that depends on external static libraries that loads Categories has to add this <tt>-all_load</tt> flag in the &ldquo;Other Linker Flags&rdquo;, under the &ldquo;Linking&rdquo; category on the &ldquo;Build Settings&rdquo; of the target, like this:</p>
<!-- broken image (host offline/expired): http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2011.41.27%20PM_original.png -->
<p>So both my <tt>RubyficationTests</tt> and <tt>Rubyfication</tt> targets had to receive this new flag. And now the Tests all pass flawlessly!</p>
]]></content:encoded><category>apple</category><category>programming</category><category>tutorials</category></item><item><title>[Objective-C] It's a Unix System! I know this!</title><link>https://akitaonrails.github.io/en/2011/04/23/objective-c-its-a-unix-system-i-know-this/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2011/04/23/objective-c-its-a-unix-system-i-know-this/</guid><pubDate>Sat, 23 Apr 2011 22:47:00 -0300</pubDate><description>&lt;p&gt;While experimenting with ways of using Objective-C a little bit closer to how I code Ruby, there were two things that annoyed me a bit. First, Date Formatting and, second, Regular Expressions.&lt;/p&gt;
&lt;p&gt;The Cocoa framework has both implemented as &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html%23//apple_ref/doc/uid/TP40002369-SW1"target="_blank" rel="noopener"&gt;NSDateFormatter&lt;/a&gt; and &lt;a href="http://developer.apple.com/library/iOS/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html"target="_blank" rel="noopener"&gt;NSRegularExpression&lt;/a&gt; that also happen to be available for iOS development.&lt;/p&gt;
&lt;p&gt;You can format dates like this:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;NSDateFormatter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dateFormatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;NSDateFormatter&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dateFormatter&lt;/span&gt; &lt;span class="nl"&gt;setDateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;NSDateFormatterMediumStyle&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dateFormatter&lt;/span&gt; &lt;span class="nl"&gt;setTimeStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;NSDateFormatterNoStyle&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSDate&lt;/span&gt; &lt;span class="nl"&gt;dateWithTimeIntervalSinceReferenceDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;162000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;formattedDateString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dateFormatter&lt;/span&gt; &lt;span class="nl"&gt;stringFromDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;NSLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;formattedDateString: %`&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;formattedDateString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="nl"&gt;en_US&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;formattedDateString: Jan 2, 2001&amp;#34;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copy code"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And you can use Regular Expressions like this:&lt;/p&gt;</description><content:encoded><![CDATA[<p>While experimenting with ways of using Objective-C a little bit closer to how I code Ruby, there were two things that annoyed me a bit. First, Date Formatting and, second, Regular Expressions.</p>
<p>The Cocoa framework has both implemented as <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html%23//apple_ref/doc/uid/TP40002369-SW1"target="_blank" rel="noopener">NSDateFormatter</a> and <a href="http://developer.apple.com/library/iOS/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html"target="_blank" rel="noopener">NSRegularExpression</a> that also happen to be available for iOS development.</p>
<p>You can format dates like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="n">NSDateFormatter</span> <span class="o">*</span><span class="n">dateFormatter</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSDateFormatter</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">dateFormatter</span> <span class="nl">setDateStyle</span><span class="p">:</span><span class="n">NSDateFormatterMediumStyle</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">dateFormatter</span> <span class="nl">setTimeStyle</span><span class="p">:</span><span class="n">NSDateFormatterNoStyle</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">NSDate</span> <span class="o">*</span><span class="n">date</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSDate</span> <span class="nl">dateWithTimeIntervalSinceReferenceDate</span><span class="p">:</span><span class="mi">162000</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">NSString</span> <span class="o">*</span><span class="n">formattedDateString</span> <span class="o">=</span> <span class="p">[</span><span class="n">dateFormatter</span> <span class="nl">stringFromDate</span><span class="p">:</span><span class="n">date</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"><span class="n">NSLog</span><span class="p">(</span><span class="err">`</span><span class="s">&#34;formattedDateString: %`&#34;</span><span class="p">,</span> <span class="n">formattedDateString</span><span class="p">);</span>  
</span></span><span class="line"><span class="cl"><span class="o">//</span> <span class="n">Output</span> <span class="k">for</span> <span class="n">locale</span> <span class="nl">en_US</span><span class="p">:</span> <span class="s">&#34;formattedDateString: Jan 2, 2001&#34;</span>  </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And you can use Regular Expressions like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">NSError</span> <span class="o">*</span><span class="n">error</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>  
</span></span><span class="line"><span class="cl"><span class="n">NSRegularExpression</span> <span class="o">*</span><span class="n">regex</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSRegularExpression</span> <span class="nl">regularExpressionWithPattern</span><span class="p">:</span><span class="s">@&#34;</span><span class="se">\\</span><span class="s">b(a|b)(c|d)</span><span class="se">\\</span><span class="s">b&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="nl">options</span><span class="p">:</span><span class="n">NSRegularExpressionCaseInsensitive</span>  
</span></span><span class="line"><span class="cl"> <span class="nl">error</span><span class="p">:</span><span class="o">&amp;</span><span class="n">error</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">NSUInteger</span> <span class="n">numberOfMatches</span> <span class="o">=</span> <span class="p">[</span><span class="n">regex</span> <span class="nl">numberOfMatchesInString</span><span class="p">:</span><span class="n">string</span>  
</span></span><span class="line"><span class="cl"> <span class="nl">options</span><span class="p">:</span><span class="mi">0</span>  
</span></span><span class="line"><span class="cl"> <span class="nl">range</span><span class="p">:</span><span class="n">NSMakeRange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="n">string</span> <span class="n">length</span><span class="p">])];</span>  </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>But I have issues with both of these. The Ruby equivalent for the date formatting example would be:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;activesupport&#39;</span>  
</span></span><span class="line"><span class="cl"><span class="n">date</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&#34;2001-01-01&#34;</span><span class="p">)</span> <span class="o">+</span> <span class="mi">162000</span><span class="o">.</span><span class="n">seconds</span>  
</span></span><span class="line"><span class="cl"><span class="n">date</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%b %d, %Y&#34;</span><span class="p">)</span>  </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And the regular expression example would be like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">number_of_matches</span> <span class="o">=</span> <span class="sr">/\W*[a|b][c|d]\W*/</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="o">.</span><span class="n">size</span>  </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>There are 2 specific things that annoy me:</p>
<ul>
<li>the Obj-C versions feel unnecessarily verbose. Now, I do understand that they are lower level and they will probably allow for more flexibility, but I think they should have higher &ldquo;porcelain&rdquo; versions, that are more straightforward.</li>
<li>in Obj-C, the Date Formatting uses the <a href="http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns"target="_blank" rel="noopener">Unicode TR-35</a> formatting standard and Regular Expressions use the <a href="http://userguide.icu-project.org/strings/regexp"target="_blank" rel="noopener">ICU</a> standard that is inspired by Perl Regular Expression with support for Unicode and loosely based on JDK 1.4 java.util.regex.</li>
</ul>
<p>So, the ideal solution for me would be:</p>
<ul>
<li>to have higher level versions of those features;</li>
<li>to have C-compatible strftime date formatting and Ruby 1.9&rsquo;s Oniguruma level regular expressions.</li>
</ul>
<h2>It&rsquo;s a Unix System<span class="hx:absolute hx:-mt-20" id="its-a-unix-system"></span>
    <a href="#its-a-unix-system" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>That&rsquo;s when the obvious thing came to me: Objective-C is nothing more than a superset of C, so anything that is compatible with C is automatically compatible with Objective-C. More than that, the <strong>iOS is a Unix System</strong>! Meaning that it has all the goodies of Posix support.</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/dFUlAQZB9Ng"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>So, how do I get <a href="http://www.cplusplus.com/reference/clibrary/ctime/strftime/"target="_blank" rel="noopener">C-compatible</a> strftime? Easy:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="cp"># import &#34;time.h&#34;  
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">…</span>  
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">-</span> <span class="p">(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span> <span class="nl">toFormattedString</span><span class="p">:(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span><span class="n">format</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="n">time_t</span> <span class="n">unixTime</span> <span class="o">=</span> <span class="p">(</span><span class="n">time_t</span><span class="p">)</span> <span class="p">[</span><span class="nb">self</span> <span class="n">timeIntervalSince1970</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">tm</span> <span class="n">timeStruct</span><span class="p">;</span>  
</span></span><span class="line"><span class="cl"> <span class="n">localtime_r</span><span class="p">(</span><span class="o">&amp;</span><span class="n">unixTime</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">timeStruct</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">30</span><span class="p">];</span> 
</span></span><span class="line"><span class="cl"><span class="n">strftime</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="p">[[</span><span class="n">NSDate</span> <span class="nl">formatter</span><span class="p">:</span><span class="n">format</span><span class="p">]</span> <span class="nl">cStringUsingEncoding</span><span class="p">:[</span><span class="n">NSString</span> <span class="n">defaultCStringEncoding</span><span class="p">]],</span> <span class="o">&amp;</span><span class="n">timeStruct</span><span class="p">);</span> <span class="n">NSString</span><span class="o">*</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSString</span> <span class="nl">stringWithCString</span><span class="p">:</span><span class="n">buffer</span> <span class="nl">encoding</span><span class="p">:[</span><span class="n">NSString</span> <span class="n">defaultCStringEncoding</span><span class="p">]];</span> 
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="n">output</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reference: <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/Rubyfication/NSDate&#43;helpers.m#L71-80"target="_blank" rel="noopener">NSDate+helpers.m</a></p>
<p>Now follow each line to understand it:</p>
<ul>
<li>At line 4 it is returning the current time represented as the number of seconds since 1970. That method actually returns a <tt>NSTimeInterval</tt> which is a number that is essentially the same as the C-equivalent <tt>time_t</tt></li>
<li>At line 6 the C function <tt>localtime_r</tt> converts the <tt>unitTime</tt> number into the C-structure <tt>timeStruct</tt></li>
<li>At line 9 we call a custom method I created called <tt>formatter</tt> that just returns a <tt>strftime</tt> compatible string format. The Obj-C string (when we create using the &ldquo;@&rdquo; symbol) is an object that we must convert to an array of chars using the <tt>cStringUsingEncoding:</tt>. C functions don&rsquo;t understand Obj-C strings, hence the conversion. Then we finally call the <tt>strftime</tt> itself that will store the result in the <tt>buffer</tt> array of char that we declared before.</li>
<li>At line 10 we now do the reverse and convert the resulting C-string (array of chars) back into an Obj-C String.</li>
</ul>
<p>Now this is too nice. I have added a few other helper methods that now allow me to use it like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="n">it</span><span class="p">(</span><span class="err">`</span><span class="s">&#34;should convert the date to the rfc822 format&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">[[[</span><span class="n">ref</span> <span class="nl">toFormattedString</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;rfc822&#34;</span><span class="p">]</span> <span class="n">should</span><span class="p">]</span> <span class="nl">equal</span><span class="p">:</span><span class="s">@&#34;Fri, 01 Jan 2010 10:15:30&#34;</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"><span class="p">});</span> </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reference: <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/RubyficationTests/DateSpec.m#L69"target="_blank" rel="noopener">DateSpec.m</a></p>
<p>And the <tt>&ldquo;rfc822&rdquo;</tt> string will just be internally converted to <tt>@&quot;%a, %d %b %Y %H:%M:%S&quot;</tt> by the <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/Rubyfication/NSDate&#43;helpers.m#L82-100"target="_blank" rel="noopener"><tt>formatter:</tt></a> selector in the <tt>NSDate</tt> class.</p>
<p>Now, to add Ruby 1.9-level regular expressions you can go straight to the source and use the original C-based <a href="http://www.geocities.jp/kosako3/oniguruma/"target="_blank" rel="noopener">Oniguruma</a> itself, exactly what Ruby does. There are several ways to integrate a C library into your Cocoa project, but someone already did all the hard work. Satoshi Nakagawa wrote an Obj-C wrapper called <a href="http://limechat.net/cocoaoniguruma/"target="_blank" rel="noopener">CocoaOniguruma</a> that makes it dead easy to integrate into your project.</p>
<p>There are several ways to integrate an external library into your project. The easier way (albeit, not exactly the best) that I am showing here is by creating a new Static Library Target within my project, called <em>CocoaOniguruma</em>:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2010.33.47%20PM_original.png?1303608817" alt=""  loading="lazy" /></p>
<p>It will create a new Group called <em>CocoaOniguruma</em> in your project. Then you just add all the files from <a href="https://github.com/psychs/cocoaoniguruma/tree/master/framework/core"target="_blank" rel="noopener">CocoaOniguruma&rsquo;s core folder</a> to that group, select the new target and all the source files and headers will be properly added to the project, like this:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2010.37.19%20PM_original.png?1303608987" alt=""  loading="lazy" /></p>
<p>Finally, you need to go to the original main target of your application and add both the new target to the target dependencies and the binary <tt>.a</tt> file to the binary linking section, like this:</p>
<p><img src="http://s3.amazonaws.com/akitaonrails/assets/2011/4/23/Screen%20shot%202011-04-23%20at%2010.39.07%20PM_original.png?1303609098" alt=""  loading="lazy" /></p>
<p>With all this set, I recommend you to explore the <tt>OnigRegexp.m</tt> and <tt>OnigRegexpUtility.m</tt>, that are Obj-C wrappers to the Oniguruma library. The author already did some very Ruby-like syntax for you to use.</p>
<p>I have wrapped those helpers in my own classes like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">-</span> <span class="p">(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span> <span class="nf">gsub:</span><span class="p">(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span><span class="nv">pattern</span> <span class="nf">with:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">replacement</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">([</span><span class="n">replacement</span> <span class="nl">isKindOfClass</span><span class="p">:[</span><span class="n">NSString</span> <span class="k">class</span><span class="p">]])</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[</span><span class="nb">self</span> <span class="nl">replaceAllByRegexp</span><span class="p">:</span><span class="n">pattern</span> <span class="nl">with</span><span class="p">:</span><span class="n">replacement</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">([</span><span class="n">replacement</span> <span class="nl">isKindOfClass</span><span class="p">:[</span><span class="n">NSArray</span> <span class="k">class</span><span class="p">]])</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">__block</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>  
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[</span><span class="nb">self</span> <span class="nl">replaceAllByRegexp</span><span class="p">:</span><span class="n">pattern</span> <span class="nl">withBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">OnigResult</span><span class="o">*</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[</span><span class="n">NSString</span><span class="o">*</span><span class="p">](</span><span class="n">replacement</span> <span class="nl">objectAtIndex</span><span class="p">:(</span><span class="o">++</span><span class="n">i</span><span class="p">));</span>  
</span></span><span class="line"><span class="cl"> <span class="p">}];</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>  
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nb">nil</span><span class="p">;</span>  
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">-</span> <span class="p">(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span> <span class="nf">gsub:</span><span class="p">(</span><span class="n">NSString</span><span class="o">*</span><span class="p">)</span><span class="nv">pattern</span> <span class="nf">withBlock:</span><span class="p">(</span><span class="n">NSString</span><span class="o">*</span> <span class="p">(</span><span class="o">^</span><span class="p">)(</span><span class="n">OnigResult</span><span class="o">*</span><span class="p">))</span><span class="nv">replacement</span> <span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[</span><span class="nb">self</span> <span class="nl">replaceAllByRegexp</span><span class="p">:</span><span class="n">pattern</span> <span class="nl">withBlock</span><span class="p">:</span><span class="n">replacement</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reference: <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/Rubyfication/NSString&#43;helpers.m#L176-190"target="_blank" rel="noopener">NSString+helpers.m</a></p>
<p>Which now allows me to use this nicer syntax:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="n">context</span><span class="p">(</span><span class="err">`</span><span class="s">&#34;Regular Expressions&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">it</span><span class="p">(</span><span class="err">`</span><span class="s">&#34;should replace all substrings that match the pattern&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>  
</span></span><span class="line"><span class="cl"> <span class="p">[[[</span><span class="err">`</span><span class="s">&#34;hello world, heyho!&#34;</span> <span class="nl">gsub</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;h</span><span class="se">\\</span><span class="s">w+&#34;</span> <span class="nl">with</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;hi&#34;</span><span class="p">]</span> <span class="n">should</span><span class="p">]</span> <span class="nl">equal</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;hi world, hi!&#34;</span><span class="p">];</span>  
</span></span><span class="line"><span class="cl"> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">it</span><span class="p">(</span><span class="s">@&#34;should replace each substrings with one corresponding replacement in the array&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span> <span class="n">NSArray</span><span class="o">*</span> <span class="n">replacements</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithObjects</span><span class="p">:</span><span class="s">@&#34;hi&#34;</span><span class="p">,</span> <span class="s">@&#34;everybody&#34;</span><span class="p">,</span> <span class="nb">nil</span><span class="p">];</span> <span class="p">[[[</span><span class="err">`</span><span class="s">&#34;hello world, heyho!&#34;</span> <span class="nl">gsub</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;h</span><span class="se">\\</span><span class="s">w+&#34;</span> <span class="nl">with</span><span class="p">:</span><span class="n">replacements</span><span class="p">]</span> <span class="n">should</span><span class="p">]</span> <span class="nl">equal</span><span class="p">:</span><span class="s">@&#34;hi world, everybody!&#34;</span><span class="p">];</span> <span class="p">});</span> <span class="n">it</span><span class="p">(</span><span class="s">@&#34;should replace each substring with the return of the block&#34;</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span> <span class="p">[[[</span><span class="err">`</span><span class="s">&#34;hello world, heyho!&#34;</span> <span class="nl">gsub</span><span class="p">:</span><span class="err">`</span><span class="s">&#34;h</span><span class="se">\\</span><span class="s">w+&#34;</span> <span class="nl">withBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">OnigResult</span><span class="o">*</span> <span class="n">obj</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="s">@&#34;foo&#34;</span><span class="p">;</span> <span class="p">}]</span> <span class="n">should</span><span class="p">]</span> <span class="nl">equal</span><span class="p">:</span><span class="s">@&#34;foo world, foo!&#34;</span><span class="p">];</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reference: <a href="https://github.com/akitaonrails/ObjC_Rubyfication/blob/master/RubyficationTests/StringSpec.m#L86-102"target="_blank" rel="noopener">StringSpec.m</a></p>
<p>If you&rsquo;re thinking that it is strange for a snippet of Objective-C code to have keywords such as <tt>context</tt> or <tt>it</tt>, they come from <a href="http://www.kiwi-lib.info/"target="_blank" rel="noopener">Kiwi</a>, which builds an RSpec-like BDD testing framework on top of SenTesting Kit for Objective-C development that you should definitely check out. But the code above should be easy enough to understand without even knowing about Kiwi. If you&rsquo;re a Ruby developer, you will probably notice that the syntax bears some resemblance to what you&rsquo;re used to already.</p>
<p>So, linking to existing standard C libraries or even third-party open source C libraries is a piece of cake for those simple cases, without having to resort to any &ldquo;Native Interface&rdquo; tunneling between virtual machines or any other plumbing. If you want C, they&rsquo;re there for you to easily integrate and use.</p>
]]></content:encoded><category>apple</category><category>programming</category><category>tutorials</category></item><item><title>Off Topic: Why Programmers Should Play Go</title><link>https://akitaonrails.github.io/en/2008/07/15/off-topic-por-que-programadores-devem-jogar-go/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2008/07/15/off-topic-por-que-programadores-devem-jogar-go/</guid><pubDate>Tue, 15 Jul 2008 01:07:00 -0300</pubDate><description>&lt;p&gt;It&amp;rsquo;s been a while since I did a translation, but this article felt quite nostalgic to me, so I made a point of sharing it. It&amp;rsquo;s by &lt;a href="http://web.archive.org/web/20080720152831/http://railspikes.com/2008/7/14/why-programmers-should-play-go"target="_blank" rel="noopener"&gt;Jon Dahl&lt;/a&gt; from the &lt;strong&gt;RailSpikes&lt;/strong&gt; blog. Read my &lt;a href="#akitas-notes"&gt;notes&lt;/a&gt; at the end. Here it is:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://flickr.com/photos/andres-colmen/2539473895/"target="_blank" rel="noopener"&gt;&lt;img src="http://s3.amazonaws.com/akitaonrails/assets/2008/7/15/2539473895_47418f2049.jpg" alt="" loading="lazy" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Go_%28board_game%29"target="_blank" rel="noopener"&gt;Go&lt;/a&gt; is an ancient strategy game with simple rules and a profound degree of complexity.&lt;/p&gt;
&lt;p&gt;Software development is the art of managing complexity using a limited number of rules, structures, and patterns.&lt;/p&gt;</description><content:encoded><![CDATA[<p>It&rsquo;s been a while since I did a translation, but this article felt quite nostalgic to me, so I made a point of sharing it. It&rsquo;s by <a href="http://web.archive.org/web/20080720152831/http://railspikes.com/2008/7/14/why-programmers-should-play-go"target="_blank" rel="noopener">Jon Dahl</a> from the <strong>RailSpikes</strong> blog. Read my <a href="#akitas-notes">notes</a> at the end. Here it is:</p>
<p><a href="http://flickr.com/photos/andres-colmen/2539473895/"target="_blank" rel="noopener"><img src="http://s3.amazonaws.com/akitaonrails/assets/2008/7/15/2539473895_47418f2049.jpg" alt=""  loading="lazy" /></a></p>
<p><a href="http://en.wikipedia.org/wiki/Go_%28board_game%29"target="_blank" rel="noopener">Go</a> is an ancient strategy game with simple rules and a profound degree of complexity.</p>
<p>Software development is the art of managing complexity using a limited number of rules, structures, and patterns.</p>
<p>Programmers should play Go.</p>
<h3>Go in 2<sup>8</sup> words or less<span class="hx:absolute hx:-mt-20" id="go-in-28-words-or-less"></span>
    <a href="#go-in-28-words-or-less" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The beauty of Go is its combination of simplicity and complexity. On the one hand, go has only a handful of rules. Place stones, don&rsquo;t get completely surrounded, control territory. Like chess, the mechanics can be picked up in a few minutes, though Go only has a single type of &ldquo;move&rdquo;, and only one edge case (the <a href="http://en.wikipedia.org/wiki/Rules_of_Go#Ko_.28no_repetition_of_the_same_shape.29"target="_blank" rel="noopener">ko</a> rule). And like chess, one can spend a lifetime discovering the strategic and tactical layers of the game.</p>
<p>While chess is quite complex and rich, such that it took a 30-node supercomputer to defeat the reining chess champion, no computer comes close to defeating even a skilled amateur Go player. There are 361 positions on a Go board, and with two players, there are 2.08168199382×10<sup>170</sup> valid positions. That&rsquo;s quite a bit bigger than a <a href="http://en.wikipedia.org/wiki/Googol"target="_blank" rel="noopener">googol</a> (yes, that is the correct spelling). Realistically, there are something on the order of 10<sup>400</sup> possible ways that a typical game could play out. And the number of possible moves roughly follows 361!, which means that only 20 moves in, there are many googols of possible ways that the game could shake down. (As a fun exercise, try plugging 361! into an online <a href="http://web.archive.org/web/20240416232143/https://www.cs.uml.edu/~ytran/factorial.html"target="_blank" rel="noopener">factorial calculator</a>.)</p>
<h3>Managing complexity<span class="hx:absolute hx:-mt-20" id="managing-complexity"></span>
    <a href="#managing-complexity" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>So how does one play Go, given this near-infinite complexity? On a tactical level, a player approaches Go like chess, thinking several moves ahead. But this only works in small spaces, like a tight battle in a small sector of the board. Beyond there, there are just too many possibilities. So on a strategic level, a player must think in <a href="http://en.wikipedia.org/wiki/Shape_%28Go%29"target="_blank" rel="noopener">shapes</a> or patterns. These shapes provide shorthand ways of managing the complexity of Go. As a non-master, I may have no idea how things will proceed in one sector of the board, but I may be able to recognize strong and weak patterns of stones, vulnerable shapes and effective formations.</p>
<p>But there&rsquo;s more: Go has several sorts of patterns. Beyond shapes, there are <a href="http://senseis.xmp.net/?GoProverbs"target="_blank" rel="noopener">Go proverbs</a>. These can be general: <em>&ldquo;Your opponent&rsquo;s good move is your good move&rdquo;</em>; specific: <em>&ldquo;Don&rsquo;t try to cut the one-point jump&rdquo;</em>; funny: <em>&ldquo;Even a moron connects against a peep&rdquo;</em>; and meta: <em>&ldquo;Don&rsquo;t follow proverbs blindly.&rdquo;</em> These proverbs are principles which help a player make good decisions. They are less specific than shapes, and so they provide guidelines for whatever situations may arise on the Go board. Proverbs often conflict, and a player must determine when and how to apply them.</p>
<p>Finally, there are <a href="http://en.wikipedia.org/wiki/Joseki"target="_blank" rel="noopener">joseki</a>. Joseki are patterns of play that are considered even for both sides. They typically happen in the corners of the board, and typically at the beginning of the game. Interestingly, there is a Go proverb that says <em>&ldquo;Learning joeski costs two stones,&rdquo;</em> meaning that memorizing these patterns isn&rsquo;t helpful. Instead, a player should learn <em>from</em> joseki by understanding what is going on in each move.</p>
<h3>Patterns in Go, patterns in software design<span class="hx:absolute hx:-mt-20" id="patterns-in-go-patterns-in-software-design"></span>
    <a href="#patterns-in-go-patterns-in-software-design" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Each of these Go patterns has a rough programming analogue.</p>
<p>Shapes in Go aren&rsquo;t unlike software <a href="http://c2.com/cgi/wiki?DesignPatterns"target="_blank" rel="noopener">design patterns</a>. While there is nothing preventing you from placing logic in your views, this shape is <a href="http://www.vimeo.com/1050804"target="_blank" rel="noopener">recognized</a> to be a weak one. Think of Gang-of-Four design patterns: the MVC, Adapter, and Factory patterns are recognized to be helpful in some circumstances (and not appropriate in others). On a lower level, iteration and recursion have commonly recognized shapes, as do database normalization vs. denormalization. Even if you can&rsquo;t hold an entire program or algorithm in your head at once, recognizing common shapes helps you to understand what is going on.</p>
<p>Go proverbs are like another type of pattern in software: CapitalizedPrinciples (for lack of a better term) made popular by Extreme Programming. Think DontRepeatYourself, YouArentGonnaNeedIt, CollectiveCodeOwnership, DailyBuild, TestFirst. These aren&rsquo;t specific code &ldquo;shapes&rdquo;, like a singleton class – they are general principles that guide the practice of programming.</p>
<p>Because joseki is about exchange between competing parties, its programming parallel is a little less clear. The closest comparison, in my mind, is programming exercises. <a href="http://binstock.blogspot.com/2008/04/perfecting-oos-small-classes-and-short.html"target="_blank" rel="noopener">This article</a>, for instance, suggests 9 exercises to help you become a better OO programmer, like:</p>
<ul>
<li>Use only one dot per line</li>
<li>Use only one level of indentation per method</li>
<li>Don&rsquo;t use setters, getters, or properties</li>
</ul>
<p>In a real-world program, you&rsquo;re unlikely to stick to these principles 100% of the time. But forcing yourself to write code in this way can be an eye-opening experience and can make you a better developer.</p>
<h3>So what can Go really do for you?<span class="hx:absolute hx:-mt-20" id="so-what-can-go-really-do-for-you"></span>
    <a href="#so-what-can-go-really-do-for-you" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Obviously, these parallels are structural. Specific Go proverbs (&ldquo;Your opponent&rsquo;s good move is your good move&rdquo;) may not have direct relevance to software development. So can Go really make you a better developer?</p>
<p>I think it can, and I&rsquo;ll go one further. I think Go can make you smarter. There is a lot of anecdotal evidence to this effect <a href="http://web.archive.org/web/20170616121831/http://www.godiscussions.com/forum/archive/index.php/t-6061.html"target="_blank" rel="noopener"><sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup></a>, <a href="http://news.ycombinator.com/item?id=133178"target="_blank" rel="noopener"><sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup></a>, <a href="http://news.ycombinator.com/item?id=228356"target="_blank" rel="noopener"><sup class="footnote" id="fnr3"><a href="#fn3">3</a></sup></a>, for example, <a href="http://www.china.org.cn/english/features/Archaeology/131298.htm"target="_blank" rel="noopener"><sup class="footnote" id="fnr4"><a href="#fn4">4</a></sup></a>:</p>
<blockquote>
  <p>In fact, all of our minds can benefit from playing Go, which officially has the capacity to make you smarter. Research has shown that that children who play Go have the potential for greater intelligence, since it motivates both the right and left sides of the brain.</p>

</blockquote>
<p>The research mentioned isn&rsquo;t footnoted, unfortunately, so take statements like this with a grain of salt.</p>
<p>But it makes sense: like chess, Go requires pattern recognition, a mix of strategic and tactical thinking, and comprehension of complex structures, though in Go the patterns are larger and the complexity is greater. A mind trained to think in these ways is going to have an easier time attacking similar problems in other spheres.</p>
<p>Like software development.</p>
<h3>Akita&rsquo;s Notes<span class="hx:absolute hx:-mt-20" id="akitas-notes"></span>
    <a href="#akitas-notes" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I&rsquo;ve liked Go for a long time. As someone of Japanese descent, of course I&rsquo;d been exposed to Go, Shogi, and other oriental games. But, like any good westernized Japanese, I paid very little attention to them. Because of this, today I know no more than the basic rules and philosophies behind Go.</p>
<p>My interest was particularly renewed when I read the <a href="http://en.wikipedia.org/wiki/Hikaru_no_Go"target="_blank" rel="noopener">Hikaru no Go</a> series, which is an entire story built around Go, and one of my favorite series, by the way. I even bought a Go board and some joseki books, but didn&rsquo;t get very far. These days I just peek at online games on the <a href="https://pandanet-igs.com/"target="_blank" rel="noopener">IGS</a> servers.</p>
<p><a href="http://web.archive.org/web/20080725154909/http://www.onemanga.com/Hikaru_no_Go/"target="_blank" rel="noopener"><img src="http://s3.amazonaws.com/akitaonrails/assets/2008/7/15/1hikaru800.jpg" alt=""  loading="lazy" /></a></p>
<p>I don&rsquo;t remember where I read this, but someone once mentioned something interesting: chess is primarily a game of destruction. Go is essentially a game of conquest and expansion. Not literally true, but there are nuances in Go that bring this to mind.</p>
<p>And in the parallel to software development, design patterns aren&rsquo;t just structures you copy and paste wherever you &ldquo;think&rdquo; they&rsquo;re needed. A handful of design patterns doesn&rsquo;t make good software.</p>
<p>What Jon was getting at makes a lot of sense. Just like a Go player, a software developer needs to be an artist. Playing is a creative activity. Strategy is a creative activity. Given a set of constraints, what&rsquo;s the best path forward?</p>
<p>More than that: the only way to learn Go is by playing, hundreds of thousands of times over many, many years. Go professionals are formed around age 10 and climb from there into old age. The only way to learn is by failing, failing, and failing again. Which circles back to what Ryan said about <a href="/2008/06/14/machucando-c-digo-por-divers-o-e-lucro/">Hurting Code</a>.</p>
<p>Refactoring is something similar to this: conquest and expansion. Only a good developer understands the real reasons for refactoring. Nobody refactors because someone told them to, just as an artist doesn&rsquo;t make a certain stroke because someone told them to.</p>
<p>A good developer values the form and philosophy of what is being built. Acronyms, brands, and fashionable names say nothing to them.</p>
<p>There&rsquo;s a lack of eastern philosophy in today&rsquo;s programmers. Being a brick-stacking coder is very easy: any grunt can do it. But reaching the <a href="http://en.wikipedia.org/wiki/Go_ranks_and_ratings"target="_blank" rel="noopener">10th dan</a> of programming is only for those who have put in the work in the art.</p>
]]></content:encoded><category>learning</category><category>programming</category><category>gaming</category><category>off-topic</category></item></channel></rss>