<?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: Sergey Shandar</title>
    <description>The latest articles on DEV Community by Sergey Shandar (@sergeyshandar).</description>
    <link>https://dev.to/sergeyshandar</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%2F817742%2Ff22f6a9f-88c1-4f3d-81e5-2fbeedc31700.png</url>
      <title>DEV Community: Sergey Shandar</title>
      <link>https://dev.to/sergeyshandar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergeyshandar"/>
    <language>en</language>
    <item>
      <title>My JavaScript Set of Best Practices</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Mon, 20 Nov 2023 04:35:29 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/my-javascript-set-of-best-practices-32nb</link>
      <guid>https://dev.to/sergeyshandar/my-javascript-set-of-best-practices-32nb</guid>
      <description>&lt;p&gt;The article shares my set of rules to follow when coding JavaScript. But, before we go deep into them, I must let you know that the way how I use JavaScript is a little bit unusual. My main purpose in using JavaScript is to use only one programming language for high-level development, instead of C#, F#, Java, Scala, Python, etc. So, I'm trying to avoid non-generic JavaScript frameworks and platform-specific tools. For low-level and system programming, I'm using &lt;a href="https://en.wikipedia.org/wiki/Rust_(programming_language)"&gt;Rust&lt;/a&gt;, and considering &lt;a href="https://en.wikipedia.org/wiki/Zig_(programming_language)"&gt;Zig&lt;/a&gt; programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript as a linter
&lt;/h2&gt;

&lt;p&gt;While I'm a big fan of &lt;a href="https://en.wikipedia.org/wiki/Type_system#Static_type_checking"&gt;static typing&lt;/a&gt; and am impressed by the &lt;a href="https://en.wikipedia.org/wiki/TypeScript"&gt;TypeScript&lt;/a&gt; project, I no longer use TypeScript &lt;code&gt;.ts&lt;/code&gt; files in my projects. The main reason is to avoid building steps. A project should be ready to use without any build steps. However, I use the TypeScript compiler as a linter and &lt;a href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html"&gt;JSDoc&lt;/a&gt; as type definitions. To use the TypeScript compiler as a linter, you will need to set these properties in your &lt;code&gt;tsconfig.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noEmit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully, one day, we will see the &lt;a href="https://github.com/tc39/proposal-type-annotations"&gt;Type Annotation proposal&lt;/a&gt; in ECMAScript and supported by popular JavaScript engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  No classes or symbols
&lt;/h2&gt;

&lt;p&gt;I think that user's defined nominal types have no future in deterministic distributed systems. There are two main problems with JavaScript classes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Classes are part of the JavaScript &lt;a href="https://en.wikipedia.org/wiki/Nominal_type_system"&gt;nominal type system&lt;/a&gt;, in contrast to the TypeScript &lt;a href="https://en.wikipedia.org/wiki/Structural_type_system"&gt;structural type system&lt;/a&gt;. Nominal typing is location-based instead of content-based, like structural typing. It means a class is identified by where or when it's defined instead of its content. Location-based identifiers are very difficult to scale and create dependency hell.&lt;/li&gt;
&lt;li&gt;Serialization and deserialization of classes require additional code. This code, usually, doesn't have any semantic meaning and is an anti-pattern. Use standard JavaScript objects and arrays instead; they can be serialized and deserialized with just one function call.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol"&gt;JavaScript Symbols&lt;/a&gt; have the same scalability problems as classes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Functional programming
&lt;/h2&gt;

&lt;p&gt;Use functional programming and pure functions as much as possible. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't use direct I/O. Direct I/O is the primary source of side effects. You can use dependency injection. Instead of writing to a file directly, use a passed function that should write to a file. It will allow you to test your code much more effortlessly.&lt;/li&gt;
&lt;li&gt;Avoid mutability or try to localize data mutations.&lt;/li&gt;
&lt;li&gt;Use arrow functions and currying instead of multiple parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more about functional programming in JavaScript in &lt;a href="https://medium.com/bitsrc/purely-functional-programming-in-javascript-91114b1b2dff"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use ECMAScript modules
&lt;/h2&gt;

&lt;p&gt;ECMAScript modules are supported by most of the modern JavaScript engines and browsers. To avoid confusion with other module systems, use &lt;code&gt;.mjs&lt;/code&gt; file extension instead &lt;code&gt;.js&lt;/code&gt;. Currently, I'm using only &lt;code&gt;export default&lt;/code&gt; because it's consistent with loading JSON files and the &lt;a href="https://en.wikipedia.org/wiki/CommonJS"&gt;CommonJS&lt;/a&gt; system. I want to use only one &lt;code&gt;export&lt;/code&gt; method and prefer simplicity over syntax sugar.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;my&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;./export-default.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;./export.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Avoid third-party dependencies without a good reason
&lt;/h2&gt;

&lt;p&gt;Development dependencies such as TypeScript or &lt;a href="https://en.wikipedia.org/wiki/ESLint"&gt;ESLint&lt;/a&gt; are okay if they don't require additional build steps. Try to avoid libraries and frameworks that use direct I/O or platform specific. They will make your code very hard to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endnotes
&lt;/h2&gt;

&lt;p&gt;This set of rules is not for everyone. If you work in a big company with a big existing codebase, this may not work for you. However, if you are working on a new project, or you are a startup, or you are working on an open-source project, you may consider these points. Don't rush to infect your codebase with complex things that are difficult to maintain. Please keep it simple as long as possible and add complexity only when needed.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>BLOCKSET v0.2</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Thu, 12 Oct 2023 20:34:18 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/blockset-v02-5139</link>
      <guid>https://dev.to/sergeyshandar/blockset-v02-5139</guid>
      <description>&lt;h1&gt;
  
  
  blockset v0.2
&lt;/h1&gt;

&lt;p&gt;I'm pleased to announce that &lt;code&gt;blockset&lt;/code&gt; v0.2 has been released. It's the first working version.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the &lt;code&gt;blockset&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;blockset&lt;/code&gt; application is a command line program that can store and retrieve data blocks using a content-dependent tree (CDT) hash function as a universal address of the blocks. The &lt;a href="https://medium.com/@sergeyshandar/content-dependent-hash-tree-9e0f60859415"&gt;CDT&lt;/a&gt; hash function splits data into small connected parts of various sizes. The algorithm allows the detection of the same parts in blocks, even if they are located in different positions of the files. In essence, storage and network systems based on a CDT hash function should save space and traffic by detecting the same duplicate parts in data blocks. For example, it may save significant space if we store build artifacts of &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;CI&lt;/a&gt; in such storage.  &lt;/p&gt;

