Re[15]: Nim lang
От: alex_public  
Дата: 12.12.18 15:52
Оценка:
Здравствуйте, WolfHound, Вы писали:

_>>Кстати, могу рассказать некий забавный момент. Я был знаком с парочкой C++ программистов, которые утверждали что их напрягает использование unique_ptr своей излишней многословностью (в каком-то смысле тем самым мусорным кодом) — типа с голыми указателями код выглядит более лаконично и читаемо. Так вот я послал их изучить как выглядит работа с памятью в Rust... Они ТАК впечатлились увиденным, что после этого начали считать unique_ptr идеалом удобства при работе с памятью.

WH>Лично я предпочту повоевать с системой типов но иметь железные гарантии того что ничего плохого не случится.

Ну это дело вкуса. Кстати, а ты хоть где-нибудь скриптовые языки используешь? )

_>>P.S. Тут в соседней темке подкинули забавную ссылку (http://smallcultfollowing.com/babysteps/blog/2018/11/10/after-nll-moving-from-borrowed-data-and-the-sentinel-pattern/) почти по теме. Хотя там уже не про "мусорный код", а про архитектурные проблемы, но и то и то происходит из одной первопричины — излишнее переусложнее базовой концепции.

WH>Тут скорее недоусложнение.
WH>Они пытаются на этапе компиляции определить момент удаления каждого объекта. Делают они это при помощи построения дерева владения.

Если бы только это, то никаких проблем бы не было — такое уже прямо сейчас в C++ работает и не привносит никаких проблем. А в Rust'е всё гораздо сложнее.

WH>Проблема в том, что в реальности нужно отслеживать время жизни групп объектов.

WH>Например, результат работы парсера нитры является кучей связанных объектов.
WH>Причем в общем случае невозможно определить дерево владения.
WH>При этом для нормальной работы с результатом нужна вся куча. А после того как результат стал не нужен все объекты нужно одновременно удалить.

Давай разберёмся, ты хочешь чтобы система гарантировала отсутствие связей между группами или готов доверить это программисту?

Если второе, то это элементарно реализуется например в C++ с помощью кастомного аллокатора на пуле (после использования просто убиваешь пул и всё). Однако если ты тут ошибёшься (объект из пула будет связан с кем-то снаружи), то после удаления пула у тебя могут возникнуть проблемы.

Если же ты хочешь систему, которая сама будет отслеживать все связи и гарантированно разделять (на этапе компиляции) объекты на независимые группы для удаления, то думаю от такого бы никто не отказался. Но у меня есть большие сомнения в реализуемости подобного.

WH>Ещё одна проблема, которая у них появилась это простота реализации деструктора в каждом объекте. Null тоже появился по тому что было легко сделать. А теперь всем очевидно, что это зло.

WH>Нужно на уровне системы типов разделять объекты с деструкторами и все остальные.
WH>Практика показывает, что это вполне возможно. В .НЕТ хоть и нет поддержки этого на уровне системы типов. Но на уровне соглашений такое разделение есть. И оно мне ни разу не мешало.

Это ещё зачем? Архитектурно в этом нет никакого смысла — будут недостатки от обеих существующих схем (с RAII или без).

WH>Их желание сделать код, в котором гарантированно не будет паники похвально, но боюсь, что тут понадобится что-то типа https://github.com/Microsoft/dafny

WH>Более простые решения работать не будут.
WH>Кроме того для не паникующих функций придётся сделать запрет на выделение памяти и определить максимальный размер стека который нужно будет проверять при вызове не паникующего кода из паникующего. Ибо нехватка памяти и переполнение стека это паника.
WH>Короче для простого кода ограничения слишком сильные. Но для низкоуровневых библиотечных выкрутасов вполне адекватны.

Это да.

А вообще говоря не вижу ничего плохого в паниках/исключениях в случае проблем с памятью и т.п. — это вполне себе правильное решение, т.к. в такой ситуации программе практически гарантированно положено "скончаться". ) Это как раз тот самый случай, когда подход исключений уместен, в отличие от многих других мест, в которые их частенько суют.
Re[14]: Nim lang
От: alex_public  
Дата: 12.12.18 16:30
Оценка: +1
Здравствуйте, WolfHound, Вы писали:

