<?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>Forem: Artyom Molchanov </title>
    <description>The latest articles on Forem by Artyom Molchanov  (@adamanq).</description>
    <link>https://forem.com/adamanq</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%2F1280112%2Fb59a5543-6559-46c7-8ef7-aa39ebd2e013.png</url>
      <title>Forem: Artyom Molchanov </title>
      <link>https://forem.com/adamanq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/adamanq"/>
    <language>en</language>
    <item>
      <title>Ash Framework: Introduction</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Sat, 04 Apr 2026 08:18:54 +0000</pubDate>
      <link>https://forem.com/adamanq/ash-framework-introduction-3lm3</link>
      <guid>https://forem.com/adamanq/ash-framework-introduction-3lm3</guid>
      <description>&lt;p&gt;When a newcomer starts with Elixir and Phoenix, they are almost always introduced to &lt;strong&gt;Ecto&lt;/strong&gt; first. You create schemas, write changesets, and move queries into contexts. This approach is flexible, but as the project grows, a serious problem begins to emerge 😟&lt;/p&gt;

&lt;p&gt;Business logic starts to spread across dozens of files. Eventually, confusion arises about where to place request handling code and how to make sense of the existing mess. After a year or two, it becomes difficult to understand where the “right” place for code is, and new developers spend weeks just getting up to speed with the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ash Framework&lt;/strong&gt; was created precisely to solve this pain 💪&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important clarification&lt;/strong&gt;: Ash is &lt;strong&gt;not a replacement for Phoenix&lt;/strong&gt; and not a new web framework. It is a powerful declarative layer that organizes business logic and data on top of the existing ecosystem.&lt;/p&gt;
&lt;/blockquote&gt;

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




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

&lt;h2&gt;
  
  
  📖 Preface
&lt;/h2&gt;

&lt;p&gt;It’s important to understand that the goal of this article is not to convince you to use Ash everywhere and all the time!&lt;/p&gt;

&lt;p&gt;Personally, I love Ash because it allows you to gather all necessary logic in a single space, where it belongs. This tool significantly simplifies work, reducing boilerplate code and freeing you from the tedious implementation of standard CRUD.&lt;/p&gt;

&lt;p&gt;If you’re ready to get acquainted with such a tool but plan to use it only when truly justified—read on without hesitation. Ash is not a universal cure-all, but rather a convenient set of useful tools.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🚀 What is Ash?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ash-hq.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/a&gt; is a framework for fast and efficient application development in Elixir. Its goal is to simplify launching new projects and make maintaining existing solutions convenient, ensuring excellent performance and stability even after long periods of active development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key idea of Ash is:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Precisely define the structure of your business logic, and let Ash handle all the rest (database migrations, API interface creation, data validation, access control, form generation).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The framework integrates beautifully with popular tools like Phoenix, PostgreSQL, GraphQL, and LiveView.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🔑 Key Abstractions in Ash
&lt;/h2&gt;

&lt;p&gt;Everything in Ash is built around three main concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/dsl-ash-resource.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Resource&lt;/strong&gt;&lt;/a&gt; — description of a single business entity&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/actions.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Action&lt;/strong&gt;&lt;/a&gt; — an operation that can be performed on a resource&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/domains.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Domain&lt;/strong&gt;&lt;/a&gt; — logical grouping of resources within one business area&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s break down each concept in detail!&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🧩 What is a Resource?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Resource&lt;/strong&gt; is &lt;strong&gt;one module&lt;/strong&gt; where a &lt;strong&gt;single business entity&lt;/strong&gt; of your application (User, Lesson, Order, Post, Payment, etc.) is fully described.&lt;/p&gt;

&lt;p&gt;Everything related to this entity is collected in one place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data structure (fields)&lt;/li&gt;
&lt;li&gt;Relationships with other entities&lt;/li&gt;
&lt;li&gt;Operations that can be performed (CRUD + custom)&lt;/li&gt;
&lt;li&gt;Validation rules&lt;/li&gt;
&lt;li&gt;Authorization (who can do what)&lt;/li&gt;
&lt;li&gt;Computed fields&lt;/li&gt;
&lt;li&gt;Indexes and constraints&lt;/li&gt;
&lt;li&gt;Storage settings in the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Resource in Ash unifies in one module what in classic Elixir/Phoenix is usually spread across several parts: Ecto Schema, Changesets, Context functions, as well as authorization logic and computed fields.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Resource — The Heart of Ash
&lt;/h3&gt;

&lt;p&gt;Ash is built around the idea of &lt;strong&gt;Resource-Oriented Design&lt;/strong&gt;. You describe &lt;strong&gt;what&lt;/strong&gt; an entity is and &lt;strong&gt;what&lt;/strong&gt; can be done with it—and Ash generates the rest: SQL queries, APIs, forms, migrations, validation, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Complete Example of a Modern Resource
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:course_hub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;domain:&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;data_layer:&lt;/span&gt; &lt;span class="no"&gt;AshPostgres&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataLayer&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== STORAGE ====================&lt;/span&gt;
  &lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="s2"&gt;"lessons"&lt;/span&gt;
    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== FIELDS (Attributes) ====================&lt;/span&gt;
  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;uuid_primary_key&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;allow_nil?&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="ss"&gt;min_length:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_length:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;public?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;public?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:atom&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;default?&lt;/span&gt; &lt;span class="ss"&gt;:draft&lt;/span&gt;
      &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="ss"&gt;one_of:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:archived&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;create_timestamp&lt;/span&gt; &lt;span class="ss"&gt;:inserted_at&lt;/span&gt;
    &lt;span class="n"&gt;update_timestamp&lt;/span&gt; &lt;span class="ss"&gt;:updated_at&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== RELATIONSHIPS ====================&lt;/span&gt;
  &lt;span class="n"&gt;relationships&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;allow_nil?&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Comment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;many_to_many&lt;/span&gt; &lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tag&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;LessonTag&lt;/span&gt;
      &lt;span class="n"&gt;source_attribute_on_join_resource&lt;/span&gt; &lt;span class="ss"&gt;:lesson_id&lt;/span&gt;
      &lt;span class="n"&gt;destination_attribute_on_join_resource&lt;/span&gt; &lt;span class="ss"&gt;:tag_id&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ACTIONS ====================&lt;/span&gt;
  &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Custom read&lt;/span&gt;
    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;pagination&lt;/span&gt; &lt;span class="ss"&gt;offset?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;countable:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Custom create with logic&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Fully custom action&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:calculate_reading_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== COMPUTED FIELDS ====================&lt;/span&gt;
  &lt;span class="n"&gt;calculations&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculate&lt;/span&gt; &lt;span class="ss"&gt;:reading_time_minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;calculation&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&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="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Float&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== INDEXES ====================&lt;/span&gt;
  &lt;span class="n"&gt;identities&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="ss"&gt;:unique_title_per_author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:author_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== AUTHORIZATION ====================&lt;/span&gt;
  &lt;span class="n"&gt;policies&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="n"&gt;action_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;authorize_if&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;authorize_if&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Main Sections of Resource
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Describes&lt;/th&gt;
&lt;th&gt;Analog in Classic Elixir/Phoenix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;attributes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fields and their types + validation&lt;/td&gt;
&lt;td&gt;Ecto Schema + fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;relationships&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Relationships with other resources&lt;/td&gt;
&lt;td&gt;Ecto associations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;actions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All possible operations (CRUD + custom)&lt;/td&gt;
&lt;td&gt;Context functions + Changesets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calculations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Computed fields (on the fly)&lt;/td&gt;
&lt;td&gt;Virtual fields / functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aggregates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aggregates (count, sum, avg, etc.)&lt;/td&gt;
&lt;td&gt;Queries with group_by&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;identities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique indexes&lt;/td&gt;
&lt;td&gt;Ecto unique constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;policies&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Authorization rules&lt;/td&gt;
&lt;td&gt;Manual permission checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;postgres&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL storage settings&lt;/td&gt;
&lt;td&gt;Migrations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Key Features of Resource
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Everything in one file&lt;/strong&gt; — a huge plus for understanding the entity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introspection&lt;/strong&gt; — Ash can read all information about a resource at runtime (fields, actions, policies). This is used for API generation, forms, admin panels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarativeness&lt;/strong&gt; — you describe &lt;strong&gt;what&lt;/strong&gt; should be there, not &lt;strong&gt;how&lt;/strong&gt; to implement it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt; — you can add your own &lt;code&gt;changes&lt;/code&gt;, &lt;code&gt;preparations&lt;/code&gt;, &lt;code&gt;validations&lt;/code&gt;, &lt;code&gt;notifiers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded Resources&lt;/strong&gt; — you can create resources stored not in a separate table but as JSON/Map within another resource.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  When to Create a New Resource?
&lt;/h3&gt;

&lt;p&gt;Almost always when a new business entity appears (a table or even a complex JSON object).&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🛠️ More About Actions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Action&lt;/strong&gt; is an &lt;strong&gt;explicitly declared operation&lt;/strong&gt; that can be performed on a resource.&lt;br&gt;
All data interaction in Ash goes &lt;strong&gt;only through Actions&lt;/strong&gt;. You cannot simply take a record and change it manually—you always call an action.&lt;/p&gt;

&lt;p&gt;This replaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular functions in Phoenix Contexts&lt;/li&gt;
&lt;li&gt;Changesets in Ecto&lt;/li&gt;
&lt;li&gt;Controllers and service layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ㅤ &lt;br&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Five Types of Actions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Action Type&lt;/th&gt;
&lt;th&gt;What It Does?&lt;/th&gt;
&lt;th&gt;In Transaction?&lt;/th&gt;
&lt;th&gt;Returns?&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;strong&gt;&lt;code&gt;create&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Creates a new record&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;New resource record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔍&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;read&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reads one record or a list&lt;/td&gt;
&lt;td&gt;No (can be enabled)&lt;/td&gt;
&lt;td&gt;Record or list of records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✏️&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;update&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Updates an existing record&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Updated record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🗑️&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;destroy&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deletes a record&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Deleted record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;action&lt;/code&gt;&lt;/strong&gt; (Generic)&lt;/td&gt;
&lt;td&gt;Any custom business logic&lt;/td&gt;
&lt;td&gt;No (can be enabled)&lt;/td&gt;
&lt;td&gt;Any value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ㅤ &lt;br&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Complete Example of All Action Types
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Standard CRUD (defaults)&lt;/span&gt;
    &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Custom Read&lt;/span&gt;
    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;pagination&lt;/span&gt; &lt;span class="ss"&gt;offset?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;countable:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default_limit:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
      &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;load:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:comment_count&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:for_user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Custom Create&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

      &lt;span class="c1"&gt;# Changes (changes)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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;change&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;NotifySubscribers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic:&lt;/span&gt; &lt;span class="s2"&gt;"new_lessons"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;# Hooks&lt;/span&gt;
      &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;_changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Custom Update&lt;/span&gt;
    &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:archive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:archive_reason&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:archived&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:archived_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Generic Action (fully custom)&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:calculate_reading_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:words_per_minute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default?:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

      &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;words_per_minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;ㅤ &lt;br&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  How to Call Actions
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Through Domain (recommended way)&lt;/span&gt;
&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;reason:&lt;/span&gt; &lt;span class="s2"&gt;"Готово"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Or with Ash.Query / Ash.Changeset for complex cases&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;for_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;ㅤ &lt;br&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Main Capabilities of Actions
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. &lt;code&gt;argument&lt;/code&gt; — Input Parameters
&lt;/h4&gt;

&lt;p&gt;Allows passing data into an action and validating it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;constraints:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;min_length:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default?:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. &lt;code&gt;accept&lt;/code&gt; — Which Attributes Can Be Changed
&lt;/h4&gt;

&lt;p&gt;Limits the list of fields that can be modified during &lt;code&gt;create&lt;/code&gt; or &lt;code&gt;update&lt;/code&gt;. Very useful for security.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:register&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:update_profile&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar_url&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;code&gt;change&lt;/code&gt; — Data Transformations
&lt;/h4&gt;

