справедливости ради, использовать указатели в любом случае придётся сильно реже, чем ссылки, так что я думаю, что в них алиасинг указателей проигнорировать впринципе вполне можно. как бы используя их, в любом случае, ты считай что говоришь, что тебе всё равно на алиасинг.
хотя справедливости ради, наверное было бы удобно иметь что-то для использования на более низком уровне, чтобы например можно было собственноручно реализовать что-то наподобие box, указатель который он хранит который, не может алиазиться.
let mut some_var j = ...
gen {
for i in 0.. {
j = i;
yield i;
}
}
— как например такое в списках выразить?
как минимум, суть в том, что в результате должен получиться ленивый список, а не обычный, а также между каждым вычислением следующео элемента могут происходить какие-либо сайдэффекиы.
блин, неловко это говорить, когда сам пишешь кучу опечаток, но в тексте много орфографических ошибок, которые немного сбивают с чтения. будет неплохо, если автор придумает что-нибудь против этого.
В другом комментарии уже и так всё объяснили но всё же, объясню и от себя
Придётся сделать трейт "украдены у Зины" и трейт "украдены у Люси", вместо трейта "украдены у кого-то" и его конкретизации.
trait Stolen {
const from : &str;
}
// или так, игнорируя, что константным параметром могут быть только инты, предполагая что объект может быть украден по нескольку раз
trait Stolen<const from : &str> {}
в идеале, если будут зависимые типы, позволяющие сделать константы не такими уж и константами — что хорошо ляжет на изменчивость при использовании разных объектов. Потом может появиться что-то такое :)
И, кстати, множественное наследование работало и позволяло из "принтеры" и "сканеры" родить "МФУ".
Вообще я немного думал о наследовании и мне кажется, что возможность наследовать только методы (интерфейсы) полностью покрывает возможности наследования с полями. А если базовый класс позволяет задавать поведение (как делают Unity или Javafx), его тогда странно, что с самого начала не заменят на пару из композиции и наследования от некого интерфейса/трейта
// вместо
abstract class Parent {
int a;
}
class Child : Parent {
...
}
//делать как-то так
interface Parent {
protected int a {get; set;}
}
sealed class Child : Parent {
// бонусом ещё и видно на месте,
// так что не придётся лезть в базовые классы за определением
protected int a {get; set;}
...
}
но наверное, в бд это может быть какой-то отдельный случай, где было удобно сделать именно так, я не сталкивался с таким, наверное.
да возможно моя мысль окажется непрактичной, я не могу сказать.
не столько некое замечание, сколько некая мысль, о которой я подумал во время чтения статьи
отдельно интересно мыслить из категории ооп без наследования классов, как в расте или хаскеле; а то и вовсе некую вырожденную категорию где есть строго только синглтоны ну или каждую структуру можно "инстанцировать" лишь единожды
по сути, исходя из такой, каждый объект характеризуется лишь своими свойствами. есть интерфейс/трейт "стул", характеризующийся тем что на нём можно сидеть и ещё какими-то свойствами.
есть трейт "деревянный стул" — по сути, объединение трейтов "стул" и "деревянный объект" + какие-то свои отдельные свойства.
и есть некий объект "The деревянный стул сделанный на фабрике в Швейцарии в 1998 году пекарем Николой Теслой во время запекания сапогов, украденных у соседки Зины, пока она …, масса которого составляет 10кг, состоит в данный момент из x.xE+27 атомов, …" — каждый такой объект уникален и каждый удовлетворяет каждый лишь строго своему набору трейтов.
каждый трейт это просто объединение других трейтов (ну или какой-то атомарный трейт по типу как условный трейт "объект со скоростью 1 м/с"), а каждый объект это некая уникальная сущность
хотя возможно, для такой модели ближе не oop, а ecs. тогда, сервисы — это те самые трейты, а компоненты… не уверен. возможно, сервисы — тоже компоненты, просто динамические? а объекты это как раз entity.
впрочем, из конкретно примера со стулом, можно ещё и привести непонятки, навроде парадокса корабля тесея… ну или что если взять половину атомов стула и использовать для создания одного стула, а половину для создания другого… будет ли хоть один из новых стульев считаться оригинальным объектом? как будто тогда уж стоит говорить и о уникальности во времени, ну или иммутабельности, что, как мне кажется, точно лишь запутывает…
как сверху упомянули, странно что выходных значений меньше, но лично я бы это даже сказал так: странно, что входные регистры не переиспользуются как выходные. учитывая, что `rdx` вроде как всё же так и делает, хоть почему-то и один. есть ли причина по которой вся шестёрка + уже выходной `rax` не может использоваться как для входа так и для выхода? это чем-то неудобно?
вообще, я немного предполагаю, что, когда придумывали этот cc, впринципе не особо задумывалось возвращать составные структуры в качестве обычного возврата функции, но вроде как так всё же даже не делают более новые cc. почему всё-таки?
не знаю как в конкретном случае, но всё же у упорядоченных ассоциативных массивов область применения время от времени да нередко находится, разве не так?
"Максимально" это конечно перегиб, всё же malloc гарантированно выровнен по выравниванию наиболее выровненного встроенного сишного типа (обычно выровнен в два машинных слова), чего просто атомикам, конечно, и хватит, но всё же для гарантий в более общем случае лучше использовать aligned_alloc, например при выравнивании по ширине кеш-линии, как иногда делается
Никакого нюанса нет, можно ограничение возможных значений считать просто инвариантом над u8, да и если захочется, всё ещё есть способы упаковать под ситуацию.
в расте это как будто окончательно решили тем, что запретили = возвращать что либо кроме (). как по мне, само то, что присваивание возвращает ссылку является стрельбой в ногу, как и возможность типам быть конвертируемыми в bool кроме пары случаев когда тип действительно близок по смыслу навроде bool? в C# ну или, может быть, любых option-типов
я не говорил о какой-то пользе трюка. это и есть просто цикл, записанный через рекурсию
собственно, суть лишь в том, что всё можно записать через циклы и мутабельные переменные, можно аналогично реализовать с неизменяемыми переменными и хвостовой рекурсией — вопрос лишь в тяжести (да и в любом случае, компилятор это обратно соптимизирует в обычный цикл)
не буду говорить, что в этом есть хоть какая-то польза с точки зрения исполнения кода, но как нечто на подумать — это может быть забавным.
да и просто то, что рекурсия написана нехвостовая, когда её почти тривиально можно сделать таковой, всё равно кажется не самой приятной вещью
немного странно, учитывая, что что факториал, что возведение в степень легко переписать через хвостовую рекурсию (хоть, конечно, и потребуется от компилятора её поддержка — но на gcc или clang это просто один флаг поставить)
далее планируемые числа фибоначи тоже
хотя вот числа аккермана и определитель без введения какого-то списка на куче кажутся тяжёлыми в этом плане (хотя я никогда не писал реализацию для аккермана хоть какую, так что знать не могу… вообще, это наверное просто вопрос того, чтоб немного поразмыслить)
в любом случае, для восстановления справедливости, не было бы неинтересным видеть тоже самое что писалось через "адекватные" циклы, написанным через tailrec
(впрочем, всё же очевидным минусом тут является в любом случае, что компилятор волен поступить как захочет)
мне до сих пор была интересна эта серия статей, так что я бы подождал одну про синхронизации, спасибо.
кроме раста я наверное не знаю языков, в которых к синхронизации как-то принуждают (но я не особо и разбирался в теме), так что также будут интересны и сравнения (в расте же вроде есть трейты Sync и Send, которые мешают передавать значения нарушающие синхронизацию в другой поток — даже если разымплементировать их надо вручную для чего-то самописного; и чтобы взять ссылку из значения под мьютексом, нужно его залочить, если память не изменяет)
в той же java хочешь пиши synchronized-блоки, хочешь нет, вроде как, а плюсы как всегда позволяют тебе делать что хочешь, но по итогу слишком уж на отвали. (но опять же, я не очень прямо хорошо погружён, я лишь студент, который многопоток использовал лишь пару раз, так что могу ошибаться)
----
по поводу конструкторов:
в расте у полей значения по умолчанию запрещены, и каждое поле нужно обязательно инициализировать; чтобы же получить значение по умолчанию нужно использовать Default::default() или какой-нибудь _::new(), а чтобы проинициализировать напрямую нужноуказать значение для кпждого поля по отдельности.
противоположным является подход например в C, Java или C#, где если не указать значение по умолчанию, то выберется конструктор по умолчанию, null или т.п. Конечно, в C# есть required, который правда всё равно для части случаев будет так себе, а в плюсах можно написать какой-то собственный простенький тип, в котором будет что-то вроде
, но как будто это костыли, о которых разработчики вряд ли будут думать (а может и будут, я не очень знаю).
подход аргентума я вижу похожим, но хоть немного лучшим в том, что значение по умолчанию нужно выбрать самим.
заодно синтаксис value.{/*lambda*/} мне напоминает что-то похожее в сишарпе или джаве (хотя наверное в котлине оно и вовсе будет околоидиоматичным, хотя и не уверен):
впринципе, в C# (и Rust тоже вроде как) также можно и сделать extension-метод, чтобы работал так же как also в котлине, но всё равно котлин в этом плане как будто красивейший, и подход из аргентума мне напоминает его, тем более что это ещё и идёт по умолчанию — по дизайну решение безусловно красивое.
ну а так, мне тоже нравится будто бы повсеместный отказ от конструкторов (и от перегрузок функций в частности)
просто в аргентуме значение по умолчанию будто бы словно есть абсолютно всегда, если я правильно понимаю, что не во всех ситуациях полезно (условно не существует же никакого сокета или дескриптора файла по умолчанию — верно? а если и есть, то стоит считать, что он должен вести себя равно какому-нибудь null, не так ли?)
по поводу классов: от того, что всегда есть значения по умолчанию, всё хорошо будет, не в этой модели, а в общем случае? и не будет ошибок с тем, что потенциально можно пропустить инициализацию какого-то поля с данной моделью их инициализации? хотя понимаю, что более старые языки тоже многие к этому склонны, но всё-таки.
и если тут утверждается, что тут счёт ссылок неатомарный, то что будет в многопотоке?
есть ли какая-то гарантия что я не протащу слабую ссылку в другой поток имея возможность редактировать основную из этого?
последний абзац я уже не понимаю, ибо так всей этой теорией не интересовался, но я просто думаю, что для N-мерного пространства можно определить N-мерный тензор, который как бы будет результатом перемножения 0 элементов, и затем уже получать то что нужно как было сказано через тензорное произведение на векторы-множители
справедливости ради, использовать указатели в любом случае придётся сильно реже, чем ссылки, так что я думаю, что в них алиасинг указателей проигнорировать впринципе вполне можно. как бы используя их, в любом случае, ты считай что говоришь, что тебе всё равно на алиасинг.
хотя справедливости ради, наверное было бы удобно иметь что-то для использования на более низком уровне, чтобы например можно было собственноручно реализовать что-то наподобие box, указатель который он хранит который, не может алиазиться.
ну условно, такое на псевдокоде
— как например такое в списках выразить?
как минимум, суть в том, что в результате должен получиться ленивый список, а не обычный, а также между каждым вычислением следующео элемента могут происходить какие-либо сайдэффекиы.
да, её и имею ввиду
блин, неловко это говорить, когда сам пишешь кучу опечаток, но в тексте много орфографических ошибок, которые немного сбивают с чтения. будет неплохо, если автор придумает что-нибудь против этого.
имелось ли ввиду в оригинале "персистентный"? просто вроде как обычно именно так переводят.
я не очень представляю как ту же seq-монаду выразить через список.
можно ли пример того о чём речь?
В другом комментарии уже и так всё объяснили но всё же, объясню и от себя
в идеале, если будут зависимые типы, позволяющие сделать константы не такими уж и константами — что хорошо ляжет на изменчивость при использовании разных объектов. Потом может появиться что-то такое :)
Вообще я немного думал о наследовании и мне кажется, что возможность наследовать только методы (интерфейсы) полностью покрывает возможности наследования с полями. А если базовый класс позволяет задавать поведение (как делают Unity или Javafx), его тогда странно, что с самого начала не заменят на пару из композиции и наследования от некого интерфейса/трейта
но наверное, в бд это может быть какой-то отдельный случай, где было удобно сделать именно так, я не сталкивался с таким, наверное.
да возможно моя мысль окажется непрактичной, я не могу сказать.
не столько некое замечание, сколько некая мысль, о которой я подумал во время чтения статьи
отдельно интересно мыслить из категории ооп без наследования классов, как в расте или хаскеле; а то и вовсе некую вырожденную категорию где есть строго только синглтоны ну или каждую структуру можно "инстанцировать" лишь единожды
по сути, исходя из такой, каждый объект характеризуется лишь своими свойствами. есть интерфейс/трейт "стул", характеризующийся тем что на нём можно сидеть и ещё какими-то свойствами.
есть трейт "деревянный стул" — по сути, объединение трейтов "стул" и "деревянный объект" + какие-то свои отдельные свойства.
и есть некий объект "The деревянный стул сделанный на фабрике в Швейцарии в 1998 году пекарем Николой Теслой во время запекания сапогов, украденных у соседки Зины, пока она …, масса которого составляет 10кг, состоит в данный момент из x.xE+27 атомов, …" — каждый такой объект уникален и каждый удовлетворяет каждый лишь строго своему набору трейтов.
каждый трейт это просто объединение других трейтов (ну или какой-то атомарный трейт по типу как условный трейт "объект со скоростью 1 м/с"), а каждый объект это некая уникальная сущность
хотя возможно, для такой модели ближе не oop, а ecs. тогда, сервисы — это те самые трейты, а компоненты… не уверен. возможно, сервисы — тоже компоненты, просто динамические? а объекты это как раз entity.
впрочем, из конкретно примера со стулом, можно ещё и привести непонятки, навроде парадокса корабля тесея… ну или что если взять половину атомов стула и использовать для создания одного стула, а половину для создания другого… будет ли хоть один из новых стульев считаться оригинальным объектом? как будто тогда уж стоит говорить и о уникальности во времени, ну или иммутабельности, что, как мне кажется, точно лишь запутывает…
как сверху упомянули, странно что выходных значений меньше, но лично я бы это даже сказал так: странно, что входные регистры не переиспользуются как выходные. учитывая, что `rdx` вроде как всё же так и делает, хоть почему-то и один. есть ли причина по которой вся шестёрка + уже выходной `rax` не может использоваться как для входа так и для выхода? это чем-то неудобно?
вообще, я немного предполагаю, что, когда придумывали этот cc, впринципе не особо задумывалось возвращать составные структуры в качестве обычного возврата функции, но вроде как так всё же даже не делают более новые cc. почему всё-таки?
не знаю как в конкретном случае, но всё же у упорядоченных ассоциативных массивов область применения время от времени да нередко находится, разве не так?
"Максимально" это конечно перегиб, всё же
mallocгарантированно выровнен по выравниванию наиболее выровненного встроенного сишного типа (обычно выровнен в два машинных слова), чего просто атомикам, конечно, и хватит, но всё же для гарантий в более общем случае лучше использоватьaligned_alloc, например при выравнивании по ширине кеш-линии, как иногда делаетсяНикакого нюанса нет, можно ограничение возможных значений считать просто инвариантом над
u8, да и если захочется, всё ещё есть способы упаковать под ситуацию.в расте это как будто окончательно решили тем, что запретили
=возвращать что либо кроме(). как по мне, само то, что присваивание возвращает ссылку является стрельбой в ногу, как и возможность типам быть конвертируемыми вboolкроме пары случаев когда тип действительно близок по смыслу навродеbool?в C# ну или, может быть, любыхoption-типовя не говорил о какой-то пользе трюка. это и есть просто цикл, записанный через рекурсию
собственно, суть лишь в том, что всё можно записать через циклы и мутабельные переменные, можно аналогично реализовать с неизменяемыми переменными и хвостовой рекурсией — вопрос лишь в тяжести (да и в любом случае, компилятор это обратно соптимизирует в обычный цикл)
не буду говорить, что в этом есть хоть какая-то польза с точки зрения исполнения кода, но как нечто на подумать — это может быть забавным.
да и просто то, что рекурсия написана нехвостовая, когда её почти тривиально можно сделать таковой, всё равно кажется не самой приятной вещью
Нет, это то же самое
я её уже однажды придумав написал, и потому легко повторю ещё раз :)
можно даже легко переписать для случаев, когда n < 0
по сути, все аргументы это просто всё те же мутабельные переменные, если бы мы писали через обычные циклы
немного странно, учитывая, что что факториал, что возведение в степень легко переписать через хвостовую рекурсию (хоть, конечно, и потребуется от компилятора её поддержка — но на gcc или clang это просто один флаг поставить)
далее планируемые числа фибоначи тоже
хотя вот числа аккермана и определитель без введения какого-то списка на куче кажутся тяжёлыми в этом плане (хотя я никогда не писал реализацию для аккермана хоть какую, так что знать не могу… вообще, это наверное просто вопрос того, чтоб немного поразмыслить)
в любом случае, для восстановления справедливости, не было бы неинтересным видеть тоже самое что писалось через "адекватные" циклы, написанным через tailrec
(впрочем, всё же очевидным минусом тут является в любом случае, что компилятор волен поступить как захочет)
мне до сих пор была интересна эта серия статей, так что я бы подождал одну про синхронизации, спасибо.
кроме раста я наверное не знаю языков, в которых к синхронизации как-то принуждают (но я не особо и разбирался в теме), так что также будут интересны и сравнения (в расте же вроде есть трейты
SyncиSend, которые мешают передавать значения нарушающие синхронизацию в другой поток — даже если разымплементировать их надо вручную для чего-то самописного; и чтобы взять ссылку из значения под мьютексом, нужно его залочить, если память не изменяет)в той же java хочешь пиши
synchronized-блоки, хочешь нет, вроде как, а плюсы как всегда позволяют тебе делать что хочешь, но по итогу слишком уж на отвали. (но опять же, я не очень прямо хорошо погружён, я лишь студент, который многопоток использовал лишь пару раз, так что могу ошибаться)----
по поводу конструкторов:
в расте у полей значения по умолчанию запрещены, и каждое поле нужно обязательно инициализировать; чтобы же получить значение по умолчанию нужно использовать
Default::default()или какой-нибудь_::new(), а чтобы проинициализировать напрямую нужноуказать значение для кпждого поля по отдельности.противоположным является подход например в C, Java или C#, где если не указать значение по умолчанию, то выберется конструктор по умолчанию, null или т.п. Конечно, в C# есть required, который правда всё равно для части случаев будет так себе, а в плюсах можно написать какой-то собственный простенький тип, в котором будет что-то вроде
, но как будто это костыли, о которых разработчики вряд ли будут думать (а может и будут, я не очень знаю).
подход аргентума я вижу похожим, но хоть немного лучшим в том, что значение по умолчанию нужно выбрать самим.
заодно синтаксис value.{/*lambda*/} мне напоминает что-то похожее в сишарпе или джаве (хотя наверное в котлине оно и вовсе будет околоидиоматичным, хотя и не уверен):
впринципе, в C# (и Rust тоже вроде как) также можно и сделать extension-метод, чтобы работал так же как
alsoв котлине, но всё равно котлин в этом плане как будто красивейший, и подход из аргентума мне напоминает его, тем более что это ещё и идёт по умолчанию — по дизайну решение безусловно красивое.ну а так, мне тоже нравится будто бы повсеместный отказ от конструкторов (и от перегрузок функций в частности)
просто в аргентуме значение по умолчанию будто бы словно есть абсолютно всегда, если я правильно понимаю, что не во всех ситуациях полезно (условно не существует же никакого сокета или дескриптора файла по умолчанию — верно? а если и есть, то стоит считать, что он должен вести себя равно какому-нибудь null, не так ли?)
по поводу классов: от того, что всегда есть значения по умолчанию, всё хорошо будет, не в этой модели, а в общем случае? и не будет ошибок с тем, что потенциально можно пропустить инициализацию какого-то поля с данной моделью их инициализации? хотя понимаю, что более старые языки тоже многие к этому склонны, но всё-таки.
и если тут утверждается, что тут счёт ссылок неатомарный, то что будет в многопотоке?
есть ли какая-то гарантия что я не протащу слабую ссылку в другой поток имея возможность редактировать основную из этого?
последний абзац я уже не понимаю, ибо так всей этой теорией не интересовался, но я просто думаю, что для N-мерного пространства можно определить N-мерный тензор, который как бы будет результатом перемножения 0 элементов, и затем уже получать то что нужно как было сказано через тензорное произведение на векторы-множители