&lt;h2&gt;
  
  
  CDT function in the &lt;code&gt;blockset&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;There are a lot of possible CDT hash functions. As a community, we should select only a few, to make communication and storage more efficient. After multiple attempts, I selected one, which I call &lt;code&gt;CDT0&lt;/code&gt;. It uses &lt;a href="https://en.wikipedia.org/wiki/SHA-2"&gt;SHA224&lt;/a&gt; as a compress function and &lt;a href="https://en.wikipedia.org/wiki/Base32#Crockford's_Base32"&gt;Crockford's base32&lt;/a&gt; (45 characters) as a printable address, suitable for URLs and file names. I would like to publish an RFC for the function when I have more time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CDT storage
&lt;/h2&gt;

&lt;p&gt;There are different ways we can build storage based on the &lt;code&gt;CDT0&lt;/code&gt; function. The &lt;code&gt;blockset&lt;/code&gt; stores parts as a set of relatively small files located in a &lt;code&gt;cdt0/&lt;/code&gt; folder. Keeping block parts as files in the &lt;code&gt;cdt0/&lt;/code&gt; folder storage has its pros and cons, which are outlined below:&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of the &lt;code&gt;blockset&lt;/code&gt; storage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A simple file copy command can synchronize multiple storages. When files in different storages have matching names, they contain identical content, eliminating user dilemmas over potential overwrites.&lt;/li&gt;
&lt;li&gt;The files can be stored statically on &lt;a href="https://en.wikipedia.org/wiki/Content_delivery_network"&gt;CDN&lt;/a&gt;, and a relatively simple script can download parts and restore a requested data block. Each &lt;code&gt;blockset&lt;/code&gt; file is
relatively small (about several kilobytes), so the script can use a simple &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;fetch&lt;/a&gt; function. There is no need for fancy &lt;a href="https://en.wikipedia.org/wiki/Peer-to-peer"&gt;P2P&lt;/a&gt; network protocols, nodes, and custom servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages of the &lt;code&gt;blockset&lt;/code&gt; storage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As mentioned before, the &lt;code&gt;blockset&lt;/code&gt; maintains many small files. Keeping a lot of small files is not space-efficient.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;blockset&lt;/code&gt; file represents only one hash. However, the CDT hash function offers a superior better resolution. This higher resolution can increase the likelihood of detecting identical parts within data blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are multiple solutions to how these problems can be solved. We can use multiple different internal storage formats and synchronize multiple storages using different protocols as long as we use the same CDT function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation of &lt;code&gt;blockset&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;blockset&lt;/code&gt; can be installed on any computer and platform that supports Rust. To install Rust, see &lt;a href="https://www.rust-lang.org/tools/install"&gt;this page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Installing the &lt;code&gt;blockset&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;cargo install blockset
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uninstalling the &lt;code&gt;blockset&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;cargo uninstall blockset
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Address validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;blockset validate 3v1d4j94scaseqgcyzr0ha5dxa9rx6ppnfbndck971ack
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calculate address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;blockset address ./README.md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to the local storage &lt;code&gt;cdt0/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;blockset add ./LICENSE
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get a file by address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;blockset get ngd7zembwj6f2tsh4gyxrcyx26h221e3f2wdgfbtq87nd ./old.md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Internals
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;blockset&lt;/code&gt; is an open-source project under GPL-3 license. You can find its source code &lt;a href="https://github.com/datablockset/blockset"&gt;here&lt;/a&gt;. The project is written in Rust, and we've made a deliberate choice to minimize the use of macros. This enhances code readability and reduces hidden control flows, ensuring a more transparent and developer-friendly experience. Currently, the &lt;code&gt;blockset&lt;/code&gt; code has no third-party dependencies. All source files except &lt;code&gt;main.rs&lt;/code&gt; don't use I/O directly, which allows us to achieve and maintain 100% code coverage. &lt;/p&gt;

&lt;p&gt;Don't hesitate to contact me if you would like to know more, would like to build on either &lt;code&gt;CDT0&lt;/code&gt; or &lt;code&gt;blockset&lt;/code&gt;, or need another license:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/sergeyshandar/"&gt;LinkedIn&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://techhub.social/@functionalscript"&gt;Mastodon&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergey-shandar"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>datascience</category>
      <category>computerscience</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Content-Dependent Hash Tree</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Sat, 30 Sep 2023 05:06:10 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/content-dependent-hash-tree-4h44</link>
      <guid>https://dev.to/sergeyshandar/content-dependent-hash-tree-4h44</guid>
      <description>&lt;p&gt;In our &lt;a href="https://dev.to/sergeyshandar/some-aspects-of-merkle-tree-19jo"&gt;early discussion&lt;/a&gt;, we highlighted the advantages of using a cryptographic hash function based on a &lt;a href="https://en.wikipedia.org/wiki/Merkle_tree" rel="noopener noreferrer"&gt;Merkle tree&lt;/a&gt; for data transferring in &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_network" rel="noopener noreferrer"&gt;CAN&lt;/a&gt;. However, the Merkle tree is not shift-resistant, leading to potential redundancies in our block set or &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_storage" rel="noopener noreferrer"&gt;CAS&lt;/a&gt;. Here, we delve deeper to tackle this challenge.&lt;/p&gt;

&lt;p&gt;The main reason I publish the algorithm is that I firmly believe that we can't solve the &lt;a href="//data-vendor-lock-in.md"&gt;data vendor lock-in problem&lt;/a&gt; if we keep our data in proprietary formats. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deciphering a Sequence of Numbers
&lt;/h2&gt;

&lt;p&gt;Imagine intercepting messages from extraterrestrials. We don't know their language, but we assume that they use a sequential language unless they are from the &lt;a href="https://en.wikipedia.org/wiki/Arrival_(film)" rel="noopener noreferrer"&gt;Arrival&lt;/a&gt; film. The messages manifest as a sequence of numbers. We only know that each number is a finite number between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;N-1&lt;/code&gt;. How can we structure this stream without any linguistic reference points? How do we identify repetitive segments?&lt;/p&gt;

&lt;p&gt;Using N=8 as an example, consider these similar sequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s0 = [7, 0, 5, 1, 2, 4, 6, 1, 7, 0, 4, 7, 3, 4, 6, 2]&lt;/code&gt; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s1 = [7, 0, 5, 1, 2, 5, 4, 6, 1, 7, 0, 4, 7, 3, 4, 6]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a glance, shared groupings &lt;code&gt;[7, 0, 5, 1, 2]&lt;/code&gt; and &lt;code&gt;[6, 1, 7, 0, 4, 7, 3, 4, 6]&lt;/code&gt; are evident. But what about handling mammoth data streams in the range of gigabytes or terabytes? Some algorithms require &lt;code&gt;O(n^2)&lt;/code&gt; operations, where &lt;code&gt;n&lt;/code&gt; is the length of the sequences. We need something close to &lt;code&gt;O(n)&lt;/code&gt;. To achieve this, we should split our sequences into groups, without considering any knowledge of other sequences.&lt;/p&gt;

