Java на habrahabr

Февраль 6, 2012

 

JAVA / [PODCAST] «Разбор полетов» — episode 9 — Индусоустойчивость

Творческий коллектив редакции подкаста «Разбор полетов» представляет вашему вниманию очередной девятый выпуск разговорно-болтологического IT-тематического подкаста;.
В этом выпуске:

Java на habrahabr

Январь 1, 2012

 

JAVA / [Перевод] Scala хуже, чем Java. Как минимум, для половины Java проектов

Итак, в своем посте (прим.пер. Да, Вирджиния, Scala сложна!) я согласился с тем, что Scala слишком сложна для большей части Java разработчиков. Тот пост вызвал немало дискуссий, большая часть которых исказила его смысл. Теперь я пишу снова, надеясь пояснить, о чем я, собственно, говорил и зачем мне все это нужно.

Но сначала обо мне. Меня зовут Дэвид Поллак.

Блог о программировании

Ноябрь 9, 2011

 

Поездка в Санкт-Петербург

Прошло уже больше месяца, с тех пор как я обещал друзьям написать про свою поездку в Питер. Было очень много разных дел по работе, в итоге только сейчас смог дописать.

Как все было.

Где-то месяц назад, совершенно случайно, увидел объявление, что 1 октября в Питере будет проводиться Scala Day.
Решил зарегистрироваться, хотя вероятность поездки была очень мала - было много дел по работе. В конечном итоге поехать удалось, но полноценно побывать на Scala Day у меня не получилось. Буквально заглянул меньше чем на час.

Для тех кто не в курсе - Scala это такой язык программирования, очень мощный и интересный. За последние несколько лет мне удалось "заразить" программированием на Scala моих многих знакомых и друзей. Мы время от времени организуем небольшие встречи-семинары-тусовки, о которых возможно расскажу позднее.

Итак, про поездку.

Стояла отличная осенняя погода.
Начитавшись страшных отзывов про трассу Москва-Санкт-Петербург, я решил поехать не сразу в Питер, а заехать по дороге в Великий Новгород.
Во-первых всегда было интересно побывать в этом городе, а во-вторых хотелось нормально отдохнуть после дороги и приехать в Питер свежим с утра.

Фото из Великого Новгорода


Великий Новгород понравился, если получится советую там побывать.

Что касается автомагистрали. Нельзя сказать, что она вся такая страшная и убитая. Я ожидал намного хуже. Конечно были довольно скверные отрезки, но были и участки с хорошим покрытием. Также было видно, что дорогой занимаются, в некоторых местах ведутся ремонтные работы, что уже очень хорошо.
Так что в целом, дорогой я доволен и обратный путь мы проделали за один раз - выехали из Питера ранним утром, к вечеру уже были дома.

Плохая дорога


Нормальная дорога

Про проживание в Санкт-Петербурге - остановились в мини-отеле. Стоимость ночлега не большая - 2000 руб за ночь. Номер вполне приличный.
Правда мне показалось, что там немного холодно и сыро и я кажется немного простыл (возможно дело не в отеле... у меня так каждый раз, когда приезжаю в Санкт-Петербург - простываю).

Машину на ночь пришлось оставить на Литейном, потом нашел платную парковку.
Конечно был культурный шок от двора...

Про Scala встречу.

Место проведения Scala встречи ("БИ Ингрия") нашел довольно просто. БИ - оказывается означает Бизнес-Инкубатор. Несмотря на зловещее название, оказалось, что это обычное здание и с добродушным охранником, который объяснил куда идти.

БИ ИНГРИЯ

Я пришел где-то на час позже начала, в аудитории было очень много людей, многие стояли вдоль стенок.
Пересказывать все, что было смысла не вижу, т.к. можно посмотреть видео здесь: http://www.e-legion.ru/blog/
Вот пару фотографий:

Scala программисты

Все лекции снимались на видеокамеру

Лично меня заинтересовал Scala PlugIn для IDEA. Думаю это вообще самая болевая точка для Scala-сообщества - нормальный редактор для Scala.

В целом само мероприятие было интересным, довольно многолюдным (в хорошем плане), с кофе-брейком и нормальным WiFi-ем (не то, что на GDD2011).

Кстати про WiFi и интернет. Пока лекторы (разработчики IDEA) в самом начале объясняли "зачем нужен нормальное IDE для Scala", мне за это время удалось скачать IDEA вместе со Scala-плагином и потом, в почти синхронном режиме, повторять демонстрацию. Правда почему-то у меня не всё получилось,
как будет время - попробую разобраться.

К сожалению, у меня был всего один свободный день, а город посмотреть очень хотелось (до этого был в Питере еще студентом, когда приезжал к друзьям в гости на пару дней, да и то тогда в основном пьянствовали...). В итоге пришлось позорно сбежать со Scala Day, о чем конечно же сожалею.

Зато немного успел погулять по Питеру. Вот фото с Исаакиевского Собора:

фотка Санкт-Петербурга

Java на habrahabr

Август 5, 2011

 

JAVA / Akka для Java разработчика (часть 1)

В последнее время появилось довольно много языков программирования, которые используют для JVM как платформу для выполнения. Одним из наиболее «горячих» тем для обсуждения в последнее время является Scala. В этой статье я не буду рассматривать заслуженно это или нет, просто хочу рассказать как можно использовать средства этого языка используя Java и не написав ни одной строчки на Scala.

Блог о программировании

Июль 19, 2011

 

Мои хинты для Netbeans 7

Недавно нужно было заново установить Netbeans 7.
Вот некоторые действия, которые всегда приходится делать после установки "коробочной" версии,
а именно: поддержка Scala, интерфейс на английском и quick file chooser.

Установка

Заходим на официальный сайт: netbeans.org
Нажимаем на [Download FREE] и переходим на ссылку http://netbeans.org/downloads/index.html
Скачиваем, устанавливаем и запускаем.

Итак, что приходится делать:

0. Обновления.

На всякий случай проверить наличие обновлений:
Меню → Help → Check for Updates

1. Русский → English

Чтобы вернуть обратно английский нужно:
- Найти файл "netbeans.conf" (для Windows-пользователей: он должен находится где-то здесь - "C:\Program Files\NetBeans 7.0\etc\" )
- Указать в настройках --locale en_US

netbeans_default_options="МНОГО_БУКВ --locale en_US"

2. File Chooser

Сразу же установить плагин Quick File Chooser:
Меню → Тools → Plugins → Available Plugins
Это намного более шустрый и удобный (на мой взгляд) диалог для выбора файлов.

3. Scala

Ставим plugin для работы со Scala.
Для версии 2.8.x: http://plugins.netbeans.org/plugin/36598/nbscala-2-8-x
Подробнее можно прочитать на вики нетбинсов:
http://wiki.netbeans.org/Scala
или на портале с плагинами:
http://plugins.netbeans.org/

Блог о программировании

Июль 15, 2011

 

Scala и пустота

Scala и пустота

В Scala есть несколько разных сущностей для обозначения несуществующих, пустых или неопределенных объектов.
Начнем с самого привычного для Java-программистов случая.

Null

Null – это trait. Объект null (с маленькой буквы) — это как раз и есть объект типа Null. Он находится внизу иерархии типов в Scala, в противовес AnyRef.
Благодаря этому вы всегда можете как-бы "занулить" любую ссылку, т.е. присвоить ссылки значение null:

scala> var x = "String" x: java.lang.String = String scala> var i = List(3) i: List[Int] = List(3) scala> i = null i: List[Int] = null scala> x = null x: java.lang.String = null

Null работает только для ссылочных типов, для более общего случая, есть "ничто (Nothing)" .

Nothing

Nothing – это тоже trait. Nothing находится на самом дне иерархии типов, в противовес Any. Соответственно, это более общий тип, чем Null и подходит даже для AnyVal объектов (числа, буквы, правда/ложь и т.д.).

В отличие от Null, Nothing не может иметь экземпляров (на то оно и ничто).
Другими словами нет аналога null для Nothing.

Возникает вопрос, где такое самое "нижнее ничто" может использоваться?
В документации по API можно найти несколько примеров:

// пакет scala.sys def error(message: String): Nothing = throw new RuntimeException(message)

Этот метод никогда ничего не возвращает, поэтому возвращаемый тип Nothing.

Unit

Тип Unit – чем-то похоже на void, который исползуется в Java. В Scala тип Unit используем тогда, когда хотим показать, что функция возвращает пустое значение (но все-таки что-то возвращает, хоть и пустое).

Если открыть документацию, то можно увидеть что:

class Unit extends Any with AnyVal

Внимание! AnyVal, а не AnyRef. Это значит, что Unit это не ссылочный тип ( в отличие от Null). Можно сказать, что Unit-у как бы "ближе по родству" будут числа, буквы и другие примитивные типы (которые тоже AnyVal).

В отличие от Nothing, Unit повезло больше. Он может иметь свой объект, правда в единственном экземпляре. Он обозначается двумя круглыми скобками: (). Например:

scala> val u = () u: Unit = ()

Другими словами Nothing уместен тогда, когда функция в принципе ничего не возвращает, а Unit – это когда возвращает, но оно пустое.
Это отличие существенно. Например результат вызова функции с Unit может быть присвоено (в Java с void такой фокус не выйдет).

scala> def foo():Unit = {} foo: ()Unit scala> val u = foo() u: Unit = ()

Nil

Nil – пустой список (extends List[Nothing]).
Поскольку Nil – это список, хоть и пустой, у него как у любого списка есть метод :: (два двоеточия), с помощью которого удобно создавать списки:

scala> var x = 1 :: 2 :: Nil x: List[Int] = List(1, 2)

Это возможно благодаря тому, что название метода заканчивается на : (двоеточие), в таком случае метод применяется к правому операнду (работает для операторной нотации вызова метода).

Другими словами, это аналогично вызову: (Nil.::(2)).::(1)

None

None – это такой хитрый объект, который используется в случае, если мы хотим получить что-то, например, из Map, а его там нет.

Например:

scala> var m = Map(1->2) m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> val n = m.get(100)// ну нет такого элемента n: Option[Int] = None

None примечателен тем, что:

  • это объект (т.е. синглтон)
  • это кейс-объект
  • наследуется от Option[Nothing]

В случае попытки получить значение (вызвав метод n.get()), мы получим исключение:java.util.NoSuchElementException.

Если у None вызывать метод isEmpty() – мы получим true.

Поскольку None – объект кейс-класса, то мы можем его "матчить" (сопоставлять по шаблону).

scala> n match { case Some(x) => println("x:" + x) case None => println("none") }

Если у None вызвать метод toList – мы получим пустой список (т.е. Nil).

scala> n.toList() == Nil res21: Boolean = true

Поскольку None объявлен как extends Option[Nothing], а Nothing – "самое нижнее ничто", то None может работать с любыми типами (как с ссылочными так и с примитивными).

Блог о программировании

Июнь 29, 2011

 

Main args, netbeans

Пара простых вещей (про Java/Scala + CLI и NetBeans)

Самый популярный и набивший оскомину пример HelloWorld встречается, наверное, уже во всех учебниках по программированию:

// Пример из туториала: http://download.oracle.com/javase/tutorial/getStarted/application/index.html class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); // Display the string. } }

Здесь String[] args — аргументы командной строки.
Например:
java HelloWorldApp 1 2 означает, что args будет равно {"1", "2"}.

Если передается всего один аргумент (например, "debug"), то все очень просто — можно подсмотреть пример из туториала: cmdLineArgs.

В случае, если аргументов много (как в гнусных линуксовых командах), то можно использовать какую-нибудь готовую библиотеку:

Для большинства задач их вполне достаточно. В том случае, если хочется большего разнообразия, то можно посмотреть здесь или в поисковиках.

В том случае, если аргументы не такие сложные и не слишком простые, а что-то среднее, то тянуть для этих целей дополнительную библиотеку нет никакого смысла. Например, если нужно передать что-то вроде: "-x -size 1024 -v". Обычно это бывает, когда требуется небольшая, почти "одноразовая" программа...

Многие настолько не любят писать разбор таких аргументов, что лепят все параметры в системные свойства (java ... -Dfoo="some string"), чтобы потом дергать их через System.getProperty().
Это конечно удобно, но не всегда нормально.

Проще написать разбор обычными стандартными средствами:

public class App {   public static void main(String[] args) { boolean v = false, x = false; int size = 0; for (int i=0;i<args.length;++i) { String arg = args[i]; if (arg.equals("-v")) { v = true; } else if (arg.equals("-size")) { size = Integer.parseInt(args[++i]);//да, здесь может быть ArrayIndexOutOfBoundsException } else if (arg.equals("-x")) { x = true; } } System.err.println("v = " + v); System.err.println("x = " + x); System.err.println("size = " + size); } }

В Scala все то же самое.
Тривиальный случай – делаем как в примере на официальном сайте: Snippet: Match Arguments.
Что-то очень сложное – подключаем сторонние библиотеки (ту же апачевскую или jopt), что и в Java случае.
В том случае, если что-то среднее, то можно написать на чистой Scala:

object App { def main(args:Array[String]) = { var v = false; var x = false; var size = 0 ("" +: args :+ "") reduceLeft ( (i, j) => { i match { case "-v" => v = true case "-size" => size = j.toInt case "-x" => x = true case _ => }; j }) println("v =" + v ) println("x = " + x) println("size = " + size) } }

Про другую известную многим фишку, о которой хотел рассказать — макросы в NetBeans-ах.
Точнее, про самый популярный макрос - debug-var. Вызывается по нажатию: Ctrl-J D.
Вообще макросы в нетбинсах есть уже много лет, по-крайне мере, когда я только начинал использовать нетбинс (3.* версии), они уже там были.
Например, для Scala можно сделать макрос, который будет вставлять в код: println("var=" + var)

Настроить можно здесь:
Tools -> Option -> Editor -> Macros

Про другие полезные макросы можно почитать здесь

Блог о программировании

Июнь 1, 2011

 

Немного карри

Использовать карринг в Scala одно удовольствие.
Само определение каррирования(или карринга, названо в честь Хаскелла Карри):

Для функции h типа h : (A × B) → C оператор каррирования Λ выполняет преобразование
Λ(h) : A → (B → C)

Отметим, что Λ - это оператор, то есть "функция над функциями".
Например берем функцию foo(x,y), каррируем и получаем moo(x)(y) - функцию от x которая возвращает функцию от y.

Таким образом мы можем сводим программу к вычислению функции от одного аргумента.

Чтобы выполнить карирование, можно вызвать Function.curried. Сейчас это уже устаревший метод, т.к. curried можно вызывать сразу у функции.

Небольшой пример (для наглядности в императивном стиле):

scala> val foo = (x:Int,y:Int) => x + y // функция от 2(ДВУХ) аргументов x и y. scala> foo(1,2) // просто сложили и получили три scala> val moo = foo.curried // получили функцию от 1(ОДНОГО) аргумента, которая возвращает scala> val zoo = moo(1) // функцию от 1(ОДНОГО) аргумента scala> zoo(2) // урраа! получили три scala> // можно каррировать и так: scala> def noo(x:Int, y:Int) = x * y scala> val a = noo _ // получили функцию от 2-х аргументов (подробнее см. partially applied function) scala> val b = a.curried scala> b(2) // = фунция 2 * аргумент scala> b(2)(3) // = 6

Метод curried можно найти в трейтах начиная от Function2 и заканчивая Function22.
Это значит, что вы можете использовать его для функций от 2 аргументов и до функций с 22-аргументами включительно.

Для функций без аргументов и с одним аргументом использовать бессмысленно.

Для функций с более чем 22-мя не поддерживается (таких трейтов вообще нет).
Например если Вы захотите сделать:
val foo = (x0:Int,x1:Int и т.д. до x22:Int) => 0
то получите ошибку компиляции:
"implementation restricts functions to 22 parameters".

Чтобы не возникало путаницы, поясню.

  • Во-первых:
    Это не значит, что вы не можете объявлять методы
    def foo(x0:Int,x1:Int и т.д. до x22:Int) = 0
    Это будет работать, но использовать в полную "силу" возможности Scala по работе с функциями уже не получится.
    Можно считать, что это "обычный" метод с 23 аргументами...
  • Во-вторых:
    Функции с varargs (переменным количество аргументов) работают нормально. Здесь никаких проблем с каррирование быть не должно.
  • В-третьих:
    Если у вас функции с более чем 22 аргументами это π#_!@#?!!!
    Думаете такого не бывает? Когда-то я работал в организации, в которой нужно было писать и разбираться со скриптами на лиспе (было и такое в моей жизни). Так вот, некоторые умельцы декларировали функции от 15-ти и более аргументов.
    Я в очередной раз взываю ко всем программистам с планеты Земля.
    Пожалуйста, постарайтесь так больше не делать. Уж очень неприятно работать с таким кодом.

Блог о программировании

Февраль 26, 2011

 

Scala. Pattern Matching


Продолжил работу по созданию учебных материалов по Scala.
Выкладываю черновую версию одной из глав.

Сопоставление по образцу (pattern matching). Начало.


В качестве вариантов перевода слова match с английского языка словарь Lingvo приводит следующие варианты:

match [mæʧ] 3) а) подбирать(под пару, под стать; по цвету, форме) to be well / ill matched — быть хорошо / плохо подобранным; хорошо / плохо сочетаться ... б) подходить, соответствовать (под пару; по цвету, форме) dress with a hat to match — платье с удачно подобранной шляпкой ...

В языке Scala ключевое слово match также используется для того, чтобы подбирать или находить соответствие:

e match { case p1 => e1 // ... case pn => en }

Где e, e1, en - некие выражения (expression) , а p1, pn - шаблоны (pattern) по которыми мы пытаемся найти соответствия.

Такая конструкция напоминает обычный switch / case из языков программирования Java или С/C++.

Сравним примеры:

Scala Java C
a match { case 0 => print("zero")   case 1 => print("one")   case _ => print("too much") }
switch (a) { case 0: System.out.print("zero"); break;   case 1: System.out.print("one"); break;   default: System.out.print("too much"); break; }
switch (a) { case 0: printf("zero"); break;   case 1: printf("zero"); break;   default: printf("too much"); break; }

Tips. В Scala можно указать сразу несколько условий в case

a match { case 1 | 2 | 3 => println("один, два, или три") }

Рассмотрим подробнее наш пример. В нем объект a "сравнивается" с разными шаблонами.
Для a равному 0, будет будет исполнен код print("zero").
Для а равному 1, будет выполнено print("one").
Для остальных случаев в Scala есть символ-джокер. Он обозначается символом подчёркивания _ . Таким образом case _ сработает в том случае, если другие шаблоны не подошли. Похожее поведение в Java реализуется с помощью слова default .

Tips. Символ-джокер, он же wild-card. По аналогии с карточными играми, например покером, в котором такая "дикая" карта (wild card) может стать другой картой по желанию игрока (например "пятым" тузом).
Простыми примерами таких символов может служить знак * в Unix/Windows скриптах или символ % в SQL-ном LIKE. В Scala wild-card "_" используется не только в case-ах, но и в других конструкциях.

Важной особенностью языка Scala заключается в том, что в отличие от switch/case С или Java, match умеет работать со строками. Более того match можно использовать для сопоставление объектов так называемых case классов, работу с которыми бы подробно рассмотрим в следующей главе.

Tips. Eсли мы попробуем например декомпилировать (javap -c ) указанный выше пример, мы обнаружим что Scala компилятор создаёт не плохой байт-код, аналогичный тому если бы мы писали на Java используя switch/case.

Итак, попробуем использовать полученные знания.
Представим, что у нас есть некоторый набор команд К. Например К = { F, +, - } :
F → пойти прямо
+ → повернуть направо
- → повернуть налево

Напишем программу, которая будет исполнять эти команды:

// полный текст программы будет приведён в конце главы cmd foreach (i => i match { case 'F' => { g.setColor(Color.red) val x2 = (x + length*cos(α)).toInt val y2 = (y + length*sin(α)).toInt g.drawLine(x, y, x2,y2) x = x2; y = y2; } case '+' => α += 0.5*Pi case '-' => α -= 0.5*Pi } )

Здесь cmd - обозначает строку с последовательностью различных команд. Например "F−F++F−F", будет означать - прямо, налево, прямо, направо, направо, прямо, налево, прямо.
Значение переменных x, y, α будут задавать текущие координаты и направление движения нашей системы.

Используем ещё раз силу match и применив какую-нибудь простую L-system-у, напишем программу которая будет рекурсивно создавать нам красивую последовательность команд.

Например, пусть будет следующее правило преобразований:
F → F+F-F-FF+F+F-F
+ → +
- → -

На языке Scala это можно записать следующим образом:

def next(x:String): String = { var result = new StringBuilder() x.foreach(p=> p match { case 'F' => result ++= "F+F-F-FF+F+F-F" case i => result +=i } ) result.toString }

Вызывая рекурсивно несколько раз данную функцию и направив полученную цепочку команд для отрисовки изображения, мы можем получить довольно занятные изображения.

Исходный код. В качестве эксперимента можно таким образом нарисовать салфетку серпинского или снежинку коха.

// Использование программного кода только в учебных целях. // Автор: Виталий Л. vit@programmisty.com import java.awt.Color import java.awt.image.BufferedImage import java.io.File import javax.imageio.ImageIO import scala.math._   object FractalLab {     def main(s:Array[String]) { // Пользуемся только стандартным JavaAPI. Никакие процессингы тут не нужны. Учимся все-таки... val w = 512; val h = w; // квадрат 512x512 val image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB) val g = image.getGraphics()   var α = 0.0; var x = 0; var y = h/2; // координаты. внимание, α - альфа. сохраняйте исходник в UTF-8.   def draw(cmd:String, length: Int) { // Используем match cmd foreach (i => i match { case 'F' => { g.setColor(Color.red) val x2 = (x + length*cos(α)).toInt val y2 = (y + length*sin(α)).toInt g.drawLine(x, y, x2,y2) x = x2; y = y2; } case '+' => α += 0.5*Pi case '-' => α -= 0.5*Pi } ) } // вспомогательная функция генератор цепочки команд def generate(s:String, level:Int, f:(String)=>String ):String = { if (level > 0) generate(f(s), level-1, f) else s }   // функция создающая новые команды, на базе старых def next(x:String): String = { var result = new StringBuilder() // используем match x.foreach(p=> p match { case 'F' => result ++= "F+F-F-FF+F+F-F" case i => result +=i } ) result.toString } // рисуем с шагов 2 пикселя цепочку команда 4 поколения. draw(generate("F", 4, next), 2) // сохраняем в файл ImageIO.write(image, "png", new File("koch.png")) } }

Продолжение следует...

Блог о программировании

Февраль 14, 2011

 

Netbeans Scala Maven

Если вам приходилось работать в связке Netbeans 6.9.1 + Scala + Maven, то вы могли заметить, что компиляция происходит сильно медленнее, чем если бы вы НЕ использовали maven-scala-plugin.
Дело в том, что по умолчанию компиляция запускается в режиме "компилировать все классы". Такое поведение можно изменить, указав в настройках для recompileMode значение modified-only (компилировать только измененные). По-умолчанию оно all.
В некоторых случаях перевод в режим modified-only удобен, например если ваша задача не выпуск финальной версии продукта, а работа над определенным куском кода в режиме "написал, нажал Shift-F6, посмотрел что получилось...".
Внимание! Перевод recompileMode в режим modified-only может привести к нежелательным последствиям и побочным эффектам. Как говорится, не уверен - не обгоняй (а уверен - обгоняй).

Пример возможной (но далеко не оптимальной) модификации pom.xml.

<plugin> <groupId>org.scala-tools</groupId> <artifactId>maven-scala-plugin</artifactId> <configuration> <recompileMode>modified-only</recompileMode> </configuration> </plugin>

 
<< < 1 из 2 > >>