LINUX.ORG.RU

Группа разработчиков Scala получила грант Евросоюза

 , , ,


1

4

Группа разработчиков языка Scala получила грант Евросоюза, выиграв конкурс языков для параллельного программирования. Разработчики получат в течение следующих 5 лет на развитие своего детища 2,3млн €.

Scala — язык программирования для платформы JVM, сочетающий возможности объектно-ориентированного и функционального программирования. Scala был разработан в лаборатории швейцарского ВУЗ’а EFPL.

>>> Подробности

★★★★★

Проверено: maxcom ()
Последнее исправление: Zhbert (всего исправлений: 3)
Ответ на: комментарий от eao197

> Интересно, вот этот код из официальной документации по Java, вы точно также раскритикуете:

Здесь одна строка кода - остальное обявления интерфейсов - что там критиковать?

возможно MyAdapter должен быть static
возможно можно было сделать MyClass implements MouseListener
вломожно ....

Но самое важное здесь стоит обратить внимание на то что MyAdapter _extends MouseAdapter_ и так сделано потому что в жабе отсутствует множественное наследование, а класс MyClass уже extends Applet.

Как я уже говорил _иногда_ можно делать что угодно, если это иногда _обосновано_.

Например возвращаясь к твоему коду вызов типа new X().m() допустим если X чужой класс - и тут ничего поделать нельзя, и то лучше запихнуть его в статический хелперкласс к этой чужой библиотеке, чтобы не страдать так везде.

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>какого хрена в user.authScheme может оказаться неизвестная конфигу схема?

Все что там может оказаться и все что лежит в схемах - указывается в конфигах (text/json). Очепятки админа никто не отменял.

тогда ее тоже надо верифицировать тогда, когда мы ее берем из базы и запихиваем в user.authScheme


authScheme это строка с символическим именем конфига автентикации пользователя. Там пустого быть не может - вообще нет такой логики когда там может быть неопределенность. Там либо PETRIVKA по дефайлту либо что-то другое из дропдавна. Единственное что такого конфига может не быть еще или уже или очепятка - и потому там проверяется что схема автентикации которая указана юзеру - существует.

r ★★★★★
()
Ответ на: комментарий от AlexRK

А ведь есть языки вообще без статических членов...

Есть языки без модификаторов видимости. ТАм что - принципиально другой дизайн?

Боюсь посеять в вас разочарование в людях, но среднестатистический программист сильно далек от вашего идеала. :)

Очень жаль. Надеюсь после этого очередного треда хоть несколько программистов не захотят быть теми среднестатистическими которые далеки:)

А то вон у вас там уже сейчас жирный свитч стоит

4 варианта в свиче - это жирный?

а если число вариантов еще увеличится на парочку?

То их будет 6ть. Его для того и придумали.

У меня есть вот такой свитч (к стати пример говнокода который такой ради скорости).

               for ( c <- json ) ( c: @switch ) match {
                        case '"' if !escape => b.append( "\"" ); string = !string; escape = false
                        case x@( '{' | '[' ) if !string => tabs += '\t'; b.append( x ).append( "\n" ).append( tabs ); escape = false
                        case x@( '}' | ']' ) if !string => tabs.deleteCharAt( tabs.length - 1 ); b.append( "\n" ).append( tabs ).append( x ); escape = false
                        case x@',' if !string => b.append( x ).append( "\n" ).append( tabs ); escape = false
                        case x@'\\' if string => b.append( x ); escape = !escape
                        case x@':' if !string => b.append( x ).append( " " ); escape = false
                        case '\n' | '\r' | '\t' | ' ' if !string =>
                        case x => b.append( x ); escape = false
                }

Кстати, а что в школе сейчас из Аристотеля-то дают? :)

Угу. В высшей. На куче курсов.

r ★★★★★
()
Ответ на: комментарий от r

> вызов типа new X().m()

Такая конструкция, вообще, бред с точки зрения ФП. И всякие примеры типа DevExpress тут ничего не доказывают. Выше я уже писал, что это равносильно созданию замыкания (функции) с последующим ее вызовом. Совершенно непонятно, зачем это делать в функциональном языке.

Только стоит отметить, что в таком классе X можно определить свои методы. Так это в ФП заменяется определением локальных функций. Методы внутреннего промежуточного класса X станут просто локальными функциями.

В общем, у меня такое ощущение, что прожженные ООП-шники пытаются спорить о том, как нужно правильно писать код на Scala :)

dave ★★★★★
()
Ответ на: комментарий от r

Здесь одна строка кода - остальное обявления интерфейсов - что там критиковать?

Объясняю, как обычно, на пальцах. Подобные адаптеры, являясь inner class-ами, обращаются к состоянию outer class-ов или же дергают методы outer class-а для делегирования операции outer class-у.