&lt;p&gt;If we group the numbers by pairs, like Merkle Tree does, we will have&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s0&lt;/code&gt;: &lt;code&gt;[[7, 0], [5, 1], [2, 4], [6, 1], [7, 0], [4, 7], [3, 4], [6, 2]]&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s1&lt;/code&gt;: &lt;code&gt;[[7, 0], [5, 1], [2, 5], [4, 6], [1, 7], [0, 4], [7, 3], [4, 6]]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, initially, we have the same groups &lt;code&gt;[7, 0]&lt;/code&gt;, &lt;code&gt;[5, 1]&lt;/code&gt;, but after that our groups are all different. The problem with such an approach is that the group size is fixed and independent of the group's content.&lt;/p&gt;

&lt;p&gt;One simple idea to have content-dependant grouping is to group numbers until they stop descending:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s0&lt;/code&gt;: &lt;code&gt;[[7, 0, 5], [1, 2], [4, 6], [1, 7], [0, 4], [7, 3, 4], [6, 2]]&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s1&lt;/code&gt;: &lt;code&gt;[[7, 0, 5], [1, 2], [5, 4, 6], [1, 7], [0, 4], [7, 3, 4], [6]]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One important rule is the autonomy of each group, akin &lt;a href="https://en.wikipedia.org/wiki/Context-free_grammar" rel="noopener noreferrer"&gt;context-free grammar&lt;/a&gt;. Grouping should only depend on items within the group. Extracting an element from a sequence mandates its inclusion in the current group. There's no going back. Sorry, "No Return Policy". An item may end the current group, and we will create a new one for the following numbers. Context-free grouping is suitable for validation because we can always validate a group without knowledge of surrounding groups.&lt;/p&gt;

&lt;p&gt;This algorithm can create the same groups of numbers in both sequences despite a shift in the middle: &lt;code&gt;[7, 0, 5]&lt;/code&gt; - 2 times, &lt;code&gt;[1, 2]&lt;/code&gt; - 2 times, &lt;code&gt;[1, 7]&lt;/code&gt; - 2 times, &lt;code&gt;[0, 4]&lt;/code&gt; - 2 times, &lt;code&gt;[7, 3, 4]&lt;/code&gt; - 2 times. The next step is to convert each group into a number and repeat the process.&lt;/p&gt;

&lt;p&gt;Let's try a simple approach: our function will convert numbers to strings and then concatenate them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s0 = ['705', '12', '46', '17', '04', '734', '62']&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s1 = ['705', '12', '546', '17', '04', '734', '6']&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next level of grouping will have the same group &lt;code&gt;1704&lt;/code&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s0 = ['7051246', '1704', '73462']&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s1 = ['70512546', '1704', '7346']&lt;/code&gt;,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the roots of the trees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;s0 = ['7051246170473462']&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s1 = ['7051254617047346']&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;p&gt;The string concatenation function works well for small sequences, but to create a good function for big data blocks, we need to research the properties of the groups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Group Properties
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;N&lt;/code&gt; is a number of possible items, then one group can have a maximum of &lt;code&gt;N+1&lt;/code&gt; items. For example, the longest groups for &lt;code&gt;N&lt;/code&gt; equals &lt;code&gt;8&lt;/code&gt; will be &lt;code&gt;[7, 6, 5, 4, 3, 2, 1, 0, x]&lt;/code&gt;, where &lt;code&gt;x&lt;/code&gt; is any number from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;7&lt;/code&gt;. A group can be partitioned into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Body&lt;/strong&gt;, all items in the group except the last one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tail&lt;/strong&gt;, the last item in the group.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Properties of a body:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a body has at least one item,&lt;/li&gt;
&lt;li&gt;numbers in the body never repeat,&lt;/li&gt;
&lt;li&gt;numbers are arranged in ascending order,&lt;/li&gt;
&lt;li&gt;the total number of unique bodies equals &lt;code&gt;2^N - 1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Properties of a tail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's always one item,&lt;/li&gt;
&lt;li&gt;the item is less than or equal to the last number of the body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the total group count &lt;code&gt;M&lt;/code&gt; equals &lt;code&gt;N*2^(N-1) + (N-1)*2^(N-2) + ... + 3*2^2 + 2*2 + 1 = (N-1)*2^N+1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The number of internal states during group assembling &lt;code&gt;S&lt;/code&gt; equals &lt;code&gt;(N-1)*2^(N+1)&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;M&lt;/th&gt;
&lt;th&gt;S&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;129&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;321&lt;/td&gt;
&lt;td&gt;640&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;769&lt;/td&gt;
&lt;td&gt;1536&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1793&lt;/td&gt;
&lt;td&gt;3584&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average length of the group is &lt;a href="https://en.wikipedia.org/wiki/E_(mathematical_constant)" rel="noopener noreferrer"&gt;e&lt;/a&gt;, ~2.71828 or less for small &lt;code&gt;N&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bit Stream
&lt;/h2&gt;

&lt;p&gt;We can start building our tree from any &lt;code&gt;N&lt;/code&gt;. The smallest possible &lt;code&gt;N&lt;/code&gt; is &lt;code&gt;2&lt;/code&gt;, and a leaf is either &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;. A good thing about a bit stream is that it doesn't rely on any artificial structure like a byte.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1
&lt;/h3&gt;

&lt;p&gt;The level 1 has 5 groups. Each group forms a new number id for the next level.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;group&lt;/th&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;00&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;N = 5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;S = 8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Min size: 2 bits. For example: &lt;code&gt;00&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Max size: 3 bits. For example: &lt;code&gt;101&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 2
&lt;/h3&gt;

&lt;p&gt;We use 5 numbers from the previous level as input for this level.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;N = 4*2^5 + 1 = 129&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;S = 256&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Min size: 4 bits. For example, &lt;code&gt;00&lt;/code&gt; of level 1 numbers or &lt;code&gt;0000&lt;/code&gt; as a bit sequence.&lt;/li&gt;
&lt;li&gt;Max size: 15 bits. For example, &lt;code&gt;432104&lt;/code&gt; of level 1 numbers or &lt;code&gt;101_100_11_01_00_101&lt;/code&gt; as a bit sequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 3
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;N = 128*2^129 + 1 = 2^136+1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S = 2^137&lt;/code&gt;. We need &lt;a href="https://en.wikipedia.org/wiki/137_(number)" rel="noopener noreferrer"&gt;137&lt;/a&gt; bits to store an internal state on the level 3.&lt;/li&gt;
&lt;li&gt;Min size: 8 bits.&lt;/li&gt;
&lt;li&gt;Max size: &lt;code&gt;0x480 + 0xF = 0x48F = 1152&lt;/code&gt; bits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 4 and up
&lt;/h3&gt;