_>>Хотя если у тебя есть время, то советовал бы глянуть с начала, чтобы сравнить с аналогичной реализацией в D (особенно про GPU наверное интересно будет).

WH>По сравнению с этим http://halide-lang.org/ ренжи детский сад ясельная группа.

Эм, и как ты вообще можешь сравнивать некую абстрактную концепцию работы с коллекциями (следующий уровень абстракции над понятием итератор) с отдельным специализированным языком, заточенным на решение SIMD задач? Между ними если и будет когда-то какая-то связь, то исключительно "дружеская" (скажем можно будет написать на Halide какой-то алгоритм, работающий с данными в виде диапазонов) и уж точно не "конкуренция".
Re[15]: Nim lang
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 12.12.18 16:56
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Проблема в том, что в реальности нужно отслеживать время жизни групп объектов.


Это же в Расте есть — через lifetime annotations.

WH>Их желание сделать код, в котором гарантированно не будет паники похвально, но боюсь, что тут понадобится что-то типа https://github.com/Microsoft/dafny


В статье такого желания я не заметил. Было желание получить корректный код при наличии возможных паник.
Re[15]: Nim lang
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.12.18 18:03
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>А в совсем клинических случаях нужен ГЦ. Чтобы он не мешал нужно разделять программу на легковесные процессы, что позволит собирать мусор в каждом процессе отдельно.

WH>Причем по умолчанию ГЦ можно выключить. И по желанию программиста либо включить в автоматически режиме. Либо запускать вручную в те моменты, когда известно, что большая часть мусора была зачищена детерминированным удалением.
Вот этот момент я не понял. В чём смысл приседать с детерминированным удалением мусора до вызова GC, если время работы GC зависит только от объёма живых объектов? Вроде бы, наоборот — GC надо запускать тогда, когда мы знаем, что живых осталось мало.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Nim lang
От: WolfHound  
Дата: 12.12.18 19:16
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот этот момент я не понял. В чём смысл приседать с детерминированным удалением мусора до вызова GC, если время работы GC зависит только от объёма живых объектов? Вроде бы, наоборот — GC надо запускать тогда, когда мы знаем, что живых осталось мало.

Детерминированное удаление всё равно быстрее и имеет намного меньшую латентность.

Например, у тебя есть сервер, который обрабатывает некие запросы. Большинство запросов зачищаются детерминированным удалением. Но некоторые запросы меняют состояние сервера и создают мусор, который не удалить детерминировано. Вот после них нужно запускать ГЦ.

Ну и не нужно забывать другие плюшки управлением временем жизни на уровне системы типов. Например, безопасную передачу графа изменяемых объектов в другой процесс.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Nim lang
От: WolfHound  
Дата: 12.12.18 19:16
Оценка:
Здравствуйте, D. Mon, Вы писали:

WH>>Проблема в том, что в реальности нужно отслеживать время жизни групп объектов.

DM>Это же в Расте есть — через lifetime annotations.
Нету. Если бы было, то этой статьи бы не было.
Просто по тому, что если бы отслеживалась жизнь группы объектов, то вот этот код
    self.chain = Chain::with(self.chain);

прямо в таком виде бы и заработал.

DM>В статье такого желания я не заметил. Было желание получить корректный код при наличии возможных паник.

The most obvious change is that we could plausibly extend the borrow checker to permit moves out of an &mut, so long as the value is guaranteed to be replaced before the function returns or panics. The “or panics” bit is the tricky part, of course.

... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Nim lang
От: WolfHound  
Дата: 12.12.18 19:16
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Ну это дело вкуса. Кстати, а ты хоть где-нибудь скриптовые языки используешь? )