По вашей классификации выходит, что в таком случае создается циклическая зависимость между inner и outer классами (ведь удали любой из них и ничего не сможет работать). А это ну очень плохо и это страшный косяк в дизайне.

Поэтому жду от вас последовательности в отстаивании своей точки зрения и объявления о том, что при работе со SWing-ом используется плохой дизайн в виде циклической зависимости между inner и outer классами. Он ведь там не иногда, он там постоянно применяется.

eao197 ★★★★★
()
Ответ на: комментарий от dave

как нужно правильно писать код на Scala

Ну так ведь ни вы, ни r этого продемострировать не можете. Приходится доходить своим умом.

eao197 ★★★★★
()
Ответ на: комментарий от dave

Такая конструкция, вообще, бред с точки зрения ФП.

Обосновать сможете? Что именно в ФП противоречит использованию таких конструкций?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Здравый смысл будет обоснованием. Я уже писал, что это пустая конструкция. Лишние действия из ничего. Но для явы она имеет смысл, поскольку там нет функций. Там нет аналога вложенному def. Грубо говоря, выше был продемонстрирован «явизм».

def process(username: String, password: String) {

  def f() { ... здесь видны username и password ... }
  def g() { ... здесь видны username и password ... }

  g()
}
dave ★★★★★
()
Ответ на: комментарий от dave

Здравый смысл будет обоснованием.

Здравый смысл к делу не подошьешь. Вы сделали серьезное заявление. Чем-то кроме вашего здравого смысла его можно обосновать?

Вложенные функции в приведенном вами примере не являются прерогативой ФП. Такой же вариант можно было бы написать и в D, и (если не ошибаюсь) в древнем Паскеле с Модулой и Оберонами.

И я еще раз приведу довод против локальных функций — если вам потребуется покрыть их Unit-тестами, то вам нужно будет как-то вытягивать их наружу из process и привязывать к username и password. К чему вы тогда придете?

Так что еще раз: чему в ФП противоречит конструкция X().m()?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Причем здесь юнит-тесты?! А для ответа на остальные вопросы я уже дал достаточно информации. Не будем ходить по кругу.

dave ★★★★★
()
Ответ на: комментарий от r

4 варианта в свиче - это жирный?

У паттерн-матчинга перед if/switch есть два очевидных преимущества:

1. Упрощение разбора сложных структур данных, вроде чего-то такого:

data match {
  case [X, Y, Z, _] => ...
  case [X, [a, b, _, c], D] => ...
  ...
}

2. Контроль со стороны компилятора за полнотой покрытия. Например, если было:

case class User ...
case class NormalUser extends User
case class BlockedUser extends User
и матч был записан как:
user match {
  case NormalUser => ...
}
то программиста заставят добавить в match обработку других вариантов. Если же со временем список вариантов для User будет расширен:
case class SuspiciousUser extends User
case class VIPUser extends User
то компилятор опять же заставит модифицировать все match-и, в которых новые варианты еще не были предусмотрены.

Использовались ли какие-то из этих преимуществ в вашем случае с Option ? Нет.Если же посмотреть на логические условия, которые задействованы в match-е с Option , то они будут выглядеть как:(!X) || (X && A) || (X && B) || XСоответственно, возникает вопрос: а почему предикат X (т.е. Some(user)) проверяется четыре раза, а не один.Т.е. преимуществ паттерн-матчинга не использовалось, логические условия вышли сложнее, чем могли бы быть. Ну и нафига там был паттерн-матчинг?

eao197 ★★★★★
()
Ответ на: комментарий от dave

Причем здесь юнит-тесты?!

У локальных функций есть свойство локальности и компактности, но их невозможно покрыть отдельными unit-тестами.

У вспомогательного класса обратная ситуация — нет локальности и компактности, но можно написать отдельные unit-тесты.

Следовательно, чаша весов может склониться либо в ту, либо в иную сторону, в зависимости от внешних факторов.

А для ответа на остальные вопросы я уже дал достаточно информации. Не будем ходить по кругу.

Не было. Либо дайте ссылку на ваше обоснование того, что «Такая конструкция, вообще, бред с точки зрения ФП.» За свои слова принято отвечать.

eao197 ★★★★★
()
Ответ на: комментарий от yaws

http://fprog.ru/2010/issue6/practice-fp-6-print.pdf, «Интервью с Джо Армстронгом»

Армстронг, правда, так же грамотно опустил scala actors


--------
— Есть ли у каких-нибудь из современных молодых языков существенные шансы догнать или
даже перегнать Erlang в его нише?
Джо: Возможно, Scala, но Scala и Erlang создавались для разных задач, так что в Scala будут труд-
ности со многим, в чем хорош Erlang. Поведение сборщика мусора Erlang и его взаимодействие с
динамической подменой кода невозможно реализовать поверх JVM, так как её семантика карди-
нально отличается от семантики Erlang VM.
-----

