Pull to refresh
-14
0

Программист

Send message

Как я писал свой распределенный мессенджер на Scala/fs2 и немного lock-free. Часть 1: Архитектура и бизнес-логика

Level of difficultyMedium
Reading time14 min
Views2.5K

Привет, хабр!

Данная задача в разных вариациях мне давалась на нескольких собеседованиях несколько лет назад. Хоть мой дизайн и проходил, мне стало интересно реализовать это в коде с нуля. Сыроватый и сильно урезанный по функционалу MVP готов, ссылка на github будет под катом. Пока что мной запланировано 3 статьи - эта, по бэкенду и по фронту. Будет много кода на scala, много котов (cats effect), стримов (fs2), пара lock-free техник, scala js, и постараюсь сделать так, чтобы мозг от всего этого не взорвался.

Все, кому интересно - добро пожаловать под кат.

Читать далее
Total votes 12: ↑12 and ↓0+12
Comments4

Naive Spellchecking, или поиск ближайших слов из словаря по метрике Левенштейна на Scala

Reading time6 min
Views3K
Приветствую! В этой статье будет показан алгоритм поиска ближайших к заданному слов из корпуса в терминах метрики Левенштейна. Наивным spellchecking-ом назван потому, что не учитывает ни морфологии, ни контекста, ни вероятности появления скорректированного слова в предложении, однако в качестве первого приближения сойдет вполне. Также алгоритм может быть расширен на поиск ближайших последовательностей из любых других сравнимых объектов, нежели простой алфавит из Char-ов, и, после допиливания напильником, его можно приспособить и для учета вероятностей появления скорректированных слов. Но в данной статье сосредоточимся на базовом алгоритме для слов определенного алфавита, скажем, английского.

Код в статье будет на Scala.

Всех заинтересовавшихся прошу под кат.
Читать дальше →
Total votes 11: ↑11 and ↓0+11
Comments0

Используем Bash в SQL-стиле

Reading time5 min
Views13K
Приветствую! Данная небольшая статья призвана осветить некоторые аспекты применения Bash для анализа файлов в SQL-стиле. Будет интересна для новичков, возможно, опытные пользователи также найдут для себя что-нибудь новое.

Структура задачи:

  • projects
    1. project1/ — проекты
      • conf/
        • <run_configurations>*.conf — конфигурации построения отчетов по таблицам
      • reports/
        • <run_configurations>/
          • report1.json — сами отчеты, содержат статистику по таблицам Apache Hive
          • report2.json
    2. project2/
      ...

Надо: найти просроченные отчеты.

Итак, расчехляем Bash, открываем отдельный терминал для man-ов и приступаем)

Всех, кому интересно — прошу под кат.
Читать дальше →
Total votes 14: ↑14 and ↓0+14
Comments36

Разбавляем асинхронное программирование функциональным на Scala

Reading time7 min
Views9.5K
Приветствую! В этой статье будет показано, как, имея на руках обычные Future-ы, сделать в scala подобие корутин и асинхронные stream-ы. Этакий небольшой туториал по функциональному программированию.

Что это и зачем


Что такое Future человеческим языком
Future — это сущность, описывающая результат некоторых вычислений, который мы получим не сразу, но в будущем. Но есть одна особенность: зачастую мы, не зная еще результата, точно знаем, что мы с ним будем делать. Например, мы попросили у сервера какой-то конфиг, и теперь у нас есть Future[Config]. Сам конфиг мы еще не получили, но точно знаем, что, когда получим, то достанем из него адрес и по этому адресу попросим у сервера картинку (config => Future[Image]). И Future[Config] способна изменяться таким образом, чтобы мы вместо конфига и потом картинки могли получить сразу картинку. Сущности, способные комбинироваться таким способом, называются монадами.

К сожалению, простое последовательное комбинирование 2х и более асинхронных операций (загрузить конфиг, а потом картинку по адресу из конфига как пример) — это все, на что способны обычные Future-ы в качестве монад. Они не позволяют ни сохранять состояние, ни делать циклы из асинхронных операций, ни выдавать несколько (или бесконечно много) значений. Вот этими недостатками мы сейчас и займемся.

Давайте для определенности представим некий виджет. Он ждет конфиг, который обновляется с определенной периодичностью, загружает по адресу из конфига значение (например, температуру), и рисует на экране текущее значение, минимум, максимум, среднее и так далее. И все это делает в цикле, да еще и асинхронно.

Применив знания из этой статьи, мы сможем этот процесс описать примерно так:

Код
// Про 'FState' - далее, пока же просто примем, что это - такая необычная Future
def getNextConfig: FState[Config]
def getTemperature(from: String): FState[Int]

case class State(temperature: Int, sumTemp: Long, count: Int) {
  def isGood = ...
}

// Как видим, получается единый асинхронный алгоритм с состоянием, 
// которое извне этого алгоритма не видно
val handle = 
  while_ ( _.isGood)
  {  for (
        config <- getNextConfig();
        if (config.isDefined);  // пустой конфиг - прекращаем выполнение
        nextValue <- getTemperature(config().source);  // грузим значение температуры
        state <- gets[State];  // тут мы берем текущее состояние
        newState = State(nextValue, state.sumTemp + nextValue, state.count + 1);
        _ <- puts(newState);  // .. и меняем его
        _ <- runInUiThread { drawOnScreen(newState) }
  ) yield() }


Или вот так:

Код
val configs: AsyncStream[Config] = ... // получаем откуда-то stream конфигов

def getTemperature(from: String): FState[Int]

case class State(temperature: Int, sumTemp: Long, count: Int)

// Получается то же самое, только вместо зависимости 'getNextConfig'
// мы, по сути, передаем сами данные - stream из конфигов
val handle = 
  foreach(configs) {
    config => for (
        nextValue <- getTemperature(config().source);  // грузим значение температуры
        state <- gets[State];  // тут мы берем текущее состояние
        newState = State(nextValue, state.sumTemp + nextValue, state.count + 1);
        _ <- puts(newState);  // .. и меняем его
        _ <- runInUiThread { drawOnScreen(newState) }
    ) yield()  
  }


Всех, кто заинтересовался, прошу под кат.
Читать дальше →
Total votes 18: ↑18 and ↓0+18
Comments13

Information

Rating
4,325-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity