В мире JVM уже давно предпринимаются попытки заместить Java чем-то более пристойным. Наиболее успешной такой попыткой, по всей видимости, на сегодняшний день является Scala . Тут вам и сообщество программистов, и куча фреймворков, и вакансии — все что угодно. Но и Scala далека от идеала. Среди наиболее существенных недостатков языка можно отметить его относительную сложность (что признает даже Одерски) и, что намного важнее, медленную скорость компиляции, а также требовательность к ресурсам во время этой компиляции. Поэтому такие языки под JVM, как Kotlin, Gosu и Ceylon все еще представляют собой интерес.

Когда мне захотелось ознакомиться с одним из этих языков, Ceylon отпугнул меня своим синтаксисом. Gosu выглядел куда более приятно. Но в примечаниях к последнему релизу языка среди прочего говорилось об устаревании оператора неравенства <> и что дескать вместо него теперь нужно использовать != . С такой нестабильностью я мириться не готов. А вот Kotlin и порадовал синтаксисом и произвел впечатление стабильного языка. К тому же, его разрабатывают наши соотечественники из JetBrains, и, понятное дело, полноценная поддержка со стороны IntelliJ IDEA также уже имеется. На нем я и решил остановиться.

Прочитав 130 страниц полного описания языка я сделал следующие выводы:

  • Язык очень похож на Scala, только проще и быстро компилируется. В частности, скорость компиляции не медленнее, чем в Java, разработчики языка ставят одной из своих главных целей. Из наиболее существенных отличий от Scala следует отметить полное отсутствие каких-либо имплиситов. Однако прикручивать методы к уже существующим final классам можно, как и в Scala.
  • Язык компилируется не только под JVM, но и в JavaScript. Это хорошо, можно писать UI и бэкенд на одном языке.
  • Все основные элементы ФП присутствуют — замыкания, хвостовая рекурсия , REPL , функции высших порядков, map / reduce / filter, автоматический вывод типов, паттерн матчинг, АТД (кстати, здесь case классы называются data классами) и так далее. Каррирования, как в Scala, похоже нет, но если функция принимает последним аргументом другую функцию, можно использовать синтаксис в стиле lock(lock) { body } , что решает ту же самую проблему.
  • Коллекции бывают неизменяемые (List, Set, Map) и изменяемые (MutableList, MutableMap, …), то же самое с переменными (val, var).
  • В языке есть немало интересных решений. Например, меня удивили делегаты, через которые, помимо прочего, сделаны ленивые вычисления. Еще есть такая фишка под названием smart casts, благодаря которой код if(x is String) { print(x.length) } компилируется и тайпчекается без дополнительного приведения переменной к типу String. Немного напоминает Rust .
  • Вместо Option/Maybe в языке используются nullable типы. С одной стороны, они дают такие же статические гарантии отсутствия NPE, с другой — более эффективны, чем Option, так как работают поверх все тех же null’ов, то есть, не приводят к использованию дополнительных классов. Что опять-таки напоминает Rust.
  • В Kotlin также есть ковариация и контравариация , но благодаря использованию ключевых слов in и out работа с ними становится намного проще и понятнее. Если тип помечен как in, методы класса могут принимать его на вход (консьюмер), если же out — методы возвращают тип (продьюсер). И не нужно помнить о том, что in — это контравариация, а out — ковариация, все просто и понятно.
  • Вообще, язык выглядит очень продуманно. Поля класса по умолчанию не являются public, при выводе data-классов перед значениями полей выводятся их имена, функции можно объявлять прямо в пакете без всяких дополнительных package object’ов и так далее. Всякие такие мелочи внушают доверие.

Чтобы попрактиковаться в программировании на Kotlin, я решил написать на нем одну программку, которую в свое время я уже писал на Scala, а также на Rust. Программа эта принимает текстовый файл, выдирает из него все URL, и выдает на выходе HTML-код со списком этих ссылок, используя в качестве тестов ссылок title соответствующих страниц. Вот что у меня получилось:

package me. eax . examples . shownotegen

import org. apache . http . client . methods . *
import org. apache . http . impl . client . *
import java. util . regex . *
import java. io . *

fun defaultUserAgent ( ) =
«»»Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, «»» +
«»»like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60″»»

fun getTitle ( url : String ) : String {
val req = HttpGet ( url )
req. setHeader ( «User-Agent» , defaultUserAgent ( ) )
try {
HttpClients. createDefault ( ) use {
it. execute ( req ) use { resp — >
val entity = resp. getEntity ( )
val charset = run {
val contentType = entity. getContentType ( ) . getValue ( ) ?: «»
val pattern = Pattern. compile ( «charset=(.*)» )
val matcher = pattern. matcher ( contentType )
if ( matcher. find ( ) ) matcher. group ( 1 ) else «UTF-8»
}
val title = run {
val body = entity. getContent ( ) . readBytes ( ) . toString ( charset )
val pttrn = Pattern. compile ( «»»(?is)<title>(.*?)</title>»»» )
val matcher = pttrn. matcher ( body )
matcher. find ( )
matcher. group ( 1 )
}
return title. replaceAll ( «»» s +»»» , » » ) . trim ( )
}

}
} catch ( e : Exception ) {
return «[NO TITLE: ${e.getMessage()}]»
}
}

fun processFile ( fileName : String ) {
val data = File ( fileName ) . readText ( Charsets. UTF_8 )
val matcher = Pattern. compile ( «»»https?:// S +»»» ) . matcher ( data )
println ( «<ul>» )
while ( matcher. find ( ) ) {
val url = matcher. group ( )
println ( «<li><a href= » $url «» >${getTitle(url)}</a></li>»» )
}
println ( «»</ul>»» )
}

fun printUsage ( ) {
val executableName = System. getProperty ( «»sun.java.command»» )
println ( «»Usage: $executableName input.txt»» )
System. exit ( 1 )
}

fun main ( args : Array < String > ) {
when ( args. size ( ) ) {
0 > printUsage ( )
else > processFile ( args [ 0 ] )
}
}

Обратите внимание на использование метода use. В Kotlin он используется вместо try with resoruces в Java. Как и ScalaKotlin позволяет вызывать методы при помощи инфиксной записиа не через точку. Объяснение тогочто делает функция run

admin

Share
Published by
admin

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

1 месяц ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

1 месяц ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

1 месяц ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

1 месяц ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

1 месяц ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

1 месяц ago