это называется грамотно опустил?

Yilativs ★★★★
()
Ответ на: комментарий от Yilativs

>>http://fprog.ru/2010/issue6/practice-fp-6-print.pdf, «Интервью с Джо Армстронгом»

Армстронг, правда, так же грамотно опустил scala actors


это называется грамотно опустил?

Ты сможешь грамотно опустить Джо? Ну валяй :)

------------
— Многие современные языки (например, Scala и F#) обзаводятся библиотеками для эмуляции
многозадачности в стиле Erlang.
---
(Мне надо будет объяснять, какие именно библиотеки имелись в виду?)
---
Есть ли у них шансы стать столь же мощными инструментами
распределенного программирования лишь за счет использования основных идей, или все-таки
для этого необходима и среда выполнения, сравнимая по мощности с Erlang?
Джо: Эти библиотеки реализуют лишь малую часть многозадачности в стиле Erlang. Они реализу-
ют самые простые части, и опускают сложные (и полезные), например, динамическую замену кода
и особую семантику распространения ошибок.
------------

Ну и сам должен же с грустью понимать - раз, при наличии разномастных JRuby, Jython etc etc, до сих пор нет реализации erlang на базе JVM, этот фактик говорит о многом. (В т.ч. и об ценности различных $lang.Actors)

PS erjang как пример (erlang for jvm) можешь не приводить: «Примерно 3/4 из .beam-файлов в стандартной поставке Erlang/OTP успешно конвертируются в .class-файлы. Это конечно не означает, что все из них транслируется корректно, время покажет.» (с)

yaws
()
Ответ на: комментарий от yaws

на всякий случай - ключевая фраза:«в стиле Erlang».

PS Просто чтобы предупредить разные там «похожий синтаксис», «похожее поведение» «Армстронг - йху» и т.п.

PPS. Лично же мое мнение - дергать Scala.Actors для меня через port нерационально.

yaws
()
Ответ на: комментарий от r

У меня есть вот такой свитч (к стати пример говнокода который такой ради скорости).

Послушайте, это же просто ад какой-то.

А что вы скажете, например, на такой вариант на C#:

private string GetTabs()
{
    return '\n' + (new String('\t', indent));
}

......................................

foreach (var x in json)
{
    if (!isString)
    {
        var buffer = x.ToString();

        switch (x)
        {
            case '"':
                isString = true;
                break;
            
            case '{':
            case '[':
                indent++;
                buffer = buffer + GetTabs();
                break;

            case '}':
            case ']':
                indent--;
                buffer = GetTabs() + buffer;
                break;

            case ',':
                buffer = buffer + GetTabs();
                break;

            case ':':
                buffer = buffer + " ";
                break;

            case '\n':
            case '\r':
            case '\t':
            case ' ':
                buffer = String.Empty;
                break;
        }
        
        if (buffer.Length > 0)
            b.Append(buffer);
    }
    else
    {
        if ((x == '"') && (!isEscape))
            isString = false;
    
        isEscape = (x == '\\') ? (!isEscape) : false;

        b.Append(x);
    }
}

Ошибки могут быть, я это в блокноте написал. :)

AlexRK
()
Ответ на: комментарий от eao197

Интересно, вот этот код из официальной документации по Java, вы точно также раскритикуете:

//An example of using an inner class.
public class MyClass extends Applet {
    ...
   someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
       ...//Event listener implementation goes here...
        }
    }
}

Костыль, заменяющий отсутствие функций высшего порядка и замыканий. Хороший пример того как Java обфускирует абстракции и вносит тонны бойлерплейта.

pitekantrop ★★★
()
Ответ на: комментарий от pitekantrop

Хороший пример того как Java обфускирует абстракции и вносит тонны бойлерплейта.

Если вы не заметили, речь шла о создании циклических зависимостей, которые суть плохо.

Замыкания, если на то пошло, так же создают циклические зависимости :)

eao197 ★★★★★
()
Ответ на: комментарий от eao197

>По вашей классификации выходит, что в таком случае создается циклическая зависимость между inner и outer классами

Создается.

А это ну очень плохо и это страшный косяк в дизайне.


Там есть четкая причина почему так делается - обоснованная - отсутствие множественного наследования.

Поэтому жду от вас последовательности в отстаивании своей точки зрения и объявления о том


Моя точка зрения последовательно она состоит в «обоснование, обоснование и еще раз обоснование».

А не хаотичный поток сознания выраженный в коде.

r ★★★★★
()
Ответ на: комментарий от eao197

>(!X) || (X && A) || (X && B) || X

Соответственно, возникает вопрос: а почему предикат X (т.е. Some(user)) проверяется четыре раза, а не один.


Почему предикат X в вышеотквоченном выражении проверяется 4 раза а не один?

