<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Deus In Machina]]></title><description><![CDATA[Welcome! I'm all about exploring the intersections of programming, technology, and culture with insights on development trends, language deep dives, and reflections on software evolution in a rapidly changing digital landscape]]></description><link>https://www.deusinmachina.net</link><image><url>https://substackcdn.com/image/fetch/$s_!ackF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png</url><title>Deus In Machina</title><link>https://www.deusinmachina.net</link></image><generator>Substack</generator><lastBuildDate>Mon, 27 Apr 2026 09:20:46 GMT</lastBuildDate><atom:link href="https://www.deusinmachina.net/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Diego Crespo]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[deusinmachina@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[deusinmachina@substack.com]]></itunes:email><itunes:name><![CDATA[Diego Crespo]]></itunes:name></itunes:owner><itunes:author><![CDATA[Diego Crespo]]></itunes:author><googleplay:owner><![CDATA[deusinmachina@substack.com]]></googleplay:owner><googleplay:email><![CDATA[deusinmachina@substack.com]]></googleplay:email><googleplay:author><![CDATA[Diego Crespo]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[AI is just the latest Monoculture]]></title><description><![CDATA[There&#8217;s growing anxiety that AI will be the death of innovation.]]></description><link>https://www.deusinmachina.net/p/ai-is-just-the-latest-monoculture</link><guid isPermaLink="false">https://www.deusinmachina.net/p/ai-is-just-the-latest-monoculture</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 05 Feb 2026 14:11:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uzXV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uzXV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uzXV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uzXV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg" width="1193" height="620" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:620,&quot;width&quot;:1193,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:99419,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.deusinmachina.net/i/186978058?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uzXV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uzXV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596c519-bf92-49b0-b610-fc5b166cab4c_1193x620.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>There&#8217;s growing anxiety that AI will be the death of innovation. The argument goes like this: LLMs are trained on existing code, so they recommend existing tools, so people use existing tools, so future LLMs are trained on even more of the same. New programming languages, libraries, and frameworks will face an impossible bootstrapping problem. How do you gain adoption when the coding assistant everyone uses has never seen your syntax?</p><p>It&#8217;s a reasonable concern. But I think it misses something important. LLMs aren&#8217;t introducing lock-in to software. They&#8217;re inheriting it. The feedback loop that people are worried about has been running for fifty years.</p><h2>We optimize for familiarity, not quality</h2><p>Look at the tools we celebrate as modern breakthroughs. Bun is a faster Node.js that runs the same code. Zig cc is llvm with better cross compilation. uv is a faster pip that installs the same packages. These are genuine improvements, and uv specifically has made my life as a Python developer significantly better. But notice what they have in common: none of them ask you to learn anything new. They compete on speed and reliability while carefully preserving the interfaces we already know.</p><p>This isn&#8217;t a criticism. It&#8217;s a survival strategy. Tools that demand new mental models face an uphill battle that most don&#8217;t survive. The path of least resistance is to make your new thing look exactly like the old thing. And that&#8217;s been true long before anyone was worried about training data.</p><h2>The lock-in runs deep</h2><h3>The C ABI</h3><p>Every language that wants to participate in systems programming eventually implements extern &#8220;C&#8221;. Rust does it. Go does it. Zig does it. Odin does it. Not because the C calling convention is well-designed, but because it&#8217;s the only calling convention that everything else understands.</p><p><br>The C ABI wasn&#8217;t created to be a universal standard. It just got there first. Now it constrains what languages can efficiently express at their boundaries. Features that don&#8217;t map cleanly onto C&#8217;s model, things like tagged unions, multiple return values, or non-nullable pointers, require awkward workarounds or simply get abandoned at the FFI layer. C++ carries decades of baggage specifically because it needed to interoperate with C. Until WebAssembly matures, there&#8217;s no real alternative. You speak C&#8217;s ABI, you spin up a webserver and communicate through REST or gRPC, or you don&#8217;t talk to anyone.</p><h3>Curly braces everywhere</h3><p>When Brendan Eich built JavaScript in ten days, management gave him an explicit instruction: make it look like Java. Not because Java&#8217;s syntax was suited to a dynamic scripting language, but because Java was familiar. And Java looked like C++ because C++ looked like C.</p><p><br>Follow the chain forward. Every mainstream language of the last thirty years uses curly braces for blocks. Java, JavaScript, C#, Go, Rust, Swift, Kotlin, TypeScript. The languages that tried something different, Python&#8217;s significant whitespace, Ruby&#8217;s end keywords, Lisp&#8217;s parentheses, either carved out niches or stayed marginal.</p><p>This pressure is so strong that the Racket team, when designing their new language Rhombus, deliberately abandoned s-expression syntax. From their documentation:</p><blockquote><p>Rhombus is a new language that is built on Racket. It offers the same kind of language extensibility as Racket itself, but using traditional (infix) notation.</p></blockquote><p>Even the people building a language specifically to showcase the power of Lisp-style macros felt they had to wrap it in familiar clothing. The syntax isn&#8217;t better. It&#8217;s just what people already know.</p><h3>The x86/ARM/NVIDIA chokepoints</h3><p>For decades, x86 dominated servers and desktops while ARM dominated mobile. Alternatives existed. MIPS, PowerPC, SPARC, Itanium. The weight of existing software, compilers, toolchains, and developer familiarity crushed all of them.<br>RISC-V is the current challenger, and look at how it&#8217;s positioning itself: as a drop-in replacement that slots into existing workflows, not as a fundamentally different way of thinking about processors. The pitch is &#8220;you won&#8217;t have to change anything.&#8221; That&#8217;s the only pitch that works.</p><p>The same dynamic plays out in GPUs. NVIDIA&#8217;s dominance isn&#8217;t just about hardware quality. It&#8217;s about CUDA. Try starting a new GPU company and see how far you get when every machine learning framework assumes CUDA exists. Intel is trying. It&#8217;s not going well. AMD has a chance, but ROCm has only recently started turning into a serious framework.</p><h3>The browser is a bad operating system we&#8217;re stuck with</h3><p>The web was designed for linked documents. JavaScript was bolted on as an afterthought. CSS was meant for styling academic papers. Somehow this accidental stack became the universal application platform.</p><p>Every attempt to replace it failed. Flash is dead. Silverlight is dead. Java applets are dead. Native app stores exist but haven&#8217;t displaced the web. So now we build complex applications by fighting against a document viewer, papering over its limitations with thousands of npm packages.</p><p><br>WebAssembly was supposed to change things. But notice what actually happened: it runs alongside JavaScript rather than replacing it. You still can&#8217;t escape the DOM. The gravitational pull of existing infrastructure is too strong.</p><h3>So what about AI?</h3><p>I could keep going. Git&#8217;s specific model of version control won and now everyone thinks in commits and branches. Unix file permissions from the 1970s still shape what&#8217;s possible on modern systems. QWERTY persists despite tradeoffs being made due to typewriter limitations.</p><p><br>The point is this: lock-in isn&#8217;t something that might happen if we&#8217;re not careful with AI. It&#8217;s the default state of computing. It&#8217;s what happens whenever switching costs accumulate faster than the benefits of switching.</p><p>Will LLMs accelerate this? Probably. A coding assistant that&#8217;s never seen your new language is a real barrier to adoption. But it&#8217;s a barrier stacked on top of dozens of existing barriers. The monoculture was already here. AI is just learning to speak it fluently.<br><br><strong>Call To Action &#128227;</strong></p><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a>, <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, and <a href="https://www.threads.net/@deusinmachinablog">Threads</a> if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/ai-is-just-the-latest-monoculture?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/ai-is-just-the-latest-monoculture?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5f25c2b2-bd4f-4243-88aa-015f253b5807&quot;,&quot;caption&quot;:&quot;Happy &#129411; Day! I hope everyone has a wonderful day&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Story of Nel&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25d2568c-107b-4954-aeb7-eb43776e15ae_854x854.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-11-29T03:17:59.047Z&quot;,&quot;cover_image&quot;:null,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/the-story-of-nel&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:152307266,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:1,&quot;publication_id&quot;:1146359,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!ackF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[An Amusing New Year's Eve]]></title><description><![CDATA[And a Happy New Year]]></description><link>https://www.deusinmachina.net/p/an-amusing-new-years-eve</link><guid isPermaLink="false">https://www.deusinmachina.net/p/an-amusing-new-years-eve</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 01 Jan 2026 01:57:14 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" width="4091" height="2720" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2720,&quot;width&quot;:4091,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;green, red, and white fireworks on sky at nighttime&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="green, red, and white fireworks on sky at nighttime" title="green, red, and white fireworks on sky at nighttime" srcset="https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1498931299472-f7a63a5a1cfa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxmaXJlJTIwd29ya3N8ZW58MHx8fHwxNzY3MjIwODczfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@rayhennessy">Ray Hennessy</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h2>Calling Raylib from PowerShell via P/Invoke</h2><p>It was a quiet New Year&#8217;s for me, which caps off a pretty eventful year. I had some time off recently and have been cranking through some fun but challenging personal projects that I hope to share more about in 2026. In the meantime, I decided to blow off some steam with a silly project just to remind myself that programming can still be fun.</p><h2>The Setup</h2><p>PowerShell can call native C libraries directly through .NET&#8217;s P/Invoke mechanism. That means I can bind to raylib entirely from PowerShell. No C# project files, no compilation step, just a simple <code>.ps1</code> script. Is this useful? Probably not, but that didn&#8217;t stop me.</p><p>I grabbed the latest version of raylib from GitHub (version 5.5), threw it into a folder called <code>PowerShell</code>, and created my <code>test_raylib.ps1</code>:</p><pre><code><code>PS ~/Documents/Programming/PowerShell&gt; (Get-ChildItem).name
raylib-5.5_linux_amd64
test_raylib.ps1
PS ~/Documents/Programming/PowerShell&gt; 
</code></code></pre><p>Since I&#8217;m on Fedora 43, I had to tell the dynamic linker where to find the library at the top of my script:</p><pre><code><code>$env:LD_LIBRARY_PATH = "$PWD/raylib-5.5_linux_amd64/lib"
</code></code></pre><p>PowerShell&#8217;s <code>Add-Type</code> cmdlet can compile inline C# code, including P/Invoke declarations, so we can just do this to bind the library:</p><pre><code><code>Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct Color {
    public byte r, g, b, a;
    public Color(byte r, byte g, byte b, byte a) {
        this.r = r; this.g = g; this.b = b; this.a = a;
    }
}

public static class Raylib {
    const string dll = "libraylib.so";

    [DllImport(dll)] public static extern void InitWindow(int width, int height, string title);
    [DllImport(dll)] public static extern void CloseWindow();
    [DllImport(dll)] public static extern bool WindowShouldClose();
    [DllImport(dll)] public static extern void BeginDrawing();
    [DllImport(dll)] public static extern void EndDrawing();
    [DllImport(dll)] public static extern void ClearBackground(Color color);
    [DllImport(dll)] public static extern void DrawCircle(int centerX, int centerY, float radius, Color color);
    [DllImport(dll)] public static extern void DrawRectangle(int posX, int posY, int width, int height, Color color);
    [DllImport(dll)] public static extern void DrawText(string text, int posX, int posY, int fontSize, Color color);
    [DllImport(dll)] public static extern int GetKeyPressed();
    [DllImport(dll)] public static extern bool IsKeyReleased(int key);
    [DllImport(dll)] public static extern void SetTargetFPS(int fps);
}
"@
</code></code></pre><p>Then we set up some variables:</p><pre><code><code># Colors
$red = [Color]::new(230, 41, 55, 255)
$green = [Color]::new(0, 228, 48, 255)
$raywhite = [Color]::new(245, 245, 245, 255)
$darkgray = [Color]::new(80, 80, 80, 255)

# Key codes
$KEY_A = 65
$KEY_D = 68
$KEY_LEFT = 263
$KEY_RIGHT = 262

# Game state
$playerX = 400
$ballX = 400
$ballY = 300
$ballDX = 3
$ballDY = 3
$score = 0
$movingLeft = $false
$movingRight = $false
</code></code></pre><p>And then call the functions from PowerShell:</p><pre><code><code># Initialize window
[Raylib]::InitWindow(800, 600, "PowerShell Pong-ish!")
[Raylib]::SetTargetFPS(60)

# Game loop
while (-not [Raylib]::WindowShouldClose()) {
    # We've got to do this manually
    $pressed = [Raylib]::GetKeyPressed()
    if ($pressed -eq $KEY_LEFT -or $pressed -eq $KEY_A) { $movingLeft = $true }
    if ($pressed -eq $KEY_RIGHT -or $pressed -eq $KEY_D) { $movingRight = $true }

    # Check for key releases
    if ([Raylib]::IsKeyReleased($KEY_LEFT) -or [Raylib]::IsKeyReleased($KEY_A)) { $movingLeft = $false }
    if ([Raylib]::IsKeyReleased($KEY_RIGHT) -or [Raylib]::IsKeyReleased($KEY_D)) { $movingRight = $false }

    # Apply movement
    if ($movingRight -and $playerX -lt 700) { $playerX += 6 }
    if ($movingLeft -and $playerX -gt 0) { $playerX -= 6 }

    # Ball movement
    $ballX += $ballDX
    $ballY += $ballDY

    # Ball collision with walls
    if ($ballX -le 10 -or $ballX -ge 790) { $ballDX = -$ballDX }
    if ($ballY -le 10) { $ballDY = -$ballDY }

    # Ball collision with paddle
    if ($ballY -ge 480 -and $ballY -le 500 -and $ballX -ge $playerX -and $ballX -le ($playerX + 100)) {
        $ballDY = -$ballDY
        $score++
    }

    # Ball fell off bottom - reset
    if ($ballY -gt 620) {
        $ballX = 400
        $ballY = 300
        $score = 0
    }

    # Draw
    [Raylib]::BeginDrawing()
    [Raylib]::ClearBackground($raywhite)
    [Raylib]::DrawRectangle($playerX, 500, 100, 20, $darkgray)
    [Raylib]::DrawCircle($ballX, $ballY, 10, $red)
    [Raylib]::DrawText("Score: $score", 10, 10, 20, $darkgray)
    [Raylib]::DrawText("A/D or Arrow keys to move", 10, 40, 16, $green)
    [Raylib]::EndDrawing()
}

[Raylib]::CloseWindow()
</code></code></pre><p>And that&#8217;s it!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2k6s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2k6s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 424w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 848w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 1272w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2k6s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp" width="595" height="508" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:508,&quot;width&quot;:595,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Pong in Powershell&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Pong in Powershell" title="Pong in Powershell" srcset="https://substackcdn.com/image/fetch/$s_!2k6s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 424w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 848w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 1272w, https://substackcdn.com/image/fetch/$s_!2k6s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5901cfb-5248-45dd-9507-84de53d61dc0_595x508.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Well, not quite. It took a few tries to get it right. And you&#8217;ll quickly see one of the many flaws with this approach if you try it yourself.</p><h2>The Gotchas</h2><p>When iterating on your P/Invoke definitions, you will run into errors like this:</p><pre><code><code>Cannot add type. The type name 'Color' already exists.</code></code></pre><p>Once <code>Add-Type</code> compiles and loads a type into the .NET runtime, it cannot be unloaded or redefined within the same PowerShell session. Your options are:</p><ul><li><p>Restart PowerShell every time you change the type definitions</p></li><li><p>Rename your types during development (Color &#8594; RLColor2 &#8594; RLColor3... definitely not what I did)</p></li><li><p>Use namespaces with version numbers</p></li><li><p>Compile to a DLL once your bindings are stable</p></li></ul><p>The other major challenge was on Fedora 43 with Wayland: <code>IsKeyDown()</code> always returned <code>false</code>, even though <code>GetKeyPressed()</code> worked fine. Who knows why this happens.</p><p>The solution was to track key state manually using the event-based functions:</p><pre><code><code># We've got to do this manually
$pressed = [Raylib]::GetKeyPressed()
if ($pressed -eq $KEY_LEFT -or $pressed -eq $KEY_A) { $movingLeft = $true }
if ($pressed -eq $KEY_RIGHT -or $pressed -eq $KEY_D) { $movingRight = $true }

# Check for key releases
if ([Raylib]::IsKeyReleased($KEY_LEFT) -or [Raylib]::IsKeyReleased($KEY_A)) { $movingLeft = $false }
if ([Raylib]::IsKeyReleased($KEY_RIGHT) -or [Raylib]::IsKeyReleased($KEY_D)) { $movingRight = $false }
</code></code></pre><p>Not something I&#8217;d want to do in a larger program, but it works for this small example.</p><p>And that&#8217;s all I&#8217;ve got for today. Happy New Year&#8217;s everyone!</p><h2>Call To Action &#128227;</h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a> <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, and <a href="https://www.threads.net/@deusinmachinablog">Threads</a> if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;fdeaf909-d059-4797-82a7-7566f852a68e&quot;,&quot;caption&quot;:&quot;Often dismissed as an eccentric and verbose scripting language from Microsoft, PowerShell frequently finds itself relegated to the background when it comes to shell languages on non-Windows platforms. Mocked as a lackluster corporate attempt at mimicking a genuine shell scripting language, it rarely receives the attention it deserves. However, after lev&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The case for PowerShell On macOS and Linux&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25d2568c-107b-4954-aeb7-eb43776e15ae_854x854.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-08-17T12:00:18.849Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!UB3T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02feb201-8620-4b9a-9123-c0e40f3047c6_1200x750.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/the-case-for-powershell-on-macos&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:135897607,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1146359,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!ackF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/an-amusing-new-years-eve?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/an-amusing-new-years-eve?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p>]]></content:encoded></item><item><title><![CDATA[The Dart Programming Language Is Underrated]]></title><description><![CDATA[A few months ago, I started programming in Dart.]]></description><link>https://www.deusinmachina.net/p/the-dart-programming-language-is</link><guid isPermaLink="false">https://www.deusinmachina.net/p/the-dart-programming-language-is</guid><pubDate>Thu, 05 Dec 2024 13:02:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!To6f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!To6f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!To6f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!To6f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!To6f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!To6f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!To6f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:707500,&quot;alt&quot;:&quot;a nerdy looking 3d model of the dart mascot called a dashatar&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="a nerdy looking 3d model of the dart mascot called a dashatar" title="a nerdy looking 3d model of the dart mascot called a dashatar" srcset="https://substackcdn.com/image/fetch/$s_!To6f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!To6f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!To6f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!To6f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7236e206-d4d1-4ed5-8e6c-964c3a48620c_1920x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A few months ago, I started programming in Dart. I was drawn to it because of Flutter, and the frustrating experience I've had using other Desktop GUI libraries like GTK3, GTK4, FLTK, WxWidgets, AvaloniaUI, Raygui, QT, etc. In my time using the language it was easy to pick up, and I felt like it had a good amount of features for a modern OOP language. But that wasn't always the case, and Dart had to reinvent itself multiple time to get to where it is today. I'll go over some of the history of Dart, and then give some thoughts on my experience using it in this language review. If you'd just like to skip the history lesson and read my thoughts on using the language, jump to the section titled "My Experience with Dart so far".</p><h2>Origins of Dart</h2><p>In October 2011, Google unveiled Dart at the GOTO conference in Aarhus, Denmark. The language was developed by Lars Bak and Kasper Lund, both renowned for their work on virtual machines and language design. Dart's initial aim was ambitious... To address the shortcomings of JavaScript and provide a language that could scale from small scripts to large, and complex applications <a href="https://googlecode.blogspot.com/2011/10/Dart-language-for-structured-web.html">inside of the browser</a></p><p>At the time, web applications were becoming increasingly complex, and JavaScript, despite its ubiquity, was showing its limitations in terms of performance and maintainability for large codebases. Dart was designed to improve on JavaScript by offering optional static typing, a more advanced virtual machine, and improved ergonomics by having more expressive language constructs.</p><h3>Early Years and Dart 1.x</h3><p>The initial versions of Dart focused on being a superior language for web development. Developers could write Dart code and compile it to JavaScript using the <code>Dart2js</code> compiler, allowing it to run in any modern browser, but the ultimate goal was for all browsers to support the Dart VM directly, allowing developers to have another blessed language to program in the browser. Google went as far as getting Dart certified as an ECMA standard with <a href="https://ecma-international.org/publications-and-standards/standards/ecma-408/#:~:text=ECMA-408.%20Dart%20programming%20language">ECMA-408</a>, and created a custom fork of Chromium called "Dartium", which integrated the Dart VM directly. Despite these efforts, Dart struggled to gain traction in the web development community.</p><p>In an effort to strengthen Dart's position in web development, Google developed <a href="https://github.com/angularDart">AngularDart</a>, a port to Dart of the popular Angular web framework. <code>AngularDart</code> offered strong typing and performance benefits over its JavaScript counterpart and was used internally at Google for building complex web applications. However, the broader web development community continued to favor JavaScript, especially after the major updates to the language that came with ES6, and the rise of TypeScript, Microsoft's language that added optional static typing to JavaScript.</p><p>In 2015, Google introduced Flutter, a UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. Dart was chosen as the language for Flutter due to its familiar syntax, performant VM, and excellent tooling with tools like <code>Observatory</code>, a profiler, debugger, and introspection tool. Dart's Hot reload feature also enhanced developer productivity, allowing developers to see code changes in real time without restarting the application. This combination enabled the creation of a GUI toolkit with very fast development cycles, significantly improving developer experience.</p><h3>Dart 2.0 and a New Direction</h3><p>But JavaScript was advancing quickly and Dart was failing to gain traction. Recognizing the challenges in replacing JavaScript, Google shifted Dart's focus. In 2018, they released <a href="https://medium.com/Dartlang/announcing-Dart-2-80ba01f43b6#:~:text=Dart%202:%20Better%20Client-Side%20Development.">Dart 2.0</a> with a renewed mission... To optimize client side development for web and mobile platforms. This brought significant changes to the language. They ditched the optional typing and instead went for a sound type system. They removed legacy features and improved the language based on feedback from the Flutter Team, AdWords, AdSense and Dart community. With these changes Dart modified its focus to lean into its ability to compile into efficient JavaScript, its ability to modify programs as they ran through hot reload, and the safety of the language through its sound type system.</p><p>On the web front, Dart powered mission critical applications like Google AdWords and AdSense, significantly boosting developer productivity while maintaining performance and reliability. The Team emphasized Dart's importance to Google, noting how it was being used to power a major source of Google's revenue through AdWords. They also highlighted Dart's capabilities in the mobile space by showing off how the official Hamilton: The Musical app, was built using Flutter.</p><p>While this shift in focus definitely helped save Dart, it began to sow doubt in the community about whether Google would keep Dart around long term. Google already had Go, had made significant investments in Kotlin, and Dart had failed in its original mission in being the web's next programming language. Given Google's tendency to kill products people began to wonder if Dart was next on the chopping block.</p><p>Unfortunately Dart has never been able to shake this feeling even now, 6 years and another major release later. Whenever Google announces layoffs, or kills another product, people start speculating on Dart and Flutters future. The Dart team continues to have to calm the community every time this happens, despite its best efforts. The Dart website even displays a link to the roadmap</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Pj7H!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Pj7H!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 424w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 848w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 1272w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Pj7H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png" width="800" height="298" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:298,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Screen shot of the dart website with a highlighted box over the link to the roadmap&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Screen shot of the dart website with a highlighted box over the link to the roadmap" title="Screen shot of the dart website with a highlighted box over the link to the roadmap" srcset="https://substackcdn.com/image/fetch/$s_!Pj7H!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 424w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 848w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 1272w, https://substackcdn.com/image/fetch/$s_!Pj7H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F766f815e-d87b-4a20-a016-b798d1fbad05_800x298.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>prominently at the very top of the page, as if to say "See, Google still has long term plans for this language". This Sword of Damocles over Dart's head hurts its adoption, and is one of the largest reason for people's hesitancy to adopt it as a technology, even though languages like TypeScript have been able to make significant inroads into the web community.</p><h3>Dart 3.0</h3><p>In 2023, after five years and numerous incremental releases, Google announced <a href="https://medium.com/Dartlang/announcing-Dart-3-53f065a10635#:~:text=Today,%20live%20from%20Mountain%20View,%20we%E2%80%99re">Dart 3.0</a>. The largest update to Dart to date, coming with 3 headlining features. The first was 100% sound null safety which the team had been incrementally working towards for the last 6 years. The "sound part" was a big deal and meant that if a value was declared non nullable, it was guaranteed by the compiler. This along with sound type safety makes Dart a very safe language overall.</p><p>The second major feature was Records, Patterns, and Class Modifiers. This gave Dart some additional functional programming features, as well as an increase in its ability to create rich and expressive programs.</p><p>Finally, Dart 3 introduced support for compiling Dart code to WebAssembly, enabling the delivery of Dart apps as native code across all modern browsers. Previously, Dart's use of garbage collection hindered its compilation to Wasm, but collaboration with the WebAssembly community led to the development of the new WasmGC feature, now nearing stability in Chromium and Firefox. This allows Dart web apps to have improved load times, and enhanced performance.</p><h2>My Experience with Dart so far</h2><p>I've used Dart for 3 projects. A CLI that grabbed the profile sprite of every FREEDOOM and DOOM sprite, so I could compile them into a <a href="https://docs.google.com/document/d/16kHQM5S_G8uoIgS_9jR7X7hMfw3sMdj8BaAlIToF4Xw/edit?usp=sharing">reference document</a>, a library that parses <a href="https://gitlab.com/diegocrespo/wads_up">DOOM wad</a> files so I can understand how the binary format works (notice a trend?), and a <a href="https://gitlab.com/diegocrespo/terbomine">File browser app</a> that indexes files by content instead of filename allowing you to do full text search on a specified set of folders. While working on these projects I was exposed to a lot of Dart's interesting features, quirks, and drawbacks, and I learned some new things about programming along the way. Here's what I found</p><h3>Dart is expressive, and very OOP</h3><p>This one you'll either love or hate. In Python when writing platform dependent code I usually write it like this</p><pre><code><code>import platform

current_platform = platform.system()

if current_platform == "Windows":
    print("Running on Windows!")
elif current_platform == "Linux":
    print("Running on Linux!")
elif current_platform == "Darwin":  # macOS
    print("Running on macOS!")
else:
    print(f"Unknown platform: {current_platform}")
</code></code></pre><p>In Dart you use a class called <code>Platform</code>, but instead of doing string comparisons you have specifically defined boolean values like <code>isLinux</code> or <code>isMacoOs</code>. You also use things like <code>Platform.environment['HOME']</code> to get the home directory whereas in Python you'd do <code>os.path.expanduser("~")</code>. Here is an example in some of my code</p><pre><code><code>  String findConfig() {
    String configDir;
    if (Platform.isLinux) {
      configDir =
          join(Platform.environment['HOME']!, '.local', 'share', 'TerboMine');
    } else if (Platform.isWindows) {
      configDir = join(Platform.environment['UserProfile']!, 'AppData', 'Local',
          'TerboMine');
    } else if (Platform.isMacOS) {
      configDir = join(Platform.environment['HOME']!, 'Library',
          'Application Support', 'TerboMine');
    } else {
      throw UnsupportedError('Unsupported platform');
    }
    return configDir;
  }

</code></code></pre><p>You work with objects a lot instead of raw strings, which leads to chaining code that looks like this</p><pre><code><code>import 'dart:io';

void main() {
  final directory = Directory('/usr/Me/Documents');

  final textFiles = directory.listSync()
      .whereType&lt;File&gt;()
      .where((file) =&gt; file.path.endsWith('.txt'))
      .toList();

  print(textFiles);
}
</code></code></pre><p>This makes the language feel like Ruby, Crystal, or even Pharo, which I like because I like those languages, but I understand that is subjective.</p><p>One draw back of being OOP means that there are a lot of different modifiers you can add to a classes which change the behavior, and it can get very confusing when a class has many keywords associated with it. This leads me to my next point</p><h3>There are a lot of keywords</h3><p>This unfortunately comes with the territory of most statically typed programming languages, but when classes support</p><ul><li><p>abstract</p></li><li><p>base</p></li><li><p>final</p></li><li><p>interface</p></li><li><p>mixin</p></li><li><p>sealed</p></li></ul><p>and variables can be <code>const</code>, <code>late</code>, or <code>final</code>, I find myself <code>type masturbating</code> as I try to craft the perfect type hierarchies. It also clutters the code visually, and I end of making liberal use of <code>var</code>. In total their are 61 plus or minus a few keywords listed in the <a href="https://dart.dev/language/keywords">Dart reference</a>. As a library author, this is great, and as a consumer of a library the intellisense I get is very informative. But that is double what Python, JavaScript, and Go have, which can be a little overwhelming.</p><p>I feel like Dart knows this is an issue, because they try to limit the noise where they can, like how private variables identified by being prefixed with a <code>_</code>. It also supports the <code>typedef</code> keyword allowing you to alias types for when they get too long</p><pre><code><code>typedef IntList = List&lt;int&gt;;
IntList il = [1, 2, 3];
</code></code></pre><h3>Dart Supports Metadata</h3><p>Dart supports metadata, which are like Python decorators</p><pre><code><code>class Television {
  /// Use [turnOn] to turn the power on instead.
  @Deprecated('Use turnOn instead')
  void activate() {
    turnOn();
  }

  /// Turns the TV's power on.
  void turnOn() {...}
  // &#183;&#183;&#183;
}
</code></code></pre><p>One thing I found cool is that you can use this to specify little TODO annotations like in this example</p><pre><code><code>class Todo {
  final String who;
  final String what;

  const Todo(this.who, this.what);
}

@Todo('Dash', 'Implement this function')
void doSomething() {
  print('Do something');
}
</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bPFi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bPFi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bPFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg" width="569" height="438" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:438,&quot;width&quot;:569,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Marge meme holding a potato calling Metadata neat&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Marge meme holding a potato calling Metadata neat" title="Marge meme holding a potato calling Metadata neat" srcset="https://substackcdn.com/image/fetch/$s_!bPFi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bPFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9112f3e-9fef-4217-99fa-c489f55d4375_569x438.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>It's very asynchronous</h3><p>I'm not used to programming in languages like JavaScript so this was a relatively new concept for me. Dart supports <code>Async Await</code>, so you'll see methods that are explicitly blocking having <code>Sync</code> in the name like</p><pre><code><code>final fileDate = file.lastModifiedSync().toIso8601String();
</code></code></pre><p>Or you'll write a function and all of a sudden you are returning a List wrapped in a future <code>Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt;</code> as in this code</p><pre><code><code>  // Search documents in the database using raw SQL
  Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt; searchDocuments(String query) async {
    if (query.isEmpty) {
      // Return an empty list if the query is empty
      return [];
    }

    final db = await instance.database;
    final escapedQuery = _escapeSpecialCharacters(query);
    return await db.rawQuery('''
      SELECT rowid, name, location FROM $tableDocuments WHERE $tableDocuments MATCH ?
    ''', [escapedQuery]);
  }
</code></code></pre><p>but that beats having to litter the code with <code>then</code> everywhere so I'll take it</p><pre><code><code>instance.database.then((db) {
    final escapedQuery = _escapeSpecialCharacters(query);
    db.rawQuery('''
      SELECT rowid, name, location FROM $tableDocuments WHERE $tableDocuments MATCH ?
    ''', [escapedQuery]).then((results) {
      callback(results);
    }).catchError((error) {
      // Handle errors here
      print(error);
    });
  });
</code></code></pre><p>Since Flutter is Dart's killer app, it makes sense that this type of code pops up everywhere as asynchronous code allows you to create non blocking functions that would otherwise slow down your app if they were synchronous. I believe this is one of the reasons Dart bills itself as a <code>client optimized</code> programming language, a term I've only ever heard used in the context of Dart.</p><h3>The tooling is excellent</h3><p>Dart allows you to try before you buy with <a href="https://dartpad.dev/">Dartpad.dev</a>. There is even sample flutter code so you can see what a simple Flutter app looks like in the browser.</p><p>It has extensions for VS Code and Android Studio, as well as an Emacs Major mode, so editor support is good. The Dart cli comes with a lot of different commands allowing you to generate documentation from docstrings, format the code, run tests etc.</p><pre><code><code>A command-line utility for Dart development.

Usage: Dart &lt;command|Dart-file&gt; [arguments]

Global options:
-v, --verbose               Show additional command output.
    --version               Print the Dart SDK version.
    --enable-analytics      Enable analytics.
    --disable-analytics     Disable analytics.
    --suppress-analytics    Disallow analytics for this `Dart *` run without changing the analytics configuration.
-h, --help                  Print this usage information.

Available commands:
  analyze    Analyze Dart code in a directory.
  compile    Compile Dart to various formats.
  create     Create a new Dart project.
  devtools   Open DevTools (optionally connecting to an existing application).
  doc        Generate API documentation for Dart projects.
  fix        Apply automated fixes to Dart source code.
  format     Idiomatically format Dart source code.
  info       Show diagnostic information about the installed tooling.
  pub        Work with packages.
  run        Run a Dart program.
  test       Run tests for a project.

</code></code></pre><p>Dart also supports creating projects using the <code>create</code> command</p><pre><code><code>Dart create --template console-application my_app
</code></code></pre><p>Which will generate a folder that typically includes...</p><ul><li><p><strong>pubspec.yaml:</strong> Defines your project's dependencies and metadata.</p></li><li><p><strong>pubspec.lock:</strong> Locks the versions of your dependencies.</p></li><li><p><strong>analysis.yaml:</strong> Configuration file to customize the behavior of the static analysis tool.</p></li><li><p><strong>lib/main.Dart:</strong> Main entry point of your application.</p></li><li><p><strong>test/:</strong> Contains test files for your project.</p></li></ul><p>You can generate executables with <code>dart compile</code> and it has a package manager and a website for browsing packages called <a href="https://pub.dev/">pub.dev</a> where I've been able to find pretty much any library I need. This is good because of my next point...</p><h3>The Standard Library is kind of small</h3><p>Because Dart has a large mobile and web focus, It has to be careful about features that could mess with the highly sandboxed nature of Android and IOS. This means the standard library that comes with a vanilla install only covers these core areas</p><pre><code><code>Dart:core
Built-in types, collections, and other core functionality. This library is automatically imported into every Dart program.
Dart:async
Support for asynchronous programming, with classes such as Future and Stream.
Dart:math
Mathematical constants and functions, plus a random number generator.
Dart:convert
Encoders and decoders for converting between different data representations, including JSON and UTF-8.
Dart:io
I/O for programs that can use the Dart VM, including Flutter apps, servers, and command-line scripts.
Dart:html
DOM and other APIs for browser-based apps. We now recommend using package:web over Dart:html.
</code></code></pre><p>To get around this, you'll notice when browsing <code>pub.dev</code> that the Dart Team publishes under three different publishers</p><ul><li><p><strong>Dart.dev</strong> - Core packages. Foundational packages that complement the core libraries.</p></li><li><p><strong>tools.Dart.dev</strong> - Tooling packages. Used by the Dart team to build various Dart tools. Can be used for building other tools, but the support commitment is lower than for core packages.</p></li><li><p><strong>labs.Dart.dev</strong> - Experimental packages. Shared for early feedback. Some will likely be discontinued.</p></li></ul><p>Many of the additional packages I needed where available from the <code>Dart.dev</code>, and the <code>tools.Dart.dev</code> publishers. But it seemed a little silly that I had to download the <a href="https://pub.dev/packages/yaml">yaml package</a> which is maintained by <code>tools.Dart.dev</code>, considering that every Dart project includes a yaml file. On the other hand, a smaller standard library meanings easier porting to different platforms, and smaller programs overall, so it is a trade off.</p><p>One challenge with Dart running on so many platforms is that you have to be careful with using certain features in the standard library or the ecosystem at large. For example... In the <a href="https://github.com/dart-lang/sdk/blob/main/sdk/lib/io/io.dart">dart io library</a> you'll see the message</p><pre><code><code>/// **Important:** Browser-based apps can't use this library.
/// Only the following can import and use the dart:io library:
///   - Servers
///   - Command-line scripts
///   - Flutter mobile apps
///   - Flutter desktop apps
</code></code></pre><p>There are also certain libraries on <code>pub.dev</code> which don't work with Flutter, Dart's killer app, and these tend to be less popular.</p><h3>Dart code is very Tall</h3><p>Dart compared to other languages I've used, loves its vertical space. It <em>loves</em> its trailing commas (I've become pro trailing comma), and will line break on every one, which leads to code like this in one of my apps</p><pre><code><code>        "validExtensions": [
          ".txt",
          ".md",
          ".rst",
          ".yaml",
          ".yml",
          ".json",
          ".xml",
          ".csv",
          ".tsv",
          ".c",
          ".cpp",
          ".h",
          ".hpp",
          ".java",
          ".class",
          ".py",
          ...]