&lt;p&gt;For levels four and up, we use hashes instead of actual data due to the explosive growth in &lt;code&gt;N&lt;/code&gt;. As we discussed before, the average length of the group is &lt;code&gt;e&lt;/code&gt;, but the maximal length of the groups for a big &lt;code&gt;N&lt;/code&gt; could be very long. I would like to discuss splitting the groups into smaller parts in one of the following articles. &lt;/p&gt;

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

&lt;p&gt;In essence, the content-dependent hash tree optimizes the identification of identical groups, catering well to both CAS and CAN applications. However, crafting a CAS on such a tree requires its own in-depth exploration.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>algorithms</category>
      <category>web3</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Some aspects of Merkle Tree</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Wed, 13 Sep 2023 20:53:02 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/some-aspects-of-merkle-tree-19jo</link>
      <guid>https://dev.to/sergeyshandar/some-aspects-of-merkle-tree-19jo</guid>
      <description>&lt;p&gt;Previously, I shared &lt;a href="https://dev.to/sergeyshandar/data-vendor-lock-in-and-web3-5cm8"&gt;my thoughts&lt;/a&gt; about how we can solve data vendor lock-in problem using &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_network" rel="noopener noreferrer"&gt;content-addressable network (CAN)&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_storage" rel="noopener noreferrer"&gt;content-addressable storage (CAS)&lt;/a&gt; for personal use. As mentioned in the article, we don't care how our network works as long as we can download a data block for a specific hash because we can always validate the downloaded data against the hash value. There is one problem with validation. If the hash validation fails and our file is quite big (say several gigabytes),  we waste our network time and resources for nothing.&lt;/p&gt;

