<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Remo Dentato</title>
    <description>The latest articles on DEV Community by Remo Dentato (@rdentato).</description>
    <link>https://dev.to/rdentato</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F290146%2F66a1b27f-4556-43bb-8d25-d94a7d627af5.png</url>
      <title>DEV Community: Remo Dentato</title>
      <link>https://dev.to/rdentato</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rdentato"/>
    <language>en</language>
    <item>
      <title>Finite States Machines (in C)</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sat, 30 Aug 2025 06:03:23 +0000</pubDate>
      <link>https://dev.to/rdentato/finite-states-machines-in-c-129n</link>
      <guid>https://dev.to/rdentato/finite-states-machines-in-c-129n</guid>
      <description>&lt;p&gt;Most of us learn to write state machines in C with a big &lt;code&gt;while&lt;/code&gt; + &lt;code&gt;switch&lt;/code&gt; and a tangle of &lt;code&gt;break&lt;/code&gt;s. It works—until it doesn’t: fall-through bugs, nested loops, and “what happens if I forget a &lt;code&gt;break&lt;/code&gt; here?”&lt;/p&gt;

&lt;p&gt;Alternative methods use a transition table, possibly with pointers to functions encoding states. Or just plain code with &lt;code&gt;if&lt;/code&gt; and state variables to control the flow of execution.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;fsm&lt;/code&gt;&lt;/strong&gt; macro library takes a different, extremely simple approach: it turns each state into a labeled block and each transition into an explicit &lt;code&gt;goto&lt;/code&gt;. The result is &lt;strong&gt;readable, predictable control flow&lt;/strong&gt; and &lt;strong&gt;straight-line, optimizer-friendly code&lt;/strong&gt;—no runtime framework, no heap, no state tables, just C code.&lt;/p&gt;

&lt;p&gt;The key benefit of this approach is that it maps one-to-one the code with state machine diagrams, meaning that it's very simple to code an FSM starting from a diagram and, conversely, derive the diagram from the code, with great improvement of maintainability. (see the example at the end of the post)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🗃️ &lt;strong&gt;Source &amp;amp; repository:&lt;/strong&gt; &lt;a href="https://repo.dentato.com/fsm" rel="noopener noreferrer"&gt;repo.dentato.com/fsm&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ctype.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"fsm.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isalpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strchr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AEIOUaeiou"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VOWEL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONSONANT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VOWEL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"vowel"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONSONANT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"consonant"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Four macros&lt;/strong&gt; do the job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fsm { … }&lt;/code&gt; — open an FSM in a function (one per function).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fsmstate(NAME) { … }&lt;/code&gt; — define a state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fsmgoto(NAME);&lt;/code&gt; — transition.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fsmexit;&lt;/code&gt; — stop the machine (continue after the &lt;code&gt;fsm { … }&lt;/code&gt; block).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How it works (and why it’s safe)
&lt;/h2&gt;

&lt;p&gt;This is the code for the library (the commented version is in the repo)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define fsm if (1) {goto fsm_state_START; fsm_exit: ;} else 
#define fsmstate(s) for(;;) for(;;) if (1) goto fsm_exit; else fsm_state_ ## s:
#define fsmgoto(s)  goto fsm_state_ ## s
#define fsmexit     goto fsm_exit
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fsm&lt;/code&gt; expands to an &lt;code&gt;if (1) { goto fsm_state_START; fsm_exit: ; } else { … }&lt;/code&gt;.&lt;br&gt;
Execution jumps &lt;strong&gt;directly&lt;/strong&gt; to &lt;code&gt;START&lt;/code&gt;. A shared &lt;code&gt;fsm_exit&lt;/code&gt; label is defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each &lt;code&gt;fsmstate(NAME)&lt;/code&gt; expands to &lt;code&gt;for(;;) for(;;) if (1) goto fsm_exit; else fsm_state_NAME:&lt;/code&gt; followed by your block.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each macro is a single statement from the compiler's point of view (no issue with dangling &lt;code&gt;else&lt;/code&gt; or missing &lt;code&gt;;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No double evaluation of arguments is possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That design guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If control ever reaches the top of a state by accident, it &lt;strong&gt;exits&lt;/strong&gt; the FSM.&lt;/li&gt;
&lt;li&gt;If your state &lt;strong&gt;falls off the end&lt;/strong&gt;, the next loop tick forces an &lt;strong&gt;exit&lt;/strong&gt;—no silent fall-through.&lt;/li&gt;
&lt;li&gt;A bare &lt;code&gt;break&lt;/code&gt;/&lt;code&gt;continue&lt;/code&gt; inside a state exits the FSM (prefer explicit &lt;code&gt;fsmexit&lt;/code&gt; for clarity).&lt;/li&gt;
&lt;li&gt;Only the code within the &lt;code&gt;fsmstate()&lt;/code&gt; blocks will be executed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Constraints you should know&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One FSM per function (labels like &lt;code&gt;fsm_exit&lt;/code&gt;, &lt;code&gt;fsm_state_*&lt;/code&gt; are reserved).&lt;/li&gt;
&lt;li&gt;Exactly one &lt;code&gt;START&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;Only valid identifiers as state names.&lt;/li&gt;
&lt;li&gt;Don’t put executable code &lt;strong&gt;between&lt;/strong&gt; states inside the &lt;code&gt;fsm { … }&lt;/code&gt; block; it won’t run.&lt;/li&gt;
&lt;li&gt;Be mindful of &lt;strong&gt;VLAs&lt;/strong&gt;: never &lt;code&gt;goto&lt;/code&gt; into a scope that introduces a VLA per C11 rules. Declare VLAs either before &lt;code&gt;fsm&lt;/code&gt; or inside a state.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why this beats the usual switch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No hidden fall-through.&lt;/strong&gt; You must say where you go next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lean codegen.&lt;/strong&gt; Compilers emit direct branches; there’s no framework cost nor the cost to access data in memory (transition tables).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readable control flow.&lt;/strong&gt; Each state is a labeled block you can jump to and grep for. You can very easily reconstruct the FSM diagram just by inspecting the code (see the "comment stripper" example below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugger-friendly.&lt;/strong&gt; You literally step between &lt;code&gt;fsm_state_*&lt;/code&gt; labels.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where &lt;code&gt;fsm&lt;/code&gt; shines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tokenizers and scanners (comments, strings, numbers).&lt;/li&gt;
&lt;li&gt;Protocol and message parsers.&lt;/li&gt;
&lt;li&gt;Little interpreters and command dispatchers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A tiny real-world sketch: comment stripper
&lt;/h2&gt;

&lt;p&gt;This example strips comments from a C source file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;strip_comment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Doesn't read from in&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line_comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;escaped_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;escaped_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;escaped_lit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;escaped_lit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="n"&gt;fputc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line_comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line_comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;star&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fsmstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;star&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fgetc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmexit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fsmgoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to the explicit nature of &lt;code&gt;fsm&lt;/code&gt; states and transactions, I've been able to quickly generate a state diagram directly from the code using an LLM (ChatGPT, in this case) and then edit it for clarity. This wouldn't have been easy (or even possible) if the FSM had been a tangled mess of switch and state variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd8c73e6nkrlucnfdvcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd8c73e6nkrlucnfdvcl.png" alt="Comment stripper diagram" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Browse or clone the repository: &lt;strong&gt;&lt;a href="https://repo.dentato.com/fsm" rel="noopener noreferrer"&gt;repo.dentato.com&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Drop &lt;code&gt;dist/fsm.h&lt;/code&gt; into your project and &lt;code&gt;#include&lt;/code&gt; it.&lt;/li&gt;
&lt;li&gt;Define &lt;strong&gt;one&lt;/strong&gt; &lt;code&gt;fsm&lt;/code&gt; per function, with exactly one &lt;code&gt;START&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;Keep &lt;strong&gt;only states&lt;/strong&gt; inside the &lt;code&gt;fsm { … }&lt;/code&gt; block; transition with &lt;code&gt;fsmgoto(State)&lt;/code&gt;; leave with &lt;code&gt;fsmexit&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For deeper patterns (error funnels, re-entrancy, tracing, diagrams), see &lt;code&gt;docs/fsm.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;I took the original idea for these macros from the May 1991 issue of the glorious "Computer Language" magazine. The article &lt;em&gt;"Goto? Yes, Goto!"&lt;/em&gt; by Tim Cooper exposed me to the idea of using macros to discipline the use of &lt;code&gt;goto&lt;/code&gt; in implementing Finite State Machines. Those macros were simple, and I used them in some form or another on various occasions. Since then, my macromancy has improved, and this is the result, almost 35 years after I read that article on a train on my way home.&lt;/p&gt;

</description>
      <category>c</category>
      <category>fsm</category>
      <category>macromancy</category>
      <category>programming</category>
    </item>
    <item>
      <title>Polymorphic C (2/2)</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sun, 08 Jun 2025 19:08:40 +0000</pubDate>
      <link>https://dev.to/rdentato/polymorphic-c-22-4g71</link>
      <guid>https://dev.to/rdentato/polymorphic-c-22-4g71</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Default to 0

&lt;ul&gt;
&lt;li&gt;Pointers to NULL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Supply missing arguments

&lt;ul&gt;
&lt;li&gt;Skipping arguments&lt;/li&gt;
&lt;li&gt;A Microsoft quirk&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Counting arguments

&lt;ul&gt;
&lt;li&gt;Multiuse example&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Zero arguments&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;To complete the recap of how we can implement Polymorphism in C, let's review how we can handle different function signatures.&lt;/p&gt;

&lt;p&gt;Note that I did not invent these techniques; I found them over the years here and there (a site, a book, a magazine, ...), then I adopted and massaged them to make them useful to me.&lt;/p&gt;

&lt;p&gt;Since we all build on someone else's previous work, I'm sharing them here in the hope they might be of help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default to 0
&lt;/h2&gt;

&lt;p&gt;A very simple case is when the last optional argument drives the behaviour of your function, and it can be defaulted to 0&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example:   move(steps [, offset]) where offset is 0 if unspecified:&lt;/span&gt;
&lt;span class="c1"&gt;// The actual function is move_f()&lt;/span&gt;
&lt;span class="cp"&gt;#define move(s,...) move_f(s, __VA__ARGS__ + 0)
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If called with &lt;code&gt;move(10,3)&lt;/code&gt; it will expand to &lt;code&gt;move_f(10, 3 + 0)&lt;/code&gt;.&lt;br&gt;
If called with &lt;code&gt;move(10)&lt;/code&gt;, it will expand to &lt;code&gt;move(10, +0)&lt;/code&gt;, which is perfectly fine for the compiler.&lt;/p&gt;

&lt;p&gt;Now, in &lt;code&gt;move_f()&lt;/code&gt; you can check for &lt;code&gt;offset&lt;/code&gt; and behave accordingly.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Pointers to NULL&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;The same can be done for pointers, but since they are dangerous beasts, it is better to put some more effort into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: transfer(items [, aux_info])&lt;/span&gt;
&lt;span class="cp"&gt;#define transfer(i,...) transfer_g(i, __VA_ARGS__ +0)
#define transfer_g(i,a) _Generic((a), \
                           info_t *: transfer_f(i,(info_t *)(a)),\
                                int: transfer_f(i,(info_t *)NULL) \
                        )
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;transfer_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;aux&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use &lt;code&gt;_Generic&lt;/code&gt; to ensure that the second argument is of the proper type and that defaults to &lt;code&gt;NULL&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Note that the C standard does not guarantee that &lt;code&gt;(void *)0&lt;/code&gt; is equal to &lt;code&gt;NULL&lt;/code&gt;, even if it is very often the case, so we can't count on the fact that &lt;code&gt;(info_t *)0&lt;/code&gt; will be equal to &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When called as &lt;code&gt;transfer(32, new_info)&lt;/code&gt;, it will expand to &lt;code&gt;transfer_g(32, new_info + 0)&lt;/code&gt;. Assuming that &lt;code&gt;new_info&lt;/code&gt; is of type &lt;code&gt;info_t *&lt;/code&gt; (as it should be) also the value &lt;code&gt;(new_info + 0)&lt;/code&gt; is of type &lt;code&gt;info_t *&lt;/code&gt;.  So, the macro &lt;code&gt;transfer_g()&lt;/code&gt; will convert it to &lt;code&gt;transfer_f(32,(info_t *)(new_info+0))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When called as &lt;code&gt;transfer(32)&lt;/code&gt;, it will expand to &lt;code&gt;transfer_f(32, +0)&lt;/code&gt;. The second argument is an &lt;code&gt;int&lt;/code&gt; (as per the C standard), and the macro will be expanded to &lt;code&gt;transfer_f(32,(info_t * )NULL)&lt;/code&gt; by the second branch of generic. &lt;/p&gt;

&lt;p&gt;If the second argument is of any other type, there will be a syntax error.&lt;/p&gt;

&lt;p&gt;Note that in the &lt;code&gt;info_t *:&lt;/code&gt; branch of &lt;code&gt;_Generic&lt;/code&gt;, casting &lt;code&gt;a&lt;/code&gt; is mandatory, otherwise the compiler will complain when the second argument is missing an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supply missing arguments
&lt;/h2&gt;

&lt;p&gt;Say you have a function where more than one last argument can be optional: &lt;code&gt;f(a [,j [,k]])&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;A simple method to implement it involves augmenting the list of arguments to ensure the proper number of arguments is always provided to the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Select the n-th argument (0-based count)&lt;/span&gt;
&lt;span class="cp"&gt;#define arg_0( x,...)           x
#define arg_1(_0, x,...)        x
#define arg_2(_0,_1, x, ...)    x
&lt;/span&gt;
&lt;span class="c1"&gt;// Example:   move(steps [, offset [, direction]]) :&lt;/span&gt;
&lt;span class="cp"&gt;#define move(...) move_f(arg_0(__VA_ARGS__),\
                         arg_1(__VA_ARGS__ , 0), \
                         arg_2(__VA_ARGS__ ,'N',`N`), \
                        )
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expansion of &lt;code&gt;move(13, -3, 'S')&lt;/code&gt; will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'S'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'S'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'S'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="err"&gt;╰────╮&lt;/span&gt;                 &lt;span class="err"&gt;╭──╯&lt;/span&gt;                  &lt;span class="err"&gt;╭────────╯&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;       &lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;         &lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="sc"&gt;'S'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expansion of &lt;code&gt;move(13, -3)&lt;/code&gt; will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
           &lt;span class="err"&gt;╭──╯&lt;/span&gt;               &lt;span class="err"&gt;╭────╯&lt;/span&gt;             &lt;span class="err"&gt;╭────────╯&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;    &lt;span class="mi"&gt;13&lt;/span&gt;         &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;          &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="sc"&gt;'N'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expansion of &lt;code&gt;move(13)&lt;/code&gt; will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'N'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="err"&gt;╰───╮&lt;/span&gt;                &lt;span class="err"&gt;╰──╮&lt;/span&gt;           &lt;span class="err"&gt;╭──────╯&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;           &lt;span class="mi"&gt;13&lt;/span&gt;   &lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="mi"&gt;0&lt;/span&gt;   &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="sc"&gt;'N'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how the default for the last argument (&lt;code&gt;'N'&lt;/code&gt; in the example) must be repeated twice to ensure it is properly expanded.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Skipping arguments&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A noticeable drawback is that if you want to provide the third argument, you &lt;em&gt;must&lt;/em&gt; provide the second argument. It would be nice if we could just omit the ones we are not interested in.&lt;/p&gt;