Т.е. преимуществ паттерн-матчинга не использовалось,


То есть ты наехал на само существование гвардов - пот твоему мнению они не нужны, и делают матч непонятным и ты его хочешь заменить на понятный тебе if. ЧИТД.



r ★★★★★
()
Ответ на: комментарий от AlexRK

>А что вы скажете, например, на такой вариант на C#:

Скажу что оно делает совсем не то что мой код:) Не мелкие ошибки - а вообще не будет работать. Эта стейтмашина совсем не такая простая как кажется.

Опять замены непривычных гвардов на привычные ifы?

К стати опять пример таки - вызовы каких-то неопределенных gettabs и тд.

Там что не ясно было написано - что этот код перфоманс критикал? Этот код здоровенные jsonы форматирует за микросекунды.

Там даже оптимизация конкатенации стрингов не доверена компилятору - потому что он ее плохо оптимизирует для этого алгоритма - а ты тут методов каких-то внешних наделал и плюсиков наставил и методов навыностил.

Думаешь я там вместо этой кучи аппендов плюсов не могу наставить и вместо табов написать красивую функцию tabs(количечтво?).

Видел там такую хитрую аннотацию @switch? Это инструкция компилятору о том чтобы он выдал ошибку компиляции если не сможет этот матч разложить в байткод на tableswitch.

Потому что в этом коде первичный параметр - перфоманс.






r ★★★★★
()
Ответ на: комментарий от pitekantrop

>Костыль, заменяющий отсутствие функций высшего порядка и замыканий. Хороший пример того как Java обфускирует абстракции и вносит тонны бойлерплейта.

К стати да - есть еще такой аспект.

r ★★★★★
()
Ответ на: комментарий от r

>К стати опять пример таки - вызовы каких-то неопределенных gettabs и тд.

Заметил геттабс.

r ★★★★★
()
Ответ на: комментарий от r

>Скажу что оно делает совсем не то что мой код:) Не мелкие ошибки - а вообще не будет работать. Эта стейтмашина совсем не такая простая как кажется.

А что, например, неправильно? Я не большой знаток Скалы, возможно какую-то хитрость не понял.

К стати опять пример таки - вызовы каких-то неопределенных gettabs и тд.

GetTabs определен в самом начале моего кода, вообще-то. :)

Там что не ясно было написано - что этот код перфоманс критикал? Этот код здоровенные jsonы форматирует за микросекунды.

Честно говоря, сильно сомневаюсь, что на Скале вообще может быть что-то перфоманс-критикал. :) Кстати, ради интереса готов свой код прогнать на мегабайтном джсоне и замерить время.

Там даже оптимизация конкатенации стрингов не доверена компилятору - потому что он ее плохо оптимизирует для этого алгоритма - а ты тут методов каких-то внешних наделал и плюсиков наставил и методов навыностил.

Ну уберу я плюсики, если окажется, что сильно проседает производительность.

Видел там такую хитрую аннотацию @switch? Это инструкция компилятору о том чтобы он выдал ошибку компиляции если не сможет этот матч разложить в байткод на tableswitch.

Это что-то не понял. Поясните, если не трудно.

AlexRK
()
Ответ на: комментарий от AlexRK

>Ошибки могут быть, я это в блокноте написал. :)

Да и вообще - чем это лучше? Опуская вещи вроде append/+ - тем что растянулось так что обозреть нельзя?

r ★★★★★
()
Ответ на: комментарий от r

>Да и вообще - чем это лучше?

По моему мнению, лучше тем, что это понять можно. :) И можно читать последовательно.

Вот скажите честно - вы свой вариант считаете более понятным? :)

растянулось так что обозреть нельзя

Ну а у вас в ширину растянулось. ИМХО, это гораздо хуже. У вас квадрат текста получился, вместо последовательного кода.

AlexRK
()
Ответ на: комментарий от AlexRK

>Кстати, ради интереса готов свой код прогнать на мегабайтном джсоне и замерить время.

Ну попробуй:)

Ну уберу я плюсики, если окажется, что сильно проседает производительность.


Такие сложные конструкции как match или жабский/шарповый switch могут компилироваться (для jvm) двумя способами - грубо говоря в кучу ifов - и в более оптимальный байткод используя инструкции tableswitch и lookupswitch. Аннотация @switch говорит компилятору что если он не сможет скомпилировать match в оптимальный байткод а не в кучу Ifов - сказать ашипка чтобы я поправил. Есть похожая аннотация @tailrec - инструкция компилятору упасть с ошибкой если он не сможет произвести хвосторекурсивную оптимизацию.

r ★★★★★
()
Ответ на: комментарий от AlexRK

>По моему мнению, лучше тем, что это понять можно

Что понять можно? Если я не ошибся ты только что переписл код со скалы на C# в блокноте - следовательно ты его понял. Так что ж тогда непонятно?