&lt;p&gt;We wouldn't have such a problem if we could validate small parts of the data block while downloading the entire data block. One of the solutions is to use &lt;a href="https://en.wikipedia.org/wiki/Merkle_tree" rel="noopener noreferrer"&gt;Merkle Tree&lt;/a&gt; for our hash function. There are a lot of good articles and videos about it, and I don't want to repeat them. I want to focus on some of the essential aspects of the Merkle tree that you should know if you would like to implement one.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;f&lt;/code&gt; is a &lt;a href="https://en.wikipedia.org/wiki/One-way_compression_function" rel="noopener noreferrer"&gt;cryptographic compress hash function&lt;/a&gt; that accepts two digests and returns one. For example, &lt;code&gt;h01 = f(h0, h1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We split a data block into a list of digests &lt;code&gt;[d0, d1, ..., dN]&lt;/code&gt;. Let's assume that &lt;code&gt;N&lt;/code&gt; is &lt;code&gt;2^P&lt;/code&gt;, where &lt;code&gt;P&lt;/code&gt; is the height of the corresponding Merkle tree. Our tree will look like this:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Second Preimage Attack
&lt;/h2&gt;

&lt;p&gt;If we know data for a specific hash, we can create a collision because the tree doesn't distinguish between hash and data digests. So, it's possible to send hash digests instead of actual data. In this case, the validation will succeed, but the data will differ.&lt;/p&gt;

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

&lt;p&gt;It's called &lt;a href="https://en.wikipedia.org/wiki/Preimage_attack" rel="noopener noreferrer"&gt;second preimage attack&lt;/a&gt;. To prevent such attacks, we need to separate data from hashes.&lt;/p&gt;

&lt;p&gt;We can use another hash function for the data blocks to convert them into hash digests. Let's call it &lt;code&gt;g&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;g&lt;/code&gt; function should differ from &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another way to fix the issue is to extend a digest with one bit. If the bit is&lt;br&gt;
set to &lt;code&gt;0&lt;/code&gt;, then it's data; otherwise, it's a result of the &lt;code&gt;f&lt;/code&gt; hash function.&lt;/p&gt;

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

&lt;p&gt;Note that such extended digest should not be used to transfer secure data because short messages can be easily restored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tails
&lt;/h2&gt;

&lt;p&gt;Actual data usually is not aligned to &lt;code&gt;2^P&lt;/code&gt;. One way to fix the problem is to add one bit &lt;code&gt;1&lt;/code&gt; and then fill the rest with  zeros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Length Extension Attack
&lt;/h2&gt;

&lt;p&gt;If we have one Merkle Tree hash, we can use it as a node in another tree and create a valid hash for a new data block. This is called &lt;a href="https://en.wikipedia.org/wiki/Length_extension_attack" rel="noopener noreferrer"&gt;length extension attack&lt;/a&gt;. &lt;br&gt;
To solve it, we can transform a root hash into another hash before publishing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Shift Resistance
&lt;/h2&gt;

&lt;p&gt;Merkle Tree is a very good idea to split data blocks into parts. We can even reduce traffic if some parts are the same. Or, we don't need to download some parts if we already have them in our hash table.  However, it only works if the same data parts are aligned with Merkle Tree parts. This is a big limitation of Merkle Tree.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>web3</category>
      <category>computerscience</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Data Vendor Lock-In and Web3</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Sat, 09 Sep 2023 00:49:30 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/data-vendor-lock-in-and-web3-5cm8</link>
      <guid>https://dev.to/sergeyshandar/data-vendor-lock-in-and-web3-5cm8</guid>
      <description>&lt;h2&gt;
  
  
  What is the biggest problem with Web2?
&lt;/h2&gt;

&lt;p&gt;Most would say the biggest problem with Web2 is centralization. For example, we host our data using central services, like Web2 social networks, Web2 cloud providers, Web2 email providers, and others. We don’t have much control over our data using Web2 services. At any time, the service can refuse access to all or part of our data. People are &lt;a href="https://zulie.medium.com/what-youre-feeling-is-platform-fatigue-or-why-i-m-not-joining-threads-1e188369d25d"&gt;tired of switching platforms and losing their data&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does Web3 solve the problem of Web2?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Web3"&gt;Wikipedia&lt;/a&gt;, one of the main properties of Web3 is decentralization. There have been multiple attempts to provide decentralized services. For example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;social networks and messengers: &lt;a href="https://en.wikipedia.org/wiki/Mastodon_(social_network)"&gt;Mastodon&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Matrix_(protocol)"&gt;Matrix&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;cloud providers, like &lt;a href="https://en.wikipedia.org/wiki/InterPlanetary_File_System"&gt;IPFS&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;finances: &lt;a href="https://en.wikipedia.org/wiki/Bitcoin"&gt;Bitcoin&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Ethereum"&gt;Ethereum&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;and source control systems: &lt;a href="https://en.wikipedia.org/wiki/Git"&gt;Git&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Mercurial"&gt;Mercurial&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these services don't really solve the fundamental problem that a user's data should belong to the user. Even if it is decentralized, we need different applications or services to access and store our data. Some decentralized services (like blockchain) might shut down or change their protocol, and we will most likely lose access to our data again. It could also be hard to reference the data from a new storage. On top of that, storing data in a blockchain could be pretty expensive. I don't want to pay for every message that I send to a friend.&lt;/p&gt;

&lt;p&gt;Another problem with Web3 technologies, like blockchain, is that they are not designed for sub-networks. For example, often, a blockchain doesn't allow forking. How will it work if we would like to run the same internet on another planet while only having occasional synchronization? For example, a signal to Mars takes from 5 to 20 minutes. I know we are probably far away from this, but still, there can be other examples of isolated sub-networks that need to be synchronized occasionally.&lt;/p&gt;

&lt;p&gt;So, instead of centralized data vendor lock-in, we now have decentralized data vendor lock-in. It's better but doesn't completely solve the problem at hand and it's not future-proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's a solution?
&lt;/h2&gt;

&lt;p&gt;I think the solution is to switch our focus from protocols (how we access the data) to focusing on the structure of data and data formats.&lt;/p&gt;

&lt;p&gt;Let's say I create some information, like a block of data. It can be an article, an image, a short text message, a document, or something else. Imagine we have a storage that keeps such blocks. Then, how can we uniquely identify the blocks and avoid duplications in the storage? Well, there is a family of functions/algorithms that can produce a unique identifier for any data block; they are called &lt;a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function"&gt;cryptographic hash functions&lt;/a&gt;. For example: &lt;a href="https://en.wikipedia.org/wiki/SHA-2"&gt;SHA2&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/SHA-3"&gt;SHA3&lt;/a&gt;. This family of functions is already used by many decentralized systems. A storage that keeps data blocks and accesses them by a hash function is called a &lt;a href="https://en.wikipedia.org/wiki/Hash_table"&gt;hash table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note: A block of data is not a file. A file has additional information, such as a name and a file extension. A name of a file doesn't uniquely identify the data it holds. You may have multiple files with different names/paths that hold the same data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data synchronization
&lt;/h2&gt;

&lt;p&gt;If we keep our data in multiple file storages, we may face synchronization problems. Have you seen that message that repeats when you try to synchronize your files to a cloud file storage? "File already exists, do you want to replace it?". Honestly, the message freaks me out. I have no idea what I should answer. I just don't want to lose my data and avoid duplications. However, if we keep our data in a big hash table, it's not a big deal to compare two hash tables and synchronize them. There are no merge conflicts, no prompts, no data loss, and no duplications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens if our hash algorithm is compromised?
&lt;/h2&gt;

&lt;p&gt;In this case, we would freeze all our data, which is using the old hash algorithm, and make a kind of immutable registry of allowed/known hashes. This means we can't add new data using the old hash algorithm, but we can access it. For new data blocks, we can use a new hash algorithm that is not compromised yet.&lt;/p&gt;

&lt;p&gt;For example, we have a &lt;a href="https://en.wikipedia.org/wiki/SHA-1#SHAttered_%E2%80%93_first_public_collision"&gt;SHA1&lt;/a&gt; hash table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;hash&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sha1(A)&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sha1(B)&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After we find that the SHA1 is compromised, we create two new tables. The first table is an immutable mapping from SHA1 to SHA256. No new blocks can be added to this table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;hash&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sha1(A)&lt;/td&gt;
&lt;td&gt;sha256(A)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sha1(B)&lt;/td&gt;
&lt;td&gt;sha256(B)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The second table is a new table with SHA256. We can add new blocks to this table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;hash&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sha256(A)&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sha256(B)&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sha256(C)&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How can we reference such data blocks from other blocks?
&lt;/h2&gt;

&lt;p&gt;Most &lt;a href="https://en.wikipedia.org/wiki/Uniform_Resource_Identifier"&gt;URL schemas&lt;/a&gt; specify a protocol, for example, &lt;code&gt;https://&lt;/code&gt;. Even Web3 has URL-specific protocols, like &lt;code&gt;bitcoin://&lt;/code&gt;. To reference a data block or a file, we don't have to use a specific protocol. Some URL schemas are protocol agnostic, such as the &lt;a href="https://en.wikipedia.org/wiki/Uniform_Resource_Name"&gt;URN family&lt;/a&gt;. Centralized registration authorities usually assign a URN for each resource. For example, &lt;a href="https://en.wikipedia.org/wiki/ISBN"&gt;ISBN&lt;/a&gt; is used to assign unique numbers to commercial books.&lt;/p&gt;

&lt;p&gt;To reference a data block, we shouldn't have to use a registry authority, even if it's decentralized. The URN has no sub-schema for hash-based names, but there is a URL schema that is designed specifically for this being &lt;a href="https://www.rfc-editor.org/rfc/rfc6920.html"&gt;RFC6920&lt;/a&gt;. This RFC describes two schemas: &lt;code&gt;ni&lt;/code&gt; and &lt;code&gt;nih&lt;/code&gt;. To put it briefly, the ni schema is for a data block hash, like &lt;code&gt;ni://sha256;....&lt;/code&gt; The &lt;code&gt;nih&lt;/code&gt; is for a short form of the hash; it works similarly to a tiny URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directed acyclic graph
&lt;/h2&gt;

&lt;p&gt;If a data block can reference another data block, then such storage can be presented as a &lt;a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph"&gt;DAG&lt;/a&gt;. Assuming that our cryptographic hash is strong, it is almost impossible to create cycle references.&lt;/p&gt;

&lt;p&gt;Note: A tree is a special case of a DAG, and a blockchain is a special case of such a tree. When I want to create a new data block, I don't want to rely on a public blockchain like Bitcoin. Public blockchains are too expensive for such simple tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source of truth and cache
&lt;/h2&gt;

&lt;p&gt;A hash table storage should be considered a source of truth. It also can be used as a &lt;a href="https://martinfowler.com/eaaDev/EventSourcing.html"&gt;source of events&lt;/a&gt;. In hash table storages, we should only add new blocks but never delete old ones. If we want to delete an old block, we should add a new block that says the old one is deleted.&lt;/p&gt;

&lt;p&gt;The storage may contain a vast number of blocks, and if we would like to understand the current state of the storage, we would need to traverse all blocks. Although, it would not be an efficient algorithm for a big hash table, especially for a large amount of users. However, we can use a cache to store the current state of the storage. One of the good properties of a cache is that it can be easily recreated from the source of truth. A good cache-creating algorithm can also be scalable and distributed between multiple nodes using advanced techniques such as &lt;a href="https://en.wikipedia.org/wiki/MapReduce"&gt;MapReduce&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uX9WelTS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwjv53pez9u88el9goqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uX9WelTS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwjv53pez9u88el9goqh.png" alt="reading" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The arrows show the direction of the data flow. SourceOfTruth is read-only for the Cache, and the Cache is read-only for View in Application.&lt;/p&gt;

&lt;p&gt;If we would like to edit information, then we should add new blocks to the source of truth:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-exLu75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1mtgtyaekl0abp42wmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-exLu75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1mtgtyaekl0abp42wmy.png" alt="writing" width="661" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  User identity
&lt;/h2&gt;

&lt;p&gt;A user should not rely on centralized authorities to create an identity. Instead, they should be able to create a unique &lt;a href="https://en.wikipedia.org/wiki/Digital_signature"&gt;digital signature&lt;/a&gt;, publish its public key, and sign messages using the signature. A user may also publish associated centralized identities (for example, email addresses), but these identities should be considered &lt;a href="https://www.nbcnews.com/tech/tech-news/elon-musks-takes-x-handle-longtime-twitter-user-rcna96074"&gt;temporary&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time stamping
&lt;/h2&gt;

&lt;p&gt;Sometimes, signing a data block with a digital signature is not enough. A user may need to prove that they are the first who created the data block. Otherwise, another user can sign the same data block with their own digital signature.&lt;/p&gt;

&lt;p&gt;To sign a data block with a time stamp, we need to publish a new data block that will reference the original one. The new data block would contain a signed time stamp using &lt;a href="https://en.wikipedia.org/wiki/Trusted_timestamping"&gt;trusted timestamping&lt;/a&gt; services. There are also decentralized solutions, for example, using a blockchain. The timestamp can be used to prove that the data block was created before an event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building data block formats for different applications
&lt;/h2&gt;

&lt;p&gt;Here are some examples and thoughts about how we can make applications and services based on hash tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  A file catalog
&lt;/h3&gt;

&lt;p&gt;Building a file catalog is very simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"a.jpg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"f/a.jpg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may extend this format to include additional file attributes, such as executables.&lt;/p&gt;

&lt;h3&gt;
  
  
  A source control system
&lt;/h3&gt;

&lt;p&gt;A source control system is built similarly to a file, but it references previous file systems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"previous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commit message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"a.jpg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"f/a.jpg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Branches can be implemented either inside the data block (like in Mercurial) or outside (like in Git).&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a private group chat (social network)
&lt;/h3&gt;

&lt;p&gt;Making a public group chat is quite easy. A private group chat may require additional thoughts.&lt;/p&gt;

&lt;p&gt;We assume that our network protocol is encrypted, and we will only focus on the data that users receive and store. We cannot control what users are doing with our messages. They can store it, and some of them can even share it with others.&lt;/p&gt;

&lt;p&gt;That leads us to the problem of how can we make sure that everyone receives the same information and if the information is leaked how can we identify the source of the leak? When Alice sends a new message into a group chat, she sends it to all members of the group chat. After that, Alice sends different digital signatures for the message to each chat member. Each member of the group chat can verify that the message is signed by Alice. However, if the message is leaked, to prove that the message was sent by Alice, a whistleblower needs to uncover his identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  What else?
&lt;/h3&gt;

&lt;p&gt;Task manager, calendar, resume, etc. They all should have very simple formats and should be easy to edit. Note, that the performance should be provided by the cache, not by the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we know what's the format of the file?
&lt;/h2&gt;

&lt;p&gt;Unfortunately, there is no universal solution for this. We can try to parse the data with different readers/parsers and see if it's valid. Some applications may parse only a specific set of formats. We can also create a hint/container data block format, which will have an extension or MIME-type and a reference/contain to the data block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extension"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mime-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:1234567890..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "format": "container",
    "extension": "txt",
    "mime-type": "text/plain",
    "data": "Hello world!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, because we store different types of blocks in one storage, the data can be shared between applications of different vendors and types, for example between social networks, task managers, calendars, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens if a user's private key is stolen?
&lt;/h2&gt;

&lt;p&gt;In this case, a user can publish a new public key and notify their friends. The friends can publish a block that confirms that they do not accept new blocks signed by the old user's key and accept only blocks that are signed with the new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I hope for
&lt;/h2&gt;

&lt;p&gt;I would like to store data in such hash-table storage. I may have multiple storages, like public, private, and shared. Some of them may be in zero-knowledge encrypted storages, and some of them offline. Data blocks in the storage should still be able to reference each other. Then I can control access to the different storages by different applications.&lt;/p&gt;

&lt;p&gt;Applications and services may have their own rules, and it's their right. If it is a social network, they may decide not to show some of my posts, they may even decline service to me. However, they can never delete my data and I can still access my data using different applications and services.&lt;/p&gt;

&lt;p&gt;Also, I don't want to split my data between different services and applications. I would like to split my data by access, who can access the data.&lt;/p&gt;

&lt;p&gt;The current state of the internet reminds me of email hosting from internet providers. Then, you are stuck with this internet provider. It's a data vendor lock-in. Our identity and data should not depend on the service provider, on a big or small company, not even on a decentralized specific blockchain. Social network applications/services should use my data, not store it in proprietary storage. I should be able to switch between different social networks without losing my data. I should be able to create my own social network application that will browse my data. How many times we should start it from scratch and lose our data?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hotmail, Gmail, ProtonMail,&lt;/li&gt;
&lt;li&gt;ICQ, Skype, Viber, WhatsUp, Telegram, Signal,&lt;/li&gt;
&lt;li&gt;Teams, Slack, Discord,&lt;/li&gt;
&lt;li&gt;LiveJournal, Facebook, Twitter, Instagram, Threads, Mastodon,&lt;/li&gt;
&lt;li&gt;SourceForge, BitBucket, GitHub, GitLab,&lt;/li&gt;
&lt;li&gt;Wikipedia, Quora, Reddit, StackOverflow,&lt;/li&gt;
&lt;li&gt;Google Drive, Dropbox, OneDrive, iCloud.&lt;/li&gt;
&lt;li&gt;Google Calendar, Outlook Calendar, Apple Calendar.&lt;/li&gt;
&lt;li&gt;Asana, Jira,&lt;/li&gt;
&lt;li&gt;LinkedIn, Hired, Upwork, Freelancer,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please, stop! Enough! Really, it's enough! I like innovations, I like competitions, I like new start-ups, and I'm happy to change my internet/storage provider and applications. I'm okay with changing a communication protocol, however, I hate when I have to lose my data, my contacts, my communication, and other things. What is the point of sign-in to a new social network if your friends are not there? Or do I have to post my blogs on every social network? The data vendor lock-in problem is the biggest problem in Web2. &lt;br&gt;
Let's not carry it to Web3.&lt;/p&gt;

&lt;p&gt;In the end, I would like to highlight four main principles that we should follow when building a decentralized internet for people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol agnostic storages.&lt;/strong&gt; It doesn't matter which protocol we use to transfer our data to storage. As soon as the storage receives new data, it is able to accept the data without conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source of truth.&lt;/strong&gt; The user's data is a source of truth. Some services may store derived data, such as a cache, but it should be possible to recreate it from the source of truth if the derived data is lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No data vendor lock-in.&lt;/strong&gt; Applications and services should store user data in the storage of the user's choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity is decentralized.&lt;/strong&gt; Anyone can create new identities. The process doesn't require any registration authority. The identity is not tied to a specific service or application.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>web3</category>
      <category>datascience</category>
      <category>security</category>
      <category>community</category>
    </item>
    <item>
      <title>Purely Functional Programming in JavaScript</title>
      <dc:creator>Sergey Shandar</dc:creator>
      <pubDate>Sat, 09 Sep 2023 00:36:12 +0000</pubDate>
      <link>https://dev.to/sergeyshandar/purely-functional-programming-in-javascript-152d</link>
      <guid>https://dev.to/sergeyshandar/purely-functional-programming-in-javascript-152d</guid>
      <description>&lt;p&gt;There are a lot of articles, videos, and blog posts about &lt;a href="https://en.wikipedia.org/wiki/Functional_programming"&gt;functional programming&lt;/a&gt; using different programming languages, including &lt;a href="https://en.wikipedia.org/wiki/JavaScript"&gt;JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Usually, the main topic of these articles is how to use various functional programming paradigms, such as &lt;a href="https://en.wikipedia.org/wiki/First-class_function"&gt;first-class functions&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Immutable_object"&gt;immutable objects&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Currying"&gt;currying&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nevertheless, the primary value of &lt;a href="https://en.wikipedia.org/wiki/Purely_functional_programming"&gt;purely functional programming languages&lt;/a&gt; is an absence of &lt;a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)"&gt;side effects&lt;/a&gt;. Partial applications of different functional paradigms in impure languages, such as JavaScript, may reduce the number of side effects but don't guarantee their complete elimination.&lt;/p&gt;

