<?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: Magne</title>
    <description>The latest articles on DEV Community by Magne (@redbar0n).</description>
    <link>https://dev.to/redbar0n</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%2F406028%2Fa56c0fb3-0a2c-492a-85ca-5e74b4f151ea.jpg</url>
      <title>DEV Community: Magne</title>
      <link>https://dev.to/redbar0n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/redbar0n"/>
    <language>en</language>
    <item>
      <title>Meta-Programming and Macro capabilities of various languages</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Thu, 02 Apr 2026 19:26:15 +0000</pubDate>
      <link>https://dev.to/redbar0n/meta-programming-and-macro-capabilities-of-various-languages-1hgd</link>
      <guid>https://dev.to/redbar0n/meta-programming-and-macro-capabilities-of-various-languages-1hgd</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meta-programming&lt;/strong&gt; = &lt;em&gt;the broad idea of “programs that manipulate or generate programs”&lt;/em&gt;. It can happen at runtime (reflection) or compile-time (macros).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Macros&lt;/strong&gt; = &lt;em&gt;one specific style of meta-programming, usually tied to transforming syntax at compile time (in a pre-processor or AST-transformer).&lt;/em&gt; It takes a piece of code as input and replaces it with another piece of code as output, often based on patterns or parameters. Macros consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rule‑based transformation: A macro is specified as a pattern (e.g., a template, an AST pattern, or token pattern) plus a replacement that is generated when that pattern is matched.&lt;/li&gt;
&lt;li&gt;Expansion, not function call: Macro use is not a runtime call; the macro is expanded before execution, so the final code is the result of replacing the macro invocation with its generated code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some programming languages and their meta-programming and macro capabilities.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;NB!&lt;/strong&gt; Take with a grain of salt. The result comes from working with &lt;strong&gt;perplexity.ai&lt;/strong&gt;, and I have not had a chance to personally verify all of the cells. They do look generally correct to me overall, though. Corrections are welcome!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Metaprogramming + macro features
&lt;/h3&gt;

&lt;p&gt;Here are the programming languages with their scores (out of 15) and links to their repos or homepages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/racket/racket" rel="noopener noreferrer"&gt;Racket&lt;/a&gt;&lt;/strong&gt;: 15
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://lisp-lang.org/" rel="noopener noreferrer"&gt;Common Lisp (CL)&lt;/a&gt;&lt;/strong&gt;: 13
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://small.r7rs.org/" rel="noopener noreferrer"&gt;Scheme (R7RS‑small)&lt;/a&gt;&lt;/strong&gt;: 12
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/rust%E2%80%91lang/rust" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;&lt;/strong&gt;: 11
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nim%E2%80%91lang/Nim" rel="noopener noreferrer"&gt;Nim&lt;/a&gt;&lt;/strong&gt;: 10
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/clojure/clojure" rel="noopener noreferrer"&gt;Clojure&lt;/a&gt;&lt;/strong&gt;: 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/carp-lang/Carp" rel="noopener noreferrer"&gt;Carp&lt;/a&gt;&lt;/strong&gt;: 9&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md" rel="noopener noreferrer"&gt;Jai&lt;/a&gt;&lt;/strong&gt;: 5
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://isocpp.org/" rel="noopener noreferrer"&gt;C++&lt;/a&gt;&lt;/strong&gt;: 5
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ziglang/zig" rel="noopener noreferrer"&gt;Zig&lt;/a&gt;&lt;/strong&gt;: 4
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ruby/ruby" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt;&lt;/strong&gt;: 4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scores are out of 15 = 4 (metaprogramming) + 3 (compile‑time facilities) + 8 (macro features).&lt;/p&gt;