И вообще что именно ты сделал для 'понятливости'? Гварды заменил на внешние if? Опять непонятные гварды? Ну а плюсы и табы - так вперед мерять производительность:)

r ★★★★★
()
Ответ на: комментарий от r

>Если я не ошибся ты только что переписл код со скалы на C# в блокноте - следовательно ты его понял.

Ну так это ж Я. :) Кроме того, понял я его не сразу. А это плохо.

Кстати, так есть у меня в коде концептуальные ошибки или нет?

И вообще что именно ты сделал для 'понятливости'? Гварды заменил на внешние if? Опять непонятные гварды?

Поясняю. Во-первых, в вашем матчинге свалена в кучу обработка внутри строки и вне ее. Следствием чего является паразитный вызов «escape = false» в каждой строке. Это просто мусор. Во-вторых, мне не понравилось сильное дублирование кода, «append» вызывается с одинаковыми аргументами несколько раз.

Сейчас чайку попью и наваляю код без плюсиков. :)

AlexRK
()
Ответ на: комментарий от AlexRK

>И можно читать последовательно.

О да! Это я уже тоже слышал. Когда-то был код

f(f(f(a,b),c),d)

и я услышал это про «читать последовательно» и этот код ужё перписывали в длинный с кучей if «который можно читать последовательно».

Ох как же людям поломали мозг эти x=x+1 за пять лет - это ужас.

Вот скажите честно - вы свой вариант считаете более понятным?


Я скажу что мой вариант более рабочий по озвученному критерию. Когда первичный критерий кода будет «понятность читателю» - я предьявлю его со слайдами.

Ну а у вас в ширину растянулось.


У меня мой код занимает ~ 1/10-1/12 монитора. Твой вообще не влез. Даже с точки зрения 'понятности' твой читать сложнее - потому что не видно что он делает.

r ★★★★★
()
Ответ на: комментарий от r

>Даже с точки зрения 'понятности' твой читать сложнее - потому что не видно что он делает.

Это круто. Новое слово в измерении понятности - влезаемость в монитор. :)

Кода на J и K вам в монитор столько влезет - ой-ей... Только вот вы будете над ним медитировать годами. :)

AlexRK
()
Ответ на: комментарий от AlexRK

Кроме того, понял я его не сразу. А это плохо.

Вычислительнообразные алогритмы реверсировать из реализаций - вообще тяжело. Никакая расстановка пробелов или именованиеФункцийПодобнымОбразом тут не поможет.

Кстати, так есть у меня в коде концептуальные ошибки или нет?

Тяжело понять:)

У меня есть два основных параметра которые переключают state машины: string и escape. Мой код выглядит как

+----|
|    V  
|    x    !string  escape  => 
|    x    string    _     => 
|    x    string  escape  => 
|    x    _       escape  => 
|    x    string  escape  => 
|    |
+----+

То есть как автомат от троки параметров (вход, состояние_escape, состояние_string).

На кажом шаге можно с легкостью проследить в виде:

если пришла «{» , мы внутри строки, состояние escape неважно то=> приклеить символ к буферу, состояние строки не менять, состояние ескейп не менять.

Очень простые шаги с понятным предусловием и результатом переключения автомата.

У тебя с обобщенными ифами вообще очень трудно определить что делается и зачем. Модифицировать вообще тяжело - если например надо будет еще какой нить символ или последовательность модифицировать у меня - можно доавить переход, если надо добавить признак - добавляется признак и автомат становиться от 4х значений.

Чтоб понять что делается у тебя это надо очень сильно реверсировать алгоритм и если введется еще какой нить признак который например срабатывает на часть вариантов где isString а часть где не string - придется все переписывать и стараться ничего не поломать - то есть вообще все переделать.

Хм. Мне действительно нравится больше мое решение - оно более понятно и управлятся с ним легче.

r ★★★★★
()
Ответ на: комментарий от AlexRK

>Новое слово в измерении понятности - влезаемость в монитор. :)

Это не новое слово - это старое слово. Потому в IDE есть обычно правая граница переноса и изпокон веку существовали правила вроде «строка не должны превышать 80 символов в длинну».

r ★★★★★
()
Ответ на: комментарий от r

>Вычислительнообразные алогритмы реверсировать из реализаций - вообще тяжело.

Особенно написанные на «крутых языках». :)

Тяжело понять:)

Хм. А как же «вообще не будет работать» (с) ? :)

То есть как автомат от троки параметров (вход, состояние_escape, состояние_string)

Зачем такое адское усложнение? Это же банальный парсинг текста, который описывается двумя-тремя предложениями:

1. Если мы не внутри строки: если символ не пробельный, добавляем его в результат (плюс табов и пробелов по вкусу), если пробельный, не добавляем. Если нашли кавычку - переходим в режим «строка».