&lt;p&gt;Side effects reduce scalability and the ability to replace components and platforms. So, it is preferable to reduce the number of side effects to a bare minimum.&lt;/p&gt;

&lt;p&gt;There are dozens of purely functional programming languages. Some of them are pretty successful in the software development industry - for example, &lt;a href="https://en.wikipedia.org/wiki/Haskell"&gt;Haskell&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Elm_(programming_language)"&gt;Elm&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/PureScript"&gt;PureScript&lt;/a&gt;. However, the most popular programming language is JavaScript, and it is not purely functional.&lt;/p&gt;

&lt;p&gt;The main reason to use JavaScript, besides its popularity, is that almost any web browser can run it. Also, one of the most popular data interchange and file formats is &lt;a href="https://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt;, a subset of JavaScript. Because of this JSON/JavaScript relation, &lt;a href="https://en.wikipedia.org/wiki/Serialization"&gt;serialization&lt;/a&gt; in JavaScript is more straightforward than in other programming languages. In my experience, &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming"&gt;object-oriented programming languages&lt;/a&gt; usually have the biggest challenges in serialization.&lt;/p&gt;

&lt;p&gt;Any working program has side effects such as input/output, functions that return the current time, or random numbers.&lt;/p&gt;

&lt;p&gt;But it is possible to write a big part of a program without using impure functions. An impure function can be rewritten as a pure function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addAndPrint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pureAddAndPrint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pure functions are much more flexible. A developer may use the &lt;code&gt;pureAddAndPrint&lt;/code&gt; function with either pure or impure arguments, such as &lt;code&gt;console.log&lt;/code&gt;. Some platforms may not have &lt;code&gt;console.log&lt;/code&gt;, and in that case, a developer could provide a replacement for it.&lt;/p&gt;

