Pull to refresh
27
0.1
Dmitry Rubinstein @Virviil

Software Developer

Send message

Спасибо, исправил. Пожалуйста ошибки в ЛС.

Скорее всего потому, что это перевод. Впрочем, возможно я переведу следующую статью автора Protocols vs Behaviours

Мне кажется, или идея менять enum на interface написана где-то на перых полутора страницах книжки Design Patterns?

Я конечно не знаю, что у вас будет в следующей статье, но на самом деле цепи считаются не так.


Рассмотрим простейший вариант — статическая цепь, то есть цепь в которой не надо считать переходные процессы.


Для её расчёта используется метод узловых потенциалов(чаще) или метод контурных токов(реже).


Преимущества: любая конфигурация сети, любые элементы (конденсаторы и индуктивности), переменный ток работает так же как и постоянные без оверхеда. Если интересно — пишите в личку.

Тема действительно интересная, я сам недавно сталкивался с распараллеливанием вычислений в Elixir, поэтому сделал небольшой рефакторинг и добавил основную основную фичу, значительно облегчающую распараллеливание — Task.


Читать по ссылке, а пока предлагаю взглянуть на код:


Весь длинный код работающего скрипта
defmodule Wordcount do
  @main_word "лошадь"

  defp count(text, word) do
    length(String.split(text, word)) - 1
  end

  defp do_proceed(file_path) do
    File.read!(file_path)
    |> count(@main_word)
    |> (fn (count) -> IO.puts "Found #{count} occurrence(s) of the word in file #{file_path}" end).()
  end

  def proceed(:async) do
    Path.wildcard("./OGENRI/*.txt")
    |> Enum.map(&Task.async(fn -> do_proceed(&1) end))
    |> Enum.map(&Task.await/1)
  end

  def proceed(:sync) do
    Path.wildcard("./OGENRI/*.txt")
    |> Enum.map(&do_proceed/1)
  end

  ### Example:
  #   benchmark
  #   benchmark(:sync)
  def benchmark(type \\ :async) do
    start_time = :os.system_time(:milli_seconds)
    proceed(type)
    end_time = :os.system_time(:milli_seconds)
    IO.puts "Finished in #{(end_time - start_time)} miliseconds"
  end
end

Вот конкретные различия между синхронной и асинхронной версией


def proceed(:sync) do
  Path.wildcard("./OGENRI/*.txt")
  |> Enum.map(&do_proceed/1)
end

def proceed(:async) do
  Path.wildcard("./OGENRI/*.txt")
  |> Enum.map(&Task.async(fn -> do_proceed(&1) end))
  |> Enum.map(&Task.await/1)
end

Пишем синхронный код — потом вуаля! — и он щелчком пальцев превращается в асинхронный. Добро пожаловать в functional programming!)

Статья хорошая, спасибо, вот только больно смотреть, когда для объяснения работы с Ecto вдруг оказался нужен Phoenix.

Elixir тоже наверно хорошо, если его кто-то действительно будет применять в телекоммуникациях, а не только в веб.

Что вы подразумеваете под "веб"? Программы, связывающие передачу данных через http в браузер и базу данных? Мне кажется на сегодняшний день веб это что-то большее. И поэтому MVC уже не "наше всё". И для веба нужны чуть более гибкие инструменты чем %мой_любимый_веб_фреймворк%.

Нет. На сколько я понимаю, ANTLR не работает в erlang?

Мне кажется, впринципе суть парсера в том, что он декларативный — во всех языках. А если нет — то это то, что автор статьи называет "велосипедом". А вот велосипеды уже разные — декларативный в ФП и императивный в ИП)

Если говорить на уровне "серьёзных книг", то после 1994 года, когда вышла "Design patterns" от GoF, реализовывать полиморфизм через наследование, а не через композицию — дурной тон.
Да и впринципе, посмотрите на современные реализации полиморфизма — сперва была мода duck typing во всяких там динамических языках, теперь — полная реализация интерфейса как к примеру в Rust.
Полиморфизм есть — наследования нету. Так что что-то у вас не сходится.

Теоретически такое можно отследить каким-нибудь статическим анализом, но я не встречал реализации пока что. И такие ошибки надо отлавливать в тестах.


А падает в данном случае зацикленный GenServer. Если add_student внутри использует cast — вызывающий процесс ничего не заметит. Если call — зависит от реализации, но если вы не отлавливаете ошибки — упадёт вызывающий процесс тоже.


В любом случае, скорее всего у вас должен быть супервизор который перезапустит или один или оба генсервера.

В принципе да, но мой комментарий не для автора статьи, а для читателей — ещё раз акцентирую внимание и представляю "правильный" кусок кода.

Если вы решите делать такое в реальном коде — функция new не приветствуется.


{:ok, school} = School.start_link
school |> School.add_student("Aimee", 2) # => :ok
school |> School.students_by_grade(2) # => ["Aimee"]
school |> School.students_by_grade # => [[grade: 2, students: ["Aimee"]]]

Мне кажется, что "умные дома" страдают не от отсутствия стандартов, а от отсутствия "стандартов".
Как только появится "ЗверУмныйДом на одном ДВД" — все сразу будут представлять себе "умный дом" именно так.

Если вы написали собственный механизм миграций — то и edeliver у надо будет рассказать как мигрировать.
Если вы используете ecto — то он и сам знает.
Вот что значит "на автомате"

По-моему, нигде в проекте на хранятся пользовательские данные. Если это картинки и файлы — в отдельной папочке, которая даже не обрабатывается beamом, а сервится прямо нгинксом.

mix edeliver migrate


Если экто — то на автомате

А если не пользоваться релизами, тогда как? Каждый раз git pull?

Что насчёт System.get_env в конфиге?

Все непонятные параметры — это синтаксический сахар к понятным параметрам.
Все очень хорошо описано на сайте elixir в разделе basic types

Information

Rating
3,261-st
Location
Тель-Авив, Тель-Авив, Израиль
Date of birth
Registered
Activity

Specialization

Backend Developer
Lead
From 900,000 ₽