</code></code></pre><p>This is definitely influenced by Flutter, which has a declarative nested syntax, but I don't consider that a bad thing, because the language is 'client optimzied' and the minute you start highlighting widgets and using the <code>Wrap with padding</code>, <code>Extract Widget</code>, <code>Extract Method</code> etc, you start seeing and editing code as structured chunks which is hard to explain if you've never experienced it.</p><h3>Concurrency in Dart</h3><p>Dart provides robust support for concurrent programming using <code>Async Await </code>patterns, and Isolates. Isolates allow you to create independent units of execution that can run concurrently on multi core processors. This enables efficient handling of computationally intensive tasks without blocking the UI thread.</p><pre><code><code>Isolate Isolate = await Isolate.spawn(heavyComputation, data);
Isolate.receivePort.listen((message) {
  // Process the result from the Isolate
});
</code></code></pre><p>Isolates offer several advantages over traditional thread-based parallelism including...</p><ul><li><p><strong>Memory Safety:</strong> Isolates have their own memory space, preventing them from interfering with each other. This eliminates the risk of data races and other concurrency related bugs that are common in thread based systems.</p></li><li><p><strong>Simplified Concurrency:</strong> Dart's Isolate model simplifies concurrent programming by providing a more intuitive and less error prone approach. You can spawn Isolates to handle independent tasks while enjoying a higher level of abstraction.</p></li><li><p><strong>Efficient Resource Utilization:</strong> Isolates can be efficiently scheduled on multiple cores, allowing you to take full advantage of modern hardware.</p></li><li><p><strong>Graceful Error Handling:</strong> If an Isolate crashes, it won't affect the rest of your application. This makes your application more resilient to errors and failures.</p></li></ul><p>Isolates are no silver bullet though as they do come with some downsides. There is overhead that comes with spawning Isolates, so you have to weigh the startup cost of spawning an Isolate vs just letting the task complete synchronously. There is also overhead when passing messages in Isolates when compared to direct memory access in traditional threads, whichs makes them less efficient. Finally, Isolates can cause weird behavior in some libraries on certain platforms, like when trying to use the <a href="https://www.reddit.com/r/Dartlang/comments/1dmlveo/how_to_not_use_raylib_with_Dart_on_macos/">popular graphics framework Raylib on macos</a></p><p>Still, Isolates are a good solution when you still want to have parallelism but want to avoid some of the pitfalls associated with it. Given Dart's focus on frontend development, incurring the performance hit for safer parallelism seems like a good tradeoff. And the fact that Isolates make it easier than traditional threading make people more inclined to actually parallelism where they can.</p><h3>Dart Does Tree Shaking but there is an asterisk</h3><p>Tree shaking, AKA Dead code elimination, results in smaller code sizes due to only including code in your app that you actually use. This is an awesome feature, and not one that is common in programming languages. Unfortunately this is also under documented in Dart, and it is unclear what is and isn't tree shakeable. This has been raised in this <a href="https://github.com/Dart-lang/sdk/issues/33920">Github Issue</a>, but there has been no resolution to it yet.</p><h3>It has a large Medium community</h3><p>This is a interesting one. There are a lot of Dart articles on Medium. I think this is because both Dart and Flutter announcements are syndicated to Medium like the <a href="https://medium.com/Dartlang/Dart-3-5-6ca36259fa2f">annoucent of Dart version 3.5</a> and have been for a long time.</p><h3>There are a lot of Materials about Flutter</h3><p>Dart can be used for both backend and frontend development, but Flutter is king. This does come with a huge benefit though, pretty much everyone in the Dart community knows Flutter, and the amount high quality tutorials teaching it are numerous compared to the size of its community</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vK4B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vK4B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vK4B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg" width="800" height="638" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:638,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;YouTube search showing multiple hour plus long dart courses&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="YouTube search showing multiple hour plus long dart courses" title="YouTube search showing multiple hour plus long dart courses" srcset="https://substackcdn.com/image/fetch/$s_!vK4B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vK4B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac81cf1b-3d7b-4b38-ac52-b00c5ae4a1ae_800x638.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is very different from the Python world where I live that has many people using different subsets of the language. For instance Data Scientists use Pandas, NumPy and Matplotlib, ML People use TensorFlow, Scikit-learn, and Keras, and web developers using use Django or Flask. The drawback to this is that if you aren't doing anything Flutter based you are kind of on your own, but I believe with libraries like <a href="https://github.com/schultek/jaspr">Jaspr</a>, <a href="https://github.com/VeryGoodOpenSource/Dart_frog">Dart Frog</a>, <a href="https://github.com/gyrdym/ml_algo">ml_algo</a>, and many others on <a href="https://github.com/yissachar/awesome-Dart">awesome-Dart</a> that is changing.</p><h3>It's pretty fast</h3><p>1 billion loop challenge</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lFua!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lFua!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 424w, https://substackcdn.com/image/fetch/$s_!lFua!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 848w, https://substackcdn.com/image/fetch/$s_!lFua!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 1272w, https://substackcdn.com/image/fetch/$s_!lFua!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lFua!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png" width="800" height="974" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:974,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;billion loop challenge showing Dart beating out every other garbage collected language&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="billion loop challenge showing Dart beating out every other garbage collected language" title="billion loop challenge showing Dart beating out every other garbage collected language" srcset="https://substackcdn.com/image/fetch/$s_!lFua!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 424w, https://substackcdn.com/image/fetch/$s_!lFua!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 848w, https://substackcdn.com/image/fetch/$s_!lFua!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 1272w, https://substackcdn.com/image/fetch/$s_!lFua!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53d8b1b2-a738-420b-884b-f7e99fb4bb3f_800x974.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Benchmark Games</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bYMU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bYMU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 424w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 848w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 1272w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bYMU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png" width="800" height="934" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:934,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Benchmark Games geometric mean graph showing Dart compared to other languages&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Benchmark Games geometric mean graph showing Dart compared to other languages" title="Benchmark Games geometric mean graph showing Dart compared to other languages" srcset="https://substackcdn.com/image/fetch/$s_!bYMU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 424w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 848w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 1272w, https://substackcdn.com/image/fetch/$s_!bYMU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf6bfae1-af31-4dd4-8fc9-bcfa8e256483_800x934.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Micro benchmarks aren't entirely representative of a programming language&#8217;s performance. But people love them as seen by Twitter&#8217;s viral billion loop challenge, and the success of the billion row challenge last year.</p><p>With that being said Dart is fast for a garbage collected language. When your virtual machine was created by the same guy who made the V8 JavaScript engine (Lars bak), and the language was designed to be easier to optimize than JavaScript, you end up with a language that is pretty quick.</p><h3>It has a cool Mascot (Objective)</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0BeZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0BeZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 424w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 848w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 1272w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0BeZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png" width="478" height="475" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:475,&quot;width&quot;:478,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:255328,&quot;alt&quot;:&quot;plushy of the dart mascot dash&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="plushy of the dart mascot dash" title="plushy of the dart mascot dash" srcset="https://substackcdn.com/image/fetch/$s_!0BeZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 424w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 848w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 1272w, https://substackcdn.com/image/fetch/$s_!0BeZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0d3532-2f0d-40f1-912e-4babf4336aec_478x475.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As is tradition, Dart has an animal mascot and her name is Dash. She is a Hummingbird and there is a <a href="https://dashatar-dev.web.app/#/">website</a> dedicated to creating your own version of a Dashatar.</p><h3>TLDR/Conclusion</h3><p>Dart is an interesting language that is in a spot most programming languages would kill to be in. It has corporate investment and a team of people who are paid to develop it. It has a killer app through Flutter that has large total addressable market (anywhere a GUI can run).</p><p>It is cross platform across all 3 major desktops, including mobile which many programming languages struggle to target. It is capable of compiling an exe with <code>dart compile exe bin/main.dart</code>, and compiling to the browser with Wasm and JavaScript. And its foundation is built on cutting edge programming language theory. Yet it has been overlooked compared to other languages that have come out in a similar time frame namely TypeScript (2012), Kotlin (2011), Go (2009), Rust (2010), and Swift (2014).</p><p>While the language is not perfect, I hope you might consider given the language a shot in the future (maybe in this years advent of code?), and I will continue to use it in my personal projects going forward. If you are interested in more Dart content, I have a Flutter article coming soon, where I will speak to my experience learning and using it. Stay tuned!</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a>, <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, and <a href="https://www.threads.net/@deusinmachinablog">Threads</a> if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/the-dart-programming-language-is?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/the-dart-programming-language-is?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;66e72dc1-e9c4-400b-92b1-297b1e534abb&quot;,&quot;caption&quot;:&quot;I recently decided to give my Emacs configuration a makeover. Over time, startup had become sluggish, and I wanted to try out the new tree-sitter modes. Setting these up involves compiling tree-sitter grammars, which is easy enough on Linux. By following the excellent article,&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Zig Saves the Day for cross platform tree-sitter compilation &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25d2568c-107b-4954-aeb7-eb43776e15ae_854x854.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-04-11T12:12:26.865Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:143469961,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[The Story of Nel]]></title><description><![CDATA[Happy &#129411; Day!]]></description><link>https://www.deusinmachina.net/p/the-story-of-nel</link><guid isPermaLink="false">https://www.deusinmachina.net/p/the-story-of-nel</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Fri, 29 Nov 2024 03:17:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ackF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>Happy &#129411; Day! I hope everyone has a wonderful day</p></div><p>Real Programmers code in the terminal.</p><p>Maybe they dabble in slick IDEs now, in this decadent era of AI assistants, auto completion, and "intelligent" debuggers. But back in the good old days, when the term "cloud" referred to the weather and not where you stored your code, Real Programmers wrote in plain text editors. Not Visual Studio Code. Not even Helix or Fleet. Just GNU Emacs and Screen.</p><p>Lest a whole new generation of developers grow up in ignorance of this glorious past, I feel duty bound to describe, as best I can through the generation gap, how a Real Programmer writes code. I'll call her Nel, because that's her name.</p><p>I first met Nel when I joined a startup aiming to disrupt the world with yet another social app. The team was young, vibrant, and glued to their screens, eyes darting between Stack Overflow tabs and AI generated code snippets. Then there was Nel, a quiet figure hunched over a terminal window, typing furiously.</p><p>Nel didn't approve of AI assistants.</p><p>"If a programmer can't write code without an autocomplete," she said, "what good are they?"</p><p>Nel had written, using nothing but Emacs and her wits, the most critical module our company had. The real time data processor that kept everything running smoothly. It was a marvel. While the rest of us wrestled with dependency hell and cursed the day JavaScript was invented, Nel's code hummed along with these things called static types that, she said, were all the documentation she needed.</p><p>One day, disaster struck. An outage in us-east-1 left us disconnected from our beloved cloud services. Panic ensued. Without Stack Overflow, AI help, or even our code repositories, we were paralyzed. Features needed fixing, bugs needed squashing, and deadlines loomed ominously.</p><p>All except Nel were in despair.</p><p>"How can we code without the internet?" someone wailed.</p><p>"I've reached my 2-hour monthly in office quota anyway. Message me on Microsoft Teams when everything is back up," said another.</p><p>Nel looked up from her terminal, a faint smile playing on her lips.</p><p>"Maybe we can, you know, stay here and write code," she suggested.</p><p>"Without documentation? Without Google? Impossible!"</p><p>Nel shrugged and returned to her screen. Curiosity got the better of me, and I wandered over to see what she was doing. Lines of code scrolled past at an impossible speed. Functions, classes, even the occasional comment, all appearing as if by magic. She wasn't even using a mouse or trackpad.</p><p>"Are you... writing a new feature?" I asked, incredulous.</p><p>"Fixing the data parser," she replied without looking up.</p><p>"From memory?"</p><p>She nodded.</p><p>"But how do you remember the syntax? The APIs? Don't you need to look up anything?"</p><p>Nel chuckled softly. "I've been coding in this language longer than most of you have been alive. Muscle memory, I suppose."</p><p>I watched in awe as she deftly wrote a for loop, complete with iterator variables and proper scope handling, all without a single reference. It was as if I'd witnessed a unicorn.</p><p>"Could you help me with a for loop?" I asked sheepishly.</p><p>She paused and turned to face me fully for the first time.</p><p>"Sure," she said, gesturing for me to sit. "What are you trying to do?"</p><p>I explained the problem, expecting her to whip out her phone to search for an answer. Instead, she grabbed a notepad and sketched out the logic, walking me through each step.</p><p>"See? No need for the internet. Just think through the problem," she said.</p><p>She laughed as I gawked.</p><p>"I used to have to do stuff like this on whiteboards for interviews," She smiled while shaking her head.</p><p>Word spread through the office. One by one, team members approached Nel, seeking guidance. She became an impromptu mentor, her desk a shrine to the lost art of independent thinking.</p><p>Meanwhile, the managers were in a frenzy. Deadlines were at risk! Productivity was plummeting! They called an emergency all hands.</p><p>"We need solutions, people!" the CTO barked. "How can we work without our tools?"</p><p>Nel stood up.</p><p>"Perhaps we've become too reliant on them," she said calmly. "Maybe it's time we trusted our own abilities."</p><p>Silence fell. The idea was radical, almost heretical.</p><p>"But how will we manage without AI suggestions? Without code linters? Without..."</p><p>"By programming," Nel reiterated, "by understanding our code, not just piecing together fragments from the internet."</p><p>An idea sparked in Nel. "We could deploy the app on premises", "Mark has a 64-core 7.5GHz laptop with 256GB of Ram and two 10TB NVME drives. If we turned off all of the startup and electron apps we'd be able to run the entire thing locally."</p><p>Eyes turned to Mark, who nodded slowly. "It just might be possible. We have as many employees here as we have users so it would be a good test of the app"</p><p>The CTO considered this. "Can we set it up quickly?"</p><p>"Absolutely," Nel interjected. "It might even run better than in the cloud."</p><p>Emboldened, we set up the on premise deployment. With Nel's guidance, the process was smooth. We bypassed the cloud entirely, running everything locally.</p><p>Her words stirred something in us. Emboldened, we returned to our desks. The hum of conversation was replaced by the clatter of keyboards. Slowly, code began to take shape...not copied, not generated, but crafted. Whenever we had issues, we would physically walk over and discuss them with our teammates. Questions that would be left unread for hours before a response was finally given, were answered in a matter of seconds.</p><p>By the time the internet was restored, it had been 6 hours, the most I've ever worked without distractedly scrolling through short form video. We had accomplished more in those disconnected hours than we had in months.</p><p>The CTO called another all hands, praising the team's resilience. They gushed about how much VC money we would be able to raise from all the featuers we had developed. But we knew who deserved the real credit.</p><p>Nel's approach had sparked a revival of genius level programming. Developers started challenging themselves to code without immediately resorting to Google. Pair programming sessions became the norm, fostering collaboration and learning. People even began reading manuals. Not everyone could hack it though, but they eventually found their way into middle management positions.</p><p>I asked Nel one day why she preferred Emacs over the myriad of sophisticated tools available.</p><p>"Because it does exactly what I need...no more, no less," she replied. "It's just me and the code."</p><p>I haven't kept in touch with Nel since she moved on to greener pastures...or perhaps terminals. But I like to think she's out there somewhere, still coding in Emacs, still eschewing the trappings of modern development.</p><p>In any event, I was impressed enough that I've started relying less on AI assistants and more on my own understanding. And while I may never reach Nel's level of mastery, I still use VS Code after all, I did download the Vim Emulation plugin. I think I might do a lunch and learn once I finally master hjkl.</p><div class="pullquote"><p>For those who don&#8217;t know this is a parody of <a href="https://users.cs.utah.edu/~elb/folklore/mel.html">The brilliant Story of Mel</a> if you&#8217;ve never read it I highly recommend it!</p></div><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>,&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;and <a href="https://www.threads.net/@deusinmachinablog">Threads</a> if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/the-story-of-nel?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/the-story-of-nel?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;793a6be9-fdd5-4228-bd1d-9b7c2f5a130b&quot;,&quot;caption&quot;:&quot;The word of the day is religionization. According to the Merriam-Webster dictionary it means&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Geek Mythology: The Religious, and Spiritual Folklore surrounding Programming&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25d2568c-107b-4954-aeb7-eb43776e15ae_854x854.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-01-26T13:01:06.513Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F514a231e-60c4-4ba4-8df6-d4c9478c265f_321x445.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/geek-mythology-the-religious-and&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:95123922,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:4,&quot;comment_count&quot;:2,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffef72695-8694-4853-8b6a-f4cf032c56b3_854x854.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Coding without braces: An alternate C Syntax]]></title><description><![CDATA[I recently stumbled upon an interesting piece of C language trivia that underscores how different computers were when C was first created.]]></description><link>https://www.deusinmachina.net/p/coding-without-braces-an-alternate</link><guid isPermaLink="false">https://www.deusinmachina.net/p/coding-without-braces-an-alternate</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 10 Oct 2024 12:02:53 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="6048" height="4032" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:4032,&quot;width&quot;:6048,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;vintage gray game console and joystick&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="vintage gray game console and joystick" title="vintage gray game console and joystick" srcset="https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1550745165-9bc0b252726f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxMnx8cmV0cm8lMjBjb21wdXRpbmd8ZW58MHx8fHwxNzI4NDQyMTgyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">Lorenzo Herrera</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><p>I recently stumbled upon an interesting piece of C language trivia that underscores how different computers were when C was first created. Specifically, C allows the use of digraphs (two letter combinations that represent a single letter) like <code>&lt;%</code> and <code>%&gt;</code> as alternatives of <code>{</code> and <code>}</code> and <code>&lt;:</code> and <code>:&gt;</code> as substitutes for <code>[</code> and <code>]</code>. The purpose of this was to provide an alternate syntax to support keyboards and character sets where braces and brackets were not available. The <a href="https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Digraphs.html">Gnu C Language manual</a> mentions these digraphs as well as <code>%:</code> as an alternative to <code>#</code>. Since nothing on the internet can be trusted anymore I wrote a simple program and compiled it to verify the claims.</p><pre><code><code>#include &lt;stdio.h&gt;

int main() &lt;%
    printf("Hello, World!\n");
    int array&lt;:5:&gt; = &lt;%1, 2, 3, 4, 5%&gt;; 
    for (int i = 0; i &lt; 5; i++) &lt;%
        printf("%d\n", array&lt;:i:&gt;); 
    %&gt;
    return 0;
%&gt;
</code></code></pre><p>And lo and behold (don't take my word for it) it worked! While it's hard to imagine a keyboard without these symbols today, and I might be showing my ignorance of international keyboards here, I'm glad someone thought to include these alternatives.</p><p>But if the <a href="https://en.cppreference.com/w/c/language/operator_alternative">cpp reference</a> is anything to go by there is is an expecation that all keyboards must have <code>?</code>,<code>&lt;</code> and <code>)</code> as there is an even more verbose version of this behavior in the form of trigraphs, which allow a three character sequence alternative instead of two. Examples include <code>??&lt;</code> for <code>{</code> and <code>??)</code> for <code>]</code> but there are many more which can be viewed <a href="https://en.cppreference.com/w/c/language/operator_alternative#:~:text=Demonstrates%20alternative%20operator">in the cpp reference</a>. While tripgrahs appear to be going away in C23, I have no doubt people have abused these as well as digraphs in code obfuscation competitions.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>,&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;and <a href="https://www.threads.net/@deusinmachinablog">Threads</a> if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/coding-without-braces-an-alternate?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/coding-without-braces-an-alternate?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;7d584369-3821-4fbb-9a1d-88615960d415&quot;,&quot;caption&quot;:&quot;2024 will by my 8th year as a programmer, and one area where I don&#8217;t have much experience in, is the low level systems programming. To rectify this, I&#8217;ve been writing some C programs. One day, while I was compiling a small C program, I realized I didn&#8217;t really know what was going on when I entered these commands&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Understanding the Compilation Process in C: A Step by Step Guide&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-01-11T13:01:47.763Z&quot;,&quot;cover_image&quot;:&quot;https://images.unsplash.com/photo-1589939705384-5185137a7f0f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxjb25zdHJ1Y3Rpb258ZW58MHx8fHwxNzA0NjYxNzY2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/understanding-the-compilation-process&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:140386952,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:2,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Changes to My Blogging Schedule: A Focus Shift]]></title><description><![CDATA[Dear Readers,]]></description><link>https://www.deusinmachina.net/p/changes-to-my-blogging-schedule-a</link><guid isPermaLink="false">https://www.deusinmachina.net/p/changes-to-my-blogging-schedule-a</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 25 Apr 2024 12:02:08 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="3486" height="3486" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3486,&quot;width&quot;:3486,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;curve road signage&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="curve road signage" title="curve road signage" srcset="https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1517255666489-db1d2c54d083?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyNHx8Y2hhbmdlfGVufDB8fHx8MTcxNDAwNTE4NHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="true">Fabien Bazanegue</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><p>Dear Readers,</p><p>I'm writing to share an important update about my Substack journey. For the past 17 months I&#8217;ve set out with a goal to deliver an article a week. I&#8217;m happy to say that I&#8217;ve never missed a week in over 75 articles. It's been an incredible learning experience, and your support and engagement have motivated me every step of the way.</p><p>However, life is all about adapting to new opportunities, and exciting changes at my job necessitate a shift in focus. Due to my knowledge of AI and LLMs (In no small part to the articles I&#8217;ve written on it here) I&#8217;ve been selected to work on a project implemeting large language models at a Fortune 500 company. I want to give this opportunity my full attention, so I need to make some adjustments to my schedule.</p><p><strong>What This Means for the Blog</strong></p><p>I won't be able to maintain my weekly posting schedule moving forward. I realize this may be disappointing, but I want to assure you this isn't goodbye. I'll still be publishing content, but on a less frequent basis.</p><p>My goal is to continue sharing my knowledge and experiences in the tech field and I hope that the experience I will gain with this project, will translate into new articles I can share with all of you. </p><p><strong>Thank you!</strong></p><p>Your readership has played a significant role in my personal and professional growth. I genuinely appreciate the comments, questions, and overall enthusiasm you've brought to this space. </p><p>I'm excited about the contributions I can make in the LLM space, and I hope you'll continue to follow my journey. With that I&#8217;ll be signing for this week. Thank you all for your support, it means a lot to me. </p><p>With gratitude,</p><p>Diego Enrique Crespo</p>]]></content:encoded></item><item><title><![CDATA[Tree-sitter: Revolutionizing Parsing with an Incremental Parsing Library]]></title><description><![CDATA[Programmers love to add the word &#8220;tree&#8221; to everything with concepts like binary trees, red-black trees, trie, tree-shaking, and now, Tree-sitter. While 'Tree-sitter' might sound whimsical, it represents a significant innovation in parsing, the fundamental task in understanding and processing code. Traditional parsing methods often face limitations in flexibility and efficiency, but Tree-sitter seeks to improve on this and more, while also doing this in real time with every key stroke. This is an ambitious goal and requires solving many difficult problems.]]></description><link>https://www.deusinmachina.net/p/tree-sitter-revolutionizing-parsing</link><guid isPermaLink="false">https://www.deusinmachina.net/p/tree-sitter-revolutionizing-parsing</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 18 Apr 2024 12:06:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!R23R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R23R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R23R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 424w, https://substackcdn.com/image/fetch/$s_!R23R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 848w, https://substackcdn.com/image/fetch/$s_!R23R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!R23R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R23R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg" width="800" height="1066" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1066,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:433803,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!R23R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 424w, https://substackcdn.com/image/fetch/$s_!R23R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 848w, https://substackcdn.com/image/fetch/$s_!R23R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!R23R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd93ebc-5792-4378-9a62-5a1eaede3705_800x1066.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">No&#8230; Not that Tree Sitter..</figcaption></figure></div><p>Programmers love to add the word&nbsp;&#8220;tree&#8221;&nbsp;to everything with concepts like binary trees,&nbsp;red-black trees,&nbsp;trie,&nbsp;tree-shaking,&nbsp;and now,&nbsp;Tree-sitter.&nbsp;While&nbsp;'Tree-sitter'&nbsp;might sound whimsical,&nbsp;it represents a significant innovation in parsing,&nbsp;the fundamental task in understanding and processing code.&nbsp;Traditional parsing methods often face limitations in flexibility and efficiency,&nbsp;but Tree-sitter seeks to improve on this and more,&nbsp;while also doing this in real time with every key stroke.&nbsp;This is an ambitious goal and requires solving many difficult problems.</p><h2><strong>The Fundamentals of Parsing</strong></h2><p>To understand the significance of Tree-sitter,&nbsp;it is essential to understand the basics of parsing.&nbsp;Parsing involves analyzing a sequence of tokens to determine its syntactic structure,&nbsp;often represented by a parse tree or an abstract syntax tree&nbsp;(AST).&nbsp;Traditional parsing methods,&nbsp;such as hand-written parsers or parser generators like Bison or ANTLR,&nbsp;have long been the standard tools for this task.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!C2TK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C2TK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 424w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 848w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 1272w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C2TK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png" width="1456" height="870" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:870,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:155885,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!C2TK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 424w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 848w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 1272w, https://substackcdn.com/image/fetch/$s_!C2TK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29abb9bd-a6f2-4800-8fc6-cdf5a34a3b7e_1601x957.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>They work by using a grammar file often written in a version of&nbsp;<a href="https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form">Extended Backus-Naur Form</a>.&nbsp;For many languages this is challenging due to the many quirks and edge cases.&nbsp;Here is a sample of some C grammar.</p><pre><code>grammar C;


primaryExpression
    :   Identifier
    |   Constant
    |   StringLiteral+
    |   '(' expression ')'
    |   genericSelection
    |   '__extension__'? '(' compoundStatement ')' // Blocks (GCC extension)
    |   '__builtin_va_arg' '(' unaryExpression ',' typeName ')'
    |   '__builtin_offsetof' '(' typeName ',' unaryExpression ')'
    ;

genericSelection
    :   '_Generic' '(' assignmentExpression ',' genericAssocList ')'
    ;

genericAssocList
    :   genericAssociation (',' genericAssociation)*
    ;

genericAssociation
    :   (typeName | 'default') ':' assignmentExpression
    ;

postfixExpression
    :
    (   primaryExpression
    |   '__extension__'? '(' typeName ')' '{' initializerList ','? '}'
    )
    ('[' expression ']'
    | '(' argumentExpressionList? ')'
    | ('.' | '-&gt;') Identifier
    | '++'
    | '--'
    )*
    ;

argumentExpressionList
    :   assignmentExpression (',' assignmentExpression)*
    ;

unaryExpression
    :
    ('++' |  '--' |  'sizeof')*
    (postfixExpression
    |   unaryOperator castExpression
    |   ('sizeof' | '_Alignof') '(' typeName ')'
    |   '&amp;&amp;' Identifier // GCC extension address of label
    )
    ;

unaryOperator
    :   '&amp;' | '*' | '+' | '-' | '~' | '!'
    ;

castExpression
    :   '__extension__'? '(' typeName ')' castExpression
    |   unaryExpression
    |   DigitSequence // for
    ;
</code></pre><p>For other languages like Schemes or Common Lisp,&nbsp;the grammar is much simpler due to how the languages&#8217;&nbsp;syntax is constructed.&nbsp;Pharo,&nbsp;a Smalltalk,&nbsp;even boasts about how simple it is to parse,&nbsp;highlighting their LL(1)&nbsp;grammar,&nbsp;which only needs one symbol of look ahead.&nbsp;This is why Pharo's syntax fits on a postcard.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vTGw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vTGw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 424w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 848w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 1272w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vTGw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png" width="1447" height="567" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:567,&quot;width&quot;:1447,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112765,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vTGw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 424w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 848w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 1272w, https://substackcdn.com/image/fetch/$s_!vTGw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa5e6976-4dbe-43d3-8848-2d4fe7b0da70_1447x567.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But since most programming languages are not developed by people with PhDs in Programming Language Theory,&nbsp;they usually accumulate language specific quirks that need to be handled as special cases within a compiler to fully parse the language.&nbsp;Because of this,&nbsp;creating plugins for IDEs that actually understand a programming language on a fundamental level is rare.&nbsp;The ugly truth is that most of the syntax highlighting you see for plugins on your favorite text editor are just a series of regex hacks.&nbsp;And we all know the issue with regexes</p><pre><code>Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.</code></pre><p>Enter Tree-sitter.</p><h2><strong>The Birth of Tree-sitter:</strong></h2><p>Tree-sitter was&nbsp;<a href="https://github.blog/2018-10-31-atoms-new-parsing-system/">announced</a>&nbsp;to the public in a GitHub blog post in 2018.&nbsp;When it was first announced it had support for 11 languages.</p><ol><li><p>Bash</p></li><li><p>C</p></li><li><p>C++</p></li><li><p>ERB</p></li><li><p>EJS</p></li><li><p>Go</p></li><li><p>HTML</p></li><li><p>JavaScript</p></li><li><p>Python</p></li><li><p>Ruby</p></li><li><p>TypeScript</p></li></ol><p>The author of the post,&nbsp;Max Brunsfeld was the creator of Tree-sitter.&nbsp;He developed it out of the need for an incremental parsing solution that was faster than the state of the art at the time.&nbsp;Incremental parsing allows IDEs to parse the file when it is first opened into a syntax tree.&nbsp;Then when edits are made in the file,&nbsp;Tree-sitter can give you a new syntax tree that reflects the edit.&nbsp;This is in contrast to how most IDEs worked pre Tree-sitter.&nbsp;They would reparse the whole file from the beginning to show you the new syntax highlighting.&nbsp;On very large files this contributed to noticeable lags in highlighting.</p><p>In Tree-sitter since the new tree shares the part of the old tree that you didn&#8217;t edit,&nbsp;creating the new syntax tree is fast and does not consume much memory.&nbsp;This makes it possible to parse source code every time a new key is pressed in the editor.&nbsp;But that is only part of the solution.</p><p>If an IDE tries to perform syntax highlighting on every keystroke it will invariably run into the situation where the code is in an incomplete state.&nbsp;This can cause errors when trying to build the syntax tree.&nbsp;But Tree-sitter is able to perform error recovery by determining where the start and end of every error is and give you back a working syntax tree to that point.</p><h2><strong>How it works</strong></h2><p>To use Tree-sitter you need to hope that someone has written a context free grammar for your language,&nbsp;or write it yourself.&nbsp;You do this by creating a&nbsp;<code>grammar.js</code>&nbsp;file.&nbsp;By developing the grammar in a programming language like Javascript it makes it easy to programmatically define grammars,&nbsp;and define grammar in terms of other grammars.&nbsp;An example of this is the C++&nbsp;parser which is defined in terms of the C grammar.&nbsp;This grammar can then be parsed using a&nbsp;"GLR-based"&nbsp;algorithm.&nbsp;This algorithm allows Tree-sitter to handle ambiguous grammars effectively,&nbsp;where multiple parse trees can be generated for a given input and the right one can be picked.</p><p>After the grammar is written,&nbsp;you run a command line tool that spits out a&nbsp;<code>parser.c</code>&nbsp;file.&nbsp;The first part of the&nbsp;<code>parser.c</code>&nbsp;file is a lexer function that tokenizes the characters in a file.&nbsp;The second part is the parse table,&nbsp;which is a large 2 dimensional array that tells the parser what to do in a given state.</p><p>From there you can compile the&nbsp;<code>parser.c</code>&nbsp;and put the compiled library in a place that an editor can find it.&nbsp;See my&nbsp;<a href="https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform">most recent article</a>&nbsp;to see what that looks like.</p><p>While parsing is Tree-sitter's primary focus,&nbsp;it offers a flexible API that allows developers to leverage its capabilities for various use cases beyond parsing.&nbsp;For example,&nbsp;since the code is parsed into a tree,&nbsp;the tree can be navigated and modified using the parse tree.&nbsp;This leads to navigation in files that is&nbsp;"aware"&nbsp;of the language it is in..&nbsp;For example,&nbsp;many editors have the ability to jump to the end of a function from the beginning of a function,&nbsp;by finding the closing curly brace</p><pre><code><code>int find_max(int num1, int num2) {
    if (num1 &gt; num2) {
        return num1;
    } else {
        return num2;
    }
}
</code></code></pre><p>But that same logic fails in a language like Python which uses whitespace for scope.</p><pre><code><code>def find_max(num1, num2):
    if num1 &gt; num2:
        return num1
    else:
        return num2
