OberonCore https://forum.oberoncore.ru/ |
|
Срезы как в голанге? https://forum.oberoncore.ru/viewtopic.php?f=22&t=6391 |
Страница 1 из 2 |
Автор: | budden [ Воскресенье, 28 Апрель, 2019 12:27 ] |
Заголовок сообщения: | Срезы как в голанге? |
В голанге можно использовать срезы (slices). Они представляют собой виртуальный массив, построенный на базе "настоящего" массива и содержат три величины: ссылку на оригинальный массив, индекс начального элемента и индекс конечного элемента. С точки зрения использования срез - это просто массив. Срезы - единственный способ иметь в голанге массив переменного размера. Настоящий массив всегда имеет фиксированный размер. В Си этот функционал можно реализовать через арифметику указателей, в лиспе есть displaced arrays и fill pointer. Вероятно, уши растут из Фортрана... В отличие от Си, в голанге невозможно попасть за границы массива с помощью среза - имеет место динамический контроль. По впечатлениям, что-то подобное нужно. Мне нравится, что это решение простое. В лиспе наворочено гораздо больше, а содержания не больше. Т.е. в плане наличия минимального набора примитивов решение в голанге выглядит интересным. Но срезы содержат ловушки. Например, операция добавления элемента в срез может копировать базовый массив, а может создавать разделяемую копию, и расширять срез за счёт охвата ранее не охваченных частей базового массива, если в нём ещё есть место. Так легко возникает непостижимый граф связей между массивами и срезами, и неявное разделение данных между разными срезами, тоже непостижимое. Вместе с отсутствием иммутабельности это выглядит опасным. Но важно, что при этом сохраняется шанс на эффективность. Есть ли что-то подобное в A2? |
Автор: | Ярослав Романченко [ Воскресенье, 28 Апрель, 2019 13:03 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Код: PROCEDURE Slice*(context: Commands.Context); Felix Friedrich, Jürg Gutknecht. Array-structured object types for mathematical programmingVAR a, b: ARRAY [*] OF LONGINT; i: LONGINT; BEGIN a := [1, 2, 3, 4, 5, 6]; b := a[2..4]; FOR i := 0 TO LEN(b, 0) - 1 DO context.out.Int(b[i], 0); context.out.Ln; END; END Slice; Felix Friedrich, Jürg Gutknecht, Oleksii Morozov, Patrick Hunziker. A Mathematical Programming Language Extension for Multilinear Algebra |
Автор: | Kemet [ Воскресенье, 28 Апрель, 2019 15:26 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Слайсов в АО нет. Но есть тип RANGE, который можно передавать вместе с массивом. К значениям типа RANGE можно применять операторы FIRST, LAST, STEP; STEP - это шаг с которым будут обрабатываться элементы массива. RANGE можно использовать везде, где допустимо использовать индекс. Код: MODULE Test; IMPORT Commands; VAR range: RANGE; VAR a, b: ARRAY [ * ] OF LONGINT; PROCEDURE Print( CONST array: ARRAY [ * ] OF LONGINT ); VAR i: SIZE; VAR context: Commands.Context; BEGIN context := Commands.GetContext( ); FOR i := 0 TO LEN( array, 0 ) - 1 DO context.out.Int( array[ i ],0 ); context.out.Char( " " ); END; context.out.Ln; END Print; PROCEDURE Do*; BEGIN a := [ 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 ]; range := 0 .. LEN( a, 0 ) - 1 BY 1; b := a[ range ]; Print( b ); range := 0 .. LEN( a, 0 ) - 1 BY 2; b := a[ range ]; Print( b ); b := a[ 0.. BY 2 ]; Print( b ); b := a[ .. BY 2 ]; Print( b ); b := a[ .. BY 2 ] * 10; Print( b ); b := a[ .. ] * 10; Print( b ); END Do; END Test.Do~ System.Free Test~ Вывод: 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 10 10 10 20 10 20 10 20 10 20 10 20 10 20 10 20 10 20 10 20 10 20 |
Автор: | Ярослав Романченко [ Вторник, 30 Апрель, 2019 10:55 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Что-то у меня пока аналогичные алгоритмы на старичке Object Pascal быстрее работают чем на Go. Скорость где? ![]() |
Автор: | Kemet [ Вторник, 30 Апрель, 2019 12:35 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Ярослав Романченко писал(а): Что-то у меня пока аналогичные алгоритмы на старичке Object Pascal быстрее работают чем на Go. Скорость где? А какие там будут аналогичные алгоритмы?
![]() |
Автор: | Info21 [ Вторник, 30 Апрель, 2019 23:58 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Не нужны ни слайсы, ни рейнджы. |
Автор: | Comdiv [ Среда, 01 Май, 2019 01:14 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Без срезов требуется использовать лишние параметры, так как данные могут находится не с 0-го смещения. Это уменьшает ошибкоуствойчивость. Но такие срезы как в Go и AO не нужны. |
Автор: | Info21 [ Среда, 01 Май, 2019 08:06 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Comdiv писал(а): Без срезов требуется использовать лишние параметры Это вопрос проектирования.Срезы и проч. стимулируют рукосуйство, сложность и, по законам природы, уязвимость. |
Автор: | Ярослав Романченко [ Среда, 01 Май, 2019 10:17 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Comdiv писал(а): Без срезов требуется использовать лишние параметры, так как данные могут находится не с 0-го смещения. Это уменьшает ошибкоуствойчивость. Но такие срезы как в Go и AO не нужны. Если-бы эти срезы ещё нормально работали... Выглядит как поделие студента первого курса. Я имею в виду голанг
|
Автор: | Ярослав Романченко [ Среда, 01 Май, 2019 11:36 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Вот, как заставить работать такой код (Playground)? Слайс IpRanges внутри структуры не увеличивается, хоть ты тресни... с каким capacity его ни создавай. Добавляется один элемент и всё. Может всю структуру пересоздавать каждый раз? ![]() Код: package main
import ( "fmt" ) type ( IP2LocRec struct { IpLo, IpHi string CCode, CName string } IpDbRange struct { IpLo, IpHi string } IpDbRanges []IpDbRange IpDbCountry struct { IpRanges IpDbRanges CName string } IpDbCountries map[string]IpDbCountry ) func process_line(row IP2LocRec) { var ( cInfo IpDbCountry ok bool ) if cInfo, ok = countries[row.CCode]; !ok { fmt.Printf("Adding country\n") countries[row.CCode] = IpDbCountry{CName: row.CName, IpRanges: make([]IpDbRange, 1, 1)} cInfo, ok = countries[row.CCode] cInfo.IpRanges[len(cInfo.IpRanges)-1] = IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi} } else { var newRanges IpDbRanges lenRanges := len(cInfo.IpRanges) capRanges := cap(cInfo.IpRanges) fmt.Printf("cInfo.IpRanges before changes: len: %v, cap: %v -> ", len(cInfo.IpRanges), cap(cInfo.IpRanges)) if lenRanges == capRanges { newRanges = make([]IpDbRange, lenRanges+1, lenRanges*2) copy(newRanges, cInfo.IpRanges) cInfo.IpRanges = newRanges fmt.Printf("after increasing len & cap: len: %v, cap: %v\n", len(cInfo.IpRanges), cap(cInfo.IpRanges)) } else { newRanges = make([]IpDbRange, lenRanges+1, capRanges) copy(newRanges, cInfo.IpRanges) cInfo.IpRanges = newRanges fmt.Printf("after increasing len: len: %v, cap: %v\n", len(cInfo.IpRanges), cap(cInfo.IpRanges)) } //_ = append(cInfo.IpRanges, IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi}) } cInfo.IpRanges[len(cInfo.IpRanges)-1] = IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi} } var countries IpDbCountries func main() { countries = make(IpDbCountries) process_line(IP2LocRec{IpLo: "0", IpHi: "10", CCode: "US", CName: "Unated States"}) //process_line(IP2LocRec{IpLo: "11", IpHi: "20", CCode: "SU", CName: "Soviet Union"}) //process_line(IP2LocRec{IpLo: "41", IpHi: "50", CCode: "IL", CName: "Israel"}) process_line(IP2LocRec{IpLo: "21", IpHi: "30", CCode: "US", CName: "Unated States"}) //process_line(IP2LocRec{IpLo: "31", IpHi: "40", CCode: "SU", CName: "Soviet Union"}) //process_line(IP2LocRec{IpLo: "51", IpHi: "60", CCode: "IL", CName: "Israel"}) process_line(IP2LocRec{IpLo: "61", IpHi: "70", CCode: "US", CName: "Unated States"}) //process_line(IP2LocRec{IpLo: "71", IpHi: "80", CCode: "SU", CName: "Soviet Union"}) //process_line(IP2LocRec{IpLo: "81", IpHi: "90", CCode: "IL", CName: "Israel"}) process_line(IP2LocRec{IpLo: "91", IpHi: "100", CCode: "US", CName: "Unated States"}) //process_line(IP2LocRec{IpLo: "101", IpHi: "110", CCode: "SU", CName: "Soviet Union"}) //process_line(IP2LocRec{IpLo: "111", IpHi: "120", CCode: "IL", CName: "Israel"}) for cCode, cInfo := range countries { fmt.Printf("Country code: %v, name: %v\n", cCode, cInfo.CName) for iRange := 0; iRange < len(cInfo.IpRanges); iRange++ { ipRange := cInfo.IpRanges[iRange] fmt.Printf("\tRange lo: %v, range hi: %v", ipRange.IpLo, ipRange.IpHi) } fmt.Printf("\n") } } |
Автор: | Kemet [ Среда, 01 Май, 2019 13:45 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Info21 писал(а): Не нужны ни слайсы, ни рейнджы. Когда собственное мнение, с большой вероятностью ошибочное, высказывается с такой категоричностью, вероятно, стоить дописывать "по моему скромному мнению". Причем, КАПСОМ, чтобы сразу была видна вся ничтожность такого мнения. |
Автор: | Ярослав Романченко [ Среда, 01 Май, 2019 14:20 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Вобщем, таки да, только полным пересозданием структуры IpDbCountry удаётся победить эти слайсы. Ни один из рецептов на стековерфлоу и т.д. не сработал |
Автор: | Comdiv [ Среда, 01 Май, 2019 14:26 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Посмотрел программу. Вы просто изменяли срез в локальной структуре, которая совсем не указатель. Срез тоже не указатель, но содержит указатель на массив, но не на длину. Нужно было вернуть локальное значение обратно в словарь. Например, добавлением в конец else ветки кода: Код: countries[row.CCode] = cInfo В любом языке, где существуют структуры вне динамической памяти было бы так же, и срезы тут ни при чём. |
Автор: | Ярослав Романченко [ Среда, 01 Май, 2019 15:17 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Comdiv писал(а): Нужно было вернуть локальное значение обратно в словарь. Именно так и сделал.
|
Автор: | Info21 [ Среда, 01 Май, 2019 16:21 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Kemet писал(а): Info21 писал(а): Не нужны ни слайсы, ни рейнджы. Когда собственное мнение, с большой вероятностью ошибочное, высказывается с такой категоричностью, вероятно, стоить дописывать "по моему скромному мнению". Причем, КАПСОМ, чтобы сразу была видна вся ничтожность такого мнения. 2) Это концепты следующего уровня. Реализовывать их надо соответственно, то есть если и в языке, то в domain-specific. 3) Мне довелось участвовать в тестировании чего-то такого в ETH до публикации -- на приличном куске реального научного софта. Нашлось четыре строчки, где что-то удалось сэкономить. 4) Кемет, вы пытаетесь поднять свою доминантность за мой счёт. Почему бы это. Впрочем, keep trying. |
Автор: | Comdiv [ Среда, 01 Май, 2019 17:20 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Info21 писал(а): 3) Мне довелось участвовать в тестировании чего-то такого в ETH до публикации -- на приличном куске реального научного софта. Нашлось четыре строчки, где что-то удалось сэкономить. Мне доводилось работать с обратной ситуацией, где имелось бы значительное повышение ошибкоустойчивости во многих строках. Но человек я простой, таким великолепным проектированием, чтобы это не имело существенного значения, заниматься не умею. Есть готовые материалы, в которых можно ознакомится с примерами?
|
Автор: | Kemet [ Среда, 01 Май, 2019 17:38 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Info21 писал(а): 4) Кемет, вы пытаетесь поднять свою доминантность за мой счёт. Почему бы это. Впрочем, keep trying. Всего лишь пытаюсь донести до разума простую мысль - нужно критичнее относится к своим измышлениям. Цитата: 3) Мне довелось участвовать в тестировании чего-то такого в ETH до публикации -- на приличном куске реального научного софта. Нашлось четыре строчки, где что-то удалось сэкономить. Вот об этом я и говорю - критичней к собственным представлениям нужно быть. Ибо у других-то результат совсем отличный от Вашего. Потому что это повышение ошибкоустойчивости и производительности труда ( и вычислений ) и единообразная алгебра и много чего ещё
|
Автор: | Info21 [ Четверг, 02 Май, 2019 00:39 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Кемет, довожу до Вашего разума: гоняйте мух на своей голове (с). 2) |
Автор: | ilovb [ Суббота, 04 Май, 2019 23:06 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
Код: _ = append(cInfo.IpRanges, IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi}) Не понял что именно не работает. Этот код? Если да, то не работает по той причине, что это кривой код. append нужно присваивать тому же слайсу. т.е. так: Код: cInfo.IpRanges = append(cInfo.IpRanges, IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi})
|
Автор: | Ярослав Романченко [ Воскресенье, 05 Май, 2019 11:11 ] |
Заголовок сообщения: | Re: Срезы как в голанге? |
ilovb писал(а): Если да, то не работает по той причине, что это кривой код. Криво. Тем не менее в некоторых советах на stackoverflow призывают именно ничего не присваивать слайсу, а делать всякий раз его пересоздание через make. Тиражируют повсюду заветную чудо-функцию, которая всё это делает append нужно присваивать тому же слайсу. т.е. так: Код: cInfo.IpRanges = append(cInfo.IpRanges, IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi}) ![]() ![]() Нужно переприсваивать всю структуру в словаре, как заметил Comdiv, так как у нас тут всё статическое. Окончательный вариант вообще вот, такой. И без каких-либо пересозданий. Код: if cInfo, ok := countries[row.CCode]; !ok { Если в конце каждого такого вызова вывести len и cap слайса видно, что при каждой необходимости его увеличения capacity удваивается, всё как в аптеке.
countries[row.CCode] = IpDbCountry{CName: row.CName, IpRanges: []IpDbRange{IpDbRange{IpLo: row.IpLo, IpHi: row.IpHi}}} } else { countries[row.CCode] = IpDbCountry{CName: row.CName, IpRanges: append( cInfo.IpRanges, IpDbRange{IpLo: row.IpLo, IpHi: row.IpHi})} } |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |