LINUX.ORG.RU
ФорумTalks

Выразительный код без программазма на вашем любимом ЯП

 ,


1

2

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

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

function makesequencer(next_f)
    let X = Nothing
        function(Y)
            if X == Nothing
                # initialization
                X = Y
            else
                Xnew = next_f(X, Y)
                X = Xnew
            end
            return X
        end
    end
end

А можно ли ту же идею реализовать на вашем любимом ЯП? Желательно с минимумом программазма в виде новых типов, классов-хренассов... В моем примере вообще нет упоминания никаких типов данных.

★★★★★

Ответ на: комментарий от t184256

Гвидо обкурился что ли - ужОс какой нечитаемый код.

Надо быть проще и создавать сопровождаемый код

import java.util.function.Consumer; // "Парный" интерфейс для Supplier

public class Test2 {
    
    private static String s = "";

    private static String mycat(String s) {
        return Test2.s += s;
    }
    
    public static void main(String[] args) {
        Consumer<String> sequencer = s -> mycat(s) ;
        sequencer.accept("O");
        System.out.println(s);
        sequencer.accept("боже");
        System.out.println(s);
        sequencer.accept("ООП");
        System.out.println(s);
        sequencer.accept("как");
        System.out.println(s);
        sequencer.accept("страшно");
        System.out.println(s);
        sequencer.accept("жить");
        System.out.println(s);
    }
}

O
Oбоже
OбожеООП
OбожеООПкак
OбожеООПкакстрашно
OбожеООПкакстрашножить

Можно и

    private static StringBuilder sb = new StringBuilder();

    private static StringBuilder mycat(String s) {
        return sb.append(s);
    }

Чай не педон, для enterpriZe-проектов предназначено.

Bioreactor ★★★★★
()
Последнее исправление: Bioreactor (всего исправлений: 1)
Ответ на: комментарий от Bioreactor

А я и не призываю писать это с применением ООП и без всего арсенала стандартной библиотеки, это в натуре нелепо. Хочешь обсуждать, как обкурился Гвидо? Критикуй Выразительный код без программазма на вашем любимом ЯП (комментарий), там для этого полный простор, правда @aedeph_ уже почти все сливки собрал.

t184256 ★★★★★
()
(defun make-sequencer (fnext &aux x)
  (lambda (y)
    (setf x (if x (funcall fnext x y) y))))

Пример:

