LINUX.ORG.RU

Ищу аналог union/enum/adt для Python/Go

 , ,


1

2

Интересуют не либы, а идиоматическое решение задачи вида:

Rust:

enum Data {
    Number(u32),
    String(String),
}

let mut items = Vec::new();
items.push(Data::Number(5));
items.push(Data::String("text".to_string()));

for item in items {
    match item {
        Data::Number(n) => println!("Number {}", n),
        Data::String(ref s) => println!("String {}", s),
    }
}

C++:

std::vector<std::variant<int, std::string>> items;
items.push_back(5);
items.push_back("text");

for (const auto &item : items) {
    if (const auto n = std::get_if<int>(&item)) {
        std::cout << "Number " << *n << std::endl;
    } else if (const auto &s = std::get_if<std::string>(&item)) {
        std::cout << "String " << *s << std::endl;
    }
}

Как это повторить на python и go?

То есть нужно заполнить вектор/список/массив объектами разных типов (желательно с гарантиями) и затем пробежаться по ним, забирая значение каждого типа.

★★★★★

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

чтобы я мог получить тоступ к значениям.

В Do делаешь switch по типу val и получаешь: https://play.golang.org/p/f_o5glSPl4W

Правда, ХЗ насколько такой код идиоматичен.

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

У гоферов других ассоциаций нет в принципе?

Ты опять забыл принять таблетки и тебе всюду кажутся неведомые «гоферы»?

И чем это не реальный код?

Тем, что рассматривается в отрыве от задачи. Возможно, что идиоматичное решение на Python или Go задачи в целом — не будет затрагивать подобные концепции вообще.

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

Делай switch прямо в цикле.

Тогда проверки интерфейса не будет же.

А какая связь между циклом и проверкой интерфейса?

Типы в примере проверяются на этапе создания (или добавления) в slice.

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

Тем, что рассматривается в отрыве от задачи. Возможно, что идиоматичное решение на Python или Go задачи в целом — не будет затрагивать подобные концепции вообще.

Скорее всего.

Например, сразу приходит в голову вопрос, что за источник у таких разнородных данных.

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

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

Например, сразу приходит в голову вопрос, что за источник у таких разнородных данных.

Например, AST. Да любое дерево, на самом деле.

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

В go нет ADT, есть duck typing на интерфейсах. Из примеров кода видно как можно натянуть сову на глобус.

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

Ну а если ты видел эту ссылку - откуда разговоры про натягивание совы?

В go нет ADT

В Go нет языковых средств, специально предназначенных для создания AlgDT. Поэтому, когда AlgDT нужны (потому что такова решаемая задача), их делают из подручных материалов.

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

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

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

Например, сразу приходит в голову вопрос, что за источник у таких разнородных данных.

Ну допустим мне нужно распарсить SVG путь. Он поддерживает 10 типов сегментов. Как вы предлагаете его хранить? Или список разнородных типов, или два списка: в одном команды, в другом данные. Третьего варианта я не знаю.

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

Просто когда AlgDT - это цель, а не инструмент, это выглядит для меня странно.

Это инструмент, а не цель.

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

Очевидно, что это маленькая подзадача, которую нужно решить для решения большей задачи. Одну из больших задач RazrFalcon сформулировал выше. Наверное, есть задача и побольше.

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

Думаю, ущербно будет и в использовании.

На то он и Go, лол =)

Но если серьезно, то есть реальная задача и я пытаюсь её решить на разных языках. Как это сделать на C/C++/Rust мне понятно. А вот питон/Go я не знаю, поэтому и пытаюсь понять. Но гоферы как обычно воют про ненужно.

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

Как будто в Python-е или Go у вас большой выбор где создавать объекты...

В C++ можно использовать кастомные аллокаторы/выделение памяти из пула.

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

Ну у Go есть GC, пусть и примитивный. Проблемы быть не должно. А питон медленный де факто. Я же про идиоматичный код, а не про быстрый. При этом ничего идиоматичного в создании 100500-т мелких объектов в C++ - нет.

Кастомные аллокаторы для такой простой задачи - перебор. Да и variant будет проще/короче, чем пердолиться с указателями/unique_ptr.