&lt;p&gt;Another use case is unit testing, and a developer may create a mock function and pass it as an argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Currying
&lt;/h2&gt;

&lt;p&gt;You may notice function declarations in this article use currying. In most purely functional programming languages, a function can accept only one argument, and currying is a way to provide multiple arguments to a function.&lt;/p&gt;

&lt;p&gt;Another way is to use a &lt;a href="https://en.wikipedia.org/wiki/Tuple"&gt;tuple&lt;/a&gt; as an argument:&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;const&lt;/span&gt; &lt;span class="nx"&gt;tupleAddAndPrint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, currying can simplify partial function applications:&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;// using currying&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;consoleLogAddCurry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pureAddAndPrint&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// using tuples&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;consoleLogAddTuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;tupleAddAndPrint&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Safety
&lt;/h2&gt;

&lt;p&gt;Usually, purely functional languages provide better safety. A pure function can’t access data outside passed arguments. On the contrary, an impure function can access almost anything, which increases the probability of vulnerabilities.&lt;/p&gt;

&lt;p&gt;One such example is the famous &lt;a href="https://en.wikipedia.org/wiki/Log4Shell"&gt;Log4Shell&lt;/a&gt;. &lt;a href="https://en.wikipedia.org/wiki/Log4j"&gt;Log4j&lt;/a&gt; is written in an impure language (Java), and users were not aware it uses HTTPS to download and run code. A pure implementation of Log4j would require an HTTPS protocol as an argument.&lt;/p&gt;

&lt;p&gt;In this case, users have some level of control, and, most likely, they would provide a &lt;a href="https://en.wikipedia.org/wiki/Method_stub"&gt;stub&lt;/a&gt; instead of an actual HTTPS protocol. Pure functions do not provide absolute protection, but they can significantly reduce the probability of vulnerabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  FunctionalScript
&lt;/h2&gt;

&lt;p&gt;It is possible to write purely functional code in an impure language. &lt;a href="https://github.com/functionalscript/functionalscript"&gt;FunctionalScript&lt;/a&gt; is an attempt to create a purely functional subset of JavaScript, and the subset should not have the ability to create a function with side effects.&lt;/p&gt;

&lt;p&gt;Because FunctionalScript is a subset of JavaScript, we do not need to develop compilers, transpilers, debuggers, IDEs, and other development tools for the language.&lt;/p&gt;

&lt;p&gt;Also, developers do not need to learn an entirely new programming language and how it interacts with other systems and languages. FunctionalScript is an open specification and has no risk of vendor lock-in.&lt;/p&gt;

&lt;p&gt;Even if the FunctionalScript specification disappears completely, any FunctionalScript code will still work like any other JavaScript code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursion Problem
&lt;/h2&gt;

&lt;p&gt;Most purely functional programming languages have no loops because all data is immutable.&lt;/p&gt;