Только если другого выхода нет.

_>Если бы только это, то никаких проблем бы не было — такое уже прямо сейчас в C++ работает и не привносит никаких проблем. А в Rust'е всё гораздо сложнее.

Вся сложность в гарантии отсутствия висящих ссылок.

_>Если же ты хочешь систему, которая сама будет отслеживать все связи и гарантированно разделять (на этапе компиляции) объекты на независимые группы для удаления, то думаю от такого бы никто не отказался. Но у меня есть большие сомнения в реализуемости подобного.

А у меня нет.
Re: Мысли о эффективном автоматическом управлении памятью
Автор: WolfHound
Дата: 29.10.14

Re[2]: Мысли о эффективном автоматическом управлении памятью
Автор: WolfHound
Дата: 29.10.14

Re[2]: Мысли о эффективном автоматическом управлении памятью
Автор: WolfHound
Дата: 30.10.14

Re[2]: Мысли о эффективном автоматическом управлении памятью
Автор: WolfHound
Дата: 30.10.14

При этом подход раста и данная система не противоречат друг другу. И их можно объедение, получив более мощную и гибкую систему, чем каждая из них по отдельности.

_>Это ещё зачем? Архитектурно в этом нет никакого смысла — будут недостатки от обеих существующих схем (с RAII или без).

За тем, что просто удалять память намного проще чем удалять память, вызывая при этом, какой то код.
И недостатков я не вижу. Попробуй придумать сценарий, в котором объект с дуструктором должен быть вне стека.

_>А вообще говоря не вижу ничего плохого в паниках/исключениях в случае проблем с памятью и т.п. — это вполне себе правильное решение, т.к. в такой ситуации программе практически гарантированно положено "скончаться". ) Это как раз тот самый случай, когда подход исключений уместен, в отличие от многих других мест, в которые их частенько суют.

Обработку ошибок нужно делать, как описано в этой статье.
http://joeduffyblog.com/2016/02/07/the-error-model/
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Nim lang
От: WolfHound  
Дата: 12.12.18 19:16
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Эм, и как ты вообще можешь сравнивать некую абстрактную концепцию работы с коллекциями (следующий уровень абстракции над понятием итератор) с отдельным специализированным языком, заточенным на решение SIMD задач? Между ними если и будет когда-то какая-то связь, то исключительно "дружеская" (скажем можно будет написать на Halide какой-то алгоритм, работающий с данными в виде диапазонов) и уж точно не "конкуренция".

Если мы говорим про засунуть код в GPU, то они решают одну и ту же исходную задачу. Только Halide намного мощнее.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Nim lang
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.12.18 20:25
Оценка: -1
Здравствуйте, anton_t, Вы писали:

M>>А что это такое? В расте, как я понял, это тупой кейс по типу union'а (в плюсах было бы отдельное поле typeTag и по нему бы был case).


_>Как на плюсах написать выделенное жирным?

_>
_>struct Point {
_>    x: i32,
_>    y: i32,
_>}

_>fn main() {
_>    let p = Point { x: 0, y: 7 };
_>    let Point { x, y } = p;
_>    assert_eq!(0, x);
_>    assert_eq!(7, y);
_>}
_>



Такого в плюсах нет. Но меня как-то никогда отсутствие данной фичи не напрягало. И что-то такое вроде то ли таки запилили, то ли вот вот запилят
Маньяк Робокряк колесит по городу
Re[17]: Nim lang
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 12.12.18 22:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>>>Проблема в том, что в реальности нужно отслеживать время жизни групп объектов.

DM>>Это же в Расте есть — через lifetime annotations.
WH>Нету.

Есть. Ибо что такое lifetime annotations, как не оно?

WH>Если бы было, то этой статьи бы не было.

WH>Просто по тому, что если бы отслеживалась жизнь группы объектов, то вот этот код
WH>
WH>    self.chain = Chain::with(self.chain);
WH>

WH>прямо в таком виде бы и заработал.

Прямо в таком и не должен, а если правильно расставить аннотации, то может и заработает. Или не заработает, ты сперва обоснуй, почему именно он должен заработать.
Re[17]: Nim lang
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.12.18 04:45
Оценка:
Здравствуйте, WolfHound, Вы писали:
WH>Детерминированное удаление всё равно быстрее и имеет намного меньшую латентность.
Продолжаю непонимать. Речь об освобождении памяти, или о финализации?
Если первое — то детерминированное освобождение всегда медленнее.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Nim lang
От: anton_t Россия  
Дата: 13.12.18 10:49
Оценка:
Здравствуйте, alex_public, Вы писали:

_>

_>И к сопоставлению с образом это не имеет ни малейшего отношения. )

Destructuring assignment это основа pattern matching.

Вот документация pattern matching для Erlang: http://erlang.org/doc/reference_manual/patterns.html , тут мы видим, что pattern matching-ом прямо называется deconstructing assignment.

Вот для Rust: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-to-break-apart-values , тут deconstructing assignment описывается как часть механизма pattern matching

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

_>Данный код записывается на C++ буквально так:

_>
_>struct Point {
_>        int32_t x;
_>        int32_t y;
_>};

_>int main()
_>{
_>    auto p=Point{0, 7};
_>    auto [x, y]=p;
_>    assert(0==x);
_>    assert(7==y);
_>}
_>


Ок, совсем недавно появилось. Но судя по proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0144r0.pdf это предназначено для простейших случаев, и что-то чуть более сложное, как в коде ниже, сделать уже невозможно. И, кроме того, полноценного pattern matching в c++, все-равно так и не появилось.

#[allow(dead_code)]
struct Point {
    x: i32,
    y: i32,
}

#[allow(dead_code)]
struct Color {
    r: u8,
    g: u8,
    b: u8
}

#[allow(dead_code)]
struct ColoredPoint {
    p: Point,
    c: Color,
}

fn main() {
  let p = Point { x: 0, y: 7 };
  let c = Color {r: 255, g: 1, b: 1};
  let cp = ColoredPoint {p: p, c: c};
  
  let ColoredPoint {p: _, c: Color{r: red, g: _, b: _}} = cp;
  
  println!("Red color: {}", red);
}
Re[17]: Nim lang
От: so5team https://stiffstream.com
Дата: 13.12.18 11:41
Оценка:
Здравствуйте, anton_t, Вы писали:

_>Так что утверждать что-то наподобие "И к сопоставлению с образом это не имеет ни малейшего отношения", по меньшей мере, безграмотно. И посмеяться можно в сторону этого утверждения.


Скажите, а вы специально такие убогие примеры приводите? Казалось бы, можно было бы взять пример Rust-овского enum-а (да хоть тот же готовый Result или Option) и инструкцию match.
Re[18]: Nim lang
От: anton_t Россия  
Дата: 13.12.18 13:15
Оценка:
Здравствуйте, so5team, Вы писали:

S>Здравствуйте, anton_t, Вы писали:


_>>Так что утверждать что-то наподобие "И к сопоставлению с образом это не имеет ни малейшего отношения", по меньшей мере, безграмотно. И посмеяться можно в сторону этого утверждения.


S>Скажите, а вы специально такие убогие примеры приводите? Казалось бы, можно было бы взять пример Rust-овского enum-а (да хоть тот же готовый Result или Option) и инструкцию match.


Скажите, а вы специально такими бессодержательными претензиями на форуме раскидываетесь? Казалось бы, можно было что-то конструктивное написать.
Re[18]: Nim lang
От: WolfHound  
Дата: 13.12.18 13:37
Оценка:
Здравствуйте, Sinclair, Вы писали:

WH>>Детерминированное удаление всё равно быстрее и имеет намного меньшую латентность.

S>Продолжаю непонимать. Речь об освобождении памяти, или о финализации?
Финализация мешает удалять объекты пачками.