2. Если мы внутри строки: если пришел символ «кавычка», смотрим, если предыдущий символ не был эскейпом, то выходим из режима строки. Потом проверяем режим эскейпа. Далее в любом случае добавляем символ в результат.

Неужели я что-то упустил? Вроде просто как три рубля. Вот оно, функциональное программирование-то - провоцирует простые вещи делать сложно. :)

Мне действительно нравится больше мое решение - оно более понятно и управлятся с ним легче.

Главное, чтобы окружающим было тоже понятно и легко. :)

AlexRK
()
Ответ на: комментарий от AlexRK

>А как же «вообще не будет работать» (с) ? :)

Мне просто кажется что ты разделив на string/неstring наверху не учел равнозначного с ним стейта escape. Поэтому я подозреваю что работать будет неправильно.

Я к стати в начале пытался написать подобно твоему. Задолбался сидеть в дебаггере.

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

Задача понятна - попробуй написать быструю реализацию форматирования на C#.

Зачем такое адское усложнение?


Усложнение?!? Это формализация. Второй курс, прикладная теория цифровых автоматов!

смотрим, если предыдущий символ не был эскейпом,


Как смотрим? :)

Ну реализуй не глядя в мою реализацию собственный алгоритм.

Вот оно, функциональное программирование-то - провоцирует простые вещи делать сложно. :)


Оно провоцирует писать умно. А не по «простому обяснению».

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


r ★★★★★
()
Ответ на: комментарий от r

Мне просто кажется что ты разделив на string/неstring наверху не учел равнозначного с ним стейта escape.

В первоначальном скала-коде escape вовсе не равнозначен со стрингом, он работает только внутри строки. И проверяется только в одном месте - когда кавычка приходит. Больше он нафиг не нужен нигде, но стоит в каждой строке. :)

Как смотрим?

Ну как - если isEscape == true, значит был эскейп.

Вот кстати вариант без плюсов. Он более грязен и менее нагляден, чем мой предыдущий, но по скорости, я думаю, Скалу выдерет. :) При условии, что он корректен, конечно.

var isString = false;
var isEscape = false;
var tabs = "\n";

foreach (var x in json)
{
    if (!isString)
    {
        var suffix = String.Empty;

        switch (x)
        {
            case '"':
                isString = true;
                break;

            case '{':
            case '[':
                tabs = tabs + "\t";
                suffix = tabs;
                break;

            case '}':
            case ']':
                tabs = tabs.Remove(tabs.Length - 1);
                b.Append(tabs);
                break;

            case ',':
                suffix = tabs;
                break;

            case ':':
                suffix = " ";
                break;

            case '\n':
            case '\r':
            case '\t':
            case ' ':
                continue;
        }

        b.Append(x);
        if (suffix.Length > 0)
            b.Append(suffix);
    }
    else
    {
        if ((x == '"') && (!isEscape))
            isString = false;
    
        isEscape = (x == '\\') ? (!isEscape) : false;

        b.Append(x);
    }
}

Можно было бы аппендов напхать в каждую строку, но мне такой вариант сильно претит.

AlexRK
()
Ответ на: комментарий от AlexRK

> Зачем такое адское усложнение? Это же банальный парсинг текста, который описывается двумя-тремя предложениями:

...

Неужели я что-то упустил? Вроде просто как три рубля. Вот оно, функциональное программирование-то - провоцирует простые вещи делать сложно. :)

Т.е. ты предлагаешь в коде писать комментарии вида «// прибавляем 1 к индексу», чтоб люди, не знающие ничего могли понять? Бред полный.

При написании кода автор пользуется известными абстракциями для «кусочков» программ - КА. Любой вменяемый програмист знает, что такое КА, какие они бывают и как их использовать. Для таких людей использование таких подходов и таких формализаций упрощает жизнь, потому что им не нужны «пара предложений» (а на самом деле несколько параграфоф), ведь достаточно таблицы переходов по стейтам + экшны.

В кратце - если тебе не понятно, это не означает, что решение сложно. Это лишь означает, что ты не в состоянии понять простоту ;)

ФП - прекрасный способ писать простые программы, которые куда более естественны, чем ООП.

Пример: задачи для людей (например, покупка продуктов) формулируются декларативно, и могут быть практически 1:1 оттранслированны в функции, без лишнего бреда вроде иерархии классов и т.д.

Т.е.: Купи 2 кг картошки, 1 кг помидор, если будет свежая камбала - возми 1.5 кг.

Для человека естественно мыслить подобными формами, что поделаешь ж)

anonymous
()
Ответ на: комментарий от anonymous

>В кратце - если тебе не понятно, это не означает, что решение сложно. Это лишь означает, что ты не в состоянии понять простоту ;)

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

ФП - прекрасный способ писать простые программы, которые куда более естественны, чем ООП.

