Pull to refresh

Comments 24

Библиотека акторов Akka для скалы, например, предлагает возможность актору изменять в процессе работы своё состояние, изменяя набор обрабатываемых сообщений (состояния при этом ещё можно складывать/доставать из стека), таким образом удобно писать логику работы и реализовывать конечные автоматы.
Из описания совершенно не видно этой фичи в Pony. Там предлагается всё это делать через известно что?
Я хоть и работал с Akka, но к сожалению плохо представляю, о чем ведется речь. Буду рад любым примерам, чтобы я мог возможно воспроизвести тоже самое на Пони.
class MyFlappingPingPongActor extends Actor {
    case class Ping()
    case class Pong()
    case class Miss()
    case class Failure(msg: String)

    def successfulPing: Receive = {
       case Ping => {
           sender ! Pong()
           context become failPing
       }
       case Pong => {
            sender ! Ping()
       }
    }

    def failPing: Receive = {
        case Ping => {
            sender ! Miss()
            context become successfulPing
        }
        case _ => {
            sender ! Failure("I'm sad, no actions until I'm happy again!")
        }
    }

    def receive = sucsessfulPing
}

Как-то так. Я уже плохо помню скалу, писал по памяти.
Так вы вроде обычный обмен сообщениями между акторами показали :)
Нет, смотрите: наш актор бывает в двух состояниях. Изначально он в состоянии successfulPing, в котором он умеет обрабатывать сообщения Ping и Pong, отвечая на них корректным результатом. Все остальные сообщения приводят к ошибке (и, кажется, то ли просто игнорируются аккой, то ли приводят к падению актора, не помню). При этом пинги кроме ответа переводят актор во второе состояние — failPing, в котором мы умеем отвечать на пинг промахом и переходить в первое состояние, а на все остальные сообщения отвечаем отправителю «печалька».
То есть, поведением актора управляет не какая-то сохранённая переменная, а просто выбранная функция-обработчик, которая умеет обрабатывать какие-то типы. Если бы я придумал какую-то более сложную логику, я бы мог написать в этих двух функциях вообще непересекающийся набор типов сообщений, которые они обрабатывают. Таким образом в акке легко можно сделать конечный автомат, который будет переходить между состояниями, и не надо будет писать какую-то сложную логику, которая будет проверять состояние перед обработкой всех возможных типов сообщений. Состоянием будет являться сама функция-обработчик актора, которой достаточно будет знать только доступные именно ей переходы.
Спасибо за доступное объяснение.
На данный момент такой прозрачности нету, однако задача меня заинтересовала, поэтому попробую набросать что нибудь взаимозаменяемое и удобное.
> Все остальные сообщения приводят к ошибке (и, кажется, то ли просто игнорируются аккой, то ли приводят к падению актора, не помню).

вот это важно, например, в cloud haskell, есть примитив receiveWait, который позволяет обрабатывать сообщения таким же образом, при этом можно явно контролировть, что произойдёт с остальными сообщениями (в случае добавления matchAny они будут прочитаны из MailBox и их можно обработать, иначе они там остаются).

В остальном, никакой разницы между Erlang (насколько я его знаю) или Haskell я лично не заметил, код так пишут всегда…
Я не хочу врать, но возможно, что в акке это вообще настраивается выставленными политиками — так же, как и разнообразные политики доставки, что делать при падении актора и т.п.
В пони этого всего я не вижу.
при этом можно явно контролировть, что произойдёт с остальными сообщениями (в случае добавления matchAny они будут прочитаны из MailBox и их можно обработать, иначе они там остаются).

В scala акторах (когда они еще были) было такое же поведение.
В akka его признали не эффективным и по умолчанию убрали. Его можно вернуть при помощи Stash.
По умолчанию же все не обработанные сообщения попадают в метод unhandled, который, если не вдаваться в подробности, игнорирует все сообщения.
Crystal… Прямо и четко говорю, что это супер производительный клон Ruby. Больше сказать нечего, весь он пропитан его духом.
я бы добавил что очень и ОЧЕНЬ сырой клон Ruby
«Go, Rust, Nim, Crystal» и, все они очень круты в своих определенных областях.
А в какой области крут Pony?
Какие языки Pony пытается потеснить? Go, DLang?
Как у него с производительностью?
Как ни странно, на все вопросы существуют ответы в статье. К примеру, 2 пейпера расскажут о бенчмарках и производительности в сравнении тех же Scala, Akka, Erlang.
Бесполезный бенчмарк для сравнительной оценки. Не указаны настройки противопоставляемых систем. Не понятно что по оси ординат откладывается, хотя мож я просмотрел. Вот к примеру покрытый пылью времени результат акка, который даже с учетом разности в железе имеет большую пропускную способность и даже несмотря на наличие stw.
Графические бенчмарки подразумевают под собой одно окружение. На абсциссе указано повышение ядер, на ординате скорость относительно Erlang.
Текстовые бенчмарки из другого пейпера имеют описание систем, на которых тестировалось максимальное количество сообщений в секунду. И там далеко не монстр, в сравнении с тем, что указан по вашей ссылке.
Юнион очень похож на кортеж, только используется для обобщения возможных типов. Особый вид дженерика.

Дженерики здесь совершенно не причем и на кортеж оно не фига не похоже. Оба есть ADT.
Многие моменты исходили из официальной документации, в том числе про похожесть на кортежи и вестимо, в плане семантики. Дженерики — своя отсебятина, поэтому вполне допускаю свою ошибку ;)
сейчас скорость передачи между акторами достигает 20кк в секунду
А чего так медленно? Судя по бенчмаркам Akka.NET у них 28КК было в начале года. У JVM-овской акки 50КК, ибо кодовую базу успели нормально оптимизировать.
Оп. Пони на хабре! :)

Поглядываю на этот язык, очень и очень нравится, но чего-то реального пока совсем не пробовал писать.

У меня вот вопрос есть: как определить, что же за ошибка произошла, если метод может упасть по нескольким условиям?
Примерно так:

fun a()? {
if 1 then error end
if 2 then error end
}

Как в методе, вызывающим a() узнать, что это была за ошибка: 1 или 2? Было дело, я гуглил, и встречал в обсуждениях что-то похожее на «если метод возвращает несколько ошибок — это неправильный метод». Но ведь это… Неправильно же.
Сейчас есть непонятная ситуация со стектрейсом, но предполагаю, что он будет.
А пока можно отслеживать принтами перед возникновением ошибки и в реальных программах — обеспечивать правильный вывод ошибок, через примитивы (Очень хороший пример у них в options пакете).

actor Main
  var _env: Env
  
  new create(env: Env) =>
    _env = env
    env.out.print("Hello, sandbox.")
    
    try
      err(1) // or err(2)
    else
      env.out.print("Error in program")
    end
    
  fun err(n: U64) ? =>
    if n == 1 then
      _env.out.print("Error in one if")
      error
    end
    
    if n == 2 then
      _env.out.print("Error in two if")
      error
    end

Одинарная кавычка оставила неприятный осадок на целую ночь.
UFO just landed and posted this here
Нативный, компилируется через LLVM.
Sign up to leave a comment.

Articles