Есть два способа создания дизайна программы. Один из них, это сделать его настолько простым, что в нем, очевидно, не будет недостатков. Другой способ — сделать его настолько запутанным, что в нем не будет очевидных недостатков.
Чарльз Энтони Ричард Хоар
На данный момент я серьезно занимаюсь программированием более 6 лет. Я хотел бы расказать о том, с какими технологиями и проектами мне приходилось работать.
C++ был моим основным языком программирования с 2005 года. Еще во время учебы я заинтересовался Qt.
Мой серьезный опыт в программировании начинается с весны 2008 года, когда мне предложили поработать в отделе распознавания речевых образов научно-исследовательского института проблем искусственного интеллекта. Как раз в то время в отделе начинали задумываться о переходе на Linux, в связи с этим необходимо было использовать библиотеки, позволяющие писать кросплатформенные приложения. В отделе была популярна WxWidgets, однако симпатии у меня эта библиотека не вызывала, поэтому я продолжил использовать свою любимую связку C++ и Qt, а для работы со звуком использовалась OpenAL. Проект, над которым я работал, носил название "Разработка автоматизированной компьютерной системы фоноскопической экспертизы цифровых фонограмм". Мной были разработаны, модифицированы и реализованы различные алгоритмы цифровой обработки речи. Проводились исследования в области автоматической сегментации речевого сигнала. Велись работы над обнаружением монтажа в цифровом сигнале. Много внимания было уделено выделению фонем из спектра речевого сигнала.
Впервые интерес к Java у меня появился где-то в 2009 году. В 2011 году я получил сертификат "Oracle Certified Professional, Java SE 6 Programmer".
Так получилось, что практически весь последний год я использовал Scala в 90% случаев. Впечатления исключительно положительные. Мне бы хотелось кратко, насколько это возможно, написать про этот замечательный язык программирования.
Развитие языков Java и C++ существенно замедлилось, и программисты, стремящиеся использовать самые современные технологии, обратили свои взоры на другие языки. Scala - весьма привлекательный выбор. Вероятно, это самый привлекательный выбор для программистов, стремящихся вырваться за рамки Java или C++. Scala имеет выразительный синтаксис, который выглядит весьма свежо после приевшихся шаблонов Java. Программы на этом языке выполняются под управлением виртуальной машины Java, что открывает доступ к огромному количеству библиотек и инструментов. Он поддерживает функциональный стиль программирования, не отказываясь при этом от объектно-ориентированного стиля, давая возможность осваивать новые парадигмы постепенно. Интерпретатор дает возможность быстро опробовать свои идеи, что превращает изучение Scala в весьма увлекательное занятие. Наконец, язык Scala является статически типизированным языком, что дает компилятору возможность находить ошибки, а вам не тратить время на их поиск в работающей программе.
Scala используется многими крупными компаниями, такими как Twitter, LinkedIn, SONY, IBM, Deutche Bank, UBS, Foursquare, Amazon, NASA, Autodesk, Siemens. Подробнее можно почитать в разделе Scala in the Enterprise. Поскольку Scala является языком программирования общего назначения, она может успешно применяться в самых разнообразных областях, например при создании:
Рассмотрим типичный пример кода, написанного на Java.
public class Person implements Serializable {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Person withFirstName(String firstName) {
return new Person(firstName, lastName);
}
public Person withLastName(String lastName) {
return new Person(firstName, lastName);
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Person person = (Person) o;
if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
return false;
}
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
return false;
}
return true;
}
public int hashCode() {
int result = firstName != null ? firstName.hashCode() : 0;
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
public String toString() {
return "Person(" + firstName + "," + lastName + ")";
}
Напишем несколько строк, показывающих, как использовать этот класс:
Person mr = new Person("Bob", "Dobbelina");
Person miss = new Person("Roberta", "MacSweeney");
Person mrs = miss.withLastName(mr.getLastName());
case class Person(firstName: String, lastName: String)
Это все. Мы можем использовать этот класс так же как в Java, даже более компактно:
val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)
Если необходимо иметь JavaBeans методы доступа к полям firstName и lastName - можно сгенерировать их автоматически, используя аннотацию @BeanProperty, как показано ниже:
case class Person(@BeanProperty firstName: String, @BeanProperty lastName: String)
На Scala можно писать в императивном стиле:
def formatPersons(people: List[Person]): String = {
val result = new StringBuilder();
for (i <- 0 until people.size) {
val firstName = people(i).firstName
if (firstName != "test") {
result.append(firstName)
if (i < people.size - 1) {
result.append(", ")
}
}
}
return result.toString
}
Но, наличие мощной системы вывода типов и возможность использовать функциональный подход позволяют переписать предыдущий пример следующим образом (заодно исправляя допущенную ранее ошибку):
def formatPersons(people: List[Person]) = people map (_.firstName) filter (_ != "test") mkString ", "
Приведу несколько примеров из статьи 10 Scala One Liners to Impress Your Friends, чтобы показать красоту и выразительность функционального подхода.
// Умножение каждого элемента списка на 2:
(1 to 10) map { _ * 2 }
// Подсчет суммы всех чисел в списке:
(1 to 1000).reduceLeft( _ + _ )
(1 to 1000).sum
// Разбиение списка по заданному критерию:
val (passed, failed) = List(49, 58, 76, 82, 88, 90) partition ( _ > 60 )
// Поиск минимума в списке
List(14, 35, -7, 46, 98).reduceLeft ( _ min _ )
List(14, 35, -7, 46, 98).min
// Поиск максимума в списке
List(14, 35, -7, 46, 98).reduceLeft ( _ max _ )
List(14, 35, -7, 46, 98).max
val result = dataList.par.map(line => processItem(line))
val wordList = List("scala", "akka", "play framework", "sbt", "typesafe")
val tweet = "This is an example tweet talking about scala and sbt."
(wordList.foldLeft(false)( _ || tweet.contains(_) ))
wordList.exists(tweet.contains)
val fileText = io.Source.fromFile("data.txt").mkString
val fileLines = io.Source.fromFile("data.txt").getLines.toList
val results = XML.load("http://search.twitter.com/search.atom?gitq=scala")
Ниже приведен небольшой список ссылок на хорошее описание некоторых возможностей Scala, которых нет в Java.
Акторы представляют собой механизм параллельных вычислений, альтернативный традиционным механизмам на основе блокировок. Отсутствие блокировок и совместно используемых данных в акторах упрощает разработку программ и позволяет не опасаться взаимоблокировок и состояний гонки за ресурсами.
Ранее Scala предоставляла простейшую реализацию акторов. Более совершенные реализации акторов доступны на сторонних ресурсах, самым известным из которых является проект Akka.
Начиная с версии 2.10, в Scala была включена поддержка акторов Akka Actors.
Приведем классический HelloWorld, написанный на Scala с использованием акторов, с сайта akka.io.
case class Greeting(who: String)
class GreetingActor extends Actor with ActorLogging {
def receive = {
case Greeting(who) ⇒ log.info("Hello " + who)
}
}
val system = ActorSystem("MySystem")
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
greeter ! Greeting("Charlie Parker")
Более серьезный пример параллельного вычисления числа π можно посмотреть в разделе Getting Started Tutorial,
а также почитать про Dataflow Concurrency, Parallel collections и Futures and Promises.
Стоит отметить, что в последнее время интерес к Scala сильно возрос и продолжает расти, причем не только в академических кругах.