Пока что ФП предлагает способ писать программы, для исходного текста которых не нужна обфускация. :)

AlexRK
()
Ответ на: комментарий от AlexRK

Он более грязен и менее нагляден, чем мой предыдущий, но по скорости, я думаю, Скалу выдерет.

Скала быстрее того, что есть на 25%. Приемлемо быстро - но никому ничего не надрал C#:)

benchmarking json C# 10000 times, mean time 462usec
took 4630.189ms

benchmarking format: 10000 times, mean time 347 usec
took 3685ms

вот полный код форматировщика на скале:

	def format( json: String ) = {
		val b = new StringBuilder
		var string = false
		var escape = false
		var tabs = new StringBuilder
		for ( c <- json ) ( c: @switch ) match {
			case '"' if !escape => b.append( "\"" ); string = !string; escape = false
			case x@( '{' | '[' ) if !string => tabs += '\t'; b.append( x ).append( "\n" ).append( tabs ); escape = false
			case x@( '}' | ']' ) if !string => tabs.deleteCharAt( tabs.length - 1 ); b.append( "\n" ).append( tabs ).append( x ); escape = false
			case x@',' if !string => b.append( x ).append( "\n" ).append( tabs ); escape = false
			case x@'\\' if string => b.append( x ); escape = !escape
			case x@':' if !string => b.append( x ).append( " " ); escape = false
			case '\n' | '\r' | '\t' | ' ' if !string =>
			case x => b.append( x ); escape = false
		}
		b.toString
	}

r ★★★★★
()
Ответ на: комментарий от r

О, большое спасибо за тест-драйв. :)

Я сегодня ради интереса еще помедитирую над вашим кодом, попробую понять, в чем может быть дело. :)

AlexRK
()
Ответ на: комментарий от yaws


это называется грамотно опустил?

Ты сможешь грамотно опустить Джо? Ну валяй :)

вопрос был к тебе, ты заявил, что Джо кого-то там опустил, но когда дело дошло до деталей переводя на твой язык, ты «за базар не ответил».
Для остальных же, - чел просто заметил что в Scala нет мало востребованных конструкций из erlang. Согласен - нет.

Например динамическая замена кода в java доступна через OSGi.
Но в скольких повседневных приложениях это нужно, вопрос.


Ну и сам должен же с грустью понимать - раз, при наличии разномастных JRuby, Jython etc etc, до сих пор нет реализации erlang на базе JVM,


а чего тут грустить, все понятно
Ruby и Python не принципиально отличаются от java и довольно популярны. Учитывая их проблемы с производительностью, их перевели на более эффективную платформу - JVM.

Языки erlang и haskel принципиально отличаются от java, крайне не популярны,но в отличии от Python и Ruby не имеют проблем с производительностью.

Зачем кому-то тогда их переводить на JVM?
Разве что только перевести умирающие проекты на что-то более стабильное или получить доступ к «кузнице framework'ов»?

Yilativs ★★★★
()
Ответ на: комментарий от Yilativs

>это называется грамотно опустил?
Грамотно, не переходя на личности, слегонца пройдясь по явно слабым местам подавляющего большинства actor-фреймворков, в общем, не теряя лицо.
Прежде счвоего любого комментария, настоятельно рекомендую прочесть скажем, http://rsdn.ru/forum/philosophy/2261047.1.aspx

Ну и верну тебя в русло

в Scala

Scala.Actors != Scala. Речь о Scala actors и только о них. О собственно Scala речь не идет.

Например динамическая замена кода в java доступна через OSGi.

Ну, такая замена кода, полагаю, и в си с паскалем возможна.
Ты уверен, что речь об плагинах?

Вот после фразы

а чего тут грустить, все понятно

написан явный, сплошной, высокошумный бред.

yaws
()
Ответ на: комментарий от r

ну вот, *минимальный* рефакторинг кода

что такое минимальный — напишу отдельным постом

насчет 2 строк комментов в серединке — я их не особо буду отстаивать, однако комменты верхнего уровня необходимы (заменяют функции в трактовке еао197)

заметим: в результате выкидывания ненужного и кривого паттерн матчинга код *сократился* на 1 строку (можете проверить, выкинув из этого и изначального кода комменты, пустые строки и строки с одной закрывающей скобкой)

паттерн матчинг тут нужен всего лишь 1 раз, да и то, этот фрагмент при не-минимальном рефакторинге должен уйти в класс АuthScheme

P.S. рефакторил без компилятора, мог ошибиться