&lt;p&gt;Each cell is either &lt;code&gt;✅&lt;/code&gt; (yes) or &lt;code&gt;–&lt;/code&gt; (no / limited).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / language&lt;/th&gt;
&lt;th&gt;Racket&lt;/th&gt;
&lt;th&gt;Common Lisp&lt;/th&gt;
&lt;th&gt;Scheme (R7RS‑small)&lt;/th&gt;
&lt;th&gt;Rust&lt;/th&gt;
&lt;th&gt;Nim&lt;/th&gt;
&lt;th&gt;Clojure&lt;/th&gt;
&lt;th&gt;Carp&lt;/th&gt;
&lt;th&gt;Jai&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Zig &lt;code&gt;comptime&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Metaprogramming features:&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime metaprogramming (e.g., open classes, &lt;code&gt;define_method&lt;/code&gt;, method hooks)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime reflection / introspection&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime &lt;code&gt;eval&lt;/code&gt; / dynamic code loading&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build‑ or tooling‑level code generation supported&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Metaprogramming score (out of 4):&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compile‑time facilities (not strictly macros):&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Racket&lt;/td&gt;
&lt;td&gt;Common Lisp&lt;/td&gt;
&lt;td&gt;Scheme (R7RS‑small)&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Nim&lt;/td&gt;
&lt;td&gt;Clojure&lt;/td&gt;
&lt;td&gt;Carp&lt;/td&gt;
&lt;td&gt;Jai&lt;/td&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;Zig &lt;code&gt;comptime&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run arbitrary code at compile time&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (&lt;code&gt;constexpr&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Types as values at compile time&lt;/td&gt;
&lt;td&gt;✅ (– but in Typed Racket)&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (&lt;code&gt;constexpr&lt;/code&gt; + templates)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;constexpr‑style type‑level / compile‑time computation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅ (&lt;code&gt;const&lt;/code&gt;‑eval)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (via &lt;code&gt;constexpr&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Macro features:&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hygienic identifier binding&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (gensym but manual)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operate on AST / syntax tree&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pattern‑based transformations&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Define new syntactic forms&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Define new keywords / syntax&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Override core language forms&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi‑phase / macros of macros&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full‑fledged DSL / language building (via macros)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macro &amp;amp; compile time features score (out of 11)&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Racket&lt;/td&gt;
&lt;td&gt;Common Lisp&lt;/td&gt;
&lt;td&gt;Scheme (R7RS‑small)&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Nim&lt;/td&gt;
&lt;td&gt;Clojure&lt;/td&gt;
&lt;td&gt;Carp&lt;/td&gt;
&lt;td&gt;Jai&lt;/td&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;Zig &lt;code&gt;comptime&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;The score counts one point per row where the language can reasonably do what the feature describes (DSL‑building is counted as a full feature, even if “limited” in some languages).&lt;/p&gt;

&lt;p&gt;The feature score is not an ultimate measure of meta-programming power, since a language (like C++) may have a higher score than another language (like Ruby), but generally be considered less tailored for meta-programming than the other language (Ruby is generally revered for its powerful meta-programming abilities).&lt;/p&gt;

&lt;p&gt;Macro features are varied and many, and thus in the total score they gain an undue weight, although runtime meta-programming may be just as, or even more, powerful.&lt;/p&gt;

&lt;p&gt;Lisp-style languages (with their homoiconic S-expressions) make out 5 of the 11 languages in our list: Racket, CL, Scheme, Clojure, Carp.&lt;/p&gt;

&lt;p&gt;For further reading: &lt;a href="https://github.com/oils-for-unix/oils/wiki/Metaprogramming" rel="noopener noreferrer"&gt;https://github.com/oils-for-unix/oils/wiki/Metaprogramming&lt;/a&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>ReScript vs. Melange</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Mon, 16 Mar 2026 16:05:04 +0000</pubDate>
      <link>https://dev.to/redbar0n/rescript-vs-melange-2h90</link>
      <guid>https://dev.to/redbar0n/rescript-vs-melange-2h90</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;rescript vs melange in 2026? which to choose and when?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perplexity.ai answered (which was so good I decided to reshare it):&lt;/p&gt;

&lt;p&gt;In 2026, Melange is the better fit if you want OCaml-first, dune/opam integration and sharing code with a backend; ReScript is better if you want a JS/TypeScript-team-friendly language that targets the JS ecosystem directly. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How they differ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ecosystem focus&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melange: Part of the OCaml world, installed via opam, built with dune, works with ocaml-lsp, ppxlib, etc., and compiles OCaml/Reason to JS. &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ReScript: JS-centric, distributed via npm as prebuilt binaries, positioned as an alternative to TypeScript with strong JS interop. &lt;a href="https://discuss.ocaml.org/t/what-is-actually-going-on-now-with-reasonml-and-rescript/13973" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Language and tooling:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melange: Uses standard OCaml (or Reason) syntax, leverages OCaml’s type system and tooling; editor support comes “for free” via the OCaml LSP stack. &lt;a href="https://discuss.ocaml.org/t/whats-possible-with-melange/13806" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ReScript: Its own syntax and compiler, historically diverged from Reason/OCaml; has its own editor tooling and build story, more familiar to JS devs but less aligned with OCaml tooling. &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Advanced features &amp;amp; evolution:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ReScript is adding features geared to JS devs like async/await syntax, new representation options, and improvements in JS interop, sometimes at the expense of OCaml compatibility. &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Melange maintains compatibility with OCaml versions and tooling, so it deliberately does not adopt features that would break that alignment. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Interop and code sharing:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melange: Excellent if you want to share types and modules between OCaml backend and JS frontend (via dune, virtual libraries, etc.). &lt;a href="https://discuss.ocaml.org/t/ahrefs-is-now-built-with-melange/12107" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ReScript: Excellent if you primarily integrate with existing JS/React/Node codebases and care less about reusing OCaml libraries. &lt;a href="https://discuss.ocaml.org/t/what-is-actually-going-on-now-with-reasonml-and-rescript/13973" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to choose Melange
&lt;/h2&gt;

&lt;p&gt;Pick Melange if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You already use OCaml on the backend and want a unified language and tooling front-to-back. &lt;a href="https://discuss.ocaml.org/t/ahrefs-is-now-built-with-melange/12107" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You want dune, opam, ocaml-lsp, ppxlib, and the wider OCaml ecosystem to “just work.” &lt;a href="https://discuss.ocaml.org/t/whats-possible-with-melange/13806" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You value readable, modular JS output and are comfortable with OCaml-style development rather than JS-style toolchains. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You may want to keep using Reason syntax or standard OCaml syntax with JSX via community dialects. &lt;a href="https://dev.to/psb/getting-started-with-reasonreact-and-melange-13hd"&gt;dev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A concrete example: an OCaml-heavy company like Ahrefs moving their frontend to Melange to align frontend and backend while still using JS UI libraries. &lt;a href="https://discuss.ocaml.org/t/ahrefs-is-now-built-with-melange/12107" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When to choose ReScript
&lt;/h2&gt;

&lt;p&gt;Pick ReScript if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your team is primarily JavaScript/TypeScript developers, and you want something that feels like “better TypeScript” with strong static typing but JS-first ergonomics. &lt;a href="https://www.reddit.com/r/ocaml/comments/1c4cts8/rescript_ruined_ocaml_for_web_momentum/" rel="noopener noreferrer"&gt;reddit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Your codebase and ecosystem are mostly JS/React, and you don’t need deep OCaml-library reuse or dune/opam integration. &lt;a href="https://discuss.ocaml.org/t/what-is-actually-going-on-now-with-reasonml-and-rescript/13973" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You are happy to follow ReScript’s language evolution, even when it diverges from OCaml (syntax and features). &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example: a React SPA team that already lives in npm, Webpack/Vite, and JS tooling, adopting ReScript as a typed language close to their current stack. &lt;a href="https://discuss.ocaml.org/t/what-is-actually-going-on-now-with-reasonml-and-rescript/13973" rel="noopener noreferrer"&gt;discuss.ocaml&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick decision matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Choose&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OCaml backend, want shared types/libs with frontend&lt;/td&gt;
&lt;td&gt;Melange&lt;/td&gt;
&lt;td&gt;OCaml ecosystem integration, dune/opam, same language everywhere. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Existing JS/React app, TS-style team&lt;/td&gt;
&lt;td&gt;ReScript&lt;/td&gt;
&lt;td&gt;JS-first tooling, npm distribution, TS-competitor positioning. &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy use of OCaml ppx, advanced OCaml tooling&lt;/td&gt;
&lt;td&gt;Melange&lt;/td&gt;
&lt;td&gt;Full ppxlib and dune support, aligned with OCaml compiler. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You don’t care about OCaml, just want a typed JS language&lt;/td&gt;
&lt;td&gt;ReScript&lt;/td&gt;
&lt;td&gt;Focus on JS interop and language features tailored to JS devs. &lt;a href="https://sancho.dev/blog/whats-possible-with-melange" rel="noopener noreferrer"&gt;sancho&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term bet on OCaml ecosystem (editor, libs, community)&lt;/td&gt;
&lt;td&gt;Melange&lt;/td&gt;
&lt;td&gt;Developed as an OCaml JS backend, maintained in OCaml community. &lt;a href="https://github.com/melange-re/melange" rel="noopener noreferrer"&gt;github&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you tell me more about your current stack (OCaml vs JS, build tool, hosting, team background), I can map you to a very specific recommendation and migration path.&lt;/p&gt;

</description>
      <category>rescript</category>
      <category>melange</category>
      <category>ocaml</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why did OOP become popular (from a DX perspective)?</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Mon, 27 Oct 2025 15:54:15 +0000</pubDate>
      <link>https://dev.to/redbar0n/why-did-oop-become-popular-from-a-dx-perspective-1b58</link>
      <guid>https://dev.to/redbar0n/why-did-oop-become-popular-from-a-dx-perspective-1b58</guid>
      <description>&lt;p&gt;My thoughts:&lt;/p&gt;

&lt;p&gt;I propose OOP (class-based, C++, Java, etc.) became popular (more so than FP) because of these DX concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intuitiveness&lt;/strong&gt;: humans typically objectify the world (&lt;a href="https://en.wikipedia.org/wiki/Objectification" rel="noopener noreferrer"&gt;objectification&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Essentialism" rel="noopener noreferrer"&gt;essentialism&lt;/a&gt;). GUI's could naturally be described in OO terms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessibility&lt;/strong&gt;: It made access/namespacing easy: if you had an object, you could easily and automatically find its behaviors/methods (autocomplete!). It provided even easier (more accessible and natural) modularization than modules with functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain modeling&lt;/strong&gt;: It enabled domain modeling (in the language of objects in the domain). Aligned with GUI development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organisation&lt;/strong&gt;: It facilitated code organisation and organisational compartmentalization (coupled behavior to data and encapsulated it). "You are responsible for those things" (vs. the better: "you are responsible for those flows / use cases"). Encapsulation made teams able to refactor internals while the interface/API remained a stable contract (enabling parallel development).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: It allowed mutation (merged with imperative/procedural), which didn't compromise on performance (in perf constrained environments and popular applications like games etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Predictability and reuse&lt;/strong&gt;: Classes provided a clear interface/template for data, which made handling similar kinds of data more predictable and reusable (inheritance and polymorphism).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Perplexity.ai answer:&lt;/p&gt;

&lt;p&gt;Object-oriented programming (OOP) became popular from a developer experience (DX) perspective because it made code more modular, reusable, and maintainable, which are all critical for effective teamwork and long-term project growth. The ability to encapsulate data and abstract away complexity led to simplified development, easier code updates, and clearer project organization.&lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt; &lt;a href="https://www.sitepoint.com/community/t/why-is-object-oriented-programming-so-popular/437620" rel="noopener noreferrer"&gt;7&lt;/a&gt; &lt;a href="https://mindmatters.ai/2023/06/why-is-object-oriented-programming-popular/" rel="noopener noreferrer"&gt;8&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core DX Benefits of OOP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: OOP lets developers organize code into distinct, logical units (objects), helping teams work on separate pieces independently without interfering with each other's work.&lt;a href="https://www.sitepoint.com/community/t/why-is-object-oriented-programming-so-popular/437620" rel="noopener noreferrer"&gt;7&lt;/a&gt; &lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusability&lt;/strong&gt;: Features like inheritance and polymorphism allow programmers to reuse code, reducing repetition and saving time across projects.&lt;a href="https://www.reddit.com/r/C_Programming/comments/blbkk0/why_is_coop_so_popular_when_according_to_lots_of/" rel="noopener noreferrer"&gt;6&lt;/a&gt; &lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: With encapsulation, internal details are hidden, making bugs easier to locate and fix while protecting sensitive data from unexpected changes.&lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstraction&lt;/strong&gt;: Developers interact with objects through clear interfaces, reducing the cognitive load and making it simpler to teach, understand, and extend codebases.&lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-World Modeling&lt;/strong&gt;: OOP enables clearer modeling of real-world concepts, making complex domains easier to translate into software structures.&lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;3&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Developers Chose OOP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Applications built with OOP could more easily adapt to growing requirements and changes, speeding up both feature development and troubleshooting.&lt;a href="https://www.sitepoint.com/community/t/why-is-object-oriented-programming-so-popular/437620" rel="noopener noreferrer"&gt;7&lt;/a&gt; &lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Team Collaboration&lt;/strong&gt;: OOP’s structure facilitated parallel development, letting larger teams contribute without merging conflicts or breaking core functionality.&lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Industry Adoption&lt;/strong&gt;: The prevalence of popular OOP languages (Java, C++, Python) further reinforced its spread, as developers preferred tools with strong IDE, library, and community support.&lt;a href="https://stackoverflow.blog/2020/09/02/if-everyone-hates-it-why-is-oop-still-so-widely-spread/" rel="noopener noreferrer"&gt;5&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GUI and Event-Driven Programming&lt;/strong&gt;: As user interfaces became central, OOP patterns fit naturally for modeling buttons, menus, and interactive elements.&lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;3&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These factors combined to make OOP a dominant paradigm, not only for technical reasons but also because it dramatically improved how developers experienced, managed, and scaled software projects.&lt;a href="https://mindmatters.ai/2023/06/why-is-object-oriented-programming-popular/" rel="noopener noreferrer"&gt;8&lt;/a&gt; &lt;a href="https://www.sitepoint.com/community/t/why-is-object-oriented-programming-so-popular/437620" rel="noopener noreferrer"&gt;7&lt;/a&gt; &lt;a href="https://www.webcreek.com/en/blog/software-development/object-oriented-programming-languages-key-features-and-benefits/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Why did FP not become as popular as OOP (from a DX perspective)?
&lt;/h1&gt;

&lt;p&gt;Functional programming (FP) has not achieved the same mainstream popularity as object-oriented programming (OOP) from a developer experience (DX) perspective due to key challenges around approachability, mental models, and ecosystem adoption. &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt; &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges for FP Adoption
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steeper Learning Curve&lt;/strong&gt;: FP relies on abstract concepts like pure functions, immutability, and recursion, which are less intuitive for many developers, especially beginners. OOP's object-based approach more closely mirrors how people think about real-world entities, making it easier for teams to learn and collaborate. &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt; &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mental Model Differences&lt;/strong&gt;: FP separates data from behavior and avoids state changes. While this leads to safer and more predictable code, it can complicate scenarios involving shared state, like working with files, databases, or real-time data streams, which often require side effects. &lt;a href="https://www.reddit.com/r/ProgrammingLanguages/comments/tv3ltp/functional_programming_vs_object_oriented/" rel="noopener noreferrer"&gt;[2]&lt;/a&gt; &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling and Ecosystem&lt;/strong&gt;: OOP languages such as Java, C++, and Python dominated industry adoption, offering richer IDE support, better documentation, and large communities, which further improved DX. FP languages often lacked these advantages in mainstream business contexts. &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readability and Maintainability&lt;/strong&gt;: While FP offers concise code, excessive use of higher-order functions and recursion can make code harder to read and debug for those unfamiliar with the paradigm, leading to slower onboarding and more confusion for teams. &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State and Mutability Needs&lt;/strong&gt;: Many practical business applications require direct management of state and mutable data. OOP’s encapsulation and state-handling patterns are often more effective and familiar for developers building GUIs, games, and large systems with complex interactions. &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt; &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key DX Differences: FP vs OOP
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;OOP (DX) Advantage&lt;/th&gt;
&lt;th&gt;FP (DX) Challenge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Learning &amp;amp; Onboarding&lt;/td&gt;
&lt;td&gt;Easy to explain objects/entities &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Abstract maths concepts (recursion, immutability) &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt; &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Organization&lt;/td&gt;
&lt;td&gt;Modular, extensible codebases &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Compact but may be harder to maintain &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community &amp;amp; Tooling&lt;/td&gt;
&lt;td&gt;Larger libraries, better IDE support &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Smaller, academia-focused communities &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State Handling&lt;/td&gt;
&lt;td&gt;Direct and familiar (classes/fields) &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Avoids mutation, harder with shared state &lt;a href="https://www.reddit.com/r/ProgrammingLanguages/comments/tv3ltp/functional_programming_vs_object_oriented/" rel="noopener noreferrer"&gt;[2]&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance &amp;amp; Memory&lt;/td&gt;
&lt;td&gt;Efficient for complex, mutable systems &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Overhead from immutability &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These factors made FP less attractive for DX in most mainstream software development contexts, even though it excels in niche domains such as data transformation and concurrent processing. &lt;a href="https://www.youtube.com/watch?v=wyABTfR9UTU" rel="noopener noreferrer"&gt;[4]&lt;/a&gt; &lt;a href="https://codefinity.com/blog/Functional-Programming-vs-Object-Oriented-Programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; &lt;a href="https://www.datacamp.com/tutorial/functional-programming-vs-object-oriented-programming" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  How could a new FP language have at least as good DX as OOP without being OOP?
&lt;/h1&gt;

&lt;p&gt;A new functional programming (FP) language could achieve developer experience (DX) at least as good as object-oriented programming (OOP) without actually becoming OOP by focusing on several key design principles and usability enhancements. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; &lt;a href="https://www.theserverside.com/tip/Understanding-the-principles-of-functional-programming" rel="noopener noreferrer"&gt;[2]&lt;/a&gt; &lt;a href="https://theory.stanford.edu/~aiken/publications/trs/FLProject.pdf" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Essential Features for Superior FP DX
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intuitive Syntax and Ergonomics&lt;/strong&gt;: Adopt clean, readable syntax that lowers the cognitive barrier for newcomers, with familiar constructs for both beginners and experts. &lt;a href="https://theory.stanford.edu/~aiken/publications/trs/FLProject.pdf" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich Tooling and IDE Support&lt;/strong&gt;: Provide high-quality debuggers, static analysis, code completion, and refactoring tools, matching the ecosystem strengths of OOP languages. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit and Powerful Data Modeling&lt;/strong&gt;: Offer strong, expressive types, pattern matching, and algebraic data types so that developers can model business domains naturally, much like classes/objects in OOP, but with immutable data. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear State Management&lt;/strong&gt;: Include ergonomic mechanisms (perhaps via monads, effects, or built-in state-management utilities) to handle state and side effects in a way that feels intuitive and does not require advanced theory for daily use. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Class Modules and Composition&lt;/strong&gt;: Enable modular development via first-class modules, namespacing, and function composition, allowing team collaboration and code reuse with clear boundaries, similar to OOP packaging and interfaces. &lt;a href="https://www.theserverside.com/tip/Understanding-the-principles-of-functional-programming" rel="noopener noreferrer"&gt;[2]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concise Interop and Practical Libraries&lt;/strong&gt;: Prioritize interoperability with existing systems and provide rich standard libraries for common tasks (GUI, database, networking), helping developers immediately solve practical problems. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative UI and Event Handling&lt;/strong&gt;: Make building user interfaces and event-driven programs as seamless as in OOP by using pure, compositional approaches (e.g., Elm, React-style architectures). &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong, Accessible Documentation&lt;/strong&gt;: Invest in clear guides, tutorials, and onboarding resources that demystify functional concepts and patterns for developers from OOP backgrounds. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Principles to Emphasize
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pure functions for predictability and easy testing. &lt;a href="https://www.theserverside.com/tip/Understanding-the-principles-of-functional-programming" rel="noopener noreferrer"&gt;[2]&lt;/a&gt; &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Immutability to prevent certain classes of bugs, with simple, ergonomic data updating. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Higher-order functions and composition for modularity, without unnecessary academic jargon. &lt;a href="https://www.theserverside.com/tip/Understanding-the-principles-of-functional-programming" rel="noopener noreferrer"&gt;[2]&lt;/a&gt; &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Declarative style for clarity and maintainability. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Built-in support for recursion, effect management, and concurrency that feels natural in large-scale application development. &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By proactively addressing usability, approachability, and real-world application integration—while keeping FP's strengths—such a language could offer an excellent DX that rivals, and even surpasses, traditional OOP environments without relying on OOP constructs. &lt;a href="https://theory.stanford.edu/~aiken/publications/trs/FLProject.pdf" rel="noopener noreferrer"&gt;[4]&lt;/a&gt; &lt;a href="https://www.theserverside.com/tip/Understanding-the-principles-of-functional-programming" rel="noopener noreferrer"&gt;[2]&lt;/a&gt; &lt;a href="https://www.xenonstack.com/insights/functional-programming" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Why necessarily "first-class modules"?
&lt;/h1&gt;

&lt;p&gt;First-class modules are necessary in a new FP language aiming for excellent DX because they allow the modular organization and flexible composition of code at runtime, without adopting OOP’s class-based approach. This capability helps teams create scalable, maintainable, and collaborative projects by treating modules as values that can be passed, stored, and dynamically selected—much like functions in FP, but for entire feature sets or data models (&lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/56575195/what-exactly-are-first-class-modules" rel="noopener noreferrer"&gt;6&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why First-Class Modules Matter in FP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity without OOP&lt;/strong&gt;: Unlike OOP, which uses classes and objects to encapsulate state and behavior, FP relies on composition and separation of concerns. First-class modules provide an alternative by allowing groups of related functions, types, and data to be packaged together and manipulated as units, increasing code reuse and adaptability (&lt;a href="https://stackoverflow.com/questions/56575195/what-exactly-are-first-class-modules" rel="noopener noreferrer"&gt;6&lt;/a&gt;, &lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Composition&lt;/strong&gt;: Developers can pass modules to functions, store them in data structures, or swap implementations at runtime. This flexibility enables plugin architectures, runtime configuration, and testing scenarios that mimic OOP’s extensibility, but stay in the FP paradigm (&lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/56575195/what-exactly-are-first-class-modules" rel="noopener noreferrer"&gt;6&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type Safety and Abstraction&lt;/strong&gt;: First-class modules can encapsulate type definitions and provide strong abstraction boundaries, supporting safe, predictable evolution of codebases as requirements change (&lt;a href="https://okmij.org/ftp/ML/first-class-modules/first-class-modules.pdf" rel="noopener noreferrer"&gt;7&lt;/a&gt;, &lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaboration and Scaling&lt;/strong&gt;: Large teams benefit from clear modular boundaries, enabling parallel development and easier code management—a core DX advantage in any mature language ecosystem (&lt;a href="https://stackoverflow.com/questions/56575195/what-exactly-are-first-class-modules" rel="noopener noreferrer"&gt;6&lt;/a&gt;, &lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, first-class modules help FP languages deliver the same DX strengths as OOP—modularity, organization, extensibility, and collaboration—without relying on objects, and fit naturally within the functional paradigm (&lt;a href="https://okmij.org/ftp/ML/first-class-modules/first-class-modules.pdf" rel="noopener noreferrer"&gt;7&lt;/a&gt;, &lt;a href="https://dev.realworldocaml.org/first-class-modules.html" rel="noopener noreferrer"&gt;3&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/56575195/what-exactly-are-first-class-modules" rel="noopener noreferrer"&gt;6&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>oop</category>
      <category>computerscience</category>
      <category>dx</category>
      <category>functional</category>
    </item>
    <item>
      <title>Solito 5 is now web-first (but still unifies NextJS and React Native)</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Wed, 22 Oct 2025 14:21:50 +0000</pubDate>
      <link>https://dev.to/redbar0n/solito-5-is-now-web-first-but-still-unifies-nextjs-and-react-native-2lek</link>
      <guid>https://dev.to/redbar0n/solito-5-is-now-web-first-but-still-unifies-nextjs-and-react-native-2lek</guid>
      <description>&lt;p&gt;What is Solito?&lt;/p&gt;

&lt;p&gt;"Navigation is the hardest piece of sharing code across platforms. Web has plain URLs for navigation state, whereas apps have complex sets of nested navigation patterns (stacks, tabs, modals, drawers). By combining the approaches into &lt;strong&gt;a single mental model and API&lt;/strong&gt;, devs can build for Web and Mobile with ease. This is touched on at length in the "Methodology" and "Gradual Adoption" sections of the Solito docs.&lt;/p&gt;

&lt;p&gt;The gap between web devs and native devs is shrinking. This stack enables you to &lt;strong&gt;ship native apps and websites with a single codebase&lt;/strong&gt;. I'm the only frontend engineer at our startup, and I was able to do just that as we scaled to thousands of users (see &lt;a href="https://beatgig.com" rel="noopener noreferrer"&gt;https://beatgig.com&lt;/a&gt;). My goal with Solito is to 1) provide the code to let others do it, and 2) perhaps more importantly, document clear patterns to deal with platform differences.&lt;br&gt;
"&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://news.ycombinator.com/item?id=30678100" rel="noopener noreferrer"&gt;fernandorojo @ Hacker News&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the launch of Solito v5, it drops the direct dependency on &lt;a href="https://necolas.github.io/react-native-web/" rel="noopener noreferrer"&gt;React Native for Web&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;See Fernando's tweet of the release of Solito v5:&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1980786809702609159-208" src="https://platform.twitter.com/embed/Tweet.html?id=1980786809702609159"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1980786809702609159-208');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1980786809702609159&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;That prompts some questions...&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Solito on web with pure NextJS, if Solito is precisely for cross-platform development?
&lt;/h2&gt;

&lt;p&gt;Grok AI’s answer to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; What is the utility of using Solito on web with pure NextJS? Couldn’t you just not use Solito? Isn’t Solito precisely for using React Native stuff on web (and vice versa)?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;—- &lt;/p&gt;

&lt;p&gt;Background context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solito 5 introduces a web-first approach by dropping the react-native-web dependency, allowing seamless integration into any Next.js app without configuration while maintaining unchanged native functionality for iOS and Android.&lt;/li&gt;
&lt;li&gt;Major updates include support for Next.js 16 and Expo SDK 54, a shift to .native.tsx files for platform-specific code, and fixes like useSearchParams() on native, simplifying monorepo setups as shown in the updated starter template.&lt;/li&gt;
&lt;li&gt;Originally launched in 2022 by Fernando Rojo to enable shared navigation patterns across web and mobile, this release builds on prior iterations like Zeego, addressing bundler complexities and enabling broader adoption in production cross-platform projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;The answer:&lt;/p&gt;

&lt;p&gt;Let’s dive into the utility of using Solito on the web with pure Next.js, especially given its roots in React Native integration, and clarify how it fits into a web-only context as of today, October 22, 2025.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background on Solito
&lt;/h3&gt;

&lt;p&gt;Solito was originally created by Fernando Rojo to bridge the gap between React Native and Next.js, enabling developers to share navigation and UI logic across web and mobile platforms. It leverages React Navigation for native apps and Next.js Router for the web, providing a unified API to manage navigation patterns (e.g., stacks, tabs, modals) that differ between the two environments. Its initial design was heavily tied to React Native, often requiring &lt;code&gt;react-native-web&lt;/code&gt; to render React Native components on the web.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solito 5 and the Web-First Shift
&lt;/h3&gt;

&lt;p&gt;With the release of Solito 5 (announced on October 21, 2025, via the target post), a significant evolution has occurred. Solito 5 drops the &lt;code&gt;react-native-web&lt;/code&gt; dependency from its core components, making it web-first. This means it now operates as a pure Next.js solution on the web, with platform-specific code (e.g., native features) isolated to &lt;code&gt;.native.tsx&lt;/code&gt; files. This shift simplifies the setup for web-only projects while retaining compatibility with React Native for those who need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utility of Solito on Web with Pure Next.js
&lt;/h3&gt;

&lt;p&gt;Even in a web-only Next.js context, Solito offers several practical benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Unified Navigation Patterns&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solito provides a consistent navigation API inspired by React Navigation, which can be more intuitive for developers familiar with mobile patterns. This is particularly useful if your team works across web and mobile or if you plan to extend to native later. For example, Solito’s &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; component can serve as a drop-in replacement for Next.js’s &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, offering a unified experience that aligns with its cross-platform philosophy.&lt;/li&gt;
&lt;li&gt;It handles complex navigation scenarios (e.g., modals, stacked screens) that go beyond Next.js’s flat, page-based routing, giving you more flexibility to mimic native-like navigation on the web.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future-Proofing and Scalability&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re building a web app today but anticipate adding React Native support later, starting with Solito minimizes refactoring. Since Solito 5 is designed to work without &lt;code&gt;react-native-web&lt;/code&gt; on the web, you can adopt it now and seamlessly extend to native by adding &lt;code&gt;.native.tsx&lt;/code&gt; files and dependencies like Expo when needed.&lt;/li&gt;
&lt;li&gt;The release notes highlight its compatibility with Next.js 16 and Expo SDK 54, ensuring it stays current with modern frameworks, which is a boon for long-term projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simplified Monorepo Setup&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solito 5 includes an updated Expo 54 starter monorepo, which, while aimed at cross-platform devs, also streamlines code organization for web-focused teams. Even if you ignore the native parts, the monorepo structure can help manage shared logic (e.g., components, hooks) across different parts of a large Next.js app.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enhanced Developer Experience&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solito’s web-first approach reduces bundler complexity (e.g., no more &lt;code&gt;index.web.tsx&lt;/code&gt; files), which can lead to faster build times and fewer configuration headaches, even in a pure Next.js setup.&lt;/li&gt;
&lt;li&gt;The migration guide and breaking changes (e.g., dropping &lt;code&gt;TextLink&lt;/code&gt; defaults) encourage clean, explicit styling and props, promoting better code maintainability—a win for any web project.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Community and Ecosystem Alignment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since Solito is backed by Fernando Rojo and has a growing community (evidenced by the positive reactions in the thread), it integrates well with other libraries like &lt;code&gt;@expo/router&lt;/code&gt; or Tailwind, as seen with Zeego’s compatibility. This makes it a robust choice for web devs looking to leverage a battle-tested tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Isn’t Solito for React Native Stuff?
&lt;/h3&gt;

&lt;p&gt;You’re right to question this—Solito’s origins are indeed tied to React Native. Historically, its primary value was enabling React Native developers to share code with Next.js apps, using &lt;code&gt;react-native-web&lt;/code&gt; to render native components on the web. However, Solito 5 redefines its scope. By dropping &lt;code&gt;react-native-web&lt;/code&gt; as a dependency, it’s no longer reliant on React Native rendering on the web. Instead, it positions itself as a versatile framework that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works standalone on Next.js for web apps.&lt;/li&gt;
&lt;li&gt;Remains compatible with React Native for native apps, but only if you opt into that ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dual nature means Solito isn’t &lt;em&gt;just&lt;/em&gt; for React Native anymore—it’s a tool for unifying development workflows, whether you stay web-only or expand to mobile. The web-first design ensures it doesn’t force React Native paradigms (like View or Text components) onto your Next.js app unless you choose to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;Imagine you’re building a Next.js e-commerce site. With Solito 5, you could use its &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; component for navigation, benefiting from its ability to handle modal overlays (e.g., a cart popup) in a way that feels native-like. If your business later decides to launch an iOS app, you can extend the same navigation logic to React Native with minimal changes, leveraging Solito’s &lt;code&gt;.native.tsx&lt;/code&gt; files. Without Solito, you’d need to rewrite navigation for mobile, potentially duplicating effort.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overhead for Web-Only&lt;/strong&gt;: If you’re strictly web-focused and happy with Next.js’s built-in routing, Solito might add unnecessary complexity. Its value shines when you need advanced navigation or plan for cross-platform growth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Curve&lt;/strong&gt;: The shift to web-first requires understanding its new conventions (e.g., no default styles on &lt;code&gt;TextLink&lt;/code&gt;), as outlined in the migration guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency&lt;/strong&gt;: While &lt;code&gt;react-native-web&lt;/code&gt; is dropped, some third-party React Native libraries you might use alongside Solito could still require it, so check your stack.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Using Solito on the web with pure Next.js is about leveraging a unified, future-proof navigation system that aligns with modern cross-platform trends, even if you start web-only. It’s not just for React Native anymore—it’s a strategic choice for developers who value flexibility, scalability, and a consistent API across potential future expansions. If your project is unlikely to go native and you’re satisfied with Next.js’s default routing, you might not need it. But for anyone eyeing a hybrid future or craving more navigation power, Solito 5’s web-first approach makes it a compelling tool.&lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Can you use web stuff on native by using solito?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your question seems to be asking whether you can use web-specific features or components on the native (React Native) side by using Solito, or perhaps vice versa—using native features on the web. Based on the context of Solito 5 (released on October 21, 2025, as per the target post) and the ongoing discussion, I’ll interpret this as: &lt;em&gt;Can Solito enable the use of web-specific ("web stuff") functionality or components in a native React Native environment, or allow native features to work on the web?&lt;/em&gt; Let’s break this down step by step, considering the current state of Solito 5 as of 04:06 PM CEST on Wednesday, October 22, 2025.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solito 5 Overview
&lt;/h3&gt;

&lt;p&gt;Solito 5, as introduced by Fernando Rojo, is now a web-first framework that drops the &lt;code&gt;react-native-web&lt;/code&gt; dependency from its core components. This means it operates natively on Next.js for the web without relying on React Native rendering, while still supporting React Native for iOS and Android via platform-specific files (e.g., &lt;code&gt;.native.tsx&lt;/code&gt;). The goal is to simplify cross-platform development by allowing shared logic and navigation, with clear separation between web and native implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can You Use Web Stuff on Native with Solito?
&lt;/h3&gt;

&lt;p&gt;The short answer is &lt;strong&gt;no, not directly&lt;/strong&gt;, but let’s explore why and how you can approach this.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Not Directly?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform Separation&lt;/strong&gt;: Solito 5 enforces a clear distinction between web and native. Web-specific features (e.g., Next.js Server Components, &lt;code&gt;useSearchParams()&lt;/code&gt;, or browser APIs like &lt;code&gt;window&lt;/code&gt;) are designed to work in a Next.js environment, which relies on a DOM. React Native, however, uses a different rendering engine (e.g., Yoga for layout, native UI components) and lacks a DOM, making web-specific APIs incompatible without additional layers like &lt;code&gt;react-native-web&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dropped &lt;code&gt;react-native-web&lt;/code&gt;&lt;/strong&gt;: Previously, Solito relied on &lt;code&gt;react-native-web&lt;/code&gt; to render React Native components on the web. With Solito 5 dropping this dependency, the web side no longer uses React Native’s rendering pipeline. Conversely, the native side doesn’t inherit web capabilities unless explicitly bridged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-Based Isolation&lt;/strong&gt;: Solito 5 uses file extensions like &lt;code&gt;.native.tsx&lt;/code&gt; for platform-specific code. Web-specific logic (e.g., in &lt;code&gt;.web.tsx&lt;/code&gt; or default &lt;code&gt;.tsx&lt;/code&gt; files) is ignored on native, and native-specific code is ignored on web. This prevents direct use of web "stuff" (e.g., Next.js hooks or components) on native.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Workarounds to Use Web-Like Features on Native
&lt;/h4&gt;

&lt;p&gt;While you can’t use web-specific APIs or components directly on native, Solito’s design allows you to share logic and abstract functionality in a way that mimics web behavior on native where possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shared Utility Logic&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write platform-agnostic code (e.g., in a shared &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt; file) that adapts to the environment using runtime checks. For example:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="c1"&gt;// Fallback for native (e.g., use React Navigation params)&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;This allows you to simulate web-like behavior (e.g., query params) on native, though you’d need to implement native equivalents (e.g., via React Navigation’s route params).&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Components with Conditional Rendering&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a shared component that uses conditional logic to render web-specific JSX on the web and native-compatible alternatives on mobile. For instance:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Web-specific&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* native navigation */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Native equivalent&lt;/span&gt;
 &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Solito’s navigation API (e.g., &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;Stack.Screen&amp;gt;&lt;/code&gt;) can help unify this, but you’d need to handle platform-specific navigation logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Leveraging Expo or Third-Party Libraries&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expo SDK 54 (supported by Solito 5) provides web-like features for React Native, such as Web APIs (e.g., &lt;code&gt;localStorage&lt;/code&gt; via &lt;code&gt;expo-secure-store&lt;/code&gt; analogs). You could use these to approximate web functionality on native, though they’re not identical to browser-native implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monorepo Shared Code&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a Solito monorepo, you can place web-specific code in a &lt;code&gt;web/&lt;/code&gt; directory and native-specific code in a &lt;code&gt;native/&lt;/code&gt; directory. Use a shared layer (e.g., &lt;code&gt;shared/&lt;/code&gt;) to export utilities or components that adapt to both platforms, reducing the need to duplicate effort.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Incompatible APIs&lt;/strong&gt;: Web-only features like Server-Side Rendering (SSR) with Next.js or browser events (e.g., &lt;code&gt;onWheel&lt;/code&gt;) won’t work on native without significant polyfills or workarounds, which may not be worth the effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Emulating web behavior on native can introduce overhead or inconsistent UX, as native apps are optimized for touch/gesture interactions rather than mouse/keyboard events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Adding web-like functionality to native requires careful abstraction, which might negate some of Solito’s simplification benefits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Can You Use Native Stuff on Web with Solito?
&lt;/h3&gt;

&lt;p&gt;The reverse—using native "stuff" (e.g., React Native components like &lt;code&gt;View&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, or native modules) on the web—is also not directly supported in Solito 5 due to the dropped &lt;code&gt;react-native-web&lt;/code&gt; dependency. However:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historical Context&lt;/strong&gt;: Earlier Solito versions relied on &lt;code&gt;react-native-web&lt;/code&gt; to render native components on the web, allowing you to use &lt;code&gt;View&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, etc., with some styling adjustments. Solito 5 removes this, so native components no longer render on the web by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workaround&lt;/strong&gt;: You could reintroduce &lt;code&gt;react-native-web&lt;/code&gt; as a project dependency and configure it manually, but this contradicts Solito 5’s web-first philosophy and adds complexity. Alternatively, use a library like &lt;code&gt;react-native-web-lite&lt;/code&gt; or rewrite native components as HTML/CSS equivalents for the web.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solito’s Intended Use
&lt;/h3&gt;

&lt;p&gt;Solito 5 is designed to unify &lt;em&gt;development experience&lt;/em&gt; and &lt;em&gt;navigation logic&lt;/em&gt; across web and native, not to make web and native environments interchangeable. The utility lies in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sharing code (e.g., business logic, styles, navigation structure) between platforms.&lt;/li&gt;
&lt;li&gt;Allowing a smooth transition from web-only to cross-platform with minimal refactoring.&lt;/li&gt;
&lt;li&gt;Providing a consistent API (e.g., &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Stack&amp;gt;&lt;/code&gt;) that abstracts platform differences.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your goal is to use web-specific features on native or vice versa, Solito facilitates this indirectly through shared abstractions rather than direct feature porting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;Suppose you want to use Next.js’s &lt;code&gt;useSearchParams()&lt;/code&gt; on native:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On web, it works out of the box with Solito 5’s web-first setup.&lt;/li&gt;
&lt;li&gt;On native, you’d need to replicate this with React Navigation’s &lt;code&gt;route.params&lt;/code&gt; or Expo’s routing system. Solito’s monorepo structure lets you define a custom hook like:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRoute&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCustomParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRoute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use this hook in both web and native contexts, with web falling back to &lt;code&gt;useSearchParams()&lt;/code&gt; via a conditional import.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;With Solito 5, you cannot directly use web "stuff" (e.g., Next.js APIs, DOM features) on native or native "stuff" (e.g., React Native components) on web without additional configuration or polyfills, as it prioritizes platform separation over feature unification.&lt;/p&gt;

&lt;p&gt;The answer:&lt;/p&gt;

&lt;p&gt;However, you can &lt;strong&gt;share logic and create platform-adapted implementations using Solito’s file-based structure and navigation API&lt;/strong&gt;. This makes it ideal for projects where you want to &lt;strong&gt;start web-only with Next.js and later add native support&lt;/strong&gt;, rather than forcing web-native interoperability.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>webdev</category>
      <category>crossplatform</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is PhotonJS?</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Wed, 22 Oct 2025 13:59:51 +0000</pubDate>
      <link>https://dev.to/redbar0n/what-is-photonjs-1ij5</link>
      <guid>https://dev.to/redbar0n/what-is-photonjs-1ij5</guid>
      <description>&lt;p&gt;Here are some clarifying answers from my session with perplexity.ai, edited for your convenience and saved here for posterity.&lt;/p&gt;

&lt;p&gt;The Photon we are talking about:&lt;/p&gt;

&lt;p&gt;&lt;a href="//photonjs.dev"&gt;photonjs.dev&lt;/a&gt; with source code at&lt;br&gt;
&lt;a href="https://github.com/photon-js/photon" rel="noopener noreferrer"&gt;https://github.com/photon-js/photon&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem PhotonJS solves:
&lt;/h1&gt;

&lt;p&gt;&lt;a href="//photonjs.dev"&gt;PhotonJS.dev&lt;/a&gt; is needed because &lt;strong&gt;not every JS based server can be deployed directly on every platform without additional work&lt;/strong&gt;. Different server frameworks and deployment platforms have variations and incompatibilities in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIs for handling requests and responses
&lt;/li&gt;
&lt;li&gt;Environment constraints (e.g., edge versus Node.js, serverless versus long-running)
&lt;/li&gt;
&lt;li&gt;Deployment formats and packaging (containers, serverless functions, VMs)
&lt;/li&gt;
&lt;li&gt;Network and security specifics, lifecycle management, and support tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Photon acts as a &lt;strong&gt;unifying layer&lt;/strong&gt; that abstracts these differences, providing a consistent developer experience and deployment workflow across multiple environments. Without such a layer, developers must often rewrite or heavily adapt their code for each platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Photon Matters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It &lt;strong&gt;saves development time and complexity&lt;/strong&gt; by allowing one codebase to run on many deployment platforms (Cloudflare Workers, Vercel, Express servers, etc.).
&lt;/li&gt;
&lt;li&gt;It handles &lt;strong&gt;environment-specific quirks and APIs&lt;/strong&gt; behind the scenes via adapters, so developers don’t need to manually tailor their servers to each host.
&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;enables easier integration with modern tooling&lt;/strong&gt; like Vite and supports multiple server environments seamlessly.
&lt;/li&gt;
&lt;li&gt;Ensures &lt;strong&gt;consistent behavior and performance&lt;/strong&gt; across platforms, improving reliability and security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  In Short
&lt;/h3&gt;

&lt;p&gt;Though technically you &lt;em&gt;can&lt;/em&gt; deploy many servers on many platforms, without a framework like Photon, you face &lt;strong&gt;significant manual effort, fragmentation, and platform lock-in&lt;/strong&gt;. Photon solves this by providing a &lt;strong&gt;flexible, adapter-based abstraction that lets servers run everywhere with minimal changes&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;The reasons it is needed and cannot be replaced by just deploying any server on any platform are:&lt;/p&gt;

&lt;p&gt;Server frameworks differ in their request handling APIs, lifecycle, and runtime requirements, and each deployment platform (e.g., Vercel, Cloudflare Workers, Express servers) has its own environment constraints — &lt;strong&gt;Photon standardizes these differences with a core logic and adapter system to avoid rewriting code per platform.​&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Photon creates a flexible abstraction that lets developers write code once and deploy that same codebase seamlessly across multiple server and deployment environments by changing adapters instead of code.​&lt;/p&gt;

&lt;p&gt;So Photon is a framework-level solution enabling cross-platform server deployments. It fills a specific niche in JavaScript/TypeScript web development to unify server and deployment platform differences.&lt;/p&gt;




&lt;p&gt;Think of Photon JS as a &lt;strong&gt;multiport adapter&lt;/strong&gt; where you can choose one of multiple inputs (servers), and one of multiple outputs (deployment platforms/infrastructure). Alternatively: think of PhotonJS as a &lt;strong&gt;digital crosspoint switch&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Comparing Photon as a multiport adapter to an electric socket multiport adapter is a useful analogy:&lt;/p&gt;

&lt;h3&gt;
  
  
  Electric Socket Multiport Adapter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Converts one electric socket into multiple sockets so multiple devices can plug in simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inputs/Outputs:&lt;/strong&gt; Takes one power source input, provides multiple physical output ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Acts as a physical bridge allowing diverse devices to share a common electricity source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; Supports different plug types and sometimes voltage conversion; enables hardware compatibility without changing the devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Photon as Multiport Adapter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Provides a core framework that supports using multiple server adapters and deployment adapters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inputs/Outputs:&lt;/strong&gt; Acts as the "bridge" between multiple backend frameworks (inputs) and multiple deployment environments (outputs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Defines common logic and interfaces that allow diverse server and deployment targets to integrate seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; Enables developers to write code once and deploy it anywhere by managing environment differences via adapters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary Comparison Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Electric Socket Multiport Adapter&lt;/th&gt;
&lt;th&gt;Photon Multiport Adapter (Metaphor)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;One electrical power socket&lt;/td&gt;
&lt;td&gt;Multiple backend server frameworks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;Multiple physical sockets to plug devices&lt;/td&gt;
&lt;td&gt;Multiple deployment environments/platforms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Distributes power to multiple devices&lt;/td&gt;
&lt;td&gt;Distributes app logic to multiple runtimes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acts as&lt;/td&gt;
&lt;td&gt;Hardware bridge&lt;/td&gt;
&lt;td&gt;Software abstraction and runtime coordination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supports diversity&lt;/td&gt;
&lt;td&gt;Different plug shapes, sometimes voltage conversion&lt;/td&gt;
&lt;td&gt;Different server frameworks and deployment targets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Physical connectivity&lt;/td&gt;
&lt;td&gt;Deployment and runtime flexibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User scope&lt;/td&gt;
&lt;td&gt;End users with devices&lt;/td&gt;
&lt;td&gt;Framework authors and developers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In essence, just like an electric multiport adapter allows diverse electrical devices to plug into one power source, Photon allows diverse backend environments to "plug into" a single unified application framework by acting as a &lt;strong&gt;flexible multiport software adapter&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Yes, Photon can be described as a kind of &lt;strong&gt;multiport adapter&lt;/strong&gt; with multiple inputs and outputs. It acts as the &lt;strong&gt;core abstraction layer&lt;/strong&gt; that defines standard interfaces (ports) for inputs and outputs, and then separately implemented adapters handle the actual integration with various server frameworks and deployment platforms.&lt;/p&gt;

&lt;p&gt;In architecture terms (similar to Hexagonal or Ports and Adapters architecture), Photon’s core codebase provides &lt;strong&gt;ports&lt;/strong&gt;—the defined APIs and runtime logic—while the server adapters and deployment adapters are the &lt;strong&gt;external adapters&lt;/strong&gt; implementing those ports for specific environments.&lt;/p&gt;

&lt;p&gt;So Photon itself handles the &lt;strong&gt;common logic and coordination ("multiple ins and outs")&lt;/strong&gt;, while the adapters handle the specifics of interacting with particular incoming requests or outgoing deployment targets. This design enables easy extension and flexibility across many backend and deployment scenarios without changing the core framework logic.[4][9]&lt;/p&gt;

&lt;p&gt;Thus, Photon is effectively a &lt;strong&gt;multiport adapter infrastructure&lt;/strong&gt; that supports multiple inputs (different server frameworks) and outputs (different deployment environments) through well-defined interfaces and adapter implementations.&lt;/p&gt;




&lt;p&gt;Photon is best described as &lt;strong&gt;a deployment-agnostic infrastructure and framework toolkit&lt;/strong&gt; aimed at making JavaScript server deployment flexible and cross-compatible. It is &lt;em&gt;not&lt;/em&gt; in itself a separate/dedicated platform for hosting or deploying applications directly (like Vercel, Netlify, Cloudflare, AWS, GCP, Hertzner etc.).&lt;/p&gt;




&lt;p&gt;The &lt;strong&gt;Photon project at &lt;a href="https://github.com/photon-js/photon" rel="noopener noreferrer"&gt;photon-js/photon&lt;/a&gt;&lt;/strong&gt; is a &lt;strong&gt;JavaScript web framework toolkit&lt;/strong&gt; designed to make it easy for developers to build modern, framework-agnostic web apps that integrate well with &lt;strong&gt;Vite&lt;/strong&gt; and various web servers and deployment environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Photon Does
&lt;/h3&gt;

&lt;p&gt;Photon acts as a &lt;strong&gt;unifying tool&lt;/strong&gt; that helps web framework authors or developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect frontend build tools (like &lt;strong&gt;Vite&lt;/strong&gt;) with backend frameworks.&lt;/li&gt;
&lt;li&gt;Simplify integration across different environments like &lt;strong&gt;Cloudflare Workers&lt;/strong&gt;, &lt;strong&gt;Vercel&lt;/strong&gt;, or &lt;strong&gt;Node.js&lt;/strong&gt; servers.&lt;/li&gt;
&lt;li&gt;Provide pre-built &lt;strong&gt;adapters&lt;/strong&gt; for popular server frameworks such as &lt;strong&gt;Express&lt;/strong&gt;, &lt;strong&gt;Fastify&lt;/strong&gt;, &lt;strong&gt;Hono&lt;/strong&gt;, and &lt;strong&gt;Elysia&lt;/strong&gt;, so the same codebase can run almost anywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explained Like You’re 5 Years Old (ELI5)
&lt;/h3&gt;

&lt;p&gt;Imagine you have a bunch of different types of &lt;strong&gt;LEGO bases&lt;/strong&gt; — one for your house, one for your car, one for your spaceship — and you want the same LEGO tower to fit on all of them. Photon is like a &lt;strong&gt;universal LEGO connector&lt;/strong&gt; that lets your tower (web app) fit neatly on any base (Cloudflare, Express, Vercel, etc.) without rebuilding it each time.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It’s Structured
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core&lt;/strong&gt;: The heart of Photon, including Vite integration and general logic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt;: Helper functions useful for framework developers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Adapters&lt;/strong&gt;: Pieces that make Photon work with different backend frameworks (Express, Hono, Fastify, etc.).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Adapters&lt;/strong&gt;: Allow the same app to deploy easily on platforms like &lt;strong&gt;Vercel&lt;/strong&gt; and &lt;strong&gt;Cloudflare Workers&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  In Short
&lt;/h3&gt;

&lt;p&gt;Photon is a (currently beta-stage) &lt;strong&gt;meta-framework toolkit&lt;/strong&gt; that helps developers make flexible web frameworks that run the same code across many environments. It’s written mainly in &lt;strong&gt;TypeScript&lt;/strong&gt;, which makes it developer-friendly and consistent across Node.js and edge environments.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Photon actually contains code-wise:
&lt;/h1&gt;

&lt;p&gt;Photon itself (as in the &lt;strong&gt;photon-js/photon&lt;/strong&gt; project) isn’t a deployment adapter or runtime layer — it’s the &lt;strong&gt;core coordination layer&lt;/strong&gt; that defines the shared logic, interfaces, and build system for all the adapters. Essentially, it contains the &lt;em&gt;glue code&lt;/em&gt; that makes the different adapters (server and deployment) interoperable.&lt;/p&gt;

&lt;p&gt;Here’s what Photon actually contains code-wise:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Core Package (&lt;code&gt;packages/core&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is the heart of Photon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides the &lt;strong&gt;Vite integration&lt;/strong&gt; so frameworks built with Photon can use Vite seamlessly within both Node and edge environments.
&lt;/li&gt;
&lt;li&gt;Exposes core abstractions like build hooks, file routing utilities, and module loading logic that adapters depend on.
&lt;/li&gt;
&lt;li&gt;Defines environment detection and API for runtime context (e.g., &lt;code&gt;isServer&lt;/code&gt;, &lt;code&gt;isEdge&lt;/code&gt;, &lt;code&gt;isBrowser&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of this as &lt;strong&gt;the shared foundation that hides differences between deployment targets.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Runtime Package (&lt;code&gt;packages/runtime&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This provides &lt;strong&gt;common runtime helpers&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions used inside user frameworks for handling requests, responses, and rendering pipelines.
&lt;/li&gt;
&lt;li&gt;Lightweight runtime utilities that work independently from any specific adapter, often exported to end users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Adapter Interfaces
&lt;/h3&gt;

&lt;p&gt;While Photon itself doesn’t directly contain adapter code, it defines &lt;strong&gt;TypeScript interfaces and base classes&lt;/strong&gt; that each specific adapter (e.g., Express or Cloudflare) must implement.&lt;br&gt;&lt;br&gt;
This ensures that each adapter behaves consistently.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Tooling and Dev Features
&lt;/h3&gt;

&lt;p&gt;Photon’s repo includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared developer utilities for testing and local development.
&lt;/li&gt;
&lt;li&gt;Configurations for monorepo management (via pnpm workspaces or TurboRepo).
&lt;/li&gt;
&lt;li&gt;Build scripts that bundle all the pieces cohesively for framework authors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Photon’s own codebase is mainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite integration logic
&lt;/li&gt;
&lt;li&gt;TypeScript interfaces for adapters
&lt;/li&gt;
&lt;li&gt;Runtime utilities shared by all environments
&lt;/li&gt;
&lt;li&gt;A monorepo setup to compile, test, and bundle these packages
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, rather than being an adapter itself, Photon defines the &lt;strong&gt;infrastructure spine&lt;/strong&gt; — the base code and contracts that allow independent server and deployment adapters to work together smoothly.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>serverless</category>
      <category>frameworks</category>
    </item>
    <item>
      <title>Referential transparency with mutation</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Tue, 22 Jul 2025 14:40:40 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/referential-transparency-with-mutation-3lai</link>
      <guid>https://dev.to/playfulprogramming/referential-transparency-with-mutation-3lai</guid>
      <description>&lt;p&gt;From a conversation with perplexity.ai about a hypothetical programming language.&lt;/p&gt;

&lt;p&gt;Referential transparency is the ability to replace a function call with its return value without affecting the program’s behaviour elsewhere (i.e. no side-effect).&lt;/p&gt;

&lt;p&gt;Referential transparency is considered a staple in pure functional programming. It typically assumes immutability. But mutability is often more efficient than immutability, since it involves changing data structures in-place rather than always having to create copies. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, could referential transparency be combined with mutability, if the language was sufficiently restrictive..?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;If a function mutates its input but is &lt;em&gt;forced to return that mutated input&lt;/em&gt; as part of its result, and if the caller is &lt;strong&gt;constrained to never reuse the original input after calling the function&lt;/strong&gt;, then this can preserve &lt;em&gt;referential transparency&lt;/em&gt; despite the mutation.&lt;/p&gt;

&lt;p&gt;This is because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the mutation is &lt;strong&gt;local and encapsulated&lt;/strong&gt; within the function’s scope and the mutated value is immediately returned and used, then the outside program never observes the mutation except via the returned result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The caller discards the old input reference and only uses the returned mutated version, so &lt;em&gt;the externally observable behavior is consistent&lt;/em&gt; and predictable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practically, the mutation is "hidden" inside the function and the function's interface looks like it produces a new value, preserving functional purity in an external view.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach aligns with the insight that &lt;strong&gt;local mutation inside a function is allowed if it doesn't leak observable side effects&lt;/strong&gt; — the function then &lt;em&gt;behaves&lt;/em&gt; like a pure function and remains referentially transparent.&lt;/p&gt;

&lt;p&gt;For example, an in-place reversal function that takes an array, mutates it internally, and returns it, while the caller uses only the returned array and never reuses the original, can be considered referentially transparent even though it mutates internally[1].&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Function mutates input and returns it&lt;/td&gt;
&lt;td&gt;Potential mutation exposed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caller reuses original input after call&lt;/td&gt;
&lt;td&gt;Breaks referential transparency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caller discards original input, uses returned value&lt;/td&gt;
&lt;td&gt;Preserves referential transparency if mutation is local and encapsulated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Thus, &lt;em&gt;mutation&lt;/em&gt; inside a function combined with a strict contract on caller usage can preserve &lt;strong&gt;referential transparency&lt;/strong&gt;, even though strictly speaking the function is not pure (since it mutates state internally). This is a subtle but important distinction in functional programming[1][3].&lt;/p&gt;

&lt;p&gt;
  References
  &lt;br&gt;
&lt;strong&gt;References:&lt;/strong&gt;

&lt;p&gt;[1] Mutation allowed internally if local and hidden, preserving referential transparency&lt;br&gt;&lt;br&gt;
[3] Referential transparency definition and differences with purity&lt;br&gt;&lt;br&gt;
[4][5][6] Definitions of referential transparency and pure functions&lt;/p&gt;

&lt;p&gt;[1] &lt;a href="https://betterprogramming.pub/your-code-should-read-like-a-story-how-to-mutate-state-and-have-effect-on-the-world-while-3e3ae808d2d6" rel="noopener noreferrer"&gt;https://betterprogramming.pub/your-code-should-read-like-a-story-how-to-mutate-state-and-have-effect-on-the-world-while-3e3ae808d2d6&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://www.reddit.com/r/functionalprogramming/comments/10k28tm/example_of_a_function_that_has_referential/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/functionalprogramming/comments/10k28tm/example_of_a_function_that_has_referential/&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://stackoverflow.com/questions/4865616/purity-vs-referential-transparency" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/4865616/purity-vs-referential-transparency&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://www.java-success.com/01-scala-functional-programming-basics-pure-functions-referential-transparency-side-effects-etc/" rel="noopener noreferrer"&gt;https://www.java-success.com/01-scala-functional-programming-basics-pure-functions-referential-transparency-side-effects-etc/&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://dev.to/ruizb/function-purity-and-referential-transparency-7h1"&gt;https://dev.to/ruizb/function-purity-and-referential-transparency-7h1&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://adabeat.com/fp/referential-transparency/" rel="noopener noreferrer"&gt;https://adabeat.com/fp/referential-transparency/&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://www.edward-huang.com/functional-programming/tech/programming/scala/2020/01/30/pure-function-vs-referential-transparency/" rel="noopener noreferrer"&gt;https://www.edward-huang.com/functional-programming/tech/programming/scala/2020/01/30/pure-function-vs-referential-transparency/&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Pure_function&lt;/a&gt;&lt;br&gt;
[9] &lt;a href="https://colofabrix.github.io/the-road-to-fp/04_pure_functions.html" rel="noopener noreferrer"&gt;https://colofabrix.github.io/the-road-to-fp/04_pure_functions.html&lt;/a&gt;&lt;br&gt;
[10] &lt;a href="https://blog.stackademic.com/functional-programming-immutability-and-pure-functions-1d52395353fb?gi=1c3e8037bd09" rel="noopener noreferrer"&gt;https://blog.stackademic.com/functional-programming-immutability-and-pure-functions-1d52395353fb?gi=1c3e8037bd09&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;

&lt;p&gt;Here's a clear JavaScript example illustrating the concept where a function &lt;strong&gt;mutates its input internally but returns it&lt;/strong&gt;, and the caller &lt;strong&gt;does not reuse the original input after the function call&lt;/strong&gt;. This setup preserves &lt;em&gt;referential transparency&lt;/em&gt; from the caller's perspective, even though the function performs mutation internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Function that mutates its input array in-place, then returns it&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reverseInPlace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;left&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Swap elements - mutation happens here&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;right&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// returns the mutated array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Original array&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&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="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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Caller does NOT use 'original' after this call, only uses returned value&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reversed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverseInPlace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [4, 3, 2, 1]&lt;/span&gt;
&lt;span class="c1"&gt;// original === reversed, but caller only uses 'reversed', not 'original'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why this preserves referential transparency here:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;function call&lt;/strong&gt; &lt;code&gt;reverseInPlace(original)&lt;/code&gt; can be replaced with &lt;strong&gt;&lt;code&gt;reversed&lt;/code&gt;&lt;/strong&gt; everywhere in the code without changing behavior since the caller uses only the returned value after mutation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The caller &lt;strong&gt;abandons the original input reference&lt;/strong&gt; and treats the returned mutated array as the new value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The mutation is &lt;strong&gt;internal to the function's scope&lt;/strong&gt; and does not produce side effects observable outside beyond the returned result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a consequence, for any given input array that the caller will no longer access after the call, the output is &lt;em&gt;deterministic&lt;/em&gt; and no externally visible unexpected mutation occurs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  References
  &lt;h3&gt;
  
  
  Reference from search results:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Local mutation inside a function that returns the mutated value is considered &lt;strong&gt;an implementation detail&lt;/strong&gt; that doesn't violate functional purity if the interface is pure (i.e., no visible side effects)[1][3].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mutation is acceptable inside a function if it is &lt;em&gt;internal and encapsulated&lt;/em&gt; and no external shared state is modified[3].&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This example fits the pattern you asked about, where mutation happens but &lt;strong&gt;referential transparency is preserved&lt;/strong&gt; by restricting the caller from reusing the original input.&lt;/p&gt;

&lt;p&gt;[1] &lt;a href="https://dev.to/macsikora/data-mutation-in-functional-javascript-1h97"&gt;https://dev.to/macsikora/data-mutation-in-functional-javascript-1h97&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://github.com/Manish-Giri/FreeCodeCamp/blob/master/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.english.md" rel="noopener noreferrer"&gt;https://github.com/Manish-Giri/FreeCodeCamp/blob/master/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.english.md&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://dev.to/macsikora/mutation-is-ok-3e00"&gt;https://dev.to/macsikora/mutation-is-ok-3e00&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://www.reddit.com/r/functionalprogramming/comments/rswsa6/how_to_handle_mutable_state_in_a_pure_functional/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/functionalprogramming/comments/rswsa6/how_to_handle_mutable_state_in_a_pure_functional/&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://stackoverflow.com/questions/28792326/functional-style-javascript-good-practice-to-avoid-argument-mutation/28792393" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/28792326/functional-style-javascript-good-practice-to-avoid-argument-mutation/28792393&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://cs.brown.edu/courses/cs016/static/files/lectures/slides/18-functional-programming.pdf" rel="noopener noreferrer"&gt;https://cs.brown.edu/courses/cs016/static/files/lectures/slides/18-functional-programming.pdf&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://softwareengineering.stackexchange.com/questions/351593/automatically-convert-mutations-in-imperative-code-into-functional-actions" rel="noopener noreferrer"&gt;https://softwareengineering.stackexchange.com/questions/351593/automatically-convert-mutations-in-imperative-code-into-functional-actions&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming" rel="noopener noreferrer"&gt;https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming&lt;/a&gt;&lt;br&gt;
[9] &lt;a href="https://ethankent.dev/posts/mutation_scopes/" rel="noopener noreferrer"&gt;https://ethankent.dev/posts/mutation_scopes/&lt;/a&gt;&lt;br&gt;
[10] &lt;a href="https://stackoverflow.com/questions/25777592/avoid-mutation-in-this-example-in-f" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/25777592/avoid-mutation-in-this-example-in-f&lt;/a&gt;&lt;/p&gt;



&lt;/p&gt;

&lt;h3&gt;
  
  
  What if multiple functions use the same input?
&lt;/h3&gt;

&lt;p&gt;Then all but the last one must take a copy of the input. The last one is allowed to mutate the input. All calls are thus referentially transparent wrt. the program as a whole.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reverseInPlace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;left&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;right&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&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="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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// First call: copy original so original remains unmodified&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverseInPlace&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r1:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// [4, 3, 2, 1]&lt;/span&gt;

&lt;span class="c1"&gt;// Second call: last use of original, so safe to pass original without copy&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverseInPlace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r2:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// [4, 3, 2, 1]&lt;/span&gt;

&lt;span class="c1"&gt;// After second call, original is mutated but not used afterward&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>functional</category>
      <category>programming</category>
      <category>language</category>
    </item>
    <item>
      <title>Could parentheses be a reason Lisp is hard to read?</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Thu, 20 Mar 2025 13:03:19 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/could-parentheses-be-a-reason-lisp-is-hard-to-read-481l</link>
      <guid>https://dev.to/playfulprogramming/could-parentheses-be-a-reason-lisp-is-hard-to-read-481l</guid>
      <description>&lt;p&gt;Many in the communities of Lisp-style languages (Lisp, Clojure etc.) seem to discount parentheses being a reason for people not adopting Lisp. (It must only be the unfamiliarity of FP! You get used to the parentheses, and see past them!) Even though newcomers frequently complain about all the parentheses (of Lisp S-expressions), and several people have attempted to make an indentation-based Lisp (I-expressions, T-expressions aka. Sweet expressions, Cirru, Wisp, etc.). So there must be something to it, or..?&lt;/p&gt;

&lt;p&gt;Shared from perplexity.ai :&lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;Reasons why developers might find heavily nested parentheses in Lisp harder to read, and how the Python equivalent addresses that issue.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;1. Visual Clutter&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lisp Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;complex-calculation&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sqrt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;y&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;Why it's hard to read in Lisp:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;The parentheses dominate the visual space, making it difficult to focus on the actual logic of the computation. You have to &lt;em&gt;mentally parse which parentheses belong to which operation&lt;/em&gt;, and this can be overwhelming in more complex expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python Example:&lt;/strong&gt;&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;complex_calculation&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;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&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;y&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="n"&gt;z&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&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="n"&gt;y&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Python is clearer:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Python uses operator precedence and infix notation (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;) instead of prefix notation (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, etc.). This reduces the need for explicit grouping with parentheses. The mathematical operators are familiar and visually intuitive, making the expression &lt;em&gt;easier to read at a glance&lt;/em&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Lack of Visual Cues&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lisp Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&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="nb"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;x&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="mi"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;  &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;a&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;Why it's hard to read in Lisp:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;With multiple levels of parentheses nested within an &lt;code&gt;if&lt;/code&gt; statement, it becomes &lt;em&gt;difficult to match opening and closing parentheses at a glance&lt;/em&gt;. Misplacing or omitting just one parenthesis can lead to errors that are hard to debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python Example:&lt;/strong&gt;&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nested_function&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;b&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&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="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&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;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&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="n"&gt;b&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="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;a&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;Why Python is clearer:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Python uses indentation and blocks instead of parentheses for structure. The logical separation between the &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;else&lt;/code&gt; branches is clear. Parentheses are only used for grouping where necessary, making them easier to &lt;em&gt;match visually&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidenote:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In postfix syntax (similar to a stack-based language like PostScript) the Lisp would look like:&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 c *) -) ((a b +) c /) +)
((a b *) ((b c -) a /) -)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;5. Reduced Readability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lisp Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
      &lt;span class="nb"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;evenp&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;expt&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nv"&gt;else&lt;/span&gt;
        &lt;span class="nv"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;1+&lt;/span&gt; &lt;span class="nv"&gt;i&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;Why it's hard to read in Lisp:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;The combination of nested parentheses and keywords like &lt;code&gt;collect&lt;/code&gt; makes it harder to follow what’s happening at each step of the loop. The logic is compact but not immediately intuitive because everything is expressed as nested expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python Example:&lt;/strong&gt;&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&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;2&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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;i&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Python is clearer:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Python's loop syntax &lt;em&gt;separates each part of the logic into distinct lines&lt;/em&gt; (&lt;code&gt;for&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;else&lt;/code&gt;). The use of indentation makes it easy to see what happens under each condition &lt;em&gt;without needing to mentally parse&lt;/em&gt; nested constructs.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Limited Expression of Precedence&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lisp Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&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="nb"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&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;Why it's hard to read in Lisp:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In Lisp's prefix notation, every operator requires explicit grouping with parentheses. This makes it harder to intuitively understand operator precedence because there’s no visual shorthand like infix operators provide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python Example:&lt;/strong&gt;&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;result&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Python is clearer:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Python uses standard mathematical notation with infix operators (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;) that inherently express precedence rules &lt;em&gt;without requiring extra grouping symbols&lt;/em&gt;. This makes the expression more natural and easier for most developers to understand.&lt;/p&gt;

&lt;p&gt;Edit:&lt;br&gt;
Actually, I'd argue that the need for precedence rules (due to infix syntax) is a bad thing since it indicates ambiguity. So it is a good thing to have a syntax (prefix or postfix) that makes the order of computation so clear it doesn't need precedence rules. The problem with Lisp syntax comes when using inherently infix operators (plus &lt;code&gt;+&lt;/code&gt;, minus &lt;code&gt;-&lt;/code&gt;, times &lt;code&gt;*&lt;/code&gt; etc.) in a prefix language like Lisp. Better to go by the more declarative names addition and subtraction. It is not as confusing to read as it looks more like regular function calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;mul&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt; &lt;span class="mi"&gt;5&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="nv"&gt;div&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;7. Indentation Challenges&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lisp Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;process-data&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;processed&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;remove-if&lt;/span&gt;
            &lt;span class="nf"&gt;#'&lt;/span&gt;&lt;span class="nb"&gt;null&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;mapcar&lt;/span&gt;
              &lt;span class="nf"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;valid-item-p&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;transform-item&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
              &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nv"&gt;processed&lt;/span&gt; &lt;span class="nf"&gt;#'&lt;/span&gt;&lt;span class="nv"&gt;item-compare&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;Why it's hard to read in Lisp:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Proper indentation is critical here because it’s the only way to &lt;em&gt;visually separate different parts of the code&lt;/em&gt;. Without clear indentation or if indentation is inconsistent, it becomes nearly impossible to &lt;em&gt;follow what’s happening at each level&lt;/em&gt; of nesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python Example:&lt;/strong&gt;&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;transform_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;valid_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;item_compare&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;Why Python is clearer:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python enforces consistent indentation as part of its syntax rules. This ensures that &lt;em&gt;code blocks are visually distinct&lt;/em&gt; and easy to follow without relying on parentheses or other delimiters.&lt;/p&gt;




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

&lt;p&gt;In each case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lisp's reliance on heavy nesting and uniform syntax creates challenges related to &lt;em&gt;readability, cognitive load, and debugging&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python addresses these issues by using features like indentation, infix operators, keywords (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;), and breaking logic into smaller steps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This comparison highlights &lt;em&gt;why many developers perceive Lisp's syntax as harder to read&lt;/em&gt; while appreciating Python's more &lt;em&gt;structured&lt;/em&gt; approach!&lt;/p&gt;




&lt;p&gt;Answer from Perplexity: &lt;a href="https://www.perplexity.ai/search/8f98d153-997c-4cca-8236-2ea8c2149ca6?utm_source=copy_output" rel="noopener noreferrer"&gt;https://www.perplexity.ai/search/8f98d153-997c-4cca-8236-2ea8c2149ca6?utm_source=copy_output&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>lisp</category>
      <category>syntax</category>
      <category>language</category>
    </item>
    <item>
      <title>Dynamic memory allocation - when, why and woes</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Thu, 13 Mar 2025 12:12:49 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/dynamic-memory-allocation-when-why-and-woes-4jj3</link>
      <guid>https://dev.to/playfulprogramming/dynamic-memory-allocation-when-why-and-woes-4jj3</guid>
      <description>&lt;p&gt;Sharing a good answer from perplexity.ai about dynamic memory allocation (as opposed to static memory allocation).&lt;/p&gt;

&lt;p&gt;Dynamic memory allocation is the process of assigning the memory space during the execution time (aka. the run time). (Static memory allocation is a process in which memory for variables and data structures is reserved at compile time, before the program runs.)&lt;/p&gt;




&lt;h1&gt;
  
  
  When was dynamic memory allocation first introduced and why?
&lt;/h1&gt;

&lt;p&gt;Dynamic memory allocation was first introduced in the early days of the C programming language, which was developed in the early 1970s. The concept became fully established and standardized with the 7th Edition of Unix, released in 1979[1].&lt;/p&gt;

&lt;p&gt;The introduction of dynamic memory allocation was driven by several key factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Flexibility: It allowed programs to request memory as needed at runtime, rather than having to pre-allocate all required memory at compile time[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient resource use: Dynamic allocation enabled more efficient use of limited memory resources, as memory could be allocated and deallocated as needed during program execution[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handling variable-sized data: It provided a solution for managing data structures whose size was not known until runtime, such as when reading data from user input or files[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overcoming limitations: Dynamic allocation addressed limitations of static and automatic memory allocation, which required compile-time constant sizes and had restricted lifetimes[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complex program needs: As programs became more complex, there was an increasing need for greater flexibility in memory management beyond what static and stack-based allocation could provide[2].&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The introduction of dynamic memory allocation represented a significant advancement in programming capabilities, allowing for more sophisticated and flexible software design. However, it also introduced new challenges, such as the need to manually manage memory to prevent leaks and fragmentation[3].&lt;/p&gt;

&lt;p&gt;Citations:&lt;br&gt;
[1] &lt;a href="https://patents.google.com/patent/US20110078404" rel="noopener noreferrer"&gt;https://patents.google.com/patent/US20110078404&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://en.wikipedia.org/wiki/C_dynamic_memory_allocation" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/C_dynamic_memory_allocation&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://en.wikipedia.org/wiki/Memory_management" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Memory_management&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://patents.google.com/patent/US20050268049A1/en" rel="noopener noreferrer"&gt;https://patents.google.com/patent/US20050268049A1/en&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://stackoverflow.com/questions/49354528/c-when-do-objects-of-classes-allocated-dynamic-memory" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/49354528/c-when-do-objects-of-classes-allocated-dynamic-memory&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://azrael.digipen.edu/%7Emmead/www/Courses/CS120/DynamicMemoryAllocation-1.html" rel="noopener noreferrer"&gt;https://azrael.digipen.edu/~mmead/www/Courses/CS120/DynamicMemoryAllocation-1.html&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://gamedev.stackexchange.com/questions/8206/dynamic-memory-allocation-and-memory-management" rel="noopener noreferrer"&gt;https://gamedev.stackexchange.com/questions/8206/dynamic-memory-allocation-and-memory-management&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  What problems did it lead to?
&lt;/h1&gt;

&lt;p&gt;Dynamic memory allocation, introduced in the early 1970s with the C programming language, led to several significant problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Memory leaks: Programs could lose references to allocated memory, causing gradual resource exhaustion[1][5].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fragmentation: Repeated allocation and deallocation could lead to memory fragmentation, making it difficult to find contiguous blocks of free memory[1][3].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Non-deterministic behavior: Allocation times became unpredictable, which is problematic for real-time systems[2][3].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allocation failures: Programs could run out of memory unexpectedly, or fail to allocate due to fragmentation[1][2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dangling pointers: Improper deallocation could result in pointers referencing freed memory[1].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance overhead: Dynamic allocation functions have significant execution overhead[1].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of reentrancy: Common implementations were not thread-safe, causing issues in multi-threaded systems[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inefficient memory usage: Dynamic allocation could lead to wasted space and inefficient memory utilization[1][5].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debugging complexity: Memory-related bugs became harder to identify and fix[5].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security vulnerabilities: Improper memory management could lead to exploitable security flaws[5].&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These issues are particularly problematic in embedded and real-time systems, where resources are constrained and predictable behavior is crucial[3][5].&lt;/p&gt;

&lt;p&gt;Citations:&lt;br&gt;
[1] &lt;a href="https://electrical.codidact.com/posts/286121" rel="noopener noreferrer"&gt;https://electrical.codidact.com/posts/286121&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://embeddedcomputing.com/technology/software-and-os/ides-application-programming/dynamic-memory-allocation-just-say-no" rel="noopener noreferrer"&gt;https://embeddedcomputing.com/technology/software-and-os/ides-application-programming/dynamic-memory-allocation-just-say-no&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://www.design-reuse.com/articles/25090/dynamic-memory-allocation-fragmentation-c.html" rel="noopener noreferrer"&gt;https://www.design-reuse.com/articles/25090/dynamic-memory-allocation-fragmentation-c.html&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://barrgroup.com/tech-talks/memory-allocation" rel="noopener noreferrer"&gt;https://barrgroup.com/tech-talks/memory-allocation&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://www.reddit.com/r/embedded/comments/u31pse/why_is_dynamic_memory_allocation_bad/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/embedded/comments/u31pse/why_is_dynamic_memory_allocation_bad/&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://stackoverflow.com/questions/72211874/what-is-the-practical-scenario-example-use-of-dynamic-memory-allocation-and-vect" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/72211874/what-is-the-practical-scenario-example-use-of-dynamic-memory-allocation-and-vect&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://blog.jyotiprakash.org/basic-dynamic-memory-allocation-programming-questions" rel="noopener noreferrer"&gt;https://blog.jyotiprakash.org/basic-dynamic-memory-allocation-programming-questions&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://docs.multiversx.com/developers/best-practices/the-dynamic-allocation-problem/" rel="noopener noreferrer"&gt;https://docs.multiversx.com/developers/best-practices/the-dynamic-allocation-problem/&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Programming languages without dynamic memory allocation?
&lt;/h1&gt;

&lt;p&gt;&lt;a href=""&gt;https://www.reddit.com/r/ProgrammingLanguages/comments/rz41q6/programming_languages_without_dynamic_memory/?rdt=40847&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systems</category>
      <category>rust</category>
      <category>zig</category>
      <category>c</category>
    </item>
    <item>
      <title>Offline-first app with GraphQL: React Relay vs. URQL</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Tue, 25 Feb 2025 11:37:29 +0000</pubDate>
      <link>https://dev.to/redbar0n/offline-first-app-with-graphql-react-relay-vs-urql-fb4</link>
      <guid>https://dev.to/redbar0n/offline-first-app-with-graphql-react-relay-vs-urql-fb4</guid>
      <description>&lt;p&gt;— A too good answer from perplexity.ai not to share, so here it is:&lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;Here’s a comparison of using &lt;strong&gt;React Relay (with or without &lt;code&gt;react-relay-offline&lt;/code&gt;)&lt;/strong&gt; versus &lt;strong&gt;Urql with Graphcache&lt;/strong&gt; for building offline-first apps:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;React Relay (Manual or with &lt;code&gt;react-relay-offline&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relay’s Strengths:&lt;/strong&gt; Built for GraphQL with optimized performance and normalized caching out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizability (Manual):&lt;/strong&gt; Full control over offline persistence, mutation queuing, and cache management when implementing manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-the-Box Offline Support (&lt;code&gt;react-relay-offline&lt;/code&gt;):&lt;/strong&gt; Simplifies offline functionality with features like mutation queuing, retries, and cache persistence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic Updates:&lt;/strong&gt; Easy to implement optimistic responses for better user experience during offline operations.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity (Manual):&lt;/strong&gt; Manual implementation requires significant effort to handle caching, persistence, and retries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle Size (&lt;code&gt;react-relay-offline&lt;/code&gt;):&lt;/strong&gt; Adds ~16.4 kB to the app size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Curve:&lt;/strong&gt; React Relay has a steeper learning curve compared to Urql due to its strict architecture and reliance on GraphQL fragments.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Urql with Graphcache&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular Design:&lt;/strong&gt; Urql’s exchange-based architecture allows flexibility in adding offline support using the &lt;code&gt;offlineExchange&lt;/code&gt; from Graphcache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graphcache Features:&lt;/strong&gt; Provides normalized caching, automatic updates based on schema, and offline persistence through storage layers like AsyncStorage or IndexedDB (&lt;a href="https://www.npmjs.com/package/@urql%2Fstorage-rn" rel="noopener noreferrer"&gt;learn more about &lt;code&gt;@urql/storage-rn&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Setup:&lt;/strong&gt; Adding offline support is straightforward by configuring &lt;code&gt;offlineExchange&lt;/code&gt; with storage (e.g., &lt;code&gt;@urql/storage-rn&lt;/code&gt; for React Native) (&lt;a href="https://egghead.io/lessons/react-native-add-read-only-offline-support-using-the-offline-exchange-from-urql-graphcache" rel="noopener noreferrer"&gt;check out this tutorial&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic Updates:&lt;/strong&gt; Supports optimistic responses and cache updates for seamless offline behavior.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom Logic for Mutations:&lt;/strong&gt; Offline mutations may require more manual handling (e.g., queuing failed mutations) compared to libraries like &lt;code&gt;react-relay-offline&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Offline Mutation Handling:&lt;/strong&gt; Mutations are only optimistically updated locally; if the server is unreachable during retries, changes may not persist unless custom logic is added (&lt;a href="https://github.com/urql-graphql/urql/discussions/2186" rel="noopener noreferrer"&gt;see discussion on Urql&lt;/a&gt; and &lt;a href="https://egghead.io/lessons/graphql-create-a-custom-exchange-for-urql-to-filter-out-mutations-when-offline" rel="noopener noreferrer"&gt;learn how to handle mutations offline&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Dependency:&lt;/strong&gt; Requires a well-defined schema for effective caching and updates.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Key Differences&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;React Relay (Manual)&lt;/th&gt;
&lt;th&gt;React Relay (&lt;code&gt;react-relay-offline&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Urql with Graphcache&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High complexity&lt;/td&gt;
&lt;td&gt;Medium complexity&lt;/td&gt;
&lt;td&gt;Low complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offline Query Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual setup&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mutation Queuing &amp;amp; Retry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual implementation&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Requires custom handling (&lt;a href="https://egghead.io/lessons/graphql-create-a-custom-exchange-for-urql-to-filter-out-mutations-when-offline" rel="noopener noreferrer"&gt;see how to handle mutations&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistence Options&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom storage logic needed&lt;/td&gt;
&lt;td&gt;Pre-configured options&lt;/td&gt;
&lt;td&gt;Pre-configured options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Optimistic Updates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Built-in hooks&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bundle Size Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;+16.4 kB&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Recommendation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;strong&gt;React Relay with &lt;code&gt;react-relay-offline&lt;/code&gt;&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are already using React Relay and need robust offline support with minimal additional setup.&lt;/li&gt;
&lt;li&gt;You require built-in mutation queuing and retry mechanisms.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;strong&gt;Urql with Graphcache&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You prefer a lightweight, modular library with flexibility in customizing exchanges.&lt;/li&gt;
&lt;li&gt;Your app primarily focuses on query caching and optimistic updates but can handle custom logic for mutation retries.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;strong&gt;Manual React Relay Implementation&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need full control over every aspect of offline functionality without relying on third-party libraries.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Relay is sometimes superior to URQL
&lt;/h3&gt;

&lt;p&gt;Relay is often considered superior to URQL for complex React applications due to its advanced features and optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: Relay's compiler pre-optimizes queries for runtime efficiency, ensuring high performance as applications scale (&lt;a href="https://dev.to/tigawanna/react-relay-2-years-later-its-still-awesome-jdg"&gt;learn more about Relay's performance&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Declarative Data Fetching&lt;/strong&gt;: Relay allows developers to declare data dependencies in components, automating data fetching and reducing boilerplate (&lt;a href="https://hasura.io/blog/exploring-graphql-clients-apollo-client-vs-relay-vs-urql" rel="noopener noreferrer"&gt;see Relay's declarative approach&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type Safety&lt;/strong&gt;: It auto-generates TypeScript/Flow types, ensuring schema consistency and reducing runtime errors (&lt;a href="https://dev.to/tigawanna/react-relay-2-years-later-its-still-awesome-jdg"&gt;explore Relay's type safety features&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built-in Features&lt;/strong&gt;: Relay provides out-of-the-box support for caching, pagination, optimistic updates, and conflict resolution, which URQL lacks natively (&lt;a href="https://hasura.io/blog/exploring-graphql-clients-apollo-client-vs-relay-vs-urql" rel="noopener noreferrer"&gt;discover Relay's built-in features&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strict Conventions&lt;/strong&gt;: Relay enforces GraphQL best practices, ensuring reliable APIs and clean architecture (&lt;a href="https://hasura.io/blog/exploring-graphql-clients-apollo-client-vs-relay-vs-urql" rel="noopener noreferrer"&gt;understand Relay's conventions&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, Relay has a steeper learning curve and requires stricter schema design, making URQL a simpler choice for smaller or less demanding projects (&lt;a href="https://dev.to/redbar0n/offline-first-app-with-graphql-react-relay-vs-urql-fb4"&gt;compare Relay and URQL for different project sizes&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in Features in Relay (Point 4 Expanded)
&lt;/h3&gt;

&lt;p&gt;Relay stands out because it provides &lt;strong&gt;robust, built-in features&lt;/strong&gt; that simplify complex GraphQL workflows. These features are designed to handle common challenges in data fetching and state management, reducing the need for additional libraries or custom implementations. Here's a detailed breakdown of these features:&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;1. Caching&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Relay includes a sophisticated &lt;strong&gt;normalized cache&lt;/strong&gt; out of the box. This means that data fetched from the server is stored in a normalized format, where each entity is stored by its unique identifier. This allows Relay to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Efficiently update only the parts of the UI that are affected by changes in the data.&lt;/li&gt;
&lt;li&gt;Avoid redundant network requests by reusing cached data whenever possible.&lt;/li&gt;
&lt;li&gt;Automatically merge new data into the cache without manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relay's cache is highly optimized and works seamlessly with its compiler, ensuring minimal runtime overhead.&lt;/p&gt;

&lt;p&gt;In contrast, while URQL has a caching layer (via its &lt;code&gt;@urql/exchange-graphcache&lt;/code&gt; package), it requires additional configuration and doesn't offer the same level of integration or performance optimization as Relay's built-in solution.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;2. Pagination&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Relay provides &lt;strong&gt;automatic pagination support&lt;/strong&gt; for GraphQL connections (a common pattern for paginated data in GraphQL). It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relay-style Cursor-based Pagination&lt;/strong&gt;: Relay is designed around GraphQL's connection model, making it easy to implement infinite scrolling or "load more" functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Cache Updates&lt;/strong&gt;: When fetching additional pages, Relay automatically updates the cache and merges new results with existing data without requiring manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;URQL does not have native pagination support. Developers often need to write custom logic or use third-party libraries to handle pagination effectively.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;3. Optimistic Updates&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Relay supports &lt;strong&gt;optimistic updates&lt;/strong&gt; out of the box, allowing developers to update the UI immediately after a mutation is triggered, even before receiving a response from the server. This creates a smoother user experience by reducing perceived latency.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;If a user submits a form, Relay can optimistically update the UI as if the mutation succeeded.&lt;/li&gt;
&lt;li&gt;If the mutation fails, Relay will roll back the optimistic update automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While URQL also supports optimistic updates, it requires more manual configuration compared to Relay's seamless integration with its store and cache.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;4. Conflict Resolution&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Relay includes mechanisms for handling &lt;strong&gt;data conflicts&lt;/strong&gt; that may arise when multiple operations (e.g., mutations) affect overlapping parts of the cache. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If two components request overlapping fields from the same object, Relay ensures that both components receive consistent and up-to-date data.&lt;/li&gt;
&lt;li&gt;When mutations are performed, Relay intelligently updates only the affected parts of the cache without overwriting unrelated fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This conflict resolution is tightly integrated with Relay's normalized cache and compiler-generated artifacts, making it reliable and efficient.&lt;/p&gt;

&lt;p&gt;URQL does not provide built-in conflict resolution mechanisms, leaving developers to handle such scenarios manually.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;5. Subscriptions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Relay supports &lt;strong&gt;GraphQL subscriptions&lt;/strong&gt; for real-time updates via third-party extensions or libraries (e.g., &lt;code&gt;subscriptions-transport-ws&lt;/code&gt; or &lt;code&gt;graphql-ws&lt;/code&gt;). Subscriptions integrate well with its caching layer, ensuring that real-time data updates are reflected throughout your application automatically.&lt;/p&gt;

&lt;p&gt;URQL also supports subscriptions but requires additional setup using its &lt;code&gt;@urql/exchange-subscription&lt;/code&gt; package. However, integrating subscriptions with URQL's cache can be more challenging compared to Relay's seamless approach.&lt;/p&gt;




&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Relay's built-in features like caching, pagination, optimistic updates, and conflict resolution are tightly integrated into its architecture. This makes it an excellent choice for large-scale applications where managing complex GraphQL workflows efficiently is critical. While URQL can achieve similar functionality with add-ons and custom logic, it requires more effort and lacks the deep integration and optimizations that Relay offers out of the box.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>react</category>
      <category>offlinefirst</category>
      <category>localfirst</category>
    </item>
    <item>
      <title>Ways of handling side-effects and IO</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Mon, 28 Oct 2024 12:20:23 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/ways-of-handling-side-effects-and-io-3e0c</link>
      <guid>https://dev.to/playfulprogramming/ways-of-handling-side-effects-and-io-3e0c</guid>
      <description>&lt;p&gt;I had this interaction with perplexity.ai regarding how various (functional) programming languages handle Input/Output (IO) and &lt;a href="https://dev.to/this-is-learning/side-effects-vs-side-causes-106c"&gt;side-effects&lt;/a&gt; in relation to balancing functional purity vs. developer ergonomics, and this summary was too good to not share, so here it is:&lt;/p&gt;




&lt;p&gt;Linear types and explicit IO handling can indeed help manage side effects, but they come with trade-offs. Let's explore this concept and its implications:&lt;/p&gt;

&lt;h2&gt;
  
  
  Linear Types and IO Handling
&lt;/h2&gt;

&lt;p&gt;Linear types, as used in languages like Rust, can provide a way to track and control side effects by ensuring that objects are used exactly once. This approach has several benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explicit resource management&lt;/li&gt;
&lt;li&gt;Guaranteed cleanup&lt;/li&gt;
&lt;li&gt;Thread safety&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, as you've noted, there are some challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  Passing IO Objects
&lt;/h3&gt;

&lt;p&gt;Passing an IO object through multiple function levels can become cumbersome. This is often referred to as "threading the state" through your program (akin to "prop drilling" in React). While it makes side effects explicit, it can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verbose function signatures&lt;/li&gt;
&lt;li&gt;Reduced code readability&lt;/li&gt;
&lt;li&gt;Potential for "parameter explosion"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using ...args
&lt;/h3&gt;

&lt;p&gt;Using variadic arguments (...args) to implicitly pass the IO object could indeed reduce the explicitness of the IO operations. This approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces verbosity&lt;/li&gt;
&lt;li&gt;May improve readability in some cases&lt;/li&gt;
&lt;li&gt;Loses some of the benefits of explicit IO handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Calling IO Directly
&lt;/h3&gt;

&lt;p&gt;Calling IO operations directly from the lowest-level function where they're needed might seem simpler, but it has drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces testability&lt;/li&gt;
&lt;li&gt;Makes the function less pure and harder to reason about&lt;/li&gt;
&lt;li&gt;Can lead to hidden dependencies and make refactoring more difficult&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alternative Approaches
&lt;/h2&gt;

&lt;p&gt;There are several ways to balance the benefits of linear types and explicit IO handling with code ergonomics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependency Injection&lt;/strong&gt;: Pass IO dependencies explicitly, but at a higher level of abstraction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monad Transformers&lt;/strong&gt;: Used in functional programming to compose different effects, including IO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effect Systems&lt;/strong&gt;: Provide a way to track and manage side effects at the type level, without the strict linearity of linear types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Capability-based Systems&lt;/strong&gt;: Control access to IO operations through capabilities that are passed explicitly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The choice between explicit IO handling with linear types and more implicit approaches depends on your specific needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For systems programming or safety-critical applications, the explicitness of linear types can be beneficial.&lt;/li&gt;
&lt;li&gt;For application development, a more flexible approach might be preferred.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, the goal is to find a balance between safety, explicitness, and ergonomics that suits your project's requirements.&lt;/p&gt;

&lt;p&gt;Citations:&lt;br&gt;
[1] &lt;a href="https://docs.rs/linear_type/latest/linear_type/" rel="noopener noreferrer"&gt;https://docs.rs/linear_type/latest/linear_type/&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://smallcultfollowing.com/babysteps/blog/2023/03/16/must-move-types/" rel="noopener noreferrer"&gt;https://smallcultfollowing.com/babysteps/blog/2023/03/16/must-move-types/&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://blog.yoshuawuyts.com/linearity-and-control/" rel="noopener noreferrer"&gt;https://blog.yoshuawuyts.com/linearity-and-control/&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://verdagon.dev/blog/linear-types-borrowing" rel="noopener noreferrer"&gt;https://verdagon.dev/blog/linear-types-borrowing&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://blog.yoshuawuyts.com/linear-types-one-pager/" rel="noopener noreferrer"&gt;https://blog.yoshuawuyts.com/linear-types-one-pager/&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://faultlore.com/blah/linear-rust/" rel="noopener noreferrer"&gt;https://faultlore.com/blah/linear-rust/&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://www.reddit.com/r/rust/comments/rei55q/less_painful_linear_types/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/rust/comments/rei55q/less_painful_linear_types/&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://www.youtube.com/watch?v=mocS_lErB1M" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=mocS_lErB1M&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Examples of each of the alternative approaches
&lt;/h1&gt;

&lt;p&gt;Certainly! I'll provide examples of the alternative approaches to dependency injection and IO handling that were mentioned. These approaches aim to balance the benefits of explicit IO handling with code ergonomics.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Dependency Injection
&lt;/h2&gt;

&lt;p&gt;Dependency Injection (DI) is a technique where dependencies are provided to a class from the outside, rather than being created within the class itself[1].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Constructor Injection&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ProductService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fetchProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PostgresDatabase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;ProductService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;Database&lt;/code&gt; dependency is injected into the &lt;code&gt;ProductService&lt;/code&gt; through its constructor. This allows for easy swapping of database implementations without changing the &lt;code&gt;ProductService&lt;/code&gt; code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Monad Transformers
&lt;/h2&gt;

&lt;p&gt;Monad Transformers are used in functional programming to compose different effects, including IO. While Java doesn't have built-in support for monads, we can simulate the concept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;computation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;computation&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;computation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;computation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;computation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;computation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
&lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wordCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;readFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="nc"&gt;IOMonad&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\s+"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wordCount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach allows for composing IO operations in a more functional style, making it easier to reason about and test.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Effect Systems
&lt;/h2&gt;

&lt;p&gt;Effect systems provide a way to track and manage side effects at the type level. While Java doesn't have a built-in effect system, libraries like ZIO for Scala demonstrate this concept. Here's a simplified example of how it might look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Effect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IOEffect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Effect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IORuntime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IORuntime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;IOEffect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IORuntime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IORuntime&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nc"&gt;IOEffect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IOEffect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach allows for explicit tracking of effects in the type system, making it clear what side effects a function might have.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Capability-based Systems
&lt;/h2&gt;

&lt;p&gt;Capability-based systems control access to IO operations through capabilities that are passed explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FileSystemCapability&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;FileSystemCapability&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FileSystemCapability&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;processFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nc"&gt;FileSystemCapability&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RealFileSystem&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;FileManager&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this approach, the &lt;code&gt;FileSystemCapability&lt;/code&gt; represents the ability to perform file operations. By passing this capability explicitly, we can control and track IO operations more effectively.&lt;/p&gt;

&lt;p&gt;Each of these approaches offers different trade-offs between explicitness, safety, and ergonomics. The choice depends on the specific requirements of your project and the language features available to you.&lt;/p&gt;

&lt;p&gt;Citations:&lt;br&gt;
[1] &lt;a href="https://stackoverflow.com/questions/130794/what-is-dependency-injection/131766" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/130794/what-is-dependency-injection/131766&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection?wt.mc_id=SEC-MVP-5004985" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection?wt.mc_id=SEC-MVP-5004985&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://www.tutorialsteacher.com/ioc/dependency-injection" rel="noopener noreferrer"&gt;https://www.tutorialsteacher.com/ioc/dependency-injection&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://www.mend.io/blog/how-to-use-dependency-injection-in-java-tutorial-with-examples/" rel="noopener noreferrer"&gt;https://www.mend.io/blog/how-to-use-dependency-injection-in-java-tutorial-with-examples/&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://builtin.com/articles/dependency-injection" rel="noopener noreferrer"&gt;https://builtin.com/articles/dependency-injection&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://www.smashingmagazine.com/2020/12/practical-introduction-dependency-injection/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2020/12/practical-introduction-dependency-injection/&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://stackify.com/dependency-injection/" rel="noopener noreferrer"&gt;https://stackify.com/dependency-injection/&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://developer.android.com/training/dependency-injection?authuser=3" rel="noopener noreferrer"&gt;https://developer.android.com/training/dependency-injection?authuser=3&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>architecture</category>
      <category>react</category>
    </item>
    <item>
      <title>Side-effects vs. side-causes</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Tue, 21 May 2024 10:24:13 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/side-effects-vs-side-causes-106c</link>
      <guid>https://dev.to/playfulprogramming/side-effects-vs-side-causes-106c</guid>
      <description>&lt;p&gt;The concept of "side-causes" doesn't seem to be a very established term yet, but I think it should be, for conceptual clarity.&lt;/p&gt;

&lt;p&gt;The current discussion in functional programming revolves very much around &lt;a href="https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29" rel="noopener noreferrer"&gt;side-effects&lt;/a&gt; (and how to avoid them). I've noticed a &lt;a href="https://stackoverflow.com/questions/4391524/is-returning-a-random-value-from-function-a-side-effect" rel="noopener noreferrer"&gt;tendency&lt;/a&gt; to label every undesired influence or reliance on externals as "side-effects". Which doesn't really make sense, if you think about it in terms related to our physical world (from where the concept of an 'effect' assumedly was derived, originally). In the physical world we have both causes and effects, which are clearly distinguished (albeit sadly often &lt;a href="https://www.scribbr.com/fallacies/false-cause-fallacy/" rel="noopener noreferrer"&gt;confused or reversed&lt;/a&gt;). So we'd do well to distinguish these concepts in programming as well.&lt;/p&gt;

&lt;p&gt;The colloquial definition seems to be that &lt;strong&gt;side-causes are hidden inputs&lt;/strong&gt;, and &lt;strong&gt;side-effects are hidden outputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But, with some help of our AI language model / search engine of choice (&lt;a href="https://www.perplexity.ai/" rel="noopener noreferrer"&gt;perplexity.ai&lt;/a&gt;), to word it more precisely and list useful examples, we can say the following.&lt;/p&gt;




&lt;p&gt;Side-effects and side-causes are related but distinct concepts in programming:&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Causes
&lt;/h2&gt;

&lt;p&gt;A side cause refers to an implicit input or dependency that a function relies on, beyond its explicit arguments. Some examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading from global variables or module-level state&lt;/li&gt;
&lt;li&gt;Getting the current time or generating random numbers&lt;/li&gt;
&lt;li&gt;Reading configuration from the environment or system properties&lt;/li&gt;
&lt;li&gt;Calling impure functions that depend on external state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Side causes violate &lt;a href="https://stackoverflow.com/a/210871/380607" rel="noopener noreferrer"&gt;referential transparency&lt;/a&gt;, meaning you cannot simply replace a function call with its result because the result may be different each time due to implicit inputs. This makes code harder to understand, test in isolation, optimize, and run in parallel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Effects
&lt;/h2&gt;

&lt;p&gt;A side effect is a change in system state or observable behavior that occurs as a result of executing a function or expression, beyond just returning a value. Some examples of side effects include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modifying a variable or data structure outside the function's local scope&lt;/li&gt;
&lt;li&gt;Writing to a file, network, or database&lt;/li&gt;
&lt;li&gt;Triggering an exception or error&lt;/li&gt;
&lt;li&gt;Calling other functions that have side effects&lt;/li&gt;
&lt;li&gt;Outputting data to the console or UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Side effects make a program's behavior dependent on the order of execution and previous state, which can make code harder to reason about, test, and maintain.[1]&lt;/p&gt;

&lt;p&gt;In summary, [explicit (my note)] side effects are about outputs/changes beyond the return value, while side causes are about implicit inputs beyond the arguments. Both can make code harder to reason about, especially in combination. Functional programming aims to minimize or isolate side effects and side causes for better modularity and determinism. [1][3]&lt;/p&gt;




&lt;h3&gt;
  
  
  Explicit vs Implicit Side-effects
&lt;/h3&gt;

&lt;p&gt;In addition here, we can make a further distinction between &lt;strong&gt;two variants of side-effects&lt;/strong&gt;. Importantly, side-causes often result in &lt;em&gt;implicit side-effects&lt;/em&gt;. Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if a function has a side-cause,&lt;/li&gt;
&lt;li&gt;and the side-cause changes from an invocation of the function to another,&lt;/li&gt;
&lt;li&gt;and the function uses it in computing its result,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then, even if the function does not affect the outside world apart from returning its result, the result is affected. This can be seen from the outside of the function (by anything that relies on its result). So even though the function didn't &lt;em&gt;directly&lt;/em&gt; affect the outside world, through a write operation or other kind of output occurring during the function execution, it still introduced some side-effect into it's own result. This is another way to view side-effects. &lt;strong&gt;Side-effects can be explicit (hidden extra outputs), but also implicit (silently modified results).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think the reason that side-causes are often erroneously called side-effects, is because side-causes generally &lt;em&gt;introduce (implicit) side-effects&lt;/em&gt;, if the side-cause affects the function's result in any manner. (If it doesn't change the result, why is the function even relying on that side-cause in the first place?). In this case you could say that "there is an unintended side-effect/surprise when calling the function", but simultaneously that "the function does not have a direct side-effect/cause on its environment".&lt;/p&gt;

&lt;p&gt;I hope this helped give some conceptual clarity, and can be a post to link to for distinguishing these two terms specifically.&lt;/p&gt;




&lt;p&gt;PS: Funnily enough, it seems the AI derived its understanding from the following citations, where the only citation it used that mentioned side-causes was my own brief comment on the Software Engineering Stack Exchange site:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"read from any input stream" is strictly speaking a side-cause, not a side-effect. Writing to an output stream would be a side-effect. See: blog.jenkster.com/2015/12/what-is-functional-programming.html&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Citations used by the AI:&lt;br&gt;
[1] &lt;a href="https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://www.linkedin.com/advice/0/what-some-common-sources-side-effects-functional" rel="noopener noreferrer"&gt;https://www.linkedin.com/advice/0/what-some-common-sources-side-effects-functional&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://softwareengineering.stackexchange.com/questions/15269/why-are-side-effects-considered-evil-in-functional-programming" rel="noopener noreferrer"&gt;https://softwareengineering.stackexchange.com/questions/15269/why-are-side-effects-considered-evil-in-functional-programming&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://dev.to/ruizb/side-effects-21fc"&gt;https://dev.to/ruizb/side-effects-21fc&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://www.freecodecamp.org/news/pure-function-vs-impure-function/" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/news/pure-function-vs-impure-function/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The top Google results I've found previously mentioning "side-causes" are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://blog.jenkster.com/2015/12/what-is-functional-programming.html" rel="noopener noreferrer"&gt;http://blog.jenkster.com/2015/12/what-is-functional-programming.html&lt;/a&gt; (Dec 2015)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chaddha.me/understanding-the-enigma-of-rxjava-part-1-8e04a456d9de" rel="noopener noreferrer"&gt;https://chaddha.me/understanding-the-enigma-of-rxjava-part-1-8e04a456d9de&lt;/a&gt; (3. Oct 2016)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gist.github.com/mattclaw/554cf037cdf5d05425d738863e8cfe97" rel="noopener noreferrer"&gt;https://gist.github.com/mattclaw/554cf037cdf5d05425d738863e8cfe97&lt;/a&gt; (22. Sept 2016)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/go-for-marty/what-are-pure-functions-side-causes-and-side-effects-5a2a01f7cbcd" rel="noopener noreferrer"&gt;https://medium.com/go-for-marty/what-are-pure-functions-side-causes-and-side-effects-5a2a01f7cbcd&lt;/a&gt; (14. Nov 2017)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.skylerlemay.com/blog/2019/08/19/what-is-a-side-effect-anyway-30daysoffp-week-2" rel="noopener noreferrer"&gt;https://www.skylerlemay.com/blog/2019/08/19/what-is-a-side-effect-anyway-30daysoffp-week-2&lt;/a&gt; (19. Aug 2019)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/functionalprogramming/comments/15axgtp/a_concise_name_for_code_lines_without_side/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/functionalprogramming/comments/15axgtp/a_concise_name_for_code_lines_without_side/&lt;/a&gt; (27. Jul 2023)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you know of any earlier reference to "side-causes"?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>coding</category>
      <category>computerscience</category>
      <category>functional</category>
    </item>
    <item>
      <title>Transducers and Eduction in Clojure simply explained</title>
      <dc:creator>Magne</dc:creator>
      <pubDate>Wed, 24 Apr 2024 13:35:36 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/transducers-and-eduction-in-clojure-simply-explained-5bij</link>
      <guid>https://dev.to/playfulprogramming/transducers-and-eduction-in-clojure-simply-explained-5bij</guid>
      <description>&lt;p&gt;&lt;em&gt;With help from our coming AI overlords:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Transducers and eduction in Clojure are ways to efficiently process and transform data, especially when working with large datasets.&lt;/p&gt;

&lt;p&gt;Here's a simple explanation:&lt;/p&gt;

&lt;h3&gt;
  
  
  Transducers:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Transducers are functions that can be composed together to create a sequence of transformations.&lt;/li&gt;
&lt;li&gt;They allow you to define a series of operations (like mapping, filtering, etc.) that can be applied to any collection of data, without having to worry about the specific data structure.&lt;/li&gt;
&lt;li&gt;Transducers are "context-independent" - they don't care about the input or output data structures, they just focus on the transformations.&lt;/li&gt;
&lt;li&gt;This makes transducers very flexible and reusable. You can combine them in different ways to create complex data pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Eduction:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Eduction is a way to apply a transducer to a collection of data without creating intermediate data structures.&lt;/li&gt;
&lt;li&gt;Normally, when you apply a series of transformations to a collection (e.g. map, filter, etc.), you end up creating a new collection at each step.&lt;/li&gt;
&lt;li&gt;With eduction, the transformations are applied "on the fly" as the data is consumed, without creating those intermediate collections.&lt;/li&gt;
&lt;li&gt;This can be much more efficient, especially when working with large datasets, because you don't have to allocate memory for all the intermediate results.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eduction&lt;/code&gt; is a Clojure core function that takes transducers as arguments, and captures the transduction process into a function. It applies the transducers to the input collection, but the result is a reducible/iterable, not a concrete data structure. You need to use functions like &lt;code&gt;iterator-seq&lt;/code&gt; to get a sequence from the reducible result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, &lt;strong&gt;transducers&lt;/strong&gt; allow you to &lt;strong&gt;&lt;em&gt;define&lt;/em&gt; reusable data transformations&lt;/strong&gt;, and &lt;strong&gt;eduction&lt;/strong&gt; allows you to &lt;strong&gt;&lt;em&gt;apply&lt;/em&gt; those transformations efficiently without creating unnecessary data structures&lt;/strong&gt;. Together, they provide a powerful way to build composable, high-performance data processing pipelines in Clojure.&lt;/p&gt;

&lt;p&gt;Eduction is best used when the result will be completely consumed in a reducible context. But transducers can be used with other functions as well, depending on the specific use case.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>dataflow</category>
      <category>streaming</category>
    </item>
  </channel>
</rss>