&lt;p&gt;Instead, developers use recursion:&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;const&lt;/span&gt; &lt;span class="nx"&gt;factorial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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;Recursion consumes stack, and it can cause a stack overflow in case of too many recursive calls. Functional languages solve this problem by &lt;a href="https://en.wikipedia.org/wiki/Tail_call"&gt;tail call&lt;/a&gt; elimination. Note that a compiler can only eliminate a call if it’s the last call or operation.&lt;/p&gt;

&lt;p&gt;For example, a tail call elimination can not be applied to our factorial function because the last operation is multiplication instead of factorial. However, we can change the function so that the tail call elimination can be applied.&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;const&lt;/span&gt; &lt;span class="nx"&gt;factorialTail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;factorialTail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;n&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;factorial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;factorialTail&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JavaScript standard (&lt;a href="https://webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit/"&gt;ECMAScript 6&lt;/a&gt;) supports the tail call elimination (aka a proper tail call), but V8 and SpiderMonkey do not. That means that Google Chrome, Microsoft Edge, Node.js, and Firefox do not support PTC. So, de facto, JavaScript has no PTC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loops in FunctionalScript
&lt;/h2&gt;

&lt;p&gt;The problem is that FunctionalScript objects are immutable, and, as shown above, we can’t use recursion for iterations.&lt;/p&gt;

&lt;p&gt;FunctionalScript allows reassigning of local variables declared with let as a workaround for this problem, and such variables can only be used inside a function where the variables are declared.&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;const&lt;/span&gt; &lt;span class="nx"&gt;factorial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;
        &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  WebAssembly
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/WebAssembly"&gt;WebAssembly&lt;/a&gt; allows developers to create web applications using almost any programming language. It is derived from &lt;a href="https://en.wikipedia.org/wiki/Asm.js"&gt;asm.js&lt;/a&gt;, which is also a subset of JavaScript.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;near-native code execution speed,&lt;/li&gt;
&lt;li&gt;different programming languages support compilation to WebAssembly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;requires additional build steps and tools,&lt;/li&gt;
&lt;li&gt;WebAssembly programs should interact with &lt;a href="https://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt; and other JavaScript &lt;a href="https://en.wikipedia.org/wiki/API"&gt;API&lt;/a&gt; using a &lt;a href="https://en.wikipedia.org/wiki/Language_interoperability"&gt;language interoperability&lt;/a&gt; layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;asm.js inspired FunctionalScript as a subset of JavaScript. Compared to asm.js and WebAssembly, FunctionalScript is a high-level programming language. Theoretically, it is possible to create &lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;JIT&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Ahead-of-time_compilation"&gt;AOT&lt;/a&gt; compilers from FunctionalScript to WebAssembly, or any other assembly language.&lt;/p&gt;

&lt;p&gt;Compared to JavaScript, a compiler from FunctionalScript may generate more optimal code because similar FunctionalScript code is more deterministic.&lt;/p&gt;

&lt;p&gt;For example, FunctionalScript can use a reference counter instead of a proper garbage collector because immutable data can not have circular references.&lt;/p&gt;

&lt;p&gt;Also, other purely functional programming languages, such as Elm, can use FunctionalScript as a compilation target.&lt;/p&gt;

&lt;h2&gt;
  
  
  FunctionalScript API Limitations
&lt;/h2&gt;

&lt;p&gt;As was mentioned earlier, FunctionalScript can not directly call functions with side effects. Because JavaScript API has many impure functions, only a limited subset of JavaScript API is available to FunctionalScript.&lt;/p&gt;

&lt;p&gt;However, a JavaScript program can pass impure functions to FunctionalScript modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typing
&lt;/h2&gt;

&lt;p&gt;FunctionalScript derived a &lt;a href="https://en.wikipedia.org/wiki/Type_system#Dynamic_type_checking_and_runtime_type_information"&gt;dynamic type system&lt;/a&gt; from JavaScript. Nevertheless, it is possible to use &lt;a href="https://en.wikipedia.org/wiki/JSDoc"&gt;JSDoc type annotations&lt;/a&gt; and a &lt;a href="https://en.wikipedia.org/wiki/TypeScript"&gt;TypeScript&lt;/a&gt; compiler as a validator. For example&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="cm"&gt;/** @type {(a: number) =&amp;gt; (b: number) =&amp;gt; number} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html"&gt;TypeScript JSDoc Reference&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;TypeScript uses a &lt;a href="https://en.wikipedia.org/wiki/Structural_type_system"&gt;structural type system&lt;/a&gt; instead of a &lt;a href="https://en.wikipedia.org/wiki/Nominal_type_system"&gt;nominal type system&lt;/a&gt;. Languages with a nominal type system may cause typecasting problems in big projects with many third-party modules. For example, two definitions of Vector3D are not compatible, and &lt;a href="https://en.wikipedia.org/wiki/Adapter_pattern"&gt;adapters&lt;/a&gt; are required. Because of this, structural type systems enhance modularization and code reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modules and Packages
&lt;/h2&gt;

&lt;p&gt;FunctionalScript uses a &lt;a href="https://en.wikipedia.org/wiki/Node.js"&gt;Node.js&lt;/a&gt; package manager (&lt;a href="https://en.wikipedia.org/wiki/Npm"&gt;npm&lt;/a&gt;) and &lt;a href="https://en.wikipedia.org/wiki/CommonJS"&gt;CommonJS&lt;/a&gt; as a module system. CommonJS is easy to implement even without a FunctionalScript parser.&lt;/p&gt;

&lt;p&gt;Because FunctionalScript is a purely functional language, a FunctionalScript module can only reference another FunctionalScript module. But, a JavaScript module can reference any FunctionalScript module.&lt;/p&gt;

&lt;p&gt;Currently, FunctionalScript does not support ECMAScript Modules and asynchronous modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Modules
&lt;/h2&gt;

&lt;p&gt;CommonJS supports loading JSON files as JavaScript modules. Because JSON contains only data, any JSON file is also a FunctionalScript module.&lt;/p&gt;

&lt;p&gt;Note that the loading procedure differs for JSON and JavaScript files, even if JSON is a subset of JavaScript.&lt;/p&gt;

&lt;p&gt;A JSON module declares all public exports in the first expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A JavaScript Common.js module declares all public exports in &lt;code&gt;module.exports&lt;/code&gt;.&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Applications
&lt;/h2&gt;

&lt;p&gt;FunctionalScript code can be used in any JavaScript/TypeScript application. Because FunctionalScript code has no direct access to IO, the same code can be used on different platforms, for example, web-browser, Node.js.&lt;/p&gt;

&lt;p&gt;FunctionalScript is a superset of JSON. Because it has no side effects, it can be used as a JSON with pure functions and expressions, for example, in configuration files.&lt;/p&gt;

&lt;p&gt;Another application is a query language as an alternative to &lt;a href="https://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Language_Integrated_Query"&gt;LINQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