(loop :repeat 5
      :with seq = (make-sequencer #'+)
      :do (print (funcall seq 1)))

lovesan ★★
()

Не любимый ЯП и нет варварского Y, но вспомнилось:

(defn makesequencer [f] (partial reductions f))

Пример:

(println ((makesequencer +) [1 2 3 4 5]))
t184256 ★★★★★
()
sub make-sequencer(&next) { # Функция
    sub ($x) { # Возвращает анонима...
        state $prefix; # Переменная блока в анониме
        # "с префиксом, вернуть next и присвоить префиксу"
        return $prefix = &next($prefix, $x) with $prefix; # &next втянуто в замыкание нашей анонимной функции
        # "просто присвоить"
        return $prefix = $x;
    }
}

my $fun = make-sequencer(* ~ *); # '~' для конкатенации, сокращение для sub myconcat($a, $b) { $a ~ $b }, &myconcat аргументом
say $fun('минимум'); # минимум
say $fun('классов'); # минимумклассов

Со смайликом. * ~ *

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

ТС просил не функцию на коллекциях, а обобщенный генератор.

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

Это понятный код
final int[] cnt = new int[1];

Недолямбды из жабки не умеют захватывать по ссылке, поэтому городим анальный цирк из костылей, ЫЫЫЫЫЫ!

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

реализовывать генераторы не через генераторы откровенно непитонично

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

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

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

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

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

Во-первых, ТСу уже показали, что на нормальных языках и велосипед короче.

Во-вторых, минимализм в языке противоречит выразительности. Код с генераторами выразителен. Код на замыканиях и ФВП — минималистичен. Ты же используешь map/reduce/filter, несмотря на то, что все они map и filter можно выразить через reduce, а reduce — через рекурсию? Вот и тут тот же случай.

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

А, так ты просто избирательно незрячий хейтер. Жаль.

t184256 ★★★★★
()

можно ли ту же идею реализовать на вашем любимом ЯП

Все языки равнозначны по возможностям реализации идей. Разница есть только в выразительности (где-то нужно 3 строчки, где-то 300).

no-such-file ★★★★★
()
Ответ на: комментарий от t184256

Любой минималистичный expression-oriented язык с ФВП, замыканиями и лямбдами будет выразительней питона со всеми его специальными примочками.

bread
()

Изменяемое состояние, да ещё неявно — это несомненное говно.

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

В этом случае это чистой воды scanl1.

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

Будто в императивном языке негде больше состояние вбросить. Тем более такой контекст, недоступный ниоткуда кроме генератора, не самое большое зло.

bread
()
Ответ на: комментарий от shkolnick-kun

И как это гуано будет работать в нескольких потоках одновременно?

Тут же надо сначала разобраться, что имеет смысл параллелить, а что распараллелить невозможно теоретически. В примере, который я привёл, Y обновляется строго последовательно, потому что отражает состояние физической системы в конкретный момент времени. Но как только текущее состояние получено, проводимые над ним вычисления можно параллелить, если в этом есть практический смысл (уменьшить время реакции на изменения входных данных). Т.е., ф-ция next_f может использовать какую угодно параллелизацию внутри себя, на вызывающий её код это никак не повлияет.

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

Тема вроде про лаконичность, а вы лишние переменные вставляете.

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

Запрещаю тебе юзать map/reduce/filter/list comprehensions год. Надоест выражаться — признаешься, что глупость ляпнул.

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

Массив - это _ссылочный тип данных_ в Java.

Если мамкины борщехлёбы этого не знают - это проблемы мамкиных борщехлёбов.

Умничать будете на собеседовании.

Или в собесе.

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

«Проблемы индейцев шерифа не волнуют.»(С)

Проблемы кулькакеров меня не волнуют.

import java.util.function.Supplier;
import java.util.concurrent.atomic.AtomicInteger;

public class Test1 {
    static private Supplier<Integer> raccoon(int x, int y) {
        final AtomicInteger atomic = new AtomicInteger();
        atomic.set(x);
        return (() -> atomic.getAndAdd(y));
    }
    
    public static void main(String[] args) {
        Supplier<Integer> lotor = raccoon(5, 5);
        for (int i = 0; i < 3; i++) {
            System.out.println(lotor.get());
        }
    }
}

$ javac Test1.java

$ java Test1
5
10
15

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

Понимаете, это всё разговоры типа «Money Talks, bullshit walks»(C).

Такого количества библиотек, фреймворков, средств разработки и т.п., как для Java нет ни для одного языка программирования.

Да, порог вхождения в Джаву высок (я имею в виду реальное enterpriZe программирование, а не «хелловорлд») , но и окупаемость весьма высока - так круто платят только за Джаву

https://lh6.googleusercontent.com/moQ0P0fA-m8seYkoZ21k3NwQ6HxvDBgeiIRbwH5sS6c...

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

но и окупаемость весьма высока - так круто платят только за Джаву
https://lh6.googleusercontent.com/moQ0P0fAm8seYkoZ21k3NwQ6HxvDBgeiIRbwH5sS6c...

Эта картинка мало что говорит без инфы о размерах каждой выборки. На основе таких данных сравнения не получится. И вообще, если кроме среднего не указывается статистики второго порядка, такие измерения можно сразу выкидывать. И выводы делать некорректно. То же самое, что утверждать, что китаец богач, потому что в Китае дофига миллионеров. Да, дофига, но гораздо больше нищебродов.

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

Java и есть «КОБОЛ 21 века»(С).

А по поводу

Политика партии: «раз у тебя в лямбде столько хреноты, то она заслужила имя».

(C)

interface My {
    public void m(int x, int y);  // Да, строгая типизация в Java обязательна
}

public class Test4 {
    public static void main(String[] args) {
        ((My) ((x, y) -> System.out.println(x + y))).m(40, 2); // пожалуйста, лямбда без имени
    }
}

В Groovy (это язычок такой, в https://www.ibm.com/developerworks/ru/library/j-groovierspring1/index.html широко используется) это «сворачивается» до

((x, y) -> println x + y)(40, 2);

Учите enterpriZe языки, хоть COBOL, хоть Java

Но учите, прежде, чем запостить что-то.

Bioreactor ★★★★★
()
Последнее исправление: Bioreactor (всего исправлений: 1)

js:

var getNext = function(y) {
       return this.x = (this.x ? this.nextf(this.x, y) : y);
}
var seq = getNext.bind({nextf : somefunction});

seq(1);
...

Как-то так.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от Bioreactor

Аналогия в логике не является доказательством -

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

Мы говорим конкретно про востребованность программистов на рынке.

Уже о востребованности? До этого речь шла о «окупаемости» и «так круто платят только за Джаву».

seiken ★★★★★
() автор топика
Ответ на: комментарий от shkolnick-kun

Глобальных переменных нету. Требования чтобы внутренние переменные синхронизировались не было. Предлагаешь все функции всегда без разбору делать thread-safe, даже когда не просили?

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

Julia собирается через LLVM в натив и работает на математике как С++/Fortran. Ну с поправкой пока-что на какие-то недоделки или отсутствие оптимизаций в нужном месте. Но язык разработан так чтобы не содержать фич, которые своим существованием мешали бы хорошему компилятору создавать максимально эффективный код. У Python/JS такой задачи не стояло

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Они эту нишу уважают (лаконичность) и делают что могут. Но для них это не главное.

Вот если на YouTube пойти и посмотреть например JuliaConf или какую-то конференцию по большим научным вычислениям, то там дофига фортрана и С++. И люди там так и говорят, мы вот мол ученные, хотим писать алгоритмы. Но мы уже задолбались прототипировать на R/Python, а потом или переписывать то же самое на C++/Fortran или еще хуже - просить «программистов». Например вместо этого есть история успеха, как на Julia сначала написали прототип локально, а потом запустили на кластере тот же код лопатить несколько петабайт - гигантский набор снимков с телескопов, который распознавал категоризировал все звезды и галактики. При том что Julia вполне по лаконичности еще ничего, уж точно в разы лучше С++/Fortran, да еще с MPI/OpenMP.

https://www.youtube.com/watch?v=uecdcADM3hY

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Но мы уже задолбались прототипировать на R/Python, а потом или переписывать то же самое на C++/Fortran или еще хуже - просить «программистов».

Т.е. апологеты Джулии против разделения труда?

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

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

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

Против неадекватного да. Тот же Devops тоже появился из отжившего свое разделения, где оно не нужно, тормозит развитие и растит бюрократию

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

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

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)

stateful функция

выразительный код

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

Предлагаешь все функции всегда без разбору делать thread-safe, даже когда не просили?

Нет, но хотя бы такими, чтобы их можно было легко сделать thread-sаfe.

Требования чтобы внутренние переменные синхронизировались не было.

Дада, а потом обязательно найдется професси-АНАЛ, который заюзает в многопоточном коде, и будет долго удивляться, когда через некоторое время что-нибудь пойдет «не так».

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

Это не повод везде городить Mutex или Lock-free штуки (которые тоже что-то стоят) просто потому что все твои коллеги не задумываются о многопоточности и не пытаются узнать статус thread-safety у API. Вместо этого, если язык не защищает как-то сам, нужны peer-review которые это поймают

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

Они эту нишу уважают (лаконичность) и делают что могут. Но для них это не главное.

Ну да. Тут или быстро или просто.

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

$60 000 в год в ДС - это круче $130 000 per year в D.C. (извиняйте за каламбур.)

Ибо в Штатах человек - это тот у кого собственное жилье имеется, а не тот, кто гастарбайтер, зависимый от рабовладельца ^W квартировладельца.

Я таки бывал в Штатах, мне очень там понравилось, но я не «путаю туризм и эмиграцию»(С).

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