|
Лямбда функции | ☑ | ||
---|---|---|---|---|
0
Почему 1С
12.02.21
✎
14:20
|
Может вопрос не по профилю форума, но видел подобные вопросы по compscience.
В общем вопрос такой, кто посоветует материал (курсы , книги), чтобы освоить лямбда функции, сами то они просты, но видимо требуют особого понимания как научится мыслить ими. Я могу читать и понимать код состоящий из каскада лямбда функций, но вот сам так писать не могу (всегда скатываюсь классический код без функциональщины), а хочу практики чтобы набить руку и при этом делать это правильно. Если кто имеет опыт буду благодарен если поделитесь. |
|||
1
Serginio1
12.02.21
✎
14:40
|
Широко используется Linq
https://metanit.com/sharp/tutorial/15.1.php |
|||
2
Почему 1С
12.02.21
✎
14:50
|
(1) Так же очень активное применяются в Kotlin который я сейчас осваиваю, и вот прохожу курсы где можно смотреть решения других участников и 90% этих решений на лямбда функциях в несколько строк и очень красивые. Мои же решения выглядят неуклюже по сравнению с ними, но все мои попытки писать в таком стиле вызывают затруднения, вот и хотелось материал на котором можно натаскаться подобному подходу, поиски по интернету как правило приводят к простому объяснению как работает каждая функция.
|
|||
3
pavig
12.02.21
✎
14:57
|
(2) Приведи пример?
|
|||
4
Serginio1
12.02.21
✎
14:59
|
(2) Посмотри статьи по Linq
Суть лямба функций в замыкании. Создается анонимный класс где свойствами являются используемые переменные и свойтва https://itvdn.com/ru/blog/article/closing-in-csharp |
|||
5
Serginio1
12.02.21
✎
15:00
|
Так же были подводные камни в старых версиях при замыкании переменных цикла
https://habr.com/ru/post/141270/ |
|||
6
Asmody
12.02.21
✎
15:05
|
(4) как же у вас забиты мозги!
Анонимный класс - это способ реализации, своего рода - костыль. Лямбда-функции и замыкания - это разные, хоть и тесно связанные вещи! |
|||
7
Asmody
12.02.21
✎
15:09
|
Лямбда-функция - это просто анонимная, т.е. неименованная функция. Всё!
Сила лямбда-функций может проявиться только в языках, где функции являются объектами первого класса. (Изначально в java/c# таковыми не являлись, откуда и появился этот костыль анонимными классами) |
|||
8
Asmody
12.02.21
✎
15:09
|
вот https://www.ohaskell.guide/lambda-function.html - просто и понятно
|
|||
9
Провинциальный 1сник
12.02.21
✎
15:11
|
(8) Ключевой вопрос "зачем?". Там на него не дается ответа..
|
|||
10
Почему 1С
12.02.21
✎
15:15
|
(3)
package tictactoe fun main() { println("Enter cells:") val inp = readLine()!!.toCharArray() val b: Array<Array<Char>> = Array(3) { Array(3) { '_' } } for (i in 0..8) b[i / 3][i % 3] = inp[i] println("---------") for (i in b.indices) { println(b[i].joinToString(prefix = "| ", postfix = " |", separator = " ")) } println("---------") var wincnt = 0 var winner = ' ' for (i in 0..2) { if (b[0][i] == b[1][i] && b[1][i] == b[2][i]) { wincnt += 1; winner = b[0][i] } } for (i in 0..2) { if (b[i][0] == b[i][1] && b[i][1] == b[i][2]) { wincnt += 1; winner = b[i][0] } } if (b[1][1] == b[0][0] && b[1][1] == b[2][2]) { wincnt += 1; winner = b[1][1] } if (b[1][1] == b[0][2] && b[1][1] == b[2][0]) { wincnt += 1; winner = b[1][1] } when { inp.count { it == 'X' } > inp.count { it == 'O' } + 1 || inp.count { it == 'O' } > inp.count { it == 'X' } + 1 -> { println("Impossible") } wincnt > 1 -> println("Impossible") wincnt == 1 -> println("$winner wins") wincnt == 0 && inp.contains('_') -> println("Game not finished") else -> println("Draw") } } Вот решение задачи крестики нолики, на входе расположение крестиков и нодликов на выходе анализ на победу 0 или x |
|||
11
Serginio1
12.02.21
✎
15:16
|
(7) >>Лямбда-функция - это просто анонимная, т.е. неименованная функция. Всё!
То есть она не может быть замыканием? А вот организация замыкания в C# это анонимный класс |
|||
12
Почему 1С
12.02.21
✎
15:16
|
Свой код не привожу он в 5 раз длинее
|
|||
13
Serginio1
12.02.21
✎
15:19
|
(7) >> (Изначально в java/c# таковыми не являлись, откуда и появился этот костыль анонимными классами)
Суть в том, что нужно отдельно хранить замыкаемые переменные ибо лямбды могут передаваться куда угодно и изменяться. Проще все это организовывать через классы. |
|||
14
Asmody
12.02.21
✎
15:33
|
(11) Замыкание - "это другое". Замыкание - это сохранение в контексте функции ссылок на внешние переменные. Замыканию не обязательно быть лямбдой. И наоборот - лямбда не обязательно замыкание
|
|||
15
Почему 1С
12.02.21
✎
15:45
|
(10) кстати плохой пример, а хороший найду вернусь к этой теме. Почему то не могу по решенным задачам нормально посмотреть историю на hyperskill.org где с этим и столкнулся
|
|||
16
Asmody
12.02.21
✎
15:52
|
(10) Это раст что ли? А when {} это там что?
|
|||
17
Вафель
12.02.21
✎
15:54
|
как можно не понимать лямбда функции?
это же классическое у => х * х |
|||
18
Вафель
12.02.21
✎
15:55
|
хитрые трюки с замыканиями. это да...
|
|||
19
GANR
12.02.21
✎
15:56
|
А что там понимать? Берём на JavaScript и пишем механизм, который в каждый тег <P> (абзац) в HTML-страничке добавляет атрибуты обнуляющие отступ сверху и снизу. Узнаете 2 вещи - регулярные выражения и лямбды - без этого, если не применять XSLT и работать с HTML-страницей как со строкой просто никак.
|
|||
20
Serginio1
12.02.21
✎
15:57
|
(14) Так в чем разница?
Лямбда может быть замыканием, а может и не быть Замыкание это лямбда выражение! |
|||
21
Почему 1С
12.02.21
✎
15:58
|
(17) kotlin, но пример плохой, просто короткий, но сути моего вопроса не раскрывает фигурные скобки это тело
|
|||
22
Asmody
12.02.21
✎
15:59
|
(20) "Замыкание это лямбда выражение" - нет!
|
|||
23
Почему 1С
12.02.21
✎
15:59
|
when это switch
|
|||
24
Вафель
12.02.21
✎
16:00
|
(19) такое лучше через жквери или дом делать, зачем строки?
|
|||
25
GANR
12.02.21
✎
16:02
|
(24) Была у меня одна задачка специфическая, что вот JavaScript, RichText как строка и ничего вот больше - была печатная форма на BIRT, к которой так просто эти DOM и прочие специализированные инструменты не очень-то и применишь.
|
|||
26
Serginio1
12.02.21
✎
17:09
|
(22) А что?
var i=1; Func<int> замыкание = () => i + 1; |
|||
27
Uberschall
12.02.21
✎
17:10
|
(6) (7) один из способов реализации, хотя, да, в Java меньше возможностей для функционального программирования. минус в том, что нельзя сделать inline функцию (минус производительность) или замыкание на нефинальные переменные, но зато можно использовать ФП вместо императивного стиля.
(2) а на каком уровне у Вас java? Мне кажется, без неё в Kotlin делать нечего. (10) inp.count { it == 'X' } - это по сути аналог stream'ов для коллекций пошел (встроенная либа для котлин) и т.д. |
|||
28
Uberschall
12.02.21
✎
17:15
|
(26) замыкание - это способ захвата переменных для использования их в контексте, когда будет выполняться собственно лямбда (контекст её выполнения может не совпадать с контекстов, в котором находится захватываемая переменная). он-захват может происходить, а может и не происходить.
|
|||
29
Доктор Манхэттен
12.02.21
✎
17:50
|
(0) Понять легко. Главное принять что функция - это такой же объект как и любой другой. Как объект-массив или как объект класса или как объект-строка. У которого так же есть ссылка, и который можно передать куда угодно в качестве параметра, по ссылке.
|
|||
30
Serginio1
12.02.21
✎
18:01
|
(28) Читаем внимательно (20)
Я говорю, что замыкание это лямбда выражение; Лямбда выражение может быть замыканием, а может и нет Ты с этим не согласен? |
|||
31
Почему 1С
12.02.21
✎
18:42
|
(27) Java на уровне университетского курса, Kotlin же это почти та же самая Java, только изящнее
(29) Понимание есть, нет навыка их использования для решения задач и хочется хорошей практики. Я про использование вида strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }.zip... Вот таких цепочек. Если тут вроде как это элементарно, то решая обычные задачи я как правило их использую на уровне sort filter map по прямому назначению, народ же оперирует ими уже для цепочки решения. задачи в целом. Я так чувствую чтобы освоить такой ход мышления нужно сначала освоится в чистофункциональных языках как иной парадигме программирования. val arr = readLine()!!.toInt().downTo(1).map { readLine()!!.toInt() } - считать с командной строки количество элементов массива и потом считать сами эти элементы в массив я же пишу val size = scanner.nextInt() val array = IntArray(size) for (i in 0..array.lastIndex) { array[i] = scanner.nextInt() } |
|||
32
Почему 1С
12.02.21
✎
18:48
|
val arr = IntArray(scanner.nextInt()) { scanner.nextInt() }
или вот тоже самое |
|||
33
Asmody
12.02.21
✎
18:58
|
(31) самое сложное в этих цепочках - левый и правый reduce. остальное очевидно
|
|||
34
Провинциальный 1сник
12.02.21
✎
19:00
|
Нихрена не понима... Нас такому не учили(
|
|||
35
Asmody
12.02.21
✎
19:03
|
и вот в таких штуках
val arr = readLine()!!.toInt().downTo(1).map { readLine()!!.toInt() } надо очень осторожно с !! - если я правильно понимаю, то это реализация nullsafe. Ну, т.е. если там null, то выполнение цепочки остановится и все выражение вернет null особенно, когда оно внутри map - могут получиться элементы null |
|||
36
Почему 1С
12.02.21
✎
19:11
|
(35) Котлин вообще на уровне компиляции запрещает обращение к null, а вот эта !! штука это подстройка под Java (readline - это Java метод) и значит она что мы гарантируем что функция java с !! никогда не возращает null
|
|||
37
Доктор Манхэттен
12.02.21
✎
19:28
|
(31) Ты неправильно пишешь, потому что объявляешь массив в одном месте, а инициализируешь в другом, еще и в цикле его модифицируешь много раз. Это антипаттерн. Нужно инициализировать массив только один раз, через val arr = ..., и больше его не модифицировать, как будто это константа. Тогда научишься писать в правильном стиле.
|
|||
38
Доктор Манхэттен
12.02.21
✎
19:30
|
(35) Если приходится использовать nullsafe, значит решение изначально спроектировано не верно. Нужно искать ошибку где-то выше.
|
|||
39
Почему 1С
12.02.21
✎
19:40
|
(37) Тут задача заполнить массив определенным количеством элементов из ввода, покажи как сделать тоже самое не инициализируя массив и не модифицируя затем его элементы?
Напоминаю сами элементы это последовательный ввод с stdin |
|||
40
Доктор Манхэттен
12.02.21
✎
19:48
|
(39) val arr = readLine()!!.toInt().downTo(1).map { readLine()!!.toInt() }
|
|||
41
Почему 1С
12.02.21
✎
20:01
|
toInt().downTo(1) - определение ренджа
map { readLine()!!.toInt() } - формирование list по ренджу List можно заранее не инициализировать, как не инициализировать заранее Array |
|||
42
Serginio1
12.02.21
✎
20:54
|
(14) Кстати в .Net есть такое понятие как деревья выражений
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/expression-trees/ Выглядит как лямда функции но ими не являются Expression<Func<int, bool>> lambda = num => num < 5; Широко применяются в Linq для IQueryable https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries |
|||
43
Ненавижу 1С
гуру
12.02.21
✎
21:40
|
(42) прикольная вещь кстати
Но что-то там не до крутили раз приходится так выкручиваться https://m.habr.com/ru/company/jugru/blog/423891/ |
|||
44
Asmody
12.02.21
✎
21:56
|
(38) не, ну как? там же внешний мир. в теории может случиться так, что readLine() вообще неоткуда будет читать. что тогда оно вернет?
|
|||
45
Asmody
12.02.21
✎
21:57
|
Таки вывалится:
"Для любителей NPE существует ещё один способ. Мы можем написать b!! и это вернёт нам либо non-null значение b (в нашем примере вернётся String), либо выкинет NPE" https://kotlinlang.ru/docs/reference/null-safety.html |
|||
46
Доктор Манхэттен
12.02.21
✎
22:44
|
(44) По хорошему нужно написать свою функцию вместо readLine(), которая все проверки делает внутри себя, а не снаружи костылями, и не возвращает ничего кроме числа. Если не ввели ничего, то возвращает 0, если ввели какие-то цифры, то возвращает это число. Если ввели неправильный текст, то выбрасывает исключение, но не возвращает никаких null. Это же основы чтобы не говнокодить.
|
|||
47
Asmody
12.02.21
✎
22:55
|
(46) Зачем изобретать велосипед? readLine() - функция JVM. ниже падать некуда особо
|
|||
48
ДедМорроз
12.02.21
✎
23:26
|
Лямбда функция это не совсем анонимная функция,это фактически загрузка программного кода в интерпретатор.
На компиллируемых языках смысла в анонимных функциях нет,в принципе,т.к.компиллятор все равно будет создавать код,который будет иметь место и адрес,а есть ли у нее имя или нет,это внутри исполняемого кода будет не видно. А вот загрузить в интерпретатор только что созданный код-это один из способов программного изменения кода программы. Почему-то,этого все бояться,но за этим будущее. |
|||
49
Ненавижу 1С
гуру
12.02.21
✎
23:44
|
(48) анонимные функции в компилириуемых языках это синтаксический сахар. Позволяет описывать функцию в точке создания ссылки на неё. А раз так, то можно применить и замыкание, но не обязательно.
Кстати, в компилириуемых языках в точке вызова может и не известен быть адрес функции. Например, если она передается параметром в другую функцию. |
|||
50
Доктор Манхэттен
12.02.21
✎
23:49
|
(47) Ниже не нужно. Нужно выше
|
|||
51
Доктор Манхэттен
12.02.21
✎
23:55
|
(48) Ты все перепутал. Лямбда функция вовсе не создается при выполнении программы, она задается на этапе программирования, и ее код нельзя менять во время выполнения.
Это только синтаксис, и ничего более. С тем же успехом в той же точке можно было бы объявить обычную функцию, и ничего бы не изменилось. |
|||
52
sitex
naïve
12.02.21
✎
23:56
|
(42) Субъективное мнение. не соглашусь
|
|||
53
Ненавижу 1С
гуру
13.02.21
✎
00:04
|
(52) с чем конкретно не согласен?
|
|||
54
Доктор Манхэттен
13.02.21
✎
02:56
|
(53) Пока еще не понял с чем не согласен.
|
|||
55
Почему 1С
13.02.21
✎
07:01
|
(37) Я так и не понял антипатеррна с с инициализацией массива и заполнением его в цикле, дай ссылку на сам антипаттерн?
|
|||
56
Доктор Манхэттен
13.02.21
✎
08:08
|
(55) Даже не знаю как еще проще объяснить. Но попробую:
Представь что массив - это константа после того, как он объявлен. И его значения тоже константы. Их нельзя второй раз перезаписывать. Создал один раз массив, и все. Больше его нельзя менять. Так понятно? |
|||
57
Почему 1С
13.02.21
✎
08:39
|
(57) ссылку на антипаттерн дай я там почитаю, пойму, можно на английском.
|
|||
58
ДедМорроз
13.02.21
✎
09:43
|
(51) как бы,в javascript мы при определении описываем тело функции строкой,и можем ее собрать так,как нам нужно.
В компиллируемых языках для некоторого изменения кода используются указатели на функции. Собственно,любой код имеет адрес точки входа,то,что ее ни программист ни интерпретатор явно не видят,не говорит,что ее нет. |
|||
59
ДедМорроз
13.02.21
✎
10:05
|
И потом,в любом языке мы можем определить сложное выражение из арифметических операций,типа sin(x*0.85)*(y+(2*x))+28.5*exp(x+y), чем вам не лямбда-функция.
|
|||
60
Кирпич
13.02.21
✎
10:08
|
Херня это всё. Куда снег девать? Через забор уже переметает.
|
|||
61
Вафель
13.02.21
✎
12:26
|
(56) если важна скорость работы, то каждый раз пересоздавать массив - некомильфо
|
|||
62
Serginio1
13.02.21
✎
12:42
|
(43) На то они и деревья выражений. С одной стороны они были придуманы как дерево для разбора и при этом еще могут компилироваться в рантайме.
Круть. Но не без наворотов. Кстати нет родного сериализатор десериализатора (59) Можем. Только в замыкании x может быть свойством объекта y локальной переменной метода да еще внутри yield. При этом эти значения могут меняться после передачи этой лямбды в другой объект. |
|||
63
ДедМорроз
13.02.21
✎
12:53
|
Это называется передача по ссылке.
Смысл передачи функции вместо результата только в том,что значение функции будет вычислено тогда,когда нужно,в случае многопоточности и возможного изменения начальных параметров это очень важно. В остальных случаях,в принципе,все на усмотрение транслятора. |
|||
64
Злопчинский
13.02.21
✎
12:53
|
(10) какято хрень полная а не решение задачи. хотя перебор - тоже решение. или я ничего не понял
|
|||
65
Serginio1
13.02.21
✎
13:30
|
(63) В любом случае лямбда выражение это функция. Просто в .Net создается анономный класс во время компиляции, в рантайме создается объект этого класса и передается метод этого класса.
Когда в .Net еще не было лямбд были анонимные методы https://github.com/dotnet/csharplang/issues/1239 И было очень не удобно. Но с приходом Linq появились и лямбды которые могли быть замыканием. Да и что касается ссылок на свойства класса в .Net до до недавнего времени их и не было. А что касается переменной метода, то как быть с этой ссылкой если ссылка на лямбду осталась уже после того, как покинули метод? В .Net есть очень удобная конструкция yield для посироения итераторов (в том числе и для рекурсивного обхода) Там как раз и начали генерить классы для построения итераторов. В том числе и для async await |
|||
66
ДедМорроз
13.02.21
✎
13:42
|
Ссылка на контекст-это вообще проблема всех языков.
Если у нас контекст функции живёт в стеке,то сделать на него ссылку можно,пока мы не вышли из функции,а после выхода он разрушается. Соответственно,мечтая о ссылках,приходится контекст куда-то прятать из стека. С одной стороны,это очень удобно,т.к. позволяет делать несколько функций с одним контекстом,ну то есть объект в понимании объектно ориентированного языка. С другой стороны,для контекстов также начинает работать сборка мусора,и программист может "потерять" в контексте большой и ненужный объект. Опять же,без фильтрации контекста тоже сложно,некую фильтрацию обеспечивает наследование классов,но не до конца,иногда хочется явно указать,что должно быть в контексте. Ну то есть передавать все в параметрах функции,что опять же,приводит к расходу памяти,так как при вложенных вызовах один и тот же параметр просто перелетает из контекста в контекст. Что касается отложенного исполнения,то это изобретение геморроя на пустом месте. Функции обратного вызова реализуют отложенное исполнение на порядок лучше,так как все системные вызовы,приводящие к отложенному исполнению,как раз работают на прерываниях и обратном вызове. С учётом возможности передачи контекста в обратный вызов про остальные реализации можно забыть. |
|||
67
ДедМорроз
13.02.21
✎
13:48
|
Собственно,передача контекста важна в следующем случае.
Допустим из-вне вызывается экспортная функция или метод объекта с двумя параметрами A и B. Мы хотим,чтобы одному ввзывателю была передана одна функция,а другому - другая,так как обработка зависит от ввзывателя. Простое решение-создание двух заглушке,которые вызывают функцию с третьим параметром,описывающим вызывателя. Для объекта существует возможность или создания двух объектов или создание объектов-заглушек. Когда же есть контекст,то мы просто передаём дополнительную информацию в нем.На самом деле,транслятор также создаёт несколько функций,но программист этого не видит и об этом не задумывается. |
|||
68
Serginio1
13.02.21
✎
14:42
|
(66,67) Это все лирика. Понимаешь замыкания и удобны тем, что вся магия делается компилятором.
Простейшее решение просто создаешь лямбду функцию и передаешь куда угодно и не задумываешься, что и как и когда её будут использовать. Вот в 1С нет замыканий и этот очень обедняет язык. |
|||
69
Asmody
13.02.21
✎
14:46
|
"и не задумываешься" - вот это особенно заметно
|
|||
70
Ненавижу 1С
гуру
13.02.21
✎
15:04
|
(69) это к чему?
|
|||
71
Asmody
13.02.21
✎
15:36
|
(70) это к слову
|
|||
72
Serginio1
13.02.21
✎
17:17
|
(69) А можно поподробнее про особенно заметно? Что именно меня так выдало?
Про "не задумываешься" приведу конструкции для async await для TypeScript когда JS их не поддерживал https://stackoverflow.com/questions/42412145/what-is-a-state-machine-in-terms-of-javascript-promises-and-c-sharp-asyc-await Мне не интересно как раскручивают деревья выражений провайдеры Linq запросов в SQL запросы. Там реально конструкции могут быть сильно навороченные. Я голову лучше забью другими вещами. Но суть, что и как я знаю. И если скорость не соответствует критериям, тогда только и ищу узкие места и занимаюсь оптимизацией |
|||
73
Asmody
13.02.21
✎
18:51
|
Если ты пишешь цепочку типа list.filter(fn1).map(fn2).foldr(fn3), сколько в результате будет циклов по побору данных? а если вспомнить про иммутабельность, сколько памяти потребует такой фокус?
так что писать в функциональном стиле очень приятно, но "не задумываясь" может привести к нехорошим последствиям |
|||
74
Asmody
13.02.21
✎
18:52
|
"побору данных" => "набору данных"
|
|||
75
Serginio1
13.02.21
✎
19:18
|
(73) Ты пропустил про yield про который я писал. Это ленивые итераторы.
Здесь про оптимизаторы и сравнение yield с массивом https://mattwarren.org/2016/09/29/Optimising-LINQ/ Даже без оптимизаторов Where склеиваются. https://docs.microsoft.com/ru-ru/dotnet/standard/linq/performance-chained-queries Ну и еще раз про оптимизаторы Linq https://github.com/antiufo/roslyn-linq-rewrite Кроме того есть Parallel LINQ https://docs.microsoft.com/ru-ru/dotnet/standard/parallel-programming/introduction-to-plinq Оптимизациями нужно заниматься тогда, когда это приносит ощутимый прирост в скорости. От того что ты будешь заниматься излишней оптимизацией ты потратишь время на ускорение, которое не заметно пользователю, но заметно твое время потраченное на излишнюю задумчивость, ты потратишь лишние ресурсы работодателя или свои. Вот в 1С нет ни замыканий ни Linq от этого больше времени тратится на циклы, структуры. Отсутствие интеллисенса при запросах к базам итд. Поверь производительность труда на C# на порядки выше чем на 1С |
|||
76
ДедМорроз
13.02.21
✎
19:20
|
Так все современные языки сделаны,чтобы не задумываясь,а потом обычный код на Си,который делает примерно то же самое кроет эту всю чудо-реализацию скоростью в десять,а то и сто раз быстрее,не расходуя память.
Фильтраторы и итераторы хороши там,где без них сложно,и время на написание кода сравнимо со временем его исполнения(другими словами,если код исполняется несколько раз,если не вообще единожды) |
|||
77
Serginio1
13.02.21
✎
19:42
|
(76) Угу. С развитием .Net Core разница между С++ сокращается. Вводятся новые типы данных, оптимизируются компиляторы итд.
Ни о каких десятках раз даже на Simd операциях нет. Старая песня. Нужно писать код быстро, без ошибок используя эффективные алгоритмы. А не выискивать экономию пару тактов. Тот же Linq как раз это все и дает. Ты же не пишешь пргграммы на Си, хоть он по твоим словам и дает огромный прирост в скорости, а используешь тормозной интерпретатор 1С |
|||
78
Провинциальный 1сник
13.02.21
✎
20:59
|
(77) Код в 1с принято писать "для читателя". Чтобы потом ты через пару лет или твой преемник мог легко в нём разобраться. А все эти "синтаксические сахары" провоцируют писать нечитаемый код. Как всякие гики в Си писали в своё время с кучей ++ в одном выражении, превращая выражение в головоломку..
|
|||
79
Serginio1
13.02.21
✎
21:14
|
(78) Как раз разбираться с Linq намного проще чем в лапша коде принятого в 1С.
И поверь разбираться в коде C# намного проще чем в 1С. И поверь мною прочитаны десятки мегабайтов кода. И у меня есть огромнейший опыт Не надо сравнивать C# и С++. C# на порядки высокоуровнее |
|||
80
Asmody
13.02.21
✎
21:24
|
(75) видал я такое "не занимайтесь оптимизацией", когда внутрь filter() закинули функцию, которая из БД читает. за запросы в цикле в 1С принято бить линейкой по рукам. а тут нормально "не задумываясь" же
|
|||
81
Serginio1
13.02.21
✎
21:45
|
(80) Еще раз в Linq to EF не закинешь функцию только Expression
Почитай на досуге http://catalog.mista.ru/1c/articles/402433/ Если в некоторых языках нет Linq то это проблемы языка. А вот в 1С запросы в цикле достаточно частое явление. И ты правда считаешь что я такие вещи делаю не задумываясь? Почему ты так решил? Или покажи мой код. Его очень много http://catalog.mista.ru/profile/82159/objects/ Про "незадумываясь" я писал про внутреннюю реализацию Linq запроса, замыкания. А выстрелить себе в ногу можно и без замыканий итд. Для этого есть профайлеры и неоптимальный код быстро находится. |
|||
82
Serginio1
13.02.21
✎
21:48
|
81 Я так скажу, все разговоры про тормознутость Linq, не экономии памяти замыканий проходили этак лет 10 назад.
В итоге подавляющее большинство используют Linq замыкания и не парят себе мозги от излишней оптимизации. Их скорость устраивает |
|||
83
Asmody
13.02.21
✎
21:52
|
(81) мир не ограничивается Linq и Net. но из твоих речей уже понятно, что на Net можно писать и без мозгов, "не задумываясь"
|
|||
84
Ненавижу 1С
гуру
13.02.21
✎
22:22
|
(73) один же цикл и память под один экземпляр данных одна будет
а вот объектов-оберток для ленивых вычислений будет несколько |
|||
85
Доктор Манхэттен
13.02.21
✎
22:46
|
(57) Более простого объяснения чем уже написано я не нашел для тебя, сорян.
|
|||
86
Доктор Манхэттен
13.02.21
✎
22:47
|
(58) Покажи как ты собираешь тело функции строкой? Это делается во время написания программы, или на этапе выполнения?
|
|||
87
Serginio1
13.02.21
✎
22:48
|
(83) Да не ожидал от тебя. И главное почему ты так считаешь так и не объяснил.
Ты же не задумываешь как компилятор оптитмизирует твой код. Откуда такие выводы? Программистский мир вбирает в себя все лучшее, что есть в различных языках. Тот же JS подтянулся к TS. TS берет лучшее из других языков. Развивается котлин. И развиваются в сторону функциональщины и оптимизации структур приближая скорость работы к C++ компиляторам. Просто в твоем мире нет Linq. Но я то в этом не виноват. А ты меня обзываешь безмозглым. Обидно, да! |
|||
88
Asmody
13.02.21
✎
23:24
|
(87) что ты прицепился к своему linq? нельзя программировать "не задумываясь". применяя какие-то конструкции и паттерны, даже если они "общеупотребительны", надо отдавать себе отчет что ты делаешь и зачем.
|
|||
89
ДедМорроз
13.02.21
✎
23:35
|
1с процедурный язык.
Понятно,что разбираемость кода на 1с всегда хуже,чем у объектно ориентированных языков. Опять же,на Си++,как и на Си можно сделать все,особенно всякие фокусы с указателями и структурами,которые в .Net,в принципе,невозможны из-за метода исполнения. Опять же,если говорить о Си++,то уже у него есть проблемы со скоростью,не говоря уже об всем остальном. А читаемость,скажем у ассемблера или Си,на самом деле,хуже чем у многих других языков из-за макросов препроцессора,когда написано одно,а после трансляции получается совершенно другое. Ну и когда вместо цикла используется рекурсия. В Си++ и без плюсов можно сделать такое,что сразу не разберёшь,особенно учитывая переопределение операторов и проведение классов при сложном наследовании. |
|||
90
ДедМорроз
13.02.21
✎
23:43
|
Что же касается запросов выбора,то системе нужно указать источник,критерии отбора и она уже сама должна анализировать что и как будет преобразовано в код.
На выходе же мы должны получить множество. Проблема в том,что понятия множества в программировании,в принципе,нет,есть массивы,есть последовательности,а чтобы сделать множество,для него нужно представление. На языке множеств и соответствий описать многие алгоритмы вообще можно одной строкой. |
|||
91
Asmody
14.02.21
✎
00:25
|
"Что же касается запросов выбора,то системе нужно указать источник,критерии отбора и она уже сама должна анализировать что и как будет преобразовано в код." - это сейчас было описание любого декларативного языка. От пролога до SQL.
|
|||
92
Ненавижу 1С
гуру
14.02.21
✎
00:47
|
(90) "чтобы сделать множество,для него нужно представление"
какая-то непонятная мне мысль |
|||
93
Asmody
14.02.21
✎
00:53
|
(92) он говорит о том, что множество в математическом смысле на компьютере не реализовать. компьютер оперирует линейными упорядоченными структурами - списками. а множество мы можем только смоделировать.
|
|||
94
Asmody
14.02.21
✎
00:55
|
хотя тот же haskell с его классами типов позволяет абстрагироваться на уровне множеств
|
|||
95
Ненавижу 1С
гуру
14.02.21
✎
01:12
|
(93) ну это всего лишь расположение в памяти, как и пишешь в (94) от этого можно абстрагироваться
я что-то последнее время считаю, что народ пишет много воды на пустом месте, наверное просто старею |
|||
96
Доктор Манхэттен
14.02.21
✎
02:46
|
(89) Процедурные языки хуже объектно-ориентированных, а объектно-ориентированные хуже функциональных.
|
|||
97
ДенисЧ
14.02.21
✎
05:27
|
(96) Чем хуже?
|
|||
98
ДенисЧ
14.02.21
✎
05:27
|
(89) "на Си++,как и на Си можно сделать всякие фокусы с указателями"
Если в языке нужны фокусы, то это явно плохой, слабовыразительный язык. |
|||
99
Доктор Манхэттен
14.02.21
✎
05:50
|
(97) Чем объектно-ориентированные
|
|||
100
ДенисЧ
14.02.21
✎
05:56
|
(99) Не убедил.
|
|||
101
Кирпич
14.02.21
✎
10:05
|
(96) Неправильно. Правильно так: Процедурные языки хуже объектно-ориентированных, а объектно-ориентированные хуже процедурных.
|
|||
102
Serginio1
14.02.21
✎
10:56
|
(88) Ты не читатель. Еще раз про "не задумываясь" было про то как реализован в итоге Linq и замыкания на нижнем уровне.
Да я знаю как это работает и какие подводные камни, но мне не интересно во что конкретный Linq запрос преобразуется или async await. Я мыслю конструкциями высшего порядка. Мало того эта реализация меняется от версии к версии компилятора. Ты же это слово переиначил вообще ко всему. Не надо так нервничать. (89) Поверь можно.Есть IntPtr есть fixsed https://metanit.com/sharp/tutorial/8.4.php есть ref return https://habr.com/ru/company/microsoft/blog/423061/ |
|||
103
Serginio1
14.02.21
✎
11:48
|
(73 ) >> Если ты пишешь цепочку типа list.filter(fn1).map(fn2).foldr(fn3), сколько в результате будет циклов по побору данных?
В .Net есть такая замечательная штука как yield return Суть её в том, что создается итератор (класс) с MoveNext и Current Тут подрасптсали https://habr.com/ru/post/136828/ https://ru.stackoverflow.com/questions/505018/В-чем-польза-yield И соответственно вычисление идет не с лева на право, а с права то есть foldr вызовет MoveNext у map, map у filter а filter у list В итоге будет всего один цикл. Поэтому я и не задумываюсь как будет реализовано в итог. И какие может выполнить оптимизации компилятор для оптимизации |
|||
104
Вафель
14.02.21
✎
12:01
|
мап однозначно генерит новый массив
|
|||
105
Serginio1
14.02.21
✎
12:08
|
(104) Да, как и OrderBy итд (не массив а итератор).
https://metanit.com/sharp/tutorial/15.8.php Но я про то, что вычисления идут с права на лево |
|||
106
Asmody
14.02.21
✎
12:22
|
(103) ну вот, а говорил "не задумываясь"
|
|||
107
Ненавижу 1С
гуру
14.02.21
✎
12:35
|
(104) от языка/среды зависит
Select в .net ленивое. То есть создаёт только обёртку над IEnumerable. var x = new List() {1,2,3}; Console.Write(x.Count()); // 4 var y=x.Select(t=>t*t); Console.Write(y.Count()); // 3 x.Add(4); Console.Write(y.Count()); // 4 |
|||
108
Ненавижу 1С
гуру
14.02.21
✎
12:35
|
(107) 3,3 и 4 выдаст
|
|||
109
Serginio1
14.02.21
✎
13:54
|
(106) Я не задумываюсь как в итоге будет обработана цепочка Linq запроса, как будут преобразованы замыкания. Я знаю принципы и этого достаточно
И как я раньше писал есть много оптимизаций. Проще сосредоточиться на высокоуровневом коде. (107) Я думал map это (Dictionary) group by |
|||
110
Кирпич
14.02.21
✎
14:24
|
Посравнивал linq с не linq
|
|||
111
Кирпич
14.02.21
✎
14:25
|
for
00:00:01.7805429 100070000 foreach 00:00:01.7357639 100070000 linq 00:00:07.5117874 100070000 |
|||
112
Кирпич
14.02.21
✎
14:26
|
правда я в C# не шарю. мож чо неправильно написал
|
|||
113
Serginio1
14.02.21
✎
14:54
|
(112) Я уже писал про оптимизаторы Linq в (75) там как раз про твой случай
и про Parallel LINQ |
|||
114
Кирпич
14.02.21
✎
15:06
|
C# конечно загадочный. Мало того, что в него понапихали кучу всего, так еще надо знать как это всё внутри работает. Иначе будут тормоза и утечки памяти.
Вот как можно догадаться что numbers.Count(x => x < 100) будет работать медленнее чем numbers.Where(x => x < 100).Count() ??? |
|||
115
Serginio1
14.02.21
✎
15:09
|
(114) Пользуйся циклами. Никто же тебя не заставляет использовать Linq. Если тебе так важна скорость. Про утечки памяти поподробнее.
(75) смотрел? |
|||
116
Serginio1
14.02.21
✎
15:10
|
||||
117
Кирпич
14.02.21
✎
15:14
|
Получается, я должен все прибамбасы C# исследовать в доль и поперек, чтобы оно у меня быстро работало. А можно ничего не исследовать и писать тупыми дедовскими циклами сразу эффективно.
|
|||
118
Кирпич
14.02.21
✎
15:15
|
(115) Про утечки в .NET читал где то.
|
|||
119
Кирпич
14.02.21
✎
15:16
|
||||
120
Кирпич
14.02.21
✎
15:17
|
||||
121
Serginio1
14.02.21
✎
15:26
|
(117) Суть линка не в скорости выполнения, а в декларативном написнии запроса.
Быстрее пишешьшь код, проще читать. Ты же пишешь на 1С, а не каком то супер быстром языке. Опять же есть оптимизаторы которые ты игнорируешь. (118) Самая простая утечка памяти это статические переменные, и соответсвенно различные подписки итд. И если ты передаешь COM , в нативное приложение тоже понятно. Но это не утечка памяти. Утечки это когда нет статических переменных и внешних нативных приложений держащих ссылки |
|||
122
Кирпич
14.02.21
✎
15:32
|
(121) "Суть линка не в скорости выполнения, а в декларативном написнии запроса."
Это я уже понял. Годится для тяп ляп и в кассу. |
|||
123
Кирпич
14.02.21
✎
15:36
|
Стратегия linq понятна:
Пишем на linq, а если будут орать, что медленно и требовать деньги назад, то переписываем на циклы. |
|||
124
Кирпич
14.02.21
✎
15:37
|
Переписываем, естественно, за деньги. :)
|
|||
125
Serginio1
14.02.21
✎
15:40
|
(122) Нет он годится для нормального написания кода.
В том числе и для Sql где в качестве коллекции это IQueriable и в качестве замыкания уже не лямбда выражения а деревья выражений. И задуман он был для SQL, а для списков это приятный довесочек. Так что любители эткономит на тактах добро пожаловать в адовый код циклов. А вот кто хочет писать и читать лаконичный, но легко читаемый код добро пожаловать в широкий мир C# где кроме Linq есть и async await (внутри тоже итераторы используются) (124) Тебе дан широкий спектр инструментов. Можешь вообще не писать. Проходили это все более 10 лет назад. И большинство приняло линк, отказавшись от циклов. |
|||
126
Serginio1
14.02.21
✎
15:44
|
(124) Не надо ничего переписывать просто подключаешь https://github.com/antiufo/roslyn-linq-rewrite
Но ты же упорно игнорируешь. Главное обосрать! |
|||
127
Кирпич
14.02.21
✎
15:44
|
(125) "И большинство приняло линк, отказавшись от циклов." да я тоже не против. Я на питоне тоже на linq строчу тыпляпы всякие. Но я от питона скорости не жду.
|
|||
128
Serginio1
14.02.21
✎
15:55
|
(127) Опять игнорируешь (126). Легким движением руки подключаешь https://github.com/antiufo/roslyn-linq-rewrite и твой тяп ляп превращается в высокоуровневые циклы!
|
|||
129
Кирпич
14.02.21
✎
16:00
|
(128) С костылями еще возиться. Лень
|
|||
130
Кирпич
14.02.21
✎
16:01
|
Я лучше подожду еще лет 5 пока микрософт нормальный C# сделает
|
|||
131
ДедМорроз
14.02.21
✎
16:04
|
Тогда вообще проще исходно писать на метаязыке,в общем виде,а потом это в общем виде транслируем в то,что нужно.
Итераторы,это тот же самый цикл,и ничем не отличается,кроме того,что с помощью итератора можно вложенные циклы в один загнать,ну и скорости это не убавит,т.к.условия будут те же самые,просто проверяться будут все сразу,а не ступенчато,как во вложенных циклах. Другое дело,что вложенные циклы для читателя кода понятнее на несколько порядков. |
|||
132
ДедМорроз
14.02.21
✎
16:13
|
И по поводу запроса в цикле.
В sql есть синтаксис prepare execute,который как раз предназначен для выполнения запроса в цикле. Не забываем,что поиск по индексным полям - это все равно цикл,и если мы его выполняем один раз для всех полей,то сначала будет цикл при выборке,потом будет цикл обхода результата,где ещё чего-то нужно будет искать,т.к. мы значения куда-то пишем. А если мы гоняем запрос в цикле,то,как ни странно,цикл-то будет один. Ну,если поиск не по индексным полям,то тут не проблема запроса в цикле,а проблема неоптимального запроса,которую цикл просто проявляет сильнее. |
|||
133
Serginio1
14.02.21
✎
16:18
|
(130) Не C#, а компилятор. https://github.com/dotnet/runtimelab/tree/feature/NativeAOT И не пять лет его в .Net 6 обещают во всяком случае для блазора
(131) Еще раз Linq это прежде всего SQL а уже во вторую очередь итераторы. Если ты владеешь SQL то тебе писать и читать удобнее именно на SQL Вот пример Linq к объектам 1С http://catalog.mista.ru/1c/articles/402433/ var qr = from Номенклатура in бд.Спр_Номенклатура from единицы in бд.Спр_Единицы.Where(единица => единица.ВладелецId == Номенклатура.ID && единица.ШтрихКод.CompareTo("4") > 0).DefaultIfEmpty() select new { Номенклатура.Наименование, Номенклатура.ПолнНаименование, единицы.ШтрихКод, ОКЕИ = единицы.ОКЕИ.Наименование }; В C# есть два вида Linq. Оди из них Sql подобный https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq |
|||
134
Кирпич
14.02.21
✎
16:28
|
(133) "В C# есть два вида Linq. Оди из них Sql подобный "
C# язык хороший, но одинеснику он не нужен. На нём только какую нибудь серверную хренотень писать. Сайты там всякие... Корпоративного масштаба. Одинесники таким не занимаются. |
|||
135
Ненавижу 1С
гуру
14.02.21
✎
16:33
|
(134) а мне нравится идея. Тот же 1с только более развитый
Кстати как там веб страницы клиентские рисовать? Вот это всё же джаваскрипте |
|||
136
Ненавижу 1С
гуру
14.02.21
✎
16:37
|
Скд тот же декларативный наверняка можно переложить на linq
|
|||
137
Serginio1
14.02.21
✎
17:15
|
(135) Blazor Webassembly сейчас развивается в том числе и компоненты
https://docs.microsoft.com/ru-ru/aspnet/core/blazor/components/?view=aspnetcore-5.0 И все это на C#. Можно и кроссплатформенные формы рисовать и единые классы использовать как на сервере так и на клиенте |
|||
138
Доктор Манхэттен
15.02.21
✎
01:23
|
(103) Чем больше отдельных не взаимосвязанных шагов, тем проще поддерживать код, отлаживать, и тестировать. Если все вычисление будет в одном цикле, то это боль в заднице для поддержки.
Тот же ваш пример list.filter(fn1).map(fn2).foldr(fn3) можно спокойно отладить и оттестировать по шагам сперва получаем list, потом .filter(fn1), потом .map(fn2) потом .foldr(fn3) И на каждом шаге контролируем результат. |
|||
139
Serginio1
15.02.21
✎
14:19
|
(138) Был вопрос
(73 ) >> Если ты пишешь цепочку типа list.filter(fn1).map(fn2).foldr(fn3), сколько в результате будет циклов по побору данных? В .Net в итоге будет один цикл (если map это Select). Отлаживай лямбды в чем проблема? |
|||
140
Почему 1С
15.02.21
✎
15:37
|
(103) Похожее есть в Котлин (по моему они это с шарпа и позаимствовали). Так называемые sequence аля ленивые вычисления, вычисления идут как обычно слева направо, но вот анализ данных идет не горизонтально, а вертикально, то есть первый элемент коллекции прогоняется через все функции (filter, map, fold ....) и в итоге на всю цепочку получается один цикл.
|
|||
141
Кирпич
15.02.21
✎
15:55
|
От количества циклов тут мало что зависит. Это доли миллисекунды. Тормоза тут не в циклах, а в медленных вызовах через интерфейс и замыкания всякие. Чем больше итераций, тем больше вызовов и тормозов соответственно.
|
|||
142
Кирпич
15.02.21
✎
16:06
|
Собственно это и является причиной того, что компы становятся мощнее, а программы тормознее. ООП с виртуальными методами и всякие Linq с замыканиями упорно стараются свести старания Intel к нулю.
|
|||
143
Serginio1
15.02.21
✎
16:12
|
(138) В .Net можно собирать несколько запросов в 1
напрммер var query=list.Where(a=>a>0); query=query.Where(a=>a<5).Select(a=>a+8); В данном случае query это цепочка вызовов. Только когда вызывется MoveNext (foreach, ToList? Count итд) начинается вызов с конца цепочки MoveNext (140) Ничего не знаю про котлин, но легко проверить последовательность вызова функций или лямбд (142) Очень актуально на форуме 1С. |
|||
144
Кирпич
15.02.21
✎
16:14
|
(143) " Очень актуально на форуме 1С."
нуачо. меня вот бесит, когда 1с по 5 минут открывается |
|||
145
Serginio1
15.02.21
✎
16:17
|
(142) На самом деле сейчас с развитием компиляторв многое инлайнится даже виртуальные меоды если точно известно что через new создается.
Все течет все меняется и скорость выполнения от версии к версии языка компилятора. Ловить пару миллисекунд в ущерб скорости написания кода и удобства чтения кода большинство не хочет. (144) Но она написана на С++! |
|||
146
Кирпич
15.02.21
✎
16:24
|
(145) "Но она написана на С++!"
А впечатление такое, что на питоне. И память жрет как не в себя. |
|||
147
ДенисЧ
15.02.21
✎
16:29
|
(146) Память и процессор нынче не ресурс, пора привыкнуть. Для того, чтобы 2+2 посчитать - нужен минимум i9
|
|||
148
Доктор Манхэттен
15.02.21
✎
17:43
|
(139) Лямбды в любом случае нужно отлаживать. А как отладить промежуточные результаты циклов? Никак. Поэтому нужно разбивать на отдельные шаги, а не лепить все в один цикл.
|
|||
149
Serginio1
15.02.21
✎
18:05
|
(148) Ты SQL запросы также отлаживаешь?
Еще раз Linq для коллекций это дополнительный бонус. Основное это SQL запросы. Но если ты привык мыслить циклами, то декларативное программирование не для тебя. |
|||
150
Ненавижу 1С
гуру
15.02.21
✎
18:06
|
Просто в тему https://m.habr.com/ru/company/typeable/blog/542440/
|
|||
151
Доктор Манхэттен
15.02.21
✎
18:08
|
(149) Мы не про SQL запросы говорим. Если не видишь разницы, то функциональное программирование не для тебя.
|
|||
152
Ненавижу 1С
гуру
15.02.21
✎
18:09
|
(151) почему то мне кажется ты тролль
|
|||
153
Вафель
15.02.21
✎
18:10
|
вот именно что отладка скл запросов это боль
|
|||
154
Доктор Манхэттен
15.02.21
✎
18:10
|
(152) Когда кажется, крестятся.
|
|||
155
Serginio1
15.02.21
✎
18:18
|
(151) Самому то не смешно? Мы говорим про Linq. Он имеет SQL подобный синтаксис смотри (133)
вот два одинаковых запроса первый SQL подобный Var numQuery1 = from num in numbers where num % 2 == 0 orderby num select num; Второй обычный //Method syntax: var numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n); Если в качестве источника будет выступать не IEnumerable а таблица БД IQueryable то будет запрос к таблице Вот пример http://catalog.mista.ru/1c/articles/402433/ (153) Linq помогает склеивать запросы. И это удобнее чес склеивать текстовые запросы. Отладив поодиночке можно их собирать. |
|||
156
Доктор Манхэттен
15.02.21
✎
20:26
|
(155) А, это хрень для запросов. Тогда извиняюсь, ошибся. Я думал мы говорим про функциональное программирование.
|
|||
157
Serginio1
15.02.21
✎
20:56
|
(156) >> Но если ты привык мыслить циклами, то декларативное программирование не для тебя.
https://ru.wikipedia.org/wiki/Language_Integrated_Query LINQ к объектам Представляет собой не что иное, как функциональное программирование, замаскированное под синтаксис SQL[8]. |
|||
158
Serginio1
15.02.21
✎
21:11
|
157+ https://rsdn.org/article/dotnet/LinqAsStapToFp.xml#EZFAC
Многим может показаться странным то, что ФП в LINQ замаскировано под SQL. Однако это не просто маскировка. Идеи ФП нацелены на то, чтобы сделать программирование более декларативным. Программируя в стиле ФП, мы как бы описываем то, что хотим получить, а не то, как мы это хотим получить. Именно это призван делать и SQL. SQL – это язык запросов, с помощью которого мы лишь описываем, что хотим выбрать из БД (или как хотим ее изменить), но при этом мы не задаем конкретный (императивный) алгоритм обработки данных. |
|||
159
Вафель
15.02.21
✎
21:57
|
а вот интересно. если в линк какую-нибудь функцию подсунуть что скл не поддерживает, то как оно в запрс транслируется?
|
|||
160
Serginio1
15.02.21
✎
22:04
|
(159) Там не функция а деревья выражений, хоть синтаксис и один. https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/expression-trees/
При обработке дерева выражений провайдером выдаст ошибку |
|||
161
Serginio1
16.02.21
✎
00:01
|
(141)>> От количества циклов тут мало что зависит. Это доли миллисекунды. Тормоза тут не в циклах, а в медленных вызовах через интерфейс и замыкания всякие.
А для промежуточных результатов нужно выделять дополнительные списки и значит дополнительные расходы на память и Add в список. Ну и конечно сравнивать инлайный if (d < 100) count++; не совсем правильно. При сравнении строк уже разница будет минимальна. Не говоря уже о group by, sort by, Select |
|||
162
Доктор Манхэттен
16.02.21
✎
00:19
|
(155) По сути ничего не поменялось. Ну раскрыли скобки, убрали точки. Синтаксис немного поменялся, но в остальном все так же.
|
|||
163
Кирпич
16.02.21
✎
08:12
|
(161) "Ну и конечно сравнивать инлайный if (d < 100) count++; не совсем правильно."
Схрена ли неправильно. Очень даже правильно. Если большие объемы данных и нужна скорость, то linq использовать нельзя (если это не для SQL). Это же ясно как день. А то, что c Linq всё красиво и понятно - это тоже вопрос. Когда по одной строчке в лямбду, то да. А если по 100 строк, то вся красота и понятность исчезает и остаются только тормоза. |
|||
164
Доктор Манхэттен
16.02.21
✎
08:20
|
(163) В лямбду и без Linq можно, см пример (155):
var numQuery2 = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); Это даже короче и понятнее чем link: Var numQuery1 = from num in numbers where num % 2 == 0 orderby num select num; |
|||
165
Кирпич
16.02.21
✎
08:22
|
(161) "А для промежуточных результатов нужно выделять дополнительные списки"
А нафига промежуточные результаты? Я так же могу всё сделать в одном цикле и выделить память только под конечный результат. Можно все сделать так же как в linq, только без лишних вызовов виртуальных методов. |
|||
166
Почему 1С
16.02.21
✎
09:02
|
(165) Нужно просто красиво и с легкой поддержкой кода, быстро тоже нужно но в последнюю очередь. Я хоть и не умею еще писать подобное, но вот в чужом коде гораздо быстрее могу разобраться если он написан в функциональном стиле(условно). От того и интерес к этим лямбда выражениям
|
|||
167
Кирпич
16.02.21
✎
09:23
|
(166) "быстро тоже нужно но в последнюю очередь."
Быстро нужно когда надо, а не в последнюю очередь. Если тебе JSON гонять двум пользователям, то пожалуйста. А если у тебя игровой движок или какая нибудь 3D модель урагана Катрина, то совсем другое дело. |
|||
168
Ненавижу 1С
гуру
16.02.21
✎
09:36
|
(167) Преждевременная оптимизация — корень всех зол. Дональд Кнут.
|
|||
169
Кирпич
16.02.21
✎
09:38
|
(168) Правильно. Пускай 1С открывается по 5 минут. Зато всё по Кнуту :)
|
|||
170
Кирпич
16.02.21
✎
09:41
|
(168) Да и Кнут это написал, когда оптимизацией считалось переписывание куска программы на ассемблере
|
|||
171
Почему 1С
16.02.21
✎
09:43
|
(167) А почему тогда для ураганов катарина, ИИ, дата майнига и других научных вычислений так популярен Питон, который совсем не про скорость выполнения.
(169) Я сейчас имею дело с конфой на 1С, которая по моим понятиям должно просто жестко висеть потому как очень много всего сделано не оптимально и не правильно сточки зрения практик и рекомендаций, но SQl каким то образом вытягивает это поделие до работоспособного состояния. |
|||
172
Кирпич
16.02.21
✎
09:44
|
(171) "других научных вычислений так популярен Питон"
потому что в питоне используются библиотеки написанные на Си |
|||
173
Почему 1С
16.02.21
✎
09:49
|
(172) Ну вот, острые умы найдут как оптимизировать высокоуровневый код которым будут пользоваться люди с умом попроще в LInq лямдах и питонах и всем будет хорошо
|
|||
174
Serginio1
16.02.21
✎
10:38
|
(164) Ты написал два вида Linq. Какой хочешь такой и используй.
Нередко приходится использовать 2 синтасиса. Опять же SelectMany проще и понятнее использовать в Sql синтаксисе var selectedUsers = from user in users from lang in user.Languages where user.Age < 28 where lang == "английский" select user; Для создания аналогичного запроса с помощью методов расширения применяется метод SelectMany: var selectedUsers = users.SelectMany(u => u.Languages, (u, l) => new { User = u, Lang = l }) .Where(u => u.Lang == "английский" && u.User.Age < 28) .Select(u=>u.User); Правда в Sql подобном синтаксисе есть let очень удобная вещь https://docs.microsoft.com/ru-ru/dotnet/csharp/linq/group-query-results https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/let-clause string[] strings = { "A penny saved is a penny earned.", "The early bird catches the worm.", "The pen is mightier than the sword." }; // Split the sentence into an array of words // and select those whose first letter is a vowel. var earlyBirdQuery = from sentence in strings let words = sentence.Split(' ') from word in words let w = word.ToLower() where w[0] == 'a' || w[0] == 'e' || w[0] == 'i' || w[0] == 'o' || w[0] == 'u' select word; |
|||
175
Serginio1
16.02.21
✎
10:44
|
(165) Нужна скорость используй Linq Rewriter или LinqOptimizer. Только вот таких людей не очень много.
Не нужна экономия пару тактов. Ну и конечно же ты пишешь на С++, ибо на 1С и питоне про инлайнинг не знают. А в 1С и о замыканиях и не знают, не то, что о Linq |
|||
176
Serginio1
16.02.21
✎
10:57
|
174+ tot into
https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/into from row in rows select row.Split(',') into columns let identifier = columns[0].Replace("Prefix_", string.Empty) group columns by identifier into g select new Log { Identifier = g.Key, DurationInSeconds = (from dur in g let duration = DateTime.Parse(dur[1]) select duration.Hour * 3600 + duration.Minute * 60 + duration.Second).Sum() } |
|||
177
Uberschall
16.02.21
✎
12:08
|
между делом спрошу, вдруг кто посоветует книгу для котлина по корутинам?
|
|||
178
Uberschall
16.02.21
✎
12:15
|
(175) по поводу оптимизации я выше писал, что есть разница между inline и не inline функциями (замыкания на не inline тратят время на создание оберток). по поводу циклов: есть возможность (не знаю как в C#) не создавать промежуточные выгрузки, а использовать отложенные операции через секвенции. При желании можно дальше пойти и использовать сплитераторы и многопоточную обработку stream'ов для java (но не все можно раздробить- это вопрос конурентности). Ну и не стоит забывать, что кроме оптимизации есть стоимость поддержки. Для декларативного стиля это большой плюс по сравнению с императивным- но это уже переход в DSL.
|
|||
179
Garykom
гуру
16.02.21
✎
12:25
|
(177) не тупи какие к черту корутины на котлине если основное применение котлина это трансляция в java совместимый байт код
короче книги по java и многопоточности в зубы и вперед |
|||
180
Uberschall
16.02.21
✎
12:27
|
(179) это понятно. но хочется тему раскрыть для себя, чтобы, если зайдет обсуждение, понимать что там происходит.
|
|||
181
Кирпич
16.02.21
✎
12:34
|
(177) Кто будет писать книги про корутины. На хабре статью прочитай и хватит. https://habr.com/ru/company/alfa/blog/336228/
|
|||
182
Uberschall
16.02.21
✎
12:37
|
(181) да, видел статью, но после java concurency (библиотека или книга) как-то не густо...
|
|||
183
Почему 1С
16.02.21
✎
13:04
|
(177) какое то своеобразное у тебя понимание применения котлина Kotlin > Java, это как сказать зачем тебе c++ когда он всего лишь переводит в машинный код.
|
|||
184
Почему 1С
16.02.21
✎
13:06
|
(182) Теория параллельных вычислений это одно, а конкретная реализация их в языке это более узкая тема которая действительно не стоит отдельной книги.
|
|||
185
Serginio1
16.02.21
✎
13:42
|
Мне в котлине понравилось легкое создание DSL. Например аналог lock в kotlin — можно реализовать просто функцией, а не отдельной языковой конструкцией:
lock(syncRoot) { doWork(); } https://kotlinlang.org/docs/reference/type-safe-builders.html |
|||
186
Garykom
гуру
16.02.21
✎
13:49
|
(185) дык Java же
|
|||
187
Почему 1С
16.02.21
✎
13:52
|
(186) хочу видеть как этот код ты скомпилишь на java
|
|||
188
Garykom
гуру
16.02.21
✎
13:56
|
(187) https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
как бы наоборот котлина в яву "компилится" |
|||
189
Почему 1С
16.02.21
✎
14:18
|
я про реализацию DSL не про конкретно lock, то есть synchronized это конструкция языка а lock это функция с лямбда параметром, а внутри скорее всего и сидит synchronized
То что Kotlin ограничен JVM не спорю, просто у него уровень абстракции выше и красивее все реализовывается |
|||
190
Uberschall
16.02.21
✎
15:04
|
(183) а что в этом странного? Kotlin создавался на основе Java, за основу были взяты её библиотеки, требовалась прямая поддержка.
(189) реализация DSL (да и вообще большей части Kotlin) исходит из соглашений, позволяющих составлять синтаксические конструкции. те же инфиксные вызовы типа 1 to "one", можно делать в более традиционном стиле типа 1.to("one") из java и наоборот. "а внутри скорее всего и сидит synchronized" - совсем не факт. synchronized построен на мониторе, а Lock- на парковке потока. |
|||
191
Uberschall
16.02.21
✎
15:06
|
(187) чтобы понять как перевести в более традиционный вид, здесь недостаточно информации. тут вообще lock может быть экземпляром объекта, для которого определен метод invoke (соглашение)...
|
|||
192
Почему 1С
16.02.21
✎
15:19
|
(191) ну тут фишка что последний параметр типа лямбда можно передавать не как параметр а описывать телом этой самой функции. Lock тут я понимаю как функцию
fun lock(par:Any, todo:()->Unit){ synchronized(par) { todo() } } |
|||
193
Serginio1
16.02.21
✎
15:20
|
(190) lock это Monitor в try finally
https://stackoverflow.com/questions/2837070/lock-statement-vs-monitor-enter-method System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); } |
|||
194
Почему 1С
16.02.21
✎
15:20
|
Реализация функции естественно может быть любой, что тоже даст уровень абстракции в будущем
|
|||
195
Serginio1
16.02.21
✎
15:21
|
Вот все что в try{...} и есть лямбда,
|
|||
196
Uberschall
16.02.21
✎
15:38
|
(192) возможно.
(193) в java synchronized может быть либо методом, либо локальным блоком. скорее всего имелось ввиду что-то такое или как в (192) fun lock(syncRoot: Lock, action: ()->Unit){ lock.lock() try{action()} finally{lock.unlock} } вызов: val syncRoot = Lock() lock(syncRoot){prinln("внутри блокировки")} в общем, особо никаких проблем с вызовом из java |
|||
197
Почему 1С
16.02.21
✎
15:41
|
(196) Java так умеет lock(syncRoot){prinln("внутри блокировки")}?
|
|||
198
Uberschall
16.02.21
✎
15:42
|
(197) lock(syncRoot, prinln("внутри блокировки")) - то же самое
|
|||
199
Почему 1С
16.02.21
✎
15:47
|
(198) что возвращает println? ))) но суть не в этом, а в том что в Котлин это реализовано красиво, хотя по функциональности может быть тем же самым
|
|||
200
Uberschall
16.02.21
✎
15:53
|
(199) соответствует сигнатуре параметра ()->Unit. println- стандартный метод, ничего не возвращает (в терминах Kotlin- это Unit).
|
|||
201
Почему 1С
16.02.21
✎
16:00
|
Ну тебе нужна функция как параметр а ты передал ничего (передал результат println)
|
|||
202
Uberschall
16.02.21
✎
16:06
|
(201) это не так работает. ()->Unit <=> ()->{что-то возвращающее Unit или ничего (Unit - аналог void)} <=> ()-> {println()} <=> {println()}
|
|||
203
Почему 1С
16.02.21
✎
16:13
|
Где в (198) определение лямбда выражения?
|
|||
204
Uberschall
16.02.21
✎
16:17
|
(203) точно, тупанул. для java придется лямбду развернуто написать:
lock(syncRoot, ()->System.out.println("внутри блокировки")) |
|||
205
Почему 1С
16.02.21
✎
16:21
|
Вот, а если речь про dsl то в java это будет выглядеть вырвиглазно а в котлин структурно и красиво, на примере того же html что приводили выше
|
|||
206
fisher
16.02.21
✎
16:21
|
(0) Я в функциональщине ни в зуб ногой, хотя щупал и замыкания и лямбды.
Но слышал, что для погружения в этот мир берут хорошую книжку по хаскелю. |
|||
207
Uberschall
16.02.21
✎
16:25
|
(205) но понимать-то все-равно надо что там происходит.
|
|||
208
Garykom
гуру
16.02.21
✎
16:33
|
(206) Для погружения достаточно знать что любую лямбду можно заменить на обычную Функцию или Процедуру (с передачей параметров по значению)
Но будет "больше кода" и не так "синтаксически сахарно красиво" |
|||
209
Garykom
гуру
16.02.21
✎
16:34
|
(208) тьфу *с передачей параметров по ссылке
|
|||
210
Serginio1
16.02.21
✎
17:17
|
(208) не всегда. Переменные метода по ссылке не передашь, так как время жизни лямбды может быть больше чем время жизни метода
|
|||
211
Ненавижу 1С
гуру
16.02.21
✎
17:23
|
(208) вообще нет
1. при замыкании мы конструируем функцию, но вовсе ее не вызываем, возможно вызовем вообще в другом методе, как бы с параметром такое не выйдет 2. нарушилась бы сигнатура функций |
|||
212
Почему 1С
16.02.21
✎
17:28
|
(206) Что за книжка, автор или название?
|
|||
213
Ненавижу 1С
гуру
16.02.21
✎
17:34
|
По крайней мере LINQ мог бы избавить от вот такого:
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%УсловиеОрганизация%", УсловиеОрганизация); |
|||
214
Garykom
гуру
16.02.21
✎
17:36
|
(210) (211) Дык вы читать то умеете?
ВСЕГДА лямбду можно заменить на вызов процедуры/функции, просто будет не так красиво. Придется например в временем жизни и сохранением параметров что то допом в коде изобретать да. |
|||
215
Garykom
гуру
16.02.21
✎
17:38
|
(214)+ Это как "можно ли программировать не используя GOTO"
Можно! Но иногда с "безусловным переходом по метке" проще. Аналогично с лямбдой. |
|||
216
Garykom
гуру
16.02.21
✎
17:40
|
Имхо для простоты поддержки λ=goto
лучше не использовать или новичкам особенно тяжко будет |
|||
217
Ненавижу 1С
гуру
16.02.21
✎
17:41
|
(214) и получается скрытый объект с методом в виде самой лямбды и полями в виде переменных замыкания
что собственно и проделывает, например, C# (215) конечно можно, не используя ЯВНО GOTO, но осознавая что за всеми ветвлениями и циклами лежит JMP |
|||
218
Garykom
гуру
16.02.21
✎
17:42
|
Кстати LINQ лишняя ненужная хрень, лучше нативный SQL разрабу подучить с особенностями реализаций конкретных серверов SQL
Или перейти на концепцию NoSQL с MapReduce понимая что это и зачем. А не извращаться с трансляторами. |
|||
219
Ненавижу 1С
гуру
16.02.21
✎
17:43
|
(218) каждому своё
|
|||
220
Serginio1
16.02.21
✎
17:50
|
(218) Смысл линка, что легким движением руки мы можем сменить СУБД.
При этом возможности Linq to EF значительно больше чем 1С, а Linq2DB еще больше. https://github.com/linq2db/linq2db https://linq2db.github.io/articles/sql/Window-Functions-(Analytic-Functions).html >> Кстати LINQ лишняя ненужная хрень, лучше нативный SQL разрабу подучить с особенностями реализаций конкретных серверов SQL Ты это расскажи миллионам C# программистам которые эту хрень используют. Пока еще реляционные базы никто не вытеснит. |
|||
221
Garykom
гуру
16.02.21
✎
17:59
|
(220) Смысл SQL в том что легким движением мы можем сменить СУБД
|
|||
222
Garykom
гуру
16.02.21
✎
18:01
|
(221)+ Достаточно перед каждым вызовом добавить обработку текста sql чтобы особенности конкретной субд учесть
ну там limit или top и прочее типа передачи параметров короче это пишется за полдня для каждой новой субд |
|||
223
Garykom
гуру
16.02.21
✎
18:04
|
(222)+ имхается уже есть готовые написанные модули для трансляции текстов sql запросов между разными популярными субд
|
|||
224
Доктор Манхэттен
16.02.21
✎
18:22
|
(174) Какой же это link? Первый вариант - это обычная запись, без всякого линка. То что Линк имеет такой же синтаксис - это его проблемы. А я всегда так писал.
|
|||
225
Serginio1
16.02.21
✎
19:31
|
(221) Угу ты 1С перепиши. Есть еще куча инструкций пригодных только для каждой СУБД.
Посмотри на количество инструкций в 1С. Здесь ты не прав. (224) Это обыкновенный Linq. То, что есть два типа линк это не проблемы а достоинства. Посмотри на SelectMany плюс let и into Кстати на чем писал? И можно склеивать запросы? var query= list.Where(a=>а.поле>5); var query2=query.Where(a=>а.поле2>5); |
|||
226
Serginio1
16.02.21
✎
19:53
|
(224) в (174) Первый это Sql подобный, а вот второй через методы расширения SelectMany и первый значительно лаконичнее
var selectedUsers = from user in users from lang in user.Languages where user.Age < 28 where lang == "английский" select user; И на чем ты писал? |
|||
227
Garykom
гуру
16.02.21
✎
20:04
|
(225) >Угу ты 1С перепиши. Есть еще куча инструкций пригодных только для каждой СУБД.
>Посмотри на количество инструкций в 1С. Здесь ты не прав. 1С переписывать нет смысла а вот использовать лишнюю прокладку нафига? Один хрен оно в sql транслируется и каким местом эта "куча инструкций"? На другом ЯП в отличие от нативного SQL хрен используешь и переписывай все заново. |
|||
228
Доктор Манхэттен
16.02.21
✎
20:12
|
(225) Зачем тогда было писать, мол: "В линке лучше", если там то же самое что и в обычном программировании?
|
|||
229
Доктор Манхэттен
16.02.21
✎
20:15
|
(225) На JS можно так склеивать, но склейка происходит по функции "И", а не "ИЛИ".
|
|||
230
Serginio1
16.02.21
✎
20:19
|
(227) >> а вот использовать лишнюю прокладку нафига?
Для интеллисенса, склеивания запросов. Например один и тотже подзапрос встречается в несколько раз. В 1С используют временные таблицы или склейку текста, что неудобно. Кстати на stackoverflow используют Dapper https://github.com/StackExchange/Dapper для предстаавления результата запроса в типизированную коллекцию. На Linq2DB достаточно богатый язык. А Какие то фичи конкретного SQL языка всегда можно вынести в хранимые процедуры. При замене СУБД только переписать их. Не прав потому, что Linq используют и очень этим довольны. И те у кто программирует на языках в которых нет Linq согласны, что Линк крутая фича. (225) Еще раз ты можешь сделать SQL запрос? У тебя ленивые вычисления? Это два одинаковых Linq запроса users может быть не только коллекцией, но и таблицей бд var selectedUsers = from user in users from lang in user.Languages where user.Age < 28 where lang == "английский" select user; Для создания аналогичного запроса с помощью методов расширения применяется метод SelectMany: var selectedUsers = users.SelectMany(u => u.Languages, (u, l) => new { User = u, Lang = l }) .Where(u => u.Lang == "английский" && u.User.Age < 28) .Select(u=>u.User); И тот и другой запрос может работать как с коллекцией так и с БД. SQl синтаксис более лаконичный и читаемый |
|||
231
Serginio1
16.02.21
✎
20:25
|
(230) Что бы понятнее, что для SQL применяются деревья выражений а не лямбда функции пример расширения between
https://stackoverflow.com/questions/1447635/linq-between-operator |
|||
232
Serginio1
16.02.21
✎
20:31
|
Кстати про линк на JS
https://habr.com/ru/post/261903/ |
|||
233
Доктор Манхэттен
16.02.21
✎
20:32
|
(230) Из этого я понял что в Linq есть конструкция, которую можно применять как для работы с обычными структурами данных, так и с базами данных, в то время как без Linq приходилось использовать аналогичный синтаксис, но имеющий различия для структур и для БД. Верно?
|
|||
234
Serginio1
16.02.21
✎
20:46
|
(233) Так скажем до линка все пользовались Ado.Net. Строковые запросы. Ну еще делали типизированные датасеты.
С появлением в 2005 yield стало понятно, что можно с ними можно многое сделать. Так в 2008 появился Linq как для коллекций IEnumerable, так и для Iqueryable. Народ с настороженностью к ним отнесся. Новый функциональный подход долго принимали. Кто то принял, а кто то и нет. Но большинство приняли особенно для Sql В студии для отладки можно было пользоваться локально БД. Там не то что конструкция. Linq запрос склеивается. И выполняется пока явно не вызовут итератор (foreach,Count итд) Поэтому можно склеивать запросы, передавать их в функции. Для SQL это деревья выражений которые обрабатывает провайдер и строит SQL запрос Вот здесь наглядно видно во что преобразуется запрос к таблицам 1С http://catalog.mista.ru/1c/articles/402433/ Просто компилятор по разному обрабатывает Linq запрос для IEnumerable и IQueryable, хотя на вид они оинаковые Да для скорости и типизации когда мало запросов например на stackoverflow используют Dapper https://github.com/StackExchange/Dapper для предстаавления результата запроса в типизированную коллекцию. |
|||
235
Доктор Манхэттен
16.02.21
✎
22:45
|
(234) Я не использую Ado.Net, так как пишу под Веб на JS. Но там примерно все то же самое.
|
|||
236
fisher
17.02.21
✎
10:06
|
(212) Real World Haskell, что ли...
|
|||
237
fisher
17.02.21
✎
10:13
|
Но не поручусь, что именно про эту слышал. Не помню. Но эта выглядит достойным кандидатом ибо изобилует примерами промышленных реализаций. А что еще нужно программисту, как не примеры? :)
|
|||
238
fisher
17.02.21
✎
10:14
|
Онлайн доступна бесплатно: http://book.realworldhaskell.org/read/
|
|||
239
fisher
17.02.21
✎
10:16
|
Опа! Оно еще и со свободными комментариями на каждый сниппет и раздел! Очень прикольный формат, как-то не сталкивался с таким.
|
|||
240
Почему 1С
17.02.21
✎
11:39
|
(239) Спасибо большое! Начал читать, как раз речь про то то что я спрашивал.
Я подозревал что нужно читать что то про функциональное программирование и даже скачал пару книг но они не пошли, а твой вариант очень хорош. Прочитаю поделюсь результатом. |
|||
241
Доктор Манхэттен
17.02.21
✎
18:02
|
Так вот ради рекламы какого сайта была затеяна вся эта беседа!
|
|||
242
fisher
17.02.21
✎
18:23
|
(241) Но красивая же подводочка, согласись!
|
|||
243
Почему 1С
18.02.21
✎
10:46
|
Почитал книжку не много, начало очень интригующее мол от вас только навыки программирования, ну читаю все понятно , понятно, потом хоп и оказывается что все что было понятно, на само деле не понятно. Перечитываю второй раз, походу функциональное программирование не мое.
|
|||
244
Garykom
гуру
18.02.21
✎
10:59
|
(243) Попробуй сначала https://ru.wikipedia.org/wiki/Регулярные_выражения изучить
|
|||
245
Почему 1С
18.02.21
✎
11:36
|
(244) Регулярными выражениями владею, периодически пользуюсь, и из последнего например было "\s+[a-zA-Z0-9а-яА-Я_]+\.[a-zA-Z0-9а-яА-Я_]+\s+В\s*\([^\)]*ВТ_ОтборыПоПрограммам[^\)]*\)" - найти все условия в тексте запроса вида '*.* в (Выбрать ВТ.Программа Из ВТ_ОтборыПоПрограммам как ВТ)'. Конечно писать их на лету не могу, но с отладчиком еще не возникало задач которые бы не смог решить.
|
|||
246
Serginio1
18.02.21
✎
15:30
|
(243) Это хаскель. Посмотри F# https://docs.microsoft.com/ru-ru/dotnet/fsharp/
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |