Здравствуйте, Alex EXO, Вы писали:
E>>После двух release candidate вышел финальный релиз Scala 2.4.0.
AE>Сам пробовал? Как он тебе?
Язык Scala или релиз 2.4.0?
С языком ситуация такая:
* после прочтения ScalaByExample, или ScalaTutorial, или ScalaOverview -- язык очень нравится. Лаконичный, чем-то сильно напоминает Ruby;
* после начала чтения ScalaReference (а другого источника, настолько же полно знакомящего читателя с тонкостями языка, пока нет) -- язык нравиться перестает. Слишком сложные определения даются для некоторых вещей (например, правила видимости и перекрытия имен, ко/контра-вариантности, линеаризация классов при наследовании и пр.). Плюс к этому сама ScalaReference написана сухим формальным языком. Может быть это и полезно для спецификации языка или разработки компилятора, но научиться с его помощью программировать на Scala вряд ли возможно. Я так до конца ScalaReference и не прочел.
Использую Scala для маленьких тестовых программок, не более 100 строк. На таких объемах впечатление нормальное, однако заметно, что его делали специалисты в области языков программирования (со своими, слегка оторванными от рельностей, взглядами). Но времени заниматься Scala более плотно сейчас нет.
Пока впечатление у меня такое -- из новых статически типизированных языков со сборкой мусора для меня самыми привлекательными являются Scala и D. Как язык мне более симпатичен D, но по ряду других факторов Scala гораздо предпочтительнее. К счастью, прямо сейчас у меня нет необходимости делать выбор между ними, поэтому я пока занимаю выжидательную позицию -- либо в каком-то из них возникнет какая-нибудь killer feature, либо появиться что-нибудь еще более привлекательное, что затмит как Scala, так и D.
Извини, если не смог помочь.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>однако заметно, что его делали специалисты в области языков программирования (со своими, слегка оторванными от рельностей, взглядами).
И в чем это выражается?
E>Как язык мне более симпатичен D,
Страшно подумать как и для чего ты исползуешь Скалу .
E>но по ряду других факторов Scala гораздо предпочтительнее.
Можно более подробно и менее туманно об этом?
E> К счастью, прямо сейчас у меня нет необходимости делать выбор между ними, поэтому я пока занимаю выжидательную позицию -- либо в каком-то из них возникнет какая-нибудь killer feature, либо появиться что-нибудь еще более привлекательное, что затмит как Scala, так и D.
А паттерн-матчингом ты пользовался? Если, да, то что с его помощью ты делал?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
E>>однако заметно, что его делали специалисты в области языков программирования (со своими, слегка оторванными от рельностей, взглядами).
VD>И в чем это выражается?
Да в той же самой линеаризации хотя бы.
Или в добавленных в последних версиях extractor-ах.
E>>но по ряду других факторов Scala гораздо предпочтительнее.
VD>Можно более подробно и менее туманно об этом?
У Scala огромное количество библиотек, унаследованных из Java.
У Scala феноменальная переносимость по сравнению с нынешним D (в вариантах dmd и даже gdc).
У Scala гораздо более качественный GC, унаследованный из Java (по сравнению с нынешним D).
Scala работает в полностью управляемой среде, поэтому любой выход за пределы массива приводит к выдаче подробного stack trace. В отличии от D, где в Release вообще проверки отключаются, а когда они есть, то нет никакого stack trace.
D меняется гораздо интенсивнее и все вкусности, которые сейчас стали обсуждаться news-группах (такие как расширенная поддержка const/final/invariant) появятся только в новой версии языка (под условным названием D 2.0), а когда это будет -- хз. Scala в этом смысле гораздо стабильнее, а значит -- предпочтительнее.
E>> К счастью, прямо сейчас у меня нет необходимости делать выбор между ними, поэтому я пока занимаю выжидательную позицию -- либо в каком-то из них возникнет какая-нибудь killer feature, либо появиться что-нибудь еще более привлекательное, что затмит как Scala, так и D.
VD>А паттерн-матчингом ты пользовался? Если, да, то что с его помощью ты делал?
Как альтернативой C-шному switch, почти как Ruby-новым case. Поскольку я парсингом граматик или преобразованием древовидных структур данных на Scala не занимался, то особой выгоды в паттерн-матчинге не заметил. Вот аргументы by name и тип unit -- это да, классная штука. Туда бы еще обобщенное программирование как в D, вообще был бы шедевр.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Да в той же самой линеаризации хотя бы. E>Или в добавленных в последних версиях extractor-ах.
Хм. С обоими понятиями не знаком. Что это такое?
E>У Scala феноменальная переносимость по сравнению с нынешним D (в вариантах dmd и даже gdc).
Ди вроде бы может жить на GCC-шном бэкэнде. А он переносим не хило. Правда с перекомпиляцией.
E>У Scala гораздо более качественный GC, унаследованный из Java (по сравнению с нынешним D).
Гы. Он не унаследован, а самый что ни на есть GC Java-ы. Он же на ее VM живет.
E>Scala работает в полностью управляемой среде, поэтому любой выход за пределы массива приводит к выдаче подробного stack trace.
Вот видишь, а сосем недавно ты от этого плевался.
E> В отличии от D, где в Release вообще проверки отключаются, а когда они есть, то нет никакого stack trace.
Согласен, то тоже проявление безопасности рантайма.
Но ведь это все приемущества VM Java.
E>Как альтернативой C-шному switch, почти как Ruby-новым case.
Это считай, что ты его не исползовал вовсе.
E> Поскольку я парсингом граматик или преобразованием древовидных структур данных на Scala не занимался, то особой выгоды в паттерн-матчинге не заметил.
Не скажи. Очень многое можно предствить case-классами (алгеброическими типами данных), и обрабатывать ПМ-ом. Просто ты еще не проникся. Уверяю тебя, что когда проникнешся, то в Ди и Руби у тебя начнется ломка. Проверно на себе.
E> Вот аргументы by name и тип unit -- это да, классная штука. Туда бы еще обобщенное программирование как в D, вообще был бы шедевр.
Обобщенное программирование там есть, првда оно как и в Яве полноценно пашет только для ссылочных типов (в общем кастрировано). Но все же.
А что значит "by name"?
И чем по твоему unit отличается от void? Что то я не пойму.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
E>>Да в той же самой линеаризации хотя бы. E>>Или в добавленных в последних версиях extractor-ах.
VD>Хм. С обоими понятиями не знаком. Что это такое?
Линеаризация -- это алгоритм упорядочения всех наследований и примесей для Scala-вского класса/объекта/trait-а. По результатам линеаризации определяется какой именно из унаследованных методов будет доступен для вызова.
я давал ссылку на работу, где авторы Scala проводят сравнения разных подходов и описывают свою идею Extractor-ов.
VD>Но ведь это все приемущества VM Java.
Для меня нет отдельных качеств Scala, которые бы я рассматривал без самого важного фактора -- Scala генерирует байт-код JVM.
E>> Вот аргументы by name и тип unit -- это да, классная штука. Туда бы еще обобщенное программирование как в D, вообще был бы шедевр.
VD>Обобщенное программирование там есть, првда оно как и в Яве полноценно пашет только для ссылочных типов (в общем кастрировано). Но все же.
Не понял о чем ты, в Scala, в отличии от Java, даже int является объектом и может использоваться как параметр для обобщенного программирования.
VD>А что значит "by name"?
Аргумент, чье значение вычисляется только при обращении к нему. Что-то а-ля ленивости, очень похоже на D-шные lazy аргументы. Подробнее различия типов аргументов обсуждалось здесь: http://www.rsdn.ru/Forum/Message.aspx?mid=2351871&only=1
я давал ссылку на работу, где авторы Scala проводят сравнения разных подходов и описывают свою идею Extractor-ов.
А зачем еще одна?
Можно пример использования этой фичи?
E>Не понял о чем ты, в Scala, в отличии от Java, даже int является объектом и может использоваться как параметр для обобщенного программирования.
В Яве тоже. Но какова цена? Они же их в обертки запихиваеют (автобоксинг).
VD>>А что значит "by name"?
E>Аргумент, чье значение вычисляется только при обращении к нему. Что-то а-ля ленивости, очень похоже на D-шные lazy аргументы. Подробнее различия типов аргументов обсуждалось здесь: http://www.rsdn.ru/Forum/Message.aspx?mid=2351871&only=1
Т.е. передают скрытую лямбду?
VD>>И чем по твоему unit отличается от void? Что то я не пойму.
E>unit -- это практически полный аналог Ruby-нового объекта Proc, т.е. завернутого в объект блока кода.
Ты ничего не путашь? unit вроде бы был полным аналогом void.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А зачем еще одна? VD>Можно пример использования этой фичи?
Это вопросы не ко мне, а к разработчикам Scala.
VD>>>А что значит "by name"?
E>>Аргумент, чье значение вычисляется только при обращении к нему. Что-то а-ля ленивости, очень похоже на D-шные lazy аргументы. Подробнее различия типов аргументов обсуждалось здесь: http://www.rsdn.ru/Forum/Message.aspx?mid=2351871&only=1
Типа того.
VD>>>И чем по твоему unit отличается от void? Что то я не пойму.
E>>unit -- это практически полный аналог Ruby-нового объекта Proc, т.е. завернутого в объект блока кода.
VD>Ты ничего не путашь? unit вроде бы был полным аналогом void.
Нет, не путаю. Вот пример кода, который использует и by-name и unit-ы (такой тривиальный шустрик, использование java.util.Calendar можно заменить на какой-то Scala-вский класс, давно дело было):
object LoopSpeed2 extends Application {
def meter( name: String, action: => unit ) {
val start = java.util.Calendar.getInstance.getTimeInMillis
action
val finish = java.util.Calendar.getInstance.getTimeInMillis
Console.println( name + ": " + (finish - start) )
}
class Repeater( command: => unit ) {
def until( condition: => boolean ): unit = {
do command while( !condition )
}
}
def repeatLoop( action: => unit ) = new Repeater( action )
val LIMIT = 100000000
meter( "Simple do-while",
{ var i = 0; do { i = i + 1 } while( i < LIMIT ); } )
meter( "Repeat until",
{ var i = 0; repeatLoop { i = i + 1 } until( i >= LIMIT ); } )
}
// vim:ts=2:sts=2:sw=2:expandtab
Здесь параметры action и command в методах meter/Repeater.until/repeatLoop как раз by name, да еще и имеют тип unit.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
E>Здесь параметры action и command в методах meter/Repeater.until/repeatLoop как раз by name, да еще и имеют тип unit.
Все же путаешь похоже. unit — это просто такое каукообразное название для void-а. Им обозначаются возвращаемые значения функций которые ничего не возращают. Чтобы описать блок кода как раз нужно описать функцию из чего-то в unit: ххх => unit
В дамнном случая, я так понимаю, из это такой своеобразный синтаксис передачи блока кода. У них еще есть вариация со вторым списком параметров (не явным) который позволяет записывать код так:
using (выражение)
{
другие выражения
}
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
E>>Здесь параметры action и command в методах meter/Repeater.until/repeatLoop как раз by name, да еще и имеют тип unit.
VD>Все же путаешь похоже. unit — это просто такое каукообразное название для void-а. Им обозначаются возвращаемые значения функций которые ничего не возращают. Чтобы описать блок кода как раз нужно описать функцию из чего-то в unit: ххх => unit
Да, конечно, тебе лучше знать. И самое замечательное в наукобразном названии для void, что обращение к void приводит к вызову обернутого в него кода:
object UnitDemo1 extends Application
{
val codeBlock: unit = { Console.println( "Hello from CodeBlock!" ) }
codeBlock
}
// vim:ts=2:sts=2:sw=2:expandtab
VD>В дамнном случая, я так понимаю, из это такой своеобразный синтаксис передачи блока кода. У них еще есть вариация со вторым списком параметров (не явным) который позволяет записывать код так: VD>
VD>using (выражение)
VD>{
VD> другие выражения
VD>}
VD>
У них это не вариация, а возможность задавать функции не один список параметров, а несколько. Причем, за счет свободного синтаксиса, если список параметров содержит один аргумент типа unit или что-нибудь, приводящееся к функтору, то выражение (т.е. блок кода) автоматически заворачивается в соответствующий объект и передается аргументом в функцию. Откуда может быть вызван:
object MutliArgs1 extends Application
{
def demo(x: int)( block: => unit) : unit = {
for( val i <- Iterator.range( 0, x ) )
block
}
demo( 3 ) { Console.println( "Hello, world!" ) }
}
// vim:ts=2:sts=2:sw=2:expandtab
Причем, функция может получать сразу несколько блоков кода, если ей это необходимо.
object MutliArgs2 extends Application
{
def repeatLoop( action: => unit )( condition: => boolean ): unit = {
action
if( condition ) repeatLoop( action )( condition )
}
var i = 0;
repeatLoop {
Console.println( "i=" + i )
i = i + 1
}( i < 4 )
}
// vim:ts=2:sts=2:sw=2:expandtab
Или, в более традиционном синтаксисе с фигурными скобками:
object MutliArgs3 extends Application
{
def repeatLoop( action: => unit )( condition: => boolean ): unit = {
action
if( condition ) repeatLoop( action )( condition )
}
var i = 0;
repeatLoop {
Console.println( "i=" + i )
i = i + 1
} { i < 4 }
}
// vim:ts=2:sts=2:sw=2:expandtab
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Линеаризация -- это алгоритм упорядочения всех наследований и примесей для Scala-вского класса/объекта/trait-а. По результатам линеаризации определяется какой именно из унаследованных методов будет доступен для вызова.
Это жестяк из CLOS. Я так понимаю, что основная проблема с ним, то что программер фиг поймёт какой метод реально будет вызван.
я давал ссылку на работу, где авторы Scala проводят сравнения разных подходов и описывают свою идею Extractor-ов.
VD>А зачем еще одна? VD>Можно пример использования этой фичи?
Ну вот есть у тебя объект (который отвечает на сообщения и о внутренностях которого ничего не известно), патерн матчинг по нему сделать нельзя, а экстрактор выдаёт на основании состояния объекта конструкцию по которой можно сделать сопоставление с образцом. Ну и обратная операция. Типа сериализации-десереализации объекта в алгебраический тип.
ЗЫ. Влад ты ж на пост Евгения о статье поставил "1". Или руки не дошли на почитать. А вдруг там описывался убийца N на Java?
E>>>Здесь параметры action и command в методах meter/Repeater.until/repeatLoop как раз by name, да еще и имеют тип unit.
VD>>Все же путаешь похоже. unit — это просто такое каукообразное название для void-а. Им обозначаются возвращаемые значения функций которые ничего не возращают. Чтобы описать блок кода как раз нужно описать функцию из чего-то в unit: ххх => unit
E>Да, конечно, тебе лучше знать. И самое замечательное в наукобразном названии для void, что обращение к void приводит к вызову обернутого в него кода: E>
E>object UnitDemo1 extends Application
E>{
E> val codeBlock: unit = { Console.println( "Hello from CodeBlock!" ) }
E> codeBlock
E>}
E>
Влад прав, unit — это действительно аналог void. Из Scala by example:
Executing a definition such as def x = e will not evaluate the expression e. Instead
e is evaluated whenever x is used. Alternatively, Scala offers a value definition
val x = e, which does evaluate the right-hand-side e as part of the evaluation
of the definition. If x is then used subsequently, it is immediately replaced by the
pre-computed value of e, so that the expression need not be evaluated again.
В типе unit ничего особенного нет, "завернуть блок кода" можно точно так же в значение любого типа:
scala> val bar = { Console.println("once"); 3.14 }
once
bar: scala.Double = 3.14
scala> bar
line8: scala.Double = 3.14
scala> bar
line9: scala.Double = 3.14
scala> def foo = { Console.println("every time"); 13 }
foo: => scala.Int
scala> foo
every time
line11: scala.Int = 13
scala> foo
every time
line12: scala.Int = 13
Здравствуйте, eao197, Вы писали:
E> Туда бы еще обобщенное программирование как в D, вообще был бы шедевр.
Хмм.. Ты имеешь в виду генерики (generics)? Так в скале они тоже очень неплохи, во всяком случае поудобней чем в жабе, а система вывода типов делает их использование ещё удобней.. Можно пример кода на Д? Спасибо..
Вот макросы бы туда, как у Н, тады да...
Здравствуйте, palm mute, Вы писали:
PM>Влад прав, unit — это действительно аналог void. Из Scala by example: PM>
PM>Executing a definition such as def x = e will not evaluate the expression e. Instead
PM>e is evaluated whenever x is used. Alternatively, Scala offers a value definition
PM>val x = e, which does evaluate the right-hand-side e as part of the evaluation
PM>of the definition. If x is then used subsequently, it is immediately replaced by the
PM>pre-computed value of e, so that the expression need not be evaluated again.
Может быть я и не прав.
Во всяком случае мой пример с codeBlock оказался некорректным -- печать осуществлялась не во время обращения к codeBlock, а во время инициализации codeBlock.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Может быть я и не прав. E>Во всяком случае мой пример с codeBlock оказался некорректным -- печать осуществлялась не во время обращения к codeBlock, а во время инициализации codeBlock.
Потому что ты использовал val, с def пример бы работал.
Здравствуйте, Gajdalager, Вы писали:
E>> Туда бы еще обобщенное программирование как в D, вообще был бы шедевр. G>Хмм.. Ты имеешь в виду генерики (generics)? Так в скале они тоже очень неплохи, во всяком случае поудобней чем в жабе, а система вывода типов делает их использование ещё удобней.. Можно пример кода на Д? Спасибо..
Да, речь о генериках. Охотно верю тому, что в Scala генерики удобнее, чем в Java. Так же я не сомневаюсь, что все заморочки с декларацией поддерживаемых параметром шаблона интерфейсов -- следствие компонентно-ориентированного подхода, где реальное связывание кода может происходить в run-time.
Однако, если переход на Scala выполняется, как в моем случае, с C++, где обобщенное программирование совсем другое, то генерики не выглядят удобными.
Вот пример кода на Scala:
object Demo1 extends Application
{
class ValueHolder
{
def value = { 0 }
}
def doSomething[ B <: ValueHolder ]( holder: B ) {
holder.value
}
doSomething( new ValueHolder )
}
// vim:ts=2:sts=2:sw=2:expandtab
В методе Demo1.doSomething указывается, что параметром может быть либо сам ValueHolder, либо его наследник. Т.е. невозможно использовать doSomething для какого-либо другого типа, не связанного с ValueHolder отношениями наследования.
А вот аналогичный пример на D:
class ValueHolder
{
int value() { return 0; }
}
class AnotherValueHolder
{
float value() { return 0.0; }
}
voiddoSomething(T)( T holder )
{
holder.value;
}
void
main()
{
doSomething( new ValueHolder );
doSomething( new AnotherValueHolder );
}
Функция doSomething может применяться к любому типу. Более того, методы ValueHolder.value и AnotherValueHolder.value не совпадают по типу возвращаемого значения.
Именно такая свобода в повторном использовании обобщенных функций в D (как и в C++) нравится мне больше, чем подход с генериками в языках Scala/Java/C#.
При этом можно заметить, насколько больше в D "синтаксического оверхеда" по сравнению с Scala (необходимость писать return, постоянные точки с запятыми) -- программы на Scala синтаксически выглядят привлекательнее
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, VladD2, Вы писали:
VD>Все же путаешь похоже. unit — это просто такое каукообразное название для void-а. Им обозначаются возвращаемые значения функций которые ничего не возращают. Чтобы описать блок кода как раз нужно описать функцию из чего-то в unit: ххх => unit
Возможно. Очень похоже, что я ошибся.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, palm mute, Вы писали:
E>>Может быть я и не прав. E>>Во всяком случае мой пример с codeBlock оказался некорректным -- печать осуществлялась не во время обращения к codeBlock, а во время инициализации codeBlock.
PM>Потому что ты использовал val, с def пример бы работал.
Суть примера как раз и была в использовании val. Поскольку с def начинается определение функции (согласно ScalaReference):
Просто Expr не обязательно заключать в фигурные скобки. Поэтому определением функции является даже такое:
scala> val x = 1
x: scala.Int = 1
scala> def f = x
f: => scala.Int
Если описание типа возвращаемого значения опущено, то Scala пытается вывести его самостоятельно исходя из типа выражения. Если при определении функции опущено '=' перед выражением (а само выражение взято в фигурные скобки):
scala> def g { x }
g: => scala.Unit
то это считается частным случаем записи:
scala> def g2: unit = x
g2: => scala.Unit
SObjectizer: <микро>Агентно-ориентированное программирование на C++.