Scala-wyliczenie a Case-klasy
Stworzyłem aktora akka o nazwie LogActor. Logaktorzy odbierają metody obsługi wiadomości od innych aktorów i rejestrują je do określonego poziomu dziennika.
Mogę rozróżnić różne poziomy na dwa sposoby. Pierwszy:import LogLevel._
object LogLevel extends Enumeration {
type LogLevel = Value
val Error, Warning, Info, Debug = Value
}
case class LogMessage(level : LogLevel, msg : String)
Drugi: ( EDIT )
abstract class LogMessage(msg : String)
case class LogMessageError(msg : String) extends LogMessage(msg)
case class LogMessageWarning(msg : String) extends LogMessage(msg)
case class LogMessageInfo(msg : String) extends LogMessage(msg)
case class LogMessageDebug(msg : String) extends LogMessage(msg)
Która droga jest bardziej efektywna? czy dopasowanie wielkości liter lub wartości enum zajmuje mniej czasu?
(przeczytałem to pytanie, ale nie ma żadnej odpowiedzi odnoszącej się do runtime issue)
3 answers
Obowiązuje"Nie Optymalizuj przedwcześnie". Nie wierzę, że różnica między nimi w ogóle ma znaczenie, w porównaniu z czasem, który spędzasz przekazując Wiadomości do swojego aktora lub faktycznie je rejestrując. Ale spodziewam się, że najlepszą wydajnością będzie stworzenie Javy enum
(która może być łatwo dostępna i używana ze Scali) do logowania poziomów zamiast Scali Enumeration
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-12 13:29:56
Całkowicie zgadzam się z Alexeyem i Dennisem, że wydajność w tym przypadku nie powinna ci przeszkadzać, ponieważ jest to bardziej problem optymalizacji kompilatorów, a nie programistów i nie wyobrażam sobie scenariusza, w którym różnica w wydajności mogłaby stać się zauważalna.
To, co powinno ci przeszkadzać, to spójność kodu i w tym sensie powinieneś oprzeć swoją decyzję na tym, czy chcesz trzymać się starego podejścia Java-owskiego z enumami, które jest poprawnie opisane w Twoim pierwszym przykładzie, czy ostatnio coraz popularniejszy wzór algebraicznych typów danych (ADT). Ten ostatni próbowałeś reprezentować w swoim drugim przykładzie, ale z pewnymi błędami.
Poniżej znajduje się sposób poprawnego rozwiązania problemu za pomocą wzorca ADT.
ADT Solution # 1
// 1. marked `sealed` to make pattern matching exhaustive
// 2. used a trait to avoid double storage of msg` and
// make the inheritance easier
sealed trait LogMessage { def msg : String }
// A better solution for isolation than names like "LogMessageError".
// Allows you to either address the members with a namespace like
// "LogMessage.Error" or do "import LogMessage._" and address them
// directly
object LogMessage {
case class Error (msg : String) extends LogMessage
case class Warning (msg : String) extends LogMessage
case class Info (msg : String) extends LogMessage
case class Debug (msg : String) extends LogMessage
}
ADT Solution # 2
Przepraszam, że pewnie mieszam Ci w głowie, ale warto zauważyć, że istnieje również alternatywne podejście ADT do podobnych sytuacji, które jest trochę podobne do tego, które kierujesz z enumami.
sealed trait LogLevel
object LogLevel {
case object Error extends LogLevel
case object Warning extends LogLevel
case object Info extends LogLevel
case object Debug extends LogLevel
}
case class LogMessage ( level : LogLevel, msg : String )
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-12 16:58:07
Jedną z najczęstszych operacji dla loggera jest porównanie bieżącego poziomu logowania do poziomu wiadomości, a dzięki enums otrzymujesz go za darmo, podczas gdy przy konfiguracji z klasami przypadków będzie to nieco kłopotliwe. I zgadzam się z @ AlexeyRomanov: dopasowanie nie powinno być tu wąskim gardłem.
EDIT: pod względem wydajności, match with case classes użyje instanceof w bajtowym kodzie, podczas gdy dla enums kompilator Scala wygenerował kod, z którym żaden z dekompilatorów nie był w stanie sobie poradzić. Informatyka wydawało się, że używa equals
. Więc technicznie wyliczenia mogą być szybsze, ale w rzeczywistości nie będzie różnicy w wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-12 15:03:31