</code></code></pre><p>With Tree-sitter,&nbsp;when you execute a&nbsp;"move to the end of the function"&nbsp;command,&nbsp;it knows where the end of a function is based on the tree,&nbsp;and does what you expect.&nbsp;This structured navigation and editing makes it easy to do all sorts of things that used to require ugly hacks,&nbsp;or horrific regexes.&nbsp;See&nbsp;<a href="https://github.com/mickeynp/combobulate">Mickey Peterson's Combobulate library</a>&nbsp;for examples of how this works in Emacs.</p><p>Tree-sitter's impact has been undeniable,&nbsp;with adoption in Vscode,&nbsp;Emacs,&nbsp;Neovim,&nbsp;and many other editors.&nbsp;It unlocks structured editing which allows unified movement and behavior between editors based on a parse tree.&nbsp;It advances on what came before,&nbsp;and is one of the few tools that lets you have your cake and eat it to.&nbsp;To top it all off it is open source,&nbsp;allowing everyone to benefit from its incredible achievements.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/tree-sitter-revolutionizing-parsing?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/tree-sitter-revolutionizing-parsing?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;7d584369-3821-4fbb-9a1d-88615960d415&quot;,&quot;caption&quot;:&quot;2024 will by my 8th year as a programmer, and one area where I don&#8217;t have much experience in, is the low level systems programming. To rectify this, I&#8217;ve been writing some C programs. One day, while I was compiling a small C program, I realized I didn&#8217;t really know what was going on when I entered these commands&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Understanding the Compilation Process in C: A Step by Step Guide&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-01-11T13:01:47.763Z&quot;,&quot;cover_image&quot;:&quot;https://images.unsplash.com/photo-1589939705384-5185137a7f0f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw1fHxjb25zdHJ1Y3Rpb258ZW58MHx8fHwxNzA0NjYxNzY2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/understanding-the-compilation-process&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:140386952,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:2,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Zig Saves the Day for cross platform tree-sitter compilation ]]></title><description><![CDATA[I recently decided to give my Emacs configuration a makeover. Over time, startup had become sluggish, and I wanted to try out the new tree-sitter modes. Setting these up involves compiling tree-sitter grammars, which is easy enough on Linux. By following the excellent article,]]></description><link>https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform</link><guid isPermaLink="false">https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 11 Apr 2024 12:12:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!dYhd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dYhd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dYhd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dYhd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png" width="586" height="586" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:586,&quot;bytes&quot;:167612,&quot;alt&quot;:&quot;Zig Lizard mascot&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Zig Lizard mascot" title="Zig Lizard mascot" srcset="https://substackcdn.com/image/fetch/$s_!dYhd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!dYhd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22d5e7b6-c195-425f-b328-b9667727d038_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Zig Mascot</figcaption></figure></div><p>I recently decided to give my Emacs configuration a makeover.&nbsp;Over time,&nbsp;startup had become sluggish,&nbsp;and I wanted to try out the new tree-sitter modes.&nbsp;Setting these up involves compiling tree-sitter grammars,&nbsp;which is easy enough on Linux.&nbsp;By following the excellent article,&nbsp;<a href="https://www.masteringemacs.org/article/how-to-get-started-tree-sitter">How to Get Started with Tree-Sitter</a>&nbsp;by Mickey Peterson I was able to get everything up and running.</p><p>But the problem is,&nbsp;all the guides I found work great for Mac and Linux,&nbsp;but not for Windows so unfortunately this code...</p><pre><code><code>(setq treesit-language-source-alist
   '((bash "https://github.com/tree-sitter/tree-sitter-bash")
     (cmake "https://github.com/uyha/tree-sitter-cmake")
     (css "https://github.com/tree-sitter/tree-sitter-css")
     (elisp "https://github.com/Wilfred/tree-sitter-elisp")
     (go "https://github.com/tree-sitter/tree-sitter-go")
     (html "https://github.com/tree-sitter/tree-sitter-html")
     (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
     (json "https://github.com/tree-sitter/tree-sitter-json")
     (make "https://github.com/alemuller/tree-sitter-make")
     (markdown "https://github.com/ikatyang/tree-sitter-markdown")
     (python "https://github.com/tree-sitter/tree-sitter-python")
     (toml "https://github.com/tree-sitter/tree-sitter-toml")
     (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
     (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
     (yaml "https://github.com/ikatyang/tree-sitter-yaml")))
     
    (mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist)) 
</code></code></pre><p>Which downloads and compiles the grammars flawlessly on my Linux system would not work for me long term.</p><h2><strong>But what is tree sitter?</strong></h2><p>I have an article about this coming soon but in brief...</p><p>Tree-sitter is a parsing library and tool that helps analyze and understand the structure of code.&nbsp;By understanding the structure of the code,&nbsp;it is able to more effectively provide syntax highlighting,&nbsp;code folding,&nbsp;symbol search,&nbsp;and structured editing.&nbsp;It is more flexible,&nbsp;and easier to work with than any other prior solution in the text editor space.&nbsp;We will look at how it does this in more depth next week&nbsp;:)</p><h2><strong>Zig to the Rescue</strong></h2><p>Ideally,&nbsp;I needed a way to automate compiling the grammars,&nbsp;so I could seamlessly transition across all my systems.&nbsp;That meant wrestling with different compilers&nbsp;(GCC,&nbsp;Clang,&nbsp;MSVC)&nbsp;on different operating systems.&nbsp;While doable,&nbsp;it sounded like a major headache,&nbsp;especially with the notoriously finicky MSVC.</p><p>Then I remembered reading about Zig's cross-compilation superpowers.&nbsp;I knew about this from Andrew Kelly's&nbsp;(creator of Zig)&nbsp;article titled...&nbsp;<code>zig cc</code><a href="https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html">: a Powerful Drop-In Replacement for GCC/Clang.</a></p><p>This came in handy when I was writing the&nbsp;<a href="https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi">Experimenting with GUIs on the Pi Zero article</a>.&nbsp;Being able to test examples beforehand by cross compile the C/C++&nbsp;examples on my 8 core 4.3Ghz cpu,&nbsp;before committing to timing them on the Pi Zero's single core 1Ghz processor,&nbsp;sped things up immensely.&nbsp;So with a potential solution in mind,&nbsp;I turned to writing the script.</p><h2><strong>Automating the download PowerShell</strong></h2><p>I whipped up a PowerShell script to automate the process.&nbsp;I've put the core logic below,&nbsp;but don't worry about trying to understand all of it.</p><pre><code><code>$ZigVersion = "0.11.0"

$fileExt = if ($IsWindows) { ".dll" } elseif ($IsLinux) { ".so" } elseif ($IsMacOS) { ".dylib" } else { throw "Unsupported OS" }

# Get the temp directory
$tempDir = Get-TempDirectory

# Determine OS and Architecture
$osArch = if ($IsWindows) { "windows-x86_64" } elseif ($IsMacOS) {
    if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq "Arm64") {
        "macos-aarch64"
    } else {
        "macos-x86_64"
    }
} elseif ($IsLinux) { "linux-x86_64" } else { "unsupported" }

# I.E zig-windows-x86_64-0.11.0
$zigOsArch = "zig-$osArch-$ZigVersion"

# Construct the download URL with the Zig version variable
$downloadZigUrl = switch ($osArch) {
    "windows-x86_64" { "https://ziglang.org/download/$ZigVersion/$zigOsArch.zip" }
    "macos-aarch64" { "https://ziglang.org/download/$ZigVersion/$zigOsArch.tar.xz" }
    "macos-x86_64" { "https://ziglang.org/download/$ZigVersion/$zigOsArch.tar.xz" }
    "linux-x86_64" { "https://ziglang.org/download/$ZigVersion/$zigOsArch.tar.xz" }
    Default { throw "Unsupported platform: $osArch" }
}

# Check if Zig directory already exists and -ReinstallZig is not used
if ((Test-Path -Path "./$zigOsArch") -and (-not $ReinstallZig)) {
    Write-Host "$zigOsArch already downloaded. Skipping install. Pass -ReinstallZig to redownload."
}
elseif ($ReinstallZig -And (Test-Path -Path "./$zigOsArch")) {

    Write-Host "Removing old Zig version $zigOsArch"
    Remove-Item -Path "./$zigOsArch" -Recurse -Force
    # Get the temp directory
    $tempDir = Get-TempDirectory

    # Download and extract the file
    Download-And-Extract-Zig -url $downloadZigUrl -tempDir $tempDir
    Write-Host "Platform specific Zig has been redownloaded and extracted to: $PSScriptRoot"
}
else {

# Download and extract the file
Download-And-Extract-Zig -url $downloadZigUrl -tempDir $tempDir

Write-Host "Zig has been downloaded and extracted to: $PSScriptRoot"
}
</code></code></pre><p>I picked Zig version&nbsp;<code>0.11.0</code>&nbsp;because master is being actively worked on so the urls are changing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2SVX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2SVX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 424w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 848w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 1272w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2SVX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png" width="1456" height="1108" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1108,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:310029,&quot;alt&quot;:&quot;zig table with download links to various versions of zig for different architectures&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="zig table with download links to various versions of zig for different architectures" title="zig table with download links to various versions of zig for different architectures" srcset="https://substackcdn.com/image/fetch/$s_!2SVX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 424w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 848w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 1272w, https://substackcdn.com/image/fetch/$s_!2SVX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c60b6ff-584d-4cd1-a646-b56bda441cd3_1602x1219.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It gets the operating system the script is running on which determines the name of the architecture,&nbsp;and the extension for the shared library.</p><p>It then interpolates the string to construct the appropriate url,&nbsp;and download the appropriate Zig compiler using that url.&nbsp;I download it to the platform specific&nbsp;<code>temp</code>&nbsp;folder,&nbsp;then extract the folder to my&nbsp;<code>.emacs.d</code>.&nbsp;The Zig executable is pre-compiled,&nbsp;so once I have the folder unzipped it's ready to go</p><h2><strong>Downloading and Compiling the Grammars.</strong></h2><p>After I've downloaded the Zig folder it's time for the second part of the script,&nbsp;downloading the tree-sitter grammars.&nbsp;I have all the grammars saved in an array,&nbsp;which I iterate through,&nbsp;cloning each repository.&nbsp;Every tree-sitter grammar repo I've encountered has either a&nbsp;<code>parser.c</code>,&nbsp;<code>scanner.c</code>,&nbsp;or&nbsp;<code>scanner.cc</code>&nbsp;located in the&nbsp;<code>src</code>&nbsp;folder.&nbsp;These are the files you need to compile to get your tree-sitter mode to work properly.&nbsp;The script ultimately gets these files and figures out which ones need to have these Zig commands run on them to create a dynamic library.</p><ol><li><p><code>zig c++ -c -fPIC $fileName -o $cppObject $($includeDirs -join ' ' ) -lc"</code></p></li><li><p><code>zig cc -c -fPIC $fileName -o $cObject $($includeDirs -join ' ')"</code></p></li><li><p><code>zig cc -c -fPIC $fileName -o $cObject $($includeDirs -join ' ')"</code></p></li></ol><p>It does some more logic to create the appropriately named&nbsp;<code>libtree-sitter-&lt;language&gt;.ext</code>,&nbsp;and finally,&nbsp;copies the files over to the tree-sitter folder in my&nbsp;<code>.emacs.d</code>.&nbsp;And that is pretty much it.&nbsp;Here is a snippet of that part of the code</p><pre><code><code>$grammarUrls = @(
    "https://github.com/camdencheek/tree-sitter-dockerfile",
    "https://github.com/tree-sitter/tree-sitter-bash",
    "https://github.com/uyha/tree-sitter-cmake",
    "https://github.com/tree-sitter/tree-sitter-css",
    "https://github.com/tree-sitter/tree-sitter-c-sharp",
    "https://github.com/tree-sitter/tree-sitter-javascript",
    "https://github.com/tree-sitter/tree-sitter-json",
    "https://github.com/tree-sitter/tree-sitter-python",
    "https://github.com/ikatyang/tree-sitter-yaml"
)
$zigCompiler = (Get-ChildItem zig-*/zig).FullName

