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);
VAR
   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. Array-structured object types for mathematical programming
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. Скорость где? :D

Автор:  Kemet [ Вторник, 30 Апрель, 2019 12:35 ]
Заголовок сообщения:  Re: Срезы как в голанге?

Ярослав Романченко писал(а):
Что-то у меня пока аналогичные алгоритмы на старичке Object Pascal быстрее работают чем на Go. Скорость где? :D
А какие там будут аналогичные алгоритмы?

Автор:  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 его ни создавай. Добавляется один элемент и всё. Может всю структуру пересоздавать каждый раз? :roll:
Код:
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 писал(а):
Не нужны ни слайсы, ни рейнджы.

Когда собственное мнение, с большой вероятностью ошибочное, высказывается с такой категоричностью, вероятно, стоить дописывать "по моему скромному мнению". Причем, КАПСОМ, чтобы сразу была видна вся ничтожность такого мнения.
1) Всё, что я сообщаю без явных ссылок на законы и проч., и что не является очевидным (для аудитории) цитированием оных, -- это всё моё мнение.

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 писал(а):
Если да, то не работает по той причине, что это кривой код.
append нужно присваивать тому же слайсу.
т.е. так:
Код:
cInfo.IpRanges = append(cInfo.IpRanges, IpDbRange{IpLo:row.IpLo, IpHi:row.IpHi})
Криво. Тем не менее в некоторых советах на stackoverflow призывают именно ничего не присваивать слайсу, а делать всякий раз его пересоздание через make. Тиражируют повсюду заветную чудо-функцию, которая всё это делает :D Но прикол в том, что оно не работает и так как вы предлагаете тоже! :lol:
Нужно переприсваивать всю структуру в словаре, как заметил Comdiv, так как у нас тут всё статическое.
Окончательный вариант вообще вот, такой. И без каких-либо пересозданий.
Код:
   if cInfo, ok := countries[row.CCode]; !ok {
      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})}
   }
Если в конце каждого такого вызова вывести len и cap слайса видно, что при каждой необходимости его увеличения capacity удваивается, всё как в аптеке.

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/