
Vladimir
01.02.2018
07:51:42

Fill
01.02.2018
07:52:02

Aleksey
01.02.2018
07:54:18
Свёртка - это паттерн. Паттерны, это хорошо
Правильно написать рекурсию может не каждый, да и выделение повторяющейся логики - обработки edge cases, отделения головы от хвоста - стоит выносить. Вот и вынесли уже в функции свёртки

Google

Aleksey
01.02.2018
07:55:45
Никто же не переписывает код с map на ручную рекурсию. Вот и со свёрткой та же ситуация
Ручной рекурсии место там, где по-другому никак. Mutual recursion например
"Пишешь рекурсию с аккумулятором? Скорее всего тебе нужна свёртка!"

john
01.02.2018
07:57:47
фильтер, мап, редюс

Aleksey
01.02.2018
07:58:24
в математике это свёртка, поэтому названия типа reduce (или inject вообще) - только запутывают людей :) Только fold!

john
01.02.2018
07:59:18
математика, люди синуса не знают а вы о математике

Aleksey
01.02.2018
07:59:57
А зачем тогда они в ФП лезут вообще? Придётся же всё равно хоть в каком-то объеме изучить :)

Fill
01.02.2018
08:02:14
А за объяснение спасибо

Aleksey
01.02.2018
08:02:49
Если деуствительно хочется, то и математики небольшого кол-ва не испугаются :)

Fill
01.02.2018
08:04:11
Да, не испугаются. Но насколько я вижу, ФП требует понимания программирования, а не понимания математики

Alexander
01.02.2018
08:05:09
Да кстати не всегда, квантовую химию сложно понять, а вот объяснить ещё сложнеею Про квант мех я вообще молчу
Пока писал уже удалил)

Google

john
01.02.2018
08:06:05
побоялся что поколотят

Bonart
01.02.2018
08:06:07

Alexander
01.02.2018
08:06:34

Bonart
01.02.2018
08:06:48

john
01.02.2018
08:06:51
просто есть проблема "бродячих мифов"
то от рекурсии надо избавляться
то еще чтонибудь
вот и избавляются от рекурсий и пишут циклы

Aleksey
01.02.2018
08:07:43
не надо избавляться от рекурсии. Просто рекурсию с аккумулятором, написанную руками, можно и нужно упрощать до свёртки
Единственная причина не использовать свёртку - необходимость прервать рекурсию до того, как сворачиваемые данные кончатся.

Fill
01.02.2018
08:09:46

Aleksey
01.02.2018
08:14:02
Ваш конкретный пример вполне нормально написан - тут рекурсия к месту, ИМХО

Fill
01.02.2018
08:15:02
Ну я понял, да. Но вот стейтмент - фолд всегда, когда возможно я не слышал раньше, так что спасибо)

A64m
01.02.2018
08:23:03
если оптимизаций особых нет, ФВП может просто заметно тормозить в каком-нибудь горячем месте, так что раннее завершение точно не единственная причина рекурсивную лапшу писать
цикл в F# кстати тоже может заметно тормозить из-за того во что всякие n .. 2 .. k компилируются

Aleksey
01.02.2018
08:28:47
Внутри свёртки может быть цикл :) Но выглядет будет функциональненько :)

A64m
01.02.2018
08:31:41
внутри-то может, проблема в том что все эти изкоробочные свертки не инлайнящиеся и вызовы переданных в них функций довольно дорогие
так же дотнетный IEnumerable<T> довольно тормозной по сравнению со своими аналогами из других языков

Aleksey
01.02.2018
08:34:03
Печаль

A64m
01.02.2018
08:34:28
поэтому в горячем месте со всем этим комбинированием комбинаторов в F# особо не разгуляешься.

Aleksey
01.02.2018
08:36:01
В более прохладных местах то можно :)

A64m
01.02.2018
08:37:12
вот так всегда неделанье оптимизаций и обосновывают!

Google

Bonart
01.02.2018
08:40:04
Оптимизировать корректное всегда проще, чем корректировать оптимизированное

Most
01.02.2018
08:40:47
и какое-то довольно громкое заявление про IEnumerable<T>) Лев Толстой, поди