foreach ($url in $grammarUrls) {
    # I.E tree-sitter-markdown 
    $repoName = $url -split '/' | Select-Object -Last 1
    # I.E tree-sitter-markdown to markdown
    $languageName = $repoName -replace 'tree-sitter-', ''
    $cloneDir = Join-Path $tempDir $repoName

    # Check if grammar directory already exists and -ReinstallGrammar is not used
    if ((Test-Path -Path $cloneDir) -and (-not $ReinstallGrammar)) {
        Write-Host "$repoName already cloned. Pass -ReinstallGrammar to reclone."
        continue
    }

    # If -ReinstallGrammar is used, clean up the current grammar directory
    if ($ReinstallGrammar -And (Test-Path -Path $cloneDir)) {
        Write-Host "Removing old version of $repoName"
        Remove-Item -Path $cloneDir -Recurse -Force
    }

    Write-Host "Downloaded $url to $cloneDir"
    # Clone the grammar repository
    git clone $url $cloneDir --depth=1

    # Navigate to the cloned directory
    Push-Location -Path $cloneDir

    # Compile the grammar using zig cc
    $libName = "libtree-sitter-$languageName$fileExt"
    $cSrcFiles = (Get-ChildItem src/*.c).FullName
    # Hack to filter schema.generated.cc from the yaml ts grammar
    # It's already included in scanner.cc
    $cppSrcFiles = Get-ChildItem src/*.cc
    | Where-Object { $_.Name -ne "schema.generated.cc" } | ForEach-Object { $_.FullName }
    $includeDirs = @('-Isrc -Isrc/tree-sitter')
    # Check if there are C++ source files
    if ($cppSrcFiles -ne $null) {
&#9;# Compile C++ files using zig c++
&#9;[System.Collections.ArrayList]$cppObjectFiles = @()
&#9;foreach ($fileName in $cppSrcFiles) {
&#9;    $cppObject = $fileName + ".o"
&#9;    $cppObjectFiles.Add($cppObject) | Out-Null
&#9;    $cppCmd = "$zigCompiler c++ -c -fPIC $fileName -o $cppObject $($includeDirs -join ' ' ) -lc"
&#9;    Write-Host "Compiling C++ files with the command: $cppCmd`n"
&#9;    Invoke-Expression $cppCmd
&#9;}

&#9;[System.Collections.ArrayList]$cObjectFiles = @()
&#9;foreach ($fileName in $cSrcFiles) {
&#9;    $cObject = $fileName + ".o"
&#9;    $cObjectFiles.Add($cObject) | Out-Null
&#9;    $cCmd = "$zigCompiler cc -c -fPIC $fileName -o $cObject $($includeDirs -join ' ')"
&#9;    Write-Host "Compiling C files with the command: $cCmd`n"
&#9;    Invoke-Expression $cCmd
&#9;}
</code></code></pre><h2><strong>Modifying the init.el</strong></h2><p>After I've downloaded and compiled everything it's time to modify my&nbsp;<code>init.el</code>.&nbsp;The&nbsp;<code>init.el</code>&nbsp;file is what Emacs runs before it starts up,&nbsp;and can be modified by the user to make Emacs do pretty much whatever you want.&nbsp;I have logic in mine to make sure that tree-sitter support is compiled into my Emacs.&nbsp;If it is,&nbsp;it goes through the different languages,&nbsp;checks if the grammar is installed,&nbsp;and then maps the corresponding file extension to the appropriate&nbsp;<code>-ts-mode</code>.</p><pre><code><code>
(if (treesit-available-p)
    (progn
        (message "Tree-Sitter is available")
        ;; Shell script files
        (if (treesit-language-available-p 'sh)
            (add-to-list 'auto-mode-alist '("\\.sh\\'" . bash-ts-mode)))
</code></code></pre><p>Some people use&nbsp;<code>major-mode-remap-alist</code>&nbsp;instead,&nbsp;but I find that solution inelegant.</p><p><a href="https://gitlab.com/diegocrespo/public_emacs_config/-/blob/main/install-ts-grammars.ps1?ref_type=heads">Here is the link</a>&nbsp;to the full PowerShell file that does all of this.&nbsp;That is also the link to my Emacs configuration if you would like to use it yourself.&nbsp;I dedicate all of it to the public domain,&nbsp;or the MIT license if you prefer a concrete license.</p><p>If you've never given Zig a try,&nbsp;I'd recommend it.&nbsp;I think it has a lot of compelling arguments to exist,&nbsp;and is filling a niche that most new programming languages don't care to fill.&nbsp;And of course,&nbsp;I'd also recommend PowerShell as a modern cross-platform shell language.&nbsp;I've written two articles about it so my bias is clear&nbsp;:)</p><p>1.<a href="https://www.deusinmachina.net/p/powershell">Getting work done with PowerShell on Linux</a></p><p>2.<a href="https://www.deusinmachina.net/p/the-case-for-powershell-on-macos">The case for PowerShell On macOS and Linux</a></p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/zig-saves-the-day-for-cross-platform?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e36baf13-633e-40fd-993b-fffb25f6d9eb&quot;,&quot;caption&quot;:&quot;I recently brought an old Raspberry Pi Zero back to life. With the oldest files dating back to the summer of 2020, it was safe to say that it was time for a fresh install. Thankfully there is still a version of Raspberry Pi OS that supports 32 bit Raspberry Pi's like the Zero W&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Experimenting with GUIs on the Pi Zero &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-02-29T13:01:20.825Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:142136682,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:1,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[The most vital knowledge in human history]]></title><description><![CDATA[I recently treated myself to a new Kindle to replace my decade old one. With a whopping 32Gb of storage, it was overkill for novels, but it sparked a curious idea (perhaps inspired by reading Asimov's Foundation)... Could I fit all of English Wikipedia onto it?]]></description><link>https://www.deusinmachina.net/p/the-most-vital-knowledge-in-human</link><guid isPermaLink="false">https://www.deusinmachina.net/p/the-most-vital-knowledge-in-human</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 04 Apr 2024 15:18:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CLEW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CLEW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CLEW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CLEW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg" width="1140" height="855" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:855,&quot;width&quot;:1140,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:237821,&quot;alt&quot;:&quot;Picture of the boston public library with many people studying at tables in it's interior&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Picture of the boston public library with many people studying at tables in it's interior" title="Picture of the boston public library with many people studying at tables in it's interior" srcset="https://substackcdn.com/image/fetch/$s_!CLEW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CLEW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ddbcc-b70a-4d92-aad6-0da7391bad49_1140x855.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Boston Public Library</figcaption></figure></div><p>I recently treated myself to a new Kindle to replace my decade old one.&nbsp;With a whopping 32Gb of storage,&nbsp;it was overkill for novels,&nbsp;but it sparked a curious idea&nbsp;(perhaps inspired by reading Asimov's Foundation)...&nbsp;Could I fit all of English Wikipedia onto it?</p><p>Of course,&nbsp;not&nbsp;<em>all</em>&nbsp;of Wikipedia,&nbsp;that currently encompasses 6,806,195 articles which is like 86gb uncompressed.&nbsp;But then I learned about Wikipedia's&nbsp;"Vital Articles."&nbsp;Out of all the sea of articles on Wikipedia,&nbsp;only a few select articles make this list,&nbsp;with five levels of&nbsp;"vitalness"&nbsp;that encompass larger and larger sections of Wikipedia.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Deus In Machina is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><ul><li><p>Level 1 - 10</p></li><li><p>Level 2 - 100</p></li><li><p>Level 3 - 1000</p></li><li><p>Level 4 - 10,000</p></li><li><p>Level 5 - 50,000</p></li></ul><p>I encourage everyone to browse the list.&nbsp;It's interesting to see what other people consider important throughout human history,&nbsp;even if it's not the list you would have made.&nbsp;That's definitely worth reflecting on.&nbsp;We programmers get a nod in Level 1 under Science,&nbsp;followed by a more prominent&nbsp;'Computers'&nbsp;section in Level 2.&nbsp;By Level 3,&nbsp;there's an entire&nbsp;'Computing and Information Technology'&nbsp;branch,&nbsp;a testament to our field.&nbsp;It did surprise me to see Cryptography get its own section at this level,&nbsp;but then I remembered its historical role in early computing during the World Wars with code breaking.</p><p>By level 4 there are 10,000 articles,&nbsp;and we get put in a higher level section called&nbsp;'Technology'&nbsp;which includes&nbsp;'Computing and information technology'&nbsp;and now encompasses 78 articles ranging from...</p><ol><li><p>Basics</p></li><li><p>Operating Systems</p></li><li><p>Networks</p></li><li><p>Computer science</p></li><li><p>User interface</p></li><li><p>Internet</p></li><li><p>Computer hardware</p></li><li><p>Cryptography</p></li><li><p>Programming</p></li><li><p>Computer Software</p></li><li><p>Data Storage</p></li></ol><p>Four programming languages get dedicated subsections in the section on Programming.</p><ol><li><p>Assembly</p></li><li><p>C</p></li><li><p>Java</p></li><li><p>Javascript</p></li></ol><p>Which I know will ruffle some feathers.&nbsp;Disappointingly,&nbsp;Most of the articles in the Computing and information technology section have a C grade,&nbsp;which Wikipedia describes as</p><blockquote><p>"Useful to a casual reader,&nbsp;but would not provide a complete picture for even a moderately detailed study"</p></blockquote><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xeft!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xeft!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 424w, https://substackcdn.com/image/fetch/$s_!xeft!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 848w, https://substackcdn.com/image/fetch/$s_!xeft!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 1272w, https://substackcdn.com/image/fetch/$s_!xeft!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xeft!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png" width="1456" height="1355" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1355,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:654810,&quot;alt&quot;:&quot;chart showing the different grades a wikipedia article can have with critiera and reader experience descriptions&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="chart showing the different grades a wikipedia article can have with critiera and reader experience descriptions" title="chart showing the different grades a wikipedia article can have with critiera and reader experience descriptions" srcset="https://substackcdn.com/image/fetch/$s_!xeft!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 424w, https://substackcdn.com/image/fetch/$s_!xeft!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 848w, https://substackcdn.com/image/fetch/$s_!xeft!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 1272w, https://substackcdn.com/image/fetch/$s_!xeft!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe11d59-fe0c-481f-942c-c5753f546b64_1721x1602.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I'd like to spend some time in the future improving this.</p><p>By level 5 we get one final high level category,&nbsp;'Communication,&nbsp;media,&nbsp;and computing technology'.&nbsp;It consists of 729 articles,&nbsp;broken down into 12 broad sections and many more subsections.</p><p>But while it's interesting to see at a high level what the community thinks is important in my field,&nbsp;it's time to figure out how to download all of this</p><h2><strong>Downloading articles</strong></h2><p>I found a nifty Calibre plugin called Wiki Reader for grabbing Wikipedia pages</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M0hM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M0hM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 424w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 848w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M0hM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png" width="1456" height="1119" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1119,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:236163,&quot;alt&quot;:&quot;Calibre plugin browser with the Wiki Reader plugin highlighted&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Calibre plugin browser with the Wiki Reader plugin highlighted" title="Calibre plugin browser with the Wiki Reader plugin highlighted" srcset="https://substackcdn.com/image/fetch/$s_!M0hM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 424w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 848w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!M0hM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce92c8e-28c8-4f29-8fc7-b5b45a5df57b_1957x1504.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The interface is simple.&nbsp;It allows you to put in the name of the book associated with the page you want to download...</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!V9hm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V9hm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 424w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 848w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 1272w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!V9hm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png" width="1005" height="541" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:541,&quot;width&quot;:1005,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71281,&quot;alt&quot;:&quot;Calibre plugin with the computer programming wikipedia page filled out in the url&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Calibre plugin with the computer programming wikipedia page filled out in the url" title="Calibre plugin with the computer programming wikipedia page filled out in the url" srcset="https://substackcdn.com/image/fetch/$s_!V9hm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 424w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 848w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 1272w, https://substackcdn.com/image/fetch/$s_!V9hm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64cb91b9-cd8d-49de-bd4f-fa0c03c6d4a4_1005x541.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Then it generates a MOBI file.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NWxQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NWxQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 424w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 848w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 1272w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NWxQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png" width="1281" height="1446" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1446,&quot;width&quot;:1281,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:705891,&quot;alt&quot;:&quot;finished mobi of the wiki article on computer programming&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="finished mobi of the wiki article on computer programming" title="finished mobi of the wiki article on computer programming" srcset="https://substackcdn.com/image/fetch/$s_!NWxQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 424w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 848w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 1272w, https://substackcdn.com/image/fetch/$s_!NWxQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f791de9-2845-4dbe-8cea-58d96f3121b6_1281x1446.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If instead of a single URL,&nbsp;you copy and paste a bunch of URLS to your clipboard,&nbsp;it can auto populate the urls,&nbsp;and combine them all into a single ebook.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ei9p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ei9p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 424w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 848w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ei9p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png" width="1000" height="1260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/690943ac-9873-4740-8294-1bc21556b564_1000x1260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1260,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:166543,&quot;alt&quot;:&quot;wiki reader interface with ten articles filled out to download from the vital articles section of wikipedia&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="wiki reader interface with ten articles filled out to download from the vital articles section of wikipedia" title="wiki reader interface with ten articles filled out to download from the vital articles section of wikipedia" srcset="https://substackcdn.com/image/fetch/$s_!Ei9p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 424w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 848w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!Ei9p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F690943ac-9873-4740-8294-1bc21556b564_1000x1260.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Unfortunately,&nbsp;while bulk downloading is possible,&nbsp;it's agonizingly slow after about 100 articles.&nbsp;But when I tried to write a Python script to scrape the pages manually,&nbsp;the results weren't much better.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!S0TJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S0TJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 424w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 848w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 1272w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!S0TJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png" width="1456" height="1378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c2713102-756c-4f02-87ea-235e067e51df_1544x1461.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1378,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:249458,&quot;alt&quot;:&quot;failed python script to download the wikipedia articles&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="failed python script to download the wikipedia articles" title="failed python script to download the wikipedia articles" srcset="https://substackcdn.com/image/fetch/$s_!S0TJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 424w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 848w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 1272w, https://substackcdn.com/image/fetch/$s_!S0TJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2713102-756c-4f02-87ea-235e067e51df_1544x1461.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I was about to throw in the towel when I stumbled another project,&nbsp;Wikibooks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g7sC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g7sC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 424w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 848w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 1272w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g7sC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png" width="1456" height="639" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:639,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1524997,&quot;alt&quot;:&quot;Wikibooks home page&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Wikibooks home page" title="Wikibooks home page" srcset="https://substackcdn.com/image/fetch/$s_!g7sC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 424w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 848w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 1272w, https://substackcdn.com/image/fetch/$s_!g7sC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e3075f7-a558-47a9-8cba-483045361db2_3688x1618.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Enter Wikibooks</strong></h2><p>Wikipedia itself has limitations as a learning resource...</p><ol><li><p>Unfriendly for Reading: Links and references disrupt the flow.</p></li><li><p>Teaching Gaps: It's not a structured learning environment.</p></li></ol><p>Wikibooks&nbsp;(also from Wikimedia)&nbsp;solves this.&nbsp;It offers deeper dives on certain subjects,&nbsp;with more organized learning paths,&nbsp;while keeping the approach to community contribution.&nbsp;All the information for a topic exists in one book,&nbsp;and you don't need to navigate a maze of links to get the full picture.&nbsp;The tradeoff is less overall coverage than its big brother Wikipedia,&nbsp;and a smaller community,&nbsp;but there are still plenty of content to choose from.&nbsp;I'm just glad a community of volunteers exist that make this knowledge freely available to all of us.</p><p>The nice thing about downloading Wikibooks over Wikipedia articles is that they are generally much friendlier to offline reading.&nbsp;Many Wikibooks offer printable versions of the books,&nbsp;and some even have e-reader friendly PDFs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w32b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w32b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 424w, https://substackcdn.com/image/fetch/$s_!w32b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 848w, https://substackcdn.com/image/fetch/$s_!w32b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 1272w, https://substackcdn.com/image/fetch/$s_!w32b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w32b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png" width="1456" height="653" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:653,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:498659,&quot;alt&quot;:&quot;c programming book with pop ups asking which version, printable, ebook optimized, pdf you want to download for the C programming language book&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="c programming book with pop ups asking which version, printable, ebook optimized, pdf you want to download for the C programming language book" title="c programming book with pop ups asking which version, printable, ebook optimized, pdf you want to download for the C programming language book" srcset="https://substackcdn.com/image/fetch/$s_!w32b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 424w, https://substackcdn.com/image/fetch/$s_!w32b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 848w, https://substackcdn.com/image/fetch/$s_!w32b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 1272w, https://substackcdn.com/image/fetch/$s_!w32b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1290724a-9d25-479a-ae72-1c01b9735375_3688x1654.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This means better formatting and a smoother reading experience on my Kindle.&nbsp;Plus,&nbsp;it's trivial to combine PDFs with tools like&nbsp;<code>PyPDF2</code>&nbsp;in Python,&nbsp;after they are downloaded.</p><h2><strong>The Joy of Learning</strong></h2><p>I went through Wikibooks and I downloaded many of the books I was interested in to put them on my Kindle.&nbsp;While going through the Philosophy section,&nbsp;I came across a Wikibook that was called&nbsp;<a href="https://en.wikibooks.org/wiki/Lun_Yu/Book_1">Lun Yu" (&#35770;&#35821;), also known as "The Analects of Confucius"</a>.&nbsp;It is a collection of sayings and ideas attributed to the Chinese philosopher Confucius and his disciples.&nbsp;The first quote from the first chapter resonated deeply with the spirit of this whole experiment...</p><blockquote><p>The Master said,&nbsp;Is it not pleasant to learn with a constant perseverance and application?</p></blockquote><p>Indeed,&nbsp;it is.</p><h2><strong>Call To Action</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/the-most-vital-knowledge-in-human?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/the-most-vital-knowledge-in-human?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;78bfca58-f81d-4174-b7ee-18635da49346&quot;,&quot;caption&quot;:&quot;I've been watching the OG Star Trek series, having never consumed any of the TV shows before, and I've been surprised at how refreshingly optimistic its take on humanity has been. It's a stark contrast to the dystopian visions that dominate much of contemporary science fiction, I.E The Hunger Games, Blade Runner, Snowpiercer, and Black Mirror. As a mill&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot; Star Trek's Optimism Towards the Future&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-03-28T12:02:19.429Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/star-treks-optimism-towards-the-future&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:143025018,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p></p>]]></content:encoded></item><item><title><![CDATA[ Star Trek's Optimism Towards the Future]]></title><description><![CDATA[I've been watching the OG Star Trek series, having never consumed any of the TV shows before, and I've been surprised at how refreshingly optimistic its take on humanity has been. It's a stark contrast to the dystopian visions that dominate much of contemporary science fiction, I.E The Hunger Games, Blade Runner, Snowpiercer, and Black Mirror. As a millennial who grew up on such bleak narratives, the setting of Star Trek feels foreign.]]></description><link>https://www.deusinmachina.net/p/star-treks-optimism-towards-the-future</link><guid isPermaLink="false">https://www.deusinmachina.net/p/star-treks-optimism-towards-the-future</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 28 Mar 2024 12:02:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!WtJG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WtJG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WtJG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 424w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 848w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 1272w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WtJG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png" width="1456" height="976" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:976,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1910360,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WtJG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 424w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 848w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 1272w, https://substackcdn.com/image/fetch/$s_!WtJG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c8fef35-de74-4bf6-ba99-fe589dca06d6_2049x1374.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I've been watching the OG Star Trek series,&nbsp;having never consumed any of the TV shows before,&nbsp;and I've been surprised at how refreshingly optimistic its take on humanity has been.&nbsp;It's a stark contrast to the dystopian visions that dominate much of contemporary science fiction,&nbsp;I.E The Hunger Games,&nbsp;Blade Runner,&nbsp;Snowpiercer,&nbsp;and Black Mirror.&nbsp;As a millennial who grew up on such bleak narratives,&nbsp;the setting of Star Trek feels foreign.</p><p>Science fiction,&nbsp;unlike fantasy,&nbsp;often strives for a sense of plausibility.&nbsp;The shift toward dark,&nbsp;dystopian futures within the genre mirrors my generation's growing pessimism.&nbsp;Millennials and Gen Z have witnessed economic struggles,&nbsp;the escalating effects of climate change,&nbsp;and increasing social division.&nbsp;Understandably,&nbsp;this has shaped our outlook on what lies ahead.</p><p>That's not to say that there aren't people who are optimistic about the future though.&nbsp;Effective Accelerationism&nbsp;(E/acc)&nbsp;challenges this pessimistic trend.&nbsp;Like the techno-optimists and transhumanists of the past,&nbsp;E/acc supporters embrace technological progress and the potential of Artificial Intelligence.&nbsp;They reject the notion that the future must inevitably be bleak.&nbsp;While I'm not sold on the E/acc crowd,&nbsp;I also generally have a positive outlook on the future.&nbsp;It certainly makes thinking about the world I will inherit as I grow older a less daunting task.</p><p>It's also worth noting that this pessimism overlooks significant advancements in the last 15 years.&nbsp;Consider the rise of smartphones,&nbsp;breakthroughs in AI and deep learning,&nbsp;the promise of CRISPR gene editing,&nbsp;reusable rockets,&nbsp;and immersive VR experiences.&nbsp;These examples suggest that while the challenges are great,&nbsp;our trajectory isn't entirely negative.&nbsp;For example just this year,&nbsp;<a href="https://wish.org/cf-update">Make-A-Wish downgraded Cystic Fibrosis</a>&nbsp;as an automatic qualifier for wish granting,&nbsp;due to ongoing advances in care.&nbsp;That's incredible and should be celebrated.</p><p>I don't think Star Trek's optimism is sourced in blind faith in progress.&nbsp;The show acknowledges social issues and conflict but envisions a humanity that has overcome its worst impulses.&nbsp;Perhaps we can draw inspiration from Star Trek,&nbsp;not to disregard the challenges we face,&nbsp;but to rekindle a sense of measured optimism.&nbsp;What if we imagined solutions along with the problems?&nbsp;What if we believed that progress,&nbsp;while never guaranteed,&nbsp;remains possible?</p><p>It's natural to be concerned about the future,&nbsp;but we shouldn't let pessimism cloud our ability to find solutions.&nbsp;The future is ours to shape,&nbsp;and perhaps a spark of the&nbsp;"Star Trek spirit",&nbsp;that belief in our potential to work together and build a better world,&nbsp;is what we need to chart a brighter course.&nbsp;Anyway,&nbsp;just some thoughts I had as we go into the weekend.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/star-treks-optimism-towards-the-future?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/star-treks-optimism-towards-the-future?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;aec3cf01-b815-41f3-a0f5-af98854edb92&quot;,&quot;caption&quot;:&quot;I used to paint Warhammer 40K mini figures, and one of the things I always enjoyed about the hobby, was building up my toolkit of home brewed accessories that I would use to paint. During my time painting, I repurposed a fishing tackle box as a mobile painting station, used bamboo spice racks for organizing my paints, and had the big bra&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Small Joys when Programming&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-01-25T13:01:18.107Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/small-joys-when-programming&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:140476889,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Learning to use Docker]]></title><description><![CDATA[It's not scary!]]></description><link>https://www.deusinmachina.net/p/learning-to-use-docker</link><guid isPermaLink="false">https://www.deusinmachina.net/p/learning-to-use-docker</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 21 Mar 2024 12:13:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!K9Nv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K9Nv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K9Nv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 424w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 848w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 1272w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K9Nv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:57193,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!K9Nv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 424w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 848w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 1272w, https://substackcdn.com/image/fetch/$s_!K9Nv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1bb910d-95ae-41fd-b707-8ec6ebd1be2e_3840x2160.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Docker was released 13 years ago and has quickly become a mainstay in the programming community.&nbsp;At first I avoided it,&nbsp;considering it too complex,&nbsp;intimidating,&nbsp;and a waste of time for small projects.&nbsp;But Docker is not any of those things.&nbsp;Sure,&nbsp;wrapping a complex project with a Docker bowtie can be challenging,&nbsp;but that's because non trivial projects usually require non trivial solutions.&nbsp;The benefits you get once this is accomplished though,&nbsp;is immense.&nbsp;But before we get to that,&nbsp;let's start simple.&nbsp;What is Docker?</p><blockquote><p>Docker is a technology that helps you package and run your software applications in a consistent and efficient way,&nbsp;regardless of the computing environment they're running on.</p></blockquote><p>This package is typically called a Docker Image.&nbsp;The running instance of an Image is called a Docker Container.&nbsp;You can think of a Docker Image like a programming language and technology agnostic version of a C#&nbsp;or Java project,&nbsp;or a Python virtual environment.&nbsp;In those examples,&nbsp;the language settings and all of the packages that you install are only for that specific project/language you are working on.</p><p>If others want to collaborate on the project,&nbsp;they will need to have the same settings and packages as you.&nbsp;For example,&nbsp;if you have a Python virtual environment you can run&nbsp;<code>pip freeze &gt; requirements.txt</code>&nbsp;to get the list of packages your project needs,&nbsp;then pass along the txt file to someone else who can then run&nbsp;<code>pip install -r requirements.txt</code>&nbsp;to download the same packages.&nbsp;But what if the person trying to install the dependencies for your project has a different version of Python than you?&nbsp;They may run into dependency issues,&nbsp;due to functions being deprecated,&nbsp;or behavior being changed as a library matures.&nbsp;Docker avoids this problem.</p><p>But there are more than just dependency conflicts that can doom a project.&nbsp;Sometimes projects require more than what the standard library,&nbsp;or 3rd party package ecosystem can provide.</p><p>Let&#8217;s say you want to do OCR on some pdfs.&nbsp;You might decide to use&nbsp;<code>pytesseract</code>.&nbsp;In the installation instructions it says that you need&nbsp;<code>Google Tesseract OCR</code>,&nbsp;as&nbsp;<code>pytesseract</code>&nbsp;is a wrapper over it.</p><blockquote><p>Install Google Tesseract OCR&nbsp;(additional info how to install the engine on Linux,&nbsp;Mac OSX and Windows).&nbsp;You must be able to invoke the tesseract command as tesseract.&nbsp;If this isn&#8217;t the case,&nbsp;for example because tesseract isn&#8217;t in your PATH,&nbsp;you will have to change the&nbsp;&#8220;tesseract_cmd&#8221;&nbsp;variable pytesseract.pytesseract.tesseract_cmd.&nbsp;Under Debian/Ubuntu you can use the package tesseract-ocr.&nbsp;For Mac OS users.&nbsp;please install homebrew package tesseract.</p></blockquote><p>Unfortunately&nbsp;<code>Tesseract</code>&nbsp;can't be pip installed,&nbsp;so getting it set up can be tricky.&nbsp;I can't count how many times I've joined a project,&nbsp;and my initial experience looks like this</p><ol><li><p>Try to install additional dependencies</p></li><li><p>Run into an error preventing the install</p></li><li><p>Message Teams Chat, &#8220;Hey, has anyone run into this error when installing X?&#8221;</p></li><li><p>"Oh yea, the link they give in the documentation is to an old version of X, this Stack Overflow post has the correct link"</p></li><li><p>*Continues trying to install and runs into problem Y*</p></li><li><p>Ask in the chat again</p></li><li><p>"Oh it&#8217;s because your using version ZZZ for this, you have to downgrade it because Y is expecting a version QQQ instead."</p></li></ol><p>Eventually you get it all working,&nbsp;and go on your merry way.&nbsp;3 months later,&nbsp;it is summer and you have new interns.&nbsp;One of them has been assigned to this project to help.&nbsp;All of a sudden you see a Teams message in chat from the new intern.</p><ol><li><p>&#8220;Hey has anyone run into this error when installing X?&#8221;</p></li><li><p>You: *Thinks very hard*. "Oh I remember this error! Hold on I have a link to a Stack Overflow post that has the fix"</p></li></ol><p>Repeat steps 4-7 as your intern struggles with the same issues you had 3 months ago.</p><p>If only there was some way you could construct your software applications,&nbsp;that would allow it to behave in a consistent and efficient way,&nbsp;regardless of the computer environment it's running on.&nbsp;Wait!&nbsp;What's that I hear you say?&nbsp;There is?&nbsp;Why yes!&nbsp;Docker of course!</p><h1><strong>Docker In Practice</strong></h1><p>Let&#8217;s use our previous example for a simple Python app that performs ocr,&nbsp;and prints out the text to the screen.</p><p>The following code takes a trimmed pdf from the&nbsp;<a href="https://tile.loc.gov/storage-services/public/gdcmassbookdig/autobiographyofb06fran/autobiographyofb06fran.pdf">Autobiography of Benjamin Franklin</a>&nbsp;pages 7-17,&nbsp;and prints it out to the console.</p><pre><code><code>import pytesseract
from pdf2image import convert_from_path

pdf_file = "trimmed_autobiography.pdf"

# Convert PDF pages to images
pages = convert_from_path(pdf_file, 300)  # DPI set to 300

# OCR each page and extract text
text = ""
for page in pages:
text += pytesseract.image_to_string(page)

print(text)
</code></code></pre><p>Now let&#8217;s look at the Dockerfile we need to build this.</p><pre><code><code>FROM python:3.12-slim-bookworm

# Set the working directory
WORKDIR /app

# Install Tesseract OCR, poppler-utils, and their dependencies
RUN apt-get update &amp;&amp; \
apt-get install -y tesseract-ocr poppler-utils &amp;&amp; \
apt-get clean

# Install python packages
RUN pip3 install --no-cache-dir pytesseract pdf2image

# Copy the main.py and PDF file into the Docker image
COPY main.py trimmed_autobiography.pdf /app/

# Command to run the Python script
CMD ["python3", "main.py"]
</code></code></pre><p>Here's a break down each line of this Dockerfile:</p><ol><li><p><code>FROM python:3.12-slim-bookworm</code>: This line specifies the base Image to use for building the Docker Image. In this case, we are using an Image named&nbsp;<code>python</code>&nbsp;with the tag&nbsp;<code>3.12-slim-bookworm</code>, which means it's based on Python 3.12 and the Debian 'slim' variant. Slim is a smaller version of Debian without extra packages. We use the Python version of Debian instead of the normal Debian Image due to the fact that regular Debian disallows global pip installs (this is normally a good thing).</p></li><li><p><code>WORKDIR /app</code>: This line sets the working directory inside the Docker container to&nbsp;<code>/app</code>. It's common practice to put the code for a project in&nbsp;<code>/app</code>&nbsp;but your working directory can be anywhere you want. The folder will be created if it isn&#8217;t there already. Subsequent commands will be executed from inside this directory</p></li><li><p><code>RUN apt-get update &amp;&amp;</code>:</p><ol><li><p><code>RUN</code>&nbsp;Is a Docker instruction that executes commands in the container during the build process.</p></li><li><p><code>apt-get update</code>&nbsp;Uses the Debian Advanced Package Manager (Apt) to update the package lists for packages that are available for installation.</p></li><li><p><code>&amp;&amp;</code>&nbsp;Allows for multiple commands to be run in a single RUN instruction and the \ allows the instruction to continue onto the next line.</p></li><li><p><code>apt-get install -y tesseract-ocr poppler-utils &amp;&amp;</code>: This line installs the packages&nbsp;<code>tesseract-ocr</code>&nbsp;and&nbsp;<code>poppler-utils</code>&nbsp;along with their dependencies using the apt-get install command. The&nbsp;<code>-y</code>&nbsp;flag automatically confirms any prompts during installation.</p></li><li><p><code>apt-get clean</code>: This command removes any unnecessary files and packages that were downloaded during the installation process. It helps to keep the Docker image size smaller.</p></li></ol></li><li><p><code>RUN pip3 install --no-cache-dir pytesseract pdf2image</code>: This command installs Python packages&nbsp;<code>pytesseract</code>&nbsp;and&nbsp;<code>pdf2image</code>&nbsp;using pip. The&nbsp;<code>--no-cache-dir</code>&nbsp;option disables caching of downloaded packages and metadata.</p></li><li><p><code>COPY main.py trimmed_autobiography.pdf /app/</code>: This line copies files&nbsp;<code>main.py</code>&nbsp;and&nbsp;<code>trimmed_autobiography.pdf</code>&nbsp;from the host machine into the&nbsp;<code>/app</code>&nbsp;directory within the Docker container.</p></li><li><p><code>CMD ["python3", "main.py"]</code>: This is the default command to run when the container starts. It specifies to run the&nbsp;<code>main.py</code>&nbsp;Python script using the python3 interpreter.</p></li></ol><p>A Dockerfile is kind of like as a script you would run if you wanted to automate setting up a new laptop.&nbsp;It would specify all the tools and their dependencies you would need and then go and fetch and install them.</p><h2><strong>Building the Docker Image</strong></h2><p>Now that we have a Dockerfile we can use it to make a Docker Image.&nbsp;If you open your terminal and run&nbsp;<code>docker build -t book-slim .</code>&nbsp;with this Dockerfile in the current directory,&nbsp;Docker will build a Docker Image based on the instructions provided in the Dockerfile.&nbsp;Once the image is created,&nbsp;you can run the Docker Image with the command&nbsp;<code>docker run --name book-slim-container book-slim</code>.&nbsp;This executes your docker Image named&nbsp;<code>book-slim</code>&nbsp;and gives the running container the name&nbsp;<code>book-slim-container</code>.&nbsp;This is helpful because all running Images need a name.&nbsp;If you don&#8217;t provide one than docker will make up a name.</p><p>Looking at my Docker Desktop app,&nbsp;I can see that when I executed my Docker Image the first couple of times without specifying a name,&nbsp;Docker gave it the name&nbsp;&#8220;trusting_nightingale&#8221;,&nbsp;and&nbsp;&#8220;nostalgic_shaw&#8221;.&nbsp;But when I specified a&nbsp;<code>--name</code>,&nbsp;that was the name it gave my container instead.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4CSI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4CSI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 424w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 848w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4CSI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png" width="1456" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154301,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4CSI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 424w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 848w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!4CSI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb2a8877-746e-4ad7-bb3f-e31d64bea887_2402x1040.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Getting back to our running program,&nbsp;after waiting patiently you should start seeing text printed out to the screen</p><blockquote><p>My father had also,&nbsp;by the same wife,&nbsp;four&nbsp;children born in America,&nbsp;and ten others by&nbsp;a second wife,&nbsp;making in all seventeen.&nbsp;I&nbsp;remember to have seen thirteen seated to-&nbsp;gether at his table,&nbsp;who all arrived at years&nbsp;of maturity,&nbsp;and were married.&nbsp;I wus the&nbsp;last of the sons,&nbsp;and the youngest chiid,&nbsp;ex-&nbsp;cepting two daughters.&nbsp;I was born at Bos-&nbsp;ton,&nbsp;in New England.&nbsp;My mother,&nbsp;the sec-&nbsp;ond wife,&nbsp;was Abiah Folger,&nbsp;daughter of&nbsp;Peter Folger,&nbsp;one of the first colonists of&nbsp;New England,&nbsp;of whom Cotton Mather makes&nbsp;.&nbsp;honorable mention,&nbsp;in his Ecclesiastical His-</p></blockquote><p>So,&nbsp;we built our Docker Image which specified all the dependencies we need to run the program,&nbsp;then we ran our Image,&nbsp;and it executed the&nbsp;<code>main.py</code>&nbsp;to print the pdf's text to the terminal like we asked it to.&nbsp;Run the command in the terminal again,&nbsp;but be warned it will fail.</p><p><code>docker run --name book-slim-container book-slim</code></p><p>This is the error message you will get</p><pre><code><code>docker: Error response from daemon: Conflict. The container name "/book-slim-container" is already in use by container "5bf83a1f62e4e6191fd502b889282334a1e666b42f473ed43e3d61fc87ac013c". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
</code></code></pre><p>The reason for this is that Docker requires each container to have a unique name,&nbsp;and we already created one named&nbsp;<code>book-slim-container</code></p><p>To resolve this,&nbsp;we have a few options...</p><ol><li><p><strong>Remove the existing container</strong>: You can remove the existing container with the conflicting name using the&nbsp;<code>docker rm</code>&nbsp;command.</p></li></ol><pre><code><code>docker rm book-slim-container
or
docker rm 5bf83a1f62e4e6191fd502b889282334a1e666b42f473ed43e3d61fc87ac013c
</code></code></pre><ol start="2"><li><p><strong>Rename the existing container</strong>: If you want to keep the existing container but use a different name for the new one, you can rename the existing container using the&nbsp;<code>docker rename</code>&nbsp;command</p></li></ol><p><code>docker rename book-slim-container new-name</code></p><ol start="3"><li><p><strong>Restart and re-execute the container</strong>: An existing container can be restarted, and then re-executed.</p></li></ol><p><code>docker restart book-slim-container &amp;&amp; docker exec book-slim-container python3 main.py</code></p><ol start="4"><li><p><strong>Avoid the issue altogether</strong>: Because an already created Docker Image is easy to execute as a container, it is common to pass the parameters&nbsp;<code>--rm</code>&nbsp;to delete the container after it is run, so subsequent runs can just recreate themselves using the same container name and Image</p></li></ol><p><code>docker run --rm --name book-slim-contaner book-slim</code></p><h2><strong>Exploring containers</strong></h2><p>Let&#8217;s peel back the veil a bit on the container itself.&nbsp;Run the following command in the terminal.</p><p><code>docker run --name book-slim-container -it book-slim /bin/bash</code></p><p>Here&#8217;s what these new commands do</p><ul><li><p><code>-i</code>: Stands for "interactive mode". This means that the container's standard input will remain open even if not attached</p></li><li><p><code>-t</code>: Stands for "tty" or "pseudo-terminal". It allocates a pseudo-terminal for the container</p></li><li><p>Together,&nbsp;<code>-it</code>&nbsp;ensures that the container session is interactive, allowing you to interact with the shell running inside the container *<code>/bin/bash</code>: Overrides the default command specified in the Dockerfile (python3 main.py) and starts a bash shell (/bin/bash) inside the container.</p></li></ul><p>If the interactive command ran successfully,&nbsp;you should be inside the container in the&nbsp;<code>WORKDIR /app</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rs-Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rs-Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 424w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 848w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 1272w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rs-Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png" width="1456" height="506" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:506,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:76174,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rs-Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 424w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 848w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 1272w, https://substackcdn.com/image/fetch/$s_!rs-Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b59c085-7bb3-4a79-b171-20a3f52df998_1706x593.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you type&nbsp;<code>ls</code>&nbsp;you can see the two files that were copied into the container when the Docker Image was built.&nbsp;You can do&nbsp;<code>python --version</code>&nbsp;and see that the python version is 3.12 and run the&nbsp;<code>main.py</code>&nbsp;file manually.&nbsp;It all works like you would expect.&nbsp;When you are done exploring the container you can type&nbsp;<code>exit</code>&nbsp;in the terminal.</p><p>So the advantage of this approach is that you do all the hard work of figuring out all the dependencies for a project,&nbsp;and then encode that into a Dockerfile.&nbsp;Then your coworkers,&nbsp;friends,&nbsp;or collaborators just need to have Docker installed,&nbsp;and then they can run two simple commands to get up and running with your project</p><pre><code><code>docker build -t  book-slim .
docker run --rm --name book-slim-contaner book-slim
</code></code></pre><h2><strong>Mounting volumes</strong></h2><p>Let&#8217;s make our python program more useful.&nbsp;Instead of printing out the text from the pdf,&nbsp;let&#8217;s save it to a file.&nbsp;Here is the new&nbsp;<code>main.py</code></p><pre><code><code>import pytesseract
from pdf2image import convert_from_path

pdf_file = "trimmed_autobiography.pdf"

# Convert PDF pages to images
pages = convert_from_path(pdf_file, 300)  # DPI set to 300

# OCR each page and extract text
text = ""
for page in pages:
text += pytesseract.image_to_string(page)

output_file = "extracted_text.txt"

with open(output_file, "w", encoding="utf-8") as file:
   file.write(text)

print("Text extracted and written to:", output_file)
</code></code></pre><p>If we were to run the Docker Image now with</p><p><code>docker run --rm --name book-slim-container book-slim</code></p><p>The&nbsp;<code>extracted_text.txt</code>&nbsp;would not be written in the same directory you ran the Docker Image.&nbsp;It would write inside the container,&nbsp;and then get cleaned up once the container finishes running.&nbsp;To make the written file accessible outside of the container,&nbsp;you want to mount a directory using the&nbsp;<code>-v</code>&nbsp;command.</p><p>Mounting a host directory into a Docker container allows you to share files and directories between the host machine&nbsp;(where Docker is running)&nbsp;and the container.&nbsp;When you mount a directory,&nbsp;you're essentially creating a link between a directory on your host system and a directory inside the container.&nbsp;This has 3 advantages</p><ol><li><p><strong>Access to Host Files</strong>: Any files or directories in the mounted directory on the host machine are accessible from within the container.</p></li><li><p><strong>Persistence of Data</strong>: Changes made to files or directories in the mounted directory from within the container persist on the host machine, and vice versa. This means that if a file is created, modified, or deleted in the mounted directory from either the host or the container, the change will be reflected in both places.</p></li><li><p><strong>4Sharing Resources</strong>:&nbsp;Mounting a directory can be useful for sharing resources such as code,&nbsp;configuration files,&nbsp;or data between the host and the container.&nbsp;This is particularly handy during development or when you need to provide input data or retrieve output data from a container.</p></li></ol><p>Here is the full command to replicate this behavior.</p><p><code>docker run --rm --name book-slim-container -v .:/app book-slim</code></p><p>To make sure the file is written locally,&nbsp;I pass&nbsp;<code>.:/app</code>&nbsp;to the&nbsp;<code>-v</code>&nbsp;command.&nbsp;This mounts the current directory&nbsp;&#8216;.&#8217;&nbsp;on the host machine to the&nbsp;<code>/app</code>&nbsp;directory inside the container.</p><p>After a few moments,&nbsp;<code>extracted_text.txt</code>&nbsp;appears,&nbsp;confirming that I successfully wrote the file to disk</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G-1s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G-1s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 424w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 848w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 1272w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G-1s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png" width="1456" height="831" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:831,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:114432,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G-1s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 424w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 848w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 1272w, https://substackcdn.com/image/fetch/$s_!G-1s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd768f89-f186-4063-ab7f-bf15dbebf74f_1779x1015.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And that's the basics of Docker.&nbsp;There are still many other aspects of Docker worth getting into&nbsp;(Docker-Compose,&nbsp;managing multiple docker containers,&nbsp;exposing ports,&nbsp;etc)&nbsp;but this should at least get you started.&nbsp;In the mean time,&nbsp;I hope that this article made Docker more approachable,&nbsp;and I hope you use it in one of your next projects!</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/learning-to-use-docker?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/learning-to-use-docker?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;f3d59109-5dd1-42a8-80fe-005e3b35c661&quot;,&quot;caption&quot;:&quot;I was recently learning SDL2, and I found the lack of tutorials in plain C frustrating. I've decided to be the change I wanted to see in the world, and write my own. This will be a multi-part series, and will serve as a quick reference for how to do common things in SDL2. I've listed the main functions at the top of the tutorial kind of like the Raylib &#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;SDL Tutorial Part 1: Opening A Window&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-02-15T13:01:23.080Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25af62e4-fa0e-47dd-87cf-3fbf139b8cb1_1459x730.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:141602172,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[The DOIT philosophy: How I'm avoiding Decision Fatigue and the Paralysis of Choice this year]]></title><description><![CDATA[My mantra for this year is DOIT and it stands for]]></description><link>https://www.deusinmachina.net/p/the-doit-philosophy-how-im-avoiding</link><guid isPermaLink="false">https://www.deusinmachina.net/p/the-doit-philosophy-how-im-avoiding</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 14 Mar 2024 12:02:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!P__R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!P__R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!P__R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 424w, https://substackcdn.com/image/fetch/$s_!P__R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 848w, https://substackcdn.com/image/fetch/$s_!P__R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!P__R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!P__R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg" width="650" height="366" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:366,&quot;width&quot;:650,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23646,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!P__R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 424w, https://substackcdn.com/image/fetch/$s_!P__R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 848w, https://substackcdn.com/image/fetch/$s_!P__R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!P__R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b16512f-2524-48a6-87a5-aee9d9e3761d_650x366.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>My mantra for this year is DOIT and it stands for</p><ul><li><p><strong>D</strong>O</p></li><li><p><strong>O</strong>vercome</p></li><li><p><strong>I</strong>terate</p></li><li><p><strong>T</strong>riumph</p></li></ul><p>I have a lot of projects that are in various states of completion,&nbsp;and I want to get them over the finish line.&nbsp;I just need to DOIT.&nbsp;In service of this,&nbsp;another goal of mine in 2024 is simplicity.&nbsp;By focusing on simplicity I will be able to more effectively achieve my project goals.&nbsp;Einstein's famous quote is applicable here</p><blockquote><p>It can scarcely be denied that the supreme goal of all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience</p></blockquote><p>Amusingly,&nbsp;the more familiar version of this quote is actually a simplified version of the former.&nbsp;It illustrates the point well...</p><blockquote><p>Everything should be made as simple as possible,&nbsp;but no simpler</p></blockquote><p>The key is the 2nd part of the quote&nbsp;"but no simpler".&nbsp;Complexity is the bane of Programmers,&nbsp;and I've been making my life more complicated than it needs to be recently.&nbsp;Sure,&nbsp;there are things that are complex just by their very nature,&nbsp;and just like how I wouldn't fear 1 duck,&nbsp;but 100,000 would give me pause,&nbsp;a 100,000 line code base would still be challenging to work with no matter what the language.&nbsp;But at least languages that value simplicity leave more space in your brain for the actual code part,&nbsp;so you don't end up looking like this</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lMdU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lMdU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 424w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 848w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lMdU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg" width="500" height="521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:521,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:79444,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lMdU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 424w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 848w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!lMdU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63ba92e9-b7a8-4e65-8e46-641ccb99235e_500x521.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Or as Andrew Kelly puts it with Zig</p><blockquote><p>Focus on debugging your application rather than debugging your programming language knowledge.</p></blockquote><p>Ultimately what we are trying to do as Programmers is create things,&nbsp;and complexity gets in the way of that.&nbsp;But the complexity which has inhibited my ability to complete projects doesn't just stop at what programming languages I am using,&nbsp;there are other things that cause this complexity,&nbsp;and they result in two things.&nbsp;Decision fatigue and the Paralysis of Choice.&nbsp;Since these are so similar,&nbsp;let's get a baseline for how they are defined</p><ul><li><p><strong>Decision Fatigue:</strong>&nbsp;The deteriorating quality of decisions made by an individual after a long session of decision making. Essentially, the more decisions you make, the more your ability to make further decisions diminishes. This is because making decisions is cognitively taxing, and over time, the mental resources needed to weigh choices, foresee outcomes, and make judgments become depleted.&nbsp;<em>As a result, an individual might resort to simpler decision-making strategies, exhibit reduced self control, or even avoid making decisions altogether as they become fatigued.</em></p></li></ul><ul><li><p><strong>Paralysis of Choice:</strong>&nbsp;When an individual is faced with too many options and finds it difficult to make a decision. Instead of making a choice, the person becomes overwhelmed by the options available and may feel anxious or unable to choose at all. The paralysis of choice suggests that having too many options can <em>lead to less satisfaction with the eventual choice made, due to the stress of the selection process and the potential for regret over the alternatives not chosen</em>.</p></li></ul><h2><strong>How it affects people</strong></h2><p>The important thing to note about the two definitions above is that it doesn't say anything about a specific scenario where this happens.&nbsp;From the time you get up to the time you go to bed, the act of decision making,&nbsp;and the number of choices presented cause the problems.&nbsp;It doesn't matter whether the decisions you are making are about lunch,&nbsp;or what Steam game to play,&nbsp;they all negatively affect your downstream decision making abilities.&nbsp;This is why&nbsp;<a href="https://www.cnbc.com/2019/06/07/why-successful-people-wear-the-same-thing-every-day.html">successful people employ the trick</a>&nbsp;of wearing the same close to reduce the amount of choices they have to make.&nbsp;But while this is definitely not a live like a&nbsp;"billionaire"&nbsp;grindset sort of article,&nbsp;the principles are sound.&nbsp;CEOs simplify their lives so they can make big decisions that steer the direction of companies and billions of dollars in capital.&nbsp;But I can do the same thing to be more successful in achieving more modest goals.</p><h2><strong>How it affects me</strong></h2><p>To this end I've been simplifying many aspects of my life.&nbsp;One way I've done this is cutting down to one large monitor.&nbsp;This might seem controversial as the productivity gain from two is almost double a single monitor.&nbsp;But a second monitor also invites temptation.&nbsp;It's easy to put things on that 2nd screen that are just for entertainment and don't serve the current task at hand.&nbsp;Furthermore,&nbsp;I find the little snags that come with a 2nd monitor interrupt my flow while working.&nbsp;For example</p><ol><li><p>Windows opening on the wrong screen</p></li><li><p>Windows opening between two screens</p></li><li><p>Resolution issues when both monitors are not the same size</p></li><li><p>Deciding which monitor a window should be on</p></li></ol><p>The point is not that these things can't be fixed,&nbsp;it's that they require three things of mine that are in limited supply.&nbsp;My concentration,&nbsp;my decision making energy,&nbsp;and my will power to not watch YouTube videos.&nbsp;I would rather alt tab to another window when I really need it,&nbsp;or split my window in two if I need to read documentation.&nbsp;Plus with one monitor I don't have to worry about one screen being in a suboptimal position.&nbsp;And as eye strain becomes more of an issue,&nbsp;this is important for me. I'm not the only one who feels this way too,&nbsp;and while my back would never let me&nbsp;program from a couch,&nbsp;I agree with a lot of the things Theo says in this video.</p><div id="youtube2-bIDL6buGNBY" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;bIDL6buGNBY&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/bIDL6buGNBY?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Another way I am simplifying my life is to stick to one operating system.&nbsp;I would switch distributions multiple times a year,&nbsp;as the sheen of the new one faded.&nbsp;This required me to spend the better part of the day just setting up everything again,&nbsp;and then another month running into little things I had forgotten to.&nbsp;This year I'm forcing myself to stick with Pop!_OS as my main desktop's operating system.&nbsp;Pop!_OS is good,&nbsp;so this isn't the hardest decision,&nbsp;but speaking it into existence as opposed to privately muttering it to my self provides some accountability.</p><p>I'm also cutting down on the number of programming languages I will start new projects in.&nbsp;I've been hopping programming languages like I hop distributions,&nbsp;and while I've appreciated the breadth of experience this has given me,&nbsp;I find that it has caused me to have very shallow experience in a lot of languages that aren't Python.&nbsp;Furthermore,&nbsp;a lot of projects start with me just digging into what programming language I'm going to use,&nbsp;what libraries are available for the task,&nbsp;and how to make my code more idiomatic.&nbsp;I end up trying to Goldilocks myself into the right programming language for the project,&nbsp;and that never works.&nbsp;This paralysis of choice also has a subtle but deadly side effect that I have been feeling more frequently too.&nbsp;Let's revisit part of the definition</p><blockquote><p>leading to less satisfaction with the eventual choice made,&nbsp;due to the stress of the selection process and the potential for regret over the alternatives not chosen.</p></blockquote><p>Less satisfaction and regret,&nbsp;two things I don't need more of in my life.&nbsp;Along these same lines I will reduce the number of categories these projects fall under.&nbsp;From GUI to Games,&nbsp;Programming Language Theory to Machine Learning,&nbsp;and Art to Level Design,&nbsp;I've doing a lot of things that cover a lot of different topics.&nbsp;They are all interesting,&nbsp;and I wish I could spend every waking moment hopping between them,&nbsp;but I will never reach the level of proficiency I desire if I spread myself so thin.</p><p>Finally as programmers there are tons of decisions we have to make related to...</p><ol><li><p>Programming languages</p></li><li><p>Frameworks</p></li><li><p>Windows vs Mac vs Linux</p></li><li><p>Mechanical Keyboard Switches</p></li><li><p>frameworks</p></li><li><p>Wall Paper Color</p></li><li><p>Text Editor Font</p></li><li><p>Text Editor</p></li><li><p>ECS, Functional, OOP</p></li><li><p>Web, Mobile Desktop</p></li></ol><p>Before we've even written a single line of code.&nbsp;It's no wonder so many of us want to start a farm instead.&nbsp;But I'm saying let's not throw the baby out with the bath water.&nbsp;Maybe I can pare things down a bit and focus on actually putting code to text editor.&nbsp;This was a lot easier back in the 80s when the options were Basic,&nbsp;Assembly,&nbsp;or Pascal&nbsp;(and let's be real, just Assembly when you were writing something serious).&nbsp;But in the context of today,&nbsp;if I don't pick the perfect stack for my project,&nbsp;who cares,&nbsp;just deal with it.&nbsp;My programming ancestors did more with less.&nbsp;Now I'm not saying to&nbsp;<a href="https://www.levels.fyi/blog/scaling-to-millions-with-google-sheets.html">scale your product to millions of users using just Google Sheets</a>,&nbsp;but it's hard to go wrong with a mainstream language today.</p><p>Of course,&nbsp;I will still learn new things for my job,&nbsp;and I will still write about the interesting things I do here.&nbsp;But I will cut back in places where I can.&nbsp;As it currently stands I have over a years worth of drafts saved up,&nbsp;so even if I just draw inspiration from my drafts it will cover me well into 2025.&nbsp;But,&nbsp;as the year is not even close to over,&nbsp;I suspect I'll come across more little nuggets that will spark ideas for new articles regardless.</p><p>Maybe some of you also struggle with this problem,&nbsp;and there are ways you can simplify your lives to make shipping easier too.&nbsp;I hope we all simplify our stacks this year,&nbsp;so that we can DOIT and be proud of what we created.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/the-doit-philosophy-how-im-avoiding?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/the-doit-philosophy-how-im-avoiding?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;df5d0c25-03e1-415c-b0be-95876768db13&quot;,&quot;caption&quot;:&quot;I&#8217;ve been trying to make small improvements in my life by working on things that were in my control. While not every change I&#8217;ve made has been a positive one, over the course a few years everything has trended in the positive direction. Taking more responsibility in my life has be&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;23 questions to ask myself in 2023&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2022-12-29T13:01:18.454Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F967f78db-b446-4cf8-83f0-8ee59b11b4cd_1280x853.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/23-questions-to-ask-myself-in-2023&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:92352391,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:2,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[A World without C]]></title><description><![CDATA[The Whitehouse released a report this week encouraging the use of memory safe languages, over non memory safe languages, specifically calling out C/C++. This has obviously caused a stir in the programming community, especially considering most people's low opinion of the government&#8217;s ability to produce quality software. But if you&#8217;ve used a computer in the last year you&#8217;ve probably been subjected to poor quality software made by the brightest minds in Silicon Valley, so it's a moot point]]></description><link>https://www.deusinmachina.net/p/a-world-without-c</link><guid isPermaLink="false">https://www.deusinmachina.net/p/a-world-without-c</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 07 Mar 2024 13:01:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!J6kv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.whitehouse.gov/wp-content/uploads/2024/02/Final-ONCD-Technical-Report.pdf">The Whitehouse released a report</a>&nbsp;this week encouraging the use of memory safe languages,&nbsp;over non memory safe languages,&nbsp;specifically calling out C/C++.&nbsp;This has obviously caused a stir in the programming community,&nbsp;especially considering most people's low opinion of the government&#8217;s ability to produce quality software.&nbsp;But if you&#8217;ve used a computer in the last year you&#8217;ve probably been subjected to poor quality software made by the brightest minds in Silicon Valley,&nbsp;so it's a moot point</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J6kv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J6kv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J6kv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg" width="697" height="500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:697,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103322,&quot;alt&quot;:&quot;Epic Hand Shake meme with one hand being Silicon Valley, the other being the Government Clasping the mutually shared Bad Software&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Epic Hand Shake meme with one hand being Silicon Valley, the other being the Government Clasping the mutually shared Bad Software" title="Epic Hand Shake meme with one hand being Silicon Valley, the other being the Government Clasping the mutually shared Bad Software" srcset="https://substackcdn.com/image/fetch/$s_!J6kv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!J6kv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F485274fd-0000-452e-8f3f-1f9527fbd24e_697x500.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>What I find surprising in all of this discourse is that people have missed the point,&nbsp;intentionally or not.&nbsp;Memory unsafe languages have footguns that lead to unsafe software,&nbsp;and that leads to CVEs that cause harm to real people.&nbsp;The context for the report is not your hobby project,&nbsp;nor your single player 2D platformer.&nbsp;It&#8217;s about software that power governments and institutions,&nbsp;places that store large amounts of people&#8217;s data etc.&nbsp;It&#8217;s about companies that provide live services to millions of people,&nbsp;and store their credit card numbers,&nbsp;phone numbers,&nbsp;addresses,&nbsp;names,&nbsp;and dates of birth.&nbsp;This also not about it becoming illegal to program in memory unsafe languages.&nbsp;To sum it up</p><blockquote><p>Programmers writing lines of code do not do so without consequence;&nbsp;the way they do their work is of critical importance to the national interest.</p></blockquote><p>A lot of the discourse revolves around C,&nbsp;with the main point being that you will never get rid of it.&nbsp;That the world runs on C,&nbsp;your operating system runs on C,&nbsp;your programming language runs on C etc,&nbsp;etc.&nbsp;I know how important C is,&nbsp;I've written multiple articles that feature C prominently,&nbsp;and I'll probably write some more</p><ul><li><p><a href="https://www.deusinmachina.net/p/history-of-unix">Tracing the Lines: From the Telephone to Unix</a></p></li><li><p><a href="https://www.deusinmachina.net/p/c-strings-and-my-slow-descent-to">C Strings and my slow descent to madness</a></p></li><li><p><a href="https://www.deusinmachina.net/p/understanding-the-compilation-process">Understanding the Compilation Process in C: A Step by Step Guide</a></p></li><li><p><a href="https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window">SDL Tutorial Part 1: Opening A Window</a></p></li></ul><p>There are a lot of reasons for C's dominance in the modern era,&nbsp;but the one that sticks out to me is that it is the lowest common denominator for just about everything.&nbsp;If you write something in C,&nbsp;it is straightforward in most languages to bind to it through an FFI.&nbsp;That means if I for instance,&nbsp;come across a cool C library that does exactly what I need,&nbsp;I can just bind the functions in my Python code without knowing all the nitty gritty details of how it's implemented.&nbsp;I can do it again in Go,&nbsp;and Java and C#&nbsp;and on and on.&nbsp;Just look at the list of programming languages that have Raylib bindings to see how powerful of a concept this can be&nbsp;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9uig!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9uig!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 424w, https://substackcdn.com/image/fetch/$s_!9uig!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 848w, https://substackcdn.com/image/fetch/$s_!9uig!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 1272w, https://substackcdn.com/image/fetch/$s_!9uig!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9uig!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png" width="1456" height="1506" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0235a580-1f04-440c-9e09-02225628d651_1622x1678.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1506,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:382482,&quot;alt&quot;:&quot;Table showing languages with bindings for raylib including C#, Fortran, and Common Lisp&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Table showing languages with bindings for raylib including C#, Fortran, and Common Lisp" title="Table showing languages with bindings for raylib including C#, Fortran, and Common Lisp" srcset="https://substackcdn.com/image/fetch/$s_!9uig!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 424w, https://substackcdn.com/image/fetch/$s_!9uig!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 848w, https://substackcdn.com/image/fetch/$s_!9uig!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 1272w, https://substackcdn.com/image/fetch/$s_!9uig!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0235a580-1f04-440c-9e09-02225628d651_1622x1678.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But Cs greatest strength is also its greatest weakness.&nbsp;It's simple.&nbsp;My 2nd Edition of K&amp;R is just shy of 300 pages,&nbsp;but a good chunk of that is a reference manual,&nbsp;and a chapter on lexical conventions which can be skipped on a first read through.&nbsp;You could skim through the book in a day.&nbsp;But while the syntax may be simple,&nbsp;there are a lot of concepts in C that are tricky to get right,&nbsp;especially in large programs</p><ol><li><p>Pointer Arithmetic</p></li><li><p>Memory Management</p></li><li><p>Headers/Preprocessor</p></li><li><p>Macros</p></li><li><p>Undefined Behavior</p></li><li><p>Strings and Cross Platform string behavior/support</p></li><li><p>Actually building large projects</p></li></ol><p>And you don't have to take my word,&nbsp;here is C++&nbsp;being brought up again as an alternative to C in the&nbsp;<a href="https://lore.kernel.org/lkml/3465e0c6-f5b2-4c42-95eb-29361481f805@zytor.com/">Linux Kernel</a>&nbsp;just this year&nbsp;(2024),&nbsp;by someone who has programmed more C than I ever will in my lifetime.&nbsp;And here is a page that&nbsp;<a href="https://lwn.net/Articles/542457/">details GCC's transition to C++</a>&nbsp;(the irony is not lost on me).&nbsp;If these people are the best C programmers in the world,&nbsp;what chance do I have?&nbsp;Even John Carmack talks about being surprised on the Lex Fridman podcast about how many mistakes he found when he attacked his code base with sanitizers and fuzzing.</p><p>You might ask,&nbsp;well can't we just make C a better language?&nbsp;And the answer is yes,&nbsp;but that takes time.&nbsp;I'm really looking forward to many of the changes that are in C23,&nbsp;but it will be many years before that will be widely available across MSVC,&nbsp;Clang,&nbsp;and GCC.&nbsp;And getting any feature into C is an exercise in frustration.&nbsp;You only have to read JeanHeyd Meneide's article titled&nbsp;<a href="https://thephd.dev/finally-embed-in-c23">Finally, Embed in C23</a>&nbsp;to understand how thankless of a task this is.&nbsp;I'll give you one excerpt,&nbsp;but I've seen this same sentiment time and time again when it comes to improving the language</p><blockquote><p>It&#8217;s deeply depressing and ultimately a great source of burnout being at the grindstone for 4 years for things people were casually discussing about in September of 1995&nbsp;(and earlier).&nbsp;It&#8217;s almost as depressing as putting typeof in the C Standard and then realizing this was something they&#8217;d been discussing doing since after C89&nbsp;(1989).&nbsp;Am I destined to just keep closing the loop on old,&nbsp;unrealized dreams because a bunch of people were too tired/scared/busy/combative to standardize what has literally been decades of existing practice?&nbsp;</p><p>It was hard to realize how tired I was of this kind of grind until the day the feature was put into the C Standard,&nbsp;this past Tuesday.&nbsp;I quite literally could not even muster a&nbsp;&#8220;yes!&#8221;&nbsp;after the vote finished.&nbsp;I just felt empty and numb,&nbsp;because quite literally dragging an entire community of implementers through several hurdles,&nbsp;to finally get them to acknowledge the existence of a problem and its solution,&nbsp;is just&#8230;&nbsp;soul-crushing.&nbsp;It is a level of effort that I recommend to nobody in any sphere of life,&nbsp;for any task.&nbsp;At least when you are on the ground and organizing and helping people,&nbsp;you&#8217;re providing some kind of material value.&nbsp;Water.&nbsp;Food.&nbsp;Improving something.&nbsp;Here?&nbsp;I&#8217;m talking about things that are quite literally older than I am.&nbsp;Just trying to bring ideas from the last 3 decades&nbsp;-&nbsp;things you would think were Table Stakes for foundational languages like C and C++&nbsp;languages&nbsp;-&nbsp;would not be seen as a radical new paradigm or shift in the language.&nbsp;Nevertheless,&nbsp;I spent&nbsp;(burned?)&nbsp;that energy,&nbsp;and finally.&nbsp;It's in.</p></blockquote><p>That doesn't sound like a fun process to me...</p><p>Now if you're still here I want to make it clear that there are qualities of C that I admire.&nbsp;It's an important language in the annals of programming history,&nbsp;and it is well worth learning.&nbsp;I love C's Spartan nature when I'm practicing Algorithms and Data Structures,&nbsp;and I appreciate that it produces software that is small and fast.&nbsp;Today's modern programming languages have done a shit job at filling in the C's shoes,&nbsp;which is why it's still around so prominently.&nbsp;I think of all the programming languages out there,&nbsp;Zig is the one I'm most hopeful for replacing C in what C does best.&nbsp;And it does so while being safer,&nbsp;easier to cross compile and build,&nbsp;and without adding a ton of complexity to the syntax like languages like Rust,&nbsp;D,&nbsp;and C++&nbsp;do.&nbsp;Now to my main point...</p><p>It is worth noting that C didn't appear on the scene until 1972.&nbsp;That means that 60%&nbsp;of the population in the United States has been around longer,&nbsp;and there are plenty of programmers that remember a world where C didn't exist.&nbsp;C was also absent in the early 8-Bit era compared to programming languages like Basic,&nbsp;Pascal,&nbsp;and Assembly due to its difficulty to compile.&nbsp;So really it's only like 45 years that C has been a major player in the programming space.&nbsp;But people keep repeating the same mantra over and over again&nbsp;"C will never die",&nbsp;which feels like a shocking amount of small mindedness coming from the programming community.&nbsp;I thought we were supposed to be innovative thinkers,&nbsp;problem solvers,&nbsp;and engineers.&nbsp;Must we forever be shackled to a programming language we created 50 years ago,&nbsp;in field that is only 75 years old?&nbsp;Is it really not possible to envision a world that isn&#8217;t powered by C or C++&nbsp;even if it takes another 50-100 years?</p><p>Two Years ago no one was talking about Large Language Models.&nbsp;We were still 30 years away from anything remotely resembling a useful AI assistant.&nbsp;Now,&nbsp;one year later my&nbsp;<em>Church</em>&nbsp;is using AI Generated images from ChatGPT in their service, and Nvidia has doubled its stock priced in a year.&nbsp;8 Years ago Visual Studio Code was released,&nbsp;and now it is the most popular text editor by far.&nbsp;The programming space can move quickly if the value is there,&nbsp;and I believe that moving away from C is one of those things.&nbsp;If our best years of programming are still to come&nbsp;(and I hope they are),&nbsp;and we expect more code to be written in the next few years than at any other point in history,&nbsp;then the percentage of C code should dwindle every year.&nbsp;If the financial incentives are there,&nbsp;and if governments will start biasing favor towards more memory safe languages,&nbsp;then there will be a strong incentive for certain companies to comply.</p><p>Replacing C does not mean erasing its legacy.&nbsp;I will continue to write about C,&nbsp;and tell its part in the ever evolving history of programming,&nbsp;and I hope you will continue to enjoy the story as it is written.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/a-world-without-c?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/a-world-without-c?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;8de09947-59ee-4a09-b28e-31e7d9b52979&quot;,&quot;caption&quot;:&quot;The telephone, invented by Alexander Graham Bell in 1876, sparked a revolution in communication. A year later, in 1877, he established the Bell Telephone Company. This marked the beginning of a fascinating journey, leading to the formation of the Volta Bureau in 1880. Guided by Bell, &#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Tracing the Lines: From the Telephone to Unix&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-08-03T12:00:07.169Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc087116c-69b8-40eb-863a-34654c4294d8_1024x820.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/history-of-unix&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:135466458,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Experimenting with GUIs on the Pi Zero ]]></title><description><![CDATA[I recently brought an old Raspberry Pi Zero back to life. With the oldest files dating back to the summer of 2020, it was safe to say that it was time for a fresh install. Thankfully there is still a version of Raspberry Pi OS that supports 32 bit Raspberry Pi's like the Zero W]]></description><link>https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi</link><guid isPermaLink="false">https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 29 Feb 2024 13:01:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!tCaP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tCaP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tCaP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 424w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 848w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 1272w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tCaP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png" width="1456" height="693" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:693,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31641,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tCaP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 424w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 848w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 1272w, https://substackcdn.com/image/fetch/$s_!tCaP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55c82b9b-fd67-4d57-a738-78a7b884e156_1489x709.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>I recently brought an old Raspberry Pi Zero back to life.&nbsp;With the oldest files dating back to the summer of 2020,&nbsp;it was safe to say that it was time for a fresh install.&nbsp;Thankfully there is still a version of Raspberry Pi OS that supports 32 bit Raspberry Pi's like the Zero W&nbsp;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ejlO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ejlO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 424w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 848w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 1272w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ejlO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png" width="1456" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:132043,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ejlO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 424w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 848w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 1272w, https://substackcdn.com/image/fetch/$s_!ejlO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3556c0ed-7230-46f0-a3e8-839ea7301b9c_2499x825.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It comes with Bookworm which is a recent Debian release,&nbsp;which means we get nice goodies like Python 3.11,&nbsp;version 6+&nbsp;of the Linux kernel&nbsp;(up from 4.19 in the old install),&nbsp;and newer versions of lots of other software.&nbsp;Not that I'll be using the RPI Zero much like a Desktop.&nbsp;A 32-bit single core CPU clocked at 1 Ghz,&nbsp;with 512Mb of RAM,&nbsp;is basically abandonware at this point as a Desktop platform.&nbsp;Even the default installer from the Raspberry Pi foundation installs software you can't use.&nbsp;It asks whether you want to install Chromium and or Firefox,&nbsp;but both programs say this when you try to use them</p><blockquote><p>Chromium/Firefox is not supported on the Raspberry PI Zero W</p></blockquote><p>Whether it's actually realistic to use the Raspberry Pi Zero as a Desktop is a boring question.&nbsp;Who cares!&nbsp;It's fun.&nbsp;But anyway,&nbsp;I'm more interested in using the Zero W to test the baseline performance of some apps that I'm writing anyways,&nbsp;so this isn't a problem.&nbsp;Let's start by looking at a couple of programs on the Pi Zero and see how they perform out of the box.&nbsp;The answer...&nbsp;Pretty slow,&nbsp;but not as bad as I was expecting.&nbsp;Opening up basic software like the terminal,&nbsp;and the file browser take anywhere from 3-6 seconds.&nbsp;That's definitely slow,&nbsp;but even on my beefy desktop with an SSD,&nbsp;most of the apps I use take at least 1-3 seconds to start up.&nbsp;That's not even an order of magnitude faster on a machine that is much more powerful. But complaining about software performance in 2024 is so pass&#233; so I'll just say it sucks.&nbsp;It did pique my interest in performing some highly unscientific testing though which is what you will get below.</p><p>Being <a href="https://xkcd.com/356/">nerdsniped</a> by timing random apps opening,&nbsp;I decided to write some basic GUI apps that did nothing more than open an&nbsp;<code>800x600</code>&nbsp;window,&nbsp;and time them on my phone.&nbsp;Starting off with GTK,&nbsp;I modified the basic&nbsp;<a href="https://docs.gtk.org/gtk4/getting_started.html">GTK4 tutorial example</a></p><pre><code><code>#include &lt;gtk/gtk.h&gt;

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), "Window");
  gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
  gtk_window_present (GTK_WINDOW (window));
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
</code></code></pre><p>Compiling the tutorial with the&nbsp;<code>-O2</code>&nbsp;optimization set,&nbsp;I was astonished to see the app take between 12-14 seconds to open a blank window.&nbsp;Now GTK4 does a lot for us out of the box,&nbsp;and that comes with an upfront cost.&nbsp;But for a blank window that is pretty bad.&nbsp;I looked around for some examples of deploying apps on resource constrained systems with GTK,&nbsp;and even&nbsp;<a href="https://discourse.gnome.org/t/optimizing-startup-time-of-gtk4-0-apps-on-rpi-zero/19637">asked in the GNOME forums</a>&nbsp;but couldn't find any solutions.&nbsp;If you know of any please let me know.</p><p>With that shocking result,&nbsp;I decided to get a baseline for how fast a window&nbsp;<em>could</em>&nbsp;open up.&nbsp;I did this by making as simple X application that opens a window,&nbsp;and then timing the result...</p><pre><code><code>#include &lt;X11/Xlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt; // For exit function

int main() {
    Display *display;
    Window window;
    XEvent event;
    int screen;

    // Open connection to the X server
    display = XOpenDisplay(NULL);
    if (display == NULL) {
        fprintf(stderr, "Cannot open display\n");
        exit(1);
    }

    screen = DefaultScreen(display);


    window = XCreateSimpleWindow(display, RootWindow(display, screen), 10, 10, 800, 600, 1,
                                 BlackPixel(display, screen), WhitePixel(display, screen));


    XSelectInput(display, window, ExposureMask | KeyPressMask);


    XMapWindow(display, window);


    while (1) {
        XNextEvent(display, &amp;event);
        
        // Break out of the loop if the user presses any key
        if (event.type == KeyPress)
            break;
    }


    XCloseDisplay(display);
    return 0;
}
</code></code></pre><p>Except,&nbsp;I almost didn't have a chance to time the result,&nbsp;as the window opened up in&nbsp;~0.5 seconds.&nbsp;I'll be the first to tell you this is not an Apples to Apples comparison,&nbsp;and writing a GUI using just X11 would be an exercise in suffering.&nbsp;(I mean but that's basically what Casey Muratori did in his&nbsp;<a href="https://www.youtube.com/watch?v=T4CjOB0y9nI&amp;list=PLnuhp3Xd9PYTt6svyQPyRO_AAuMWGxPzU&amp;index=6">Handmade Hero Series</a>&nbsp;for Windows).&nbsp;But if all apps opened at that speed,&nbsp;my RPI Zero W wouldn't feel slow at all.&nbsp;Armed with this new knowledge,&nbsp;I decided to look at a couple of other ways of opening a window.</p><p>Since I've been on an SDL2 kick recently,&nbsp;it only made sense to do the same test with that library.&nbsp;You make recognize this code as essentially the example I wrote in&nbsp;<a href="https://open.substack.com/pub/deusinmachina/p/sdl-tutorial-part-1-opening-a-window?r=1nv6s0&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=true">SDL Tutorial Part 1: Opening A Window</a>&nbsp;from a couple weeks ago</p><pre><code><code>#include &lt;SDL2/SDL.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

int main(){
 if (SDL_Init(SDL_INIT_VIDEO) &lt; 0){
   printf("Couldn't initialize SDL: %s\n", SDL_GetError());
   return EXIT_FAILURE;
 }

 SDL_Window *window = SDL_CreateWindow("Example: 0", SDL_WINDOWPOS_UNDEFINED,
   &#9;&#9;&#9;&#9;SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
 if (!window){
   printf("Failed to open %d x %d window: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError());
   return EXIT_FAILURE;
 }

 SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 250);
 SDL_RenderClear(renderer);
 SDL_RenderPresent(renderer);
 SDL_Delay(2000);
 SDL_DestroyWindow(window);
 SDL_DestroyRenderer(renderer);
 SDL_Quit();
 return EXIT_SUCCESS;
}
</code></code></pre><p>And our results...&nbsp;A little over 3.1 seconds.&nbsp;While SDL2 is not a retained mode GUI,&nbsp;I could certainly do more with it than I could with just a raw X app. So,&nbsp;so long as people didn't need a screen reader for the program,&nbsp;this might be a viable option.&nbsp;(I'm not even sure you could run any sufficiently complex app,&nbsp;and a screen reader on the RPI Zero,&nbsp;at the same time anyway though).</p><p>I recently made a simple GUI app in Python with Tkinter,&nbsp;and since it's already built into Python I wrote my example in it next to see how it would perform</p><pre><code><code>import tkinter as tk

app = tk.Tk()
app.title("Simple 800x600 Window")

app.geometry("800x600")

app.mainloop()
</code></code></pre><p>~2.9 seconds.&nbsp;For an language that has to interpret the code upfront,&nbsp;that is not bad.&nbsp;I think that Tkinter is an underrated gem of the Python world,&nbsp;and I'll be writing more about that soon.&nbsp;But,&nbsp;while the Tk integration with Python is great,&nbsp;I wanted to look at two more implementations.&nbsp;One using the de facto Tcl bindings to Tk,&nbsp;and the other using just raw C and Tk</p><pre><code><code>#!/usr/bin/env wish

wm title . "Simple Window"
wm geometry . 800x600

tkwait window .
</code></code></pre><p>Tcl is an interesting language that warrants its own discussion at a later date,&nbsp;but on my RPI Zero I was able to open up the window in&nbsp;~2.0 seconds which is a great improvement.&nbsp;Considering we are entering the territory of as fast,&nbsp;or faster than the default apps,&nbsp;I feel like we have reached acceptable speeds.&nbsp;But Python and Tcl are just binding the underlying C Tk library,&nbsp;so let's look at C next.</p><pre><code><code>#include &lt;tk.h&gt;

int main(int argc, char **argv) {
    Tcl_Interp *interp;
    Tk_Window window;

    // Initialize Tcl and the Tk toolkit
    Tcl_FindExecutable(argv[0]);
    interp = Tcl_CreateInterp();

    if (Tcl_Init(interp) == TCL_ERROR) {
        return -1;
    }

    if (Tk_Init(interp) == TCL_ERROR) {
        return -1;
    }

    // Create a new top-level Tk window
    window = Tk_MainWindow(interp);

    // Set the title of the window using Tcl command
    Tcl_Eval(interp, "wm title . \"Simple Tk C App\"");

    // Set the size of the window
    Tk_GeometryRequest(window, 800, 600);

    // Start the Tk event loop
    Tk_MainLoop();

    return 0;
}
</code></code></pre><p>Honestly maybe a tenth of a second faster than Tcl example but much less ergonomic.&nbsp;I did compile everything with&nbsp;<code>-O2</code>&nbsp;when I could,&nbsp;but I think that is just a testament to how well Tcl and Tk are integrated.</p><p>Next I looked at the Fast Light Toolkit&nbsp;(FLTK),&nbsp;a cross platform GUI library I used many years ago when I first attempted to learn C++.&nbsp;Fun fact this is also the GUI library used to create the Eureka Doom Level editor,&nbsp;a cross platform tool I have extensive experience with.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PtMu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PtMu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 424w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 848w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 1272w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PtMu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png" width="1456" height="884" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:884,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:495285,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PtMu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 424w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 848w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 1272w, https://substackcdn.com/image/fetch/$s_!PtMu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf781e13-7e28-4830-88a5-46bd37ab3d69_2186x1327.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It's certainly got the right name for this test,&nbsp;so let's see if it can live up to it.</p><pre><code><code>#include &lt;FL/Fl.H&gt;
#include &lt;FL/Fl_Window.H&gt;

int main() {
    // Create a window with dimensions 800x600
    Fl_Window *window = new Fl_Window(800, 600);

    // Set the window label
    window-&gt;label("My FLTK Window");

    // Show the window
    window-&gt;show();

    // Run the FLTK event loop
    return Fl::run();
}
</code></code></pre><p>Aaand at 1.1 seconds we have a new winner.&nbsp;That was really impressive.&nbsp;I would be curious to see how much of it's speed it could retain with a more complex application.</p><p>To finish this test off,&nbsp;I'll add two late additions.&nbsp;A simple Qt6 app using QT Widgets and C++</p><pre><code><code>#include &lt;QApplication&gt;
#include &lt;QWidget&gt;

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.resize(800, 600);
    window.setWindowTitle("Simple Qt6 App on Raspberry Pi Zero");
    window.show();

    return app.exec();
}
</code></code></pre><p>and a QtQuick example with qml</p><pre><code><code>import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 800
    height: 600
    visible: true
}
</code></code></pre><p>Compiling these apps made my little Pi Zero chug,&nbsp;but it was worth it.&nbsp;At a little under 2.5 seconds for QT widgets,&nbsp;and 2.75 seconds for the QML example,&nbsp;that's not bad.&nbsp;QT is used a lot in the auto industry for infotainment systems which are not known for their specs,&nbsp;so it's not surprising that we could get something running on our RPI Zero.&nbsp;Qt also comes with all the same goodies that GTK and other fully featured cross platform GUIs would need to build&nbsp;<em>any</em>&nbsp;type of app,&nbsp;so its performance here indicates it would be pretty snappy on any computer more powerful than a Raspberry Pi Zero.&nbsp;It's not my favorite cross platform GUI for a few reasons,&nbsp;but every non electron based desktop GUI developer job I've seen uses it,&nbsp;so that's a strong point in its favor.</p><p>Now,&nbsp;I'll be the first one to tell you that there are a lot more that goes into making a GUI app than how fast it opens.&nbsp;There is the set of widgets that it provides,&nbsp;how cross platform it is,&nbsp;what its memory footprint looks,&nbsp;its ability to provide a native&nbsp;"look and feel"&nbsp;etc.&nbsp;All things we didn't test here.&nbsp;But I hope that I've at least convinced you to give one of these great libraries a try</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/experimenting-with-guis-on-the-pi?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;0a815171-7260-4ea1-baca-e5c7341fe977&quot;,&quot;caption&quot;:&quot;I used to paint Warhammer 40K mini figures, and one of the things I always enjoyed about the hobby, was building up my toolkit of home brewed accessories that I would use to paint. During my time painting, I repurposed a fishing tackle box as a mobile painting station, used bamboo spice racks for organizing my paints, and had the big bra&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Small Joys when Programming&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-01-25T13:01:18.107Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/small-joys-when-programming&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:140476889,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[SDL Tutorial Part 2: Drawing Text]]></title><description><![CDATA[This is part 2 of my SDL series using C.]]></description><link>https://www.deusinmachina.net/p/sdl-tutorial-part-2-drawing-text</link><guid isPermaLink="false">https://www.deusinmachina.net/p/sdl-tutorial-part-2-drawing-text</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 22 Feb 2024 13:01:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!8Mwd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Mwd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Mwd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 424w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 848w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 1272w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Mwd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png" width="1284" height="796" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:796,&quot;width&quot;:1284,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:15225,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8Mwd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 424w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 848w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 1272w, https://substackcdn.com/image/fetch/$s_!8Mwd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06593386-1c57-447e-8c8d-281e9b0e44b4_1284x796.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>This is part 2 of my SDL series using C. If you missed part 1 you <a href="https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window">can find it here</a>.&#128204;&nbsp;</p></blockquote><h2><strong>Displaying Text Cheat Sheet</strong></h2><ol><li><p><a href="https://wiki.libsdl.org/SDL2_ttf/TTF_Init">TTF_Init</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2_ttf/TTF_OpenFont">TTF_OpenFont</a>.</p></li><li><p><a href="https://wiki.libsdl.org/SDL2_ttf/TTF_RenderText_Solid">TTF_RenderText_Solid</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_CreateTextureFromSurface">SDL_CreateTextureFromSurface</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_RenderCopy">SDL_RenderCopy</a></p><p></p></li></ol><p>Displaying Text in SDL2 requires a very similar set of operations to how we handled creating a window and renderer in part 1.&nbsp;But before we get to displaying text, we need to include the appropriate header. Since SDL2 is designed to be modular, the libraries that work with text are in their own separate headers/files.&nbsp;To work with text,&nbsp;you will need&nbsp;<code>SDL_ttf.h</code>.&nbsp;You can either include it and the appropriate files directly in your project,&nbsp;linking them at compile time,&nbsp;or if you are on Linux like I am,&nbsp;use your package manager to install them globally.&nbsp;While we won&#8217;t be going over the specifics for how to set up SDL in this tutorial, the  SDL <a href="https://wiki.libsdl.org/SDL2/Installation">Wiki provides a pag</a>e on how to properly set up SDL that is pretty thorough. Now, for those of you who just want to see the code, here is the entire source.</p><pre><code><code>#include &lt;SDL2/SDL.h&gt;
#include &lt;SDL2/SDL_ttf.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
#define MY_FONT "/usr/share/fonts/truetype/freefont/FreeSans.ttf"

int main(){
  if (SDL_Init(SDL_INIT_VIDEO) &lt; 0){
    printf("Couldn't initialize SDL: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }
    // Initialize SDL_ttf
    if (TTF_Init() &lt; 0) {
        printf("SDL_ttf could not initialize! TTF_Error: %s\n", TTF_GetError());
        SDL_Quit();
        return EXIT_FAILURE;
    }

  SDL_Window *window = SDL_CreateWindow("Drawing Text", SDL_WINDOWPOS_UNDEFINED,
&#9;&#9;&#9;&#9;&#9;SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);

  if (!window){
    printf("Failed to open %d x %d window: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);

  if (!renderer){
    printf("Failed to create renderer: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_SetRenderDrawColor(renderer, 255,255,255,255);
  SDL_RenderClear(renderer);

  TTF_Font *font = TTF_OpenFont(MY_FONT, 64); // specify the path to your font file and font size

  if (!font){
    printf("Failed to load font: %s\n", TTF_GetError());
    return EXIT_FAILURE;
  }
  
  // Create surface with rendered text
  SDL_Color textColor = {0, 0, 0, 255}; // black color
  SDL_Surface *textSurface = TTF_RenderText_Solid(font, "Hello World!", textColor);

  if (!textSurface) {
    printf("Failed to create text surface: %s\n", TTF_GetError());
    return EXIT_FAILURE;
  }

  // Create texture from surface
  SDL_Texture *textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

  if (!textTexture){
    printf("Failed to create text texture: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }

  // Render text
  SDL_Rect textRect = {50, 50, textSurface-&gt;w, textSurface-&gt;h}; // rectangle where the text is drawn 
  SDL_RenderCopy(renderer, textTexture, NULL, &amp;textRect);

  SDL_RenderPresent(renderer);
  SDL_Delay(2000);
  SDL_DestroyWindow(window);
  SDL_DestroyRenderer(renderer);
  SDL_Quit();

  return EXIT_SUCCESS;
}
</code></code></pre><p>Starting off we&nbsp;<code>#include &lt;SDL2/SDL_ttf.h&gt;</code>&nbsp;which gives us access to functions that help us display text.&nbsp;Since the ttf module works with fonts,&nbsp;which are normally&nbsp;.ttf files, we need a font to properly display the text in our Window.&nbsp;You can either download a font from the internet,&nbsp;or use a&nbsp;.ttf file that you have on your computer.&nbsp;To keep it simple, I&#8217;ll just use one of the default ones that comes on my computer. At the top of my program,&nbsp;I've created a define that simply points to a default font</p><pre><code><code>#define MY_FONT "/usr/share/fonts/truetype/freefont/FreeSans.ttf"
</code></code></pre><blockquote><p>On macOS you should be able to find some&nbsp;.ttf files located at&nbsp;<code>/Library/Fonts</code>&nbsp;and on Windows&nbsp;<code>C:\Windows\Fonts</code></p></blockquote><p>Following the same paradigm we used to initialize our video module,&nbsp;we have to initialize our ttf library.&nbsp;The same pattern is used,&nbsp;where we check to see if the return value of the&nbsp;<a href="https://wiki.libsdl.org/SDL2_ttf/TTF_Init">TTF_Init</a>&nbsp;function is less than zero,&nbsp;and if it is,&nbsp;we display an error to the user</p><pre><code><code>   // Initialize SDL_ttf
   if (TTF_Init() &lt; 0) {
       printf("SDL_ttf could not initialize! TTF_Error: %s\n", TTF_GetError());
       SDL_Quit();
       return EXIT_FAILURE;
   }
</code></code></pre><p>If the ttf library was installed and linked correctly then we can attempt to load a font using&nbsp;<a href="https://wiki.libsdl.org/SDL2_ttf/TTF_OpenFont">TTF_OpenFont</a>.&nbsp;Again we want to check that the font was actually loaded and we do that with our if statement</p><pre><code><code>  TTF_Font *font = TTF_OpenFont(MY_FONT, 64); // specify the path to your font file and font size

  if (!font){
    printf("Failed to load font: %s\n", TTF_GetError());
    return EXIT_FAILURE;
  }
</code></code></pre><p>Now that we've loaded our font we need to create a text surface using&nbsp;<a href="https://wiki.libsdl.org/SDL2_ttf/TTF_RenderText_Solid">TTF_RenderText_Solid</a>&nbsp;This surface is essentially an image containing the rendered text.&nbsp;Since this is an operation that can fail,&nbsp;we want to make sure that we check this using an if statement like we've done before</p><pre><code><code> // Create surface with rendered text
  SDL_Color textColor = {0, 0, 0, 255}; // black color
  SDL_Surface *textSurface = TTF_RenderText_Solid(font, "Hello World!", textColor);

  if (!textSurface) {
    printf("Failed to create text surface: %s\n", TTF_GetError());
    return EXIT_FAILURE;
  }
</code></code></pre><p>The next step uses&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_CreateTextureFromSurface">SDL_CreateTextureFromSurface</a>&nbsp;to convert our&nbsp;<code>SDL_Surface</code>&nbsp;(your rendered text)&nbsp;into an&nbsp;<code>SDL_Texture</code>.&nbsp;This is necessary because modern SDL2 uses the GPU for rendering,&nbsp;and textures are the GPU-friendly way of handling images.&nbsp;This conversion process uploads the surface data&nbsp;to the GPU memory,&nbsp;enabling efficient rendering.&nbsp;This operation can also fail,&nbsp;so it is important to check that it doesn't before doing anything with the texture</p><pre><code><code>  // Create texture from surface
  SDL_Texture *textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

  if (!textTexture){
    printf("Failed to create text texture: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }
</code></code></pre><p>Finally,&nbsp;we call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_RenderCopy">SDL_RenderCopy</a>.&nbsp;This function tells SDL2 to copy the text texture to the renderer.&nbsp;The&nbsp;<code>SDL_Rect</code>&nbsp;<code>textRect</code> that is defined is used to position and size the text on the screen.</p><p>It is important to understand that nothing will be drawn on the screen yet.&nbsp;It's more like preparing what needs to be drawn.&nbsp;The actual drawing happens when you call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_RenderPresen">SDL_RenderPresent</a>.</p><pre><code><code>  // Render text
  SDL_Rect textRect = {50, 50, textSurface-&gt;w, textSurface-&gt;h}; // rectangle where the text is drawn 
  SDL_RenderCopy(renderer, textTexture, NULL, &amp;textRect);
</code></code></pre><p>If all goes well then when you run the code, you should see some text on the screen.&nbsp;With that, you are well on your way to learning the core components of using the SDL2 library.&nbsp;With just the information that you&#8217;ve learned from part 1 and part 2, you should be able to make a graphical version of the guess my number game,&nbsp;a common beginner programming task, but with an SDL flavored twist. You can even create a rudimentary text adventure, if you were so inclined.</p><p>One final note. Between this and the last tutorial,&nbsp;you may be seeing a lot of repetitive code that might be better off abstracted away in functions.&nbsp;That&#8217;s good,&nbsp;and means you are getting familiar with the patterns in the library. Opinions about the structure of code should be based off the needs of the code base. While I&#8217;m keeping it simple for these tutorials, eventually we should abstract away some common patterns.</p><h2>FAQ</h2><h3>Why Not Draw Directly to the Renderer?</h3><p>SDL2 uses two main types of objects for drawing:&nbsp;<code>SDL_Surface</code>&nbsp;and&nbsp;<code>SDL_Texture</code>.&nbsp;<code>SDL_Surface</code>&nbsp;is a CPU-based bitmap,&nbsp;useful for manipulating pixel data directly.&nbsp;<code>SDL_Texture</code>,&nbsp;on the other hand,&nbsp;is GPU-based.&nbsp;Modern SDL2 applications use the GPU for rendering&nbsp;(via&nbsp;<code>SDL_Renderer</code>),&nbsp;which is faster and more efficient but requires textures,&nbsp;not surfaces.</p><p>The reason you can't directly render the font to the renderer is that&nbsp;<code>SDL2_ttf</code>&nbsp;is designed to work with surfaces,&nbsp;as historically SDL handled rendering with surfaces before textures and GPU rendering were introduced.</p><h3>Does that mean that SDL2 can render just the surface instead of the texture if I don't want to use the GPU?</h3><p>Yes,&nbsp;SDL2 can render using just an&nbsp;<code>SDL_Surface</code>&nbsp;without converting it to an&nbsp;<code>SDL_Texture</code>&nbsp;if you prefer or need to render without using the GPU.&nbsp;This approach is known as&nbsp;"software rendering"&nbsp;and it's done entirely by the CPU,&nbsp;bypassing the GPU.</p><p>Software rendering with&nbsp;<code>SDL_Surface</code>&nbsp;was the primary method used in SDL before SDL2 introduced hardware-accelerated rendering with&nbsp;<code>SDL_Texture</code>&nbsp;and&nbsp;<code>SDL_Renderer</code>.&nbsp;While software rendering is less efficient and slower than hardware accelerated rendering,&nbsp;it can be useful in certain scenarios,&nbsp;like on systems with limited or no GPU capabilities.&nbsp;Instead of using a renderer like we are using you would instead create a&nbsp;<code>SDL_Surface</code>&nbsp;with&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_GetWindowSurface">SDL_GetWindowSurface</a></p><pre><code><code>SDL_Surface *windowSurface = SDL_GetWindowSurface(window);</code></code></pre><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/sdl-tutorial-part-2-drawing-text?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/sdl-tutorial-part-2-drawing-text?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Deus In Machina</span></a></p><p></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;6c16a1e6-8650-4f86-8789-e4ea83e4c81f&quot;,&quot;caption&quot;:&quot;I was recently learning SDL2, and I found the lack of tutorials in plain C frustrating. I've decided to be the change I wanted to see in the world, and write my own. This will be a multi-part series, and will serve as a quick reference for how to do common things in SDL2. I've listed the main functions at the top of the tutorial kind of like the Raylib &#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;SDL Tutorial Part 1: Opening A Window&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-02-15T13:01:23.080Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25af62e4-fa0e-47dd-87cf-3fbf139b8cb1_1459x730.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:141602172,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[SDL Tutorial Part 1: Opening A Window]]></title><description><![CDATA[I was recently learning SDL2, and I found the lack of tutorials in plain C frustrating. I've decided to be the change I wanted to see in the world, and write my own. This will be a multi-part series, and will serve as a quick reference for how to do common things in SDL2. I've listed the main functions at the top of the tutorial kind of like the Raylib Cheatsheet, if you just need a quick reference.]]></description><link>https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window</link><guid isPermaLink="false">https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 15 Feb 2024 13:01:23 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/25af62e4-fa0e-47dd-87cf-3fbf139b8cb1_1459x730.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hBT4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hBT4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 424w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 848w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 1272w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hBT4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55324,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hBT4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 424w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 848w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 1272w, https://substackcdn.com/image/fetch/$s_!hBT4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F453c320c-e2a0-4d51-ab5b-28ed0bd70043_1459x730.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>I was recently learning SDL2,&nbsp;and I found the lack of tutorials in plain C frustrating.&nbsp;I've decided to be the change I wanted to see in the world,&nbsp;and write my own.&nbsp;This will be a multi-part series,&nbsp;and will serve as a quick reference for how to do common things in SDL2.&nbsp;I've listed the main functions at the top of the tutorial kind of like the Raylib Cheatsheet,&nbsp;if you just need a quick reference.</p><p>&nbsp;Before we dive in,&nbsp;I want to point out an immensely helpful resource that will be useful as you become more experienced.&nbsp;<a href="https://wiki.libsdl.org/wiki/index">The SDL2 Wiki</a>&nbsp;contains an index which has a link to every SDL function wiki page.&nbsp;This will teach you everything you need to know about calling the function and handling its output properly.&nbsp;If a big list of functions is too disjointed,&nbsp;there is also a&nbsp;<a href="https://wiki.libsdl.org/SDL2/APIByCategory">wikipage</a>&nbsp;that links to the same resources,&nbsp;but organized into API categories as well.&nbsp;This can be useful as common operations usually require multiple functions that are related.</p><h2><strong>Open a Window Cheat Sheet</strong></h2><ol><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_Init">SDL_Init</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_CreateRenderer">SDL_CreateRenderer</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_CreateWindow">SDL_CreateWindow</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_SetRenderDrawColor">SDL_SetRenderDrawColor</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_RenderClear">SDL_RenderClear</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_RenderPresent">SDL_RenderPresent</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_DestroyWindow">SDL_DestroyWindow</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_DestroyRenderer">SDL_DestroyRenderer</a></p></li><li><p><a href="https://wiki.libsdl.org/SDL2/SDL_Quit">SDL_Quit</a></p></li></ol><h2><strong>Tutorial</strong></h2><p>The simplest and fastest way to get a window open in SDL2 is to write the following code.</p><pre><code><code>#include &lt;SDL2/SDL.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720

int main() {
    SDL_Window *window = SDL_CreateWindow("Example: 0", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_SetRenderDrawColor(renderer, 255,255,255,250);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    SDL_Delay(2000);
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_Quit();
    return EXIT_SUCCESS;
}
</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AqE7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AqE7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 424w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 848w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 1272w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AqE7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png" width="1279" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1279,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:10915,&quot;alt&quot;:&quot;A blank SDL2 window titled Example: 0&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A blank SDL2 window titled Example: 0" title="A blank SDL2 window titled Example: 0" srcset="https://substackcdn.com/image/fetch/$s_!AqE7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 424w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 848w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 1272w, https://substackcdn.com/image/fetch/$s_!AqE7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09dbfff1-6b62-4a00-843f-b06c87a4190f_1279x793.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The start of something great</figcaption></figure></div><p>But this is not recommended.&nbsp;It's possible that many of the functions that we just called can fail,&nbsp;so we want to include a few more checks to make sure that everything is working correctly.&nbsp;Let's do that now</p><pre><code><code>int main(){
  if (SDL_Init(SDL_INIT_VIDEO) &lt; 0){
    printf("Couldn't initialize SDL: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_Window *window = SDL_CreateWindow("Example: 0", SDL_WINDOWPOS_UNDEFINED,
&#9;&#9;&#9;&#9;&#9;SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
  if (!window){
    printf("Failed to open %d x %d window: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
  SDL_SetRenderDrawColor(renderer, 255, 255, 255, 250);
  SDL_RenderClear(renderer);
  SDL_RenderPresent(renderer);
  SDL_Delay(2000);
  SDL_DestroyWindow(window);
  SDL_DestroyRenderer(renderer);
  SDL_Quit();
  return EXIT_SUCCESS;
}
</code></code></pre><p>The first thing we do is call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_Init">SDL_Init</a>&nbsp;and pass the flag&nbsp;<code>SDL_INIT_VIDEO</code>,&nbsp;which initializes the video subsystem.&nbsp;SDL has many initialization flags that you can bitwise OR&nbsp;(<code>|</code>)&nbsp;together to initialize multiple subsystems at once.&nbsp;For example like this</p><pre><code><code>    // Initialize SDL with video and audio subsystems
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return 1;
    } else {
        printf("SDL video and audio initialized successfully.\n");
</code></code></pre><p>But we will stick to the video subsystem for now.&nbsp;Next we will call&nbsp;<code>SDL_CreateWindow</code>.&nbsp;It takes in a title,&nbsp;x and y for the window position,&nbsp;width and height for the window size,&nbsp;and some flags.&nbsp;If we go to the wikipage for&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_CreateWindow">SDL_CreateWindow</a>&nbsp;we will see the function prototype,&nbsp;a description of its parameters&nbsp;(including flags that can be passed),&nbsp;and the expected return values on failure.&nbsp;This is how I knew what that I wanted to pass&nbsp;<code>SDL_WINDOWPOS_UNDEFINED</code>&nbsp;for the x and y,&nbsp;and let the operating system handle window placement.</p><p>Moving on,&nbsp;we create our renderer with&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_CreateRenderer">SDL_CreateRenderer</a>.&nbsp;We give it the window we created,&nbsp;so we can render to it,&nbsp;and pass its index parameter&nbsp;<code>-1</code>&nbsp;to initialize the first rendering driver that can support our requested parameter flag of&nbsp;<code>0</code>.&nbsp;You will always pass&nbsp;<code>-1</code>&nbsp;as the&nbsp;<strong>index parameter</strong>&nbsp;unless you have a good reason not to.&nbsp;For the&nbsp;<strong>render flag</strong>&nbsp;we pass&nbsp;<code>0</code>&nbsp;which defaults to&nbsp;<code>SDL_RENDERER_ACCELERATED</code>&nbsp;(using hardware acceleration for the graphics)&nbsp;if it is supported on your system.&nbsp;If you want to be more explicit you can pass&nbsp;<code>SDL_RENDERER_ACCELERATED</code>&nbsp;instead.&nbsp;Just like with the SDL window,&nbsp;we write an if statement to check if the renderer was created so that we don't accidentally use it if it hasn't been initialized.</p><p>Next we call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_SetRenderDrawColor">SDL_SetRenderDrawColor()</a>&nbsp;and pass it our renderer,&nbsp;as well as 4 integers with values from 0-255.&nbsp;The 4 integers correspond to&nbsp;<code>Red</code>,&nbsp;<code>Green</code>,&nbsp;<code>Blue</code>,&nbsp;and&nbsp;<code>Alpha</code>&nbsp;values of a color.&nbsp;The alpha controls the transparency of the color,&nbsp;while setting the R,&nbsp;G,&nbsp;and B values to various levels allow you to create any color you want between&nbsp;<code>0,0,0,255</code>&nbsp;(Black)&nbsp;and&nbsp;<code>255,255,255,255</code>&nbsp;(White).&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_SetRenderClear">SDL_RenderClear()</a>&nbsp;takes our renderer and clears it with the white color we set using&nbsp;<code>SDL_SetRenderDrawColor</code>.&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_RenderPresent">SDL_RenderPresent()</a>&nbsp;displays our graphics to the screen&nbsp;(just a white window for now)&nbsp;and then we call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_Delay">SDL_Delay(2000)</a>&nbsp;which specifies a number of milliseconds to wait before moving onto the next piece of code.&nbsp;Normally the rendering code will be in a while loop that will constantly update until the user quits the game,&nbsp;but for simplicities'&nbsp;sake,&nbsp;we will stick with a delay for now.</p><p><a href="https://wiki.libsdl.org/SDL2/SDL_DestroyWindow">SDL_DestroyWindow</a>&nbsp;safely removes our window once we are done with it.&nbsp;If for whatever reason the window was not initialized,&nbsp;it is still safe to call this on the&nbsp;<code>window</code>&nbsp;variable.&nbsp;The same goes for&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_DestroyRenderer">SDL_DestroyRenderer</a>.&nbsp;It does the same thing as&nbsp;<code>SDL_DestroyWindow</code>&nbsp;and cleans up our renderer.&nbsp;Finally we call&nbsp;<a href="https://wiki.libsdl.org/SDL2/SDL_Quit">SDL_Quit</a>&nbsp;which cleans up the systems we initialized before we close our program.</p><p>And that is it,&nbsp;we've created our first window in SDL.&nbsp;In the next tutorial we will look at how to draw text on the screen.</p><p>One last thing to note.&nbsp;I will not be abstracting many things to functions or multiple files in these first few tutorials.&nbsp;I believe it's important when you are learning a new library,&nbsp;to keep it as simple as possible.&nbsp;As the code gets longer this will become a bigger pain point,&nbsp;and that is good.&nbsp;You will have a much clearer picture about what we should abstract,&nbsp;and why we should abstract it,&nbsp;as you become more familiar with SDL.&nbsp;Feel free to come up with your own abstractions as you see fit</p><h2><strong>FAQ</strong></h2><h3><strong>Why do we clear the screen with a color?</strong></h3><p>We clear the screen with a color so that the previous frames pixels don't interfere with the next frames pixels.&nbsp;For example,&nbsp;if we have a square on the screen that we are moving with the&nbsp;<code>WASD</code>&nbsp;keys,&nbsp;if we don't clear the screen,&nbsp;then square will smear across the screen as the old pixels from it's old position are not&nbsp;"wiped"&nbsp;away.</p><h3><strong>Why SDL and not Raylib?</strong></h3><p><a href="https://www.raylib.com/">Raylib</a>&nbsp;is an awesome C library for creating games,&nbsp;and Raysan specifically made it for teaching.&nbsp;He did&nbsp;<a href="https://gist.github.com/raysan5/17392498d40e2cb281f5d09c0a4bf798">a comparison</a>&nbsp;at one point between the two frameworks,&nbsp;though it is a little dated at this point.&nbsp;It is easier to learn and make new FFI bindings for Raylib than it is for SDL and Raylib comes with more convenience features out of the box.&nbsp;You are not making a mistake if you choose Raylib.&nbsp;But SDL has been around over twice as long as Raylib.&nbsp;Many of the open source projects I'm interested in contributing to&nbsp;(Doom Source Ports,&nbsp;<a href="https://gitlab.com/OpenMW/openmw">OpenMW</a>,&nbsp;and others were started before Raylib existed and use SDl2.&nbsp;Since these projects use SDL so will I.&nbsp;SDL2 is also a little lower level than Raylib,&nbsp;and requires you to work at a lower level with it's subsystems.&nbsp;This means instead of placing drawing code between a&nbsp;<code>BeginDrawing</code>&nbsp;and&nbsp;<code>EndDrawing</code>&nbsp;block like in Raylib,&nbsp;you have to set up the renderer,&nbsp;create textures,&nbsp;copy them to the GPU,&nbsp;before finally presenting it to the screen.&nbsp;I find this process to be enlightening.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi&nbsp;&#128075;&nbsp;my name is Diego Crespo and I like to talk about technology,&nbsp;niche programming languages,&nbsp;and AI.&nbsp;I have a&nbsp;<a href="https://twitter.com/deusinmach">Twitter</a>&nbsp;and a&nbsp;<a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>,&nbsp;if you&#8217;d like to follow me on other social media platforms.&nbsp;If you liked the article,&nbsp;consider liking and subscribing.&nbsp;And if you haven&#8217;t why not check out another article of mine listed below!&nbsp;Thank you for reading and giving me a little of your valuable time.&nbsp;A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/sdl-tutorial-part-1-opening-a-window?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p>]]></content:encoded></item><item><title><![CDATA[The continued rise of Handheld gaming]]></title><description><![CDATA[My very first handheld game was probably the ring toss game&#8230; But in all seriousness it was my fathers Game Boy in the late 90s. I distinctly remember playing Star Wars and I don&#8217;t think I ever beat it.]]></description><link>https://www.deusinmachina.net/p/the-continued-rise-of-handheld-gaming</link><guid isPermaLink="false">https://www.deusinmachina.net/p/the-continued-rise-of-handheld-gaming</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 08 Feb 2024 13:00:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iknQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iknQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iknQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iknQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg" width="720" height="405" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:405,&quot;width&quot;:720,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:175507,&quot;alt&quot;:&quot;ring toss water game&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="ring toss water game" title="ring toss water game" srcset="https://substackcdn.com/image/fetch/$s_!iknQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iknQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe58169-1481-4c21-ad6b-9ffc153a5747_720x405.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>My very first handheld game was probably the ring toss game&#8230;&nbsp;But in all seriousness it was my fathers Game Boy in the late 90s.&nbsp;I distinctly remember playing Star Wars and I don&#8217;t think I ever beat it.&nbsp;&nbsp;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QZcr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QZcr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QZcr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg" width="891" height="1081" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1081,&quot;width&quot;:891,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:73169,&quot;alt&quot;:&quot;original game boy&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="original game boy" title="original game boy" srcset="https://substackcdn.com/image/fetch/$s_!QZcr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QZcr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f432658-e9af-450a-b2ed-fbe77cbc03af_891x1081.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Game Boy by&nbsp;<a href="https://commons.wikimedia.org/wiki/User:Evan-Amos">Evan-Amos</a></figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cIC5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cIC5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 424w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 848w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cIC5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png" width="1456" height="1232" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1232,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:642483,&quot;alt&quot;:&quot;star wars for the game boy&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="star wars for the game boy" title="star wars for the game boy" srcset="https://substackcdn.com/image/fetch/$s_!cIC5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 424w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 848w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!cIC5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc14c21d-7a61-4bcf-8270-cc33cf5544ca_1749x1480.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is what peak gaming in 1992 looked like</figcaption></figure></div><p>I remember handheld gaming being all the rage growing up,&nbsp;and I have fond memories of playing on Game Boys,&nbsp;Game Boy Colors,&nbsp;Game Boy Advances,&nbsp;PSPs,&nbsp;and DS'.&nbsp;Like many,&nbsp;after about the PSP era,&nbsp;I moved away from consoles and handhelds in favor of PCs.&nbsp;But since getting back into handheld gaming with my Steam Deck,&nbsp;I was shocked to see there had been a Cambrian explosion of handhelds.&nbsp;Many are from major players in the tech space,&nbsp;though some are from companies I've never heard of.&nbsp;It feels like we are in a renaissance,&nbsp;or,&nbsp;that is what I thought the angle of this article was going to be when I started writing it.&nbsp;But in actually researching handheld history,&nbsp;I've come to the conclusion that while I had abandoned it,&nbsp;it hadn't gone anywhere.</p><h2><strong>A lightning Tour</strong></h2><p>Let's take a look back at one of the earliest handhelds.&nbsp;For the sake of brevity I'll only consider handhelds that could play more than one game,&nbsp;so no Game and Watches,&nbsp;or single game electronics.&nbsp;In this vein the honor to the first handheld gaming console that fits our criteria is the Microvision created in 1979.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ben5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ben5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ben5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ben5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ben5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ben5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg" width="1456" height="1985" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1985,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:363355,&quot;alt&quot;:&quot;microvision&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="microvision" title="microvision" srcset="https://substackcdn.com/image/fetch/$s_!ben5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ben5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ben5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ben5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d7e85e9-4edb-4409-ae44-25d806518376_1920x2618.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Microvision&nbsp;-&nbsp;<a href="https://commons.wikimedia.org/wiki/User:Evan-Amos">Evan-Amos</a></figcaption></figure></div><p>It looked more like the iClicker I had in College than a gaming device,&nbsp;but it had 12 different games that it could play.&nbsp;Clocking in on a CPU that ran at 1kHZ,&nbsp;a frequency I have never seen next to a CPU,&nbsp;It's honestly hugely impressive it could play anything.</p><p>But just 10 years later we would be introduced to one of the most popular handhelds of all time,&nbsp;by one of handheld gaming&#8217;s most prolific supporters,&nbsp;Nintendo.&nbsp;The Game Boy would be a smash hit,&nbsp;bringing handheld gaming to the masses.&nbsp;Nintendo has certainly not slowed down since then and if we look at the timeline from the Game Boy to the Switch we get a history that spans from 1989-2021 with no signs of stopping.</p><ul><li><p><strong>Game Boy</strong>: Released on April 21, 1989, in Japan, July 31, 1989, in North America, and September 28, 1990, in Europe. The OG.</p></li><li><p><strong>Game Boy Pocket</strong>: Released in 1996, it was a smaller, lighter Game Boy that required fewer batteries.</p></li><li><p><strong>Game Boy Light</strong>: Released only in Japan on April 14, 1998, this model featured a backlit screen.</p></li><li><p><strong>Game Boy Color</strong>: Released on October 21, 1998, in Japan, November 18, 1998, in North America, and November 23, 1998, in Europe. Backwards compatible with the Game Boy! Contained a 15-bit color palette instead of the 4 in the original Game Boy.</p></li><li><p><strong>Game Boy Advance</strong>: Released on March 21, 2001, in Japan, June 11, 2001, in North America, and June 22, 2001, in Europe. Backwards compatible again! Hardware that was more powerful than the SNES from a decade prior.</p></li><li><p><strong>Game Boy Advance SP</strong>: Released in February 2003, it featured a front-lit screen and a clamshell design.</p></li><li><p><strong>Game Boy Micro</strong>: Released on September 13, 2005, in Japan, and subsequently in other regions. A slimmer version of the original GBA.</p></li><li><p><strong>Nintendo DS</strong>: Released on November 21, 2004, in North America, December 2, 2004, in Japan, February 24, 2005, in Australia, and March 11, 2005, in Europe. Successor to and backwards compatible with the Game Boy Advance.</p></li><li><p><strong>Nintendo DS Lite</strong>: Released in early 2006, it was a slimmer and lighter version of the original DS.</p></li><li><p><strong>Nintendo DSi</strong>: Released on November 1, 2008, in Japan, and in 2009 in other regions. No slot for GBA Games. Two cameras, SD Card slot, and other enhancements.</p></li><li><p><strong>Nintendo DSi XL/LL</strong>: Released in 2009, it was a DS that larger screens.</p></li><li><p><strong>Nintendo 3DS</strong>: Released on February 26, 2011, in Japan, March 25, 2011, in Europe, March 27, 2011, in North America, and March 31, 2011, in Australia. Successor to the DS with the most notable feature being the 3d graphics, 3 cameras, and AR capabilities.</p></li><li><p><strong>Nintendo 3DS XL</strong>: Released in 2012, this version featured larger screens.</p></li><li><p><strong>Nintendo 2DS</strong>: Released on October 12, 2013, as a budget version of the 3DS without 3D capability.</p></li><li><p><strong>New Nintendo 3DS</strong>: Released on October 11, 2014, in Japan, and 2015 in other regions. Enhanced performance, better 3d, a C-stick, and built in NFC.</p></li><li><p><strong>New Nintendo 3DS XL</strong>: Released alongside the New Nintendo 3DS, with larger screens.</p></li><li><p><strong>New Nintendo 2DS XL</strong>: Released on July 13, 2017, as an upgraded version of the 2DS.</p></li><li><p><strong>Nintendo Switch</strong>: Released on March 3, 2017, a hybrid console, usable as docked as a home console and undocked as a handheld device.</p></li><li><p><strong>Nintendo Switch Lite</strong>: Released on September 20, 2019, features non removeable joycons.</p></li><li><p><strong>Nintendo Switch OLED</strong>: Released on October 8, 2021, it's a Switch, but with a nicer screen.</p></li></ul><p>Phew!&nbsp;That was a lot.&nbsp;While compiling this list a couple of things became apparent to me.</p><ol><li><p>Nintendo has been keeping the handheld dream alive, even after other hardware manufactures had left the space.</p></li><li><p>Nintendo&nbsp;<em>loves</em>&nbsp;to sell you the same handheld over and over again.</p></li></ol><p>Multiple Game Boy's DS'&nbsp;and Switches.&nbsp;I wouldn't be surprised if we see a Switch XL at some point.&nbsp;And you already know there will be a Switch 2 Lite.</p><p>But while Nintendo never stopped making Handhelds,&nbsp;the list of handhelds we got from 1989 to&nbsp;~2013 ranged for weird,&nbsp;wacky,&nbsp;cool,&nbsp;and everything in between.&nbsp;Here are some of them</p><ul><li><p><strong>Atari Lynx (1989)</strong>&nbsp;- First handheld console with a color LCD screen.</p></li><li><p><strong>Sega Game Gear (1990)</strong>&nbsp;- Competitor to the Nintendo Game Boy, known for its backlit color screen.</p></li><li><p><strong>Sega Nomad (1995)</strong>&nbsp;- Handheld version of the Sega Genesis, allowing players to use Genesis cartridges.</p></li><li><p><strong>Tapwave Zodiac (2004)</strong>&nbsp;- Short lived device that functioned as both a PDA and a gaming console.</p></li><li><p><strong>Sony PlayStation Portable (PSP) (2005)</strong>- Known for its powerful hardware, multimedia capabilities, and wide game selection. I had one with a skin covered in green skulls, and it was incredible.</p></li><li><p><strong>GP2X Wiz (2009)</strong>&nbsp;- An open-source, Linux-based handheld console produced by GamePark Holdings.</p></li><li><p><strong>Pandora (2010)</strong>&nbsp;- A combination of a handheld game console and a mini PC, running Linux.</p></li><li><p><strong>Sony PlayStation Vita (2012)</strong>&nbsp;- Successor to the PSP. Featured a touch screen, rear touchpad, and high-quality graphics. Please bring it back Sony.</p></li><li><p><strong>Nvidia Shield Portable (2013)</strong>&nbsp;- An Android-based device that combined a game controller with a screen, capable of streaming games from a PC.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HzSi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HzSi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HzSi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg" width="1200" height="1600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1600,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:291948,&quot;alt&quot;:&quot;raunchy ad for the zodiac tapwave&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="raunchy ad for the zodiac tapwave" title="raunchy ad for the zodiac tapwave" srcset="https://substackcdn.com/image/fetch/$s_!HzSi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HzSi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbc71cad-e207-442e-b909-c270d97077d2_1200x1600.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Yes this was a real Ad.&nbsp;The early 2000s were wild</figcaption></figure></div><p>One interesting thing to note about this time.&nbsp;With devices like the Nvidia Shield,&nbsp;we begin to see the rise of handheld streaming devices.&nbsp;This is a lot more common now with the likes of the PlayStation&nbsp;Portal,&nbsp;and Logitech G Cloud&nbsp;(with an honorable mention to the Steam Link).</p><p>I would be remiss if I didn't at least talk about the most common forms of handheld gaming of our generation,&nbsp;mobile gaming.&nbsp;While I do remember playing games like Dragon's lair on my father's Sprint flip phone...</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!C311!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C311!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 424w, https://substackcdn.com/image/fetch/$s_!C311!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 848w, https://substackcdn.com/image/fetch/$s_!C311!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 1272w, https://substackcdn.com/image/fetch/$s_!C311!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C311!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png" width="1456" height="929" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:929,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1159329,&quot;alt&quot;:&quot;Dragons Lair game&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Dragons Lair game" title="Dragons Lair game" srcset="https://substackcdn.com/image/fetch/$s_!C311!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 424w, https://substackcdn.com/image/fetch/$s_!C311!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 848w, https://substackcdn.com/image/fetch/$s_!C311!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 1272w, https://substackcdn.com/image/fetch/$s_!C311!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbe12686-f3c2-4a64-b984-227480f1236d_1564x998.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It was when we got smartphones where I really saw the quality of mobile gaming blow up.&nbsp;I remember games like Zenonia back in 2009 being awesome.&nbsp;I couldn't believe I was playing such a fully featured rpg right in the palm of my hand at that time.&nbsp;I remember sitting back and playing it for hours on my landscaped iPod in a wooden chair with no cushion,&nbsp;my back and eyes would never permit that now.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!svPe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!svPe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 424w, https://substackcdn.com/image/fetch/$s_!svPe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 848w, https://substackcdn.com/image/fetch/$s_!svPe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!svPe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!svPe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg" width="640" height="363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:363,&quot;width&quot;:640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:105265,&quot;alt&quot;:&quot;Zenonia for the Iphone&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Zenonia for the Iphone" title="Zenonia for the Iphone" srcset="https://substackcdn.com/image/fetch/$s_!svPe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 424w, https://substackcdn.com/image/fetch/$s_!svPe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 848w, https://substackcdn.com/image/fetch/$s_!svPe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!svPe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2957cffa-fbc7-4028-a00e-834b8d117f6c_640x363.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This was pre candy crush too,&nbsp;so the dark patterns were either non existent,&nbsp;or much simpler at the time.&nbsp;You could even buy a game once,&nbsp;and never pay for it again&nbsp;(shocking I know).&nbsp;And remember Infinity Blade?&nbsp;Mobile gaming may have truly peaked in 2010.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!07LC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!07LC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 424w, https://substackcdn.com/image/fetch/$s_!07LC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 848w, https://substackcdn.com/image/fetch/$s_!07LC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 1272w, https://substackcdn.com/image/fetch/$s_!07LC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!07LC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png" width="1456" height="696" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:696,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2990373,&quot;alt&quot;:&quot;Infinity blade mobile game&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Infinity blade mobile game" title="Infinity blade mobile game" srcset="https://substackcdn.com/image/fetch/$s_!07LC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 424w, https://substackcdn.com/image/fetch/$s_!07LC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 848w, https://substackcdn.com/image/fetch/$s_!07LC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 1272w, https://substackcdn.com/image/fetch/$s_!07LC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb420f269-e3ae-426d-bda0-0914aadd42d8_2551x1220.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">No longer available on the App Store :&#8217;(</figcaption></figure></div><p>But if we include phones on this tour,&nbsp;we'd be here all day so let's get back to dedicated handhelds.&nbsp;Not only have we had great handhelds for the last 35 years,&nbsp;if you look at the top 5 best selling consoles of all time...</p><ol><li><p>PlayStation 2</p></li><li><p>Nintendo DS</p></li><li><p>Nintendo Switch</p></li><li><p>Game Boy/Game Boy Color</p></li><li><p>PlayStation 4</p></li></ol><p>We see that three out of the top 5 are actually handhelds.&nbsp;So with that fact,&nbsp;and with this article having mentioned over two dozen handheld devices at this point,&nbsp;It's safe to say handhelds,&nbsp;and handheld gaming,&nbsp;never went away.&nbsp;In fact I'd say it's more popular now that it has ever been!</p><p>The experience is also so much better than it used to be.&nbsp;For one,&nbsp;I don't have to go through dozens of AA batteries a month anymore.&nbsp;And two,&nbsp;they don't feel cut down.&nbsp;Using my previously mentioned Star Wars Game Boy game as an example,&nbsp;I recently found out that this is what the NES version looked like.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!A0mu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!A0mu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 424w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 848w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 1272w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!A0mu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png" width="1177" height="1090" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1090,&quot;width&quot;:1177,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:731239,&quot;alt&quot;:&quot;Star Wars for the NES&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Star Wars for the NES" title="Star Wars for the NES" srcset="https://substackcdn.com/image/fetch/$s_!A0mu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 424w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 848w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 1272w, https://substackcdn.com/image/fetch/$s_!A0mu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf78f498-3c87-4d27-a54c-345b2bcdead2_1177x1090.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">It looks so good!</figcaption></figure></div><p>Shocking!&nbsp;I would have loved to have my Game Boy version look like that back in the 90s.&nbsp;By the Game Boy Advanced era in 2001,&nbsp;we were able to create incredible 2D handheld experiences,&nbsp;but we were only just&nbsp;<em>getting</em>&nbsp;to the point where we could render anything impressive in 3D.&nbsp;Sure you could program a 3D GBA game if you were a literal programming God like Randal Linden,&nbsp;but unless you are willing to write 200,000 lines of highly optimized assembly then we still needed a few generations before this was feasible for your average programmer.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6Hp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6Hp5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 424w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 848w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 1272w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6Hp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png" width="1321" height="883" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:883,&quot;width&quot;:1321,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1023987,&quot;alt&quot;:&quot;quake running on the Game Boy&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="quake running on the Game Boy" title="quake running on the Game Boy" srcset="https://substackcdn.com/image/fetch/$s_!6Hp5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 424w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 848w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 1272w, https://substackcdn.com/image/fetch/$s_!6Hp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec9d493a-6bc0-4ece-8095-fc51f7e88db1_1321x883.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">&nbsp;I don't know how this is even possible</figcaption></figure></div><p>But fast forward to the PSP era,&nbsp;and we were beginning to see what no compromise 3d handheld experiences looked like.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fgn3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fgn3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 424w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 848w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 1272w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fgn3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png" width="1456" height="738" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f264770c-51a2-414c-8473-8c8462faab38_1544x783.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:738,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1020893,&quot;alt&quot;:&quot;Tekken Dark Resurrection&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Tekken Dark Resurrection" title="Tekken Dark Resurrection" srcset="https://substackcdn.com/image/fetch/$s_!fgn3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 424w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 848w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 1272w, https://substackcdn.com/image/fetch/$s_!fgn3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff264770c-51a2-414c-8473-8c8462faab38_1544x783.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And by the time we got to the Switch,&nbsp;it was clear that while certain games might have struggled to hit their 30fps target sometimes,&nbsp;we weren't getting stripped down version of a game originally made for PCs and consoles anymore.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!N6xn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N6xn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!N6xn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg" width="1280" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158807,&quot;alt&quot;:&quot;Breath of the wild screenshot&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Breath of the wild screenshot" title="Breath of the wild screenshot" srcset="https://substackcdn.com/image/fetch/$s_!N6xn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!N6xn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4541c484-e6d9-4fe6-8448-bf6e343cff78_1280x720.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And now in the more modern times&nbsp;(a sentence that will age like milk)&nbsp;we see many other players in the space besides Sony and Nintendo.&nbsp;There are Android,&nbsp;Windows,&nbsp;and Linux based handhelds,&nbsp;some from well known brands,&nbsp;and others from rising stars...</p><ul><li><p><strong>GPD XD</strong>: 2015</p></li><li><p><strong>GPD Win</strong>: 2016</p></li><li><p><strong>GPD XD Plus</strong>: 2018</p></li><li><p><strong>Abernic RG351P</strong>: 2020</p></li><li><p><strong>Retroid Pocketc 2S</strong>: 2020</p></li><li><p><strong>Miyoo Mini</strong>: 2021</p></li><li><p><strong>Ayn Odin</strong>: 2022</p></li><li><p><strong>Steam Deck</strong>: 2022</p></li><li><p><strong>Miyoo Mini +</strong>: 2023</p></li><li><p><strong>Logitech G Cloud</strong>: 2023</p></li><li><p><strong>Lenovo Legion Go</strong>: 2023</p></li><li><p><strong>Ayn Odin 2</strong>: 2023</p></li><li><p><strong>Asus Rog Ally</strong>: 2023</p></li><li><p><strong>Steam Deck OLED</strong>: 2023</p></li><li><p><strong>PlayStation Portal</strong>: 2023</p></li><li><p><strong>Msi Claw</strong>: Sometime in 2024</p></li></ul><p>And it's exciting.&nbsp;It feels like we've hit an inflection point with handhelds.&nbsp;With devices like my Steam Deck,&nbsp;I don't feel like I'm giving anything up when I'm using it.&nbsp;But at the same time,&nbsp;I'm excited for every new iteration.&nbsp;It feels just like how it was in the late 90s and 2000s where every console generation,&nbsp;or graphics card generation,&nbsp;was a noticeable improvement over the last.&nbsp;And with the Switch 2 rumored to be announced later this year,&nbsp;it seems like that excitement isn't going to be slowing down anytime soon.</p><h2><strong>Call To Action &#128227;</strong></h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a> and a <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/the-continued-rise-of-handheld-gaming?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/the-continued-rise-of-handheld-gaming?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;cc0e8204-767c-4c53-8e3f-a17dc3c47295&quot;,&quot;caption&quot;:&quot;In 1996, Mike Harrington and Gabe Newell, two Microsoft employees working on Windows NT, left their jobs to start a game company. They were inspired by Michael Abrash, who had also left Microsoft earlier to go to ID Software and work on Quake. Through their connection to Abrash, Gabe and Mike were able to meet with John Romero of Doom fame. Romero was i&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Evolution of Valve's Source Engine&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-12-28T13:01:01.638Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1730857-5b14-4c03-8628-358977b6b575_1439x566.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/the-evolution-of-valves-source-engine&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:139195252,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:2,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Lets compile Linux DOOM]]></title><description><![CDATA[I'm no Fabien Sanglard]]></description><link>https://www.deusinmachina.net/p/lets-compile-linux-doom</link><guid isPermaLink="false">https://www.deusinmachina.net/p/lets-compile-linux-doom</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 01 Feb 2024 13:00:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pL_S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pL_S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pL_S!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 424w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 848w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 1272w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pL_S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png" width="1456" height="621" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:621,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2770005,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pL_S!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 424w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 848w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 1272w, https://substackcdn.com/image/fetch/$s_!pL_S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd605a-45e9-4e5f-b30f-3df986aa5fcb_2196x937.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In honor of Doom&#8217;s 30th birthday, I decided I would try to compile the Doom source code on GitHub. Since I had no idea what I was doing, I  searched around and found the this incredible video by<a href="https://www.youtube.com/@hot_coffee_guy"> hot_coffee_guy</a>. It has no sound, but by just watching it, and with a little trial and error, I was able to get the game up and running. </p><div id="youtube2-9JgQfQHHhTw" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;9JgQfQHHhTw&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/9JgQfQHHhTw?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>I encountered some challenges along the way, and want to fill in explanations where I can, both as a record for anyone who might experience the same issue, and for my own edification so let&#8217;s get to it!</p><h2>The Setup</h2><p>The first step is to get the source code. It is available in the <a href="https://github.com/id-Software/DOOM">id-software repository</a> here. You can clone it, or fork it, whichever you desire. I decided to make a fork and named it DOOMLEARN.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AQNC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AQNC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 424w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 848w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 1272w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AQNC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png" width="1456" height="820" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:820,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:238946,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AQNC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 424w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 848w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 1272w, https://substackcdn.com/image/fetch/$s_!AQNC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3423e505-abfb-49c9-94f9-cb7b9b51b324_1915x1078.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Using CMake and building with an IDE</h3><p>The first time I did this, I used <code>Make</code> and the <code>Makefile</code> that came with the project. However, on my second round for this article,  I wanted to make code edits using CLion, so I opted to create a <code>CMake</code> file. I&#8217;ve added a <code>CMakeLists.txt</code> file to my version of the project, and if you want to use it, <a href="https://github.com/diego-crespo/DOOMLEARN/blob/master/linuxdoom-1.10/CMakeLists.txt">you can find it here</a>. </p><h3>Using Make</h3><p>If you use <code>Make</code> the setup is already done for you. Just navigate to where you downloaded the DOOM source code, <code>cd</code> into <code>linuxdoom-1.10</code>, and run&#8230; </p><pre><code># the executable automatically writes to a folder called linux
mkdir linux
make</code></pre><p>You can expedite the compilation process by specifying the <code>-j</code> parameter with the desired number of parallel jobs</p><pre><code><code>make -j8</code></code></pre><h2>Getting Started</h2><p>Now that the prep work is out of the way, we need to build the project. You can build it with either <code>Make</code> or <code>CMake</code>. I'll demonstrate the <code>Make</code> method first before transitioning to the <code>CMake</code> build for the rest of the article.</p><pre><code>deca@pop-os:~/programming/c_programming/DOOMLEARN/linuxdoom-1.10$ make -j8
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c doomdef.c -o linux/doomdef.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c doomstat.c -o linux/doomstat.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c dstrings.c -o linux/dstrings.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c i_system.c -o linux/i_system.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c i_sound.c -o linux/i_sound.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c i_video.c -o linux/i_video.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c i_net.c -o linux/i_net.o
gcc   -g -Wall -DNORMALUNIX -DLINUX  -c tables.c -o linux/tables.o
dstrings.c:25:1: warning: &#8216;rcsid&#8217; defined but not used [-Wunused-const-variable=]
   25 | rcsid[] = "$Id: m_bbox.c,v 1.1 1997/02/03 22:45:10 b1 Exp $";
      | ^~~~~
Assembler messages:
Fatal error: can't create linux/dstrings.o: No such file or directory
make: *** [Makefile:91: linux/dstrings.o] Error 1
make: *** Waiting for unfinished jobs....
doomdef.c:26:1: warning: &#8216;rcsid&#8217; defined but not used [-Wunused-const-variable=]
   26 | rcsid[] = "$Id: m_bbox.c,v 1.1 1997/02/03 22:45:10 b1 Exp $";
      | ^~~~~
Assembler messages:
</code></pre><p>After building the project we get a lot of warnings, which is to be expected for a game that came out in 1993, but eventually we hit our first fatal error.</p><pre><code>i_video.c:49:10: fatal error: errnos.h: No such file or directory
   49 | #include &lt;errnos.h&gt;
      |          ^~~~~~~~~~
</code></pre><p>In CLion, since I setup my <code>CMakeLists.txt</code> file, I can build the program in one click by pressing the run button.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cR-c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cR-c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 424w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 848w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 1272w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cR-c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png" width="1435" height="748" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f4e679e1-ad46-4e38-927b-a93497789462_1435x748.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:748,&quot;width&quot;:1435,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112959,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cR-c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 424w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 848w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 1272w, https://substackcdn.com/image/fetch/$s_!cR-c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4e679e1-ad46-4e38-927b-a93497789462_1435x748.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>To make finding errors easier, I recommend suppressing most of the warnings to focus on compilation errors that stop the build. I did this by adding the following commands to my <code>CMakeLists.txt</code> file</p><pre><code>set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-but-set-variable")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-variable")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pointer-to-int-cast")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-const-variable")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable")
</code></pre><p>These commands effectively suppress most of the warnings the project generates. Now, let's address the initial problem&#8230;</p><pre><code><code>i_video.c:49:10: fatal error: errnos.h: No such file or directory
   49 | #include &lt;errnos.h&gt;
      |          ^~~~~~~~~~
</code></code></pre><p>Thankfully our first error is simple. There is no header file called <code>errnos.h</code>. It is <code>errno.h</code> and it exists in the C standard library. To fix this we just have to open the <code>i_video.c</code> file and remove the &#8220;s&#8221; from the header.</p><pre><code>#include &lt;errno.h&gt;</code></pre><p>Now lets recompile the project again. This time we get a different error</p><pre><code>gcc   -Wno-unused-but-set-variable -Wno-pointer-to-int-cast -Wno-unused-const-variable -g -Wall -DNORMALUNIX -DLINUX -g -fdiagnostics-color=always -MD -MT CMakeFiles/linuxxdoom.dir/m_misc.c.o -MF CMakeFiles/linuxxdoom.dir/m_misc.c.o.d -o CMakeFiles/linuxxdoom.dir/m_misc.c.o -c /home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/m_misc.c
/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-<strong>1.10/m_misc.c:257:48: error: initializer element is not constant
  257 |     {"sndserver", (int *) &amp;sndserver_filename, (int) "sndserver"},</strong>
      |                                                ^
/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/m_misc.c:257:48: note: (near initialization for &#8216;defaults[14].defaultvalue&#8217;)
/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/m_misc.c:264:35: error: initializer element is not constant
  264 |     {"mousedev", (int*)&amp;mousedev, (int)"/dev/ttyS0"},
      |                                   ^
/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/m_misc.c:264:35: note: (near initialization for &#8216;defaults[16].defaultvalue&#8217;)
/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/m_misc.c:265:37: error: initializer element is not constant
  265 |     {"mousetype", (int*)&amp;mousetype, (int)"microsoft"},
      |                                     ^</code></pre><p>The issue is related to a cast on the  <code>defaultvalue</code> field in the default_t struct in our <code>m_misc.c</code> file.</p><pre><code>typedef struct
{
    char*&#9;name;
    int*&#9;location;
    int&#9;&#9;defaultvalue;
    int&#9;&#9;scantranslate;&#9;&#9;// PC scan code hack
    int&#9;&#9;untranslated;&#9;&#9;// lousy hack
} default_t;
</code></pre><p>I think what is happening is we are using the pointer to the string as an number, but this won&#8217;t work on 64 bit systems. A pointer is 8 bytes on 64bit systems and and an int holds four. We can fix this by changing the <code>defaultvalue</code> to a <code>long long</code> (or <code>long int</code> whichever you prefer) which will be large enough to hold the address of our pointer</p><pre><code>typedef struct
{
    char*&#9;name;
    int*&#9;location;
    <strong>long long&#9;defaultvalue;</strong>
    int&#9;&#9;scantranslate;&#9;&#9;// PC scan code hack
    int&#9;&#9;untranslated;&#9;&#9;// lousy hack
} default_t;

</code></pre><p>This means we need to make a change on every cast to <code>defaultvalue</code> in the file to be a <code>long long</code> instead of an int. The first is on line 257</p><pre><code>// UNIX hack, to be removed. 
#ifdef SNDSERV
    {"sndserver", (int *) &amp;sndserver_filename, (long long) "sndserver"},
    {"mb_used", &amp;mb_used, 2},
</code></pre><p>The next are on lines 264 and 265</p><pre><code>#ifdef LINUX
    {"mousedev", (int*)&amp;mousedev, (long long)"/dev/ttyS0"},
    {"mousetype", (int*)&amp;mousetype, (long long)"microsoft"},
</code></pre><p>and finally 288-297</p><pre><code>    {"chatmacro0", (int *) &amp;chat_macros[0], (long long) HUSTR_CHATMACRO0 },
    {"chatmacro1", (int *) &amp;chat_macros[1], (long long) HUSTR_CHATMACRO1 },
    {"chatmacro2", (int *) &amp;chat_macros[2], (long long) HUSTR_CHATMACRO2 },
    {"chatmacro3", (int *) &amp;chat_macros[3], (long long) HUSTR_CHATMACRO3 },
    {"chatmacro4", (int *) &amp;chat_macros[4], (long long) HUSTR_CHATMACRO4 },
    {"chatmacro5", (int *) &amp;chat_macros[5], (long long) HUSTR_CHATMACRO5 },
    {"chatmacro6", (int *) &amp;chat_macros[6], (long long) HUSTR_CHATMACRO6 },
    {"chatmacro7", (int *) &amp;chat_macros[7], (long long) HUSTR_CHATMACRO7 },
    {"chatmacro8", (int *) &amp;chat_macros[8], (long long) HUSTR_CHATMACRO8 },
    {"chatmacro9", (int *) &amp;chat_macros[9], (long long) HUSTR_CHATMACRO9 }</code></pre><p>Now let&#8217;s build the project again.</p><pre><code>
<strong>/usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in CMakeFiles/linuxxdoom.dir/i_sound.c.o</strong>
/usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: error adding symbols: bad value
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
</code></pre><p>Cool a linker error! That means that we were able to compile our code to obj files. It looks like a thread local storage error in the way we are using <code>errno</code>. <code>errno</code> is a global variable used in C to indicate the error status of many library functions, particularly those involving system calls. When these functions fail, they typically set <code>errno</code> to an integer value representing what kind of error occurred. Not totally unexpected as we changed the way we handled <code>errno</code> earlier on in the program. The issue is in the <code>i_sound.c</code> so let&#8217;s go there.   </p><p><code>errno</code> is thread safe, but we were using a non standard version of <code>errno</code> in our program. Searching for it in our file we see the offending code on line 166. We have to delete the line <code>extern int errno</code>&#8230;</p><pre><code>myioctl
( int&#9;fd,
  int&#9;command,
  int*&#9;arg )
{   
    int&#9;&#9;rc;
    extern int&#9;errno;
    
    rc = ioctl(fd, command, arg);  
    if (rc &lt; 0)
    {
&#9;fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command);
&#9;fprintf(stderr, "errno=%d\n", errno);
&#9;exit(-1);
    }
}

</code></pre><p>and then include the <code>errno.h</code> header file like we&#8217;ve done before. Then we will be using the errno value that comes with the standard library. </p><pre><code>#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;sys/errno.h&gt;
</code></pre><p>Building it again and we get an executable!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XujO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XujO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 424w, https://substackcdn.com/image/fetch/$s_!XujO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 848w, https://substackcdn.com/image/fetch/$s_!XujO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 1272w, https://substackcdn.com/image/fetch/$s_!XujO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XujO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png" width="1456" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118078,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XujO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 424w, https://substackcdn.com/image/fetch/$s_!XujO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 848w, https://substackcdn.com/image/fetch/$s_!XujO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 1272w, https://substackcdn.com/image/fetch/$s_!XujO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83db55b6-d8a1-4d90-8c95-09ee9e9d6ce4_1727x571.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Buuut it will segfault when we try to run it</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SZo8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SZo8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 424w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 848w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 1272w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SZo8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png" width="1456" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:119909,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SZo8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 424w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 848w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 1272w, https://substackcdn.com/image/fetch/$s_!SZo8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59533eaa-bff6-4699-89ca-d8237a6ff42f_1727x571.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>What is the error saying?  No files found? Let&#8217;s look where this error is called</p><pre><code>void W_InitMultipleFiles (char** filenames)
{&#9;
    int&#9;&#9;size;
    
    // open all the files, load headers, and count lumps
    numlumps = 0;

    // will be realloced as lumps are added
    lumpinfo = malloc(1);&#9;

    for ( ; *filenames ; filenames++)
&#9;W_AddFile (*filenames);

    if (!numlumps)
&#9;I_Error ("W_InitFiles: no files found");
    
    // set up caching
    size = numlumps * sizeof(*lumpcache);
    lumpcache = malloc (size);
    
    if (!lumpcache)
&#9;I_Error ("Couldn't allocate lumpcache");

    memset (lumpcache,0, size);
}
</code></pre><p>Line 292 of <code>w_wad.c</code> is where this function is defined, but where is it used? Using our IDE we find its first usage in <code>d_main.c</code> in line 1021</p><pre><code>    W_InitMultipleFiles (wadfiles);</code></pre><p>The variable <code>wadfiles</code> is an array of wadfiles that are defined earlier in our <code>d_main.c</code> on line 37. We set the array of wadfiles in our function called <code>D_AddFile</code> on line 543</p><pre><code>void D_AddFile (char *file)
{
    int     numwadfiles;
    char    *newfile;
&#9;
    for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
&#9;;

    newfile = malloc (strlen(file)+1);
    strcpy (newfile, file);
&#9;
    wadfiles[numwadfiles] = newfile;
}
</code></pre><p>And our first usage of our <code>D_AddFile</code> comes on line 621</p><pre><code>    if (M_CheckParm ("-shdev"))
    {
&#9;gamemode = shareware;
&#9;devparm = true;
&#9;D_AddFile (DEVDATA"doom1.wad");
&#9;D_AddFile (DEVMAPS"data_se/texture1.lmp");
&#9;D_AddFile (DEVMAPS"data_se/pnames.lmp");
&#9;strcpy (basedefault,DEVDATA"default.cfg");
&#9;return;
    }</code></pre><p>Hmm seems like we have a bunch of parameters which tell Doom where the wadfile is. Looking further up the lines of source code, we get our indication of what we need to do</p><pre><code>#ifdef NORMALUNIX
    char *home;
    char *doomwaddir;
    doomwaddir = getenv("DOOMWADDIR");
    if (!doomwaddir)
&#9;doomwaddir = ".";

    // Commercial.
    doom2wad = malloc(strlen(doomwaddir)+1+9+1);
    sprintf(doom2wad, "%s/doom2.wad", doomwaddir);

    // Retail.
    doomuwad = malloc(strlen(doomwaddir)+1+8+1);
    sprintf(doomuwad, "%s/doomu.wad", doomwaddir);
    
    // Registered.
    doomwad = malloc(strlen(doomwaddir)+1+8+1);
    sprintf(doomwad, "%s/doom.wad", doomwaddir);
</code></pre><p>It appears that we can set an environment variable to tell DOOM where to look for our wad. If we don&#8217;t set this variable, it will assume it is in whatever directory the wadfile is called. That&#8217;s useful information, but before we can do anything with that, we need to get an actual wad file.</p><h2>Getting a DOOM WAD</h2><p>There are two ways you can get this.</p><ol><li><p>If you don&#8217;t own DOOM you can go to the <a href="https://www.doomworld.com/classicdoom/info/shareware.php">doomworld website</a> and <a href="http://www.doomworld.com/3ddownloads/ports/shareware_doom_iwad.zip">download the shareware version</a> ( this is a downloadable link)</p></li><li><p>If you own a copy of DOOM, get the wad from the game files</p></li></ol><p>If you download the shareware version you will want to rename the version from DOOM1.wad to doom1.wad (that&#8217;s the string the code looks for), and then follow the steps in the next section. I own DOOM on GOG so I will outline how do get the wad file from there because it requires a few steps. First go to your GOG library and find your DOOM Files</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rIg3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rIg3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 424w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 848w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 1272w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rIg3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png" width="1456" height="1039" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1039,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1872053,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rIg3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 424w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 848w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 1272w, https://substackcdn.com/image/fetch/$s_!rIg3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50982bda-427f-4398-bfe7-6e3c1fd1e5bf_2680x1912.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Clicking on the 18Mb Ultimate Doom Link will download the game. In my downloads I now have a file called <code>setup_the_ultimate_doom_1.9_(28044).exe</code>. To get the wad from the .exe, I need to extract it using a tool called <code>innoextract</code>.  Make a folder called doom_unpack, and move the <code>setup.exe</code> to it. Once that is done, in the terminal run</p><pre><code>innoextract setup_the_ultimate_doom_1.9_(28044).exe</code></pre><p>Doing this will extract all the files in the game including our DOOM.WAD</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6xY2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6xY2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 424w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 848w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 1272w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6xY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png" width="1456" height="568" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:568,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:122611,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6xY2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 424w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 848w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 1272w, https://substackcdn.com/image/fetch/$s_!6xY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8b7e9f4-ea44-4b5a-b7fb-15c44d34e43e_1611x628.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Remember! In the code, <code>doom.wad</code> is all lowercase. Make sure to change the name!</p><pre><code>// looking for lowercase doom
D_AddFile (DEVDATA"doom.wad");</code></pre><h2>Once you have the doom1.wad or doom.wad</h2><p>After moving our <code>doom.wad</code> into our <code>linuxdoom-1.10/linux</code> folder (where the executable is), lets start running our code again in our IDE. </p><pre><code>V_Init: allocate screens.
M_LoadDefaults: Load system defaults.
Z_Init: Init zone memory allocation daemon. 
W_Init: Init WADfiles.
<strong>Error: W_InitFiles: no files found</strong></code></pre><p>What gives! The error is still there? Before you freak out, it&#8217;s because of the way the IDE is calling the executable and the paths. If you manually <code>cd</code> into the <code>linux</code> folder, and run the executable (with the doom1 or doom wad in the same folder) you will see two things. </p><pre><code>V_Init: allocate screens.
M_LoadDefaults: Load system defaults.
Z_Init: Init zone memory allocation daemon. 
W_Init: Init WADfiles.
 adding ./doom.wad
===========================================================================
                 Commercial product - do not distribute!
         Please report software piracy to the SPA: 1-800-388-PIR8
===========================================================================
M_Init: Init miscellaneous info.
R_Init: Init DOOM refresh daemon - [.Segmentation fault (core dumped)
</code></pre><p>One is that the game successfully added the wad, and two, that we have a new error. If you remember back in the code that deals with the DOOM wad, there was a section where it checked the DOOMWADDIR environment variable, which sets the path to our DOOMWADDIR.</p><pre><code>    doomwaddir = getenv("DOOMWADDIR");
    if (!doomwaddir)
&#9;doomwaddir = ".";</code></pre><p>Let&#8217;s try setting that environment variable. Since this happens during the &#8220;run&#8221; phase of the program, we have to make sure the environment variable is set during that phase in our IDE</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!htsC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!htsC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 424w, https://substackcdn.com/image/fetch/$s_!htsC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 848w, https://substackcdn.com/image/fetch/$s_!htsC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 1272w, https://substackcdn.com/image/fetch/$s_!htsC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!htsC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png" width="1456" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:276417,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!htsC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 424w, https://substackcdn.com/image/fetch/$s_!htsC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 848w, https://substackcdn.com/image/fetch/$s_!htsC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 1272w, https://substackcdn.com/image/fetch/$s_!htsC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42a03dc5-df1b-4c68-9b46-a86e5a854b1c_2746x1029.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Since I&#8217;m using Clion this requires clicking the drop down next to the hammer icon and clicking &#8220;Edit Configurations&#8221;. This will open up a window that will allow me to set an environment variable.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fgw0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fgw0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 424w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 848w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fgw0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png" width="1456" height="879" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:879,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:189006,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fgw0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 424w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 848w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!fgw0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb543bcdf-dd52-4063-a5de-717bb3f26787_1919x1158.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you are following along using Make and the terminal the same effect can be had by just running this code before running the executable</p><pre><code>export DOOMWADDIR=/path/to/folder/where/doom.wad/is</code></pre><p>After making this change, you should see a new erro when you build the project.</p><pre><code>M_LoadDefaults: Load system defaults.
Z_Init: Init zone memory allocation daemon. 
W_Init: Init WADfiles.
 adding /home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/doom.wad
===========================================================================
                 Commercial product - do not distribute!
         Please report software piracy to the SPA: 1-800-388-PIR8
===========================================================================
M_Init: Init miscellaneous info.
R_Init: Init DOOM refresh daemon - [.
Process finished with exit code 139 (interrupted by signal 11:SIGSEGV)
</code></pre><p>Progress! Now it&#8217;s crashing on the R_Init DOOM step. Which is called on line 1095 in <code>d_main.c</code></p><pre><code>    printf ("R_Init: Init DOOM refresh daemon - ");
    R_Init ();</code></pre><p>The definition of this function is defined in line 773 in <code>r_main.c</code></p><pre><code>void R_Init (void)
{
    R_InitData ();
    printf ("\nR_InitData");
    R_InitPointToAngle ();
    printf ("\nR_InitPointToAngle");
    R_InitTables ();
    // viewwidth / viewheight / detailLevel are set by the defaults
</code></pre><p>Considering that I didn&#8217;t see the <code>printf ("\nR_InitData")</code> in the terminal, I&#8217;m assuming the crash was in R_InitData. That is defined on line 654 of <code>r_data.c</code></p><pre><code>void R_InitData (void)
{
    R_InitTextures ();
    printf ("\nInitTextures");
    R_InitFlats ();
    printf ("\nInitFlats");
    R_InitSpriteLumps ();
    printf ("\nInitSprites");
    R_InitColormaps ();
    printf ("\nInitColormaps");
}</code></pre><p>More printfs that didn&#8217;t print to the terminal, The errors must be in <code>R_InitTextures</code>.</p><pre><code>I_Init: Setting up machine state.
Could not start sound server [sndserver]
D_CheckNetGame: Checking network game status.
startskill 2  deathmatch: 0  startmap: 1  startepisode: 1
player 1 of 1 (1 nodes)
S_Init: Setting up sound.
S_Init: default sfx volume 8
HU_Init: Setting up heads up display.
ST_Init: Init status bar.
Error: xdoom currently only supports 256-color PseudoColor screens</code></pre><p>I admit this is where I got stuck, but <a href="https://youtu.be/9JgQfQHHhTw?t=364">hot_coffee_guy&#8217;s video</a> we see that we have to make a few changes in <code>r_data.c</code> including&#8230;</p><p>Adding and include for  &lt;stdint.h&gt; at the top of the file.</p><pre><code>static const char
rcsid[] = "$Id: r_data.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";

#include &lt;stdint.h&gt;

#include "i_system.h"</code></pre><p>This allows the use of fixed width integer types like <code>intptr_t</code>. These types have a consistent size across different platforms. Next we have to change our <code>maptexture_t</code> struct to be an <code>int columndirectory</code> instead of an <code>void       **columndirectory</code></p><pre><code>typedef struct
{
    char&#9;&#9;name[8];
    boolean&#9;&#9;masked;&#9;
    short&#9;&#9;width;
    short&#9;&#9;height;
    int                     columndirectory;
    short&#9;&#9;patchcount;
    mappatch_t&#9;patches[1];
} maptexture_t;

</code></pre><p>Next we remove the hard coding of the pointer sizes to the textures on line 484-487 in our <code>r_data.c</code>. We can do this and make the code more flexible using the <code>sizeof</code> operator</p><pre><code><code>    textures = Z_Malloc (numtextures*sizeof(*textures), PU_STATIC, 0);
    
texturecolumnlump = Z_Malloc (numtextures*sizeof(*texturecolumnlump), PU_STATIC, 0);
    texturecolumnofs = Z_Malloc (numtextures*sizeof(*texturecolumnofs), PU_STATIC, 0);
    texturecomposite = Z_Malloc (numtextures*sizeof(*texturecomposite), PU_STATIC, 0);
</code></code></pre><p>On line 644 in our <code>R_InitColormaps</code> function, we want to change the cast from  <code>int</code> to an <code>intptr_t</code>. This concludes are changed to <code>r_data.c</code></p><pre><code>void R_InitColormaps (void)
{
    int&#9;lump, length;
    
    // Load in the light tables, 
    //  256 byte align tables.
    lump = W_GetNumForName("COLORMAP"); 
    length = W_LumpLength (lump) + 255; 
    colormaps = Z_Malloc (length, PU_STATIC, 0); 
    colormaps = (byte *)( ((intptr_t)colormaps + 255)&amp;~0xff); 
    W_ReadLump (lump,colormaps); 
}
</code></pre><p>The next file we wanto to change is <code>r_draw.c</code>. In <code>r_draw.c</code> we want to add the <code>#include &lt;stdint.h&gt;</code> to the top again. Then we want to jump down to line 459 with the function  <code>R_InitTranslationTables</code> and change our cast from an <code>int</code> to an <code>intptr_t</code> for the <code>translationtables</code> variable on line 464</p><pre><code><code>    translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
    translationtables = (byte *)(( (intptr_t)translationtables + 255 )&amp; ~255);
</code></code></pre><p>Moving back to <code>r_data.c</code>, We then cast the variable <code>colormaps</code> in the function <code>R_InitColormaps </code>to an <code>intptr_t</code></p><pre><code>//
void R_InitColormaps (void)
{
    int&#9;lump, length;
    
    // Load in the light tables, 
    //  256 byte align tables.
    lump = W_GetNumForName("COLORMAP"); 
    length = W_LumpLength (lump) + 255; 
    colormaps = Z_Malloc (length, PU_STATIC, 0); 
    colormaps = (byte *)( (<strong>(intptr_t)</strong>colormaps + 255)&amp;~0xff); 
    W_ReadLump (lump,colormaps); 
}
</code></pre><p>and again we add <code>sizeof</code> to make our code more flexible and allocate the right amount of memory.</p><pre><code><code>    texturecolumnlump = Z_Malloc (numtextures*sizeof(*texturecolumnlump), PU_STATIC, 0);
    texturecolumnofs = Z_Malloc (numtextures*sizeof(*texturecolumnofs), PU_STATIC, 0);
    texturecomposite = Z_Malloc (numtextures*sizeof(*texturecomposite), PU_STATIC, 0);

</code></code></pre><p>Now with all of that done we compile and run our executable again. No linking errors or segfaults this time! So everything was successful.  Let&#8217;s see what happens when we run our program</p><pre><code>Could not start sound server [/home/deca/programming/c_programming/DOOMLEARN/linuxdoom-1.10/sndserver]
S_Init: default sfx volume 8
<strong>Error: xdoom currently only supports 256-color PseudoColor screens</strong></code></pre><p>A new error! We are making more progress! This one is because the original DOOM was designed to run in an 8-bit color mode, which is not natively supported by most modern systems. Modern displays and graphics interfaces usually operate at much higher color depths (like 24-bit or 32-bit). When you try to run an 8-bit application on a system that doesn't support this color depth natively, you can get color distortion and errors.</p><p>I can check what my current color depth is by using <code>xdpyinfo.</code>This is a commandline utility on Linux that displays information about an X server. The X server is part of the X Window System which provides the framework for creating and managing graphical user interfaces on Linux desktops. </p><p><code>xdpyinfo</code> provides various details like screen dimensions, supported visuals, and color depth. Since we are only interested in the color depth we can <code>grep</code> for it in the output.</p><pre><code>xdpyinfo | grep 'depth of root window'
  depth of root window:    24 planes
</code></pre><p>So my X server is running with a 24-bit color depth and I need to run at 8-bit. What do I do? Thankfully I can get around this by starting a Separate X Session. By starting a new session with specific parameters, I can configure it to use an 8-bit color depth, which will allow DOOM to display correctly. <code>Xephyr</code> is the tool I will use to do this. It is a nested X server that operates as a client to a host X server. By using <code>Xephyr</code>, I can construct a display with the characteristics I need. Type this into the terminal</p><pre><code>sudo Xephyr :2 -ac -screen 640x480x8</code></pre><p>What this is doing, is executing Xephyr as a superuser, without access control (-ac), with a screen resolution of 640x480 pixels and a color depth of 8-bits (x8).  The result is an empty display. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H0Ag!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H0Ag!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 424w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 848w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 1272w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H0Ag!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png" width="634" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:634,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13020,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!H0Ag!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 424w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 848w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 1272w, https://substackcdn.com/image/fetch/$s_!H0Ag!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3428ee5-5f52-4b46-85b2-8e448b6efc0e_634x555.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now we need to make sure the game launches in this second display. If you are following along in the IDE, you can set the <code>DISPLAY</code> environment variable to <code>:2</code>, which is the first argument we passed to <code>Xephyr</code>. If you are in a terminal, just type this , before launching the DOOM executable</p><pre><code><code>DISPLAY=:2</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cGuD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cGuD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 424w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 848w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cGuD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png" width="1456" height="879" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ade861a0-a881-4b12-896f-478484b78d30_1919x1158.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:879,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:166199,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cGuD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 424w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 848w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!cGuD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fade861a0-a881-4b12-896f-478484b78d30_1919x1158.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When we run our executable it should pop up in the <code>Xephyr</code> window. But all the colors will be messed up.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4dod!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4dod!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 424w, https://substackcdn.com/image/fetch/$s_!4dod!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 848w, https://substackcdn.com/image/fetch/$s_!4dod!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 1272w, https://substackcdn.com/image/fetch/$s_!4dod!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4dod!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png" width="647" height="536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:536,&quot;width&quot;:647,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38506,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4dod!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 424w, https://substackcdn.com/image/fetch/$s_!4dod!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 848w, https://substackcdn.com/image/fetch/$s_!4dod!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 1272w, https://substackcdn.com/image/fetch/$s_!4dod!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ce7c15-ab05-41c1-a389-ad961172f195_647x536.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Googling this error, leads to this <a href="https://stackoverflow.com/questions/60823500/x-server-8-bit-pseudo-color-initiating-the-palette-linux-xdoom">stack overflow</a> post that highlights the solution. We want to add a call to XInstallColormap near line 820 before the call to <code>XDefineCursor</code> in the <code>i_video.c</code> file. The <code>XInstallColormap</code> function installs the specified colormap into the X server's colormap database. Once installed, the colormap becomes available for use by windows on the specified X server. This means that any window that is using this colormap will be able to display colors from that colormap, fixing our messed up colors.</p><pre><code>XInstallColormap( X_display, X_cmap );</code></pre><p>Finally we have to change this line in <code>p_setup.c</code>  on line 536</p><pre><code>linebuffer = Z_Malloc (total*sizeof(*linebuffer), PU_LEVEL, 0);</code></pre><p>Now we run the executable for one final time and&#8230;. It works! The game is running!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aRd3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aRd3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 424w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 848w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 1272w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aRd3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png" width="1107" height="947" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/892691c2-9858-420d-8009-46326f8fc634_1107x947.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:947,&quot;width&quot;:1107,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:499409,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aRd3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 424w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 848w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 1272w, https://substackcdn.com/image/fetch/$s_!aRd3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F892691c2-9858-420d-8009-46326f8fc634_1107x947.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>On my 4k monitor the screen is waay too small, but I&#8217;m just happy it&#8217;s running at all.</p><p>While this was an interesting exercise, and a good way to see how to organize large C projects, If you want to actually play vanilla Doom on modern hardware, you should use <a href="https://github.com/chocolate-doom/chocolate-doom">Chocolate Doom</a> ( a pun on Vanilla Doom). The project aims to accurately reproduce the game so that it can run on new hardware, <em>but without altering gameplay</em>. They are so dedicated to this that they have a <a href="https://github.com/chocolate-doom/chocolate-doom/blob/master/NOT-BUGS.md">NOT-BUGS.md</a>, for bugs that you would experience in the original game, that they won&#8217;t fix. <br>As a fun fact this is the DOOM source port that <a href="https://www.youtube.com/@ModernVintageGamer">Modern Vintage Gamer</a> used to port DOOM to the Nintendo Switch. It&#8217;s simpler than other source ports like <a href="https://github.com/ZDoom/gzdoom">GZDoom</a>, which while much more feature packed, is much more difficult ot port</p><div id="youtube2-F4Dv32-PoU4" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;F4Dv32-PoU4&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/F4Dv32-PoU4?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Also if you&#8217;d like to look at the changes I made for this project you can find then on my <a href="https://github.com/diego-crespo/DOOMLEARN">GitHub</a>. You can see the specific changes I made compared to the original code using <a href="https://github.com/id-Software/DOOM/compare/master...diego-crespo:DOOMLEARN:master">this link</a>.</p><p>And if you want to know more about the DOOM source code from someone who actually knows what there doing, might I point you to Fabien Sanglard and his <a href="https://fabiensanglard.net/gebbdoom/">Game Engine Black Book: DOOM</a>. It goes over the history of Id Software, the hardware in computers at the time, and of course lots of information about the DOOM Engine internals. It is well worth the read and price.</p><h2>Call To Action &#128227;</h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a> and a <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/lets-compile-linux-doom?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/p/lets-compile-linux-doom?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;7051d33d-fd8a-4549-8fd7-fff61d88eb8a&quot;,&quot;caption&quot;:&quot;In 1996, Mike Harrington and Gabe Newell, two Microsoft employees working on Windows NT, left their jobs to start a game company. They were inspired by Michael Abrash, who had also left Microsoft earlier to go to ID Software and work on Quake. Through their connection to Abrash, Gabe and Mike were able to meet with John Romero of Doom fame. Romero was i&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Evolution of Valve's Source Engine&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-12-28T13:01:01.638Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1730857-5b14-4c03-8628-358977b6b575_1439x566.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/the-evolution-of-valves-source-engine&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:139195252,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Small Joys when Programming]]></title><description><![CDATA[I used to paint Warhammer 40K mini figures, and one of the things I always enjoyed about the hobby, was building up my toolkit of home brewed accessories that I would use to paint.]]></description><link>https://www.deusinmachina.net/p/small-joys-when-programming</link><guid isPermaLink="false">https://www.deusinmachina.net/p/small-joys-when-programming</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 25 Jan 2024 13:01:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-suQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-suQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-suQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 424w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 848w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 1272w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-suQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif" width="1456" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1880031,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-suQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 424w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 848w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 1272w, https://substackcdn.com/image/fetch/$s_!-suQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbed5c08a-92c4-40ae-8a3a-80cf39c9ac63.heif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Skitarii Rangers</figcaption></figure></div><p>I used to paint Warhammer 40K mini figures, and one of the things I always enjoyed about the hobby, was building up my toolkit of home brewed accessories that I would use to paint. During my time painting, I repurposed a fishing tackle box as a mobile painting station, used bamboo spice racks for organizing my paints, and had the big brain idea of drilling magnets into my paintbrush handles so I could hang them for storage. I even crafted my own washes from diluted inks. My personal workflow fixed deficiencies I encountered over the course of years of painting.</p><p>This concept of customization is something I&#8217;ve developed as I become a more seasoned programmer as well. From configuring custom key bindings in Emacs, to writing little scripts that automate problems only I have, and agonizing over the ideal keyboard for programming, I&#8217;ve been meticulously honing my programming environment for years.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pxVj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pxVj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 424w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 848w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 1272w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pxVj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png" width="1456" height="1231" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1231,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:274228,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pxVj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 424w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 848w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 1272w, https://substackcdn.com/image/fetch/$s_!pxVj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd29b82-29b0-4c71-9766-c564a229a9d7_1790x1513.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">517 lines and counting!</figcaption></figure></div><p>Even the Operating System my code runs on has not escaped customization. People have asked me,  &#8220;<em>What if you are working on a machine that isn&#8217;t set up with your workflow? </em>&#8221;, as if I would somehow be unable to work in that environment. Sure there might be some pain, but it&#8217;s not like I would suddenly have forgotten how to program. </p><p>This reminds me of an anecdote of my CTO a few years ago. He was using my Macbook and trying to copy and paste something out of my terminal. His Mac was set up to copy as soon as the mouse was done highlighting, but mine wasn&#8217;t. He kept going to paste the output into another program and getting nothing. It took him a few tries to realize what was going on, but he got it eventually. So sure, my muscle memory might betray me in the beginning, but after a time things will go smoothly again. Plus I like to think it&#8217;s good for my brain. You know, neuroplasticity and stuff.</p><p>I consider these difficulties a blessing. It makes me appreciate more what I have built, which otherwise spends most of its day unappreciated in the background. It&#8217;s also a sentiment that can be applied in other domains as well. James Hoffman, a World Barista Champion turned coffee YouTuber, touches on this in his video <a href="https://www.youtube.com/watch?v=tU1y7hBSgiY">What No One Tells You About Learning To Taste</a></p><div id="youtube2-tU1y7hBSgiY" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;tU1y7hBSgiY&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/tU1y7hBSgiY?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>As someone who worked tirelessly to achieve perfection in coffee, he realized that there we downsides that were making him unhappy. He avoided bad coffee and was a burden on his friends due to his high expectations around it. But he realized that he could still enjoy good coffee. He just needed to change his perspective. He said&#8230;</p><blockquote><p>In the case of coffee I started to drink bad coffee.  Now, I didn't go and seek it out, but when it was gonna happen I just let it happen.</p></blockquote><p>I think that&#8217;s a healthy way of thinking about it. And, bringing this back to programming, the inability to always work in your preferred environment, should not rob you of the little things that make programming enjoyable. Programming is as much an art as science, and a little bit of personal expression is always fun. So remember&#8230;</p><blockquote><p>Without a little ugliness there can be no beauty</p><p>- James Hoffman</p></blockquote><p>And go fiddle with some customizations.</p><h2>Call To Action &#128227;</h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a> and a <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/contemplating-loss-in-the-digital?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMDA1NTI0NjQsInBvc3RfaWQiOjEzNzEyNzc4MywiaWF0IjoxNjk1MzA3NDMzLCJleHAiOjE2OTc4OTk0MzMsImlzcyI6InB1Yi0xMTQ2MzU5Iiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.xfTsuo9K9txQ2hSv0AsAPTMqJm3sx3EVKCy-A-PvuPo&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.deusinmachina.net/p/contemplating-loss-in-the-digital?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMDA1NTI0NjQsInBvc3RfaWQiOjEzNzEyNzc4MywiaWF0IjoxNjk1MzA3NDMzLCJleHAiOjE2OTc4OTk0MzMsImlzcyI6InB1Yi0xMTQ2MzU5Iiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.xfTsuo9K9txQ2hSv0AsAPTMqJm3sx3EVKCy-A-PvuPo"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;91ba426d-b6c7-43cb-b222-b4a6748bc5b0&quot;,&quot;caption&quot;:&quot;Computing technology has undergone significant transformations since its initial accessibility to the masses. One particular evolution that stands out is the shift from 8-bit to 64-bit computing architectures. I still vividly remember my first encounter with these terms during my childhood, while playing on my father's Sega Genesis. There &#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Evolution of Computing: From 8-bit to 64-bit&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-08-31T12:00:41.499Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba94e2-ea1f-4b51-bb11-987e1de4c893_720x510.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/the-evolution-of-computing-from-8&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:136578749,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:3,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Gambit-C: Embedding C code directly in Scheme]]></title><description><![CDATA[Every programming language bills itself as a general purposes programming language, but that always comes with tradeoffs.]]></description><link>https://www.deusinmachina.net/p/gambit-c-scheme-and-c-a-match-made</link><guid isPermaLink="false">https://www.deusinmachina.net/p/gambit-c-scheme-and-c-a-match-made</guid><dc:creator><![CDATA[Diego Crespo]]></dc:creator><pubDate>Thu, 18 Jan 2024 13:00:43 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="3409" height="3553" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3553,&quot;width&quot;:3409,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;black horse chess piece near roque chess piece&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="black horse chess piece near roque chess piece" title="black horse chess piece near roque chess piece" srcset="https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1560174038-da43ac74f01b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOXx8a25pZ2h0JTIwY2hlc3MlMjBwaWVjZXxlbnwwfHx8fDE3MDQ0MTMwOTR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@m4quuv">Piotr Makowski</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><p>Every programming language bills itself as a general purposes programming language, but that always comes with tradeoffs. Working in a systems programming language gives you access to pointers and raw memory, affording you fine grained control over your code. However, this comes at the cost of slower development and platform specific headaches. Working in a high level programming language likes Python lets you crank out code quickly, but the performance suffers as you are many layers removed from the hardware. So if one programming language can&#8217;t cover all of your needs, how about two? One for high level programming, and one for low level programming? Thankfully just about every language has a way of interacting with C code through a foreign interface. But some make that easier than others. Enter Gambit-C.</p><p>Gambit-C is a Scheme that compiles to C code, and can be built using a C compiler. There are two ways of using C code in Gambit. One is calling C functions in Gambit, the other is by calling Gambit code from C. Lets look at both.</p><h2>Using C code in Gambit</h2><p>Gambit defines 5 special forms for working with C data</p><ol><li><p><code>c-declare</code></p></li><li><p><code>c-lambda</code></p></li><li><p><code>c-define</code></p></li><li><p><code>c-initialize</code></p></li><li><p><code>c-define-type</code></p></li></ol><p>These are executed during the &#8220;C phase&#8221; of a Gambit-C program, before the execution of Scheme code. Here is how you would use them.</p><h3>C-Declare</h3><p>Lets create an empty file called <code>embed.scm</code> and save it.  We can compile this with the Gambit compiler <code>gsc</code> with the <code>-c</code> flag to see the corresponding C file that is created.</p><pre><code>gsc -c embed.scm </code></pre><p>The resulting C file contains preprocessor defines, information about the version of Gambit and an include for <code>gambit.h</code>. Here is a portion of what that file looks like</p><pre><code>#ifdef ___LINKER_INFO
; File: "embed.c", produced by Gambit v4.9.3
(
409003
(C)
"embed"
(("embed"))
(
"embed"
)
(
)
(
"embed#"
)
(
)
(
)
 ()
)
#else
#define ___VERSION 409003
#define ___MODULE_NAME "embed"
#define ___LINKER_ID ___LNK_embed
#define ___MH_PROC ___H_embed
#define ___SCRIPT_LINE 0
#define ___SYMCOUNT 1
#define ___GLOCOUNT 1
#define ___SUPCOUNT 1
#define ___SUBCOUNT 1
#define ___LBLCOUNT 2
#define ___MODDESCR ___REF_SUB(0)
#include "gambit.h"</code></pre><p><code>c-declare</code> is a special form that allows us to write our own includes, function declarations and variable declarations in the resulting C file. The code defined here can be used in the rest of our <code>c-</code>special forms.</p><p>Let&#8217;s test this out by adding a simple <code>c-declare</code> to our <code>embed.scm</code> file that includes <code>stdio.h</code></p><pre><code>(c-declare #&lt;&lt;c-declare-end
#include &lt;stdio.h&gt;
c-declare-end
)</code></pre><p>Now if we compile our code with the same flags as last time</p><pre><code>gsc -c embed.scm</code></pre><p>We see that <code>stdio.h</code> is now included in our <code>embed.c</code> file.</p><pre><code>___BEGIN_SUB
 ___DEF_SUB(___X0)
___END_SUB




#include &lt;stdio.h&gt;



#undef ___MD_ALL
#define ___MD_ALL ___D_R0 ___D_R1</code></pre><h2>C-Lambda</h2><p>C-lambda allows you to create a Scheme procedure that corresponds to a C function, or a sequence of C code. It is used to bridge between Scheme and C, allowing you to call C functions or execute C code directly from Scheme. It has 3 parts.</p><ol><li><p>A list of types for each argument the C function expects.</p></li><li><p>The type for the value the C function returns.</p></li><li><p>The body with the name of the C function or a string of C code to execute. </p></li></ol><p>Since we defined <code>stdio.h</code> in the <code>c-declare</code> section, lets write a simple hello world program in our <code>c-lambda</code>.</p><pre><code>(c-declare #&lt;&lt;c-declare-end
#include &lt;stdio.h&gt;
c-declare-end

)

((c-lambda () void
#&lt;&lt;c-lambda-end
printf("Hello World!\n");
c-lambda-end
))
</code></pre><p>Now we compile our Scheme code with gsc</p><pre><code>gsc -exe embed.scm</code></pre><p>and execute to get our Hello World!</p><pre><code>./embed
 
Hello World!</code></pre><p>And now, if we look at the C file we can see our <code>printf</code>.</p><pre><code>#undef ___AT_END
#define ___return goto ___return_embed_23_0
printf("Hello World!\n");
___return_embed_23_0:;
</code></pre><p>I don&#8217;t know about you, but this is starting to get interesting. Being able to execute C code by just embedding it directly into a Scheme file is super cool and convenient. </p><p>We can expand our example further by writing an actual C function and using it in Scheme. Here is our new <code>embed.scm</code> file</p><pre><code>;; create our square function
(c-declare #&lt;&lt;c-declare-end

  int square(int x) {
    return x * x;
  }

c-declare-end
)

;; Define a Scheme function to call our 'square' c function
(define square-scheme (c-lambda (int) int "square"))

;; using our square function
(display "Enter an integer: ")
(define input (read))
(let ((result (square-scheme input)))
  (display "The square of ")
  (display input)
  (display " is ")
  (display result)
  (newline))
</code></pre><p>It contains a new function in the <code>c-declare</code> section that squares numbers. In the <code>c-lambda</code> section, I tell Scheme what the C function is called, and what the arguments and return values are. </p><p>Then I write some regular Scheme code to prompt the user for an integer, read said integer, and then call the bound C function &#8220;square&#8221; using the <code>square-scheme</code> function. Now we compile like last time, execute the code, type in an integer, and bam!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PdCY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PdCY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 424w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 848w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 1272w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PdCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png" width="1456" height="596" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:596,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:41614,&quot;alt&quot;:&quot;terminal showing the square of 10&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="terminal showing the square of 10" title="terminal showing the square of 10" srcset="https://substackcdn.com/image/fetch/$s_!PdCY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 424w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 848w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 1272w, https://substackcdn.com/image/fetch/$s_!PdCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F817dd0ce-1bc1-4a92-bf39-c3b62c14ea67_1496x612.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We square values. So we can not only define c functions directly in our Scheme code, but also bind and execute those functions as well, without ever having to leave Scheme.</p><p>But I admit, writing C in a macro block inside a Scheme file is not the best user experience. There is neither syntax highlighting nor formatting. Thankfully you can define a C function in a regular ole C file and just use that. Here is a simple file named <code>triple.c</code> that does just that</p><pre><code>//triple.c
int triple(int num){
  return num * 3;
}
</code></pre><p>In our <code>embed.scm</code> file, using our trusty c-declare and c-lambda, we can bind the c code. </p><pre><code>(c-declare #&lt;&lt;c-declare-end
  #include "triple.c"
c-declare-end
)

(define num 100)
(define triple (c-lambda (int) int "triple"))

(display (string-append "The triple of " (number-&gt;string num) " is " (number-&gt;string (triple num))))
(newline)</code></pre><p>Then we compile and execute&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qPwa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qPwa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 424w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 848w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 1272w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qPwa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png" width="1456" height="596" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:596,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54613,&quot;alt&quot;:&quot;terminal showing the triple of 100&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="terminal showing the triple of 100" title="terminal showing the triple of 100" srcset="https://substackcdn.com/image/fetch/$s_!qPwa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 424w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 848w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 1272w, https://substackcdn.com/image/fetch/$s_!qPwa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F232510a7-1828-43b2-86c4-68f119c6f720_1496x612.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And just like that we are using C code in Scheme with no fuss. </p><h3>Inline Assembly</h3><p>A quick detour. In C you can drop down to inline assembly when the moments require it. Since a <code>c-lambda</code> allows you to write any valid C code, it stands to reason you would be able to do this in Gambit-C as well. Here is a small example in a file called <code>asm.scm</code></p><pre><code>((c-lambda () void
#&lt;&lt;c-lambda-end
    int a = 10;
    int b = 20;
    int result;

    // Inline assembly block
    __asm__(
        "add %1, %2\n\t" // Assembly instruction: Add b to a
        "mov %2, %0\n\t" // Move the sum (now in a) to result
        : "=r" (result)   // Output operands: 'result' is output in a register
        : "r" (a), "r" (b) // Input operands: a and b are inputs, both in registers
    );

    printf("The result is: %d\n", result);

c-lambda-end
))

(display "ASM example")
(newline)
</code></pre><p>After compiling and running the file like normal, we can get the result of our assembly operation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1C9q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1C9q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 424w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 848w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 1272w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1C9q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png" width="1263" height="558" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:558,&quot;width&quot;:1263,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38376,&quot;alt&quot;:&quot;terminal showing the output of our asm result&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="terminal showing the output of our asm result" title="terminal showing the output of our asm result" srcset="https://substackcdn.com/image/fetch/$s_!1C9q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 424w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 848w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 1272w, https://substackcdn.com/image/fetch/$s_!1C9q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6429883-0e15-4df1-a1e2-169b40d71aa9_1263x558.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Using Gambit Code in C</h2><h3>C-Define</h3><p>The <code>c-define</code> special form in Gambit-C is a way to connect Scheme procedures with C, allowing C functions to call Scheme code directly. When C calls the Scheme code, its arguments are converted to Scheme types, and passed to the Scheme procedure. The Scheme procedure's result is then converted back to a C type, and returned by the function.</p><p>Lets look at an example. Let&#8217;s say I want to read in a file using Scheme instead of C. I can do it by creating a <code>read.scm</code> file that looks like this using <code>c-define</code>&#8230;</p><pre><code>(c-define (<strong>read-file-into-string</strong> <strong>filename</strong>) (<strong>char-string</strong>) <strong>char-string "c_read_file_into_string" ""</strong>
  (let ((port (open-input-file filename))  
        (content ""))
    (let loop ((line (read-line port)))  
      (if (eof-object? line)  
          (begin
            (close-input-port port)  
            content)  
          (begin
            (set! content (string-append content line "\n"))  
            (loop (read-line port)))))
    ))
</code></pre><p>The <code>c-define</code> is simple, consisting of the five parameters. </p><ol><li><p>The name for the function in Scheme (<code>read-file-into-string</code>)</p></li><li><p>The number of arguments (in this case just <code>filename</code>)</p></li><li><p>the type of the input arguments (<code>char-string</code>) and the type of the output value (<code>char-string</code>)</p></li><li><p>The name of the function in C</p></li><li><p>The scope. In our case &#8220;&#8220; but it can be &#8220;static&#8221; as well</p></li></ol><p>After that it&#8217;s just a regular ole body of Scheme code. We can create a <code>read.h</code> file which has the prototype for our Scheme/C function </p><pre><code>#ifndef READ_H
#define READ_H

char* c_read_file_into_string(const char* filename);

#endif // READ_H</code></pre><p>And then we create our <code>main.c</code> function from which we will call our Scheme code from. I struggled with this part a bit, but I found this old conversation on <a href="https://gist.github.com/ncweinhold/991905">GitHub</a> that cleared things up for me. Here is the boiler plate for how you set up C to call Scheme in your <code>main.c</code>. I&#8217;ve bolded the sections that you have to change. The rest can stay the same</p><pre><code>#include &lt;stdio.h&gt;

#include "gambit.h"

#include <strong>"your_scheme.h"</strong>

#define SCHEME_LIBRARY_LINKER ____20_<strong>your_scheme</strong>_

___BEGIN_C_LINKAGE
extern ___mod_or_lnk SCHEME_LIBRARY_LINKER (___global_state_struct*);
___END_C_LINKAGE


int main(int argc, char** argv) {
// C code like normal 
  printf("Hello World, this is from C\n");

  ___setup_params_struct setup_params;
  ___setup_params_reset (&amp;setup_params);

  setup_params.version = ___VERSION;
  setup_params.linker = SCHEME_LIBRARY_LINKER;

  ___setup (&amp;setup_params);
// scheme code
  <strong>your_scheme_function();</strong>

  ___cleanup();
  
  return 0;
}</code></pre><p>Our files we want to use will be called <code>read.h</code>, and <code>read_.c</code>. To create our <code>read_.c</code> file properly, we need to generate c code from Scheme that does not contain a main entry point, or it will conflict with our <code>main.c</code> file. I&#8217;ll let Marc Feeley (the maintainer of Gambit-C) in the GitHub discussions explain why&#8230;</p><blockquote><p>By default the link file (here <code>somescheme_.c</code> generated from <code>somescheme.c</code>) contains a C &#8220;main&#8221; function so that without any additional step the code can be compiled and linked (at the C level) to obtain an executable program. In other words the entry point of the program will be the Gambit runtime system.</p><p>However your file main.c also defines a C &#8220;main&#8221; function so you end up with a duplicate definition. The way around this, shown below, is to compile the link file with the <code>-D___LIBRARY</code> C compiler option. This will cause the <code>somescheme_.c</code> file to avoid the inclusion of a C &#8220;main&#8221; function (through a series of #ifdefs). In other words, the Scheme code and the Gambit runtime system are acting as a library to the main C program.</p></blockquote><p>Let&#8217;s create a quick <code>build.sh</code> file, that will build our Scheme code without a main, and then call gcc to glue everything together&#8230;</p><pre><code>#!/bin/bash
gsc -c read.scm
gsc -link read.c
gsc -obj -cc-options -D___LIBRARY read.c read_.c
gsc -obj main.c

# don't forget to include the location of the Gambit headers and dynamic libraries in the gcc command!

gcc read.o read_.o main.o <strong>-I/usr/include/gambit.h</strong> <strong>/usr/lib/x86_64-linux-gnu/libgambit.so.4</strong> -lm -ldl -lutil -lssl -lcrypto -o main
</code></pre><p>As you can see, the <code>read.scm</code> file is converted into a <code>read.c</code> using the commands we talked about before, and then is linked. The linked file is then compiled with the <code>gsc -obj -cc-options -D___LIBRARY</code> and converted to a <code>read_.c</code> file. We then compile an object file out of our <code>main.c</code>. Finally we just call <code>gcc</code> and pass it our object files and specify all our libs and voil&#224;! We have a main program. Here is what our <code>main.c</code> function looks like before we compile it. I&#8217;ve bolded the sections of the boiler plate that I changed.</p><pre><code>#include &lt;stdio.h&gt;

#include "gambit.h"

#include "<strong>read.h</strong>"

#define SCHEME_LIBRARY_LINKER ___LNK_<strong>read_</strong>_

___BEGIN_C_LINKAGE
extern ___mod_or_lnk SCHEME_LIBRARY_LINKER (___global_state_struct*);
___END_C_LINKAGE


int main(int argc, char** argv) {
  printf("Hello World, this is from C\n");

  ___setup_params_struct setup_params;
  ___setup_params_reset (&amp;setup_params);

  setup_params.version = ___VERSION;
  setup_params.linker = SCHEME_LIBRARY_LINKER;

  ___setup (&amp;setup_params);

  <strong>char *text = c_read_file_into_string("dickinson.txt");
  printf("%s\n", text);</strong>

  ___cleanup();
  
  return 0;
}
</code></pre><p>And when we run the main executable&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p8gU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p8gU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 424w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 848w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 1272w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p8gU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png" width="1456" height="801" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:801,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112917,&quot;alt&quot;:&quot;scheme code in C reading Emily Dickinson&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="scheme code in C reading Emily Dickinson" title="scheme code in C reading Emily Dickinson" srcset="https://substackcdn.com/image/fetch/$s_!p8gU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 424w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 848w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 1272w, https://substackcdn.com/image/fetch/$s_!p8gU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f3cb52f-9071-4639-a9d1-a4b7d7409821_1899x1045.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Boom! we are calling Scheme code in C. </p><h3>C-Define-Type</h3><p>At its simplest, <code>c-define-type</code> lets you define a name in Scheme that refers to a C type. You use this when you have to interact with c-types that are not your standard, int, char, float etc. For example the manual shows how it can be used with Cs &#8220;File&#8221; type, and how it can be used to create a pointer to a file type.</p><pre><code>(c-define-type FILE "FILE")
(c-define-type FILE* (pointer FILE))</code></pre><p>I&#8217;ve found it the most useful when binding C code that requires custom structs. In Raylib, Raylib uses a custom Color struct in many of it&#8217;s functions</p><pre><code>typedef struct Color {
    unsigned char r;        // Color red value
    unsigned char g;        // Color green value
    unsigned char b;        // Color blue value
    unsigned char a;        // Color alpha value
} Color;
</code></pre><p>We can make the Color struct available from our Gambit-C code by using <code>c-define-type</code></p><pre><code>(c-define-type color (struct "Color"))</code></pre><p>This allows us to annotate functions like clear background with the &#8220;color&#8221; type</p><pre><code>(define ClearBackground (c-lambda (color) void "ClearBackground"))</code></pre><p>But what if we actually need to create a color? Well we have to define a <code>c-lambda</code> that constructs the color for us. Here we define our <code>make-color</code> function, which takes in 4 unsigned-int8s (don&#8217;t annotate with unsigned-char because unsigned-char is not 8 bit on the Scheme side), and returns a color. The body of our <code>c-lambda</code> creates a color from the arguments we passed to the <code>c-lambda</code>, which we can access with ___arg1, ___arg2, etc.</p><pre><code><code>(define make-color (c-lambda (unsigned-int8 unsigned-int8 unsigned-int8 unsigned-int8) color
#&lt;&lt;c-lambda-end
Color col =(Color){___arg1, ___arg2, ___arg3, ___arg4}; 
___return( col);
c-lambda-end
))

(define LIGHTGRAY (make-color 200 200 200 255))
(define YELLOW (make-color 253 249 0 255))
(define ORANGE (make-color 255 161 0 255))</code></code></pre><p>If we want to get a individual value of the color, unfortunately we will have to create functions for each value I.E color-r, color-g, color-b etc. Here is an example of me doing this using another type, Vector2, which is a struct with two float components, an X, and a Y.</p><pre><code>(define make-vector2 (c-lambda (float float) vector2
#&lt;&lt;c-lambda-end
Vector2 vec =(Vector2){___arg1, ___arg2}; 
___return(vec);
c-lambda-end
))

(define vector2-x (c-lambda (vector2) float
#&lt;&lt;c-lambda-end
___return(___arg1.x);
c-lambda-end
))

(define vector2-y (c-lambda (vector2) float
#&lt;&lt;c-lambda-end
___return(___arg1.y);
c-lambda-end
))
</code></pre><p>but this is Scheme, so defining a hygenic macro to do this should be easy enough. </p><h3>C-Initialize</h3><p>I&#8217;ll be honest I haven&#8217;t needed to use this so I don&#8217;t know much about it. All&#8217;s I know is it is good if you need to start a resource before your code runs. I.E connect to a database.</p><h2>Binding other C-Libraries</h2><p>Because Gambit-C interfaces with C so well, it is trivial to bind to C libraries. As an example, lets expand upon the <a href="https://github.com/raysan5/raylib">Raylib bindings</a> (A popular game library written in C) we introduced earler. Since <a href="https://github.com/raysan5/raylib/releases">Raylib builds the releases</a> for every major platform, we don&#8217;t have to compile the code ourselves. Download the build for your platform on their release page. Since I&#8221;m on linux I&#8217;ll download the tar.gx</p><pre><code># Download the code
wget https://github.com/raysan5/raylib/releases/download/5.0/raylib-5.0_linux_amd64.tar.gz

# decompress
tar -xzf raylib-5.0_linux_amd64.tar.gz</code></pre><p>Once we have Raylib on our system we see two folders in the downloaded directory. <code>include</code> contains all of our C header files, and <code>lib</code> contains our compiled code (<code>libraylib.a</code>, <code>libraylib.so</code>, etc). So as not to confuse Gambit with multiple definitions for the same code, lets delete everything in the lib folder except <code>libraylib.a</code>.  This lets us use Raylib statically (Gambit can use dynamic libraries too!)</p><p>Now that we&#8217;ve done that we can work on writing the Gambit code. To simplify things we will just write it directly in this directory. First lets create a file called <code>main.scm</code>. Once we&#8217;ve done that, we can use our <code>c-declare</code>&#8217;s and <code>c-lambda</code>&#8217;s, just like we&#8217;ve been doing before, to bring in the header files, and bind our functions.</p><pre><code>(c-declare #&lt;&lt;c-declare-end
#include "raylib.h"
c-declare-end
)

(define screenWidth 800)
(define screenHeight 450)

;; Declare Raylib functions
(define InitWindow (c-lambda (int int char-string) void "InitWindow"))
(define SetTargetFPS (c-lambda (int) void "SetTargetFPS"))
(define WindowShouldClose (c-lambda () bool "WindowShouldClose"))
(define BeginDrawing (c-lambda () void "BeginDrawing"))
(define EndDrawing (c-lambda () void "EndDrawing"))
(define CloseWindow (c-lambda () void "CloseWindow"))


;; Initialization
(InitWindow screenWidth screenHeight "raylib [core] example - basic window")
(SetTargetFPS 60)

(let loop ()
  (unless (WindowShouldClose)
    (BeginDrawing)
    (EndDrawing)
    (loop)))
</code></pre><p>Once we&#8217;ve written our binding code, it&#8217;s time to compile. If this were C code we would compile our program with these flags</p><pre><code>gcc -o main main.c -Iinclude/ -Llib/ -lraylib -lGL -lm -lpthread -ldl -lrt -lX11</code></pre><p>Thankfully, <code>gsc</code>, the Gambit compiler, allows us to compile it in much the same way. The Gambit-C compiler works in two phases, the first is a compilation step to create .o files and the next is a linking phase. If you specify the above commands to run in the compilation phase (--cc-options) and the linking phase (-ld-options) then it will build the executable just fine</p><pre><code>gsc -exe -cc-options <strong>"-Iinclude/ -Llib/"</strong> -ld-options <strong>"-Llib/ -lraylib -lGL -lm -lpthread -ldl -lrt -lX11"</strong> main.scm</code></pre><p>Now we run our main program and&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BXPa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BXPa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 424w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 848w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 1272w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BXPa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png" width="1456" height="665" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:665,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:215879,&quot;alt&quot;:&quot;Raylib running with gambit bindings&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Raylib running with gambit bindings" title="Raylib running with gambit bindings" srcset="https://substackcdn.com/image/fetch/$s_!BXPa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 424w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 848w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 1272w, https://substackcdn.com/image/fetch/$s_!BXPa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba6b3d72-3bad-4a5a-b265-6fb022440e4a_1885x861.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We can use Raylib to make games.</p><h2>One Final Experiment</h2><p>I&#8217;ve been recently getting back into C and translated my classic brainfuck interpreter to C for practice.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zK6m!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zK6m!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 424w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 848w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 1272w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zK6m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png" width="1456" height="697" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:697,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:334011,&quot;alt&quot;:&quot;brainfuck in C&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="brainfuck in C" title="brainfuck in C" srcset="https://substackcdn.com/image/fetch/$s_!zK6m!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 424w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 848w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 1272w, https://substackcdn.com/image/fetch/$s_!zK6m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28f54346-dd6d-49bf-ad9f-0a7b2d070bad_2915x1395.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It consists of 3 files, a <code>main.c</code>, <code>bf_interpreter.c</code>, and a<code> bf_interpreter.h</code>. I wrote this before I ever started using Gambit, so there are no tricks to make this code easier to embed. We know how easy it is for Gambit to call the C code on it&#8217;s own, all languages with an FFI can do that. But what if I copy and paste the code directly into a <code>c-declare</code> and then call it with a <code>c-lambda</code>? Would it still work? Let&#8217;s start with by defining our <code>c-declare</code>. I'll create a <code>brainfuck.scm</code> file and I&#8217;ll copy and paste my <code>bf_interpreter.h</code> into the declare&#8230;</p><pre><code> (c-declare #&lt;&lt;c-declare-end

#include &lt;string.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;stdlib.h&gt;
#define STACK_SIZE 30000

struct Interpreter {
    unsigned char stack[STACK_SIZE];
    unsigned char *stack_ptr;
    char *code;
    char *code_ptr;
    bool is_valid;
};
struct Interpreter createInterpreter(const char code[]);

int interpreterInterpret(struct Interpreter *interpreter);

)
</code></pre><p>Then in the same block I&#8217;ll copy and paste all of <code>bf_interpreter.c</code> (truncated for brevity)</p><pre><code>(c-declare #&lt;&lt;c-declare-end

#include &lt;string.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;stdlib.h&gt;
#define STACK_SIZE 30000

struct Interpreter {
    unsigned char stack[STACK_SIZE];
    unsigned char *stack_ptr;
    char *code;
    char *code_ptr;
    bool is_valid;
};


struct Interpreter createInterpreter(const char code[]);

int interpreterInterpret(struct Interpreter *interpreter);


struct Interpreter createInterpreter(const char code[]) {
    struct Interpreter interpreter;
    interpreter.is_valid = false;
    // Initialize stack to zero
    memset(interpreter.stack, 0, STACK_SIZE);

    // Set the data pointer to the beginning of the stack
    interpreter.stack_ptr = interpreter.stack;

    // Allocate memory and copy the Brainfuck code for the interpreter
    // Ensure the code is null-terminated
    interpreter.code = strdup(code);
    if (interpreter.code == NULL) {
        perror("Failed to copy code to interpreter");
        return interpreter;
    }

    // Set the code pointer to the beginning of the code.
    interpreter.code_ptr = interpreter.code;
    interpreter.is_valid = true;

    return interpreter;
}

int interpreterInterpret(struct Interpreter *interpreter) {
    printf("===BEGINNING INTERPRETATION===\n");

    int user_number;
    char *code = interpreter-&gt;code;
    for (int i = 0; i &lt; strlen(code); i++) {
        char instr = code[i];
        switch (instr) {
.......
 </code></pre><p>then in a <code>c-lambda</code> I&#8217;ll copy over my <code>main.c</code> code. </p><pre><code>((c-lambda () void
#&lt;&lt;c-lambda-end
    char filename[] = "instructions_hello_world.txt";
    char *content = readCode(filename);
    printf("%s\n", content);
    struct Interpreter bf = createInterpreter(content);
    interpreterInterpret(&amp;bf);

c-lambda-end
))
</code></pre><p>And it should run right? It will, with two minor updates. For the sake of simplicity I added the code from the <code>bf_interpreter.h</code> and .c file into the<code> c-declare</code>. Since I did that, I no longer need the includes in my <code>main.c</code>, because these are already visible from our <code>c-declare</code> (I know that from the documentation &#128515;)</p><pre><code>///No needed anymore in our c-lambda
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include "bf_interpreter.h"</code></pre><p>Lastly, I removed the <code>return EXIT_SUCCESS</code> line from the <code>c-lambda</code> that was present in my <code>main.c</code>. The reason is it will cause our program to segfault. This is understandable because Gambit expects to run Scheme code after it&#8217;s executed all the c stuff, but we prematurely exit. But other than that, all the rest of the code is the same. Let&#8217;s execute it!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!34Uc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!34Uc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 424w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 848w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 1272w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!34Uc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png" width="1456" height="985" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:985,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:129327,&quot;alt&quot;:&quot;termianl showing the results of the brainfuck interpreter&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="termianl showing the results of the brainfuck interpreter" title="termianl showing the results of the brainfuck interpreter" srcset="https://substackcdn.com/image/fetch/$s_!34Uc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 424w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 848w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 1272w, https://substackcdn.com/image/fetch/$s_!34Uc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1800fd9b-f0b8-4250-8033-83618dd78a34_1893x1281.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Pretty&#8230;Darn&#8230;Cool.</p><p>Before we wrap up, I have one more thing to talk about in regards to Gambit&#8217;s CFFI overhead. You may be wondering, as I was, what the overhead between Gambit calling C is, or C calling Gambit. I asked this very question on the <a href="https://gitter.im/gambit/gambit">gambit-c gitter</a>, and Marc Feeley the maintainer for Gambit actually answered!<br></p><blockquote><p><strong>Diego:</strong> Since Gambit Compiles to C code, there shouldn't be any overhead for calling C functions like there is when using a C-FFI in other languages right?</p><p><strong>Marc Feeley:</strong> People often misunderstand the type of &#8220;Scheme to C&#8221; compilation that is performed by Gambit. In many other compilers that compile a certain language X to C there is a 1-to-1 mapping of functions in language X and functions in C. If you define function <code>f</code> in your X program then you can expect some function to exist in the generated C code that is a translation of <code>f</code>. Some Scheme to C compilers actually do this (Bigloo, and I think Chicken also). But Gambit takes another approach in order to correctly and fully implement Scheme tail-calls and continuations, which don&#8217;t have a direct equivalent in (standard) C. Gambit uses a trampoline to implement control transfers between pieces of Scheme code (whether they are calls to a procedure or returns from a procedure). So if you use the C calling convention as a reference, then Scheme calls and returns typically have a higher cost than a C call/return.</p><p><br>Gambit's C FFI has the additional burden of converting the data representation of parameters and return values. A Scheme integer is not represented the same way as a C integer, so some conversion must happen when going from Scheme to C and back. This is true for all types (floats, booleans, characters, strings, etc) except the <code>scheme-object</code> type that keeps the same representation. There is also the burden of protecting Scheme values (and converted values) from being garbage collected and moved in a way that would cause issues on the C side. Finally there&#8217;s an overhead in supporting bidirectional calls between Scheme and C, and exceptions, and continuations.<br>So calls between Scheme and C using <code>c-lambda</code> and <code>c-define</code> are certainly not as cheap as a C function calling another C function. Surprisingly, the use of trampolines and some compiler optimizations can make Scheme to Scheme calls faster than C to C calls (but that is a different subject).<br>When performance is critical the lesser known <code>(##c-code "&lt;c-code&gt;")</code> which has no direct overhead can be quite useful. If <code>x</code> is a variable containing a fixnum, then computing the square of <code>x</code> can be done with essentially no overhead with <code>(##c-code "___RESULT = ___FIX(___INT(___ARG1)*___INT(___ARG1));" x)</code>. Note however that this code does no type checking and no overflow checking (but that&#8217;s sometimes what you want to avoid).</p></blockquote><p>A very thorough answer!</p><p>I hope that this has given you a brief overview of Gambit-C&#8217;s, C interfacing capabilities, and I hope that you will give the language a try. If you could only pick two programming languages to cover all of your programming needs, what would you choose? Comment down below, I&#8217;d love to hear your thoughts.</p><h2>Gitlab Repo</h2><p>You can find all of the code in this example in the <a href="https://gitlab.com/diegocrespo/gambit-c-interface/-/tree/main/raylib?ref_type=heads">Gitlab repo</a>. Also if you haven&#8217;t had enough Gambit yet check out <a href="https://cons.io/">Gerbil Scheme</a>! It is built on top of Gambit-C and adds some cool features!</p><h2>Call To Action &#128227;</h2><p>Hi &#128075; my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a <a href="https://twitter.com/deusinmach">Twitter</a> and a <a href="https://mastodon.social/deck/@DiegoCrespo">Mastodon</a>, if you&#8217;d like to follow me on other social media platforms. If you liked the article, consider liking and subscribing. And if you haven&#8217;t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/p/contemplating-loss-in-the-digital?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMDA1NTI0NjQsInBvc3RfaWQiOjEzNzEyNzc4MywiaWF0IjoxNjk1MzA3NDMzLCJleHAiOjE2OTc4OTk0MzMsImlzcyI6InB1Yi0xMTQ2MzU5Iiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.xfTsuo9K9txQ2hSv0AsAPTMqJm3sx3EVKCy-A-PvuPo&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.deusinmachina.net/p/contemplating-loss-in-the-digital?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMDA1NTI0NjQsInBvc3RfaWQiOjEzNzEyNzc4MywiaWF0IjoxNjk1MzA3NDMzLCJleHAiOjE2OTc4OTk0MzMsImlzcyI6InB1Yi0xMTQ2MzU5Iiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.xfTsuo9K9txQ2hSv0AsAPTMqJm3sx3EVKCy-A-PvuPo"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Deus In Machina&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.deusinmachina.net/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Deus In Machina</span></a></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;39b739ca-46e5-48d6-9969-4fe0d81cfdc5&quot;,&quot;caption&quot;:&quot;I recently implemented a Brainfuck interpreter in the Crystal programming language and I&#8217;d like to share my honest opinion about working in the language. When looking at a new programming language I am interested in these things in no particular order&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;&#128142;Crystal the language for humans&#128142;&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:100552464,&quot;name&quot;:&quot;Diego Crespo&quot;,&quot;bio&quot;:&quot;Using writing as a vehicle to organize my thoughts about the world&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc30f9f3-c687-4ab4-b4b1-f2485b4c8ccb_1920x1080.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2023-04-27T12:01:05.936Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94673e9c-7bba-402d-bd67-e1798889bf18_714x446.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://www.deusinmachina.net/p/a-look-at-the-crystal-programming&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:115371761,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;Deus In Machina&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F71f79212-7760-4bfa-a390-93b35da06734_1074x1074.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item></channel></rss>