S>Если первое — то детерминированное освобождение всегда медленнее.

В теории. А на практике грамотно сделанное детерминированное удаление всегда быстрее.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[18]: Nim lang
От: WolfHound  
Дата: 13.12.18 13:37
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Есть. Ибо что такое lifetime annotations, как не оно?

Оно вообще за время жизни объектов не отвечает.
Оно отвечает за удаление всех не владеющих ссылок на объект до того как будет удалена владеющая.
А за время жизни объекта отвечает владеющая ссылка, которая в расте существует в единственном экземпляре.
Это ограничивает структуру владения деревом.

DM>Прямо в таком и не должен, а если правильно расставить аннотации, то может и заработает.

Удачи.

DM>Или не заработает, ты сперва обоснуй, почему именно он должен заработать.

В расте не должен.
Для того чтобы он заработал нужно иметь как минимум две владеющие ссылки на объект.
Что в системе типов раста невозможно.
А вот в этой системе типов
Автор: WolfHound
Дата: 29.10.14
такое делается без проблем.

Причём обе системы типов можно подружить.
Для объектов с деструкторами деревянное владение. Как врасте.
Для всех остальных объектов кластерное. Как в моей системе типов.
И для не владеющих ссылок борроучекер.

Думаю получиться самая гибкая на данный момент система контроля жизни объектов на этапе компиляции.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: Nim lang
От: so5team https://stiffstream.com
Дата: 13.12.18 13:53
Оценка:
Здравствуйте, anton_t, Вы писали:

S>>можно было бы взять пример Rust-овского enum-а (да хоть тот же готовый Result или Option) и инструкцию match.


_>Скажите, а вы специально такими бессодержательными претензиями на форуме раскидываетесь? Казалось бы, можно было что-то конструктивное написать.


Конструктивное как раз и было написано. Предложили бы на C++ написать что-то вроде:
match some_optional {
  Some(v) => ... // Some action on v.
  _ => return
}
Re[19]: Nim lang
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.12.18 15:04
Оценка:
Здравствуйте, WolfHound, Вы писали:
WH>Финализация мешает удалять объекты пачками.
Это понятно. Непонятно, про какой случай идёт речь — про финализацию или её отсутствие.

WH>В теории. А на практике грамотно сделанное детерминированное удаление всегда быстрее.

Непонятно, как можно быть меньше, чем 0.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Nim lang
От: alex_public  
Дата: 13.12.18 20:59
Оценка:
Здравствуйте, anton_t, Вы писали:

_>>

_>>И к сопоставлению с образом это не имеет ни малейшего отношения. )
_>Destructuring assignment это основа pattern matching.

Т.е. по твоему все языки с возможностью деструктурирующего присваивания (а это и JS и Python и ещё множество других) автоматически обладают и сопоставлением с образцом? ))) У тебя похоже какое-то очень убогое представление о последнем... )

_>Вот документация pattern matching для Erlang: http://erlang.org/doc/reference_manual/patterns.html , тут мы видим, что pattern matching-ом прямо называется deconstructing assignment.


Не вижу подобных слов по указанной тобой ссылке. Если же ты хочешь сказать, что пример кода по ссылке отдалённо напоминает деструктурирующее присваивание, то ты похоже совсем не разобрался как он работает. Или быть может ты когда-то видел присваивание, которое выкинет ошибку по причине того, что переменная в левой части содержит не то значение? )))

_>Вот для Rust: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-to-break-apart-values , тут deconstructing assignment описывается как часть механизма pattern matching


Всё с точность до наоборот. Сопоставление с образцом (причём в самом тривиальном его виде) может быть использовано в Rust'е для осуществления механизма деструкции. И кстати именно так написано по твоей же ссылке — ты вообще сам читал то, на что ссылаешься? )))

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