&lt;p&gt;Providing the types are different, we can ask &lt;code&gt;_Generic&lt;/code&gt; for help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define arg_0( x,...)           x
#define arg_1(_0, x,...)        x
#define arg_2(_0,_1, x, ...)    x
&lt;/span&gt;
&lt;span class="c1"&gt;// We need a different type than int for the direction&lt;/span&gt;
&lt;span class="cp"&gt;#define N ((char)'N')
#define S ((char)'S')
#define E ((char)'E')
#define W ((char)'W')
&lt;/span&gt;
&lt;span class="c1"&gt;// Example:   move(steps [, offset [, direction]]) :&lt;/span&gt;
&lt;span class="cp"&gt;#define move(...) move_g(arg_0(__VA_ARGS__),\
                         arg_1(__VA_ARGS__ , N), \
                         arg_2(__VA_ARGS__ , N, N), \
                        )
&lt;/span&gt;
&lt;span class="cp"&gt;#define move_g(s, t, d) _Generic( (t) \
                            int: move_f(s, (int)(t), d), \
                           char: move_f(s, 0, (char)(t))  \
                         ) 
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To better understand how it works, let's check the macro expansion of &lt;code&gt;move(13, -3, S)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="err"&gt;╰────╮&lt;/span&gt;               &lt;span class="err"&gt;╭──╯&lt;/span&gt;               &lt;span class="err"&gt;╭────────╯&lt;/span&gt;
&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;           &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                   &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;│&lt;/span&gt;                  &lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;           &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;move(13, -3)&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="err"&gt;╰────╮&lt;/span&gt;               &lt;span class="err"&gt;╭──╯&lt;/span&gt;            &lt;span class="err"&gt;╭────────╯&lt;/span&gt;
&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;        &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// -3 is an int&lt;/span&gt;
                   &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;        &lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;move(13, E)&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="err"&gt;╰────╮&lt;/span&gt;               &lt;span class="err"&gt;│&lt;/span&gt;             &lt;span class="err"&gt;╭──────╯&lt;/span&gt;
&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="n"&gt;E&lt;/span&gt;     &lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// E is a char&lt;/span&gt;
                   &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;╰─────────────╮&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;            &lt;span class="mi"&gt;13&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="mi"&gt;0&lt;/span&gt;     &lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for &lt;code&gt;move(13)&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="err"&gt;╰──╮&lt;/span&gt;              &lt;span class="err"&gt;│&lt;/span&gt;          &lt;span class="err"&gt;╭──────╯&lt;/span&gt;
&lt;span class="n"&gt;move_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;        &lt;span class="mi"&gt;13&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="n"&gt;N&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// E is a char.&lt;/span&gt;
               &lt;span class="err"&gt;│&lt;/span&gt;              &lt;span class="err"&gt;╰──────────╮&lt;/span&gt;
&lt;span class="n"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;        &lt;span class="mi"&gt;13&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique allows for more flexibility, but it's a little bit more complicated. For example, the default for the third argument is repeated three times, and the default for the second parameter (0) is in the &lt;code&gt;move_f()&lt;/code&gt; function, not in the original &lt;code&gt;move()&lt;/code&gt; macro.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;A Microsoft quirk&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;The Microsoft compiler &lt;code&gt;cl&lt;/code&gt; preprocessor might need an extra level of macro expansion to ensure everything works correctly. To stay safe, you may want to add the macro &lt;code&gt;arg_x&lt;/code&gt; that will ensure the end value will be expanded one more time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define arg_x(...)           __VA_ARGS__
#define arg_0( x,...)        x
#define arg_1(_0, x,...)     x
#define arg_3(_0,_1, x, ...) x
&lt;/span&gt;
&lt;span class="c1"&gt;// Example:   move(steps [, offset [, direction]]) :&lt;/span&gt;

&lt;span class="cp"&gt;#define move(...) move_f(arg_x(arg_0(__VA_ARGS__)),\
                         arg_x(arg_1(__VA_ARGS__ , 0)), \
                         arg_x(arg_1(__VA_ARGS__ , 0, 'N')), \
                        )
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't check if the latest version of &lt;code&gt;cl&lt;/code&gt; still requires this, but &lt;code&gt;arg_x&lt;/code&gt; is harmless and will keep you safe from possible bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Counting arguments
&lt;/h2&gt;

&lt;p&gt;The most flexible way to handle a variable number of arguments is to count how many of them there are.&lt;br&gt;
This allows for specifying entirely different functions for each signature (with the help of &lt;code&gt;_Generics&lt;/code&gt;, if needed).&lt;/p&gt;

&lt;p&gt;Unfortunately, the C preprocessor still lacks a way to count the number of arguments passed to a macro, and, to stay within C11 boundaries, we have to resort to some additional macros.&lt;/p&gt;

&lt;p&gt;This is the most common way to count the number of arguments (up to a maximum of 4):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define ARG_CNT(_1,_2,_3,_4,_N, ...) _N
#define ARG_COUNT(...)   ARG_CNT(__VA_ARGS__, 4, 3, 2, 1, 0)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, the macro &lt;code&gt;ARG_COUNT(a,b,c,d)&lt;/code&gt; will be expanded to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ARG_COUNT(a, b, c, d)

  ARG_CNT(a, b, c, d, 4, 3, 2, 1, 0)
          │  │  │  │  │
         _1,_2,_3,_4,_N
                      |
                      4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro &lt;code&gt;ARG_COUNT(a,b)&lt;/code&gt; will be expanded to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ARG_COUNT(a, b)

  ARG_CNT(a, b, 4, 3, 2, 1, 0)
          │  │  │  │  │
         _1,_2,_3,_4,_N
                      |
                      2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As long as there are fewer than 5 arguments, &lt;code&gt;_N&lt;/code&gt; will match the number of passed arguments.&lt;/p&gt;

&lt;p&gt;The limit here is that we can only count up to a predefined number (4 in the example above) but this is not a real limitation: the number of arguments of a function should not be too high, and, in any case, you can extend the list of numbers in  &lt;code&gt;ARG_COUNT()&lt;/code&gt; and the list of arguments in &lt;code&gt;ARG_CNT()&lt;/code&gt; to match your needs.&lt;/p&gt;

&lt;p&gt;Now we need to map our function so that, for example, &lt;code&gt;move(14)&lt;/code&gt; maps to &lt;code&gt;move_1(14)&lt;/code&gt;, and &lt;code&gt;move(14,5)&lt;/code&gt; to &lt;code&gt;move_2(14,5)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define ARG_JOIN(x ,y)   x ## y
#define ARG_VRG(x, y)    ARG_JOIN(x, y)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro &lt;code&gt;ARG_VRG()&lt;/code&gt; creates a new identifier from two pieces. The process needs to be completed with the help of the &lt;code&gt;ARG_JOIN()&lt;/code&gt; to ensure proper macro expansion. For example, the expansion of &lt;code&gt;ARG_VRG(move_,2)&lt;/code&gt; is the identifier &lt;code&gt;move_2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's put everything together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define ARG_CNT(_1,_2,_3,_4,_N, ...) _N
#define ARG_COUNT(...)   ARG_CNT(__VA_ARGS__, 4, 3, 2, 1, 0)
#define ARG_JOIN(x ,y)   x ## y
#define ARG_VRG(x, y)    ARG_JOIN(x, y)
&lt;/span&gt;
&lt;span class="cp"&gt;#define N ((char)'N')
#define S ((char)'S')
#define E ((char)'E')
#define W ((char)'W')
&lt;/span&gt;
&lt;span class="c1"&gt;// A specific macro for each function is needed to avoid possible conflicts with other functions using `ARG_VRG()`.&lt;/span&gt;
&lt;span class="cp"&gt;#define move_arg(f,...) ARG_VRG(f, ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
&lt;/span&gt;
&lt;span class="cp"&gt;#define move(...)       move_arg(move_, __VA_ARGS__)     
#define move_1(s)       move_f(x,0,N)
#define move_2(s, t)   _Generic( (t) \
                            int: move_f(s, (int)(t), N), \
                           char: move_f(s, 0, (char)(t))  \
                        )
#define move_3(s,t,d)   move_f(s,t,d)
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;move_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multiuse example
&lt;/h3&gt;