&lt;p&gt;The most powerful and frequently used part of Actions. Here the main business logic happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;

  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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;change&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;NotifySubscribers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic:&lt;/span&gt; &lt;span class="s2"&gt;"lessons"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;code&gt;prepare&lt;/code&gt; — Query Preparation (mainly for &lt;code&gt;read&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Allows pre-configuring the query: sorting, preloading relations, additional filters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;load:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:comments&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;limit:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Hooks (before/after)
&lt;/h4&gt;

&lt;p&gt;Allows executing code before or after an action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;validate_business_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;_changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="no"&gt;LessonNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after_transaction&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;broadcast_new_lesson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. &lt;code&gt;transaction?&lt;/code&gt; — Transaction Management
&lt;/h4&gt;

&lt;p&gt;Determines whether the action should be wrapped in a database transaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:transfer_money&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boolean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:from_account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:to_account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:decimal&lt;/span&gt;

  &lt;span class="n"&gt;transaction?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# complex operation with multiple records&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  7. &lt;code&gt;pipe_through&lt;/code&gt; — Reusing Logic
&lt;/h4&gt;

&lt;p&gt;Allows creating common pipelines and attaching them to different actions (very useful for DRY).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In Resource&lt;/span&gt;
&lt;span class="n"&gt;pipelines&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;ensure_actor_role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="n"&gt;actor_role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:create_admin_content&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:update_admin_content&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Why Actions Are Awesome?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full typing and introspection&lt;/strong&gt; — Ash knows everything about an action at runtime (used for GraphQL, forms, admin panels).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarativeness&lt;/strong&gt; — code reads like business documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability&lt;/strong&gt; — one action can be used in LiveView, API, Background Job, Tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; — authorization policies are tied to specific actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt; — easy to test individual actions.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Comparison with Classic Elixir/Phoenix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Where is logic?&lt;/th&gt;
&lt;th&gt;Number of files&lt;/th&gt;
&lt;th&gt;Clarity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ecto + Context&lt;/td&gt;
&lt;td&gt;Context + Changeset&lt;/td&gt;
&lt;td&gt;4–8&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ash Actions&lt;/td&gt;
&lt;td&gt;In one Resource&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Actions are where all your business logic lives.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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




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

&lt;h2&gt;
  
  
  🏢 What is a Domain?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Domain&lt;/strong&gt; is a &lt;strong&gt;logical container&lt;/strong&gt; that groups related &lt;strong&gt;Resources&lt;/strong&gt;.&lt;br&gt;
It is similar to &lt;strong&gt;Phoenix Context&lt;/strong&gt;, but much more powerful. If Resource describes one entity (like &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Lesson&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt;), then Domain is a "module" or "bounded context" (in DDD terms) that brings together several entities of one business area.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Accounts&lt;/code&gt; — domain for users, profiles, authorization.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Courses&lt;/code&gt; — domain for courses, lessons, tests, enrollments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Billing&lt;/code&gt; — domain for payments, subscriptions, invoices.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Therapy&lt;/code&gt; — domain for therapy sessions, conversations, messages.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Three Main Goals of Domain
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Grouping Resources&lt;/strong&gt;
Organizing the project. Instead of all resources being scattered, they are explicitly grouped into logical units.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Code Interface&lt;/strong&gt;
Domain allows defining convenient wrapper functions for calling resource actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Settings and Cross-Cutting Concerns&lt;/strong&gt;
Here you can set behavior that applies to all resources in the domain (timeouts, default pagination, authorization, etc.).&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  How Domain Looks in Practice
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:course_hub&lt;/span&gt;

  &lt;span class="c1"&gt;# 1. Grouping resources&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Course&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Quiz&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enrollment&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 2. Code Interface — convenient functions&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:get_lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;args:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;get?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:list_published_courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:enroll_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;resource:&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enrollment&lt;/span&gt;

  &lt;span class="c1"&gt;# 3. Shared settings&lt;/span&gt;
  &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;default_page_size&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Enabling AshAdmin (admin panel)&lt;/span&gt;
  &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;show?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Why Do You Need Domain?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organization and boundaries.&lt;/strong&gt; Clearly separates different parts of the application (like bounded contexts in DDD). &lt;code&gt;Accounts&lt;/code&gt; doesn't know about &lt;code&gt;Billing&lt;/code&gt; without explicit relations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convenient public API.&lt;/strong&gt; Instead of &lt;code&gt;Ash.read!(CourseHub.Courses.Lesson, ...)&lt;/code&gt;, you write beautifully:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lesson!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_published_courses!&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;
&lt;strong&gt;Centralized management.&lt;/strong&gt; You can disable authorization for the entire domain in dev mode, set common policies, notifiers, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introspection and extensions.&lt;/strong&gt; Many Ash extensions (GraphQL, JsonApi, Phoenix) work at the domain level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing and isolation.&lt;/strong&gt; Easier to test one business area as a whole.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Best Practices When Working with Domains
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One resource — one domain.&lt;/strong&gt; A resource cannot belong to multiple domains simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How many domains to make?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Small project → 1–3 domains.&lt;/li&gt;
&lt;li&gt;Medium/large → one per major business area (Accounts, Core, Billing, Notifications, etc.).
This helps with scaling and understanding architecture.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Code Interface&lt;/strong&gt; — a very powerful feature. You can define not only simple wrappers but also those with preset filters, loads, etc.&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Comparison: Domain vs Resource
&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;Resource&lt;/th&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it describes&lt;/td&gt;
&lt;td&gt;One entity&lt;/td&gt;
&lt;td&gt;Group of entities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where logic lies&lt;/td&gt;
&lt;td&gt;Attributes, actions, policies&lt;/td&gt;
&lt;td&gt;Grouping + shared settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code call&lt;/td&gt;
&lt;td&gt;Through domain&lt;/td&gt;
&lt;td&gt;Public app interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analog in Phoenix&lt;/td&gt;
&lt;td&gt;Schema + Context (partially)&lt;/td&gt;
&lt;td&gt;Phoenix Context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quantity per project&lt;/td&gt;
&lt;td&gt;Many (one per table)&lt;/td&gt;
&lt;td&gt;Few (per business area)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Why Domain Is Especially Useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Project grows &amp;gt;10–15 resources.&lt;/li&gt;
&lt;li&gt;Complex authorization (policies) needed.&lt;/li&gt;
&lt;li&gt;Doing GraphQL / JSON:API / Admin panel.&lt;/li&gt;
&lt;li&gt;Team development — everyone needs to understand boundaries.&lt;/li&gt;
&lt;/ul&gt;

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




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

&lt;h2&gt;
  
  
  ⚔️ Ash + Phoenix vs Ecto + Phoenix
&lt;/h2&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;Phoenix + Ecto (classic) 😐&lt;/th&gt;
&lt;th&gt;Phoenix + Ash 🔥&lt;/th&gt;
&lt;th&gt;Who wins?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Business logic organization&lt;/td&gt;
&lt;td&gt;Scattered across Context, Changeset, separate modules&lt;/td&gt;
&lt;td&gt;Everything in one Resource&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CRUD operations&lt;/td&gt;
&lt;td&gt;Write manually: create, read, update, delete + boilerplate&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;defaults [:create, :read, :update, :destroy]&lt;/code&gt; — done ✨&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization&lt;/td&gt;
&lt;td&gt;Manual checks / Bodyguard / scopes&lt;/td&gt;
&lt;td&gt;Declarative Policies (secure by default) ⚡&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Computed fields&lt;/td&gt;
&lt;td&gt;Virtual fields + functions in Context&lt;/td&gt;
&lt;td&gt;Calculations — auto-loaded and cached&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Number of files per entity&lt;/td&gt;
&lt;td&gt;3–6+ files (Schema + Context + Changeset + Policy)&lt;/td&gt;
&lt;td&gt;One file — Resource&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API generation&lt;/td&gt;
&lt;td&gt;Absinthe / GraphQL manually + lots of code&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AshGraphql&lt;/code&gt; or &lt;code&gt;AshJsonApi&lt;/code&gt; — add extension and done&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LiveView forms&lt;/td&gt;
&lt;td&gt;Phoenix.Component + manual validation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AshPhoenix.Form&lt;/code&gt; — forms know everything themselves&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;Write yourself (or use schemas)&lt;/td&gt;
&lt;td&gt;Built into Policies (attribute-based or context-based)&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintainability after 2–3 years&lt;/td&gt;
&lt;td&gt;Medium (logic spreads)&lt;/td&gt;
&lt;td&gt;High (everything declarative and in one place)&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development speed&lt;/td&gt;
&lt;td&gt;Normal at start&lt;/td&gt;
&lt;td&gt;Much faster after learning curve 🚀&lt;/td&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Maximum (full control)&lt;/td&gt;
&lt;td&gt;Very high + can escape to pure Ecto when needed&lt;/td&gt;
&lt;td&gt;Draw&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;Easier for beginners&lt;/td&gt;
&lt;td&gt;Steeper but pays off in large projects&lt;/td&gt;
&lt;td&gt;Ecto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  What to Choose in 2026?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros of Ash&lt;/strong&gt; 🔥:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarativeness → "Describe the domain — Ash does the rest."&lt;/li&gt;
&lt;li&gt;Boilerplate reduction by orders of magnitude ("I write code 3–5 times faster").&lt;/li&gt;
&lt;li&gt;Automatic generation of GraphQL, JSON:API, Admin panel, authentication.&lt;/li&gt;
&lt;li&gt;Authorization policies and multi-tenancy out of the box.&lt;/li&gt;
&lt;li&gt;Excellent maintainability in the long run (exactly what production dreams of).
&lt;strong&gt;Pros of classic Phoenix + Ecto&lt;/strong&gt; 😐:&lt;/li&gt;
&lt;li&gt;Full control over every byte of code.&lt;/li&gt;
&lt;li&gt;Simpler for very small projects and pet projects.&lt;/li&gt;
&lt;li&gt;No extra abstraction (if you love "bare" Elixir).&lt;/li&gt;
&lt;li&gt;Easier for Elixir beginners.
&lt;strong&gt;When to choose what?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Small pet project or experiment → pure Phoenix + Ecto.&lt;/li&gt;
&lt;li&gt;Medium/large project, SaaS, long-lived app → Phoenix + Ash (huge time and nerve savings).&lt;/li&gt;
&lt;li&gt;Want both → you can safely mix in one project (Ash and regular Ecto coexist perfectly).&lt;/li&gt;
&lt;/ul&gt;

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




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

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

&lt;p&gt;Ash is not just a library but a shift in approach to Elixir development. It especially shines in medium and large projects where clean architecture, development speed, and long-term maintainability are important.&lt;br&gt;
Of course, it has a learning curve and may be excessive for very simple pet projects. But if you're tired of spreading logic and want a clear declarative structure—Ash gives a very pleasant sense of control over your code.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🙏 From the Author
&lt;/h2&gt;

&lt;p&gt;Thank you very much for your interest in this article! I hope it helped you understand what Ash is and why it's used.&lt;br&gt;
If you liked this article and want more materials like this—join me on my &lt;a href="https://t.me/devs_inc_en" rel="noopener noreferrer"&gt;Telegram channel&lt;/a&gt;, where I post book reviews, Elixir publications, technical literature, and interesting news!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ash</category>
      <category>phoenix</category>
      <category>ecto</category>
    </item>
    <item>
      <title>Ash Framework: Знакомство</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Sat, 04 Apr 2026 08:05:54 +0000</pubDate>
      <link>https://forem.com/adamanq/ash-framework-znakomstvo-g0g</link>
      <guid>https://forem.com/adamanq/ash-framework-znakomstvo-g0g</guid>
      <description>&lt;p&gt;Когда новичок приходит в Elixir и Phoenix, ему почти всегда первым делом показывают &lt;strong&gt;Ecto&lt;/strong&gt;. Создаём схемы, пишем changeset’ы, выносим запросы в контексты. Подход гибкий, но с ростом проекта начинает проявляться серьёзная проблема 😟&lt;/p&gt;

&lt;p&gt;Бизнес-логика расползается по десяткам файлов. В итоге возникает путаница относительно того, куда именно поместить код обработки запросов и как разобраться в существующем беспорядке, а через год-два сложно понять, где находится «правильное» место для кода, а новые разработчики тратят недели на погружение в проект&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ash Framework&lt;/strong&gt; создан именно для решения этой боли 💪&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Важное уточнение&lt;/strong&gt;: Ash — это &lt;strong&gt;не замена Phoenix&lt;/strong&gt; и не новый веб-фреймворк. Это мощный декларативный слой, который организует бизнес-логику и данные поверх существующей экосистемы.&lt;/p&gt;
&lt;/blockquote&gt;

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




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

&lt;h2&gt;
  
  
  📖 Предисловие
&lt;/h2&gt;

&lt;p&gt;Важно понимать, что цель этой статьи вовсе не состоит в том, чтобы уговорить вас использовать Ash повсеместно и постоянно!&lt;/p&gt;

&lt;p&gt;Сам я люблю Ash именно из-за того, что он даёт возможность собрать всю необходимую логику в едином пространстве, где ей самое место. Этот инструмент значительно упрощает работу, уменьшая количество шаблонного кода и освобождая от утомительной реализации стандартных CRUD.&lt;/p&gt;

&lt;p&gt;Если готовы ознакомиться с таким инструментом, но собираетесь прибегать к нему лишь тогда, когда это действительно оправдано — смело читайте дальше. Ash — это не универсальное лекарство от всех проблем, а всего лишь удобный набор полезных инструментов.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🚀 Что такое Ash?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ash-hq.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/a&gt; — это фреймворк для быстрой и эффективной разработки приложений на Elixir. Его цель заключается в облегчении запуска новых проектов и обеспечении удобства поддержки существующих решений, гарантируя отличную производительность и стабильность даже после длительного периода активной разработки.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ключевая идея Ash звучит так:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Точно сформулируй структуру своей бизнес-логики, а всю остальную работу (миграция базы данных, создание API-интерфейсов, валидация данных, управление доступом, оформление форм) возьмет на себя Ash&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Фреймворк прекрасно взаимодействует с такими популярными инструментами, как Phoenix, PostgreSQL, GraphQL и LiveView.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🔑 Ключевые абстракции Ash
&lt;/h2&gt;

&lt;p&gt;Всё в Ash строится вокруг трёх основных понятий:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/dsl-ash-resource.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Resource (Ресурс)&lt;/strong&gt;&lt;/a&gt; — описание одной бизнес-сущности&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/actions.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Action (Действие)&lt;/strong&gt;&lt;/a&gt; — операция, которую можно выполнить над ресурсом&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/ash/domains.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Domain (Домен)&lt;/strong&gt;&lt;/a&gt; — логическая группа ресурсов одной бизнес-области&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Давайте разберём каждую концепцию подробно!&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🧩 Что такое Ресурс?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Resource&lt;/strong&gt; — это &lt;strong&gt;один модуль&lt;/strong&gt;, в котором полностью описана &lt;strong&gt;одна бизнес-сущность&lt;/strong&gt; вашего приложения (Пользователь, Урок, Заказ, Пост, Платёж и т.д.).&lt;/p&gt;

&lt;p&gt;В нём в одном месте собрано &lt;strong&gt;всё&lt;/strong&gt;, что касается этой сущности:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Структура данных (поля)&lt;/li&gt;
&lt;li&gt;Связи с другими сущностями&lt;/li&gt;
&lt;li&gt;Операции, которые можно выполнять (CRUD + кастомные)&lt;/li&gt;
&lt;li&gt;Правила валидации&lt;/li&gt;
&lt;li&gt;Авторизация (кто и что может делать)&lt;/li&gt;
&lt;li&gt;Вычисляемые поля&lt;/li&gt;
&lt;li&gt;Индексы и ограничения&lt;/li&gt;
&lt;li&gt;Настройки хранения в базе&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resource в Ash объединяет в одном модуле то, что в классическом Elixir/Phoenix обычно разносится по нескольким частям: Ecto Schema, Changesets, Context-функции, а также логика авторизации и вычисляемые поля.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Resource — сердце Ash
&lt;/h3&gt;

&lt;p&gt;Ash построен вокруг идеи &lt;strong&gt;Resource-Oriented Design&lt;/strong&gt;. Ты описываешь &lt;strong&gt;что&lt;/strong&gt; представляет собой сущность и &lt;strong&gt;что&lt;/strong&gt; с ней можно делать — а Ash сам генерирует остальное: SQL-запросы, API, формы, миграции, валидацию и т.д.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Полный пример современного Resource
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:course_hub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;# Привязка к приложению&lt;/span&gt;
    &lt;span class="ss"&gt;domain:&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;# В каком домене живёт&lt;/span&gt;
    &lt;span class="ss"&gt;data_layer:&lt;/span&gt; &lt;span class="no"&gt;AshPostgres&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataLayer&lt;/span&gt;  &lt;span class="c1"&gt;# Где храним данные&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ХРАНЕНИЕ ====================&lt;/span&gt;
  &lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="s2"&gt;"lessons"&lt;/span&gt;
    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ПОЛЯ (Attributes) ====================&lt;/span&gt;
  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;uuid_primary_key&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;               &lt;span class="c1"&gt;# видно в API и формах&lt;/span&gt;
      &lt;span class="n"&gt;allow_nil?&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="ss"&gt;min_length:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_length:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;public?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;public?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:atom&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;default?&lt;/span&gt; &lt;span class="ss"&gt;:draft&lt;/span&gt;
      &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="ss"&gt;one_of:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:archived&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;create_timestamp&lt;/span&gt; &lt;span class="ss"&gt;:inserted_at&lt;/span&gt;
    &lt;span class="n"&gt;update_timestamp&lt;/span&gt; &lt;span class="ss"&gt;:updated_at&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== СВЯЗИ (Relationships) ====================&lt;/span&gt;
  &lt;span class="n"&gt;relationships&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Accounts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;allow_nil?&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Comment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;many_to_many&lt;/span&gt; &lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tag&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;public?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;LessonTag&lt;/span&gt;
      &lt;span class="n"&gt;source_attribute_on_join_resource&lt;/span&gt; &lt;span class="ss"&gt;:lesson_id&lt;/span&gt;
      &lt;span class="n"&gt;destination_attribute_on_join_resource&lt;/span&gt; &lt;span class="ss"&gt;:tag_id&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ДЕЙСТВИЯ (Actions) ====================&lt;/span&gt;
  &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Кастомное чтение&lt;/span&gt;
    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;pagination&lt;/span&gt; &lt;span class="ss"&gt;offset?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;countable:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Кастомное создание с логикой&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# Полностью кастомное действие&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:calculate_reading_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ВЫЧИСЛЯЕМЫЕ ПОЛЯ ====================&lt;/span&gt;
  &lt;span class="n"&gt;calculations&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculate&lt;/span&gt; &lt;span class="ss"&gt;:reading_time_minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;calculation&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&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="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Float&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== ИНДЕКСЫ ====================&lt;/span&gt;
  &lt;span class="n"&gt;identities&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="ss"&gt;:unique_title_per_author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:author_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ==================== АВТОРИЗАЦИЯ ====================&lt;/span&gt;
  &lt;span class="n"&gt;policies&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="n"&gt;action_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;authorize_if&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;authorize_if&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Основные разделы Resource
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Раздел&lt;/th&gt;
&lt;th&gt;Что описывает&lt;/th&gt;
&lt;th&gt;Аналог в обычном Elixir/Phoenix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;attributes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Поля и их типы + валидация&lt;/td&gt;
&lt;td&gt;Ecto Schema + поля&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;relationships&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Связи с другими ресурсами&lt;/td&gt;
&lt;td&gt;Ecto associations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;actions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Все возможные операции (CRUD + кастомные)&lt;/td&gt;
&lt;td&gt;Context-функции + Changesets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calculations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Вычисляемые поля (на лету)&lt;/td&gt;
&lt;td&gt;Virtual fields / функции&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aggregates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Агрегаты (count, sum, avg и т.д.)&lt;/td&gt;
&lt;td&gt;Запросы с group_by&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;identities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Уникальные индексы&lt;/td&gt;
&lt;td&gt;Ecto unique constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;policies&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;code&gt;postgres&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Настройки хранения в PostgreSQL&lt;/td&gt;
&lt;td&gt;Миграции&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Ключевые особенности Resource
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Всё в одном файле&lt;/strong&gt; — огромный плюс для понимания сущности.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introspection&lt;/strong&gt; — Ash может в runtime читать всю информацию о ресурсе (поля, действия, политики). Это используется для генерации API, форм, админок.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Декларативность&lt;/strong&gt; — ты описываешь &lt;strong&gt;что&lt;/strong&gt; должно быть, а не &lt;strong&gt;как&lt;/strong&gt; это реализовать.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Расширяемость&lt;/strong&gt; — можно добавлять свои &lt;code&gt;changes&lt;/code&gt;, &lt;code&gt;preparations&lt;/code&gt;, &lt;code&gt;validations&lt;/code&gt;, &lt;code&gt;notifiers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded Resources&lt;/strong&gt; — можно создавать ресурсы, которые хранятся не в отдельной таблице, а как JSON/Map внутри другого ресурса.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  Когда создавать новый Resource?
&lt;/h3&gt;

&lt;p&gt;Практически всегда, когда появляется новая бизнес-сущность (таблица или даже сложный JSON-объект).&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🛠️ Подробнее об Actions (Действиях)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Action (Действие)&lt;/strong&gt; — это &lt;strong&gt;явно объявленная операция&lt;/strong&gt;, которую можно выполнить над ресурсом.  &lt;/p&gt;

&lt;p&gt;Всё взаимодействие с данными в Ash идёт &lt;strong&gt;только через Actions&lt;/strong&gt;. Нельзя просто взять запись и изменить её вручную — всегда вызываешь действие.&lt;/p&gt;

&lt;p&gt;Это заменяет:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Обычные функции в Context’ах Phoenix&lt;/li&gt;
&lt;li&gt;Changesets в Ecto&lt;/li&gt;
&lt;li&gt;Контроллеры и сервисные слои&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Пять типов Actions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Тип действия&lt;/th&gt;
&lt;th&gt;Что делает?&lt;/th&gt;
&lt;th&gt;В транзакции?&lt;/th&gt;
&lt;th&gt;Что возвращает?&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;strong&gt;&lt;code&gt;create&lt;/code&gt;&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔍&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;read&lt;/code&gt;&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✏️&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;update&lt;/code&gt;&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🗑️&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;destroy&lt;/code&gt;&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;action&lt;/code&gt;&lt;/strong&gt; (Generic)&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;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Полный пример всех типов Actions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Стандартные CRUD (defaults)&lt;/span&gt;
    &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Кастомное Read&lt;/span&gt;
    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;pagination&lt;/span&gt; &lt;span class="ss"&gt;offset?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;countable:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default_limit:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
      &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;load:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:comment_count&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:for_user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Кастомное Create&lt;/span&gt;
    &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

      &lt;span class="c1"&gt;# Изменения (changes)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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;change&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;NotifySubscribers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic:&lt;/span&gt; &lt;span class="s2"&gt;"new_lessons"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;# Хуки&lt;/span&gt;
      &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;_changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;# side-effect после успешного создания&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Кастомное Update&lt;/span&gt;
    &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:archive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:archive_reason&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                    &lt;span class="c1"&gt;# какие поля можно менять&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:archived&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:archived_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Generic Action (полностью кастомное)&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:calculate_reading_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
      &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:words_per_minute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default?:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

      &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;words_per_minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Как вызывать Actions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Через домен (рекомендуемый способ)&lt;/span&gt;
&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;reason:&lt;/span&gt; &lt;span class="s2"&gt;"Готово"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Или с Ash.Query / Ash.Changeset для сложных случаев&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;for_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Основные возможности Actions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;code&gt;argument&lt;/code&gt; — входные параметры
&lt;/h4&gt;

&lt;p&gt;Позволяет передавать данные в действие и валидировать их.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;constraints:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;min_length:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default?:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_nil?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. &lt;code&gt;accept&lt;/code&gt; — какие атрибуты можно менять
&lt;/h4&gt;

&lt;p&gt;Ограничивает список полей, которые разрешено изменять при &lt;code&gt;create&lt;/code&gt; или &lt;code&gt;update&lt;/code&gt;. Очень полезно для безопасности.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:register&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;# только эти поля можно передать&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:update_profile&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar_url&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;code&gt;change&lt;/code&gt; — трансформации данных
&lt;/h4&gt;

&lt;p&gt;Самая мощная и часто используемая часть Actions. Здесь происходит основная бизнес-логика.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;

  &lt;span class="c1"&gt;# Встроенные изменения&lt;/span&gt;
  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&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="c1"&gt;# Кастомный change-модуль&lt;/span&gt;
  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;NotifySubscribers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic:&lt;/span&gt; &lt;span class="s2"&gt;"lessons"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# Анонимная функция&lt;/span&gt;
  &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;code&gt;prepare&lt;/code&gt; — подготовка запроса (в основном для &lt;code&gt;read&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Позволяет заранее настроить запрос: сортировку, предзагрузку связей, дополнительные фильтры и т.д.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;prepare&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="ss"&gt;sort:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;inserted_at:&lt;/span&gt; &lt;span class="ss"&gt;:desc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;load:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:reading_time_minutes&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;limit:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Хуки (before/after)
&lt;/h4&gt;

&lt;p&gt;Позволяют выполнить код до или после выполнения действия.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:publish&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# проверка перед выполнением&lt;/span&gt;
    &lt;span class="n"&gt;validate_business_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;_changeset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# side-effect после успешного создания&lt;/span&gt;
    &lt;span class="no"&gt;LessonNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after_transaction&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;broadcast_new_lesson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. &lt;code&gt;transaction?&lt;/code&gt; — управление транзакцией
&lt;/h4&gt;

&lt;p&gt;Определяет, нужно ли оборачивать действие в базу данных транзакцию.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ss"&gt;:transfer_money&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boolean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:from_account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:to_account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;
  &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="ss"&gt;:amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:decimal&lt;/span&gt;

  &lt;span class="n"&gt;transaction?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;   &lt;span class="c1"&gt;# будет выполнено в одной транзакции&lt;/span&gt;

  &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# сложная операция с несколькими записями&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  7. &lt;code&gt;pipe_through&lt;/code&gt; — переиспользование логики
&lt;/h4&gt;

&lt;p&gt;Позволяет создавать общие пайплайны и подключать их к разным действиям (очень полезно для DRY).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# В Resource&lt;/span&gt;
&lt;span class="n"&gt;pipelines&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;ensure_actor_role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="n"&gt;actor_role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:create_admin_content&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ss"&gt;:update_admin_content&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:ensure_admin&lt;/span&gt;
  &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Почему Actions — это круто?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Полная типизация&lt;/strong&gt; и &lt;strong&gt;introspection&lt;/strong&gt; — Ash знает всё о действии в runtime (используется для GraphQL, форм, админок)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Декларативность&lt;/strong&gt; — код читается как документация бизнеса&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Повторное использование&lt;/strong&gt; — одно действие можно использовать в LiveView, API, Background Job, Tests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Безопасность&lt;/strong&gt; — политики авторизации привязываются к конкретным действиям&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Тестируемость&lt;/strong&gt; — легко тестировать отдельные действия&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Сравнение с классическим Elixir/Phoenix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Подход&lt;/th&gt;
&lt;th&gt;Где логика?&lt;/th&gt;
&lt;th&gt;Кол-во файлов&lt;/th&gt;
&lt;th&gt;Понятность&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ecto + Context&lt;/td&gt;
&lt;td&gt;Context + Changeset&lt;/td&gt;
&lt;td&gt;4–8&lt;/td&gt;
&lt;td&gt;Средняя&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ash Actions&lt;/td&gt;
&lt;td&gt;В одном Resource&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Высокая&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Actions — это то место, где живёт вся бизнес-логика&lt;/strong&gt; твоего ресурса&lt;/p&gt;
&lt;/blockquote&gt;

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




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

&lt;h2&gt;
  
  
  🏢 Что такое Domain (Домены)?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Domain (Домен)&lt;/strong&gt; — это &lt;strong&gt;логический контейнер&lt;/strong&gt;, который объединяет группу связанных &lt;strong&gt;Resources&lt;/strong&gt; (ресурсов).  &lt;/p&gt;

&lt;p&gt;Он похож на &lt;strong&gt;Phoenix Context&lt;/strong&gt;, но гораздо мощнее. Если Resource — это описание одной сущности (как &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Lesson&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt;), то Domain — это «модуль» или «bounded context» (в терминах DDD), который собирает вместе несколько сущностей одной бизнес-области.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Пример&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Accounts&lt;/code&gt; — домен для пользователей, профилей, авторизации&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Courses&lt;/code&gt; — домен для курсов, уроков, тестов, enrollments&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Billing&lt;/code&gt; — домен для платежей, подписок, инвойсов&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Therapy&lt;/code&gt; — домен для терапии, разговоров, сообщений (из реальных примеров)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Три главные цели Domain
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Группировка ресурсов&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Организация проекта. Вместо того чтобы все ресурсы были разбросаны, они явно лежат в логических группах.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Централизованный Code Interface&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Domain позволяет определять удобные функции-обёртки для вызова действий ресурсов.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Общие настройки и cross-cutting concerns&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Здесь можно задать поведение, которое применяется ко всем ресурсам домена (таймауты, пагинация по умолчанию, авторизация и т.д.).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  Как выглядит Domain на практике
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:course_hub&lt;/span&gt;

  &lt;span class="c1"&gt;# 1. Группировка ресурсов&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Course&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Lesson&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Quiz&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enrollment&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 2. Code Interface — удобные функции&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:get_lesson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;args:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;get?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:list_published_courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;
  &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:enroll_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;resource:&lt;/span&gt; &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enrollment&lt;/span&gt;

  &lt;span class="c1"&gt;# 3. Общие настройки&lt;/span&gt;
  &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c1"&gt;# глобальный таймаут&lt;/span&gt;
    &lt;span class="n"&gt;default_page_size&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Включение AshAdmin (админка)&lt;/span&gt;
  &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;show?&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Зачем нужен Domain?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Организация и границы.&lt;/strong&gt; Чётко разделяет разные части приложения (как bounded contexts в DDD). &lt;code&gt;Accounts&lt;/code&gt; не знает про &lt;code&gt;Billing&lt;/code&gt; без явного отношения&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Удобный публичный API.&lt;/strong&gt; Вместо &lt;code&gt;Ash.read!(CourseHub.Courses.Lesson, ...)&lt;/code&gt; ты пишешь красиво:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_lesson!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lesson_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;CourseHub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Courses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_published_courses!&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;&lt;p&gt;&lt;strong&gt;Централизованное управление.&lt;/strong&gt; Можно отключить авторизацию для всего домена в dev-режиме, задать общие политики, notifiers и т.д.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Introspection и расширения.&lt;/strong&gt; Многие расширения Ash (GraphQL, JsonApi, Phoenix и т.д.) работают на уровне домена&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Тестирование и изоляция.&lt;/strong&gt; Легче тестировать одну бизнес-область целиком&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Лучшие практики при работе с доменом
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Один ресурс — один домен.&lt;/strong&gt; Ресурс не может принадлежать нескольким доменам одновременно.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Сколько доменов делать?&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Маленький проект → 1–3 домена.
&lt;/li&gt;
&lt;li&gt;Средний/большой → по одному на крупную бизнес-область (Accounts, Core, Billing, Notifications и т.д.).
Это помогает в масштабировании и понимании архитектуры.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Interface&lt;/strong&gt; — очень мощная фича. Ты можешь определять не только простые обёртки, но и с предустановленными фильтрами, load'ами и т.д.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Сравнение: Domain vs Resource
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Аспект&lt;/th&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Domain&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;/tr&gt;
&lt;tr&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Аналог в Phoenix&lt;/td&gt;
&lt;td&gt;Schema + Context (частично)&lt;/td&gt;
&lt;td&gt;Phoenix Context&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;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Почему Domain особенно полезен?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Проект растёт &amp;gt; 10–15 ресурсов&lt;/li&gt;
&lt;li&gt;Нужна сложная авторизация (policies)&lt;/li&gt;
&lt;li&gt;Делаешь GraphQL / JSON:API / Admin-панель&lt;/li&gt;
&lt;li&gt;Командная разработка — всем нужно понимать границы&lt;/li&gt;
&lt;/ul&gt;

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




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

&lt;h3&gt;
  
  
  ⚔️ Ash + Phoenix vs Ecto + Phoenix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Аспект&lt;/th&gt;
&lt;th&gt;Phoenix + Ecto (классика) 😐&lt;/th&gt;
&lt;th&gt;Phoenix + Ash 🔥&lt;/th&gt;
&lt;th&gt;Кто выигрывает?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Организация бизнес-логики&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Разбросана по Context, Changeset, отдельным модулям&lt;/td&gt;
&lt;td&gt;Всё в &lt;strong&gt;одном Resource&lt;/strong&gt; — атрибуты, действия, политики, связи&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ash&lt;/strong&gt; (всё на виду)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CRUD-операции&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Пишешь вручную: create, read, update, delete + boilerplate&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;defaults [:create, :read, :update, :destroy]&lt;/code&gt; — и готово ✨&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ash&lt;/strong&gt; (1 строка)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Авторизация&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ручные проверки / Bodyguard / scopes&lt;/td&gt;
&lt;td&gt;Декларативные &lt;strong&gt;Policies&lt;/strong&gt; (secure by default) ⚡&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ash&lt;/strong&gt; (автоматика)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Вычисляемые поля&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Virtual fields + функции в Context&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Calculations&lt;/strong&gt; — автоматически подгружаются и кэшируются&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Количество файлов на сущность&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3–6+ файлов (Schema + Context + Changeset + Policy)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1 файл&lt;/strong&gt; — Resource&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Генерация API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Absinthe / GraphQL вручную + много кода&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AshGraphql&lt;/code&gt; или &lt;code&gt;AshJsonApi&lt;/code&gt; — добавил расширение и готово&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LiveView формы&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Phoenix.Component + ручная валидация&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;AshPhoenix.Form&lt;/strong&gt; — формы сами знают всё&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-tenancy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Пишешь сам (или используешь схемы)&lt;/td&gt;
&lt;td&gt;Встроено в Policies (attribute-based или context-based)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Поддерживаемость через 2–3 года&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Средняя (логика расползается)&lt;/td&gt;
&lt;td&gt;Высокая (всё декларативно и в одном месте)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ash&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Скорость разработки&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Нормальная на старте&lt;/td&gt;
&lt;td&gt;Значительно быстрее после кривой обучения 🚀&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ash&lt;/strong&gt; (после обучения)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Гибкость&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Максимальная (полный контроль)&lt;/td&gt;
&lt;td&gt;Очень высокая + можно escape в чистый Ecto когда нужно&lt;/td&gt;
&lt;td&gt;Ничья&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Кривая обучения&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Легче для новичков&lt;/td&gt;
&lt;td&gt;Круче, но окупается в большом проекте&lt;/td&gt;
&lt;td&gt;Ecto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Что стоит выбрать в 2026 году?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Плюсы Ash&lt;/strong&gt; 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Декларативность&lt;/strong&gt; → «Опиши домен — остальное Ash выведет сам»&lt;/li&gt;
&lt;li&gt;Сокращение шаблонного кода (часто встречаются отзывы о Ash вроде: «я создаю программы, используя в 3–5 раз меньше строк»)&lt;/li&gt;
&lt;li&gt;Автоматическая генерация GraphQL, JSON:API, Admin-панели, аутентификации&lt;/li&gt;
&lt;li&gt;Политики авторизации и multi-tenancy из коробки&lt;/li&gt;
&lt;li&gt;Отличная поддерживаемость на длинной дистанции (именно то, о чём мечтают в продакшене)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Плюсы классического Phoenix + Ecto&lt;/strong&gt; 😐&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Полный контроль над каждым байтом кода&lt;/li&gt;
&lt;li&gt;Проще для совсем маленьких проектов и пет-проектов&lt;/li&gt;
&lt;li&gt;Нет дополнительной абстракции (если ты любишь «голый» Elixir)&lt;/li&gt;
&lt;li&gt;Легче для новичков в Elixir&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Когда выбирать что?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Маленький пет-проект или эксперимент&lt;/strong&gt; → бери чистый Phoenix + Ecto&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Средний/крупный проект, SaaS, долгоживущее приложение&lt;/strong&gt; → Phoenix + Ash (экономия времени и нервов огромная)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Хочешь и то, и другое&lt;/strong&gt; → можно спокойно миксовать в одном проекте (Ash и обычный Ecto отлично уживаются)&lt;/li&gt;
&lt;/ul&gt;




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

&lt;h2&gt;
  
  
  😴 В заключение
&lt;/h2&gt;

&lt;p&gt;Ash — это не просто библиотека, а изменение подхода к разработке на Elixir. Он особенно хорошо заходит в проектах среднего и крупного размера, где важны чистота архитектуры, скорость разработки и долгосрочная поддерживаемость.&lt;/p&gt;

&lt;p&gt;Конечно, у него есть кривая обучения, и в совсем простых пет-проектах он может быть избыточен. Но если вы устали от расползающейся логики и хотите чёткой, декларативной структуры — Ash дарит очень приятное ощущение контроля над кодом.&lt;/p&gt;

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




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

&lt;h2&gt;
  
  
  🥴 От автора
&lt;/h2&gt;

&lt;p&gt;Спасибо большое за интерес к этой статье! Надеюсь, она помогла разобраться, что представляет собой Ash и зачем он используется.&lt;/p&gt;

&lt;p&gt;Если эта статья пришлась вам по душе и хочется ещё материалов такого плана, присоединяйтесь ко мне в моём &lt;a href="https://t.me/devs_inc" rel="noopener noreferrer"&gt;телеграм-канале&lt;/a&gt;, где выкладываю обзоры книг, публикации по Elixir, переводы технической литературы и интересные новости!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ash</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Thu, 19 Mar 2026 17:05:36 +0000</pubDate>
      <link>https://forem.com/adamanq/-igb</link>
      <guid>https://forem.com/adamanq/-igb</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7" class="crayons-story__hidden-navigation-link"&gt;AD9833 DDS Generator Board&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ua3mqj" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3831248%2F7b0c6671-cae6-45c2-97a8-0fa75341b7a2.jpg" alt="ua3mqj profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ua3mqj" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Alexey Bolshakov
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Alexey Bolshakov
                
              
              &lt;div id="story-author-preview-content-3372554" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ua3mqj" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3831248%2F7b0c6671-cae6-45c2-97a8-0fa75341b7a2.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Alexey Bolshakov&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 19&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7" id="article-link-3372554"&gt;
          AD9833 DDS Generator Board
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dds"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dds&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/microchips"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;microchips&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/stm8"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;stm8&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/microcontroller"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;microcontroller&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>dds</category>
      <category>microchips</category>
      <category>stm8</category>
      <category>microcontroller</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Sun, 15 Mar 2026 13:11:26 +0000</pubDate>
      <link>https://forem.com/adamanq/-ogk</link>
      <guid>https://forem.com/adamanq/-ogk</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/sag1v/the-internet-is-getting-quieter-who-will-feed-the-next-generation-of-ai-4bl1" class="crayons-story__hidden-navigation-link"&gt;The Internet Is Getting Quieter - Who Will Feed the Next Generation of AI?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/sag1v" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F139634%2F0331a21e-6a3d-421a-bc25-2fbd6c1b6dea.jpg" alt="sag1v profile" class="crayons-avatar__image" width="800" height="540"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/sag1v" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sagiv ben giat
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sagiv ben giat
                
              
              &lt;div id="story-author-preview-content-3345524" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/sag1v" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F139634%2F0331a21e-6a3d-421a-bc25-2fbd6c1b6dea.jpg" class="crayons-avatar__image" alt="" width="800" height="540"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sagiv ben giat&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/sag1v/the-internet-is-getting-quieter-who-will-feed-the-next-generation-of-ai-4bl1" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 12&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/sag1v/the-internet-is-getting-quieter-who-will-feed-the-next-generation-of-ai-4bl1" id="article-link-3345524"&gt;
          The Internet Is Getting Quieter - Who Will Feed the Next Generation of AI?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/knowledgesharing"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;knowledgesharing&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/stackoverflow"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;stackoverflow&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opinion"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opinion&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/sag1v/the-internet-is-getting-quieter-who-will-feed-the-next-generation-of-ai-4bl1" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;64&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/sag1v/the-internet-is-getting-quieter-who-will-feed-the-next-generation-of-ai-4bl1#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              30&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>knowledgesharing</category>
      <category>stackoverflow</category>
      <category>opinion</category>
    </item>
    <item>
      <title>BEAM: In Plain English</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Thu, 25 Sep 2025 07:00:03 +0000</pubDate>
      <link>https://forem.com/adamanq/beam-in-plain-english-2n1o</link>
      <guid>https://forem.com/adamanq/beam-in-plain-english-2n1o</guid>
      <description>&lt;p&gt;Imagine a universe where billions of messages, calls, and financial transactions happen every second. Each message reaches its recipient flawlessly, phone calls remain uninterrupted, and funds are transferred instantly. What ensures such impeccable performance? No, it's not magic—it's virtual machines—the unsung heroes of digital infrastructure.&lt;/p&gt;

&lt;p&gt;Among them stands out one remarkable machine — &lt;strong&gt;BEAM&lt;/strong&gt;. Created decades ago, it looks like an invention from a distant future. It powers stable operations for giants like WhatsApp, Discord, financial services, and IoT systems. Even after all these years since its inception, BEAM continues to impress with its performance and reliability.&lt;/p&gt;

&lt;p&gt;This article is not intended as an in-depth exploration into the inner workings of BEAM or its implementation details. We won't delve into byte code flow or provide specific internal code snippets here. Instead, this piece aims to give you a general understanding of what BEAM does, why it's important, and how it can benefit your business under heavy loads. For those who want to dive deeper into BEAM’s internals, I recommend reading the book — &lt;em&gt;&lt;a href="https://blog.stenmans.org/theBeamBook/#CH-BEAM" rel="noopener noreferrer"&gt;The BEAM Book: Understanding the Erlang Runtime System&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In today's era characterized by rapid development of real-time technologies, artificial intelligence, and mass parallel user connections, BEAM excels at providing high response speed, reliability even during failures, and quick adaptation to increasing load, making it an optimal solution for complex challenges. But let's start with the basics!&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Virtual Machine? 🤔
&lt;/h2&gt;

&lt;p&gt;Imagine writing a program that needs to run everywhere—on laptops, smartphones, servers, smart speakers, etc. How do you ensure compatibility across different operating systems and hardware configurations? The answer lies in using a virtual machine (VM). It's a special execution environment that interprets your code, acting as a bridge between your application and the underlying device. The VM takes intermediate code (like Java bytecode) and translates it into instructions suitable for each platform, freeing you from worrying about memory management or multithreading intricacies. In essence, a virtual machine serves as a universal adapter enabling your code to run anywhere!&lt;/p&gt;

&lt;p&gt;Additionally, many virtual machines come equipped with useful tools such as automatic garbage collection, built-in performance optimizations, and data protection mechanisms. These features make app development significantly easier and more efficient. Without VMs, creating modern projects ranging from mobile games to large-scale cloud services would be much harder.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Are Virtual Machines Needed? 🌟
&lt;/h2&gt;

&lt;p&gt;Virtual machines aren't just developer conveniences but powerful tools for building versatile, reliable, and scalable solutions. Let's explore their key advantages through practical examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-platform Compatibility&lt;/strong&gt; 📱💻&lt;br&gt;&lt;br&gt;
Write once, run anywhere. An example is a banking app written in Java running seamlessly both on bank servers and client Android phones thanks to JVM. This saves time and resources, especially valuable in enterprise-level development involving diverse platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Management&lt;/strong&gt; 🧹&lt;br&gt;&lt;br&gt;
Virtual machines handle resource allocation, including memory control (via garbage collection), threading, and hardware interaction. For instance, in the Erlang VM (BEAM), each process gets isolated memory areas, preventing issues caused by individual process crashes. Such architecture minimizes bugs and simplifies coding tasks, relieving developers from manually managing memory allocation and deallocation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt; 🔒&lt;br&gt;&lt;br&gt;
By isolating executable code from the OS, virtual machines create secure sandboxes protecting against potential threats posed by harmful programs. This feature is crucial in environments like AWS Lambda or Google Cloud Functions, where thousands of code fragments from various users execute simultaneously on shared hardware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimization&lt;/strong&gt; ⚡&lt;br&gt;&lt;br&gt;
Many VMs dynamically optimize code execution while applications are running. One prominent example is Just-In-Time compilation (JIT), which makes browser engines like V8 incredibly fast. Starting with version OTP 24, BEAM introduced its own JIT mechanism, further enhancing performance. These techniques prove invaluable when dealing with repetitive computations common in highly loaded web apps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support for Complex Systems&lt;/strong&gt; 🌐&lt;br&gt;&lt;br&gt;
Some VMs are specifically designed to support concurrency, distributed computing, and fault tolerance. For example, popular game server infrastructures, like those powering &lt;a href="https://highscalability.com/how-league-of-legends-scaled-chat-to-70-million-players-it-t/" rel="noopener noreferrer"&gt;&lt;em&gt;League of Legends&lt;/em&gt;&lt;/a&gt;, rely heavily on BEAM, efficiently handling millions of concurrent player connections with minimal latency and high reliability.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, virtual machines allow developers to focus directly on product functionality rather than low-level technicalities, accelerating development processes and reducing costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Popular Virtual Machines: Who's Who? 🦸‍♂️
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JVM (Java Virtual Machine):&lt;/strong&gt; Used for Java, Kotlin, Scala. Ideal for large business systems (banking solutions), web servers (Spring Framework), and Android platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Extensive ecosystem (huge library availability), Just-In-Time compilation technology.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; High initial RAM usage, comparatively slow startup times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fact:&lt;/strong&gt; Adopted by nearly 90% of Fortune 500 companies worldwide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;V8 (JavaScript Engine):&lt;/strong&gt; Powering Node.js and modern browsers. Optimized for web environments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Exceptional performance for client-side websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Con:&lt;/strong&gt; Not well suited for long-term server-based solutions, where BEAM shines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CLR (.NET Common Language Runtime):&lt;/strong&gt; Supports languages within the .NET family, notably C#. Strongly integrated with Microsoft technologies (Azure).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Seamless integration with Windows platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Con:&lt;/strong&gt; Limited cross-platform capabilities compared to JVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;BEAM (Erlang VM):&lt;/strong&gt; Designed for Erlang, Elixir, and other compatible languages (LFE, Alpaca). Best suited for highly scalable, resilient, and concurrent systems, excelling in messaging, telecommunications, and fintech.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Capable of handling millions of simultaneous processes with minimal delays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Con:&lt;/strong&gt; Smaller toolkit and framework libraries, though actively growing (Phoenix, Nerves frameworks).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comparison Table:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VM&lt;/th&gt;
&lt;th&gt;Strengths&lt;/th&gt;
&lt;th&gt;Weaknesses&lt;/th&gt;
&lt;th&gt;Use Cases&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JVM&lt;/td&gt;
&lt;td&gt;Versatility, extensive ecosystem&lt;/td&gt;
&lt;td&gt;Memory consumption, startup lag&lt;/td&gt;
&lt;td&gt;Enterprise, Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;V8&lt;/td&gt;
&lt;td&gt;Speed for web clients&lt;/td&gt;
&lt;td&gt;Unsuitable for backend servers&lt;/td&gt;
&lt;td&gt;Node.js, Browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLR&lt;/td&gt;
&lt;td&gt;Integration with Microsoft tech&lt;/td&gt;
&lt;td&gt;Dependence on MS ecosystem&lt;/td&gt;
&lt;td&gt;.NET, Azure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BEAM&lt;/td&gt;
&lt;td&gt;Concurrency, resilience&lt;/td&gt;
&lt;td&gt;Fewer libraries &amp;amp; frameworks&lt;/td&gt;
&lt;td&gt;Real-time, Telecom&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By 2025, with the rise of IoT and streaming data, BEAM has become particularly relevant for real-time applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deeper Look Into BEAM 🌌
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;BEAM&lt;/strong&gt; is a virtual machine engineered for programming languages like &lt;strong&gt;Erlang&lt;/strong&gt;, &lt;strong&gt;Elixir&lt;/strong&gt;, and others (such as LFE). Initially developed in the 1990s by Ericsson for telecommunication purposes, where reliability and capacity to manage massive traffic were critical, today BEAM forms the backbone of numerous high-performance services. It handles billions of daily messages (as seen in WhatsApp), supports millions of online gamers simultaneously (products like League of Legends), and keeps real-time chat services (Discord) functioning smoothly. As the need for high throughput, low latency, and robustness grows, BEAM proves indispensable in 2025 more than ever before.&lt;/p&gt;

&lt;h3&gt;
  
  
  History of BEAM: From Telco to Global Platforms 📜
&lt;/h3&gt;

&lt;p&gt;Originally, BEAM stood for "&lt;em&gt;Bogdan's Erlang Abstract Machine&lt;/em&gt;" named after Bogumil Hausman ("Bogdan"), who created its first iteration. However, over time, it became associated with another author—"&lt;em&gt;Björn's Erlang Abstract Machine&lt;/em&gt;", reflecting contributions made by Björn Gustavsson, who maintains the current implementation. Both contributors played significant roles in shaping the system while working at Ericsson.&lt;/p&gt;

&lt;p&gt;Before BEAM emerged, there was another virtual machine called JAM (&lt;em&gt;Joe's Abstract Machine&lt;/em&gt;)—the first interpreter for the Erlang language. Developed by Joe Armstrong alongside Mike Williams in C, detailed insights are found in the &lt;a href="https://www.erlang.org/blog/beam-compiler-history/" rel="noopener noreferrer"&gt;developers' blog&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Therefore Bogumil (“Bogdan”) Hausman created TEAM (Turbo Erlang Abstract Machine). It compiled the Erlang code to C code, which was then compiled to native code using GCC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, BEAM finds widespread use in finance (Klarna), advertising (AdRoll), notification systems (Pinterest), and Internet of Things (IoT) deployments (Nerves). With advancements such as Just-In-Time compiler introduction in OTP 24 and type improvement enhancements in Elixir v1.15+, BEAM remains a viable choice. Future plans include closer alignment with WebAssembly for supporting web applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's So Great About BEAM? 🚀
&lt;/h2&gt;

&lt;p&gt;BEAM distinguishes itself among other virtual machines due to unique characteristics essential for scalable and demanding applications. Below are its main advantages, supported by concrete figures and comparisons with similar solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fast and Lightweight Processes&lt;/strong&gt; ⚡&lt;br&gt;&lt;br&gt;
Process creation in BEAM takes only microseconds, consuming approximately 2.5 KB per process, allowing millions of instances to coexist on a single machine. Compared to Java threads requiring megabytes of memory, BEAM offers superior efficiency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 While asynchronous tasks in Rust are lightweight too, BEAM surpasses in building distributed solutions due to its actor model, isolated processes with negligible overhead, auto-failure recovery via supervisors, and hot code swapping without downtime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Actor Model&lt;/strong&gt; 🎭&lt;br&gt;&lt;br&gt;
Processes behave independently, exchanging messages without sharing resources or causing blocking. Unlike Java threads, this greatly simplifies concurrent processing. Imagine a chat messenger like Discord where each room acts as an independent process freely accepting new messages regardless of other activities. Performance is impressive: BEAM can process roughly 100k messages per second on a single core.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Let It Crash Philosophy&lt;/strong&gt; 💥&lt;br&gt;&lt;br&gt;
BEAM embraces the principle of “let it crash”: if a process fails, it simply stops executing. Yet, thanks to careful design, failure goes largely unnoticed by end-users. Consider managing a busy restaurant where someone suddenly leaves mid-shift. Typically, chaos ensues, disrupting service. In BEAM, however, there's a supervisor-like manager immediately spawning a replacement process. Customers continue receiving orders promptly, unaware of any interruption.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☎️ This philosophy proved effective back in the '90s when Ericsson used BEAM to maintain large telecommunication stations. If a component crashed, the overall system remained operational without disruption.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hot Code Reloading&lt;/strong&gt; 🔄&lt;br&gt;&lt;br&gt;
Applications can update themselves without halting ongoing operations. BEAM holds two versions of software modules simultaneously, switching almost instantaneously. In contrast, Java transitions require additional effort and may cause temporary delays. Successful implementations include payment gateway Klarna, updating continuously without a single second of downtime, ensuring continuous shopping experiences for customers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Systems&lt;/strong&gt; 🌐&lt;br&gt;&lt;br&gt;
Individual nodes connect into unified clusters through network links. This setup enhances fault tolerance and horizontal scaling. Take Pinterest notifications: thousands of new servers easily join existing clusters, boosting total output without compromising individual node performance. Scalability extends to tens of thousands of nodes with minimal request latencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Low Latency&lt;/strong&gt; ⏱&lt;br&gt;&lt;br&gt;
Incremental garbage collection minimizes delays. The Phoenix framework, built atop BEAM, handles thousands of requests with millisecond-level responses. Other languages like Python occasionally experience longer pauses due to their garbage collection models, whereas BEAM consistently performs under heavy loads with low latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Just-In-Time Compilation&lt;/strong&gt; 🚀&lt;br&gt;&lt;br&gt;
Starting with OTP 24, BEAM introduces Just-In-Time compilation, improving computational-intensive task speeds by up to 20–30%. Although BEAM primarily focuses on concurrency, this optimization dramatically increases execution speed for computation-heavy tasks. Parsing JSON files now happens faster thanks to enhanced compiler optimizations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Inside BEAM: How Does It Work? 🛠
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Scheduler: Maestro of Multitasking 🎻
&lt;/h3&gt;

&lt;p&gt;The scheduler in BEAM operates like a conductor leading an orchestra. Thousands of musicians (processes) play together, each needing their turn to perform. Nobody plays for too long—otherwise, music turns chaotic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Real-world Example:&lt;/strong&gt; A single WhatsApp server handled millions of active connections simultaneously. Implementing this feat using conventional OS threads would have been impossible, yet BEAM manages it gracefully with its unique scheduling scheme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is one scheduler per CPU core. On an eight-core server, eight schedulers operate.&lt;/li&gt;
&lt;li&gt;Every process receives a fixed number of steps ("reductions") before yielding control to another process.&lt;/li&gt;
&lt;li&gt;Processes fall into two queues: ready-for-execution and waiting-for-resources.&lt;/li&gt;
&lt;li&gt;Load balancing employs task stealing mechanics to redistribute workload evenly.&lt;/li&gt;
&lt;li&gt;Time-wheel structure stores active timers for efficient timing operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Common Issue:&lt;/strong&gt; Long-running Built-In Functions (BIFs) executed without yielding control can block scheduler activity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Garbage Collection: Keeping Memory Clean 🧹
&lt;/h3&gt;

&lt;p&gt;The garbage collector (GC) in BEAM works similarly to a diligent janitor silently cleaning tables in a bustling city full of restaurants. Each process has its dedicated storage area ("heap"). When unused objects fill a heap, cleanup occurs locally, leaving other processes unaffected.&lt;/p&gt;

&lt;p&gt;BEAM implements generational garbage collection: newer elements ("young generation") frequently cleaned because they tend to die quickly, while older generations are checked less often.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Common Issue:&lt;/strong&gt; Accumulation of long-lived objects can lead to increased resource consumption. Monitor parameters like high_water carefully.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Large binary data (files, images) resides separately outside the GC zone, avoiding unnecessary bloat.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Real-world Example:&lt;/strong&gt; Discord manages millions of active channels on BEAM. Even if one particular chat accumulates transient data, the cleanup mechanism swiftly removes it without impacting other chats’ performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Algorithm Overview:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heap and stack expand towards each other until meeting, triggering cleanup.&lt;/li&gt;
&lt;li&gt;Two types of cycles exist: minor (frequent young-generation cleanups) and major (infrequent old-generation cleanups).&lt;/li&gt;
&lt;li&gt;Data copying technique moves values between two memory zones ("from space" → "to space").&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✨ Carefully monitor memory growth dynamics in your processes. Rapidly expanding sizes might indicate presence of long-living objects requiring architectural adjustments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Register-Based Architecture: Faster and More Efficient 🧠
&lt;/h3&gt;

&lt;p&gt;BEAM utilizes register-based architecture. Registers act as small, fast-access memory regions storing intermediate results of calculations. Each register holds specific values participating in computational operations. By keeping data close to the processor, registers enable swift access and high-performance operation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Simple addition (&lt;code&gt;add(A, B)&lt;/code&gt; resulting value stored in registers X0 and X1).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational Principles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registers X (up to 1024): Store function arguments.&lt;/li&gt;
&lt;li&gt;Registers Y: Local variables.&lt;/li&gt;
&lt;li&gt;Instructions like &lt;code&gt;move&lt;/code&gt; and &lt;code&gt;call&lt;/code&gt;, direct memory addressing allowed. JIT compilation substantially improves performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Common Issue:&lt;/strong&gt; Overflowing registers — pay attention to function size and optimization strategies.&lt;/p&gt;

&lt;p&gt;✨ &lt;strong&gt;Performance Tips:&lt;/strong&gt; Minimize stack usage, utilize registers effectively for intermediate result storage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Supervisors and Fault-Tolerance: Let It Crash! 💥
&lt;/h3&gt;

&lt;p&gt;In typical systems, a failing process means disaster. In BEAM, however, this event aligns with the development philosophy.&lt;/p&gt;

&lt;p&gt;Consider electrical networks: A vast grid where one substation breaks down. Normally, entire neighborhoods lose power. In BEAM, automated switches disconnect the faulty element and reconnect reserve units instantly, preserving normalcy throughout the city.&lt;/p&gt;

&lt;p&gt;Supervisors form hierarchical structures. When child processes crash, parent supervisors decide whether to restart affected components individually or collectively.&lt;/p&gt;

&lt;p&gt;Such architecture guarantees automatic restoration of system integrity.&lt;/p&gt;

&lt;p&gt;Mechanisms involved: tree-structured supervision, one-for-one strategy, state monitoring (running, garbage collection).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Common Issue:&lt;/strong&gt; Ignoring supervisor role, opting for custom solutions instead of proven OTP libraries.&lt;/p&gt;

&lt;p&gt;✨ Developer Advice: Design applications tolerant of errors, leave failure-handling logic to specialized supervisor mechanisms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Dynamic Code Loading and Distributed Systems 🌍
&lt;/h3&gt;

&lt;p&gt;BEAM allows live updates to running applications. Similar to a musician changing instruments mid-performance invisibly to listeners.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two module versions reside simultaneously:&lt;/strong&gt; Old handles ongoing requests, new accepts fresh ones. Updates occur transparently without stopping the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Replacement:&lt;/strong&gt; Achieved via command &lt;code&gt;:code.load_file(Module)&lt;/code&gt;. Follow proper update rules to avoid disruptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution:&lt;/strong&gt; Check remote node availability using &lt;code&gt;net_adm:ping(Node)&lt;/code&gt;, leverage Mnesia database. Clustering examples exist in Kubernetes environments utilizing BEAM-powered virtual machines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling:&lt;/strong&gt; Utilize OTP tools for cluster-wide node monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Scalability: BEAM Network Across Thousands of Nodes 🌐
&lt;/h3&gt;

&lt;p&gt;BEAM isn't merely a standalone node but a connected network behaving as a unified whole. Individual network members interact seamlessly, forming a coherent distributed infrastructure.&lt;/p&gt;

&lt;p&gt;Key benefits of this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy clusters spanning multiple servers, enabling transparent communication between processes.&lt;/li&gt;
&lt;li&gt;Particularly beneficial in IoT systems and microservices architectures, where message delivery automatically distributes across appropriate servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Real-world Case Study:&lt;/strong&gt; Pinterest applied this technology to deliver notifications. As traffic grew, adding extra servers scaled the system effortlessly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  BEAM in 2025: Why Should You Pay Attention? 🚀
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Handling Massive Traffic: WhatsApp manages millions of simultaneous connections.&lt;/li&gt;
&lt;li&gt;Scalable Microservices: Effortless deployment and management in Kubernetes.&lt;/li&gt;
&lt;li&gt;Real-time Operations: Phoenix provides lightning-fast chat communications.&lt;/li&gt;
&lt;li&gt;Reliability and Resilience: Proven in big players like Klarna.&lt;/li&gt;
&lt;li&gt;IoT and AI: Nerves for IoT devices, TensorFlow compatibility via port mechanisms.&lt;/li&gt;
&lt;li&gt;Future Development: Enhanced performance through JIT compilation, WebAssembly support for web apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Success Story:&lt;/strong&gt; Pinterest reduced notification delay by 50%, leveraging BEAM.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  BEAM — The Future That's Already Here! 🌌
&lt;/h2&gt;

&lt;p&gt;As we stand in 2025, Elixir and Erlang occupy niche positions among commonly used development tools, drawing little public attention. Personally, I believe this situation is unfair given the truly amazing and innovative possibilities offered by these technologies. Despite the learning curve and project complexity, the rewards promise to be substantial!&lt;/p&gt;

&lt;p&gt;Embrace the world of Elixir/Erlang, launch a new project, and experience the true power of the BEAM virtual machine! ✨&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Note from the Author
&lt;/h2&gt;

&lt;p&gt;Thank you very much for taking interest in this article! Hopefully, it helped clarify what BEAM is and why it's so widely adopted. Initially, I planned to write something more advanced and filled with technical details, but realized I'd struggle to top the comprehensive guide provided in the book &lt;a href="https://blog.stenmans.org/theBeamBook/#CH-BEAM" rel="noopener noreferrer"&gt;&lt;em&gt;The BEAM Book: Understanding the Erlang Runtime System&lt;/em&gt;&lt;/a&gt;. Thus, I've opted for a simpler explanation.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>beam</category>
      <category>erlang</category>
      <category>virtualmachine</category>
    </item>
    <item>
      <title>BEAM: Простыми словами</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Thu, 25 Sep 2025 06:58:34 +0000</pubDate>
      <link>https://forem.com/adamanq/beam-prostymi-slovami-3104</link>
      <guid>https://forem.com/adamanq/beam-prostymi-slovami-3104</guid>
      <description>&lt;p&gt;Представьте вселенную, где ежесекундно происходят миллиарды сообщений, звонков и финансовых операций. Каждое послание достигает адресата, звонки продолжаются бесперебойно, а средства поступают моментально. Что обеспечивает такую безупречную работу? Нет, это не волшебство, а именно &lt;strong&gt;виртуальные машины&lt;/strong&gt; — незаметные герои цифровой инфраструктуры.&lt;/p&gt;

&lt;p&gt;Среди них есть одна выдающаяся машина — &lt;strong&gt;BEAM&lt;/strong&gt;. Созданная еще в прошлом веке, она выглядит как разработка из далекого будущего. Именно она поддерживает стабильную работу таких гигантов, как WhatsApp, Discord, финансовые сервисы и IoT системы. Даже спустя десятилетия после своего появления, BEAM продолжает поражать своей производительностью и надежностью.&lt;/p&gt;

&lt;p&gt;Цель этой статьи вовсе не в подробном погружении в механизмы работы BEAM и внутренние детали реализации. Здесь мы не будем разбираться, куда уходят байты или приводить конкретные внутренние фрагменты кода. Эта статья предназначена лишь для общего понимания сути технологии, её назначения и возможностей, полезных для вас и вашего бизнеса в условиях больших нагрузок. Для тех, кто желает глубже изучить внутреннее устройство BEAM, рекомендую книгу — &lt;a href="https://blog.stenmans.org/theBeamBook/#CH-BEAM" rel="noopener noreferrer"&gt;The BEAM Book: Understanding the Erlang Runtime System&lt;/a&gt; на английском языке. (А вот русскоязычная версия вскоре появится в &lt;a href="//t.me/digital_tent"&gt;моём телеграм-канале&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Сегодня, когда эпоха характеризуется бурным развитием технологий реального времени, искусственного интеллекта и массового параллельного подключения пользователей, BEAM выделяется своей способностью обеспечивать высокую скорость отклика, надежность даже при отказах и быструю адаптацию к росту нагрузки, превращаясь в оптимальное решение для сложных задач. Но, начнём с основ!&lt;/p&gt;




&lt;h2&gt;
  
  
  Что такое виртуальная машина? 🤔
&lt;/h2&gt;

&lt;p&gt;Представь себе написание программы, которую ты хочешь запустить абсолютно на всём — будь то ноутбук, смартфон, сервер или даже умная колонка. Как добиться совместимости с разными операционными системами и железом? Решение простое — использовать виртуальную машину (ВМ). Она представляет собой специальную среду выполнения, которая интерпретирует твой код, действуя как мостик между твоим приложением и конкретным устройством. ВМ берет промежуточный код (например, байт-код Java) и преобразует его в инструкции, подходящие именно этой платформе, освобождая тебя от забот о деталях работы памяти или многопоточности. Проще говоря, виртуальная машина — это своего рода универсальный переходник, позволяющий твоему коду запускаться повсеместно!&lt;/p&gt;

&lt;p&gt;Кроме того, виртуальные машины часто имеют полезные инструменты, такие как автоматический сборщик мусора, встроенные оптимизации производительности и средства защиты данных. Благодаря этому разработка приложений становится значительно легче и эффективнее. Без ВМ создание современных проектов, начиная от мобильных игр и заканчивая крупными облачными сервисами, было бы намного сложнее.&lt;/p&gt;




&lt;h2&gt;
  
  
  Зачем нужны виртуальные машины? 🌟
&lt;/h2&gt;

&lt;p&gt;Виртуальные машины — это не просто комфорт разработчиков, а мощный инструмент для создания универсальных, надежных и легко расширяемых решений. Рассмотрим основные преимущества виртуальных машин на понятных примерах:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Кроссплатформенность&lt;/strong&gt; 📱💻&lt;br&gt;&lt;br&gt;
Написал код один раз — работает везде. Например, банковское приложение на Java запускается на сервере банка и на Android-смартфоне клиента благодаря JVM. Это экономит время и ресурсы, особенно в enterprise-разработке, где команды работают с разными платформами.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Управление ресурсами&lt;/strong&gt; 🧹&lt;br&gt;&lt;br&gt;
Виртуальная машина берет на себя контроль над оперативной памятью (например, посредством сборки мусора), многопоточностью и взаимодействием с техникой. Так, в VM Erlang (BEAM) каждому процессу выделяется отдельная область памяти, что позволяет избежать проблем с утечками даже при падении отдельных процессов. Такая архитектура снижает риск возникновения багов и существенно облегчает написание кода, поскольку разработчикам больше не приходится самостоятельно заботиться о выделении и освобождении памяти.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Безопасность&lt;/strong&gt; 🔒&lt;br&gt;&lt;br&gt;
За счет изоляции исполняемого кода от операционной системы, виртуальные машины создают своего рода песочницу, защищающую систему от потенциально опасных действий программы. Эта функция незаменима в облаках вроде AWS Lambda или Google Cloud Functions, где на одной машине одновременно выполняются тысячи фрагментов кода от разных пользователей.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Оптимизация&lt;/strong&gt; ⚡&lt;br&gt;&lt;br&gt;
Многие виртуальные машины способны динамически оптимизировать исполнение программного кода прямо во время работы приложения. Яркий пример — механизм Just-in-time компиляции (JIT). Именно благодаря ему браузерные движки типа V8 делают JavaScript невероятно быстрым, а среда BEAM начиная с версии OTP 24 заметно повышает производительность при помощи собственного механизма JIT. Такие технологии полезны там, где программа многократно повторяется, как, например, в высоконагруженных веб-приложениях.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Поддержка сложных систем&lt;/strong&gt; 🌐&lt;br&gt;&lt;br&gt;
Некоторые виртуальные машины специально спроектированы для обеспечения конкурентности, распределения нагрузки и устойчивости к сбоям. Так, сервера популярной игры &lt;a href="https://highscalability.com/how-league-of-legends-scaled-chat-to-70-million-players-it-t/" rel="noopener noreferrer"&gt;League of Legends основаны именно на BEAM&lt;/a&gt;, что позволяет эффективно обрабатывать миллионы одновременных подключений игроков с минимальными задержками и высоким уровнем надежности.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Таким образом, виртуальные машины помогают разработчикам сосредоточиться непосредственно на создании функциональности продукта, а не на низкоуровневых технических аспектах, ускоряя процессы разработки и снижая расходы.&lt;/p&gt;




&lt;h2&gt;
  
  
  Популярные виртуальные машины: Кто есть? 🦸‍♂️
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JVM (Java Virtual Machine):&lt;/strong&gt; Используется для Java, Kotlin, Scala. Отлично подходит для крупных бизнес-систем (например, банковские решения), веб-серверов (Spring Framework) и платформ Android. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Преимущества:&lt;/strong&gt; обширная инфраструктура (огромное количество готовых библиотек), технология Just-In-Time компиляции. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Недостатки:&lt;/strong&gt; большие начальные затраты оперативной памяти и сравнительно долгий запуск приложений.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Факт:&lt;/strong&gt; Решение применяется в большинстве (около 90%) крупнейших мировых корпораций (Fortune 500).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;V8 (JavaScript Engine):&lt;/strong&gt; Основана в Node.js и современных браузерах. Оптимизировано для работы в веб-пространстве. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Преимущества:&lt;/strong&gt; высокая производительность для клиентской части сайта. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Недостаток:&lt;/strong&gt; плохо приспособлена для долговременных серверных решений, где преимущество на стороне BEAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CLR (.NET Common Language Runtime):&lt;/strong&gt; Поддерживает языки семейства .NET, включая C#. Хорошо интегрируется с технологиями от Microsoft (например Azure). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Преимущества:&lt;/strong&gt; тесная совместимость с Windows-платформой.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Недостаток:&lt;/strong&gt; ограниченная кросс-платформенность по сравнению с JVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;BEAM (Erlang VM):&lt;/strong&gt; Работает с языками Erlang, Elixir, LFE. Лучше всего справляется с высоко нагруженными системами, ориентированными на масштабируемость, устойчивость и параллельность обработки запросов. Прекрасно подходит для мессенджеров, телекоммуникационных сервисов и финансовых технологий. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Преимущества:&lt;/strong&gt; поддерживает миллионы параллельных процессов одновременно, минимизирует задержки выполнения операций. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Недостаток:&lt;/strong&gt; меньший объем библиотеки инструментов и фреймворков, хотя активно развивается (например Phoenix, Nerves).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Сравнение в таблице&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ВМ&lt;/th&gt;
&lt;th&gt;Сильные стороны&lt;/th&gt;
&lt;th&gt;Слабые стороны&lt;/th&gt;
&lt;th&gt;Применение&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JVM&lt;/td&gt;
&lt;td&gt;Универсальность, экосистема&lt;/td&gt;
&lt;td&gt;Память, запуск&lt;/td&gt;
&lt;td&gt;Enterprise, Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;V8&lt;/td&gt;
&lt;td&gt;Скорость для веб&lt;/td&gt;
&lt;td&gt;Не для серверов&lt;/td&gt;
&lt;td&gt;Node.js, браузеры&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLR&lt;/td&gt;
&lt;td&gt;Интеграция с Microsoft&lt;/td&gt;
&lt;td&gt;Привязка к экосистеме&lt;/td&gt;
&lt;td&gt;.NET, Azure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BEAM&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;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;В 2025 году, с ростом IoT и стриминга данных, BEAM особенно актуальна для реального времени.&lt;/p&gt;




&lt;h2&gt;
  
  
  Подробнее о BEAM  🌌
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;BEAM&lt;/strong&gt; представляет собой виртуальную машину, предназначенную для работы с языками программирования &lt;strong&gt;Erlang&lt;/strong&gt;, &lt;strong&gt;Elixir&lt;/strong&gt; и рядом других (например, LFE, Alpaca). Изначально она была создана в 1990-е годы в компании Ericsson специально для телекоммуникаций, где крайне важны устойчивость к сбоям и способность выдерживать огромные нагрузки. Сейчас BEAM лежит в основе многих высоконагруженных сервисов: она обслуживает миллиарды сообщений ежедневно (как WhatsApp), поддерживает миллионы пользователей онлайн-игр одновременно (например, продукты Riot Games) и обеспечивает бесперебойную работу чат-сервисов реального времени (таких как Discord). В условиях современного мира, где критически важными становятся высокая производительность, минимальное время отклика и надежность, в 2025 году BEAM демонстрирует свою незаменимость сильнее, чем когда бы то ни было ранее.&lt;/p&gt;

&lt;h3&gt;
  
  
  История BEAM: От телекома к глобальным платформам 📜
&lt;/h3&gt;

&lt;p&gt;Изначально аббревиатура BEAM расшифровывалась как &lt;em&gt;«Bogdan’s Erlang Abstract Machine»&lt;/em&gt; в честь Богумила "Богдана" Хаусмана, который создал первую её версию. Однако сейчас название часто связывают с именем другого автора — &lt;em&gt;«Björn’s Erlang Abstract Machine»&lt;/em&gt;, поскольку именно Бьёрн Густавссон разработал и поддерживает актуальную реализацию. Оба специалиста внесли значительный вклад в развитие системы, трудясь в компании Ericsson.&lt;/p&gt;

&lt;p&gt;До появления BEAM существовала другая виртуальная машина — JAM (&lt;em&gt;Joe’s Abstract Machine&lt;/em&gt;), ставшая первым интерпретатором языка программирования Erlang. Она была создана Джо Армстронгом совместно с Майком Уильямсом на языке C (подробности можно найти в &lt;a href="https://www.erlang.org/blog/beam-compiler-history/" rel="noopener noreferrer"&gt;блоге разработчиков&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Поэтому Богумил («Богдан») Хаусман создал TEAM (Турбо-Эрланг-Абстрактную-машину). Она компилировала код Эрланга в Си-код, который затем компилировался в нативный код с помощью GCC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;На сегодняшний день BEAM активно применяется в финансовом секторе (например, Klarna), рекламной индустрии (AdRoll), системах уведомлений (Pinterest) и сфере Интернета вещей (Nerves). Благодаря внедрению технологии Just-In-Time компилятора в версии OTP 24 и развитию языка Elixir до уровня 1.15+, включающего улучшение работы с типизацией, BEAM продолжает оставаться актуальным решением. В будущем планируется ещё большее сближение с технологией WebAssembly для поддержки веб-приложений.&lt;/p&gt;




&lt;h2&gt;
  
  
  Почему BEAM — это круто? 🚀
&lt;/h2&gt;

&lt;p&gt;BEAM отличается от прочих виртуальных машин своими уникальными характеристиками, особенно полезными для масштабируемых и нагруженных приложений. Рассмотрим основные преимущества вместе с конкретными примерами, цифрами и сравнением с аналогичными решениями:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Быстрые и лёгкие процессы&lt;/strong&gt; ⚡&lt;br&gt;
Создание процессов в BEAM занимает всего несколько микросекунд, занимая около ~2.5 КБ оперативной памяти каждый процесс, что позволяет одновременно запустить миллионы экземпляров на одной машине. В отличие от потоков Java Virtual Machine, потребляющих целые мегабайты памяти. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Асинхронные задачи в Rust также легковесны, однако BEAM значительно удобнее для построения распределённых решений благодаря встроенной модели акторов, изолированные процессы с минимальными накладными расходами, автоматическую отказоустойчивость через супервизоры и горячую замену кода без остановки системы.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Модель акторов&lt;/strong&gt; 🎭&lt;br&gt;
Процессы здесь ведут себя как самостоятельные акторы, обменивающиеся сообщениями друг с другом без общих ресурсов и блокировки. Это значительно упрощает работу по сравнению с потоками Java Virtual Machine. Например, представим себе мессенджер вроде Discord, где каждая отдельная комната чата функционирует как независимый процесс, свободно принимающий новые сообщения независимо от других процессов. Производительность впечатляет: виртуальная машина BEAM способна обработать около ста тысяч сообщений всего за одну секунду на одном ядре.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Философия «пусть падает»&lt;/strong&gt; 💥&lt;br&gt;
BEAM основывается на принципе «let it crash»: когда какой-либо процесс ломается, он просто прекращает свою работу. Однако, благодаря продуманному подходу, такое событие практически незаметно для пользователей. Допустим, вы управляете большим рестораном, и вдруг кто-то из сотрудников уходит посреди смены. Обычно такая ситуация привела бы к хаосу среди клиентов, но в BEAM действует своего рода супервайзер («менеджер»), который моментально запускает замену сбойного процесса новым экземпляром. И клиент продолжает получать заказ вовремя, даже не заметив заминки.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☎️ История показывает, насколько эффективна эта философия: ещё в девяностые годы прошлого века компания Ericsson использовала BEAM для поддержания работоспособности крупных телекоммуникационных станций. Если один из компонентов падал, система продолжала функционировать бесперебойно.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Горячая замена кода&lt;/strong&gt; 🔄&lt;br&gt;
Система позволяет обновлять программы, не останавливая работающую систему. BEAM держит одновременно две версии программного модуля, переключаясь между ними почти мгновенно. Для сравнения, в Java такой переход требует больше усилий и зачастую вызывает кратковременные задержки. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; Торговая площадка Klarna, которая обновляется без единой секунды простоя, позволяя клиентам совершать покупки непрерывно.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Распределённые системы&lt;/strong&gt; 🌐&lt;br&gt;
Отдельные узлы BEAM соединяются в единую распределённую систему через сетевые соединения. Такой подход обеспечивает высокую отказоустойчивость и лёгкость горизонтального масштабирования. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; в Pinterest тысячи новых серверов легко подключаются к существующему кластеру, увеличивая общую производительность без потери производительности отдельных частей. Масштабируемость достигает десятков тысяч узлов с минимальной задержкой обработки запросов.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Низкая задержка&lt;/strong&gt; ⏱&lt;br&gt;
За счёт инкрементальной сборки мусора BEAM сводит задержки к минимуму. Фреймворк Phoenix, построенный поверх BEAM, способен обрабатывать тысячи запросов с минимальным временем отклика, измеряемым в миллисекундах. Другие языки программирования, такие как Python, иногда испытывают длительные паузы из-за своей модели сбора мусора, тогда как BEAM уверенно справляется с большими нагрузками, сохраняя низкую задержку.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JIT-компиляция&lt;/strong&gt; 🚀&lt;br&gt;
Начиная с версии OTP 24, BEAM поддерживает технологию Just-In-Time компиляции, ускоряя выполнение интенсивных вычислительных операций примерно на 20–30%. Хотя основной фокус BEAM всё равно остаётся на параллельной обработке, новая оптимизация существенно повышает скорость выполнения ресурсоёмких задач. Например, парсинг JSON-файлов теперь выполняется заметно быстрее благодаря улучшенной оптимизации компилятором.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Внутренности BEAM: Как это работает? 🛠
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Планировщик: Дирижёр многозадачности 🎻
&lt;/h3&gt;

&lt;p&gt;Планировщик BEAM — это как дирижёр в оркестре. У него тысячи музыкантов (процессов), и каждому нужно время, чтобы сыграть свою партию. Никто не играет слишком долго — иначе музыка превратится в хаос.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; Один сервер WhatsApp с использованием BEAM одновременно обслуживал миллионы подключений. Такое было бы невозможно реализовать через обычные потоки операционной системы, однако BEAM справляется с этой задачей благодаря своей уникальной схеме планирования процессов.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Механизм работы:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Количество планировщиков соответствует числу ядер процессора. Например, на восьмиядерном сервере действует восемь планировщиков.&lt;/li&gt;
&lt;li&gt;Каждый процесс получает определённое количество шагов выполнения («редукций»), после чего управление передаётся другому процессу.&lt;/li&gt;
&lt;li&gt;Процессы распределяются по двум очередям: готовых к выполнению (ready) и ожидающих ресурсов (waiting).&lt;/li&gt;
&lt;li&gt;Реализована технология перераспределения нагрузок («краже задач») для балансировки активности.&lt;/li&gt;
&lt;li&gt;Используется структура типа «колеса времени»: массив временных интервалов для хранения активных таймеров с целью снижения накладных расходов.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Типичная ошибка:&lt;/strong&gt; Долгие встроенные функции (BIFs), выполняемые без передачи управления, способны заблокировать работу планировщика.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Сборка мусора: Чистота в памяти 🧹
&lt;/h3&gt;

&lt;p&gt;Сборщик мусора (GC) в среде выполнения BEAM действует подобно аккуратному дворнику, незаметно обходящему рестораны большого города BEAM и аккуратно собирающему грязную посуду, освобождая пространство на столах.&lt;/p&gt;

&lt;p&gt;Каждый отдельный процесс имеет свою собственную зону хранения («кучу»). Когда память конкретного процесса заполняется ненужными объектами, уборка проводится именно там, не затрагивая работу остальных процессов.&lt;/p&gt;

&lt;p&gt;BEAM применяет методику поколений (generational garbage collection): часто очищаются недавно созданные элементы («молодое поколение»), поскольку они имеют короткий срок жизни, тогда как старшие поколения проверяются гораздо реже.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Типичная ошибка:&lt;/strong&gt; длительное накопление долгоживущих объектов может привести к повышенному потреблению ресурсов, отслеживайте параметр high_water.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Объёмные двоичные данные (файлы, изображения) располагаются обособленно от основной зоны сборки мусора, предотвращая её чрезмерное заполнение.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; Discord обслуживает миллионы активных каналов на платформе BEAM. Даже если один конкретный чат накапливает временные данные, система очистки мгновенно избавляется от них, абсолютно не влияя на производительность других чатов.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Алгоритм работы:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Стек и куча расширяются навстречу друг другу до тех пор, пока не встретятся. Тогда запускается процедура уборки.&lt;/li&gt;
&lt;li&gt;Существуют два типа циклов сбора мусора: молодой (частый, минорный) и старый (редкий, полный).&lt;/li&gt;
&lt;li&gt;Используется техника копирования данных между двумя зонами памяти ("from space" → "to space"), обеспечивая эффективную обработку совместно используемых элементов. Ключевые параметры мониторинга: gen_gcs, high_water. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✨ Внимательно наблюдайте за динамикой роста областей памяти ваших процессов. Быстро увеличивающиеся размеры могут свидетельствовать о наличии объектов с длительным жизненным циклом, что требует пересмотра архитектуры вашего приложения.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Архитектура на основе регистров: быстрее и эффективнее 🧠
&lt;/h3&gt;

&lt;p&gt;Машина BEAM основана на регистровой модели работы. Регистровая машина работает через использование набора регистров — специальных быстродействующих областей памяти, предназначенных для хранения промежуточных результатов вычислений. Каждый регистр хранит определённое значение, которое участвует в операции обработки данных. Регистры позволяют быстрее обращаться к данным и обеспечивают высокую производительность выполнения операций, поскольку данные уже находятся в быстрой памяти процессора.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Примеры:&lt;/strong&gt; Простое вычисление суммы двух чисел (add(A, B) → результат в регистрах X0 и X1).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Принцип функционирования:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Регистры X (до 1024 штук): Хранят аргументы функций.&lt;/li&gt;
&lt;li&gt;Регистры Y: Для локальных переменных.&lt;/li&gt;
&lt;li&gt;Используются инструкции типа move и call, поддерживается прямая адресация памяти. Технология JIT существенно повышает производительность.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Типичная ошибка:&lt;/strong&gt; Переполнение регистров — важно следить за размером функций и корректностью оптимизации.&lt;/p&gt;

&lt;p&gt;✨ &lt;strong&gt;Советы по улучшению производительности:&lt;/strong&gt; Уменьшайте использование стека, активно задействуйте регистры для хранения промежуточных значений.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Супервизоры и отказоустойчивость: Пусть падает! 💥
&lt;/h3&gt;

&lt;p&gt;В обычной среде крах процесса означает бедствие. Но в виртуальной машине BEAM это заложено в философию разработки.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Возьмём аналогию электрической сети:&lt;/strong&gt; Есть большая электрическая сеть. В ней одна подстанция «вырубилась». В обычном случае — весь район без света. В BEAM же стоит автоматика: неисправная подстанция отключается, а система мгновенно подключает резервную. Город даже не моргнёт лампочкой.&lt;/p&gt;

&lt;p&gt;Супервизор формируют древовидную структуру. Когда дочерний процесс выходит из строя, узел супервизора определяет стратегию действий: восстановить лишь пострадавший элемент либо целую группу процессов разом.&lt;/p&gt;

&lt;p&gt;Подобная архитектура обеспечивает автоматическое восстановление работоспособности всей системы.&lt;/p&gt;

&lt;p&gt;Механизм работы: дерево супервизоров, стратегии типа one_for_one, состояния выполнения (running, сбор мусора).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Типичная ошибка:&lt;/strong&gt; игнорирование роли супервизора, использование неподходящих инструментов вроде самодельных решений вместо проверенных библиотек OTP.&lt;/p&gt;

&lt;p&gt;✨ Советы разработчикам: пишите приложения так, чтобы ошибки были простительны, а логика обработки сбоев оставляйте специализированным механизмам супервизора.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Динамическая загрузка кода и распределенные системы 🌍
&lt;/h3&gt;

&lt;p&gt;Платформа BEAM позволяет обновлять код прямо на лету, когда приложение активно функционирует. Подобно тому, как музыкант переключается на другой инструмент посреди выступления, абсолютно незаметно для аудитории.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;В BEAM одновременно хранятся две версии каждого модуля:&lt;/strong&gt; одна старая продолжает обрабатывать существующие запросы, другая новая принимает новые задачи. Таким образом исправляются ошибки и добавляются функции без остановок работы приложения.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Замена кода:&lt;/strong&gt; выполняется командой :code.load_file(Module). Важно соблюдать правила обновления, иначе возможны сбои.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Распределенность:&lt;/strong&gt; Проверяется доступность удаленных нод через команду net_adm:ping(Node), база данных поддерживается системой Mnesia. Пример реализации — кластеры в Kubernetes с использованием виртуальных машин на основе BEAM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Масштабирование:&lt;/strong&gt; Использование инструментов из набора OTP для мониторинга состояния узлов сети.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Масштабируемость: BEAM-сеть на тысячи узлов 🌐
&lt;/h3&gt;

&lt;p&gt;BEAM представляет собой не единый узел, а целую взаимосвязанную сеть, функционирующую как единое целое. Каждый отдельный элемент сети способен взаимодействовать с остальными узлами так, словно они являются частью единой распределённой инфраструктуры.&lt;/p&gt;

&lt;p&gt;Вот несколько преимуществ такой архитектуры:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Вы можете развернуть кластер из множества серверов, позволяя процессам обмениваться сообщениями между собой прозрачно и эффективно.&lt;/li&gt;
&lt;li&gt;Особенно полезно это в системах Internet of Things (IoT) и микросервисных архитектурах, когда доставка сообщений автоматически распределяется BEAM'ом среди нужных серверов.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; компания Pinterest применила эту технологию для отправки уведомлений своим пользователям. По мере роста нагрузки всё, что потребовалось сделать, — добавить дополнительные сервера в кластер.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  BEAM в 2025 году: почему стоит обратить внимание? 🚀
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Большие объёмы трафика: WhatsApp обслуживает миллионы подключений одновременно.&lt;/li&gt;
&lt;li&gt;Масштабируемые микросервисы: простое развертывание и управление в Kubernetes.&lt;/li&gt;
&lt;li&gt;Работа в режиме реального времени: Phoenix обеспечивает мгновенные чат-коммуникации.&lt;/li&gt;
&lt;li&gt;Надежность и отказоустойчивость: проверена крупными финансовыми компаниями вроде Klarna.&lt;/li&gt;
&lt;li&gt;Интернет вещей и машинное обучение: Nerves для устройств IoT и совместимость с TensorFlow через механизм портов.&lt;/li&gt;
&lt;li&gt;Перспективы развития: оптимизация производительности благодаря JIT-компиляции и поддержка WebAssembly для веб-приложений.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;strong&gt;Пример из практики:&lt;/strong&gt; Pinterest снизил задержку доставки уведомлений на 50% именно благодаря платформе BEAM.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  BEAM — будущее, которое уже здесь! 🌌
&lt;/h2&gt;

&lt;p&gt;На сегодняшний день, в 2025 году, технологии Elixir и Erlang занимают скромное место среди используемых инструментов разработки и не получают должного внимания общественности. Но лично я считаю, что такая ситуация весьма незаслуженна, потому что предлагаемые ими возможности действительно удивительны и оригинальны. Хотя путь освоения и развития проектов на этой платформе может показаться непростым, результат обещает быть потрясающим!&lt;/p&gt;

&lt;p&gt;Откройте для себя мир Elixir/Erlang, окунитесь в разработку нового проекта и ощутите всю мощь виртуальной машины BEAM! ✨&lt;/p&gt;




&lt;h2&gt;
  
  
  От автора
&lt;/h2&gt;

&lt;p&gt;Спасибо большое за интерес к этой статье! Надеюсь, она помогла разобраться, что представляет собой BEAM и зачем она используется. Изначально планировал сделать материал сложнее и добавить больше технических подробностей, однако понял, что вряд ли смогу превзойти книгу &lt;a href="https://blog.stenmans.org/theBeamBook/#CH-BEAM" rel="noopener noreferrer"&gt;The BEAM Book: Understanding the Erlang Runtime System&lt;/a&gt;, поэтому решил изложить всё простыми словами.&lt;/p&gt;

&lt;p&gt;Если эта статья пришлась вам по душе и хочется ещё материалов такого плана, присоединяйтесь ко мне в &lt;a href="//t.me/devs_inc"&gt;моём телеграм-канале&lt;/a&gt;, где выкладываю обзоры книг, публикации по Elixir, переводы технической литературы и интересные новости!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>erlang</category>
      <category>beam</category>
      <category>virtualmachine</category>
    </item>
    <item>
      <title>Speeding up Elixir: integration with native code (NIF, Ports, etc.)</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Wed, 21 May 2025 08:59:32 +0000</pubDate>
      <link>https://forem.com/adamanq/speeding-up-elixir-integration-with-native-code-nif-ports-etc-5ajd</link>
      <guid>https://forem.com/adamanq/speeding-up-elixir-integration-with-native-code-nif-ports-etc-5ajd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Important:&lt;/strong&gt; Before introducing new languages into your project, ensure that your existing Elixir code has been optimized first. In many cases, proper optimization can significantly improve application performance and sometimes yield better results than adding another programming language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Elixir&lt;/strong&gt; and &lt;strong&gt;Erlang&lt;/strong&gt; when are excellent languages for developing scalable and fault-tolerant systems. However, there may come times when you need to extract maximum performance or utilize libraries available only in other languages. If you're facing such situations or simply want to explore how to combine two favorite programming languages, this article is for you! &lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Search When You Need Native Code Integration
&lt;/h2&gt;

&lt;p&gt;Before diving into technical details, it's important to understand when native code integration should be considered:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Compute-intensive Tasks
&lt;/h3&gt;

&lt;p&gt;The BEAM virtual machine excels at concurrency but isn't designed for heavy computations. Consider integrating native code if your bottleneck involves CPU-bound operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧮 Mathematical Calculations—Linear algebra or matrix operations&lt;/li&gt;
&lt;li&gt;🔐 Cryptography—Encryption/decryption of large datasets&lt;/li&gt;
&lt;li&gt;🎨 Media Processing—Images, videos, audio&lt;/li&gt;
&lt;li&gt;🧠 Machine Learning—Model inference, vector operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Hardware Interaction
&lt;/h3&gt;

&lt;p&gt;When low-level access to hardware is required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📟 Embedded Systems—Raspberry Pi, microcontrollers (Note: While Nerves exists in Elixir, it might fall short)&lt;/li&gt;
&lt;li&gt;🎮 Specific Drivers—Unconventional devices&lt;/li&gt;
&lt;li&gt;📊 GPU Computing—CUDA, OpenCL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Reusing Existing Codebases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🏛️ Proven Libraries on C/C++&lt;/li&gt;
&lt;li&gt;📚 Ecosystem Advantages from other languages (e.g., Python for ML)&lt;/li&gt;
&lt;li&gt;🔧 Avoid Reinventing the Wheel&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Profiling and Bottlenecks
&lt;/h3&gt;

&lt;p&gt;Typical signs indicating it's time to consider native code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before Optimization - 1000ms&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;SlowModule&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&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="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Potential bottleneck candidate for native optimization&lt;/span&gt;
    &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&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;acc&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&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="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Imagine CPU-heavy calculations here&lt;/span&gt;
    &lt;span class="c1"&gt;# That don't scale well within BEAM&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Exhausted all possible optimizations in Elixir and still slow?&lt;/span&gt;
&lt;span class="c1"&gt;# Perhaps it's time to introduce native code!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Native extensions transform Elixir into an all-purpose tool where BEAM handles everything except critical computations. This opens doors to ML, hardware, video processing, and more speed-critical tasks.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Balance Comparison of Integration Methods
&lt;/h2&gt;

&lt;p&gt;Choosing the right method of integration is crucial for project success. Here's a comparative table of methods with their pros and cons:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;BEAM Safety&lt;/th&gt;
&lt;th&gt;Implementation Complexity&lt;/th&gt;
&lt;th&gt;Language Support&lt;/th&gt;
&lt;th&gt;Communication Overhead&lt;/th&gt;
&lt;th&gt;Asynchronicity&lt;/th&gt;
&lt;th&gt;Ideal Use Cases использования&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NIF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;❌ Dangerous&lt;/td&gt;
&lt;td&gt;🔧🔧🔧 Medium&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;None (direct call)&lt;/td&gt;
&lt;td&gt;❌ Blocks scheduler&lt;/td&gt;
&lt;td&gt;Microservices, lengthy CPU-bound tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dirty NIF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;⚠️ Conditionally Safe&lt;/td&gt;
&lt;td&gt;🔧🔧🔧 Medium&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;None (direct call)&lt;/td&gt;
&lt;td&gt;✅ Doesn't block primary scheduler&lt;/td&gt;
&lt;td&gt;Long computational tasks (&amp;gt;1ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡&lt;/td&gt;
&lt;td&gt;✅✅ Completely Safe&lt;/td&gt;
&lt;td&gt;🔧 Simple&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;td&gt;High (IPC)&lt;/td&gt;
&lt;td&gt;✅ Process isolation&lt;/td&gt;
&lt;td&gt;Python, Go, Bash-scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port Driver&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;✅ Safe&lt;/td&gt;
&lt;td&gt;🔧🔧🔧🔧 Complex&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;✅ Dedicated thread&lt;/td&gt;
&lt;td&gt;Video/audio processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡&lt;/td&gt;
&lt;td&gt;✅✅ Completely Safe&lt;/td&gt;
&lt;td&gt;🔧🔧 Medium&lt;/td&gt;
&lt;td&gt;Any with gRPC support&lt;/td&gt;
&lt;td&gt;Moderate (network)&lt;/td&gt;
&lt;td&gt;✅ Separate service&lt;/td&gt;
&lt;td&gt;Microservice architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rustler&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;✅ Safe&lt;/td&gt;
&lt;td&gt;🔧🔧 Medium&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;None (direct call)&lt;/td&gt;
&lt;td&gt;✅ Supports asynchronous APIs&lt;/td&gt;
&lt;td&gt;Alternative to C NIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zigler&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;✅ Safe&lt;/td&gt;
&lt;td&gt;🔧🔧 Medium&lt;/td&gt;
&lt;td&gt;Zig&lt;/td&gt;
&lt;td&gt;None (direct call)&lt;/td&gt;
&lt;td&gt;✅ Safer than standard NIFs&lt;/td&gt;
&lt;td&gt;Alternative to C in NIF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Visual Comparison by Key Metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Speed:               Safety:               Simplicity:
NIF         █████    Port        █████     Port        █████
Dirty NIF   ████     Dirty NIF   ███       gRPC        ████
Rustler     ████     Rustler     ████      Rustler     ████
Zigler      █████    Zigler      ████      Zigler      ████
Port Driver ████     Port Driver ████      NIF         ███
Port        ██       gRPC        █████     Port Driver █
gRPC        ██       NIF         █         Dirty NIF   ███
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Mechanisms Behind Integration
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  🧠 NIFs — Maximal Performance
&lt;/h3&gt;

&lt;p&gt;Native Implemented Functions (NIFs) offer the fastest way to integrate native code, albeit being the riskiest option. They execute directly in the BEAM scheduler's thread, ensuring lightning-fast execution due to zero overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Do NIFs Work?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compilation:&lt;/strong&gt; Native code (C/Rust/Zig) compiles into a dynamic library (.so, .dll)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loading:&lt;/strong&gt; BEAM loads the library during module startup via :erlang.load_nif/2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Execution:&lt;/strong&gt; Functions run in the same thread as the calling Elixir code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blazing Speed:&lt;/strong&gt; Calls take approximately 0.1–1 µs &lt;em&gt;(~100–1000× faster than Ports)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access to BEAM API:&lt;/strong&gt; Direct interaction with Erlang terms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Serialization:&lt;/strong&gt; No encoding/decoding costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution:&lt;/strong&gt; Library ships alongside the OTP app&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ &lt;strong&gt;Drawbacks&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Risk of VM Crash: Errors in NIF terminate the entire BEAM instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduler Blocking:&lt;/strong&gt; Long-running NIFs freeze multithreading&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging Difficulty:&lt;/strong&gt; Memory leaks hard to detect&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform Dependency:&lt;/strong&gt; Requires compilation per target architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Dirty NIFs — Safer Alternative&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With Erlang/OTP 20+, we have Dirty NIFs, which execute in dedicated thread pools, allowing longer computations without blocking the BEAM scheduler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Defining a Dirty NIF&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"long_computation"&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="n"&gt;long_computation_nif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_DIRTY_CPU&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Use ERL_NIF_DIRTY_CPU for CPU-bound ops and ERL_NIF_DIRTY_IO for I/O-bound ones&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔌 &lt;strong&gt;Ports — Complete Isolation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ports provide a safe mechanism for interacting with external programs through standard I/O streams (stdin/stdout). It's the safest form of integration since the external program runs in its own OS process.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Do Ports Work?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch:&lt;/strong&gt; Elixir spawns an external program as a separate OS process&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication:&lt;/strong&gt; Data exchange occurs over stdin/stdout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; Failure of the external program doesn't affect BEAM&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Safety:&lt;/strong&gt; Isolation ensures BEAM stability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Agnosticism:&lt;/strong&gt; Works with any programming language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Debugging:&lt;/strong&gt; External program can be tested independently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency-Free:&lt;/strong&gt; No specific BEAM-compatible libraries needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ &lt;strong&gt;Downsides&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Overheads:&lt;/strong&gt; Approximately 100–500 µs per invocation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serialization Required:&lt;/strong&gt; Needs conversion of data (usually to JSON)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocking Calls:&lt;/strong&gt; By default blocks the caller process&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🚗 &lt;strong&gt;Port Drivers — Goldilocks Zone&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Port Drivers are high-performance alternatives to Ports, though they require greater complexity. These drivers are written in C and embedded directly into BEAM’s address space, running in separate threads.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Do Port Drivers Work?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load:&lt;/strong&gt; BEAM loads the C library into its memory space&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread Allocation:&lt;/strong&gt; Each driver operates in its own thread&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Operation:&lt;/strong&gt; Data exchanges occur via message queues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Significantly faster than regular ports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Lower risk compared to NIFs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async Capability:&lt;/strong&gt; Non-blocking operation supported&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convenience:&lt;/strong&gt; No need to spawn additional processes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Requires knowledge of Erlang C API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Scope:&lt;/strong&gt; Only works with C/C++&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less Documentation:&lt;/strong&gt; Few examples and guides available&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🐊 &lt;strong&gt;&lt;a href="https://github.com/E-xyza/zigler" rel="noopener noreferrer"&gt;Zigler&lt;/a&gt; — Wrapper Around NIFs for Zig&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Zigler is a library enabling writing native extensions using the Zig programming language. It integrates the Zig compiler directly into the Elixir compilation cycle, allowing direct coding in Zig inside Elixir modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minimal overhead for native calls&lt;/li&gt;
&lt;li&gt;Memory safety without garbage collection&lt;/li&gt;
&lt;li&gt;Direct access to low-level operations&lt;/li&gt;
&lt;li&gt;Simpler compilation compared to other native extensions&lt;/li&gt;
&lt;li&gt;Hot reloading capability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Zig is relatively young with a smaller community&lt;/li&gt;
&lt;li&gt;Higher entry barrier for Elixir developers&lt;/li&gt;
&lt;li&gt;Limited ecosystem of libraries compared to Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🦀 &lt;strong&gt;&lt;a href="https://github.com/rusterlium/rustler" rel="noopener noreferrer"&gt;Rustler&lt;/a&gt; — Wrapping NIFs for Rust&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rustler is a library for creating native extensions in Erlang/Elixir using Rust. It provides a safe binding between Rust and Erlang/Elixir, facilitating writing NIFs in Rust.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memory safety enforced at compile-time&lt;/li&gt;
&lt;li&gt;High performance for computationally intensive tasks&lt;/li&gt;
&lt;li&gt;Rich ecosystem of Rust packages (crates)&lt;/li&gt;
&lt;li&gt;Protection against crashes in native code (protects BEAM from crashing)&lt;/li&gt;
&lt;li&gt;Parallel execution without blocking the BEAM scheduler&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Complicated build process and dependency management&lt;/li&gt;
&lt;li&gt;Requires familiarity with two different programming paradigms&lt;/li&gt;
&lt;li&gt;Possible compatibility issues across versions&lt;/li&gt;
&lt;li&gt;Potential bottlenecks at runtime boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🌐 &lt;strong&gt;Global gRPC and Similar Protocols&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For more advanced scenarios involving external services, especially in microservice architectures, protocols like gRPC provide structured and scalable ways of integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;gRPC Benefits for Elixir&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contract Schema:&lt;/strong&gt; Strong typing via Protocol Buffers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional Streaming:&lt;/strong&gt; Supports streaming both ways&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform:&lt;/strong&gt; Supports multiple languages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; More efficient than REST/JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;❗️ An example using &lt;strong&gt;gRPC&lt;/strong&gt; was omitted due to its extensive nature. For detailed info about gRPC in Elixir, see &lt;a href="https://github.com/elixir-grpc/grpc" rel="noopener noreferrer"&gt;elixir-grpc&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧪 Practical Examples of Integration
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📚 The goal of this article is to give an overview of available native integration methods. Deep implementations and edge cases are omitted to maintain balance between theory and practical application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Exploring Criteria for Choosing Integration Methods
&lt;/h3&gt;

&lt;p&gt;Before moving onto examples, let's define key factors influencing our choice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; How fast does the call execute?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Risk level for BEAM stability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation Complexity:&lt;/strong&gt; Ease of implementation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Support:&lt;/strong&gt; Suitability of the chosen language with BEAM&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ⚙️ &lt;strong&gt;C — Maximum Performance Using NIF and Port Drivers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Optimal Methods:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NIF&lt;/strong&gt; — for instantaneous operations (&amp;lt;1ms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port Drivers&lt;/strong&gt; — for long-lasting or async tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Choose This Approach?&lt;/strong&gt;&lt;br&gt;
C offers seamless compatibility with BEAM, making it ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critically performant tasks&lt;/li&gt;
&lt;li&gt;Low-level operations (hardware, GPU)&lt;/li&gt;
&lt;li&gt;Integrating pre-existing C libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Example 1: Fast NIF for Hashing (Best Suited for C)&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hash_nif.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;erl_nif.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/sha.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="nf"&gt;sha256_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlNifEnv&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ErlNifBinary&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;enif_inspect_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&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="n"&gt;enif_make_badarg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;ErlNifBinary&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;enif_alloc_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enif_make_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"sha256"&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="n"&gt;sha256_nif&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;ERL_NIF_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Elixir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CryptoNif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&lt;/span&gt;&lt;span class="p"&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;NULL&lt;/span&gt;&lt;span class="p"&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;NULL&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;Elixir Part:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CryptoNif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@on_load&lt;/span&gt; &lt;span class="ss"&gt;:load_nif&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;load_nif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./hash_nif"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;sha256&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="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"NIF not loaded!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compiling C Source:&lt;/strong&gt;&lt;br&gt;
You'll need the &lt;strong&gt;OpenSSL&lt;/strong&gt; library installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For Ubuntu/Debian&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libssl-dev

&lt;span class="c"&gt;# For CentOS/RHEL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;openssl-devel

&lt;span class="c"&gt;# For macOS (with Homebrew)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;openssl
Compile the C &lt;span class="nb"&gt;source&lt;/span&gt;:


gcc &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; hash_nif.so hash_nif.c &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; /usr/lib/erlang/erts-15.2.7/include &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Path depends on your system&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; /usr/include/openssl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-L&lt;/span&gt; /usr/lib/openssl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-lssl&lt;/span&gt; &lt;span class="nt"&gt;-lcrypto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;CryptoNif&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;208&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;154&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;208&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;163&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;43&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="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;209&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;93&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Example 2: Port Driver for String Reversal&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// reverse_driver.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"erl_driver.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ErlDrvPort&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;reverse_and_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ErlDrvSizeT&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvSizeT&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&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="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buf&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;buf&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;driver_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="nf"&gt;driver_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvPort&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;driver_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;driver_stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;driver_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlDrvEntry&lt;/span&gt; &lt;span class="n"&gt;driver_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver_stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reverse_and_send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"reverse_driver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extended_marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MARKER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;major_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MAJOR_VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minor_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MINOR_VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver_flags&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="n"&gt;DRIVER_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverse_driver&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;driver_entry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Elixir Part:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;ReverseString&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:erl_ddll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_driver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'reverse_driver'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'reverse_driver'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:data&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="k"&gt;after&lt;/span&gt;
      &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compiling C Source:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gnu99 &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; reverse_driver.so reverse_driver.c &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/lib/erlang/erts-15.2.7/include/ &lt;span class="c"&gt;# Path depends on your system&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ReverseString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.6&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;ReverseString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"olleh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🦀 Rustler — Security and Performance with Rustler
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Optimal Method:&lt;/strong&gt; Rustler (specialized wrapper for NIF)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Rustler?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full memory safety&lt;/li&gt;
&lt;li&gt;Convenient macros for working with BEAM terms&lt;/li&gt;
&lt;li&gt;Automatic error handling&lt;/li&gt;
&lt;li&gt;Async task support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: Parallel Data Processing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;Rustler&lt;/code&gt; to mix.exs &lt;em&gt;(Current version is 0.36.1)&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:rustler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.36.1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Rust Project Inside Elixir:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix deps.get
mix rustler.new

This is the name of the Elixir module the NIF module will be registered to.
Module name &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; RustUtils
This is the name used &lt;span class="k"&gt;for &lt;/span&gt;the generated Rust crate. The default is most likely fine.
Library name &lt;span class="o"&gt;(&lt;/span&gt;rustutils&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Enter&lt;span class="o"&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 rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rayon&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[rustler::nif]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parallel_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i64&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;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.par_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="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="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;rustler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;init!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Elixir.RustUtils"&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;Elixir Part:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;RustUtils&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rustler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:rust_utils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;crate:&lt;/span&gt; &lt;span class="s2"&gt;"rustutils"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parallel_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nif_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:not_loaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;RustUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parallel_double&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="c1"&gt;# =&amp;gt; [2, 4, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 🐍 Python — Effortless Integration Through Ports
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Optimal Method:&lt;/strong&gt; Ports&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Ports?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total process isolation&lt;/li&gt;
&lt;li&gt;Easy debugging&lt;/li&gt;
&lt;li&gt;Access to Python ecosystem&lt;/li&gt;
&lt;li&gt;Handles long operations (like ML models)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: Creating Your Own Model and Integrating TensorFlow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Build the Model:&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="c1"&gt;# create_model.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&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="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; &lt;span class="n"&gt;use_bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_weights&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;]])])&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ Model saved to my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;"&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 python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#tensorflow_port.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TF_CPP_MIN_LOG_LEVEL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict&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="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&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;input_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&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;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reshape&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;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&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;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&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;Elixir Part:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@timeout&lt;/span&gt; &lt;span class="mi"&gt;5_000&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"python3 tensorflow_port.py"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:use_stdio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:exit_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:stderr_to_stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;input_data&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:eol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"result"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&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="ss"&gt;:ok&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:exit_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Python process exited with status &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;after&lt;/span&gt;
      &lt;span class="nv"&gt;@timeout&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;To run the script, enter the Python environment and launch &lt;code&gt;iex -S mix&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.10&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. 🦫 &lt;strong&gt;Go — Efficiency Through CGO or gRPC&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Optimal Methods:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CGO wrappers for NIF — best for max performance&lt;/li&gt;
&lt;li&gt;gRPC — suitable for complex interactions and microservices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CGO Wrapper for Go Code (Suitable for Performance)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// fib.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&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="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&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;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="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="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="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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C Wrapper:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// c_src/go_nif.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;erl_nif.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"libfib.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="nf"&gt;go_fib_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlNifEnv&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;enif_get_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enif_make_badarg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&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="n"&gt;enif_make_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"go_fib"&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="n"&gt;go_fib_nif&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;ERL_NIF_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Elixir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NifGo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&lt;/span&gt;&lt;span class="p"&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;NULL&lt;/span&gt;&lt;span class="p"&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;NULL&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;Elixir part:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;NifGo&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@on_load&lt;/span&gt; &lt;span class="ss"&gt;:load_nif&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;load_nif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;nif_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"priv/go_nif"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd!&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Preload Go library&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"priv/libfib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd!&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Load main NIF library&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nif_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;go_fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_n&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"NIF not loaded!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build &lt;span class="nt"&gt;-buildmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c-shared &lt;span class="nt"&gt;-o&lt;/span&gt; priv/libfib.so fib.go

gcc &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/lib/erlang/erts-15.2.7/include/ &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Path varies based on your system&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;./priv &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; priv/go_nif.so &lt;span class="se"&gt;\&lt;/span&gt;
    c_src/go_nif.c &lt;span class="se"&gt;\&lt;/span&gt;
    ./priv/libfib.so &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-Wl&lt;/span&gt;,-rpath,&lt;span class="s1"&gt;'$ORIGIN'&lt;/span&gt;

&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./priv iex &lt;span class="nt"&gt;-S&lt;/span&gt; mix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NifGo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;go_fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ If you'd rather avoid dealing with &lt;strong&gt;CGO&lt;/strong&gt;, opt for &lt;strong&gt;gRPC&lt;/strong&gt; or &lt;strong&gt;Ports&lt;/strong&gt; instead. They're safer, although slower.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. 🐊 Zig — Integration Via Zigler&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Optimal Method:&lt;/strong&gt; &lt;strong&gt;Zigler&lt;/strong&gt; (wrapper for Zig-based NIFs)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Zigler?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimum overhead for native calls&lt;/li&gt;
&lt;li&gt;Memory safety without garbage collection&lt;/li&gt;
&lt;li&gt;Direct access to low-level operations&lt;/li&gt;
&lt;li&gt;Simplified compilation relative to other native extensions&lt;/li&gt;
&lt;li&gt;Hot-reloading capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: Quick Binary Data Handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;Zigler&lt;/code&gt; to &lt;strong&gt;mix.exs&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:zigler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.13.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;runtime:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;lib/nif_zig.ex:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Zig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:zigler&lt;/span&gt;

  &lt;span class="sx"&gt;~Z""&lt;/span&gt;&lt;span class="s2"&gt;"
  pub fn string_count(string: []u8) i64 {
    return @intCast(string.len);
  }

  pub fn list_sum(array: []f64) f64 {
    var sum: f64 = 0.0;
    for(array) | item | {
      sum += item;
    }
    return sum;
  }
  """&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="mf"&gt;11.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Optimal Method&lt;/th&gt;
&lt;th&gt;Alternatives&lt;/th&gt;
&lt;th&gt;When To Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NIF, Port Drivers&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;Maximum performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rustler (NIF)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Safety + performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;gRPC&lt;/td&gt;
&lt;td&gt;Integration with ML/scientific tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C-обёртки (NIF), gRPC&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;Leveraging Go ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zig&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Zigler (NIF)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Modern alternative to C&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Integrating Elixir with native code unlocks new possibilities for developers, combining BEAM's strengths (scalability, reliability) with the performance and libraries of other languages. We've explored various integration techniques: &lt;strong&gt;NIF&lt;/strong&gt;, &lt;strong&gt;Dirty NIF&lt;/strong&gt;, &lt;strong&gt;Ports&lt;/strong&gt;, &lt;strong&gt;Port Drivers&lt;/strong&gt;, &lt;strong&gt;Rustler&lt;/strong&gt;, &lt;strong&gt;Zigler&lt;/strong&gt;, and &lt;strong&gt;gRPC&lt;/strong&gt;, along with their optimal usage scenarios.&lt;/p&gt;

&lt;p&gt;Remember, choosing an integration method should align with your project's requirements regarding performance, security, and ease of development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Author's Notes
&lt;/h2&gt;

&lt;p&gt;Thank you for reading this article! I hope you've found it insightful learning about ways to integrate other languages into Elixir. Among these options, I found Port Drivers particularly challenging, as crafting one turned out to be quite an adventure, requiring hours of trial-and-error to find the correct approach. Overall, however, integrating other languages into Elixir proved neither difficult nor boring—it was actually fun!&lt;/p&gt;

&lt;p&gt;If you spot inaccuracies or have interesting additions, please share them in the comments section. Constructive feedback is always appreciated 😎&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>nif</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ускоряем Elixir: интеграция с нативным кодом (NIF, Ports и др.)</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Wed, 21 May 2025 02:58:30 +0000</pubDate>
      <link>https://forem.com/adamanq/uskoriaiem-elixir-intieghratsiia-s-nativnym-kodom-nif-ports-i-dr-17kk</link>
      <guid>https://forem.com/adamanq/uskoriaiem-elixir-intieghratsiia-s-nativnym-kodom-nif-ports-i-dr-17kk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ &lt;strong&gt;Важно:&lt;/strong&gt; Перед внедрением новых языков в проект сначала убедитесь, что код на Elixir был максимально оптимизирован. В большинстве случаев грамотная оптимизация текущего кода значительно улучшает производительность приложения и иногда даёт лучшие результаты, нежели добавление другого языка программирования.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt; &lt;strong&gt;Elixir&lt;/strong&gt; и &lt;strong&gt;Erlang&lt;/strong&gt; — отличные языки для разработки масштабируемых и отказоустойчивых систем. Но иногда нужно выжать максимум производительности или использовать библиотеку, доступную лишь на другом языке. Если вы попали именно в такую ситуацию или просто хотите узнать, как совместить два ваших любимых языка программирования, эта статья для вас! &lt;br&gt;&lt;/p&gt;






&lt;h2&gt;
  
  
  🔍 Когда нужна интеграция с нативным кодом
&lt;/h2&gt;

&lt;p&gt;Прежде чем углубляться в технические детали, важно понять, &lt;strong&gt;когда&lt;/strong&gt; стоит рассматривать интеграцию с нативным кодом:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Вычислительно-интенсивные задачи
&lt;/h3&gt;

&lt;p&gt;BEAM создан для конкурентности, а не для вычислений. Если ваше узкое место — CPU-bound операции:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧮 &lt;strong&gt;Математические вычисления&lt;/strong&gt; — Линейная алгебра или операции с матрицами&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Криптография&lt;/strong&gt; — Шифрование/Дешифрование больших объёмов данных&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;Обработка медиа&lt;/strong&gt; — Изображения, видео, аудио&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Машинное обучение&lt;/strong&gt; - инференс моделей, векторные операции&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Аппаратное взаимодействие
&lt;/h3&gt;

&lt;p&gt;Когда требуется низкоуровневый доступ к оборудованию:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📟 &lt;strong&gt;Embedded-системы&lt;/strong&gt; — Raspberry Pi, микроконтроллеры &lt;em&gt;(Для этого есть Nerves в Elixir, но его иногда может не хватить)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🎮 &lt;strong&gt;Специфические драйверы&lt;/strong&gt; — нестандартные устройства&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;GPU-вычисления&lt;/strong&gt; — CUDA, OpenCL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Переиспользование существующего кода
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🏛️ &lt;strong&gt;Проверенные временем библиотеки&lt;/strong&gt; на C/C++&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Экосистемные преимущества&lt;/strong&gt; других языков &lt;em&gt;(например, Python для ML)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🔧 &lt;strong&gt;Избегание "изобретения велосипеда"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Профилирование и узкие места
&lt;/h3&gt;

&lt;p&gt;Типичные признаки, что пора задуматься о нативном коде:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# До оптимизации - 1000мс&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;SlowModule&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&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="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Потенциальное узкое место для нативной оптимизации&lt;/span&gt;
    &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&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;acc&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&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="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Представьте CPU-интенсивные вычисления&lt;/span&gt;
    &lt;span class="c1"&gt;# которые плохо масштабируются в BEAM&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Вы исчерпали возможности оптимизации на Elixir и всё ещё медленно? &lt;/span&gt;
&lt;span class="c1"&gt;# Возможно, пора подключать нативный код!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Нативные расширения превращают Elixir в универсальный инструмент, где BEAM решает всё, кроме критических вычислений. Это открывает двери к ML, hardware, видеообработке и всему, где важна скорость.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚖️ Сравнение методов интеграции
&lt;/h2&gt;

&lt;p&gt;Выбор правильного метода интеграции критически важен для успеха проекта. Вот сравнительная таблица методов интеграции с их плюсами и минусами:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Метод&lt;/th&gt;
&lt;th&gt;Скорость&lt;/th&gt;
&lt;th&gt;Безопасность BEAM&lt;/th&gt;
&lt;th&gt;Сложность реализации&lt;/th&gt;
&lt;th&gt;Поддержка языков&lt;/th&gt;
&lt;th&gt;Коммуникационные затраты&lt;/th&gt;
&lt;th&gt;Асинхронность&lt;/th&gt;
&lt;th&gt;Идеальные сценарии использования&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NIF&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;C, C++&lt;/td&gt;
&lt;td&gt;Нет (прямой вызов)&lt;/td&gt;
&lt;td&gt;❌ Блокирует планировщик&lt;/td&gt;
&lt;td&gt;Микросервисы, долгие CPU-bound задачи&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dirty NIF&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;C, C++&lt;/td&gt;
&lt;td&gt;Нет (прямой вызов)&lt;/td&gt;
&lt;td&gt;✅ Не блокирует основной планировщик&lt;/td&gt;
&lt;td&gt;Долгие вычисления (&amp;gt;1ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port&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;Высокие (IPC)&lt;/td&gt;
&lt;td&gt;✅ Процессная изоляция&lt;/td&gt;
&lt;td&gt;Python, Go, Bash-скрипты&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port Driver&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;C, C++&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;gRPC&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;Любой с поддержкой gRPC&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;Rustler&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;Rust&lt;/td&gt;
&lt;td&gt;Нет (прямой вызов)&lt;/td&gt;
&lt;td&gt;✅ Поддержка асинхронного API&lt;/td&gt;
&lt;td&gt;Альтернатива C NIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zigler&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;Zig&lt;/td&gt;
&lt;td&gt;Нет (прямой вызов)&lt;/td&gt;
&lt;td&gt;✅ Безопаснее стандартных NIF&lt;/td&gt;
&lt;td&gt;Альтернатива C в NIF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Визуальное сравнение по ключевым метрикам
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Скорость:            Безопасность:         Простота:
NIF         █████    Port        █████     Port        █████
Dirty NIF   ████     Dirty NIF   ███       gRPC        ████
Rustler     ████     Rustler     ████      Rustler     ████
Zigler      █████    Zigler      ████      Zigler      ████
Port Driver ████     Port Driver ████      NIF         ███
Port        ██       gRPC        █████     Port Driver █
gRPC        ██       NIF         █         Dirty NIF   ███
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Немного о механизмах интеграции
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  🧠 NIFs — максимальная производительность
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Native Implemented Functions (NIFs)&lt;/strong&gt; — самый быстрый способ интеграции, но и самый опасный. Они выполняются напрямую в потоке планировщика BEAM, обеспечивая молниеносную скорость за счет отсутствия накладных расходов.&lt;/p&gt;

&lt;h3&gt;
  
  
  Как работают NIF?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Компиляция&lt;/strong&gt;: Нативный код (C/Rust/Zig) компилируется в динамическую библиотеку (&lt;code&gt;.so&lt;/code&gt;, &lt;code&gt;.dll&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Загрузка&lt;/strong&gt;: BEAM загружает библиотеку при старте модуля через &lt;code&gt;:erlang.load_nif/2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Прямое выполнение&lt;/strong&gt;: Функции выполняются в том же потоке, что и вызывающий Elixir-код&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  ✅ Преимущества
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Молниеносная скорость&lt;/strong&gt;: Вызов занимает ~0.1-1 μs (в 100-1000 раз быстрее Ports)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Доступ к BEAM API&lt;/strong&gt;: Прямая работа с термами Erlang&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Отсутствие сериализации&lt;/strong&gt;: Нет накладных расходов на кодирование/декодирование данных&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Распространение&lt;/strong&gt;: Библиотека идёт вместе с OTP-приложением&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ❌ Недостатки
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Риск падения всей ВМ&lt;/strong&gt;: Ошибка в NIF убьёт весь BEAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Блокировка планировщика&lt;/strong&gt;: Долгие NIF замораживают многопоточность&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Сложность отладки&lt;/strong&gt;: Трудно обнаружить утечки памяти&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Платформозависимость&lt;/strong&gt;: Требуется компиляция под каждую архитектуру&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dirty NIFs — безопасная альтернатива
&lt;/h3&gt;

&lt;p&gt;С Erlang/OTP 20+ появились &lt;strong&gt;Dirty NIFs&lt;/strong&gt; — специальный вид NIF, который исполняется в выделенном пуле потоков, что позволяет выполнять долгие вычисления без блокировки планировщика BEAM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Определение Dirty NIF&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"long_computation"&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="n"&gt;long_computation_nif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_DIRTY_CPU&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;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Совет&lt;/strong&gt;: Используйте &lt;code&gt;ERL_NIF_DIRTY_CPU&lt;/code&gt; для CPU-bound операций и &lt;code&gt;ERL_NIF_DIRTY_IO&lt;/code&gt; для операций ввода/вывода&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔌 Ports — полная изоляция
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ports&lt;/strong&gt; — способ для взаимодействия с внешними программами через стандартные потоки ввода-вывода (stdin/stdout). Это самый безопасный способ интеграции, так как внешняя программа запускается в отдельном процессе ОС.&lt;/p&gt;

&lt;h4&gt;
  
  
  Как работают Ports?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Запуск&lt;/strong&gt;: Elixir запускает внешнюю программу как отдельный OS-процесс&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Обмен данными&lt;/strong&gt;: Коммуникация через стандартные потоки (stdin/stdout)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Изоляция&lt;/strong&gt;: Падение внешней программы не влияет на BEAM&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  ✅ Преимущества
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Полная безопасность&lt;/strong&gt;: Изоляция гарантирует стабильность BEAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Языковая агностичность&lt;/strong&gt;: Работает с любым языком программирования&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Простота отладки&lt;/strong&gt;: Внешнюю программу можно тестировать отдельно&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Отсутствие зависимостей&lt;/strong&gt;: Не требует специфичных для BEAM библиотек&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ❌ Недостатки
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Высокие накладные расходы&lt;/strong&gt;: ~100-500 μs на вызов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Сериализация&lt;/strong&gt;: Требуется преобразование данных (обычно в JSON)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Блокирующие вызовы&lt;/strong&gt;: По умолчанию блокирует вызывающий процесс&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🚗 Port Drivers — золотая середина
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Port Drivers&lt;/strong&gt; — производительная альтернатива Ports, но более сложная. Это драйверы на языке C, встроенные непосредственно в адресное пространство BEAM и работающие в отдельных потоках.&lt;/p&gt;

&lt;h4&gt;
  
  
  Как работают Port Drivers?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Загрузка&lt;/strong&gt;: BEAM загружает C-библиотеку в свое адресное пространство&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Выделение потока&lt;/strong&gt;: Драйвер работает в отдельном потоке&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Асинхронность&lt;/strong&gt;: Обмен данными через очередь сообщений&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  ✅ Преимущества
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Скорость&lt;/strong&gt;: Значительно быстрее обычных портов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Безопасность&lt;/strong&gt;: Меньший риск чем у NIF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Асинхронность&lt;/strong&gt;: Поддержка неблокирующих операций&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Удобство&lt;/strong&gt;: Не требует запуска отдельного процесса&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ❌ Недостатки
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Сложность&lt;/strong&gt;: Требует знания C API Erlang&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ограниченность&lt;/strong&gt;: Работает только с C/C++&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Меньшая документация&lt;/strong&gt;: Не так много примеров и руководств&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🐊 &lt;a href="https://github.com/E-xyza/zigler" rel="noopener noreferrer"&gt;Zigler&lt;/a&gt; - Обёртка над NIFs для Zig
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Zigler&lt;/strong&gt; — Библиотека, позволяющая писать нативные расширения на языке &lt;strong&gt;Zig&lt;/strong&gt;. Встраивает компилятор &lt;strong&gt;Zig&lt;/strong&gt; прямо в цикл компиляции &lt;strong&gt;Elixir&lt;/strong&gt; и позволяет напрямую писать код на &lt;strong&gt;Zig&lt;/strong&gt; в модулях &lt;strong&gt;Elixir&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Преимущества
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Минимальные накладные расходы на вызов нативного кода&lt;/li&gt;
&lt;li&gt;Безопасность памяти без сборщика мусора&lt;/li&gt;
&lt;li&gt;Прямой доступ к низкоуровневым операциям&lt;/li&gt;
&lt;li&gt;Более простая компиляция в сравнении с другими нативными расширениями&lt;/li&gt;
&lt;li&gt;Поддержка горячей перезагрузки кода&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Недостатки
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zig&lt;/strong&gt; — относительно молодой язык с меньшим сообществом&lt;/li&gt;
&lt;li&gt;Более высокий порог входа для разработчиков &lt;strong&gt;Elixir&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Ограниченная экосистема библиотек в сравнении с &lt;strong&gt;Rust&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/rusterlium/rustler" rel="noopener noreferrer"&gt;Rustler&lt;/a&gt; - Обёртка над NIFs для Rust
&lt;/h2&gt;

&lt;p&gt;Rustler — это библиотека для создания нативных расширений Erlang/Elixir на языке Rust. Обеспечивает безопасный биндинг между Rust и Erlang/Elixir, позволяя писать NIFs на Rust.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Преимущества
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Безопасность памяти на уровне компиляции&lt;/li&gt;
&lt;li&gt;Высокая производительность для вычислительно сложных задач&lt;/li&gt;
&lt;li&gt;Богатая экосистема пакетов Rust (crates)&lt;/li&gt;
&lt;li&gt;Защита от сбоев в нативном коде (защита BEAM от падения)&lt;/li&gt;
&lt;li&gt;Параллельное выполнение без блокировки планировщика BEAM&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Недостатки
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Усложненный процесс сборки и зависимостей&lt;/li&gt;
&lt;li&gt;Требует знания двух различных парадигм программирования&lt;/li&gt;
&lt;li&gt;Возможные проблемы с совместимостью версий&lt;/li&gt;
&lt;li&gt;Потенциальные узкие места на границе сред выполнения&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🌐 gRPC и другие протоколы
&lt;/h3&gt;

&lt;p&gt;Для более сложных сценариев взаимодействия с внешними сервисами, особенно в микросервисной архитектуре, gRPC и подобные протоколы предоставляют структурированный и масштабируемый способ интеграции.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ Преимущества gRPC для Elixir
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Схема контрактов&lt;/strong&gt;: Строгие типы через Protocol Buffers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Двунаправленный стриминг&lt;/strong&gt;: Поддержка потоковой передачи в обе стороны&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Кросс-платформенность&lt;/strong&gt;: Поддержка множества языков&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Производительность&lt;/strong&gt;: Более эффективен чем REST/JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;❗️Пример с &lt;strong&gt;gRPC&lt;/strong&gt; был слишком объёмен, чтобы рассмотреть его в рамках этой статьи, из-за чего он не был включён в неё. Подробнее о gRPC на Elixir можно почитать вот тут -  &lt;a href="https://github.com/elixir-grpc/grpc?ysclid=max94g2mno544469162" rel="noopener noreferrer"&gt;elixir-grpc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  🧪 Практические примеры интеграции
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;📚 &lt;em&gt;Цель статьи — дать обзор доступных способов интеграции с нативным кодом. Глубокие реализации и edge-кейсы здесь опущены, чтобы сохранить баланс между теорией и применением.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🔍 Критерии выбора метода интеграции
&lt;/h2&gt;

&lt;p&gt;Прежде чем перейти к примерам, определим ключевые факторы выбора:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Производительность&lt;/strong&gt;: Насколько быстро работает вызов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Безопасность&lt;/strong&gt;: Риск для стабильности BEAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Сложность реализации&lt;/strong&gt;: Легко ли внедрить решение&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Поддержка языка&lt;/strong&gt;: Насколько хорошо язык работает с BEAM&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. ⚙️ C — максимальная производительность с NIF и Port Drivers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Оптимальные методы&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NIF&lt;/strong&gt; — для мгновенных операций (&amp;lt;1ms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port Drivers&lt;/strong&gt; — для долгих или асинхронных задач&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Почему именно так?
&lt;/h3&gt;

&lt;p&gt;C имеет прямую совместимость с BEAM, что делает его идеальным для:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Критически важных по производительности задач&lt;/li&gt;
&lt;li&gt;Низкоуровневых операций (работа с железом, GPU)&lt;/li&gt;
&lt;li&gt;Интеграции с существующими C-библиотеками&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Пример 1: Быстрый NIF для хеширования (оптимально для C)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hash_nif.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;erl_nif.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/sha.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="nf"&gt;sha256_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlNifEnv&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ErlNifBinary&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;enif_inspect_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&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="n"&gt;enif_make_badarg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;ErlNifBinary&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;enif_alloc_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SHA256_DIGEST_LENGTH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enif_make_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"sha256"&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="n"&gt;sha256_nif&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;ERL_NIF_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Elixir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CryptoNif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&lt;/span&gt;&lt;span class="p"&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;NULL&lt;/span&gt;&lt;span class="p"&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;NULL&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;Elixir часть&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;CryptoNif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@on_load&lt;/span&gt; &lt;span class="ss"&gt;:load_nif&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;load_nif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./hash_nif"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;sha256&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="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"NIF not loaded!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Компиляция C-исходника&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Для запуска данного примера вам нужна &lt;strong&gt;openssl&lt;/strong&gt; библиотека&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Для Ubuntu/Debian&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libssl-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Для CentOS/RHEL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;openssl-devel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Для macOS (если используете Homebrew)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; hash_nif.so hash_nif.c &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; /usr/lib/erlang/erts-15.2.7/include &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Путь до Erlang зависит от вашей системы&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; /usr/include/openssl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-L&lt;/span&gt; /usr/lib/openssl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-lssl&lt;/span&gt; &lt;span class="nt"&gt;-lcrypto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;CryptoNif&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;208&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;154&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;208&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;163&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;43&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="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;209&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;93&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Пример 2: Port Driver для реверса строки
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// reverse_driver.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"erl_driver.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ErlDrvPort&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;reverse_and_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ErlDrvSizeT&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvSizeT&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&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="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buf&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;buf&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;driver_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="nf"&gt;driver_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvPort&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;driver_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;driver_stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlDrvData&lt;/span&gt; &lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverData&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;drv_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;driver_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlDrvEntry&lt;/span&gt; &lt;span class="n"&gt;driver_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver_stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reverse_and_send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"reverse_driver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready_async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extended_marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MARKER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;major_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MAJOR_VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minor_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ERL_DRV_EXTENDED_MINOR_VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver_flags&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="n"&gt;DRIVER_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverse_driver&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;driver_entry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Elixir часть&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;ReverseString&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:erl_ddll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_driver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'reverse_driver'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'reverse_driver'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:data&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="k"&gt;after&lt;/span&gt;
      &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Компиляция C-исходника&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gnu99 &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; reverse_driver.so reverse_driver.c &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/lib/erlang/erts-15.2.7/include/ &lt;span class="c"&gt;# Путь до Erlang зависит от вашей системы&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; port &lt;span class="o"&gt;=&lt;/span&gt; ReverseString.start
&lt;span class="c"&gt;#Port&amp;lt;0.6&amp;gt;&lt;/span&gt;
iex&lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; ReverseString.reverse&lt;span class="o"&gt;(&lt;/span&gt;port, &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"olleh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. 🦀 Rust — безопасность и производительность с Rustler
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Оптимальный метод&lt;/strong&gt;: Rustler (специализированная обёртка над NIF)&lt;/p&gt;

&lt;h3&gt;
  
  
  Почему Rustler?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Полная безопасность памяти&lt;/li&gt;
&lt;li&gt;Удобные макросы для работы с BEAM терминами&lt;/li&gt;
&lt;li&gt;Автоматическая обработка ошибок&lt;/li&gt;
&lt;li&gt;Поддержка асинхронных задач&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Пример: Параллельная обработка данных
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Добавляем в mix.exe &lt;code&gt;Rustler&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;(На данный момент актуальная версия - 0.36.1)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:rustler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.36.1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Добавляем Rust-проект в Elixir&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix deps.get
mix rustler.new

This is the name of the Elixir module the NIF module will be registered to.
Module name &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; RustUtils
This is the name used &lt;span class="k"&gt;for &lt;/span&gt;the generated Rust crate. The default is most likely fine.
Library name &lt;span class="o"&gt;(&lt;/span&gt;rustutils&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;# Тут просто нажимаем Enter (Ну или переименуйте на более удобное название)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rayon&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[rustler::nif]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parallel_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i64&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;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.par_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="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="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;rustler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;init!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Elixir.RustUtils"&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;Elixir часть&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;RustUtils&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rustler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:rust_utils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;crate:&lt;/span&gt; &lt;span class="s2"&gt;"rustutils"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parallel_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nif_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:not_loaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;RustUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parallel_double&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="c1"&gt;# =&amp;gt; [2, 4, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. 🐍 Python — простота интеграции через Ports
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Оптимальный метод&lt;/strong&gt;: Ports&lt;/p&gt;

&lt;h3&gt;
  
  
  Почему Ports?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Полная изоляция процессов&lt;/li&gt;
&lt;li&gt;Простота отладки&lt;/li&gt;
&lt;li&gt;Доступ ко всему Python-экосистеме&lt;/li&gt;
&lt;li&gt;Поддержка долгих операций (ML модели и т.д.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Пример: Создание своей модели и интеграция с TensorFlow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Создаём модель&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="c1"&gt;# create_model.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&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="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; &lt;span class="n"&gt;use_bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_weights&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;]])])&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ Model saved to my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;"&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 python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#tensorflow_port
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TF_CPP_MIN_LOG_LEVEL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_model.h5&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict&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="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&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;input_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&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;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reshape&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;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&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;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&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;Elixir часть&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@timeout&lt;/span&gt; &lt;span class="mi"&gt;5_000&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"python3 tensorflow_port.py"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:use_stdio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:exit_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:stderr_to_stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;input_data&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:eol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Jason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"result"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&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="ss"&gt;:ok&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wait_for_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:exit_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Python process exited with status &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;after&lt;/span&gt;
      &lt;span class="nv"&gt;@timeout&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Для работы программы нужно будет зайти в Python-окружение и оттуда запустить &lt;code&gt;iex -S mix&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.10&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;TensorflowPort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. 🐹 Go — эффективность через C-обёртки или gRPC
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Оптимальные методы&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C-обёртки для NIF — когда нужна максимальная производительность&lt;/li&gt;
&lt;li&gt;gRPC — для сложных взаимодействий и микросервисов&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  C-обёртка для Go кода (оптимально для производительности)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// fib.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&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="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&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;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="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="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="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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C-обёртка&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// c_src/go_nif.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;erl_nif.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"libfib.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="nf"&gt;go_fib_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ErlNifEnv&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ERL_NIF_TERM&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;enif_get_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enif_make_badarg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&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="n"&gt;enif_make_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ErlNifFunc&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"go_fib"&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="n"&gt;go_fib_nif&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;ERL_NIF_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Elixir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NifGo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nif_funcs&lt;/span&gt;&lt;span class="p"&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;NULL&lt;/span&gt;&lt;span class="p"&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;NULL&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;Elixir часть&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;NifGo&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@on_load&lt;/span&gt; &lt;span class="ss"&gt;:load_nif&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;load_nif&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;nif_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"priv/go_nif"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd!&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Предварительная загрузка Go-библиотеки&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"priv/libfib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd!&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Загрузка основной NIF-библиотеки&lt;/span&gt;
    &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_nif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nif_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;go_fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_n&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"NIF not loaded!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build &lt;span class="nt"&gt;-buildmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c-shared &lt;span class="nt"&gt;-o&lt;/span&gt; priv/libfib.so fib.go

gcc &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/lib/erlang/erts-15.2.7/include/ &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Путь до Erlang зависит от вашей системы&lt;/span&gt;
    &lt;span class="nt"&gt;-I&lt;/span&gt;./priv &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; priv/go_nif.so &lt;span class="se"&gt;\&lt;/span&gt;
    c_src/go_nif.c &lt;span class="se"&gt;\&lt;/span&gt;
    ./priv/libfib.so &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-Wl&lt;/span&gt;,-rpath,&lt;span class="s1"&gt;'$ORIGIN'&lt;/span&gt;

&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./priv iex &lt;span class="nt"&gt;-S&lt;/span&gt; mix

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; NifGo.go_fib&lt;span class="o"&gt;(&lt;/span&gt;3&lt;span class="o"&gt;)&lt;/span&gt;
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;em&gt;Если вам не хочется возиться с компиляцией и ABI, можно использовать gRPC или Ports вместо cgo. Это безопаснее, хоть и медленнее.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. ⚡ Zig — Интеграция через Zigler
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Оптимальный метод&lt;/strong&gt;: Zigler (специализированная обёртка для Zig)&lt;/p&gt;

&lt;h3&gt;
  
  
  Почему Zigler?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Простота как у Rustler&lt;/li&gt;
&lt;li&gt;Производительность как у C&lt;/li&gt;
&lt;li&gt;Современные фичи языка (comptime, etc.)&lt;/li&gt;
&lt;li&gt;Безопаснее чистого C&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Пример: Быстрая обработка бинарных данных
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Добавьте Zigler в mix.exe:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:zigler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.13.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;runtime:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;lib/nif_zig.ex&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Zig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:zigler&lt;/span&gt;

  &lt;span class="sx"&gt;~Z""&lt;/span&gt;&lt;span class="s2"&gt;"
  pub fn string_count(string: []u8) i64 {
    return @intCast(string.len);
  }

  pub fn list_sum(array: []f64) f64 {
    var sum: f64 = 0.0;
    for(array) | item | {
      sum += item;
    }
    return sum;
  }
  """&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Результат:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;NifZig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="mf"&gt;11.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📊 Сводная таблица оптимальных методов
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Язык&lt;/th&gt;
&lt;th&gt;Оптимальный метод&lt;/th&gt;
&lt;th&gt;Альтернативы&lt;/th&gt;
&lt;th&gt;Когда использовать&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NIF, Port Drivers&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;Максимальная производительность&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rustler (NIF)&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;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;gRPC&lt;/td&gt;
&lt;td&gt;Интеграция с ML/научными библиотеками&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C-обёртки (NIF), gRPC&lt;/td&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;Использование Go-экосистемы&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zig&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Zigler (NIF)&lt;/td&gt;
&lt;td&gt;-&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;
  
  
  😴 Заключение
&lt;/h2&gt;

&lt;p&gt;Интеграция Elixir с нативным кодом открывает новые горизонты для разработчиков, позволяя сочетать преимущества BEAM (масштабируемость, отказоустойчивость) с производительностью и библиотеками других языков. В статье мы рассмотрели ключевые методы интеграции: NIF, Dirty NIF, Ports, Port Drivers, Rustler, Zigler и gRPC, а также их оптимальные сценарии использования.&lt;/p&gt;

&lt;p&gt;Помните, что выбор метода интеграции должен основываться на конкретных требованиях вашего проекта к производительности, безопасности и простоте разработки.&lt;/p&gt;




&lt;h2&gt;
  
  
  От автора
&lt;/h2&gt;

&lt;p&gt;Благодарю вас за внимание к данной статье! Надеюсь, вам было интересно узнать про способы интеграции других языков в Elixir. Из всех вариантов мне показался наиболее сложным Port Drivers, потому что создание одного такого драйвера само по себе превращается в настоящий квест, успешно завершённый лишь после нескольких часов подбора подходящих методов на C. В остальном, интеграция других языков в Elixir оказалась вовсе несложной, скорее даже увлекательной.&lt;/p&gt;

&lt;p&gt;Если вы обнаружили неточности в материале или у вас есть интересные дополнения — пожалуйста, напишите об этом в комментариях. Конструктивная обратная связь всегда ценна 😎&lt;/p&gt;

&lt;p&gt;Для тех, кому интересно глубже погрузиться в мир технологий, архитектуры и разработки, приглашаю заглянуть в мой &lt;a href="https://t.me/devs_inc" rel="noopener noreferrer"&gt;телеграм-канал&lt;/a&gt; 🖥, где я делюсь рецензиями на технические книги, полезными материалами по Elixir и не только 🤤&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>nif</category>
      <category>programming</category>
    </item>
    <item>
      <title>Elixir for Machine Learning. Part 1 - Theory</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Wed, 02 Apr 2025 14:52:26 +0000</pubDate>
      <link>https://forem.com/adamanq/elixir-for-machine-learning-part-1-theory-3g0h</link>
      <guid>https://forem.com/adamanq/elixir-for-machine-learning-part-1-theory-3g0h</guid>
      <description>&lt;p&gt;In recent times, the role of artificial intelligence in various fields has been gaining momentum. Many companies are already implementing AI to assist users on their portals, while others are developing their own neural networks to solve specialized tasks&lt;/p&gt;

&lt;p&gt;While Python dominates the ML landscape, Elixir finds its niche in specific areas: real-time data processing systems (Bumblebee), model inference services (Nx.Serving), and distributed machine learning systems. Companies such as &lt;strong&gt;&lt;a href="https://dockyard.com" rel="noopener noreferrer"&gt;DockYard&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://dashbit.co" rel="noopener noreferrer"&gt;Dashbit&lt;/a&gt;&lt;/strong&gt; have successfully implemented ML solutions using Elixir in industrial environments&lt;/p&gt;

&lt;p&gt;This article is divided into two parts — Theory and Practice. In the first part, we will explore the basics of machine learning, familiarize ourselves with key concepts, and learn about libraries that help create neural networks using Elixir&lt;/p&gt;



&lt;h2&gt;
  
  
  What Are Machine Learning and Neural Networks?
&lt;/h2&gt;

&lt;p&gt;Machine Learning (ML) is an approach to creating systems that can learn from data and improve performance over time without explicit programming. Instead of writing specific instructions to solve a task, we build models that adapt and "learn" based on experience.&lt;/p&gt;

&lt;p&gt;Neural networks are one of the most popular methods in machine learning, inspired by how the human brain works. They consist of interconnected nodes (neurons), organized into layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The input layer receives raw data (e.g., image pixels)&lt;/li&gt;
&lt;li&gt;Hidden layers process information, identifying increasingly complex patterns&lt;/li&gt;
&lt;li&gt;The output layer provides the final result (e.g., object classification)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each neuron takes input signals, processes them by applying an activation function to the weighted sum of inputs, and passes the result along the network. Connections between neurons carry weight coefficients that determine signal importance.&lt;/p&gt;

&lt;p&gt;The training process involves adjusting these weights so that the network produces accurate results. This happens through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feeding many training examples&lt;/li&gt;
&lt;li&gt;Calculating the error between the network's predictions and actual values&lt;/li&gt;
&lt;li&gt;Adjusting weights to minimize this error using the &lt;a href="https://en.wikipedia.org/wiki/Backpropagation" rel="noopener noreferrer"&gt;backpropagation algorithm&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Key Concepts in Machine Learning
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Models and Their Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model&lt;/strong&gt; — a mathematical or algorithmic construct that learns from data to perform a specific task. Models come in various types:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linear models&lt;/strong&gt;: Relatively simple models that assume a linear relationship between input and output data. Examples: &lt;a href="https://en.wikipedia.org/wiki/Linear_regression" rel="noopener noreferrer"&gt;linear regression&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Logistic_regression" rel="noopener noreferrer"&gt;logistic regression&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neural networks&lt;/strong&gt;: Multi-layered models capable of identifying complex nonlinear dependencies. Used in computer vision, natural language processing, and other complex problems
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensemble models&lt;/strong&gt;: Combinations of multiple models to produce more accurate results. Examples: &lt;a href="https://en.wikipedia.org/wiki/Random_forest" rel="noopener noreferrer"&gt;random forests&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Gradient_boosting" rel="noopener noreferrer"&gt;gradient boosting&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Tensors and Their Role in ML
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tensor&lt;/strong&gt; — a generalization of &lt;a href="https://en.wikipedia.org/wiki/Scalar_(mathematics)" rel="noopener noreferrer"&gt;scalars&lt;/a&gt;, vectors, and matrices to multi-dimensional data arrays. Tensors are fundamental data structures in modern machine learning systems:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalar&lt;/strong&gt;: Rank-0 tensor (0-D). Example: the number 5
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector&lt;/strong&gt;: Rank-1 tensor (1-D). Example: [1, 2, 3]
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Matrix&lt;/strong&gt;: Rank-2 tensor (2-D). Example: [[1, 2, 3], [4, 5, 6]]
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-dimensional tensor&lt;/strong&gt;: Rank-3+ tensor (3-D and higher). Example: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tensors are used to represent and process various types of data in &lt;strong&gt;ML&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images &lt;em&gt;(4D tensors: [batch_size, height, width, channels])&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Text &lt;em&gt;(sequences of vectors representing words or tokens)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Time series &lt;em&gt;(sequences of observations over time)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Learning Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Learning&lt;/strong&gt; — the process by which a model adjusts its parameters based on data:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Supervised Learning&lt;/strong&gt;: The model learns from labeled data where the correct answer is known for each input example. Example tasks: image classification, price prediction, speech recognition
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unsupervised Learning&lt;/strong&gt;: The model learns from unlabeled data, uncovering hidden structures and patterns. Example tasks: &lt;a href="https://en.wikipedia.org/wiki/Cluster_analysis" rel="noopener noreferrer"&gt;clustering&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Dimensionality_reduction" rel="noopener noreferrer"&gt;dimensionality reduction&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Anomaly_detection" rel="noopener noreferrer"&gt;anomaly detection&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reinforcement Learning&lt;/strong&gt;: The model learns by interacting with an environment, receiving rewards or penalties for its actions. Applied in robotics, gaming, autonomous systems
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Hyperparameters and Their Tuning
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hyperparameters&lt;/strong&gt; — model settings defined before training and not altered during the process:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architectural hyperparameters&lt;/strong&gt;: Number of layers in a neural network, number of neurons per layer, types of activation functions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization parameters&lt;/strong&gt;: Learning rate, batch size, number of training epochs
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regularization parameters&lt;/strong&gt;: L1/L2 regularization coefficients, dropout rate to prevent overfitting
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hyperparameter tuning is typically done using methods like &lt;strong&gt;grid search&lt;/strong&gt;, &lt;strong&gt;random search&lt;/strong&gt;, or &lt;strong&gt;Bayesian optimization&lt;/strong&gt;.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Model Evaluation Metrics
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt; — quantitative measures used to assess model performance:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For classification tasks&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy&lt;/strong&gt;: Proportion of correct predictions among all predictions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precision &amp;amp; Recall&lt;/strong&gt;: Metrics reflecting the balance between false positives and false negatives
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;F1-score&lt;/strong&gt;: Harmonic mean of precision and recall
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROC-AUC&lt;/strong&gt;: Area under the &lt;a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" rel="noopener noreferrer"&gt;ROC curve&lt;/a&gt;, indicating the model's ability to distinguish classes
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For regression tasks&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mean squared error (MSE)&lt;/strong&gt;: Average of squared differences between predicted and actual values
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean absolute error (MAE)&lt;/strong&gt;: Average of absolute differences between predicted and actual values
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coefficient of determination (R²)&lt;/strong&gt;: Measures how well the model explains data variation
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The choice of metric depends on the specific task and business context. For instance, in medical diagnostics, minimizing false negatives is critical, while in recommender systems, the quality of top recommendations may be more important.  &lt;/p&gt;

&lt;p&gt;Now that we’ve covered the key concepts of machine learning, let’s move on to the tools that enable their application in the &lt;strong&gt;Elixir&lt;/strong&gt; ecosystem.  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Elixir&lt;/strong&gt; Tools for Machine Learning
&lt;/h2&gt;

&lt;p&gt;The machine learning ecosystem in &lt;strong&gt;Elixir&lt;/strong&gt; is rapidly evolving, offering increasingly powerful and developer-friendly tools. Let’s explore the key libraries that enable &lt;strong&gt;ML&lt;/strong&gt; on the &lt;strong&gt;BEAM&lt;/strong&gt; platform.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx" rel="noopener noreferrer"&gt;Numerical Elixir&lt;/a&gt; (Nx): The Foundation for Computation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/elixir-nx/nx" rel="noopener noreferrer"&gt;&lt;strong&gt;Nx&lt;/strong&gt;&lt;/a&gt; is the backbone of &lt;strong&gt;Elixir&lt;/strong&gt;'s ML ecosystem, developed by the &lt;strong&gt;Dashbit&lt;/strong&gt; team under the leadership of José Valim (the creator of &lt;strong&gt;Elixir&lt;/strong&gt;). This library provides high-performance numerical computing and support for multi-dimensional tensors, which are critical for machine learning.&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Features of Nx:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tensor operations&lt;/strong&gt;: A comprehensive set of functions for manipulating multi-dimensional data arrays.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numerical stability&lt;/strong&gt;: High-precision computations with error control.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computation compilation&lt;/strong&gt;: Transforms &lt;strong&gt;Elixir&lt;/strong&gt; code into optimized machine code.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic differentiation&lt;/strong&gt;: Essential for backpropagation algorithms.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A particularly powerful feature of &lt;strong&gt;Nx&lt;/strong&gt; is the &lt;code&gt;defn&lt;/code&gt; system (definable numerical functions), which compiles computations into efficient low-level code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MathOps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Defn&lt;/span&gt;  

  &lt;span class="n"&gt;defn&lt;/span&gt; &lt;span class="n"&gt;multiply_and_add&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;do&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;  
  &lt;span class="k"&gt;end&lt;/span&gt;  
&lt;span class="k"&gt;end&lt;/span&gt;  

&lt;span class="c1"&gt;# Usage  &lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&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="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
&lt;span class="no"&gt;MathOps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multiply_and_add&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="c1"&gt;# Result: Nx.tensor([11, 18, 27])  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Supported Nx Backends:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Nx&lt;/strong&gt; operates via a backend system that determines where and how computations are executed:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EXLA&lt;/strong&gt;: Integration with &lt;a href="https://openxla.org/xla" rel="noopener noreferrer"&gt;&lt;strong&gt;XLA&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;(Accelerated Linear Algebra)&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; from &lt;strong&gt;Google&lt;/strong&gt;, enabling compilation for &lt;strong&gt;CPU&lt;/strong&gt;, &lt;strong&gt;GPU&lt;/strong&gt;, and &lt;strong&gt;TPU&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Torchx&lt;/strong&gt;: Connection to &lt;a href="https://pytorch.org" rel="noopener noreferrer"&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/a&gt;, leveraging its optimized &lt;a href="https://en.wikipedia.org/wiki/CUDA" rel="noopener noreferrer"&gt;&lt;strong&gt;CUDA&lt;/strong&gt;&lt;/a&gt; operations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ONNX&lt;/strong&gt;: Support for &lt;a href="https://onnx.ai" rel="noopener noreferrer"&gt;&lt;strong&gt;Open Neural Network Exchange&lt;/strong&gt;&lt;/a&gt; for compatibility with a wide range of models.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BinaryBackend&lt;/strong&gt;: Native &lt;strong&gt;Elixir&lt;/strong&gt; implementation with no external dependencies.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backend selection depends on the task and available hardware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Global use of EXLA backend  &lt;/span&gt;
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;global_default_backend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Using PyTorch for a specific operation  &lt;/span&gt;
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backend_transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Torchx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;device:&lt;/span&gt; &lt;span class="ss"&gt;:cuda&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/axon" rel="noopener noreferrer"&gt;Axon&lt;/a&gt;: Neural Networks with a Functional Approach
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Axon&lt;/strong&gt; is a high-level framework for defining, training, and evaluating neural networks, built on top of &lt;strong&gt;Nx&lt;/strong&gt;. Its standout feature is its functional design, which aligns perfectly with &lt;strong&gt;Elixir&lt;/strong&gt;'s philosophy.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Features of Axon:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative model definition&lt;/strong&gt;: A clear pipeline approach to architecture design.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in optimizers&lt;/strong&gt;: Implementations of &lt;a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#Adam" rel="noopener noreferrer"&gt;&lt;strong&gt;Adam&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent" rel="noopener noreferrer"&gt;&lt;strong&gt;SGD&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#RMSProp" rel="noopener noreferrer"&gt;&lt;strong&gt;RMSProp&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loss functions&lt;/strong&gt;: A wide range for various tasks (e.g., &lt;a href="https://en.wikipedia.org/wiki/Mean_squared_error" rel="noopener noreferrer"&gt;&lt;strong&gt;MSE&lt;/strong&gt;&lt;/a&gt;, cross-entropy).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Training management&lt;/strong&gt;: Tools for early stopping, validation, and callbacks.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of creating and training a classification model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model definition  &lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

&lt;span class="c1"&gt;# Compilation and training  &lt;/span&gt;
&lt;span class="n"&gt;trained_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="n"&gt;model&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:categorical_cross_entropy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:adam&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compiler:&lt;/span&gt; &lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Advanced Capabilities of Axon:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Axon&lt;/strong&gt; supports a wide range of layers and architectures:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Convolutional layers&lt;/strong&gt;: For computer vision tasks (&lt;code&gt;Axon.conv&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recurrent networks&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Long_short-term_memory" rel="noopener noreferrer"&gt;&lt;strong&gt;LSTM&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Gated_recurrent_unit" rel="noopener noreferrer"&gt;&lt;strong&gt;GRU&lt;/strong&gt;&lt;/a&gt; for sequential data.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformers&lt;/strong&gt;: Attention mechanisms for &lt;a href="https://en.wikipedia.org/wiki/Natural_language_processing" rel="noopener noreferrer"&gt;&lt;strong&gt;NLP&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Batch_normalization" rel="noopener noreferrer"&gt;&lt;strong&gt;BatchNorm&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Layer_normalization" rel="noopener noreferrer"&gt;&lt;strong&gt;LayerNorm&lt;/strong&gt;&lt;/a&gt; for training stability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regularization&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Dropout_(neural_networks)" rel="noopener noreferrer"&gt;&lt;strong&gt;Dropout&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Regularization_(mathematics)" rel="noopener noreferrer"&gt;&lt;strong&gt;L1/L2&lt;/strong&gt;&lt;/a&gt; to combat overfitting.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of a convolutional network for image classification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&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;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_size:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;padding:&lt;/span&gt; &lt;span class="ss"&gt;:same&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;kernel_size:&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;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_size:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;padding:&lt;/span&gt; &lt;span class="ss"&gt;:same&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;kernel_size:&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;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-explorer/explorer" rel="noopener noreferrer"&gt;Explorer&lt;/a&gt;: Data Processing and Preparation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Explorer&lt;/strong&gt; is a library for working with tabular data, inspired by &lt;strong&gt;Python&lt;/strong&gt;'s &lt;a href="https://pandas.pydata.org" rel="noopener noreferrer"&gt;&lt;strong&gt;Pandas&lt;/strong&gt;&lt;/a&gt;. It integrates seamlessly with &lt;strong&gt;Nx&lt;/strong&gt;, enabling easy conversion of data into tensors.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Key Features of Explorer:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DataFrame API&lt;/strong&gt;: Powerful interface for data manipulation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtering and grouping&lt;/strong&gt;: Efficient handling of large datasets.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loading/saving&lt;/strong&gt;: Support for &lt;strong&gt;CSV&lt;/strong&gt;, &lt;strong&gt;Parquet&lt;/strong&gt;, &lt;strong&gt;JSON&lt;/strong&gt;, and other formats.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization&lt;/strong&gt;: Integration with &lt;a href="https://vega.github.io/vega-lite/examples/" rel="noopener noreferrer"&gt;&lt;strong&gt;Vega-Lite&lt;/strong&gt;&lt;/a&gt; for charting.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of data processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Loading and processing data  &lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_csv!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"titanic.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"survived"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"fare"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;fare_category:&lt;/span&gt; &lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  
    &lt;span class="k"&gt;cond&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
      &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"low"&lt;/span&gt;  
      &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"medium"&lt;/span&gt;  
      &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"high"&lt;/span&gt;  
    &lt;span class="k"&gt;end&lt;/span&gt;  
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  

&lt;span class="c1"&gt;#### Converting to Tensors for ML  &lt;/span&gt;
&lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_nx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"fare"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
&lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_nx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"survived"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/bumblebee" rel="noopener noreferrer"&gt;Bumblebee&lt;/a&gt;: Pre-trained Models for Practical Use
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bumblebee&lt;/strong&gt; provides pre-trained models and tools for deploying them, simplifying the use of state-of-the-art models without training from scratch.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Key Features:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-trained models&lt;/strong&gt;: &lt;a href="https://huggingface.co/docs/transformers/model_doc/bert" rel="noopener noreferrer"&gt;&lt;strong&gt;BERT&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://huggingface.co/openai-community/gpt2" rel="noopener noreferrer"&gt;&lt;strong&gt;GPT-2&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://pytorch.org/vision/stable/models/resnet.html" rel="noopener noreferrer"&gt;&lt;strong&gt;ResNet&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://huggingface.co/docs/transformers/model_doc/clip" rel="noopener noreferrer"&gt;&lt;strong&gt;CLIP&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://dockyard.com/blog/2022/12/15/stable-diffusion-with-bumblebee" rel="noopener noreferrer"&gt;&lt;strong&gt;Stable Diffusion&lt;/strong&gt;&lt;/a&gt;, and more.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in pipelines&lt;/strong&gt;: Ready-made solutions for common tasks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hugging Face integration&lt;/strong&gt;: Access to thousands of models.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized inference&lt;/strong&gt;: Efficient execution on various hardware.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example for sentiment analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"distilbert-base-uncased-finetuned-sst-2-english"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_tokenizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"distilbert-base-uncased"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  

&lt;span class="n"&gt;serving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  

&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I love Elixir, it's an amazing language!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="c1"&gt;# =&amp;gt; %{predictions: [%{label: "POSITIVE", score: 0.998}]}  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://hexdocs.pm/nx/Nx.Serving.html" rel="noopener noreferrer"&gt;Nx.Serving&lt;/a&gt;: Deploying Models in Production
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nx.Serving&lt;/strong&gt; is a tool for efficiently deploying &lt;strong&gt;ML&lt;/strong&gt; models as services. It offers:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request batching&lt;/strong&gt;: Automatic grouping for efficient execution.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queues and priorities&lt;/strong&gt;: Workload management and resource allocation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot swapping&lt;/strong&gt;: Model updates without downtime.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Performance and resource usage tracking.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of an image classification service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;model_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"microsoft/resnet-50"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
&lt;span class="n"&gt;featurizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_featurizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"microsoft/resnet-50"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  

&lt;span class="n"&gt;serving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Vision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_classification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="n"&gt;featurizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;# Dynamic batching  &lt;/span&gt;
    &lt;span class="ss"&gt;defn_options:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;compiler:&lt;/span&gt; &lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# GPU acceleration  &lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Running as an OTP process  &lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;ImageClassifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Usage  &lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cat.jpg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batched_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ImageClassifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://livebook.dev" rel="noopener noreferrer"&gt;LiveBook&lt;/a&gt;: Interactive Development and Experimentation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LiveBook&lt;/strong&gt; is an interactive environment for developing and documenting &lt;strong&gt;Elixir&lt;/strong&gt; code, ideal for &lt;strong&gt;ML&lt;/strong&gt; experiments. It provides:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jupyter-like interface&lt;/strong&gt;: Interactive code cells.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in visualization&lt;/strong&gt;: Charts, graphs, tables.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with ML libraries&lt;/strong&gt;: Special widgets for &lt;strong&gt;Nx&lt;/strong&gt;, &lt;strong&gt;Axon&lt;/strong&gt;, &lt;strong&gt;Explorer&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt;: Share and collaborate on notebooks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU execution&lt;/strong&gt;: Hardware acceleration support.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LiveBook&lt;/strong&gt; simplifies learning, experimentation, and documentation for &lt;strong&gt;Elixir&lt;/strong&gt; &lt;strong&gt;ML&lt;/strong&gt; projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example LiveBook cell  &lt;/span&gt;
&lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;  
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:axon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:explorer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:kino&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.8"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;])&lt;/span&gt;  

&lt;span class="c1"&gt;### Interactive hyperparameter input  &lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Control&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="p"&gt;[&lt;/span&gt;  
    &lt;span class="ss"&gt;learning_rate:&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Learning rate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="s2"&gt;"0.001"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
    &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="ss"&gt;submit:&lt;/span&gt; &lt;span class="s2"&gt;"Train model"&lt;/span&gt;  
&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/scholar" rel="noopener noreferrer"&gt;Scholar&lt;/a&gt;: Traditional Machine Learning Algorithms
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scholar&lt;/strong&gt; extends the &lt;strong&gt;Elixir ML&lt;/strong&gt; ecosystem with classical algorithms, often better suited for certain tasks than deep learning:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linear models&lt;/strong&gt;: Regression, &lt;a href="https://en.wikipedia.org/wiki/Support_vector_machine" rel="noopener noreferrer"&gt;&lt;strong&gt;SVM&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Logistic_regression" rel="noopener noreferrer"&gt;logistic regression&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision trees&lt;/strong&gt;: Single trees and ensembles.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clustering&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/K-means_clustering" rel="noopener noreferrer"&gt;&lt;strong&gt;K-means&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DBSCAN" rel="noopener noreferrer"&gt;&lt;strong&gt;DBSCAN&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dimensionality reduction&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Principal_component_analysis" rel="noopener noreferrer"&gt;&lt;strong&gt;PCA&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding" rel="noopener noreferrer"&gt;&lt;strong&gt;t-SNE&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Statistical methods&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Bayesian_statistics" rel="noopener noreferrer"&gt;Bayesian models&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Density_estimation" rel="noopener noreferrer"&gt;density estimation&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example of using linear regression
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Scholar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Linear&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;LinearRegression&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Defn&lt;/span&gt;

&lt;span class="c1"&gt;# Data preparation&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Model training&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fit&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="c1"&gt;# Prediction&lt;/span&gt;
&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;]]))&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #Nx.Tensor&lt;/span&gt;
&lt;span class="c1"&gt;#  f32[1]&lt;/span&gt;
&lt;span class="c1"&gt;#  [17.0]&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Practical Application: Integration with Phoenix
&lt;/h3&gt;

&lt;p&gt;It's worth noting how seamlessly &lt;strong&gt;ML&lt;/strong&gt; models integrate with the &lt;a href="https://www.phoenixframework.org" rel="noopener noreferrer"&gt;Phoenix&lt;/a&gt; web framework, enabling powerful intelligent web applications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MLController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt;  
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;  

  &lt;span class="c1"&gt;# Model initialization at application start  &lt;/span&gt;
  &lt;span class="nv"&gt;@serving&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
  &lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
    &lt;span class="c1"&gt;# Asynchronous analysis  &lt;/span&gt;
    &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  
      &lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batched_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;await&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;predictions:&lt;/span&gt; &lt;span class="p"&gt;[%{&lt;/span&gt;&lt;span class="ss"&gt;label:&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;score:&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;sentiment:&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;confidence:&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  
        &lt;span class="n"&gt;conn&lt;/span&gt;  
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;error:&lt;/span&gt; &lt;span class="s2"&gt;"Analysis failed"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="k"&gt;end&lt;/span&gt;  
  &lt;span class="k"&gt;end&lt;/span&gt;  
&lt;span class="k"&gt;end&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This integration makes it easy to create &lt;strong&gt;APIs&lt;/strong&gt; for text analysis, image classification, recommendation systems, and other &lt;strong&gt;ML&lt;/strong&gt; applications while leveraging &lt;strong&gt;BEAM&lt;/strong&gt;'s advantages for horizontal scaling and high availability.  &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;ML&lt;/strong&gt; ecosystem in &lt;strong&gt;Elixir&lt;/strong&gt; offers a balanced combination of high-level tools and low-level control, allowing developers to choose the right abstraction level for their tasks. While not as extensive as the &lt;strong&gt;Python&lt;/strong&gt; ecosystem, &lt;strong&gt;Elixir&lt;/strong&gt;'s unique advantages make it attractive for certain machine learning scenarios, particularly those involving high-load systems and real-time data processing.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Model Training and Evaluation Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Data preparation  &lt;/span&gt;
&lt;span class="n"&gt;train_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_images&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;test_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test_images&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Creating data batches  &lt;/span&gt;
&lt;span class="n"&gt;batches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeatedly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  
    &lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random_uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;min:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max:&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:s64&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="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Model definition with regularization and dropout  &lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:relu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_regularizer:&lt;/span&gt; &lt;span class="ss"&gt;:l2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dropout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;rate:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:relu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dropout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;rate:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:softmax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Training with early stopping and hyperparameter optimization  &lt;/span&gt;
&lt;span class="n"&gt;trained_model_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="n"&gt;model&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:categorical_cross_entropy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Optimizers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;learning_rate:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;early_stopping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"validation_loss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;patience:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;iterations:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Model evaluation  &lt;/span&gt;
&lt;span class="n"&gt;test_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeatedly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;test_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_labels&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&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="n"&gt;eval_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
  &lt;span class="n"&gt;model&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trained_model_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




  
&lt;h3&gt;
  
  
  Comparison with Python Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Elixir&lt;/strong&gt; for &lt;strong&gt;ML&lt;/strong&gt; doesn't aim to replace &lt;strong&gt;Python&lt;/strong&gt; completely but rather complements the existing ecosystem:  &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Elixir (Nx/Axon)&lt;/th&gt;
&lt;th&gt;Python (TensorFlow/PyTorch)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ecosystem Maturity&lt;/td&gt;
&lt;td&gt;Emerging&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;High (distributed systems)&lt;/td&gt;
&lt;td&gt;GPU/TPU optimized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware Support&lt;/td&gt;
&lt;td&gt;CPU/GPU (via EXLA)&lt;/td&gt;
&lt;td&gt;Extensive (CUDA, TPU, ROCm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency&lt;/td&gt;
&lt;td&gt;Built-in (BEAM VM)&lt;/td&gt;
&lt;td&gt;Library-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Available Models&lt;/td&gt;
&lt;td&gt;Limited (Bumblebee)&lt;/td&gt;
&lt;td&gt;Vast model repositories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Integration&lt;/td&gt;
&lt;td&gt;Native (Phoenix LiveView)&lt;/td&gt;
&lt;td&gt;Via Flask/FastAPI/Django&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Simple (Mix releases + OTP)&lt;/td&gt;
&lt;td&gt;Complex (Docker/K8s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community&lt;/td&gt;
&lt;td&gt;Growing&lt;/td&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;High-quality (hexdocs)&lt;/td&gt;
&lt;td&gt;Extensive but fragmented&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production Use&lt;/td&gt;
&lt;td&gt;Erlang ecosystem (WhatsApp, Discord)&lt;/td&gt;
&lt;td&gt;Industry leader (Google, Meta)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The best strategy often involves a hybrid approach: training models in &lt;strong&gt;Python&lt;/strong&gt; and integrating them into &lt;strong&gt;Elixir&lt;/strong&gt; systems for inference.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Elixir for ML
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Computing&lt;/strong&gt;: &lt;strong&gt;BEAM&lt;/strong&gt; enables easy distribution of training tasks across cluster nodes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Processing&lt;/strong&gt;: Thanks to actors and &lt;strong&gt;OTP&lt;/strong&gt;, &lt;strong&gt;Elixir&lt;/strong&gt; excels at streaming data processing (e.g., for &lt;strong&gt;IoT&lt;/strong&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt;: Models can run in production with minimal downtime.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Limitations and Challenges
&lt;/h2&gt;

&lt;p&gt;Despite rapid development, &lt;strong&gt;Elixir&lt;/strong&gt;'s &lt;strong&gt;ML&lt;/strong&gt; ecosystem has some limitations:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of certain specialized algorithms and optimization methods
&lt;/li&gt;
&lt;li&gt;Lower performance for very large models compared to optimized &lt;strong&gt;Python&lt;/strong&gt; libraries
&lt;/li&gt;
&lt;li&gt;Limited &lt;strong&gt;TPU&lt;/strong&gt; support
&lt;/li&gt;
&lt;li&gt;Fewer documentation and learning resources
&lt;/li&gt;
&lt;li&gt;Not all modern architectures (e.g., some transformers) have efficient implementations
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;When to use &lt;strong&gt;Elixir&lt;/strong&gt; for &lt;strong&gt;ML&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For integrating &lt;strong&gt;ML&lt;/strong&gt; into existing &lt;strong&gt;Elixir/Phoenix&lt;/strong&gt; applications
&lt;/li&gt;
&lt;li&gt;In systems requiring high fault tolerance and scalability
&lt;/li&gt;
&lt;li&gt;For real-time data processing and online learning
&lt;/li&gt;
&lt;li&gt;In distributed systems where concurrency matters
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;strong&gt;Python&lt;/strong&gt; is preferable:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For research and prototyping
&lt;/li&gt;
&lt;li&gt;When working with very large models (e.g., LLMs)
&lt;/li&gt;
&lt;li&gt;When specialized algorithms only available in &lt;strong&gt;Python&lt;/strong&gt; are needed
&lt;/li&gt;
&lt;li&gt;With tight deadlines requiring ready-made solutions
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Neural Networks in Elixir
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Elixir&lt;/strong&gt; &lt;strong&gt;ML&lt;/strong&gt; ecosystem is young but promising. Community efforts focus on:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improving hardware acceleration integration (&lt;strong&gt;GPU/TPU&lt;/strong&gt;)
&lt;/li&gt;
&lt;li&gt;Expanding pre-trained models in &lt;strong&gt;Axon&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enhancing data processing tools (&lt;strong&gt;Explorer&lt;/strong&gt;, &lt;strong&gt;Scholar&lt;/strong&gt;)
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The &lt;strong&gt;ML&lt;/strong&gt; ecosystem in &lt;strong&gt;Elixir&lt;/strong&gt; is growing rapidly thanks to companies like &lt;a href="https://dashbit.co" rel="noopener noreferrer"&gt;Dashbit&lt;/a&gt; and developer contributions. For those wanting to dive deeper, we recommend:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hexdocs.pm/nx" rel="noopener noreferrer"&gt;Official Nx Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/elixir-nx/axon" rel="noopener noreferrer"&gt;Axon GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Xk1WPGKaDBg" rel="noopener noreferrer"&gt;Train a Neural Network in Minutes with Elixir &amp;amp; Axon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Es08MRtSkoE&amp;amp;t=1345s" rel="noopener noreferrer"&gt;A Practical Guide to Machine Learning in Elixir - Chris Grainger&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://livebook.dev/" rel="noopener noreferrer"&gt;Livebook as an ML Experimentation Tool&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  From the Author
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this article helped you understand &lt;strong&gt;Elixir&lt;/strong&gt;'s potential in machine learning and inspired you to experiment with this powerful technology combination.  &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Elixir&lt;/strong&gt; &lt;strong&gt;ML&lt;/strong&gt; ecosystem is evolving, and I welcome discussions about any questions, suggestions, or corrections. If you spot inaccuracies or have interesting additions—please share them in the comments. Constructive feedback is always valuable 😎  &lt;/p&gt;

&lt;p&gt;In Part 2, we'll build a complete ML project in Elixir, so stay tuned!  &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>machinelearning</category>
      <category>nx</category>
      <category>programming</category>
    </item>
    <item>
      <title>Elixir для Machine Learning. Часть 1 - Теория</title>
      <dc:creator>Artyom Molchanov </dc:creator>
      <pubDate>Wed, 02 Apr 2025 13:35:52 +0000</pubDate>
      <link>https://forem.com/adamanq/elixir-dlia-machine-learning-chast-1-tieoriia-14af</link>
      <guid>https://forem.com/adamanq/elixir-dlia-machine-learning-chast-1-tieoriia-14af</guid>
      <description>&lt;p&gt;В последнее время роль искусственного интеллекта в различных сферах начинает набирать обороты. Многие компании уже внедряют ИИ для помощи пользователям на своих порталах, а некоторые разрабатывают собственные нейронные сети для решения специализированных задач&lt;/p&gt;

&lt;p&gt;В то время как &lt;strong&gt;Python&lt;/strong&gt; доминирует в &lt;strong&gt;ML&lt;/strong&gt;-ландшафте, &lt;strong&gt;Elixir&lt;/strong&gt; находит применение в особых нишах: системы обработки данных в реальном времени &lt;strong&gt;&lt;em&gt;(Bumblebee)&lt;/em&gt;&lt;/strong&gt;, сервисы инференса моделей &lt;strong&gt;&lt;em&gt;(Nx.Serving)&lt;/em&gt;&lt;/strong&gt; и распределенные системы машинного обучения. Компании, такие как &lt;strong&gt;&lt;a href="https://dockyard.com" rel="noopener noreferrer"&gt;DockYard&lt;/a&gt;&lt;/strong&gt; и &lt;strong&gt;&lt;a href="https://dashbit.co" rel="noopener noreferrer"&gt;Dashbit&lt;/a&gt;&lt;/strong&gt;, уже успешно внедряют &lt;strong&gt;ML&lt;/strong&gt;-решения на &lt;strong&gt;Elixir&lt;/strong&gt; в промышленной среде&lt;/p&gt;

&lt;p&gt;Данная статья разделена на 2 части — Теория и Практика. В первой части мы рассмотрим основы машинного обучения, познакомимся с ключевыми понятиями и библиотеками, которые помогут создавать нейронные сети с использованием &lt;strong&gt;Elixir&lt;/strong&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Что такое машинное обучение и нейронные сети?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Машинное обучение &lt;em&gt;(Machine Learning, ML)&lt;/em&gt;&lt;/strong&gt; — это подход к созданию систем, которые могут обучаться на данных и улучшать свою производительность с опытом без явного программирования. Вместо написания конкретных инструкций для решения задачи, мы создаем модель, которая может адаптироваться и "учиться" на основе опыта&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Нейронные сети&lt;/strong&gt; — один из наиболее популярных методов машинного обучения, вдохновленный принципами работы человеческого мозга. Они представляют собой системы взаимосвязанных узлов &lt;em&gt;(нейронов)&lt;/em&gt;, организованных в слои:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Входной слой&lt;/strong&gt; получает исходные данные &lt;em&gt;(например, пиксели изображения)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Скрытые слои&lt;/strong&gt; обрабатывают информацию, выявляя все более сложные паттерны&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Выходной слой&lt;/strong&gt; предоставляет итоговый результат &lt;em&gt;(например, классификацию объекта)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Каждый нейрон получает входные сигналы, обрабатывает их, применяя активационную функцию к взвешенной сумме входов, и передает результат дальше по сети. Связи между нейронами имеют весовые коэффициенты, которые определяют важность сигнала&lt;/p&gt;

&lt;p&gt;Процесс обучения нейронной сети заключается в настройке этих весовых коэффициентов таким образом, чтобы сеть выдавала правильные результаты. Это происходит путем:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Подачи множества обучающих примеров&lt;/li&gt;
&lt;li&gt;Вычисления ошибки между предсказаниями сети и фактическими значениями&lt;/li&gt;
&lt;li&gt;Корректировки весов для минимизации этой ошибки с помощью &lt;a href="https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8" rel="noopener noreferrer"&gt;алгоритма обратного распространения ошибки &lt;strong&gt;&lt;em&gt;(backpropagation)&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Ключевые концепции в машинном обучении
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Модели и их типы
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Модель&lt;/strong&gt; — математическая или алгоритмическая конструкция, которая обучается на данных для выполнения определённой задачи. Модели бывают разных типов:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Линейные модели&lt;/strong&gt;: Относительно простые модели, которые предполагают линейную зависимость между входными и выходными данными. Примеры: &lt;a href="https://ru.wikipedia.org/wiki/%D0%9B%D0%B8%D0%BD%D0%B5%D0%B9%D0%BD%D0%B0%D1%8F_%D1%80%D0%B5%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F" rel="noopener noreferrer"&gt;линейная регрессия&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D0%B3%D0%B8%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D1%80%D0%B5%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F" rel="noopener noreferrer"&gt;логистическая регрессия&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Нейронные сети&lt;/strong&gt;: Многослойные модели, которые могут выявлять сложные нелинейные зависимости. Применяются для задач компьютерного зрения, обработки естественного языка и других сложных проблем&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ансамбли моделей&lt;/strong&gt;: Комбинации нескольких моделей для получения более точного результата. Примеры: &lt;a href="https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BB%D0%B5%D1%81%D0%B0" rel="noopener noreferrer"&gt;случайные леса &lt;em&gt;&lt;strong&gt;(Random Forests)&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Gradient_boosting" rel="noopener noreferrer"&gt;градиентный бустинг &lt;strong&gt;&lt;em&gt;(Gradient Boosting)&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Тензоры и их роль в ML
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Тензор&lt;/strong&gt; — это обобщение понятий &lt;a href="https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%B0%D0%BB%D1%8F%D1%80" rel="noopener noreferrer"&gt;скаляра&lt;/a&gt;, вектора и матрицы на многомерные массивы данных. Тензоры являются фундаментальной структурой данных в современных системах машинного обучения:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Скаляр&lt;/strong&gt;: Тензор ранга 0 (0-D). Пример: число 5&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Вектор&lt;/strong&gt;: Тензор ранга 1 (1-D). Пример: [1, 2, 3]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Матрица&lt;/strong&gt;: Тензор ранга 2 (2-D). Пример: [[1, 2, 3], [4, 5, 6]]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Многомерный тензор&lt;/strong&gt;: Тензор ранга 3+ (3-D и выше). Пример: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Тензоры используются для представления и обработки различных типов данных в &lt;strong&gt;ML&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Изображения &lt;em&gt;(тензоры размерности 4: [batch_size, height, width, channels])&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Тексты &lt;em&gt;(последовательности векторов, представляющих слова или токены)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Временные ряды &lt;em&gt;(последовательности наблюдений с течением времени)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Типы обучения
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Обучение&lt;/strong&gt; — процесс, при котором модель настраивает свои параметры на основе данных:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Обучение с учителем &lt;em&gt;(Supervised Learning)&lt;/em&gt;&lt;/strong&gt;: Модель обучается на размеченных данных, где для каждого входного примера известен правильный ответ. Примеры задач: классификация изображений, прогнозирование цен, распознавание речи&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Обучение без учителя &lt;em&gt;(Unsupervised Learning)&lt;/em&gt;&lt;/strong&gt;: Модель обучается на неразмеченных данных, выявляя скрытые структуры и паттерны. Примеры задач: &lt;a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7" rel="noopener noreferrer"&gt;кластеризация&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%A1%D0%BD%D0%B8%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8" rel="noopener noreferrer"&gt;уменьшение размерности&lt;/a&gt;, &lt;a href="https://habr.com/ru/articles/530574/" rel="noopener noreferrer"&gt;обнаружение аномалий&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Обучение с подкреплением &lt;em&gt;(Reinforcement Learning)&lt;/em&gt;&lt;/strong&gt;: Модель обучается через взаимодействие с окружающей средой, получая награды или штрафы за свои действия. Применяется в робототехнике, играх, автономных системах&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Гиперпараметры и их настройка
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Гиперпараметры&lt;/strong&gt; — это настройки модели, которые задаются до начала обучения и не изменяются в его процессе:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Архитектурные гиперпараметры&lt;/strong&gt;: Количество слоёв в нейронной сети, количество нейронов в каждом слое, типы активационных функций&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Параметры оптимизации&lt;/strong&gt;: Скорость обучения &lt;strong&gt;&lt;em&gt;(learning rate)&lt;/em&gt;&lt;/strong&gt;, размер батча &lt;strong&gt;&lt;em&gt;(batch size)&lt;/em&gt;&lt;/strong&gt;, количество эпох обучения&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Регуляризационные параметры&lt;/strong&gt;: Коэффициенты &lt;strong&gt;L1/L2&lt;/strong&gt; регуляризации, параметр dropout для предотвращения переобучения&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Настройка гиперпараметров обычно выполняется с помощью методов, таких как поиск по сетке &lt;strong&gt;&lt;em&gt;(grid search)&lt;/em&gt;&lt;/strong&gt;, случайный поиск &lt;strong&gt;&lt;em&gt;(random search)&lt;/em&gt;&lt;/strong&gt; или байесовская оптимизация&lt;/p&gt;
&lt;h3&gt;
  
  
  Метрики оценки моделей
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Метрики&lt;/strong&gt; — это количественные показатели, которые используются для оценки качества работы модели:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Для задач классификации&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Точность &lt;em&gt;(Accuracy)&lt;/em&gt;&lt;/strong&gt;: Доля правильных предсказаний среди всех предсказаний&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Точность и полнота &lt;em&gt;(Precision &amp;amp; Recall)&lt;/em&gt;&lt;/strong&gt;: Показатели, отражающие баланс между ложноположительными и ложноотрицательными результатами&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;F1-мера&lt;/strong&gt;: Гармоническое среднее между точностью и полнотой&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROC-AUC&lt;/strong&gt;: Площадь под &lt;a href="https://ru.wikipedia.org/wiki/ROC-%D0%BA%D1%80%D0%B8%D0%B2%D0%B0%D1%8F" rel="noopener noreferrer"&gt;ROC-кривой&lt;/a&gt;, отражающая способность модели различать классы&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Для задач регрессии&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Среднеквадратичная ошибка &lt;em&gt;(MSE)&lt;/em&gt;&lt;/strong&gt;: Среднее значение квадратов разностей между предсказанными и фактическими значениями&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Средняя абсолютная ошибка &lt;em&gt;(MAE)&lt;/em&gt;&lt;/strong&gt;: Среднее значение абсолютных разностей между предсказанными и фактическими значениями&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Коэффициент детерминации &lt;em&gt;(R²)&lt;/em&gt;&lt;/strong&gt;: Показывает, насколько хорошо модель объясняет вариацию данных&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Выбор метрики зависит от конкретной задачи и бизнес-контекста. Например, в медицинской диагностике важнее минимизировать количество ложноотрицательных результатов, а в рекомендательных системах может быть важнее качество верхних рекомендаций&lt;/p&gt;

&lt;p&gt;Теперь, когда мы рассмотрели ключевые концепции машинного обучения, давайте перейдем к инструментам, которые делают возможным применение этих концепций в экосистеме &lt;strong&gt;Elixir&lt;/strong&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Инструменты &lt;strong&gt;Elixir&lt;/strong&gt; для машинного обучения
&lt;/h2&gt;

&lt;p&gt;Экосистема машинного обучения в &lt;strong&gt;Elixir&lt;/strong&gt; быстро развивается, предлагая все более мощные и удобные инструменты для разработчиков. Рассмотрим ключевые библиотеки, которые делают возможным применение &lt;strong&gt;ML&lt;/strong&gt; на платформе &lt;strong&gt;BEAM&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx" rel="noopener noreferrer"&gt;Numerical Elixir&lt;/a&gt; (Nx): Фундамент для вычислений
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/elixir-nx/nx" rel="noopener noreferrer"&gt;&lt;strong&gt;Nx&lt;/strong&gt;&lt;/a&gt; — это основа всей ML-экосистемы &lt;strong&gt;Elixir&lt;/strong&gt;, разработанная командой &lt;strong&gt;Dashbit&lt;/strong&gt; под руководством Жозе Валима &lt;em&gt;(создателя &lt;strong&gt;Elixir&lt;/strong&gt;)&lt;/em&gt;. Эта библиотека предоставляет высокоэффективные числовые вычисления и поддержку многомерных тензоров, что критически важно для машинного обучения&lt;/p&gt;
&lt;h4&gt;
  
  
  Ключевые возможности Nx:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Тензорные операции&lt;/strong&gt;: Полный набор функций для манипуляции многомерными массивами данных&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Численная стабильность&lt;/strong&gt;: Высокая точность вычислений с контролем численных ошибок&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Компиляция вычислений&lt;/strong&gt;: Преобразование кода &lt;strong&gt;Elixir&lt;/strong&gt; в оптимизированный машинный код&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Автоматическое дифференцирование&lt;/strong&gt;: Необходимое для алгоритмов обратного распространения ошибки&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Особенно мощной особенностью &lt;strong&gt;Nx&lt;/strong&gt; является система &lt;code&gt;defn&lt;/code&gt; &lt;em&gt;(определяемых числовых функций)&lt;/em&gt;, которая позволяет компилировать вычисления в эффективный низкоуровневый код:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MathOps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Defn&lt;/span&gt;

  &lt;span class="n"&gt;defn&lt;/span&gt; &lt;span class="n"&gt;multiply_and_add&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;do&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Использование&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&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="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="no"&gt;MathOps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multiply_and_add&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="c1"&gt;# Результат: Nx.tensor([11, 18, 27])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Поддерживаемые бэкенды Nx:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Nx&lt;/strong&gt; работает через систему бэкендов, которые определяют, где и как будут выполняться вычисления:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EXLA&lt;/strong&gt;: Интеграция с &lt;a href="https://openxla.org/xla?hl=ru" rel="noopener noreferrer"&gt;&lt;strong&gt;XLA&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;(Accelerated Linear Algebra)&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; от &lt;strong&gt;Google&lt;/strong&gt;, обеспечивающая компиляцию для &lt;strong&gt;CPU&lt;/strong&gt;, &lt;strong&gt;GPU&lt;/strong&gt; и &lt;strong&gt;TPU&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Torchx&lt;/strong&gt;: Соединение с &lt;a href="https://pytorch.org" rel="noopener noreferrer"&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/a&gt;, использующее его оптимизированные &lt;a href="https://ru.wikipedia.org/wiki/CUDA" rel="noopener noreferrer"&gt;&lt;strong&gt;CUDA&lt;/strong&gt;&lt;/a&gt;-операции&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ONNX&lt;/strong&gt;: Поддержка &lt;a href="https://onnx.ai" rel="noopener noreferrer"&gt;&lt;strong&gt;Open Neural Network Exchange&lt;/strong&gt;&lt;/a&gt; для совместимости с широким спектром моделей&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BinaryBackend&lt;/strong&gt;: Нативная реализация на &lt;strong&gt;Elixir&lt;/strong&gt;, не требующая внешних зависимостей&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Выбор бэкенда зависит от задачи и доступного оборудования:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Глобальное использование EXLA-бэкенда&lt;/span&gt;
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;global_default_backend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Использование PyTorch для конкретной операции&lt;/span&gt;
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backend_transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Torchx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;device:&lt;/span&gt; &lt;span class="ss"&gt;:cuda&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/axon" rel="noopener noreferrer"&gt;Axon&lt;/a&gt;: Нейронные сети с функциональным подходом
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Axon&lt;/strong&gt; — это высокоуровневый фреймворк для определения, обучения и оценки нейронных сетей, построенный поверх &lt;strong&gt;Nx&lt;/strong&gt;. Главная особенность &lt;strong&gt;Axon&lt;/strong&gt; — функциональный дизайн, идеально соответствующий философии &lt;strong&gt;Elixir&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Особенности Axon:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Декларативное определение моделей&lt;/strong&gt;: Понятный пайплайн-подход к созданию архитектур&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Встроенные оптимизаторы&lt;/strong&gt;: Реализации &lt;a href="https://www.geeksforgeeks.org/adam-optimizer-in-tensorflow/" rel="noopener noreferrer"&gt;&lt;strong&gt;Adam&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%BE%D1%85%D0%B0%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BD%D1%8B%D0%B9_%D1%81%D0%BF%D1%83%D1%81%D0%BA" rel="noopener noreferrer"&gt;&lt;strong&gt;SGD&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.geeksforgeeks.org/rmsprop-optimizer-in-deep-learning/" rel="noopener noreferrer"&gt;&lt;strong&gt;RMSProp&lt;/strong&gt;&lt;/a&gt; и других алгоритмов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Функции потерь&lt;/strong&gt;: Широкий набор для различных задач &lt;em&gt;(&lt;a href="https://www.geeksforgeeks.org/mean-squared-error/" rel="noopener noreferrer"&gt;&lt;strong&gt;MSE&lt;/strong&gt;&lt;/a&gt;, кросс-энтропия и др.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Управление обучением&lt;/strong&gt;: Инструменты для раннего останова, валидации, обратных вызовов&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример создания и обучения модели классификации:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Определение модели&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Компиляция и обучение&lt;/span&gt;
&lt;span class="n"&gt;trained_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:categorical_cross_entropy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:adam&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compiler:&lt;/span&gt; &lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Расширенные возможности Axon:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Axon&lt;/strong&gt; поддерживает широкий спектр слоев и архитектур:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Сверточные слои&lt;/strong&gt;: Для задач компьютерного зрения &lt;em&gt;(&lt;code&gt;Axon.conv&lt;/code&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Рекуррентные сети&lt;/strong&gt;: &lt;a href="https://ru.wikipedia.org/wiki/%D0%94%D0%BE%D0%BB%D0%B3%D0%B0%D1%8F_%D0%BA%D1%80%D0%B0%D1%82%D0%BA%D0%BE%D1%81%D1%80%D0%BE%D1%87%D0%BD%D0%B0%D1%8F_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C" rel="noopener noreferrer"&gt;&lt;strong&gt;LSTM&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%A3%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D1%8F%D0%B5%D0%BC%D1%8B%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%80%D0%B5%D0%BD%D1%82%D0%BD%D1%8B%D0%B9_%D0%B1%D0%BB%D0%BE%D0%BA" rel="noopener noreferrer"&gt;&lt;strong&gt;GRU&lt;/strong&gt;&lt;/a&gt; для последовательных данных&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Трансформеры&lt;/strong&gt;: Внимание, мультиголовое внимание для &lt;a href="https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0" rel="noopener noreferrer"&gt;&lt;strong&gt;NLP&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Нормализация&lt;/strong&gt;: &lt;a href="https://en.wikipedia.org/wiki/Batch_normalization" rel="noopener noreferrer"&gt;&lt;strong&gt;BatchNorm&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.geeksforgeeks.org/what-is-layer-normalization/" rel="noopener noreferrer"&gt;&lt;strong&gt;LayerNorm&lt;/strong&gt;&lt;/a&gt; для стабилизации обучения&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Регуляризация&lt;/strong&gt;: &lt;a href="https://ru.wikipedia.org/wiki/%D0%98%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_(%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8)" rel="noopener noreferrer"&gt;&lt;strong&gt;Dropout&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://deepmachinelearning.ru/docs/Machine-learning/Base-concepts/Regularization" rel="noopener noreferrer"&gt;&lt;strong&gt;L1/L2&lt;/strong&gt;&lt;/a&gt; для борьбы с переобучением&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример сверточной сети для классификации изображений:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&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;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_size:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;padding:&lt;/span&gt; &lt;span class="ss"&gt;:same&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;kernel_size:&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;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_size:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;padding:&lt;/span&gt; &lt;span class="ss"&gt;:same&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;kernel_size:&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;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-explorer/explorer" rel="noopener noreferrer"&gt;Explorer&lt;/a&gt;: Обработка и подготовка данных
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Explorer&lt;/strong&gt; — библиотека для работы с табличными данными, вдохновленная &lt;a href="https://pandas.pydata.org" rel="noopener noreferrer"&gt;&lt;strong&gt;Pandas&lt;/strong&gt;&lt;/a&gt; из &lt;strong&gt;Python&lt;/strong&gt;. Она тесно интегрируется с &lt;strong&gt;Nx&lt;/strong&gt;, позволяя легко преобразовывать данные в тензоры&lt;/p&gt;

&lt;h4&gt;
  
  
  Ключевые возможности Explorer:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DataFrame API&lt;/strong&gt;: Мощный интерфейс для манипуляций с данными&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Фильтрация и группировка&lt;/strong&gt;: Эффективная работа с большими наборами данных&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Загрузка/сохранение&lt;/strong&gt;: Поддержка &lt;strong&gt;CSV&lt;/strong&gt;, &lt;strong&gt;Parquet&lt;/strong&gt;, &lt;strong&gt;JSON&lt;/strong&gt; и других форматов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Визуализация&lt;/strong&gt;: Интеграция с &lt;a href="https://vega.github.io/vega-lite/examples/" rel="noopener noreferrer"&gt;&lt;strong&gt;Vega-Lite&lt;/strong&gt;&lt;/a&gt; для создания диаграмм&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример работы с данными:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Загрузка и обработка данных&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_csv!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"titanic.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"survived"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"fare"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;fare_category:&lt;/span&gt; &lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="k"&gt;cond&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"low"&lt;/span&gt;
      &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"medium"&lt;/span&gt;
      &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"high"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;#### Преобразование в тензоры для ML&lt;/span&gt;
&lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_nx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"fare"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Explorer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_nx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"survived"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/bumblebee" rel="noopener noreferrer"&gt;Bumblebee&lt;/a&gt;: Готовые модели для практического применения
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bumblebee&lt;/strong&gt; — это библиотека, предоставляющая предобученные модели и инструменты для их использования. &lt;strong&gt;Bumblebee&lt;/strong&gt; значительно упрощает работу с современными моделями без необходимости обучать их с нуля&lt;/p&gt;

&lt;h3&gt;
  
  
  Ключевые возможности:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Предобученные модели&lt;/strong&gt;: &lt;a href="https://huggingface.co/docs/transformers/model_doc/bert" rel="noopener noreferrer"&gt;&lt;strong&gt;BERT&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://huggingface.co/openai-community/gpt2" rel="noopener noreferrer"&gt;&lt;strong&gt;GPT-2&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://pytorch.org/vision/stable/models/resnet.html" rel="noopener noreferrer"&gt;&lt;strong&gt;ResNet&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://huggingface.co/docs/transformers/model_doc/clip" rel="noopener noreferrer"&gt;&lt;strong&gt;CLIP&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://dockyard.com/blog/2022/12/15/stable-diffusion-with-bumblebee" rel="noopener noreferrer"&gt;&lt;strong&gt;Stable Diffusion&lt;/strong&gt;&lt;/a&gt; и другие&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Встроенные пайплайны&lt;/strong&gt;: Готовые решения для типовых задач&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Интеграция с Hugging Face&lt;/strong&gt;: Доступ к тысячам моделей&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Оптимизированный инференс&lt;/strong&gt;: Эффективное выполнение на различном оборудовании&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример использования для анализа тональности текста:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"distilbert-base-uncased-finetuned-sst-2-english"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_tokenizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"distilbert-base-uncased"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;serving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I love Elixir, it's an amazing language!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; %{predictions: [%{label: "POSITIVE", score: 0.998}]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://hexdocs.pm/nx/Nx.Serving.html" rel="noopener noreferrer"&gt;Nx.Serving&lt;/a&gt;: Развертывание моделей в продакшене
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nx.Serving&lt;/strong&gt; — инструмент для эффективного развертывания &lt;strong&gt;ML&lt;/strong&gt;-моделей в качестве сервисов. Он обеспечивает:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Батчинг запросов&lt;/strong&gt;: Автоматическое группирование для эффективного выполнения&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Очереди и приоритеты&lt;/strong&gt;: Управление нагрузкой и распределение ресурсов&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Горячая замена&lt;/strong&gt;: Обновление моделей без простоя&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Мониторинг&lt;/strong&gt;: Отслеживание производительности и использования ресурсов&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример создания сервиса для распознавания изображений:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;model_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"microsoft/resnet-50"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;featurizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_featurizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"microsoft/resnet-50"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;serving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Vision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_classification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;featurizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;# Динамический батчинг&lt;/span&gt;
    &lt;span class="ss"&gt;defn_options:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;compiler:&lt;/span&gt; &lt;span class="no"&gt;EXLA&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Использование GPU&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Запуск как процесса OTP&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;ImageClassifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Использование&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cat.jpg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batched_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ImageClassifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://livebook.dev" rel="noopener noreferrer"&gt;LiveBook&lt;/a&gt;: Интерактивная разработка и эксперименты
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LiveBook&lt;/strong&gt; — это интерактивная среда для разработки и документирования кода &lt;strong&gt;Elixir&lt;/strong&gt;, идеально подходящая для &lt;strong&gt;ML&lt;/strong&gt;-экспериментов. Она предоставляет:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jupyter-подобный интерфейс&lt;/strong&gt;: Интерактивные ячейки кода&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Встроенная визуализация&lt;/strong&gt;: Диаграммы, графики, таблицы&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Интеграция с ML-библиотеками&lt;/strong&gt;: Специальные виджеты для &lt;strong&gt;Nx&lt;/strong&gt;, &lt;strong&gt;Axon&lt;/strong&gt;, &lt;strong&gt;Explorer&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Совместная работа&lt;/strong&gt;: Возможность делиться ноутбуками и работать над ними вместе&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Выполнение на GPU&lt;/strong&gt;: Поддержка аппаратного ускорения&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LiveBook&lt;/strong&gt; существенно упрощает обучение, экспериментирование и документирование &lt;strong&gt;ML&lt;/strong&gt;-проектов на &lt;strong&gt;Elixir&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Пример ячейки LiveBook&lt;/span&gt;
&lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:axon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:explorer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.5"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:kino&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.8"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;### Интерактивный ввод гиперпараметров&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Control&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="ss"&gt;learning_rate:&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Learning rate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="s2"&gt;"0.001"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="no"&gt;Kino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;submit:&lt;/span&gt; &lt;span class="s2"&gt;"Train model"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/elixir-nx/scholar" rel="noopener noreferrer"&gt;Scholar&lt;/a&gt;: Традиционные алгоритмы машинного обучения
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scholar&lt;/strong&gt; расширяет экосистему &lt;strong&gt;Elixir ML&lt;/strong&gt; классическими алгоритмами, которые часто бывают более подходящими для определенных задач, чем глубокое обучение:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Линейные модели&lt;/strong&gt;: Регрессия, &lt;a href="https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%BF%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2" rel="noopener noreferrer"&gt;&lt;strong&gt;SVM&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D0%B3%D0%B8%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D1%80%D0%B5%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F" rel="noopener noreferrer"&gt;логистическая регрессия&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Деревья решений&lt;/strong&gt;: &lt;a href="https://www.jcchouinard.com/decision-trees-in-machine-learning/" rel="noopener noreferrer"&gt;Одиночные деревья&lt;/a&gt; и ансамбли&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Кластеризация&lt;/strong&gt;: &lt;a href="https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_k-%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85" rel="noopener noreferrer"&gt;&lt;strong&gt;K-means&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/DBSCAN" rel="noopener noreferrer"&gt;&lt;strong&gt;DBSCAN&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Понижение размерности&lt;/strong&gt;: &lt;a href="https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D1%8B%D1%85_%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82" rel="noopener noreferrer"&gt;&lt;strong&gt;PCA&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%BE%D1%85%D0%B0%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%B2%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81%D0%BE%D1%81%D0%B5%D0%B4%D0%B5%D0%B9_%D1%81_t-%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%D0%BC" rel="noopener noreferrer"&gt;&lt;strong&gt;t-SNE&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Статистические методы&lt;/strong&gt;: &lt;a href="https://education.yandex.ru/handbook/ml/article/bajesovskij-podhod-k-ocenivaniyu" rel="noopener noreferrer"&gt;Байесовские модели&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Density_estimation" rel="noopener noreferrer"&gt;оценка плотности&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример использования линейной регрессии:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Scholar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Linear&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;LinearRegression&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Defn&lt;/span&gt;

&lt;span class="c1"&gt;# Подготовка данных&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Обучение модели&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fit&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="c1"&gt;# Предсказание&lt;/span&gt;
&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;]]))&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #Nx.Tensor&lt;/span&gt;
&lt;span class="c1"&gt;#  f32[1]&lt;/span&gt;
&lt;span class="c1"&gt;#  [17.0]&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Практическое применение: Интеграция с Phoenix
&lt;/h3&gt;

&lt;p&gt;Отдельно стоит отметить, насколько органично &lt;strong&gt;ML&lt;/strong&gt;-модели интегрируются с веб-фреймворком &lt;a href="https://www.phoenixframework.org" rel="noopener noreferrer"&gt;Phoenix&lt;/a&gt;, создавая мощные интеллектуальные веб-приложения:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MLController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;MyAppWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Serving&lt;/span&gt;

  &lt;span class="c1"&gt;# Инициализация модели при старте приложения&lt;/span&gt;
  &lt;span class="nv"&gt;@serving&lt;/span&gt; &lt;span class="no"&gt;Bumblebee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;compile:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;batch_size:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@serving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Асинхронный анализ&lt;/span&gt;
    &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="no"&gt;Serving&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batched_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;await&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;predictions:&lt;/span&gt; &lt;span class="p"&gt;[%{&lt;/span&gt;&lt;span class="ss"&gt;label:&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;score:&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;sentiment:&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;confidence:&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;error:&lt;/span&gt; &lt;span class="s2"&gt;"Analysis failed"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Такая интеграция позволяет легко создавать &lt;strong&gt;API&lt;/strong&gt; для анализа текста, классификации изображений, рекомендательных систем и многих других &lt;strong&gt;ML&lt;/strong&gt;-приложений, используя все преимущества &lt;strong&gt;BEAM&lt;/strong&gt; для горизонтального масштабирования и высокой доступности&lt;/p&gt;

&lt;p&gt;Экосистема &lt;strong&gt;ML&lt;/strong&gt; в &lt;strong&gt;Elixir&lt;/strong&gt; предлагает сбалансированное сочетание высокоуровневых инструментов и низкоуровневого контроля, позволяя выбрать подходящий уровень абстракции для конкретной задачи. Хотя она еще не так обширна, как &lt;strong&gt;Python&lt;/strong&gt;-экосистема, уникальные преимущества &lt;strong&gt;BEAM&lt;/strong&gt; делают &lt;strong&gt;Elixir&lt;/strong&gt; привлекательным выбором для определенных сценариев машинного обучения, особенно связанных с высоконагруженными системами и обработкой данных в реальном времени&lt;/p&gt;

&lt;h2&gt;
  
  
  Пример кода для обучения и оценки модели
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Подготовка данных&lt;/span&gt;
&lt;span class="n"&gt;train_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_images&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test_images&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Создание батчей данных&lt;/span&gt;
&lt;span class="n"&gt;batches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeatedly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random_uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;min:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max:&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:s64&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="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Определение модели с регуляризацией и дропаутом&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;shape:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:relu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;kernel_regularizer:&lt;/span&gt; &lt;span class="ss"&gt;:l2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dropout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;rate:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:relu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dropout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;rate:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;activation:&lt;/span&gt; &lt;span class="ss"&gt;:softmax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Обучение с ранним остановом и оптимизацией гиперпараметров&lt;/span&gt;
&lt;span class="n"&gt;trained_model_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:categorical_cross_entropy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Optimizers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;learning_rate:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;early_stopping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"validation_loss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;patience:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;epochs:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;iterations:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Оценка модели&lt;/span&gt;
&lt;span class="n"&gt;test_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeatedly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;test_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_labels&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&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="n"&gt;eval_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evaluator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:accuracy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Axon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trained_model_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




 
&lt;h3&gt;
  
  
  Сравнение с Python-инструментами
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Elixir&lt;/strong&gt; для &lt;strong&gt;ML&lt;/strong&gt; не стремится полностью заменить &lt;strong&gt;Python&lt;/strong&gt;, а скорее дополняет существующую экосистему:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Критерий&lt;/th&gt;
&lt;th&gt;Elixir (Nx/Axon)&lt;/th&gt;
&lt;th&gt;Python (TensorFlow/PyTorch)&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Производительность&lt;/td&gt;
&lt;td&gt;Высокая (распределенные системы)&lt;/td&gt;
&lt;td&gt;Оптимизирована под GPU/TPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Поддержка железа&lt;/td&gt;
&lt;td&gt;CPU/GPU (через EXLA)&lt;/td&gt;
&lt;td&gt;Широкая (CUDA, TPU, ROCm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Параллелизм&lt;/td&gt;
&lt;td&gt;Встроенный (BEAM VM)&lt;/td&gt;
&lt;td&gt;Зависит от библиотек&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Доступные модели&lt;/td&gt;
&lt;td&gt;Ограниченный набор (Bumblebee)&lt;/td&gt;
&lt;td&gt;Обширные репозитории моделей&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Интеграция с веб&lt;/td&gt;
&lt;td&gt;Нативная (Phoenix LiveView)&lt;/td&gt;
&lt;td&gt;Через Flask/FastAPI/Django&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Развертывание&lt;/td&gt;
&lt;td&gt;Простое (микс релизы + OTP)&lt;/td&gt;
&lt;td&gt;Комплексное (Docker/K8s)&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Документация&lt;/td&gt;
&lt;td&gt;Качественная (hexdocs)&lt;/td&gt;
&lt;td&gt;Обширная (но фрагментированная)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Использование в продакшене&lt;/td&gt;
&lt;td&gt;Erlang-экосистема (WhatsApp, Discord)&lt;/td&gt;
&lt;td&gt;Лидер индустрии (Google, Meta)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Лучшая стратегия часто заключается в использовании гибридного подхода: обучение моделей на &lt;strong&gt;Python&lt;/strong&gt; и их интеграция в &lt;strong&gt;Elixir&lt;/strong&gt;-системы для инференса&lt;/p&gt;

&lt;h2&gt;
  
  
  Преимущества Elixir в ML
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Распределённые вычисления&lt;/strong&gt;. &lt;strong&gt;BEAM&lt;/strong&gt; позволяет легко распределять задачи обучения между узлами кластера
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Обработка в реальном времени&lt;/strong&gt;. Благодаря акторам и &lt;strong&gt;OTP&lt;/strong&gt;, &lt;strong&gt;Elixir&lt;/strong&gt; эффективен для потоковой обработки данных &lt;em&gt;(например, в &lt;strong&gt;IoT&lt;/strong&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Надёжность&lt;/strong&gt;. Модели могут работать в продакшене с минимальным временем простоя&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Ограничения и вызовы
&lt;/h2&gt;

&lt;p&gt;Несмотря на быстрое развитие, экосистема &lt;strong&gt;ML&lt;/strong&gt; в &lt;strong&gt;Elixir&lt;/strong&gt; имеет ряд ограничений:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Отсутствие некоторых специализированных алгоритмов и методов оптимизации&lt;/li&gt;
&lt;li&gt;Меньшая производительность для очень больших моделей по сравнению с оптимизированными &lt;strong&gt;Python&lt;/strong&gt;-библиотеками&lt;/li&gt;
&lt;li&gt;Ограниченная поддержка &lt;strong&gt;TPU&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Меньше документации и обучающих материалов&lt;/li&gt;
&lt;li&gt;Не все современные архитектуры &lt;em&gt;(например, некоторые виды трансформеров)&lt;/em&gt; имеют эффективные реализации&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Практические применения
&lt;/h2&gt;

&lt;p&gt;Когда стоит использовать &lt;strong&gt;Elixir&lt;/strong&gt; для &lt;strong&gt;ML&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Для интеграции &lt;strong&gt;ML&lt;/strong&gt; в существующие &lt;strong&gt;Elixir/Phoenix&lt;/strong&gt;-приложения&lt;/li&gt;
&lt;li&gt;В системах, требующих высокой отказоустойчивости и масштабируемости&lt;/li&gt;
&lt;li&gt;Для обработки данных в реальном времени и онлайн-обучения&lt;/li&gt;
&lt;li&gt;В распределенных системах, где важен параллелизм&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Когда лучше использовать &lt;strong&gt;Python&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Для исследовательской работы и прототипирования&lt;/li&gt;
&lt;li&gt;При работе с очень большими моделями &lt;em&gt;(например, большими языковыми моделями)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Когда требуются специализированные алгоритмы, доступные только в &lt;strong&gt;Python&lt;/strong&gt;-библиотеках&lt;/li&gt;
&lt;li&gt;При ограниченном времени на разработку и необходимости использовать готовые решения&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Будущее нейросетей на Elixir
&lt;/h2&gt;

&lt;p&gt;Экосистема &lt;strong&gt;Elixir&lt;/strong&gt; для &lt;strong&gt;ML&lt;/strong&gt; ещё молода, но перспективна. Усилия сообщества направлены на:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Улучшение интеграции с аппаратным ускорением &lt;em&gt;&lt;strong&gt;(GPU/TPU)&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Расширение списка готовых моделей в &lt;strong&gt;Axon&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Развитие инструментов для обработки данных &lt;em&gt;&lt;strong&gt;(Explorer, Scholar)&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Заключение
&lt;/h3&gt;

&lt;p&gt;Экосистема &lt;strong&gt;ML&lt;/strong&gt; в &lt;strong&gt;Elixir&lt;/strong&gt; активно развивается благодаря усилиям компаний, таких как &lt;a href="https://dashbit.co" rel="noopener noreferrer"&gt;Dashbit&lt;/a&gt;, и сообщества разработчиков. Для тех, кто хочет глубже погрузиться в тему, рекомендуем следующие ресурсы:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/nx" rel="noopener noreferrer"&gt;Официальная документация Nx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elixir-nx/axon" rel="noopener noreferrer"&gt;Репозиторий Axon на GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Xk1WPGKaDBg" rel="noopener noreferrer"&gt;Train a Neural Network in Minutes with Elixir &amp;amp; Axon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Es08MRtSkoE&amp;amp;t=1345s" rel="noopener noreferrer"&gt;A Practical Guide to Machine Learning in Elixir - Chris Grainger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://livebook.dev/" rel="noopener noreferrer"&gt;Livebook как инструмент для ML-экспериментов&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  От автора
&lt;/h2&gt;

&lt;p&gt;Благодарю вас за внимание к этой статье! Надеюсь, она помогла вам лучше понять возможности &lt;strong&gt;Elixir&lt;/strong&gt; в сфере машинного обучения и вдохновила на собственные эксперименты с этой мощной комбинацией технологий =)&lt;/p&gt;

&lt;p&gt;Экосистема &lt;strong&gt;ML&lt;/strong&gt; в &lt;strong&gt;Elixir&lt;/strong&gt; активно развивается, и я буду рад обсудить любые вопросы, предложения или замечания. Если вы обнаружили неточности в материале или у вас есть интересные дополнения — пожалуйста, напишите об этом в комментариях. Конструктивная обратная связь всегда ценна 😎&lt;/p&gt;

&lt;p&gt;Для тех, кому интересно глубже погрузиться в мир технологий, архитектуры и разработки, приглашаю заглянуть в мой &lt;a href="https://t.me/devs_inc" rel="noopener noreferrer"&gt;телеграм-канал 🖥&lt;/a&gt;, где я делюсь рецензиями на технические книги, полезными материалами по &lt;strong&gt;Elixir&lt;/strong&gt; и не только 🤤&lt;/p&gt;

&lt;p&gt;Во второй части статьи мы перейдем к практике и создадим полноценный ML-проект на Elixir, так что не пропустите продолжение!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>machinelearning</category>
      <category>nx</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