_>Так что утверждать что-то наподобие "И к сопоставлению с образом это не имеет ни малейшего отношения", по меньшей мере, безграмотно. И посмеяться можно в сторону этого утверждения.


Это смотря в каком языке. )

_>>Данный код записывается на C++ буквально так:

_>>
_>>struct Point {
_>>        int32_t x;
_>>        int32_t y;
_>>};

_>>int main()
_>>{
_>>    auto p=Point{0, 7};
_>>    auto [x, y]=p;
_>>    assert(0==x);
_>>    assert(7==y);
_>>}
_>>


_>Ок, совсем недавно появилось. Но судя по proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0144r0.pdf это предназначено для простейших случаев, и что-то чуть более сложное, как в коде ниже, сделать уже невозможно.


Данная возможность входит в текущий стандарт языка (C++17) и предназначена она не для простейших случаев, а для всех нужных. Потому что это не сопоставление с образцом, а структурное связывание — отдельная языковая возможность.

_>И, кроме того, полноценного pattern matching в c++, все-равно так и не появилось.


Полноценное сопоставление с образом без проблем реализуется в C++ например с помощью этой https://github.com/solodon4/Mach7 библиотечки. И это гораздо более мощная вещь чем структурное связывание, но при этом нужная гораздо реже.

  смешной код
_>
_>#[allow(dead_code)]
_>struct Point {
_>    x: i32,
_>    y: i32,
_>}

_>#[allow(dead_code)]
_>struct Color {
_>    r: u8,
_>    g: u8,
_>    b: u8
_>}

_>#[allow(dead_code)]
_>struct ColoredPoint {
_>    p: Point,
_>    c: Color,
_>}

_>fn main() {
_>  let p = Point { x: 0, y: 7 };
_>  let c = Color {r: 255, g: 1, b: 1};
_>  let cp = ColoredPoint {p: p, c: c};
  
_>  let ColoredPoint {p: _, c: Color{r: red, g: _, b: _}} = cp;
  
_>  println!("Red color: {}", red);
_>}
_>


Мдаа, ты снова умудрился показать не сопоставление с образцом, а какую-то ненужную ерунду. А всего то стоило проставить значение у какой-нибудь из переменных в образце (как в примере на Эрланге или в примере 18-14 на Расте). Я начинаю думать, что ты реально не понимаешь смысл технологии сопоставления с образцом.
Re[18]: Nim lang
От: anton_t Россия  
Дата: 14.12.18 05:12
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Полноценное сопоставление с образом без проблем реализуется в C++ например с помощью этой https://github.com/solodon4/Mach7 библиотечки. И это гораздо более мощная вещь чем структурное связывание, но при этом нужная гораздо реже.


_>
  смешной код
_>>
_>>#[allow(dead_code)]
_>>struct Point {
_>>    x: i32,
_>>    y: i32,
_>>}

_>>#[allow(dead_code)]
_>>struct Color {
_>>    r: u8,
_>>    g: u8,
_>>    b: u8
_>>}

_>>#[allow(dead_code)]
_>>struct ColoredPoint {
_>>    p: Point,
_>>    c: Color,
_>>}

_>>fn main() {
_>>  let p = Point { x: 0, y: 7 };
_>>  let c = Color {r: 255, g: 1, b: 1};
_>>  let cp = ColoredPoint {p: p, c: c};
  
_>>  let ColoredPoint {p: _, c: Color{r: red, g: _, b: _}} = cp;
  
_>>  println!("Red color: {}", red);
_>>}
_>>



_>Мдаа, ты снова умудрился показать не сопоставление с образцом, а какую-то ненужную ерунду. А всего то стоило проставить значение у какой-нибудь из переменных в образце (как в примере на Эрланге или в примере 18-14 на Расте). Я начинаю думать, что ты реально не понимаешь смысл технологии сопоставления с образцом.



Когда на плюсах реализуешь этот "смешной код", тогда и поговорим.
А паттерн матчинг из говна и палок на текстовом препроцессоре это действительно смешно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.