Мне нужно простое, лаконичное решение, а не overengineering.

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

Как будто в Python-е или Go у вас большой выбор где создавать объекты...

В C++ можно использовать кастомные аллокаторы/выделение памяти из пула.

Если ты чего-то не знаешь, это не значит, что этого нет - https://golang.org/pkg/sync/#Pool

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

Any item stored in the Pool may be removed automatically at any time without notification.

Шта? Ну и зачем мне пул, если у меня GC? Хде логика?

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

Логика в том, что если у тебя буферы в пуле навыделялись и долго не используются, gc их приберет. На практике это полезно, если профиль нагрузки меняется со временем. Если нагрузка примерно равномерная, то gc не подберет эти буферы примерно никогда.

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

Но у меня один массив. И он и является «пулом».

PS: API у Go конечно наркоманский. Get, который на самом деле Take и:

Callers should not assume any relation between values passed to Put and the values returned by Get.
If Get would otherwise return nil and p.New is non-nil, Get returns the result of calling p.New.

ЯННП. Я положил один объект, а оно вернуло другой/пустой? Это типа костыль из-за отсутствия Option?

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

Ну допустим мне нужно распарсить SVG

Ну вот, если есть реальная задача — уже можно что-то обсуждать.

Идиоматичное решение на Go будет ближе к C. Соответственно нужно идти от концепций С и поднимать уровень абстракции там, где это возможно.

Я же про идиоматичный код

Нет, ты тут скорее про натягивание совы на глобус и последующим негодованием на тему того, почему сова внезапно стала круглой.

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

Optimize Garbage Collection in Go

Бедные гоферы. Я-то думал GC должен решать все проблемы, связанные с аллокациями. Ну там фрагментация, поколения объектов и тд. А тут такая подляна.

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

Ну вот, если есть реальная задача — уже можно что-то обсуждать.

Типичный лор.

Идиоматичное решение на Go будет ближе к C.

В Си это будет union, которого в Go нет.

Нет, ты тут скорее про натягивание совы на глобус

Если вам не понятно слово «аналог», то я тут ничем помочь не могу.

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

https://www.cockroachlabs.com/blog/how-to-optimize-garbage-collection-in-go/

Ну так память же все равно аллоцируется динамически. Pool только предотвращает деаллокацию тех объектов, которые Pool создал. Поэтому можно взять из Pool-а объект, который был аллоцирован гораздо раньше. Тем не менее, аллоцирован-то он будет в хипе, а не на стеке или в каком-то другом блоке памяти.

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

Объясняю на пальцах: есть SVG path, который содержит 10 типов сегментов. Эти сегменты нужно распарсить и сложить в список. Где тут сова, а где глобус?

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

Ну вот, если есть реальная задача — уже можно что-то обсуждать.

Типичный лор.

Сведение разговора к предметности — его лучшая сторона.

В Си это будет union, которого в Go нет.

В Си это тип+union, в Go в первом приближении — тип+interface.

Если вам не понятно слово «аналог», то я тут ничем помочь не могу

Если тебе непонятно, что аналог — это не решение 1 в 1, то тебе не только я — тут тебе вообще никто не поможет.

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

в Go в первом приближении — тип+interface.

Т.е. ты пришел к решению, которое предложили несколько страниц назад, и которое ты назвал «натягивание совы на гобус».

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

Т.е. ты пришел к решению, которое предложили несколько страниц назад, и которое ты назвал «натягивание совы на гобус».

Ни к какому решению я не «приходил». И другие решения я тоже никак не называл. С чего ты это вообще решил — одному Патрегу известно.

«натягивание совы на глобус» — это о подходе, суть которого не в решении задачи, а в показательной истерии на тему того, что сова получилась круглой.

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

И другие решения я тоже никак не называл.

Совсем никак: Ищу аналог union/enum/adt для Python/Go

То ты «tailgunner ★★★★★ (Score: X MaxScore: X) (01.02.2019 16:51:27) Я понимаю буквально (X.X.X.X)», то тебя наоборот в какие-то неведомые дали уносит.

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

Мде. Если что, это твоя цитата. Которая относилась к тредуб в котором было много разного кода, в том числе - «тип+interface». И всё это ты назвал так, как назвал.

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