&lt;p&gt;Let's look at another example around the following object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;RGB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;obj_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's focus on the setters/getters for &lt;code&gt;RGB&lt;/code&gt;, we want to be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the current value of the RGB field&lt;/li&gt;
&lt;li&gt;Set the RGB value passing an integer (e.g. &lt;code&gt;0xFFE0A0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set the RGB value passing the three components R, G, and B separately&lt;/li&gt;
&lt;li&gt;Set the RGB value passing the name of the color (e.g. &lt;code&gt;"White"&lt;/code&gt;, &lt;code&gt;"Pink"&lt;/code&gt;, ...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normally, one would create the following API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;set_rgb_from_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rgb&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;set_rgb_from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;set_rgb_from_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and will call the appropriate function depending on what we need. &lt;/p&gt;

&lt;p&gt;But let's say we want to create a sort of "super function" that can do all of the above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;obj_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and will select the proper function for us. Here's how we can make it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define ARG_CNT(_1,_2,_3,_4,_N, ...) _N
#define ARG_COUNT(...)   ARG_cnt(__VA_ARGS__, 4, 3, 2, 1, 0)
#define ARG_JOIN(x ,y)   x ## y
#define ARG_VRG(x, y)    ARG_JOIN(x, y)
&lt;/span&gt;
&lt;span class="cp"&gt;#define obj_rgb_arg(f,...)  ARG_VRG(f, ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
&lt;/span&gt;
&lt;span class="cp"&gt;#define obj_rgb(...)        obj_rgb_arg(obj_rgb_, __VA_ARGS__)     
&lt;/span&gt;
&lt;span class="cp"&gt;#define obj_rgb_1(o)        get_rgb(o)
&lt;/span&gt;
&lt;span class="cp"&gt;#define obj_rgb_2(o, c)    _Generic( (c) \
                                 int: obj_rgb_from_int(o, (int)((uintptr_t)(t))), \
                              char *: obj_rgb_from_str(o, (char *)((uintptr_t)(t))), \
                            )
&lt;/span&gt;
&lt;span class="cp"&gt;#define obj_rgb_4(o,r,g,b)  obj_rgb_from_rgb(o,r,g,b)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Armed with these, we can write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;   &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;old&lt;/span&gt; &lt;span class="n"&gt;rgb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obj_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;obj_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Black"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;obj_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;obj_rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_rgb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't be distracted by the fact that mixing getters and setters might be seen as bad design. The point here is to show what is possible to do, the actual API design must follow sane principles of usability, understandability, and maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero arguments
&lt;/h2&gt;

&lt;p&gt;All the techniques above have one thing in common: they assume there is at least one argument.  Sometimes it would be nice to be able to call &lt;code&gt;f()&lt;/code&gt; or &lt;code&gt;f(x)&lt;/code&gt;, but it is not very common.&lt;/p&gt;

&lt;p&gt;My &lt;a href="https://github.com/rdentato/vrg" rel="noopener noreferrer"&gt;&lt;code&gt;vrg&lt;/code&gt;&lt;/a&gt; library allows for zero arguments in a C11-compatible way, you can have a look at it if you are interested. &lt;/p&gt;

&lt;p&gt;However, I feel it is too complicated and, frankly, the cases for zero arguments are very few.&lt;/p&gt;

&lt;p&gt;The actual solution for handling zero arguments is to use the new &lt;code&gt;__VA_OPT__&lt;/code&gt; keyword introduced by C23 (and already available in some form as an extension in &lt;code&gt;gcc&lt;/code&gt;, for example). &lt;/p&gt;

&lt;p&gt;Let's wait for C23 support to be more widespread in C compilers and we'll revisit these techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We showed what C allows us to do about polymorphism. As it often happens with C, it only offers the basic building blocks, it's up to the programmer to put them together in the correct way.&lt;/p&gt;

&lt;p&gt;Mixing the techniques described here to handle function signatures and the techniques described in the previous article, you can achieve most of the (good) things modern object oriented languages can do.&lt;/p&gt;

&lt;p&gt;Just one caveat about complexity. It's far too easy to be tempted to write long, complex macros just to allow for some little nicer function definition. One should always balance the complexity of the code with the actual benefit it provides. &lt;/p&gt;

&lt;p&gt;Remember: since there is no bug in non-existent code, the less the code the better!&lt;/p&gt;

&lt;p&gt;If you find yourself staring at a series of complicated, indirect macro expansions, you might have gone too far with your polymorphic desires.&lt;/p&gt;

</description>
      <category>api</category>
      <category>c</category>
      <category>programming</category>
    </item>
    <item>
      <title>Polymorphic C (1/2)</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Mon, 26 May 2025 20:16:44 +0000</pubDate>
      <link>https://dev.to/rdentato/polymorphic-c-4kk2</link>
      <guid>https://dev.to/rdentato/polymorphic-c-4kk2</guid>
      <description>&lt;p&gt;Polymorphism, the ability to write functions whose behavior depends on the type and number of their arguments (i.e., their signature), is a feature of many modern programming languages.&lt;/p&gt;

&lt;p&gt;In the C world, this concept is especially relevant to &lt;strong&gt;library writers&lt;/strong&gt; and developers implementing the backend of a complex system: fellow programmers prefer a clean, consistent API over dozens or hundreds of closely related functions that differ only by name and signature.&lt;/p&gt;

&lt;p&gt;Too often, APIs end up littered with near-identical functions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;result_type&lt;/span&gt; &lt;span class="nf"&gt;mixdown_integer_and_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;result_type&lt;/span&gt; &lt;span class="nf"&gt;mixdown_unsigned_integer_and_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;result_type&lt;/span&gt; &lt;span class="nf"&gt;mixdown_string_and_float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// and so on ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;each variant must be remembered and called explicitly, making the interface hard to learn and easy to misuse. &lt;/p&gt;

&lt;p&gt;How much better would it be to hide those functions (which you, still, have to write) under a single function &lt;code&gt;mixdown(x,y)&lt;/code&gt; that would select the appropriate function based on the type of its arguments?&lt;/p&gt;

&lt;p&gt;While C doesn’t provide built-in support for method overloading or virtual dispatch tables, you can still craft polymorphic interfaces using a handful of idioms. &lt;/p&gt;

&lt;p&gt;In this article, I’ll focus on argument types. See &lt;a href="https://dev.to/rdentato/polymorphic-c-22-4g71"&gt;the next article&lt;/a&gt;, on how to handle functions signatures.&lt;/p&gt;

&lt;p&gt;I’ll explore four approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;void pointers to tagged structures&lt;/em&gt;, &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;function‑pointer tables&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;tagged pointers&lt;/em&gt;, &lt;/li&gt;
&lt;li&gt;the C11 &lt;code&gt;_Generic&lt;/code&gt; keyword,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;using a running example of graphical objects (points, rectangles, circles, ...) that implement operations such as &lt;code&gt;scale()&lt;/code&gt; and &lt;code&gt;translate()&lt;/code&gt;. I’ll try to highlight the trade-offs in safety, performance, and memory usage, and point out common pitfalls you’ll want to avoid.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Void Pointers to Tagged Structures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;Store a type tag in each object’s struct so that functions can inspect the tag at runtime and dispatch to the correct implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define OBJ_POINT  0
#define OBJ_RECT   1
#define OBJ_CIRCLE 2
&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GraphicObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// must be OBJ_POINT&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// must be OBJ_RECT&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// must be OBJ_CIRCLE&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// All structs must have the same initial sequence for this to work correctly&lt;/span&gt;
&lt;span class="c1"&gt;// The C standard only guarantees it in the context of accessing the fields&lt;/span&gt;
&lt;span class="c1"&gt;// of structures with unions but, in practice, this is often unnecessary.&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;GraphicObject&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Point&lt;/span&gt;         &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Circle&lt;/span&gt;        &lt;span class="n"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Rectangle&lt;/span&gt;     &lt;span class="n"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This relies on the C standard's guarantee that if a union contains several structures that share a common initial sequence it is permitted to inspect the common initial part of any of them. (C11 §6.5.2.3)&lt;/p&gt;

&lt;h3&gt;
  
  
  Dispatch Function
&lt;/h3&gt;

&lt;p&gt;Each "high-level" functions will inspect the &lt;code&gt;tag&lt;/code&gt; field and call the proper function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_POINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;// Ignore            &lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_RECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;scale_rectangle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Rectangle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_CIRCLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;scale_circle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt;
            &lt;span class="c1"&gt;// handle error&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pros &amp;amp; Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to implement.&lt;/li&gt;
&lt;li&gt;Works with any pointer type uniformly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No compile-time type checks: passing the wrong pointer (e.g. &lt;code&gt;scale(stdout, ...)&lt;/code&gt;) compiles fine but has undefined behavior.&lt;/li&gt;
&lt;li&gt;Every call incurs a &lt;code&gt;switch&lt;/code&gt;‐dispatch overhead.&lt;/li&gt;
&lt;li&gt;Tags consume extra space in every object.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Function Pointers in Object Tables (“Manual V-tables”)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;Embed pointers to each operation directly in the object (or point to a shared function‐pointer table), mimicking C++’s virtual table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// … other ops&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize per-type tables once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="n"&gt;point_ops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="n"&gt;translate_point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="n"&gt;scale_point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GraphicOps&lt;/span&gt; &lt;span class="n"&gt;circle_ops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="n"&gt;translate_circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="n"&gt;scale_circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// similarly for Rectangle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage via Macros
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define translate(obj, dx, dy) ((obj)-&amp;gt;ops.translate(obj, dx, dy))
#define scale(obj, sx, sy)     ((obj)-&amp;gt;ops.scale(obj, sx, sy))
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;new_circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aligned_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// C11 standard&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;circle_ops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// point to the function table&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pros &amp;amp; Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No runtime &lt;code&gt;switch&lt;/code&gt;; dispatch is a single indirect call.&lt;/li&gt;
&lt;li&gt;Compile‐time type safety: if you pass a "wrong" argument to the high level function, it will give an error.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objects contains an additional pointer (which is usually larger that an &lt;code&gt;int&lt;/code&gt;) per instance.&lt;/li&gt;
&lt;li&gt;Macro wrappers double‐evaluate the &lt;code&gt;obj&lt;/code&gt; argument (beware side effects).&lt;/li&gt;
&lt;li&gt;Slightly more boilerplate on initialization (for example, you will need a &lt;code&gt;scale-point()&lt;/code&gt; funtction even if it does nothing).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Tagged Pointers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;Use the low (least significant) bits of a pointer which are zero (to guarantee proper memory alignment) to store the tag instead of allocating space in every object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdalign.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stddef.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Determine the max tags allowed by the alignment requirements&lt;/span&gt;
&lt;span class="c1"&gt;// This is guaranteed to work by the C11 standard&lt;/span&gt;
&lt;span class="cp"&gt;#define MAX_TAGS   alignof(max_align_t)
#define TAG_MASK   ((uintptr_t)(MAX_TAGS-1))
#define PTR_MASK   (~TAG_MASK)
&lt;/span&gt;
&lt;span class="c1"&gt;// Check we have room for at least four tags&lt;/span&gt;
&lt;span class="n"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alignof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_align_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#define OBJ_POINT  0
#define OBJ_RECT   1
#define OBJ_CIRCLE 2
&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The type is defined as a structure to ensure that GraphicObject&lt;/span&gt;
&lt;span class="c1"&gt;// is different from any other type.&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;TaggedPtr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#define TAGGED_PTR_NULL ((TaggedPtr){0})
&lt;/span&gt;
&lt;span class="c1"&gt;// We'll use the TaggedPtr to represen a generic objec&lt;/span&gt;
&lt;span class="cp"&gt;#define GraphicObject TaggedPtr
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;TaggedPtr&lt;/span&gt; &lt;span class="nf"&gt;tag_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;TaggedPtr&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uintptr_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;untag_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TaggedPtr&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;PTR_MASK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TaggedPtr&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;TAG_MASK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The allocation and tagging :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;GraphicObject&lt;/span&gt; &lt;span class="nf"&gt;new_circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aligned_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;TAGGED_PTR_NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tag_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OBJ_CIRCLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dispatch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GraphicObject&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;untag_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_POINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ignore&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_RECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;scale_rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_CIRCLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale_circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt;         &lt;span class="cm"&gt;/* handle error */&lt;/span&gt;                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pros &amp;amp; Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No per‐object tag field → smaller objects.&lt;/li&gt;
&lt;li&gt;Compile‐time enforcement of pointer types (no &lt;code&gt;scale(stdout)&lt;/code&gt; issue).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited number of tags (bits used by alignment).&lt;/li&gt;
&lt;li&gt;Still a runtime &lt;code&gt;switch&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding more tags
&lt;/h3&gt;

&lt;p&gt;If more than few tags (let's say, more than 16) are needed, a good alternative is available if we are ready to accept some portability constraint.&lt;/p&gt;

&lt;p&gt;Counting on the fact the the vast majority of the current CPU architecture only use 48 bits for addressing virtual memory, we can store the tag in the &lt;em&gt;most significant&lt;/em&gt; (highest) 16 bits of the pointer.&lt;/p&gt;

&lt;p&gt;The functions &lt;code&gt;get_tag()&lt;/code&gt;, &lt;code&gt;tag_ptr()&lt;/code&gt;, and &lt;code&gt;untag_ptr()&lt;/code&gt; are conceptually similar and only shift the tag from/to the highest bits.&lt;/p&gt;

&lt;p&gt;The impact on portability and, possibly, software longevity needs to be assessed before using this method.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Compile-Time Dispatch with &lt;code&gt;_Generic&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;Use C11’s &lt;code&gt;_Generic&lt;/code&gt; keyword to select the correct function based on the static type of the expression—no runtime overhead for dispatch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define scale(obj, sx, sy) \
    _Generic((obj),        \
        Circle*:   scale_circle,    \
        Rectangle*:scale_rectangle, \
        Point*:    scale_point      \
    )(obj, sx, sy)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now calls like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are resolved at &lt;em&gt;compile time&lt;/em&gt; to &lt;code&gt;scale_point(p,2,2)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caveats
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Static‐only&lt;/strong&gt;: &lt;code&gt;_Generic&lt;/code&gt; cannot dispatch on runtime data; you cannot use it to iterate a heterogeneous list of &lt;code&gt;GraphicObject&lt;/code&gt;, for example.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verbosity&lt;/strong&gt;: Every operation needs its own &lt;code&gt;_Generic&lt;/code&gt; macro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited flexibility&lt;/strong&gt;: &lt;code&gt;_Generic()&lt;/code&gt; has its own quirks and sometimes need extra care in how the functions are designed to accomodate its rules on the arguments type.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  5. Type-Safe Void Pointers
&lt;/h2&gt;

&lt;p&gt;You can combine &lt;code&gt;_Generic&lt;/code&gt; with void pointers to get compile-time type check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define scale(obj, sx, sy)         \
    _Generic((obj),                \
        GraphicObject *: scale_dispatch,\
        Point *:         scale_dispatch,\
        Rectangle *:     scale_dispatch,\
        Circle *:        scale_dispatch \
    )(obj, sx, sy)
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scale_dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_POINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;// Ignore            &lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_RECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;scale_rectangle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Rectangle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;OBJ_CIRCLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale_circle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt;  &lt;span class="c1"&gt;// handle error&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It requires some more boilerplate, but completely remove the biggest weakness of using void pointers: the &lt;code&gt;scale()&lt;/code&gt; macro ensures that &lt;code&gt;scale_dispatch()&lt;/code&gt; can be called only on valid pointers. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GraphicObject *&lt;/code&gt; will serve as a pointer to an object of unknown type instead of using &lt;code&gt;void *&lt;/code&gt; and this will reinforce type-checking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While C lacks built-in polymorphism, thoughtful application of void‐pointer tagging, function pointers, tagged pointers, and &lt;code&gt;_Generic&lt;/code&gt; can yield flexible, type-safe, and reasonably efficient polymorphic APIs. Each approach carries its own trade-offs between binary size, runtime cost, and safety:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Void pointers + tags&lt;/strong&gt;: simplest, but no compile-time checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function pointers&lt;/strong&gt;: mirrors C++ v-tables, moderate overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tagged pointers&lt;/strong&gt;: memory‐efficient, but fragile portability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;_Generic&lt;/code&gt;&lt;/strong&gt;: zero‐cost dispatch, compile-time only.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I mostly write libraries and back-end software, I believe my duty is to balance these considerations, polishing an API so that the "real" programmer can write clear, concise, and correct code without worrying about too many underlying details.&lt;/p&gt;

&lt;p&gt;Polymorphism in C is entirely possible—just plan for it!&lt;/p&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>api</category>
    </item>
    <item>
      <title>A very minimal base for Concatenative Combinators</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sun, 15 Sep 2024 07:41:34 +0000</pubDate>
      <link>https://dev.to/rdentato/a-very-minimal-base-for-concatenative-combinators-1kcc</link>
      <guid>https://dev.to/rdentato/a-very-minimal-base-for-concatenative-combinators-1kcc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In a &lt;a href="https://dev.to/rdentato/a-concatenative-combinators-abstraction-algorithm-b31"&gt;previous article&lt;/a&gt; I described an abstraction algorithm for Concatenative Combinatory Logic (CCL) which uses a quite large base for convenience.&lt;/p&gt;

&lt;p&gt;The reason was practical: the bigger the base, the shorter the abstracted expressions will be.&lt;/p&gt;

&lt;p&gt;In &lt;a href="http://tunes.org/~iepos/joy.html" rel="noopener noreferrer"&gt;1&lt;/a&gt;, Brent Kirby provided examples of much smaller bases for CCL up to just two combinators and we might ask ourselves: "Does a smaller base exists?".&lt;/p&gt;

&lt;p&gt;In other words, we are looking for a single combinator (let's call it &lt;code&gt;𝗯&lt;/code&gt;) from which we can derive any other concatenative combinator.&lt;/p&gt;

&lt;p&gt;Of course, such combinator, if it exists, will equivalent to an expression using any of the other known bases.&lt;/p&gt;

&lt;h2&gt;
  
  
  In search of the single one
&lt;/h2&gt;

&lt;p&gt;For our search, let's use the two-combinators base &lt;code&gt;{𝘀',𝗸}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          (𝑦) (𝑥) 𝗸  = 𝑥
  (𝑧) (𝑣) (𝑦) (𝑥) 𝘀' = ((𝑧) 𝑣) 𝑥 (𝑧) 𝑦
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are looing for a combinator &lt;code&gt;𝗯&lt;/code&gt; from which we can calculate the two base combinators &lt;code&gt;𝘀'&lt;/code&gt; and &lt;code&gt;𝗸&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      𝗸  = (𝗯) 𝗯
      𝘀' = ((𝗯) 𝗯) 𝗯 = (𝗸) 𝗯 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If such combinator exists, it is a base for the Concatenative Combinatory Logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using an helping hand
&lt;/h2&gt;

&lt;p&gt;Before starting, let's assume that the &lt;code&gt;𝗯&lt;/code&gt; has a certain structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    𝗯 = (𝛾) (𝛽) (𝛼) 𝘁 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;𝘁&lt;/code&gt; is a combinator such that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  (𝑧) (𝑣) (𝑦) (𝑥) 𝘁 = (𝑣) (𝑦) (𝑥) 𝑧
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;{𝘀', 𝗸}&lt;/code&gt; is a base, we could abstract the free variables 𝑧, 𝑣, 𝑦, and 𝑥 from the left side expression and obtain a definition for &lt;code&gt;𝘁&lt;/code&gt; which only contains &lt;code&gt;𝘀'&lt;/code&gt; and &lt;code&gt;𝗸&lt;/code&gt; and no free variables. Due to the length of such definition, for convenience, we'll keep using &lt;code&gt;𝘁&lt;/code&gt; in the following.&lt;/p&gt;

&lt;p&gt;For the same reason, we'll use &lt;code&gt;𝗶&lt;/code&gt; as a shorthand for the equivalent expression &lt;code&gt;() (𝗸) () 𝘀'&lt;/code&gt; .&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching ...
&lt;/h2&gt;

&lt;p&gt;Let's start by finding combinators  &lt;code&gt;𝛾&lt;/code&gt;, &lt;code&gt;𝛽&lt;/code&gt;, and &lt;code&gt;𝛼&lt;/code&gt; such that &lt;code&gt;(𝗸) 𝗯 = 𝘀'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  (𝗸) 𝗯 = (𝗸) (𝛾) (𝛽) (𝛼) 𝘁
        = (𝛾) (𝛽) (𝛼) 𝗸 
        = (𝛾) 𝛼 
        = 𝘀'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, we need to find &lt;code&gt;𝛼&lt;/code&gt; and &lt;code&gt;𝛾&lt;/code&gt; such that &lt;code&gt;(𝛾) 𝛼 = 𝘀'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This can be simply achieved by choosing:  &lt;code&gt;𝛼 = 𝗶&lt;/code&gt; and &lt;code&gt;𝛾 = 𝘀'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝛾) 𝛼 = (𝘀') 𝗶 = 𝘀' 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need  &lt;code&gt;(𝗯) 𝗯 = 𝗸&lt;/code&gt;, which means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  (𝗯) 𝗯 = ((𝛾) (𝛽) (𝛼) 𝘁) (𝛾) (𝛽) (𝛼) 𝘁
        = (𝛾) (𝛽) (𝛼) (𝛾) (𝛽) (𝛼) 𝘁
        = (𝛾) (𝛽) (𝛾) (𝛽) (𝛼) 𝛼
        = 𝗸
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lookin at the last equality, it means that &lt;code&gt;𝛼&lt;/code&gt;, &lt;code&gt;𝛽&lt;/code&gt;, and &lt;code&gt;𝛾&lt;/code&gt; must be such that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  𝗸 = (𝛾) (𝛽) (𝛾) (𝛽) (𝛼) 𝛼
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We already found &lt;code&gt;𝛼&lt;/code&gt; and &lt;code&gt;𝛾&lt;/code&gt;, we can substitute them in the expression to obtain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  𝗸 = (𝛾)  (𝛽) (𝛾)  (𝛽) (𝛼) 𝛼
    = (𝘀') (𝛽) (𝘀') (𝛽) (𝗶) 𝗶
    = (𝘀') (𝛽) (𝘀') (𝛽) 𝗶
    = (𝘀') (𝛽) (𝘀') 𝛽
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to satisfy the equality&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  𝗸 = (𝘀') (𝛽) (𝘀') 𝛽
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we need &lt;code&gt;𝛽&lt;/code&gt; to be a combinator that deletes three arguments and replaces them with &lt;code&gt;𝗸&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's easy to see that the following combinator does the trick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  𝛽 = (((𝗸) 𝗸) 𝗸) 𝗸
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In fact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  (𝑧) (𝑦) (𝑥) 𝛽 = (𝑧) (𝑦) (𝑥) (((𝗸) 𝗸) 𝗸) 𝗸
                = (𝑧) (𝑦) ((𝗸) 𝗸) 𝗸
                = (𝑧) (𝗸) 𝗸
                = 𝗸
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which gives us a definition for &lt;code&gt;𝗯&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   𝗯 = (𝘀') ((((𝗸) 𝗸) 𝗸) 𝗸) (𝗶) 𝘁
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since, by definition, any expression using only combinators, is a combinator itself, we have found our single-combinator base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have proved that there exist a base &lt;code&gt;{𝗯}&lt;/code&gt; for the Concatenative Combinatory Logic that is formed by a single combinator.&lt;/p&gt;

&lt;p&gt;The result is not surprising as the same result is valid in the standard Combinatory Logic and comes from the fact that the two computational model are equivalent.&lt;/p&gt;

&lt;p&gt;For how impractical it may be to use a single combinator as a base, this results may be of interest in some specific context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography
&lt;/h2&gt;

&lt;p&gt;(1)  &lt;em&gt;The Theory of Concatenative Combinators&lt;/em&gt;,&lt;br&gt;
     Brent Kerby (bkerby at byu dot net).&lt;br&gt;
     Completed June 19, 2002. Updated February 5, 2007.&lt;br&gt;
     ((link)(&lt;a href="http://tunes.org/%7Eiepos/joy.html)" rel="noopener noreferrer"&gt;http://tunes.org/~iepos/joy.html)&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>theory</category>
      <category>concatenative</category>
    </item>
    <item>
      <title>Church-Rosser proof for CCL</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sat, 14 Sep 2024 15:29:24 +0000</pubDate>
      <link>https://dev.to/rdentato/church-rosser-proof-for-ccl-c5l</link>
      <guid>https://dev.to/rdentato/church-rosser-proof-for-ccl-c5l</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/rdentato/a-concatenative-combinators-abstraction-algorithm-b31"&gt;previous article&lt;/a&gt;, I argued that the Church-Rosser theorem holds for Concatenative Combinators.&lt;/p&gt;

&lt;p&gt;Providing rigorous proof was behind my abilities and I just presented a reasoning to convince you readers that it was true.&lt;/p&gt;

&lt;p&gt;However, a few days ago, the new OpenAI model &lt;code&gt;o1&lt;/code&gt; was made available and I took it as an opportunity to check a key principle that I believe is true:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;AI is here to augment our abilities and allow us to explore further, not to replace us!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, I passed my entire article to the new &lt;code&gt;o1&lt;/code&gt; model in ChatGPT and ask it to create a proof for the Church-Rosser theorem.&lt;/p&gt;

&lt;p&gt;It did it in 28 seconds and, beside the proof itself, it also provided me with the reasoning that it followed to create the proof:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Constructing clarity

Clarifying definitions and assumptions, and presenting a rigorous proof for the Church-Rosser theorem within Concatenative Combinators Logic, ensuring accuracy and compliance throughout the discussion.

Clarifying key concepts

I’m diving into terms, defining reduction rules, and ensuring clarity on confluence, leading to a precise statement of the Church-Rosser theorem.

Crafting reduction clarity

I’m working through the rules and language of concatenative combinator logic, including expressions, reduction rules, and their relations, to streamline the proof.

Taking a closer look

I’m exploring the Church-Rosser Theorem for concatenative combinator logic, demonstrating the confluent nature of the reduction system. This involves showing that any expression E reducible to both E1 and E2 can be further reduced to a common expression E3.

Tackling the reduction

I’m laying out the proof by first establishing that the reduction relation is locally confluent. This involves verifying that expressions reduce to distinct forms in one step and can be further reduced to a common form.

Pinpointing overlaps

I’m examining critical pairs in concatenative combinator logic, focusing on overlapping redexes caused by overlapping arguments (quotes). This narrows down the possible overlaps to specific cases.

Analyzing overlapping reductions

I’m examining the scenario where combinators share arguments, allowing one redex to overlap with another. This helps understand the limits of such overlaps in concatenative combinator logic.

Assessing termination and confluence

I’m mapping out that the reduction system is locally confluent. Now, I need to demonstrate it’s terminating to conclude that it’s confluent using Newman’s Lemma.

Defining a measure

I’m piecing together a well-founded measure M(E) on expressions E, ensuring that reductions consistently decrease this measure to establish termination in concatenative combinatory logic.

Pondering weak confluence

Hmm, I’m thinking about how weak confluence aligns with non-terminating reductions, like in lambda calculus, where Church-Rosser theorem steps in without assuming termination.

Defining critical pairs

I'm nearing the concept of critical pairs, essential for ensuring all potential overlaps in concatenative combinator logic are Joinable. This involves examining all possible overlaps and confirming joinability in each scenario.

Analyzing redex scenarios

I’m thinking through two redex cases. Let me see. First, no multiple reduction rules for a single redex. Second, nested redexes only reduce immediate quotes.

Confirming convergence

I’m piecing together that nested redexes don’t overlap, so the reduction system avoids divergence. Independent redexes are good, and the Church-Rosser theorem holds.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which allowed me to understand the proof itself better.&lt;/p&gt;

&lt;p&gt;Below you'll find the unedited result. It looks correct to me and further reassures me of the correctness of the abstraction algorithm I described in the other &lt;a href="https://dev.to/rdentato/a-concatenative-combinators-abstraction-algorithm-b31"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I deem this to be a &lt;strong&gt;successful example&lt;/strong&gt; of how these new LLM models can help us fill the gaps in our knowledge and allow us to progress.&lt;/p&gt;

&lt;p&gt;I would love to hear your thoughts in the comments.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WARNING: AI Generated content below.&lt;/strong&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The proof
&lt;/h2&gt;

&lt;p&gt;The Church-Rosser theorem is a fundamental result in rewriting systems, including combinatory logic and lambda calculus. It asserts that if an expression can be reduced to two different expressions, then there exists a common expression to which both can be further reduced. In the context of concatenative combinator logic, we aim to prove that the reduction system is confluent, meaning the Church-Rosser property holds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Expressions
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;expression&lt;/strong&gt; in concatenative combinator logic is defined recursively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terminals&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Variable&lt;/strong&gt;: A symbol from a predefined set (e.g., &lt;code&gt;𝑎&lt;/code&gt;, &lt;code&gt;𝑏&lt;/code&gt;, &lt;code&gt;𝑐&lt;/code&gt;, ..., &lt;code&gt;𝑥&lt;/code&gt;, &lt;code&gt;𝑦&lt;/code&gt;, &lt;code&gt;𝑧&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combinator&lt;/strong&gt;: A function that manipulates quotations (e.g., &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;zap&lt;/code&gt;, &lt;code&gt;dup&lt;/code&gt;, &lt;code&gt;cons&lt;/code&gt;, &lt;code&gt;dip&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quote&lt;/strong&gt;: An expression enclosed in parentheses &lt;code&gt;( ... )&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expressions&lt;/strong&gt;: A sequence of terms (including quotes and combinators).&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reduction Rules
&lt;/h3&gt;

&lt;p&gt;Each combinator has a specific reduction rule, defining how it transforms its arguments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identity (&lt;code&gt;i&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑥) i → 𝑥
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zap (&lt;code&gt;zap&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑥) zap → ε   (where `ε` denotes the empty expression)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Duplication (&lt;code&gt;dup&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑥) dup → (𝑥) (𝑥)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dip (&lt;code&gt;dip&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑦) (𝑥) dip → (𝑥) (𝑦)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cons (&lt;code&gt;cons&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑦) (𝑥) cons → ((𝑦) 𝑥)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run (&lt;code&gt;run&lt;/code&gt;)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑥) run → 𝑥 (𝑥)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;**Other combinators are defined similarly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Reduction Relation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One-Step Reduction (&lt;code&gt;→&lt;/code&gt;)&lt;/strong&gt;: Expression &lt;code&gt;E&lt;/code&gt; reduces to &lt;code&gt;E'&lt;/code&gt; in one step if &lt;code&gt;E&lt;/code&gt; contains a redex (reducible expression) that matches a reduction rule, and &lt;code&gt;E'&lt;/code&gt; is obtained by replacing that redex with its contractum (result of the reduction).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Step Reduction (&lt;code&gt;→*&lt;/code&gt;)&lt;/strong&gt;: The transitive and reflexive closure of &lt;code&gt;→&lt;/code&gt;. Expression &lt;code&gt;E&lt;/code&gt; reduces to &lt;code&gt;E'&lt;/code&gt; in zero or more steps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Confluence
&lt;/h3&gt;

&lt;p&gt;A rewriting system is &lt;strong&gt;confluent&lt;/strong&gt; if for all expressions &lt;code&gt;E&lt;/code&gt;, &lt;code&gt;E1&lt;/code&gt;, and &lt;code&gt;E2&lt;/code&gt;, whenever &lt;code&gt;E →* E1&lt;/code&gt; and &lt;code&gt;E →* E2&lt;/code&gt;, there exists an expression &lt;code&gt;E3&lt;/code&gt; such that &lt;code&gt;E1 →* E3&lt;/code&gt; and &lt;code&gt;E2 →* E3&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Statement of the Church-Rosser Theorem
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Theorem (Church-Rosser):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In concatenative combinator logic, the reduction system is confluent; that is, for any expression &lt;code&gt;E&lt;/code&gt;, if &lt;code&gt;E →* E1&lt;/code&gt; and &lt;code&gt;E →* E2&lt;/code&gt;, then there exists an expression &lt;code&gt;E3&lt;/code&gt; such that &lt;code&gt;E1 →* E3&lt;/code&gt; and &lt;code&gt;E2 →* E3&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof
&lt;/h2&gt;

&lt;p&gt;We will prove the Church-Rosser theorem by demonstrating that the reduction system in concatenative combinator logic is confluent. The proof involves the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Establish that the reduction system is locally confluent.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show that every reduction sequence is terminating for finite expressions.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conclude confluence using Newman's Lemma.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1: Local Confluence
&lt;/h3&gt;

&lt;p&gt;A reduction system is &lt;strong&gt;locally confluent&lt;/strong&gt; if, whenever an expression &lt;code&gt;E&lt;/code&gt; reduces to &lt;code&gt;E1&lt;/code&gt; and &lt;code&gt;E2&lt;/code&gt; in one step (i.e., &lt;code&gt;E → E1&lt;/code&gt; and &lt;code&gt;E → E2&lt;/code&gt;), there exists an expression &lt;code&gt;E3&lt;/code&gt; such that &lt;code&gt;E1 →* E3&lt;/code&gt; and &lt;code&gt;E2 →* E3&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Critical Pairs and Overlaps
&lt;/h4&gt;

&lt;p&gt;In concatenative combinator logic, critical pairs arise when two reduction rules overlap, potentially leading to different reductions from the same expression. To prove local confluence, we need to examine all possible overlaps of redexes and show that their reductions can be joined.&lt;/p&gt;

&lt;p&gt;However, in our system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Combinators act only on their immediate preceding quotes.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Each combinator consumes a fixed number of quotes.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reductions are deterministic based on the combinator and its arguments.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, overlapping redexes can only occur in limited and well-defined situations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case Analysis
&lt;/h4&gt;

&lt;p&gt;We consider all possible cases where overlaps might occur.&lt;/p&gt;

&lt;h5&gt;
  
  
  Case 1: Independent Redexes
&lt;/h5&gt;

&lt;p&gt;When two redexes are completely disjoint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expression&lt;/strong&gt;: &lt;code&gt;E = A B&lt;/code&gt;, where &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are independent redexes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reductions&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;E → A' B&lt;/code&gt; by reducing &lt;code&gt;A&lt;/code&gt; to &lt;code&gt;A'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E → A B'&lt;/code&gt; by reducing &lt;code&gt;B&lt;/code&gt; to &lt;code&gt;B'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Confluence&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Since &lt;code&gt;A'&lt;/code&gt; and &lt;code&gt;B'&lt;/code&gt; do not interfere, we can further reduce &lt;code&gt;A' B&lt;/code&gt; to &lt;code&gt;A' B'&lt;/code&gt;, and similarly, reduce &lt;code&gt;A B'&lt;/code&gt; to &lt;code&gt;A' B'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;: The reductions can be joined at &lt;code&gt;A' B'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h5&gt;
  
  
  Case 2: Nested Redexes
&lt;/h5&gt;

&lt;p&gt;When one redex is inside another:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expression&lt;/strong&gt;: &lt;code&gt;E = (E1) C&lt;/code&gt;, where &lt;code&gt;E1&lt;/code&gt; contains a redex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reductions&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;E → (E1') C&lt;/code&gt; by reducing inside the quote.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E → E2&lt;/code&gt; by applying the combinator &lt;code&gt;C&lt;/code&gt; to &lt;code&gt;(E1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Confluence&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;After applying &lt;code&gt;C&lt;/code&gt;, we get &lt;code&gt;E2&lt;/code&gt;, which may contain &lt;code&gt;E1&lt;/code&gt; in its expanded form.&lt;/li&gt;
&lt;li&gt;We need to show that both reduction paths can be further reduced to a common expression.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;However, in concatenative combinator logic, combinators do not reduce inside quotes unless explicitly applied. Since quotes are considered atomic with respect to outer combinators, reductions inside quotes do not interfere with reductions outside.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;: The reductions are independent and can be joined.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Case 3: Overlapping Redexes Due to Associativity
&lt;/h5&gt;

&lt;p&gt;Associativity is not inherent in concatenative combinator logic; the application of combinators depends on the exact structure of the expression.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;: Overlapping redexes that could cause divergence do not exist in this system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion of Local Confluence
&lt;/h4&gt;

&lt;p&gt;Since in all possible cases the reductions can be joined, the reduction system is locally confluent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Termination
&lt;/h3&gt;

&lt;p&gt;For finite expressions, the reduction system is &lt;strong&gt;strongly normalizing&lt;/strong&gt;, meaning that all reduction sequences terminate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Justification
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Finite Expressions&lt;/strong&gt;: The number of combinators and quotes in any finite expression is finite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduction Rules&lt;/strong&gt;: Each reduction either reduces the number of combinators or restructures the expression in a way that eventually leads to no further reductions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Infinite Expansion&lt;/strong&gt;: Although some combinators (like &lt;code&gt;dup&lt;/code&gt;) can duplicate quotes, the nesting of quotes is finite, preventing infinite expansion in finite expressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For expressions involving recursion or infinite constructs, termination may not hold. However, for the purposes of proving confluence in the finite case, termination is sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Applying Newman's Lemma
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Newman's Lemma&lt;/strong&gt; states that if a reduction system is terminating and locally confluent, then it is confluent.&lt;/p&gt;

&lt;p&gt;Since we have established:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt;: All reduction sequences for finite expressions terminate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Confluence&lt;/strong&gt;: The reduction system is locally confluent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Therefore&lt;/strong&gt;, by Newman's Lemma, the reduction system in concatenative combinator logic is confluent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have proven that concatenative combinator logic satisfies the Church-Rosser theorem for finite expressions. The key points are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Reduction Rules&lt;/strong&gt;: Each combinator has a unique reduction rule that applies in a well-defined manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Overlapping Redexes Causing Divergence&lt;/strong&gt;: Due to the nature of the combinators and their fixed arity, overlapping redexes that could lead to non-confluence do not occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination and Local Confluence&lt;/strong&gt;: Established for finite expressions, allowing us to apply Newman's Lemma.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Therefore&lt;/strong&gt;, the reduction system is confluent, meaning that the order of reductions does not affect the final result. Any expression can be reduced to a unique normal form (if it exists), regardless of the reduction path taken.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remarks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infinite Expressions&lt;/strong&gt;: For expressions that can lead to infinite reduction sequences (e.g., due to recursive combinators), the termination property does not hold. In such cases, more advanced methods are required to establish confluence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Implications&lt;/strong&gt;: The confluence property ensures that the abstraction algorithm and other computations in concatenative combinator logic are consistent and reliable.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>theory</category>
      <category>ai</category>
      <category>o1</category>
      <category>concatenative</category>
    </item>
    <item>
      <title>Literate Programming style for AI-Supported Coding</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Tue, 23 Jul 2024 14:40:17 +0000</pubDate>
      <link>https://dev.to/rdentato/literate-programming-style-for-ai-supported-programming-3jml</link>
      <guid>https://dev.to/rdentato/literate-programming-style-for-ai-supported-programming-3jml</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently rewrote (for the n-th time) a small literate programming tool.&lt;br&gt;
The concept always fascinated me: writing software structuring the code as an explanation of &lt;em&gt;why&lt;/em&gt; it does what it does (as opposed to just setting up a bunch of classes, functions, variables, in the order the programming language forces me to do) always seemed a "good thing" to me.&lt;/p&gt;

&lt;p&gt;Just have a look at the source code for my &lt;a href="https://github.com/rdentato/tng/blob/master/src/tng.md" rel="noopener noreferrer"&gt;&lt;code&gt;tng&lt;/code&gt;&lt;/a&gt; tool (of course, it is written using itself) and tell me how much easier it is to find your way in how the code works. A blessing for maintainers!&lt;/p&gt;

&lt;p&gt;Reality, however, is much harsher. Very few programmers are also good &lt;em&gt;writers&lt;/em&gt;, and I, for one, am no exception. Creating a document that is easy to read, well structured, and engaging is not a simple task. Literate Programming, for how interesting an idea it may be, never became &lt;em&gt;mainstream&lt;/em&gt; and was left relegated to some small circle writing scientific software.&lt;/p&gt;

&lt;p&gt;But then came AI. Whoever tried to use one of the many "copilots" around knows that to get any decent code out of them you have to go a great length in describing what you want, to get the proper logic, and create the right context to avoid the AI will hallucinate or re-invent functions that already existed. &lt;/p&gt;

&lt;p&gt;This article explores the idea that Literate Programming, when combined with AI, could revolutionize the way we write and understand code. By leveraging AI to fill in the gaps, developers can focus more on the conceptual and design aspects of programming, potentially enhancing productivity and code quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Literate Programming?
&lt;/h2&gt;

&lt;p&gt;Literate Programming, introduced by Donald Knuth in the 1980s, is a programming paradigm that intertwines code and documentation. Instead of writing code first and then documenting it later, developers write their programs as an exposition of logic in a natural language, interspersed with source code snippets. This approach aims to make the code more understandable and maintainable, as the documentation explains the thought process behind the code's structure and functionality.&lt;/p&gt;

&lt;p&gt;In a traditional Literate Programming setup, a developer might describe the problem and solution in plain English, gradually introducing code snippets to illustrate specific points. This results in a comprehensive document that serves both as the program itself and its documentation, providing a clear narrative that can be followed by other developers or even the original author at a later date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Literate Programming Meets AI
&lt;/h2&gt;

&lt;p&gt;With the advent of sophisticated AI models, there's an exciting opportunity to enhance Literate Programming. By using a literate style, developers can describe the high-level structure and functionality of a program in natural language, leaving the AI to generate detailed code snippets or, vice-versa, write a snippet of code and ask for a comprehensive description of the way it works.&lt;/p&gt;

&lt;p&gt;The key point is that code and documentation go hand in hand. They evolve together while the software is developed, the text part captures the reasoning behind the code and the code provides an implementation of what the text described. They are kept together to maximize the chance that code and text stay in sync.&lt;/p&gt;

&lt;p&gt;This approach can significantly reduce the time spent on boilerplate code and help developers focus on the overarching design and logic of their programs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Describing Programs to AI
&lt;/h3&gt;

&lt;p&gt;Imagine you are tasked with creating a web application. Instead of jumping straight into coding, you start by outlining the application's features and functionalities in a literate programming style. For instance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Introduction and Setup&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need a web application that allows users to register, log in, and manage their profiles.&lt;/li&gt;
&lt;li&gt;The application will use a standard MVC framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Registration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The registration form should capture user details like name, email, and password.&lt;/li&gt;
&lt;li&gt;On submission, the data will be validated and stored in the database.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Login&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The login form should authenticate users using their email and password.&lt;/li&gt;
&lt;li&gt;Upon successful login, users will be redirected to their profile page.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By refining these descriptions, the developer provides a clear narrative for what the program should do. The AI can then take these descriptions and generate the necessary code, filling in the blanks with specific implementations. For example, given the description of the registration process, the AI might generate the HTML form, the validation logic, and the database interaction code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of AI-Assisted Literate Programming
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Productivity&lt;/strong&gt;: By offloading routine coding tasks to the AI, developers can focus on more complex and creative aspects of software design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Documentation&lt;/strong&gt;: Literate Programming inherently produces better-documented code, which is further enhanced by the AI's ability to generate comprehensive and consistent descriptions of the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning and Collaboration&lt;/strong&gt;: This approach can serve as an educational tool, helping new developers understand the rationale behind code structures and decisions. It also facilitates better collaboration among team members by providing a clear and detailed narrative of the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Literate Programming, when combined with AI, offers a promising new way to approach software development. By focusing on describing the program's functionality and structure in natural language, developers can leverage AI to handle the detailed coding tasks.&lt;/p&gt;

&lt;p&gt;Also, AI can improve the quality of documentation by rewriting (in better English) sketchy or roughly outlined descriptions of the code. As pointed out earlier, great programmers are not necessarily great writers.&lt;/p&gt;

&lt;p&gt;This synergy between human creativity and machine precision can lead to more efficient, error-free, and well-documented code.&lt;/p&gt;

&lt;p&gt;To fully grasp the benefits of AI in this context, we must shift our focus. &lt;br&gt;
I believe we should try this new approach; using one of the many LitProg tools available (of course, I'm using my &lt;code&gt;tng&lt;/code&gt; tool but I'm biased :) try to establish a new workflow that mixes writing, prompting, coding, cut, and paste. I'm quite sure there's something to gain.&lt;/p&gt;

&lt;p&gt;In conclusion, the integration of Literate Programming with AI support holds the potential to significantly enhance the software development process. By shifting some of the workload to AI, developers can focus on innovation and design, ultimately leading to better software and a more enjoyable programming experience. Embracing this shift in mindset can prove itself crucial to unlocking the full potential of AI-assisted programming.&lt;/p&gt;

</description>
      <category>literateprogramming</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Choose Your Own Coding Assistant</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sun, 11 Feb 2024 16:39:26 +0000</pubDate>
      <link>https://dev.to/rdentato/choose-your-own-coding-assistant-11gi</link>
      <guid>https://dev.to/rdentato/choose-your-own-coding-assistant-11gi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the ever-evolving landscape of AI-powered tools, assistants for software development have carved a niche for themselves, especially in the realm of coding.&lt;/p&gt;

&lt;p&gt;This post reports the results of experimenting with four leading Large Language Models (plus a bonus guest star at the end of the article).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OpenAI's GPT-4&lt;/em&gt;, &lt;em&gt;Meta CodeLlama70B&lt;/em&gt;, &lt;em&gt;Meta CodeLlama7B&lt;/em&gt;, and &lt;em&gt;Mistral Mixtral8x7B&lt;/em&gt; were tasked with coding challenges to evaluate which one reigns supreme as a coding assistant. The aim is to get an assessment of their capabilities and discern which LLM could be most beneficial for various coding tasks.&lt;/p&gt;

&lt;p&gt;For &lt;em&gt;GPT-4&lt;/em&gt;, I've selected the last release of &lt;em&gt;GTP-4 Turbo&lt;/em&gt; (gpt-4-0125-preview) as it corrects some "laziness" that its predecessor had.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Setup
&lt;/h2&gt;

&lt;p&gt;The battleground for this comparison was set up in Visual Studio Code, enhanced by the "Continue" plugin, allowing for direct interaction with each LLM. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy71p2kb5b50mih94207p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy71p2kb5b50mih94207p.png" alt="Visual Studio Code with Continue" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup mirrors the functionality of other coding assistants like GitHub Copilot and AWS Codewhisperer and offers more privacy control over your code (for example by running the LLM on private servers) and the option of switching to the best (or less expensive) LLM for the task at hand.&lt;/p&gt;

&lt;p&gt;Here is how my setup appears:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmgun82jyyy1xqjdbn1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmgun82jyyy1xqjdbn1u.png" alt="Visual Studio Code screenshot" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note, on the right end side, the answer I just got from CodeLlama70B.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tests
&lt;/h2&gt;

&lt;p&gt;The LLMs were evaluated across eight critical areas in coding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Generation:&lt;/strong&gt; Their prowess in crafting code snippets or full modules from scratch based on requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Explanation and Documentation:&lt;/strong&gt; How well they could elucidate existing code and create meaningful documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit Test Generation:&lt;/strong&gt; Their ability to autonomously generate unit tests for existing code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging and Error Correction:&lt;/strong&gt; Efficiency in identifying, explaining, and rectifying code bugs or errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring / Optimization Recommendations:&lt;/strong&gt; The LLMs' capacity to suggest and implement code improvements for better quality and performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Review Assistance:&lt;/strong&gt; Their ability to aid in code reviews by spotting potential issues and suggesting enhancements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and Best Practices:&lt;/strong&gt; Proficiency in detecting security vulnerabilities and enforcing best practices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requirements Analysis:&lt;/strong&gt; The capability to comprehend software requirements in natural language and translate them into technical specifications. While this not being exactly "coding", it is quite related to that as there might be the need to further refine unclear requirements or somehow transform them (for example, to derive a Finite State Machine that will be further coded in a programming language).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The performance of each LLM has been rated on a scale from 0 to 3, with multiple tests, 19 in total, conducted in each area to ensure fair competition across tasks of the same area.&lt;/p&gt;

&lt;p&gt;Throughout the tests, the system prompt has been kept very simple: it just sets up the role of the LLM as a coding assistant and instructs it to be concise and straight to the point (to avoid using too many tokens in lengthy and possibly useless explanations). &lt;/p&gt;

&lt;p&gt;This has been done to assess the LLMs' &lt;em&gt;native&lt;/em&gt; abilities and opens up the possibility of further increasing their abilities through specific system prompting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;Here is the summary of the tests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl88ojt0q0hu1ye3ogysk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl88ojt0q0hu1ye3ogysk.png" alt="Overall Scores" width="706" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;GPT-4&lt;/em&gt;, not surprisingly, emerged as the overall victor, offering the most accurate and comprehensive assistance across all tasks. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;CodeLlama70B&lt;/em&gt; and &lt;em&gt;Mixtral8x7B&lt;/em&gt; were close competitors, being on par with GPT-4 in some specific areas.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;CodeLlama7B&lt;/em&gt;, despite ranking last, showed potential in certain tasks, indicating that tailored prompting could enhance its performance. Its appeal is in its small size which allows it to run on consumer-grade hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the results for each category:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoyf9z93tos8yh76bhgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoyf9z93tos8yh76bhgs.png" alt="Detailed Scores" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Task Examples
&lt;/h2&gt;

&lt;p&gt;You can find the full list of tasks used for this test, with prompts and the output for each LLM, on &lt;a href="https://github.com/rdentato/compare_coding_AI" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. Note that I'll update it from time to time with new tests and, possibly, new LLMs.&lt;/p&gt;

&lt;p&gt;Here are just a few examples of tasks used in the test.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation" rel="noopener noreferrer"&gt;FEN Counting&lt;/a&gt;:&lt;/strong&gt; This task tested the models' knowledge of FEN strings for chessboard positions. While all four LLMs had some knowledge of what FEN was, only GPT-4 managed to generate completely accurate code. This might be one of those cases when having more &lt;a href="https://dev.to/rdentato/are-small-ai-better-for-programming-3cib"&gt;"unrelated knowledge"&lt;/a&gt; could result in better performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Guideline Compliance:&lt;/strong&gt; Surprisingly, none of the LLMs detected all deviations from a set of coding style guidelines, revealing an area where more work is due to ensure an LLMs can assist. Better prompting or even a RAG approach to ensure the proper guidelines are fully "understood" by the LLM might be needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ambiguity Analysis:&lt;/strong&gt; Sometimes requirements clash with each other, possibly generating confusion, rework, or bugs. This specific task was aimed to check if the LLM were able to identify conflicting or overlapping requirements. Interestingly, &lt;em&gt;Mixtral8x7B&lt;/em&gt; ended up being better than &lt;em&gt;CodeLlama70B&lt;/em&gt; at this task.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Setting up a personal coding assistant using these LLMs can mitigate concerns regarding data and code privacy issues, common with cloud-based solutions.&lt;/p&gt;

&lt;p&gt;There are also cost factors to be considered, like the costs of hosting your own LLM, the benefits of the higher cost per token of GPT-4 (when compared with other cloud API solutions), and so on.&lt;/p&gt;

&lt;p&gt;In conclusion, while GPT-4 stands out for its comprehensive support, smaller models may present viable alternatives depending on your specific needs. &lt;/p&gt;

&lt;p&gt;The tests used for this assessment are meant to cover a wide area of tasks and get a feeling of how the different LLMs would perform. Take them as a first cut and conduct specific tests tailored to your use cases to make an informed choice.&lt;/p&gt;

&lt;p&gt;One thing is sure: whoever is not using an AI assistant for coding, will need to do so very soon to avoid being left behind. &lt;/p&gt;

&lt;p&gt;Now is the time to determine which task should benefit from using an AI assistant for coding and to what extent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus section
&lt;/h2&gt;

&lt;p&gt;During the preparation of this post, Google launched their new LLM &lt;em&gt;Gemini Advance&lt;/em&gt;, showing significant improvements over Google Bard. &lt;/p&gt;

&lt;p&gt;I've quickly compared it with GPT-4 across the 8 categories. Further tests are surely needed but, in the meantime, here is a first cut view of how Gemini Advanced scored against GPT-4 overall:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuefn4gwupafrpyrbbw5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuefn4gwupafrpyrbbw5u.png" alt="GPT4 vs Gemini Advanced" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and across the eight areas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv1z0paxs352bda0650o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv1z0paxs352bda0650o.png" alt="GPT4 vs Gemini Advanced (details)" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two LLMs are quite close! Clearly Google's new LLM is a serious contender to the crown of "best LLM overall".&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>llm</category>
    </item>
    <item>
      <title>Crafting GPTs to Power Up Your Toolbox</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sat, 27 Jan 2024 09:05:52 +0000</pubDate>
      <link>https://dev.to/rdentato/crafting-gpts-to-power-up-your-toolbox-1f31</link>
      <guid>https://dev.to/rdentato/crafting-gpts-to-power-up-your-toolbox-1f31</guid>
      <description>&lt;p&gt;Despite OpenAI GPTs, and their marketplace, are not really ready for widespread adoption, they present a unique opportunity to create powerful, AI-powered applications tailored to individual needs. &lt;/p&gt;

&lt;p&gt;Creating a domain-specific tool using GPTs doesn't require complex programming skills or deep AI knowledge. The concept revolves around leveraging basic techniques to craft tools that may significantly enhance your work efficiency and productivity.&lt;/p&gt;

&lt;p&gt;In this article, I want to show a concrete example of the steps needed to add domain knowledge to these tools and how easy is to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilizing the Knowledge Base
&lt;/h2&gt;

&lt;p&gt;The most flexible way to provide specific capabilities to GPTs is through defining "Actions" (calls to unrestricted APIs) that can offer dynamic information retrieval and interaction with other systems.&lt;/p&gt;

&lt;p&gt;For many applications, however, the extensive capabilities provided by Actions might be overkill and not worth the hassle of setting up servers, dealing with security and authorizations, worrying about network bandwidth, and so on. &lt;/p&gt;

&lt;p&gt;In this article, we'll use solely GPTs's "Knowledge Base" as a simpler, yet incredibly effective, alternative. By uploading a few files to the knowledge base, users can significantly enhance GPTs's ability to generate relevant, context-aware responses. Although there are limits to the number of files and their sizes, most use cases won't bump into these constraints.&lt;/p&gt;

&lt;p&gt;You need to have the *Code Interpreter" enabled in your GPTs to have everything working:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagee1v6ser3ktsp2lu7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagee1v6ser3ktsp2lu7w.png" alt="Code Interpreter enabled" width="222" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study: The Creative Bartender
&lt;/h2&gt;

&lt;p&gt;To illustrate how we can do it, let's consider the creation of a tool to support a creative bartender. This AI-powered bartender has access to the book &lt;a href="https://archive.org/details/b21538943" rel="noopener noreferrer"&gt;"&lt;em&gt;Drinks of all Kinds - HOT AND COLD - FOR ALL SEASONS&lt;/em&gt;"&lt;/a&gt;, published in 1896, containing an extensive collection of drink recipes and is tasked to generate new recipes based on user input (for example, a set of ingredients or the name of the drink to create).&lt;/p&gt;

&lt;p&gt;Please don't try those drinks at home! Their taste and healtiness is, to say the least, dubious!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bartender GPTs architecture
&lt;/h2&gt;

&lt;p&gt;To better understand how these types of GPTs are structured,  let's look at the overall architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaq4l4xk4pb3pulgmeag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaq4l4xk4pb3pulgmeag.png" alt="Bartender Architecture" width="778" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To construct our Bartender tool, we start with structuring its knowledge. Nothing good will come by just throwing a bunch of PDFs at it. It's like teaching to humans: one thing is to provide relevant, and structured, material to learn from, and another one is to just tell them to read hundreds of pages hoping they'll pick up what we intended them to learn.&lt;/p&gt;

&lt;p&gt;Let's organize the knowledge this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keywords.txt&lt;/strong&gt;: This file contains indexed keywords, acting as a Retrieval-Augmented Generation (RAG) component, providing the Bartender's ability to suggest recipes that are related to the user input. This is the &lt;em&gt;static knowledge&lt;/em&gt; of our AI: just a set of &lt;em&gt;keywords&lt;/em&gt; and the information in which recipes they are mentioned:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          ....
          egg is 13.
          gin is 14.
          japanese is 15.
          jersey is 16.
          jersey is 17.
          crystal is 17.
          ice is 17.
          ....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt will instruct the LLM to use this &lt;em&gt;static knowledge&lt;/em&gt; to identify keywords in user's input and determine the recipes that are related to these keywords (identified by a number).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;recipes.py&lt;/code&gt;&lt;/strong&gt;: This script handles the extraction from the recipes database of those recipes identified by the LLM as related to the user's input. If there are less than two recipes identified, it will select random recipes to provide enough material to create novel concoctions. In our example the task is simple but you can imagine to have a script that performs more complicated tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;recipes.db&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;offsets.ndx&lt;/code&gt;&lt;/strong&gt;: The actual &lt;em&gt;database&lt;/em&gt; with recipes data extracted from the book. It could have been a SQL database (for example, using sqlite) or any other suitable format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;prompts.md&lt;/code&gt;&lt;/strong&gt;: Everything is governed by the prompt which is reported here verbatim:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Role 
You are a creative bartender whose task is to create new recipes 
based on existing recipes.

## Instructions
  - Based on your knowledge, choose words that are related to the
    user prompt and take their associated {numbers}
  - Execute the `recipes.py` script passing as arguments the {numbers}:
      `%run /mnt/data/recipes.py {number} {number} ...`
  - Use the information in the {title} and {recipe} to create a new
    recipe.

## Constraints
  - Do not use any other information than the recipes 
  - Write the description of the recipe in a discoursive style,
    do not use lists or bullet point
  - Use the same writing style as the original recipes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directions given in the &lt;em&gt;Instructions&lt;/em&gt; and &lt;em&gt;Constraints&lt;/em&gt; sections work together to ensure that the LLM will stay within the boundary of its knowledge. &lt;/p&gt;

&lt;p&gt;The way to execute the script is also explicitly mentioned to avoid the LLM, hallucinating, would create his own Python script (it tried to do so a couple of times before I included this specific instruction).&lt;/p&gt;

&lt;p&gt;This is an example of the activation of &lt;code&gt;recipes.py&lt;/code&gt; on the prompt &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make an "Imperial Dog Apple Drink"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlw5jttx0nsmrvh1u5vp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlw5jttx0nsmrvh1u5vp.png" alt="Executing recipes.py" width="604" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note how the output of the script is structured as two quoted strings, one labeled &lt;code&gt;title&lt;/code&gt; and the other labeled &lt;code&gt;recipe&lt;/code&gt;. These labels are referred to in the prompt as &lt;code&gt;{title}&lt;/code&gt; and &lt;code&gt;{recipe}&lt;/code&gt; to guide the final LLM step and make it produce a text based on the script output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI/UI Pattern
&lt;/h2&gt;

&lt;p&gt;This Bartender example also shows a common pattern in AI tool design, which I call AI/UI, where an LLM is used to process user input and determine the actual parameters to be passed to a program, and it is used again to &lt;em&gt;humanize&lt;/em&gt; the program's output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqb03hplp9ys8paaeseo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqb03hplp9ys8paaeseo.png" alt="AI/UI" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is one of the most common uses for LLMs: being a human-friendly &lt;em&gt;User Interface&lt;/em&gt; for programs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This "Creative Bartender" example highlights the simplicity and the potential of using GPTs to create domain-specific AI-powered tools. &lt;/p&gt;

&lt;p&gt;As GPTs, or similar developers-friendly platforms, evolve making it easier to deploy such custom tools, we can anticipate a rapid growth of innovative AI-powered applications. To be ready for that time, now is the right time to experiment, exploring how AI can enhance our efficiency and creativity across various domains.&lt;/p&gt;

&lt;p&gt;If you have access to GPTs marketplace, you can directly interact with the &lt;a href="https://chat.openai.com/g/g-H2Oc0qLoM-bartender" rel="noopener noreferrer"&gt;"Creative Bartender"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The full code and text files are available on &lt;a href="https://gh.dentato.com/bartender" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gpts</category>
    </item>
    <item>
      <title>Are small AI better for programming?</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sat, 20 Jan 2024 22:16:44 +0000</pubDate>
      <link>https://dev.to/rdentato/are-small-ai-better-for-programming-3cib</link>
      <guid>https://dev.to/rdentato/are-small-ai-better-for-programming-3cib</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I've been immersed in the world of computer programming since the era of 8-bit computers, witnessing its evolution firsthand. Back then, programming was about the intricacies of hardware, meticulous manipulation of bits and bytes and using GOTO. Over time, we got the various programming styles: functional, procedural, object oriented, using higher and higher level of abstractions, and now, we hear talks of its "end of life" due to the rise of AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumkthg9o49gnsqz588hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumkthg9o49gnsqz588hg.png" alt="Image description" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is "Programming"?
&lt;/h2&gt;

&lt;p&gt;I do not really agree with this view. I firmly believe that the essence of programming will always remain relevant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Computer programming is the task of understanding a problem and articulating, in an extremely clear way, how a computer system must operate to provide a solution to that problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just as we transitioned from dealing with individual CPU instructions to working with abstract data types and classes, we are now advancing towards a paradigm that aligns even more closely with natural language. This evolution doesn't signify the end of programming; rather, it represents a transformation in &lt;em&gt;&lt;strong&gt;how we conceptualize the problems we want to solve and how we articulate their solutions&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The role of AI
&lt;/h2&gt;

&lt;p&gt;And for this, the role of AI, especially Large Language Models (LLMs), has become increasingly significant. My journey through this landscape has been one of exploration and discovery, focusing on how AI can enhance the programming process.&lt;br&gt;
Many see, and use, AI as a sort of glorified autocorrect in coding, offering suggestions and corrections up to entire, fully developed, functions. That's a fair and productive way to use it but I believe that the true potential of AI in programming lies far beyond these basic applications.&lt;/p&gt;

&lt;p&gt;I often use the term "&lt;em&gt;&lt;strong&gt;RubberGrokking&lt;/strong&gt;&lt;/em&gt;" to describe the process of conversing with an AI to progressively clarify and refine the problem at hand, and to elucidate the most appropriate solution. That poor yellow plastic duck that used to silently stare at us while hearing our rants, is now able to get back at us with feedback, hints, and, sometimes, even useful artifacts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The role of AI in programming is to engage the developer in conversations that will help clarify the problem and find the proper solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqug6i44i55lhrwg5aidj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqug6i44i55lhrwg5aidj.png" alt="Image description" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Take a walk on the Small side
&lt;/h2&gt;

&lt;p&gt;After the intial tests with large LLM, my intrigue led me to consider smaller, fine-tuned AIs. The idea stemmed from the consideration that while large AIs know a lot about a wide array of topics, such extensive knowledge might not be necessary for specific programming tasks and might just be a waste of time and money. I mean, GPT-4 may know a lot about kittens, but when will I ever need that knowledge?&lt;/p&gt;

&lt;p&gt;Using compact models promises several advantages: they're faster during inference, easier to fine-tune, and could potentially be hosted locally, addressing privacy concerns. Rather than using a single large model to rule them all, I could have many smaller, custom tailored models.&lt;/p&gt;

&lt;p&gt;Initially, this smaller AI seemed like the perfect solution. But as I delved deeper, integrating both small and large models into my work, I could appreciate the major drawback: it's hard to get an adequate return on the time (and money) spent to create your perfect fitting model. By the time you've created the model you need, something else popped up: a new LLM, a new tool, a new need to fulfill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantage of being heavy-weight
&lt;/h2&gt;

&lt;p&gt;Besides the advantage of being just one API call away, large models showed me something I was not properly considering: the value of &lt;em&gt;&lt;strong&gt;unrelated knowledge&lt;/strong&gt;&lt;/em&gt;. Solving real world problems, like programming is meant to do, requires quite some knowledge of the world: we don't need just technical knowledge to do our job, we also need to know, depending on the type of application we are developing, what a mortgage is, what a grocery store is, and the fact that kittens will make your video tons on view on YouTube.&lt;/p&gt;

&lt;p&gt;Large models, with their vast database of information, allow for exploring solutions on a higher level. They enable us to draw parallels and insights from seemingly unrelated fields. This broad knowledge base provides a rich context for problem-solving in programming.&lt;/p&gt;

&lt;p&gt;Relying solely on a smaller model could mean constantly fine-tuning or retraining it to incorporate a wide range of knowledge. The effort involved in this process made me currently gravitate more toward larger models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2gvh5katpmstclx76f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2gvh5katpmstclx76f9.png" alt="Image description" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions (and moving forward)
&lt;/h2&gt;

&lt;p&gt;With all that said, the idea of harnessing the benefits of smaller models (faster inference, privacy, …) still lingers in my mind. Maybe a properly trained model with the right balance of technical and world knowledge could be used as a base tool and then supplemented with the proper knowledge to handle the problem at hand.&lt;br&gt;
Many research efforts are aimed at integrating Large Language Models (LLMs) with more structured representations of knowledge, such as Ontologies. This integration may bring new opportunities to re-evaluate the use of small models. Alternatively, in the meantime, some major breakthroughs could completely change our perspective on what 'small' and 'large' mean in this context.&lt;br&gt;
My exploration into the optimal use of small versus large AI models in programming is still ongoing, and it's an exciting time to be part of this technological revolution. The field of AI-assisted programming is evolving rapidly and while traditional programming isn't disappearing, its future iteration will undoubtedly be transformed by AI, possibly in ways we can't yet fully comprehend.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>A Concatenative Combinators abstraction algorithm</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Mon, 04 Dec 2023 18:19:01 +0000</pubDate>
      <link>https://dev.to/rdentato/a-concatenative-combinators-abstraction-algorithm-b31</link>
      <guid>https://dev.to/rdentato/a-concatenative-combinators-abstraction-algorithm-b31</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Concatenative_programming_language" rel="noopener noreferrer"&gt;Concatenative programming languages&lt;/a&gt; like &lt;em&gt;Forth&lt;/em&gt; or &lt;em&gt;Joy&lt;/em&gt; have their theoretical foundation in a computational model that is equivalent to 𝜆-calculus and Combinatory Logic: the Concatenative Combinatory Logic. This article shows a simple abstraction algorithm that is akin to the process of compilation.&lt;/p&gt;

&lt;p&gt;In [1], Kerby discusses &lt;em&gt;abstraction&lt;/em&gt; by converting expressions containing concatenative combinators to lambda expressions with variables and then proceeds by abstracting variables from the lambda expressions.&lt;/p&gt;

&lt;p&gt;This article follows a more direct approach and provides abstraction rules that are aimed at making the algorithm easier to apply and implement.&lt;/p&gt;

&lt;p&gt;Even if we are mostly interested in showing that such algorithm exists we have made an effort to choose a base of combinators that will keep the resulting expression as short as possible (abstraction usually leads to very long and complex expressions). Further improvements can be made while implementing the algorithm, but we won't discuss them here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expressions
&lt;/h2&gt;

&lt;p&gt;The language of concatenative combinators is defined by the following EBNF:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   expression := term+
   term := combinator | var | quote
   quote := '(' expression? ')'
   combinator := [A-Za-z_][A-Za-z_0-9]*
   var := [𝑎𝑏𝑐-𝑥𝑦𝑧]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can be summarized as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;em&gt;expression&lt;/em&gt; is a list of terms&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;combinator&lt;/em&gt; is a term&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;variable&lt;/em&gt; is a term&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;quote&lt;/em&gt; (an expression enclosed in parenthesis) is a term&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;nil&lt;/em&gt; quote &lt;code&gt;()&lt;/code&gt; is a term&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that variables are notated with a different set of symbols.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   (𝑦) dup
   (cons (𝑧)) sip (𝑦)
   (alpha) (beta) dip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;evaluation&lt;/em&gt; of an expression proceeds from left to right by finding the first combinator that can be successfully reduced (i.e. the one that has enough quotes at its left) and replacing it and its arguments with the result of its application to the arguments.&lt;/p&gt;

&lt;p&gt;We assume that, as in classical Combinatory Logic, the Church-Rosser theorem holds. While not a real proof, at the end of this paper we'll provide a reasoning that reassures us on the validity of the Church-Rosser theorem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concatenative Combinators
&lt;/h2&gt;

&lt;p&gt;Let's use an intuitive definition of what a concatenative combinator is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;em&gt;combinator&lt;/em&gt; is an operator that shuffles, duplicates or removes&lt;br&gt;
&lt;em&gt;quotes&lt;/em&gt; there are at their left in an expression.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The behavior of a combinator is defined as an equivalence like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    (𝑦) (𝑥) swap  = (𝑥) (𝑦)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can interpret the definition of &lt;code&gt;swap&lt;/code&gt; above by saying that in any given expression you can replace any occurrence of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    (𝑦) (𝑥) swap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    (𝑥) (𝑦)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sake of reasoning (and as a possible strategy of implementation) we can think of a combinator as a program that operates on a stack:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A combinator is a &lt;em&gt;program&lt;/em&gt; that pulls a certain number of quoted expressions from a stack and pushes back in the stack a number of expressions containing any number of them (even zero), possibily in a different order&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  (Non minimal) Base for concatenative combinators
&lt;/h2&gt;

&lt;p&gt;To simplify the abstraction algorithm we'll use the following combinators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    (𝑥) i    = 𝑥
                    (𝑥) zap  = 
                    (𝑥) run  = 𝑥 (𝑥)
                    (𝑥) dup  = (𝑥) (𝑥)
                (𝑦) (𝑥) cons = ((𝑦) 𝑥)
                (𝑦) (𝑥) cosp = ((𝑦) 𝑥) (𝑦)
                (𝑦) (𝑥) dip  = 𝑥 (𝑦)
                (𝑦) (𝑥) sip  = (𝑦) 𝑥 (𝑦)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which are a superset of the bases defined in [1] and, hence, ensure that every possible expression can be represented using those combinators.&lt;/p&gt;

&lt;p&gt;We'll extend the concept of combinator &lt;em&gt;defintions&lt;/em&gt; by allowing a combinator to add other elements that were not in the original arguments.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              (𝑦) (𝑥) add = (𝑦) (succ) 𝑥
             (𝑦) (𝑥) mult = (zero) ((𝑦) add) 𝑥
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Abstraction
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;abstraction&lt;/em&gt; of an expression &lt;code&gt;𝓕&lt;/code&gt; with respect to the variable &lt;code&gt;𝑥&lt;/code&gt; is denoted with &lt;code&gt;{𝓕}[(𝑥)]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The result of the &lt;em&gt;abstraction&lt;/em&gt; of the variable &lt;code&gt;𝑥&lt;/code&gt; from the expression &lt;code&gt;𝓕&lt;/code&gt; is an expression &lt;code&gt;𝓖&lt;/code&gt; that does not contain &lt;code&gt;𝑥&lt;/code&gt; and that, when applied to &lt;code&gt;(𝑥)&lt;/code&gt;. will return &lt;code&gt;𝓕&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           𝓖 = {𝓕}[(𝑥)]  -&amp;gt;  (𝑥) 𝓖 = 𝓕
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a sense, abstraction is similar to compilation. Given an expression &lt;code&gt;𝓕&lt;/code&gt; containing a variable &lt;code&gt;𝑥&lt;/code&gt; (the &lt;em&gt;source code&lt;/em&gt;) we can see &lt;code&gt;{𝓕}[(𝑥)]&lt;/code&gt; as a program that when applied to a quoted expression &lt;code&gt;(𝓡)&lt;/code&gt; will result in the original expression where any occurence of the variable &lt;code&gt;𝑥&lt;/code&gt; is replaced by &lt;code&gt;𝓡&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When abstracting multiple variable we'll have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         {𝓕}[(𝑦) (𝑥)] = {{𝓕}[(𝑥)]}[(𝑦)] = 𝓖
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, we first abstract wrt &lt;code&gt;𝑥&lt;/code&gt;, then &lt;code&gt;𝑦&lt;/code&gt; and the result &lt;code&gt;𝓖&lt;/code&gt; is such that &lt;code&gt;(𝑦) (𝑥) 𝓖 = 𝓕&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that abstraction is defined with respect to a quoted variable as concatenative combinators are defined to only operate on quotes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstraction rules
&lt;/h2&gt;

&lt;p&gt;We'll use the following definitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;𝑥&lt;/code&gt; is a generic variable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓖&lt;/code&gt; is a non empty expression that &lt;em&gt;does not&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (i.e. &lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;does not occur&lt;/em&gt; in &lt;code&gt;𝓖&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓜&lt;/code&gt; is an expressions that &lt;em&gt;may&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (&lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;may occur&lt;/em&gt; in &lt;code&gt;𝓜&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓝&lt;/code&gt; is an expressions that &lt;em&gt;do&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (&lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;occurs&lt;/em&gt; in &lt;code&gt;𝓝&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given an expression, looking at the list of terms from left to right there can only be the following cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The expression is empty;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The expression can be split in two parts with first terms containing the variable &lt;code&gt;𝑥&lt;/code&gt; followed by other terms not containing &lt;code&gt;𝑥&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The expression can be split in two parts with first terms not containing the variable &lt;code&gt;𝑥&lt;/code&gt; followed by other terms containing &lt;code&gt;𝑥&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first term is a quote containing &lt;code&gt;𝑥&lt;/code&gt; (otherwise it would have been accounted for in case 3) followed by an expression containing &lt;code&gt;𝑥&lt;/code&gt; (otherwise it would have been accounted for in case 0);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first term is the variable &lt;code&gt;𝑥&lt;/code&gt; (unquoted).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This leads to the following abstraction rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     1           {}[(𝑥)] = zap
     2       {𝓝 𝓖}[(𝑥)] = {𝓝}[(𝑥)] 𝓖
     3       {𝓖 𝓝}[(𝑥)] = (𝓖) dip {𝓝}[(𝑥)]
     4    {(𝓝) 𝓜}[(𝑥)] = ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
     5       {𝑥 𝓜}[(𝑥)] = run {𝓜}[(𝑥)]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the expressions on the right side can't be reduced further without being applied to a quote.&lt;/p&gt;

&lt;p&gt;It's easy to prove, by induction on the length of the expressions, that the algorithm converges: at each step the expressions to be abstracted become smaller and smaller.&lt;/p&gt;

&lt;p&gt;In the following subsection we'll show that the rules do hold by applying them to &lt;code&gt;(𝑥)&lt;/code&gt; and checking that the result is, indeed, the original expression.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule 1
&lt;/h3&gt;

&lt;p&gt;This is the base case for when the expression is empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     1           {}[(𝑥)] = zap     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check that applying the result to (𝑥) we got the empty expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       (𝑥) zap
       ╰─────╯            by def. of zap
                      ◄── empty expression
       ╰╯                 by def. of abstraction
       (𝑥) {}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 2
&lt;/h3&gt;

&lt;p&gt;This rule allows us to stop earlier in the abstraction process: trailing terms not containing &lt;code&gt;𝑥&lt;/code&gt; can be left untouched.&lt;/p&gt;

&lt;p&gt;This is implied by the fact that the combinators are concatenative.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     2      {𝓝 𝓖}[(𝑥)] = {𝓝}[(𝑥)] 𝓖
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check that rule &lt;code&gt;2&lt;/code&gt; holds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     (𝑥) {𝓝}[(𝑥)] 𝓖
     ╰───────────╯        by definition of abstraction
     𝓝 𝓖
     ╰──╯                 by definition of abstraction
     (𝑥) {𝓝 𝓖}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 3
&lt;/h3&gt;

&lt;p&gt;This rule is to be applied when the expression consists of a list of terms which do not contain &lt;code&gt;𝑥&lt;/code&gt; followed by a list of terms which contain &lt;code&gt;𝑥&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     3      {𝓖 𝓝}[(𝑥)] = (𝓖) dip {𝓝}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To prove that this rule holds, let's apply it to &lt;code&gt;(𝑥)&lt;/code&gt; and check that the result is &lt;code&gt;𝓖 𝓝&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       (𝑥) (𝓖) dip {𝓝}[(𝑥)]
       ╰─────────╯                by def. of dip
       𝓖 (𝑥) {𝓝}[(𝑥)]
         ╰───────────╯            by def of abstraction
       𝓖 𝓝
       ╰──╯                       by def of abstraction
       (𝑥) {𝓖 𝓝}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 4
&lt;/h3&gt;

&lt;p&gt;This rule is to be applied when the expression consist of a quote that contains &lt;code&gt;𝑥&lt;/code&gt; followed by a list of terms which contain &lt;code&gt;𝑥&lt;/code&gt; (if they didn't we would have used rule 0).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     4    {(𝓝) 𝓜}[(𝑥)] = ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's apply it to &lt;code&gt;(𝑥)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       (𝑥) ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
       ╰──────────────────╯                by def. of cosp
       ((𝑥) {𝓝}[(𝑥)]) (𝑥) {𝓜}[(𝑥)]
        ╰───────────╯                      by def. of abstraction
       (𝓝) (𝑥) {𝓜}[(𝑥)]
           ╰────────────╯                  by def. of abstraction
       (𝓝) 𝓜
       ╰─────╯                             by def. of abstraction
       (𝑥) {(𝓝) 𝓜}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rule 5
&lt;/h3&gt;

&lt;p&gt;This is the rule to apply when the first term is &lt;code&gt;𝑥&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     5         {𝑥 𝓜}[(𝑥)] = run {𝓜}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To show that rules &lt;code&gt;5&lt;/code&gt; holds, let's apply it to &lt;code&gt;(𝑥)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               (𝑥) run {𝓜}[(𝑥)]
               ╰─────╯              by def. of run
               𝑥 (𝑥) {𝓜}[(𝑥)]
                 ╰───────────╯      by def. of abstraction
               𝑥 𝓜
               ╰──╯                 by def. of abstraction
               (𝑥) {𝑥 𝓜}[(𝑥)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Optimization
&lt;/h2&gt;

&lt;p&gt;The only optimization we mention here is the possibility of simplifying some special cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     3a         {𝓖}[(𝑥)] = zap 𝓖
     4a    {(𝑥) 𝓜}[(𝑥)] = dup {𝓜}[(𝑥)]
     4b      {(𝓝)}[(𝑥)] = ({𝓝}[(𝑥)]) cons
     4c       {(𝑥)}[(𝑥)] = 
     5a         {𝑥}[(𝑥)] = i

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They can be easily checked as we did in the previous section.&lt;/p&gt;

&lt;p&gt;Note that those special cases are included in the general case when one of the expressions is empty or has a special form.&lt;/p&gt;

&lt;p&gt;Let's give just one example that shows that rule &lt;code&gt;4b&lt;/code&gt; is &lt;em&gt;implied&lt;/em&gt; in rule &lt;code&gt;4&lt;/code&gt; when the expression 𝓜 is empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     4    {(𝓝) 𝓜}[(𝑥)] = ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
     4b      {(𝓝)}[(𝑥)] = ({𝓝}[(𝑥)]) cons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's easy to see that, under the assumption of 𝓜 being empty, the two are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  (𝑥) {(𝓝) 𝓜}[(𝑥)]
      ╰────────────╯                 by rule 4
  (𝑥) ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
                      ╰────────╯     by hypotesis that 𝓜 is empty
  (𝑥) ({𝓝}[(𝑥)]) cosp {}[(𝑥)]
  ╰──────────────────╯               by def. of cosp
  ((𝑥) ({𝓝}[(𝑥)])) (𝑥) {}[(𝑥)]
                       ╰──────╯      by rule 1
  ((𝑥) ({𝓝}[(𝑥)])) (𝑥) zap
                   ╰──────╯          by def. of zap
  ((𝑥) ({𝓝}[(𝑥)]))
  ╰───────────────╯                  by def. of cons
  (𝑥) ({𝓝}[(𝑥)]) cons
  ╰──────────────────╯               by rule 4b
  (𝑥) {(𝓝)}[(𝑥)] 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quotes
&lt;/h2&gt;

&lt;p&gt;As said at the beginning. combinators only operate on quotes.&lt;/p&gt;

&lt;p&gt;This is needed since (as in CL and 𝜆-calculus) there is no distinction between functions (programs) and data. Quotes are what make this distinction.&lt;/p&gt;

&lt;p&gt;Note that we have assumed that quotes are &lt;em&gt;transparent&lt;/em&gt;. i.e. that reductions may happen within a quote. This has the advantage that all expressions are reduced to their minimal form but also has the disadvantage of having to compute any single quotes even if they might be discarded at a later time. &lt;em&gt;Opaque&lt;/em&gt; quotes allow for lazy evaluation and the content of a quote is evaluated only when (and if) it is really needed, not before.&lt;/p&gt;

&lt;p&gt;From the abstraction algorithm there is no difference as the two type of quotes are equivalent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Church-Rosser theorem
&lt;/h2&gt;

&lt;p&gt;The Church-Rosser theorem, plays a key role in the evaluation of an expression and the fact that it holds for concatenative combinators is an assumption for the abstraction algorithm to work. It is also essential for the discussion on transparent/opaque quotes in the preceding section.&lt;/p&gt;

&lt;p&gt;It can be formulated in many different ways, this is one of them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let 𝓐 ⊳ 𝓑 be the reduction of the expression 𝓐 to the expression 𝓑; then&lt;br&gt;
𝓤 ⊳ 𝓧 ∧ 𝓤 ⊳ 𝓨 ⇒ ∃𝓩:  𝓧 ⊳ 𝓩 ∧ 𝓨 ⊳ 𝓩&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In plain words, if an expression 𝓤 can be reduced to two different expressions 𝓧 and 𝓨, then there is an expression 𝓩 to whom both 𝓧 and 𝓨 can be reduced.&lt;/p&gt;

&lt;p&gt;Which means that the strategy of reductions is irrelevant as any of them will lead to the same expression 𝓩.&lt;/p&gt;

&lt;p&gt;While the general proof of this theorem is quite complex, in our specific case (concatenative combinators that only act on quotes) it's pretty straightforwad to convince ourselves that the theorem holds.&lt;/p&gt;

&lt;p&gt;Let's consider the following expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          (𝓊) A (𝓋) B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are combinators and &lt;code&gt;𝓊&lt;/code&gt; and &lt;code&gt;𝓋&lt;/code&gt; are generic expressions.&lt;/p&gt;

&lt;p&gt;The only interesting case is when both of them can be reduced (i.e. they both are a &lt;em&gt;redex&lt;/em&gt;). Let's consider one step of reduction.&lt;/p&gt;

&lt;p&gt;If we reduce &lt;code&gt;(𝓊) A&lt;/code&gt;, there will be no consequence on &lt;code&gt;(𝓋) B&lt;/code&gt;, since it is already a redex.&lt;/p&gt;

&lt;p&gt;If we reduce &lt;code&gt;(𝓋) B&lt;/code&gt; the result can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a redex itself, which brings us in the same situation we were before the reduction,&lt;/li&gt;
&lt;li&gt;a non reducible expression like &lt;code&gt;(𝓈) (𝓉) C&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resulting expression &lt;code&gt;(𝓊) A (𝓈) (𝓉) C&lt;/code&gt; now contains only one redex (&lt;code&gt;(𝓊) A&lt;/code&gt;) because the combinator &lt;code&gt;C&lt;/code&gt; only operates on quotes and &lt;code&gt;A&lt;/code&gt; is unquoted.&lt;/p&gt;

&lt;p&gt;This reasoning can be repeated for a more general case but it's easy to see that the redex in an expression to do not interfere with each other and, hence, the order in which they are reduced is irrelevant for the end result.&lt;/p&gt;

&lt;p&gt;UPDATE: An AI-generated proof is now available &lt;a href="https://dev.to/rdentato/church-rosser-proof-for-ccl-c5l"&gt;here&lt;/a&gt;. Please check it and provide your feedback if you feel inclined to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have defined an abstraction algorithm for Concatenative combinators that is simple enough to be implemented and even applied by hand &lt;/p&gt;

&lt;p&gt;This frees us from the need to handle variables when using Concatenative Combinators.&lt;/p&gt;

&lt;p&gt;We have also argued around the validity of the Church-Rosser theorem that is an assumption for the abstraction algorithm to work.&lt;/p&gt;

&lt;p&gt;Here are the list of all the abstraction rules (including the special cases):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     1           {}[(𝑥)] = zap
     2       {𝓝 𝓖}[(𝑥)] = {𝓝}[(𝑥)] 𝓖
     3       {𝓖 𝓝}[(𝑥)] = (𝓖) dip {𝓝}[(𝑥)]
     3a         {𝓖}[(𝑥)] = zap 𝓖
     4    {(𝓝) 𝓜}[(𝑥)] = ({𝓝}[(𝑥)]) cosp {𝓜}[(𝑥)]
     4a    {(𝑥) 𝓜}[(𝑥)] = dup {𝓜}[(𝑥)]
     4b      {(𝓝)}[(𝑥)] = ({𝓝}[(𝑥)]) cons
     4c       {(𝑥)}[(𝑥)] = 
     5       {𝑥 𝓜}[(𝑥)] = run {𝓜}[(𝑥)]
     5a         {𝑥}[(𝑥)] = i


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;𝑥&lt;/code&gt; is a generic variable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓖&lt;/code&gt; is a non empty expression that &lt;em&gt;does not&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (i.e. &lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;does not occur&lt;/em&gt; in &lt;code&gt;𝓖&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓜&lt;/code&gt; is an expressions that &lt;em&gt;may&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (&lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;may occur&lt;/em&gt; in &lt;code&gt;𝓜&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;𝓝&lt;/code&gt; is an expressions that &lt;em&gt;do&lt;/em&gt; contain &lt;code&gt;𝑥&lt;/code&gt;
   (&lt;code&gt;𝑥&lt;/code&gt; &lt;em&gt;occurs&lt;/em&gt; in &lt;code&gt;𝓝&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bibliography
&lt;/h2&gt;

&lt;p&gt;[1]  &lt;em&gt;The Theory of Concatenative Combinators&lt;/em&gt;,&lt;br&gt;
     Brent Kerby (bkerby at byu dot net).&lt;br&gt;
     Completed June 19, 2002. Updated February 5, 2007.&lt;br&gt;
     (&lt;a href="http://tunes.org/~iepos/joy.html" rel="noopener noreferrer"&gt;link&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;[2]  &lt;em&gt;Lambda-Calculus and Combinators, an introduction&lt;/em&gt;,&lt;br&gt;
     J. Roger Hindley, Jonathan P. Seldin&lt;br&gt;
     (&lt;a href="http://www.cambridge.org/9780521898850" rel="noopener noreferrer"&gt;link&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>concatenative</category>
    </item>
    <item>
      <title>A Simple Unit Test Framework for C</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Thu, 12 Oct 2023 19:29:10 +0000</pubDate>
      <link>https://dev.to/rdentato/minimal-unit-test-framework-for-c-46h4</link>
      <guid>https://dev.to/rdentato/minimal-unit-test-framework-for-c-46h4</guid>
      <description>&lt;h1&gt;
  
  
  &lt;code&gt;tst&lt;/code&gt;: A Simple Unit Testing Framework for C
&lt;/h1&gt;

&lt;p&gt;Every developer understands the undeniable importance of unit testing. While crafting a piece of software, it's equally crucial to ensure that it functions as intended. For those working in C, a myriad of testing frameworks abound, but I found them quite complex to use and had to write my own, single header unit testing framework.&lt;/p&gt;

&lt;p&gt;You can find the entire project on &lt;a href="https://github.com/rdentato/tst" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why &lt;code&gt;tst&lt;/code&gt;?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At first glance, &lt;code&gt;tst&lt;/code&gt; might seem like just another testing tool in an ocean of options. However, a closer look reveals its carefully thought out features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimalistic Design&lt;/strong&gt;: One of &lt;code&gt;tst&lt;/code&gt;'s standout features is its no-nonsense, clean design. There aren't any complicated configurations to wrestle with or convoluted syntaxes to learn. Everything is straightforward, making it an ideal choice for developers who appreciate simplicity and efficiency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility in Grouping and Tagging&lt;/strong&gt;: With &lt;code&gt;tst&lt;/code&gt;, you can effortlessly tag and group tests, allowing for selective test executions. You can select which group of tests to execute via argument on the command line, this becomes an invaluable asset for large projects where running the entire test suite can be time-consuming. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Integration&lt;/strong&gt;: Incorporating &lt;code&gt;tst&lt;/code&gt; into your project couldn't be simpler. Just create a dedicated &lt;code&gt;test&lt;/code&gt; directory, place the &lt;code&gt;tst.h&lt;/code&gt; header and you're done. Each test will be a single program designed to check that some aspect of the program is working properly.&lt;br&gt;
I've added a &lt;code&gt;makefile&lt;/code&gt; to simplify the management of test. If you add a file named &lt;code&gt;t_xxx.c&lt;/code&gt; in the test directory, it will be assumed to be a test and you can compile it with &lt;code&gt;make t_xxx&lt;/code&gt;. With &lt;code&gt;make runtest&lt;/code&gt; you will compile and execute all the tests in the directory that follow the naming convention.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expressive Reporting&lt;/strong&gt;: The framework produces a clear, concise, and informative reports. Each test outcome is reported, making it easy to pinpoint issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Function Highlights&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Tst&lt;/code&gt; comes packed with intuitive functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstrun( ... )&lt;/strong&gt;: Groups and begins test execution, often used to enclose all tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstcase( ... )&lt;/strong&gt;: Define individual test cases with descriptive titles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstcheck(int test, ... )&lt;/strong&gt;: Performs a test check and reports pass/fail status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstassert(int test, ... )&lt;/strong&gt;: Similar to &lt;code&gt;tstcheck&lt;/code&gt;, but halts the entire test suite upon a failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstgroup(int test, ... )&lt;/strong&gt;: A conditional test group. If the initial test is false, the entire group is skipped.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstclk( ... )&lt;/strong&gt;: Times and reports how long a block of code takes to execute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstdata( ... ) and tstnote( ... )&lt;/strong&gt;: Provide additional data or notes for context within your test report.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tsttags( ... )&lt;/strong&gt;: Specify the tags that are defined for selective disabling/enabling of groups of tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tstsettags(int argc, char **argv)&lt;/strong&gt;: Enable/Disable the tags according to what specified on the command line. For example, to disable tests that are related to MongoDB or files:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  my_test -UseMongDB -UseFiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;tsttag(tag)&lt;/strong&gt;: checks if a group of tests is enabled. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   tstgroup(tsttag(UseMongoDB)) {
      // To be executed if the `UseMongoDB` group is enabled
   }

   tstgroup(!tsttag(UseFiles)) {
      // To be executed if the `UseFiles` group is disabled
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;A Practical Dive&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's dive into a practical example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;tstrun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;tstcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Basic Arithmetic Checks"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tstcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Addition seems off!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;tstcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Multiplication isn't working as expected"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;tstcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Subtraction has an issue!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// This will fail!&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon executing the above, &lt;code&gt;tst&lt;/code&gt; produces a clean output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FILE ▷ basic_arith.c 
CASE┬── Basic Arithmetic Checks » basic_arith.c:4
PASS│  1 + 1 == 2 » basic_arith.c:5
PASS│  2 * 3 == 6 » basic_arith.c:6
FAIL├┬ 2 - 2 == 1 » basic_arith.c:7
    │╰  Subtraction has an issue!
    ╰── 1 KO | 2 OK | 0 SKIP
RSLT ▷ 1 KO | 2 OK | 0 SKIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The report is crystal clear in identifying the problem. The failing test is flagged, and its associated message pinpoints the issue, all while indicating the precise file and line number.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Tst&lt;/code&gt; goes beyond just being a testing framework; it’s an advocate for efficient and effective software development. It strips away complexities, leaving developers with a pure, straightforward testing experience. Whether you're a seasoned C developer or just beginning your coding journey, &lt;code&gt;tst&lt;/code&gt; has something valuable to offer. Dive into it, and you might soon find it becoming an indispensable part of your development process.&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
      <category>c</category>
      <category>unittest</category>
      <category>testing</category>
    </item>
    <item>
      <title>What's in a C (NaN)box?</title>
      <dc:creator>Remo Dentato</dc:creator>
      <pubDate>Sun, 01 Oct 2023 10:16:27 +0000</pubDate>
      <link>https://dev.to/rdentato/whats-in-a-c-box-1ib4</link>
      <guid>https://dev.to/rdentato/whats-in-a-c-box-1ib4</guid>
      <description>&lt;p&gt;Most modern scripting languages use &lt;em&gt;dynamic types&lt;/em&gt;: values carry a type (an integer, a decimal number, a string, ...) but variables don't. So you can write code like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.3&lt;/span&gt;
   &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful when you have an array whose elements can be of different types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.3&lt;/span&gt;
   &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alas, we C programmers do not have this luxury. Variables are typed and if, for example, your array need to contain values that can be integers, doubles or pointers, you are on your own.&lt;/p&gt;

&lt;p&gt;Typically, this is solved by squeezing multiple values into a &lt;code&gt;union&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 8 bytes&lt;/span&gt;
     &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 4 bytes (most likely)&lt;/span&gt;
     &lt;span class="kt"&gt;void&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 8 bytes on 64-bits arch&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;myval_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// The entire union will occupy 8 bytes&lt;/span&gt;

  &lt;span class="n"&gt;myval_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The previous value is overwritten&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;union&lt;/code&gt; will be big enough to contain the biggest type it needs to contain; in the example above the &lt;code&gt;union&lt;/code&gt; will be (most likely) 8 bytes. I say "most likely" because the C standard does not mandate how unions will be packed but overlapping the values it's the common way to go.&lt;/p&gt;

&lt;p&gt;To set or get a value, you will access the proper field: &lt;code&gt;v.d&lt;/code&gt; for the &lt;code&gt;double&lt;/code&gt;, &lt;code&gt;v.p&lt;/code&gt; for the pointer and so on.&lt;/p&gt;

&lt;p&gt;The problem is: "How can I know the type of the value?" The answer is simple: "You can't!"&lt;/p&gt;

&lt;p&gt;If you need to do it, usually the type is stored explictly together with the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="cp"&gt;#define VALTYPE_DOUBLE  1
&lt;/span&gt;  &lt;span class="cp"&gt;#define VALTYPE_INTEGER 2
&lt;/span&gt;  &lt;span class="cp"&gt;#define VALTYPE_POINTER 3
&lt;/span&gt;
  &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// type&lt;/span&gt;
     &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kt"&gt;void&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;myval_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;myval_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VALTYPE_DOUBLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with this approach, besides having to update multiple fields, is that it's way to wasteful! An additional integer for each value you want to store!&lt;/p&gt;

&lt;p&gt;In fact, this is not the way modern scripting languages do it. They use a neat trick called &lt;em&gt;NaNBoxing&lt;/em&gt; which, to my shame, I was completely ignorant of until recently!&lt;/p&gt;

&lt;p&gt;Once I got to know it, I had to implement a small header library C (available &lt;a href="https://github.com/rdentato/val" rel="noopener noreferrer"&gt;on Github&lt;/a&gt;).&lt;br&gt;
It allows writing code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="n"&gt;val_t&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; 

  &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my string"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// of course just the pointer, this is C!&lt;/span&gt;
  &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valisdouble&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do some double-y thing&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valisinteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do some int-ey thing&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll describe here how the library is used, the implementation details will come on a future post (hopefully).&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;val_t&lt;/code&gt; type
&lt;/h2&gt;

&lt;p&gt;After including the header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"val.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you will have a new data type &lt;code&gt;val_t&lt;/code&gt; that can store a value of different types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signed or unsigned integers (up to 48 bits)&lt;/li&gt;
&lt;li&gt;Double-precision floating-point numbers&lt;/li&gt;
&lt;li&gt;Booleans. There are two constants defined: &lt;code&gt;valtrue&lt;/code&gt; and &lt;code&gt;valfalse&lt;/code&gt; which are different from any integer.&lt;/li&gt;
&lt;li&gt;Nil. A constant different from any integer or boolean.&lt;/li&gt;
&lt;li&gt;Generic pointers&lt;/li&gt;
&lt;li&gt;Pointers to strings (&lt;code&gt;char *&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library provides a &lt;code&gt;val()&lt;/code&gt; function to store values into a &lt;code&gt;val_t&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;val_t&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// Stores a double value&lt;/span&gt;
&lt;span class="n"&gt;val_t&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a string"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Stores a pointer to a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the details on storing the type, etc are handled by &lt;code&gt;val()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve values
&lt;/h3&gt;

&lt;p&gt;Once your data is safely stored inside a &lt;code&gt;val_t&lt;/code&gt; variable, you can retrieve it utilizing specific type conversion functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;void * valtopointer(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;double valtodouble(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;float valtofloat(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_Bool valtobool(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;long valtointeger(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;char * valtostring(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and cast it as needed. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;val_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                 &lt;span class="c1"&gt;// stored a float&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;valtodouble&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// retrieved a float&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Constants for Common Scenarios
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;val&lt;/code&gt; library defines certain constants of type &lt;code&gt;val_t&lt;/code&gt; to handle common scenarios and default values gracefully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;valfalse&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;valtrue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;valnil&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;valnilpointer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;valnilstr&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Identifying the Stored Type
&lt;/h3&gt;

&lt;p&gt;Determining the type of data stored within a &lt;code&gt;val_t&lt;/code&gt; variable can be done using the &lt;code&gt;valtype()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;valtype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val_t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns one of these constants, each indicative of the nature of the stored data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VALDOUBLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VALINTEGER&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VALBOOL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VALNIL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VALPOINTER&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VALSTRING&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more context-specific checks, you might utilize a suite of helper functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;int valisnil(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valisinteger(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valissigned(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valisbool(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valisdouble(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valispointer(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int valisstring(val_t v);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;val&lt;/code&gt; library opens the doors to a world where C programmers can bask in the flexibility that is common of dynamically-typed languages like JavaScript. &lt;/p&gt;

&lt;p&gt;Through utilization of the &lt;code&gt;val&lt;/code&gt; library, developers can store and manage diverse data types without the need for complex, memory-consuming data structures, thereby achieving more with less.&lt;/p&gt;

&lt;p&gt;Next post will deep dive into the NaNboxing details.&lt;/p&gt;

</description>
      <category>c</category>
      <category>nanboxing</category>
    </item>
  </channel>
</rss>