A64m
01.02.2018
08:43:52
Оптимизировать корректное всегда проще, чем корректировать оптимизированное
так тормозные базовые инструменты к таким проблемам как раз и приводят. Энумераблы тормозные, так что те кто писал Лист решил сэкономить на спичках и сделать итератор на велью-типе, а от итераторов на велью-типах смешной баг с форичем бывает, про который Липперт 10 лет писал что теперь нельзя исправлять, а все равно потом исправить пришлось

Bonart
01.02.2018
08:46:10
К проблемам приводит забивание гвоздей микроскопом. В 99% случаев производительности хватает и так, а в 1% все равно нужна возможность подхачить ручками.
В яве нет генериков в рантайме и непримитивных значений - это как раз мешает сделать код быстрее даже руками

A64m
01.02.2018
08:47:18
ну так надо чтоб базовые инструменты с нормальной скоростью работали, чтоб программист не думал вот сейчас можно себе тормоза позволить или нет, а работу работал

Most
01.02.2018
08:47:59
» с нормальной скоростью работали
what is normalnaya skorost`?)

Bonart
01.02.2018
08:47:59
А не надо думать про тормоза до того как они возникают - преждевременная оптимизация что у нас по Кнуту?

A64m
01.02.2018
08:48:08

Bonart
01.02.2018
08:48:37

Evgeniy
01.02.2018
08:48:53
Я предлагаю направить разговор в другом направлении: вот код, вот бенчмарк, давайте обсуждать.

Bonart
01.02.2018
08:49:08
А в шарпе - сделал чтобы работало, потом МОЖЕТ БЫТЬ в 1 месте из 100 нужно (и можно) подхачить

A64m
01.02.2018
08:51:16

Bonart
01.02.2018
08:51:48

A64m
01.02.2018
08:53:51
Как и напоминать про тормозные итераторы в том же дотнете ;)
напоминать про тормозные итераторы - подход конструктиный. Потому что это проблема не решенная, а говорить ну и что что есть нерешенные проблемы, вот у нас когда-то проблему с дженериками решили, давайте лучше теперь этому до пенсии радоваться - не конструктивно. Обсуждение больше-не-проблемы вообще бессмысленное занятие, от этого ничего лучше не станет. А обсуждение проблемы - первый шаг к ее решению

Bonart
01.02.2018
08:55:09
> Потому что это проблема не решенная
Как именно не решенная? Код на итераторах можно руками превратить в быстрый. В 99% случаев медленность итераторов вообще не трогает.

Google

Bonart
01.02.2018
08:56:03

A64m
01.02.2018
08:57:35
почему без предложения? Я приводил пример имплементации более эффективных "итераторов" в другом языке.

Bonart
01.02.2018
08:58:59

A64m
01.02.2018
09:02:23
существует вполне рабочий подход для эффективной имплементации таких штук как "свертки" (обычно там не чистая свертка, так что в кавычках) существуют даже костыли, которые эмитят оптимизированный код или используют уже существующие оптимизации (не очень успешно) https://arxiv.org/pdf/1406.6631.pdf просто это все должно в компиляторе быть, а не прикостылено

Fill
01.02.2018
09:04:41
Как по мне, использование коробочных решений by default предпочтительнее, ведь их рано или поздно опимизируют в отличае от моего кода

Bonart
01.02.2018
09:05:20

Fill
01.02.2018
09:05:57
Я обычно понимаю оптимизацию, как правильную комбинацию коробочных инструментов
а не написание своих

Evgeniy
01.02.2018
09:06:29
Переписывание Seq в F#, кстати, застопорилось.
https://github.com/Microsoft/visualfsharp/pull/2745

A64m
01.02.2018
09:06:41
ну так я и говорю, что это должно быть из коробки, понятно что использовать какую-то стороннюю библиотеку типа стримс которая и не работает особо а может просто сдохнуть или тем более какой-нибудь адовый линкоптимайзер, который в рантайме что-то компиляет, ради такого никто не будет
это просто пруф оф концепт для того что должно быть в компиляторе ФЯ но нету

Bonart
01.02.2018
09:07:51
Кому должно и зачем? Возможно у разработчиков компилятора есть более приоритетные фичи. Кстати, структуры по ссылке в 7.2 как раз добавляют коробочных оптимизаций

A64m
01.02.2018
09:08:46
конечно есть, ФЯ же вечно полтора человека делают, там ресурсов ни на что не хватает, это правда не значит что ничего и не надо

Fill
01.02.2018
09:09:19

Vlad
01.02.2018
09:11:13

Evgeniy
01.02.2018
09:11:37
Это очень долгая тема, я уже не верю, что когда-нибудь смержат.
То есть уже третий PR к ряду, и там около 8к LoC нового кода с конфликтами.

Fill
01.02.2018
09:15:26
всем чатиком пулим и резолвим

Google

A64m
01.02.2018
09:16:08

Evgeniy
01.02.2018
09:29:43

Pavel
01.02.2018
11:07:01
всем добрый день, вопрос такой:
если мэтчим, например, простой инт, то можем перечислять несколько вариантов таким образом:
match x with | 1 | 3 | 8 -> "good" | _ -> "bad"
если же мэтчим опциональный тип с каким-то условием, было бы классно писать что-то типа
match option with | None | Some when <...> -> "good" | _ -> "bad", но компилироваться это не хочет, приходится писать
match option with | None -> "good"| Some when <...> -> "good" | _ -> "bad", т.е. если вместо "good" будет что-то достаточно большое, придётся либо копипастить, либо выносить в функцию (но кода всё равно становится больше, его модификация требует лезть уже как минимум в два места)
можно ли как-то это обойти штатными методами?
как вариант вижу попользовать AP, наверное


Roman
01.02.2018
11:28:32
всем добрый день, вопрос такой:
если мэтчим, например, простой инт, то можем перечислять несколько вариантов таким образом:
match x with | 1 | 3 | 8 -> "good" | _ -> "bad"
если же мэтчим опциональный тип с каким-то условием, было бы классно писать что-то типа
match option with | None | Some when <...> -> "good" | _ -> "bad", но компилироваться это не хочет, приходится писать
match option with | None -> "good"| Some when <...> -> "good" | _ -> "bad", т.е. если вместо "good" будет что-то достаточно большое, придётся либо копипастить, либо выносить в функцию (но кода всё равно становится больше, его модификация требует лезть уже как минимум в два места)
можно ли как-то это обойти штатными методами?
match option with | None | Some when <...> -> "good" | _ -> "bad"
Так работает?

Pavel
01.02.2018
11:28:48
нет

Klei
01.02.2018
11:29:14
всем добрый день, вопрос такой:
если мэтчим, например, простой инт, то можем перечислять несколько вариантов таким образом:
match x with | 1 | 3 | 8 -> "good" | _ -> "bad"
если же мэтчим опциональный тип с каким-то условием, было бы классно писать что-то типа
match option with | None | Some when <...> -> "good" | _ -> "bad", но компилироваться это не хочет, приходится писать
match option with | None -> "good"| Some when <...> -> "good" | _ -> "bad", т.е. если вместо "good" будет что-то достаточно большое, придётся либо копипастить, либо выносить в функцию (но кода всё равно становится больше, его модификация требует лезть уже как минимум в два места)
можно ли как-то это обойти штатными методами?
When относится ко всей группе, если нет возможности его через скобочки ограничить в рамках одного варианта (не пробовал), юзай шаблоны.

Pavel
01.02.2018
11:29:25

Roman
01.02.2018
11:29:32
А если написать все же
None | Some 1 | Some 3 | Some 8 -> good

Pavel
01.02.2018
11:30:50

Klei
01.02.2018
11:31:11
Если параметр в Some используется, то возникает различный набор переменных, в случае None такой переменной не существует, вот он и ругается.

Pavel
01.02.2018
11:31:52
да, причины понятны, ограничить скобочками никак нельзя, насколько я понимаю
просто вдруг уже есть какой-то стандартный active pattern для подобных вещей

Klei
01.02.2018
11:33:35
А можно пример синтаксиса такого шаблона?
А то мне в голову не приходит, как его можно зауниверсалить.

Pavel
01.02.2018
11:37:27
пытаюсь написать, но, похоже, я тупой
вот это компилируется:
let (|NoneOrCond|Other|) condition option =
match option with
| None -> NoneOrCond
| Some x when condition x -> NoneOrCond
| _ -> Other
но я теперь не знаю как это использовать потому что на
let test cond t =
match t with
| NoneOrCond cond -> "good"
| Other cond -> "bad"
компилятор ругается

Григорий
01.02.2018
11:44:59
а что если "разобрать" значение опционального типа и после уже сравнивать в match?

Pavel
01.02.2018
11:46:18
всм всё это делать в AP?