@rest.Method(httpMethod = Array(POST))
def login(request: rest.Request,
        @rest.Param(name = "login") login: String,
        @rest.Param(name = "password") password: String): Response =
{
    // do all the checks and return on failure
    {
        debug("accessing login... " + login)

        if( login == null || password == null ) return respond(UNAUTHORIZED, "You should provide login and password")
        if( ! AccountsStorage.contains(login) )  return respond(UNAUTHORIZED, "User not found")
        if( user.inactive ) return respond(UNAUTHORIZED, "Account is inactive")

        if( user.authScheme == "PETRIVKA")
            if( ! user.passwordMatches(password) ) return respond(UNAUTHORIZED, "Authentication failed")
        else
            // authenticate by starting external command, provided by 3d party
            // NOTE running wrong command may result in password leak into 3d party
            val authSchemeCommand = AccessStorage.access.auth_configs.find(_.key == user.authScheme) match {
                case None => return respond(FORBIDDEN, "Unknown authentication scheme: " + user.authScheme)
                case Some(scheme) => scheme.command
            }
            log.debug("authenticating with " + authSchemeCommand)
            val authProcess = Runtime.getRuntime.exec(authSchemeCommand.replace("{login}", login).replace("{password}", password))
            if( authProcess.waitFor != 0 ) return  respond(UNAUTHORIZED, "Authentication within " + authScheme + " failed")
    }
    // all checks ok, so do unconditional login
    {
        request.session("user") = user
        return respond( AUTHORIZED, "" )
    }
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eao197

ну вот, какие замечания будут по рефакторингу (постом выше)?

по модулю конечно того, что код с паттерн-матчингом при не-минимальном рефакторинге должен уйти в класс АuthScheme

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

еще одна причина выделить uncheckedLogin в отдельную функцию — это то, что у нее побочные эффекты, а то, что после выделения останется в login побочных эффектов иметь не будет — поэтому в нормальном языке можно было бы ей поставить характеристику pure (вроде это тоже хотят в скале?) и при тестинге регрессий сравнивать ее со старой реализацией например

впрочем, мне она кажется пока что недостаточно веской; не люблю лишние функции

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>паттерн матчинг тут нужен всего лишь 1 раз, да и то, этот фрагмент при не-минимальном рефакторинге должен уйти в класс АuthScheme

Чего я понять не могу - так это чего вы все пытаетесь избавиться от паттерн матчинга. Чего он у вас вызывает такой ужас, что его так стремятся заменить ifами? Пролог чтоле в детстве в кошмарах снился?:)

Комменты по коду:

Между if( ! AccountsStorage.contains(login) ) и f( user.inactive ) надо получение самого юзера. Допустим:

val user = AccountsStorage.find(login)

Критика:

1 .Пара AccountsStorage.contains() и AccountsStorage.find() - неатомарна. Последствия понятны.

2. Это 2 обращения к базе вместо одного.

3. У тебя тут вся логика построена в виде:

ifnot reject
ifnot reject
....
ifnot reject

doit

Я такой паттерн (guard clauses) допускаю когда эти проверки - совсем простые и вынесены в виде ifnot return потому что последующий код - большой. Здесь эти проверки - основнная логика. Поэтому:

Ты говорил что у меня правильщик может незаметить пары строчек рядом. У тебя правильщик может незаметить что вставил позитивное условие в код без else. Даже в стучае кучи ifов в следствии разнородности я всегда пишу код вида
if
else if
else if
_else_

иначе внести баг очень легко. Это не нужно в случае простых гвардов - но в данном случае ИМХО это просто _необходимо_ иначе потенциальная ошибка в виде залогиненого юзера когда не надо, легко вкрадывается и фиг отслеживается без отладчика что гдето в каком-то if ! (not) забыли.

Еще мне очевидно не нравится разнесение связной логики в разные места. А именно:

if( ! user.passwordMatches(password) ) return respond(UNAUTHORIZED, «Authentication failed»)

То есть если пароль не совпадает - ругнуться а если совпадает.... ничего не делать. Ээээ? Ага - логин это дефаултное поведение ищите ниже.

У меня дефаултное поведение было _не пускать_. А пустить _только_ при выполнении одного или второго условия. Все остальное - это сахар для пользователя - подробности сообщения - если бы они были ненужны - там бы было по другому - комбинатор который логинит пользователя при 2х позитивных вариантах а все None одинаково по©ілают пользователя нафик.

У тебя дефолтное поведение _пустить_. Это имхо недопустимо для кода связанного с безопасностью.

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

и еще по модулю того, что стиль r сохранен, а лучше было бы иф-ы писать не в 1 строку, а разнести по строкам

Функциональный if - это аналог ?: в жабосях. А не императивный интерсептор. И вообще раз уж тут собрались ценители чтения то

если пользователь не активен то послать его, а иначе пустить

читается «правильнее» чем маяковский

если пользователь не активен
     то послать его нафиг
иначе
      пустить.
r ★★★★★
()
Ответ на: комментарий от r

Пролог чтоле в детстве в кошмарах снился?

Видимо, о Прологе вы знаете еще меньше, чем о функциональном программировании.

eao197 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.