Raku rebless більше не працює з успадкованими класами


9

Код, вказаний у цій темі, більше не працює: Як я можу повторити об'єкт у Perl 6?

Я писав цей фрагмент коду минулого року, і він працював тоді. Тепер це не так:

class Person { ; }
class Woman is Person { ; }
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

Metamodel::Primitives.rebless($tom, Woman);
# -> New type Woman for Person is not a mixin type

Повідомлення про помилку не має сенсу, оскільки воно має працювати з успадкованими класами. Принаймні так було.

Документація не є корисною; https://docs.raku.org/routine/rebless


Може бути помилкою регресії. Напевно, найкраще повідомити про це як про ракудо.
jjmerelo

У лютому минулого року відбулися зміни: github.com/perl6/nqp/blob/…
jjmerelo

Також я оновив документацію, виноску вказуючи на @jnthn відповідь docs.raku.org/type/Metamodel::Primitive . Спасибі, raiph
jjmerelo

Відповіді:


11

передбачається працювати з успадкованими класами

Це ніколи не повинно було бути таким загальним. Я розробив цей API і реалізував його в першу чергу, і він коли-небудь замислювався як деталь реалізації міксинів.

До недавнього часу він не входив до тестового набору мовних специфікацій - а коли він став його частиною, він вже мав свою сучасну, більш обмежувальну, семантику. Обмеження на ньому важливі з міркувань продуктивності: коли ми знаємо, що тип не є тим, який може бути ціллю операції mixin, ми можемо JIT-компілювати атрибути доступу до цього об'єкта в щось набагато простіше (ми заплатили додатковий умовний хід на кожен атрибут доступу перед зміною, і тепер доведеться платити лише за цільовими типами mixin).

Можна змінити оригінальну програму для роботи, використовуючи MOP для побудови класу. Насправді, наступна не зовсім оригінальна програма; Я зробив невеликий твір для того, щоб показати, як можна надати методи в підкласі як анонімну роль, щоб уникнути занадто великої кількості котло MOP.

class Person { method m() { "person" } }
constant Woman = do {
    my \w = Metamodel::ClassHOW.new_type(:is_mixin, :name<Woman>);
    w.^add_parent(Person);
    w.^add_role(role { method m() { "woman" } });
    w.^compose()
}
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m; # person
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m; # woman

Хоча це самий семантично прямий виправлення до оригінальної програми, є коротший спосіб: використовувати butоператор на Personоб'єкті типу, щоб створити тип mixin і повернути його, а потім просто налаштувати його ім'я на свій смак:

class Person { method m() { "person" } }
constant Woman = Person but role { method m() { "woman" } }
BEGIN Woman.^set_name('Woman');

my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m;
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m;

Що тільки на один рядок більше, ніж оригінал.


constant Woman = Person but role …Не усвідомлював, що це можна зробити. І таким чином, але для BEGINлінійки, Раку майже змушує себе робити і прототипну парадигму в стилі JS!
користувач0721090601

Добре. Дякую за пояснення. Я сподіваюся, що він знайде свій шлях до документації, оскільки docs.raku.org/routine/rebless досить марний ... Я скоро оновлю «Починаючу Раку».
Арне Соммер

@ user0721090601 Raku підтримує, цитуючи S12: "Програмування OO на основі класів та прототипів" . Однак якщо ви створюєте об’єкти за допомогою classключового слова , то, цитуючи S12 ще раз: "за замовчуванням об'єкти, отримані з Muпідтримки досить стандартної моделі на основі класу ... bless... виклики ... BUILD процедури ... BDILD семантика BUILD є успадковано від Mu". Підсумовуючи це, я стверджую, що точніше сказати, що Раку підтримує A) "серйозно викривляючи навіть OO на базі стандартних класів із лише парою рядків коду" та B) "OO на основі прототипу".
raiph

Дивіться raku-musings.com/reblessed.html, щоб побачити порушення змін.
Арне Соммер

5

Дивіться відповідь jnthn для авторитетного обговорення того, що саме сталося reblessі що з цим робити.

воно працювало ... Тепер це не так ... Повідомлення про помилку не має сенсу ... воно повинно працювати з успадкованими класами ... Принаймні так було ... Документація не корисна

Цю (ультра довгу!) Відповідь, можливо, варто прочитати тим, хто зацікавлений у подальшому обговоренні принципів та практики підходу TDD, який лежить в основі роботи над мовою програмування Raku та пов'язаними з нею артефактами, такими як компілятор Rakudo та вміст docs.raku.org .

Ця відповідь структурована як конкретні відповіді на окремі частини оригінального запитання Арна та коментарі, які вони написали у відповідь на попередню версію цієї відповіді. Моя мета полягала в тому, щоб зробити Арне більш корисним, хоча, сподіваюся, ще корисним для інших.

Арн: Код, вказаний у цій темі, вже не працює: Як я можу повторити об'єкт у Раку?

Я оновив прийняту відповідь на це ПЗ, щоб посилатися на цю ОП.

Арн: Я писав цей фрагмент коду минулого року, і він працював тоді. Тепер це не так

Відповідна зміна обговорювалась у квітні 2019 року, коли jnthn писав:

Останнім часом типи, які були ціллю reblessоперації, почали створюватись явно як цільові типи mixin, щоб сприяти оптимізації. ...

У коментарі 11 днів тому закриваючи rakudo GH випуск "Rebless для користувацького типу вже не працює" , він написав:

Вам потрібно домовитись про is_mixinте, щоб ClassHOW.new_typeіменний аргумент передався до ... Немає способу зробити це з синтаксисом класу, таким чином, цільовий тип rebless повинен бути зібраний і за допомогою MOP.

(Клацніть вище посилання, щоб дізнатися, як робити те, що пропонується.)

Це питання також обговорюється трохи далі в роботі, яке він працював ... раптом він не став ... документація ... повинна документувати розділ виклику нижче.

Арн: він повинен працювати з успадкованими класами. Принаймні так було.

жаркий - г epository про еЛ.Л. s PEC т реси - визначаєщо Рака код повинен робити. ( Св . Roa st можна читати як s upposed t o s.)

Ще в одному повідомленні квітня 2019 року jnthn написав:

Попередньої специфікації для цього не було Metamodel::Primitives.rebless. Я додав цей видовище, щоб тепер є. Це означає, що зараз є певне визначення того, на що можна очікувати, що буде працювати.

Те, що поведінку Ракудо визначає виконуваний тестовий набір, є основоположною частиною підходу @ Ларрі до забезпечення того, щоб Раку поводився надійно [1] і має глибокі наслідки [2] .

Вплив цієї зміни на широко використовуваний модуль

Ось короткий знімок впливу цієї зміни, що розгортається для популярного модуля Inline :: Perl5.

У квітні 2019 року компанія Niner відкрила випуск GK про ракудо щодо впливу,Inline::Perl5 і я вивів деякі основні моменти обміну між niner та jnthn нижче.

(Я вилучив деякі речі, які були важливими в оригінальному контексті, але відволікали контекст цього ЗУ. Будь ласка, не вважайте, що ви повністю розумієте оригінальну розмову з цього витягу. Якщо ви сумніваєтесь, натисніть посилання. )

niner: TBH, що я тут роблю, напевно, завжди був своєрідним риб'ячим ... Можливо, навіть таке ... Я можу позбутися [його] ... Було б добре хоч би тримати вже розгорнуті версії Inline :: Perl5 в режимі запуску та запуску .

jnthn: Не було попередньої специфікації для Metamodel::Primitives.rebless. Я додав [a] spectest так, що тепер є. Це означає, що зараз існує певне визначення того, на що можна очікувати, і на яке Inline :: Perl5 можна покластися.

Оскільки невідомі іменовані параметри ігноруються, але :mixinне потрібні були у попередніх версіях Rakudo, то можна було б створити нову версію Inline :: Perl5, яка може працювати як на попередніх версіях Rakudo, так і на наступній, тому може бути принаймні зворотний співвіт.

Я не думаю, що жоден спосіб підтримувати роботу для існуючих версій Inline :: Perl5 ...

niner: На жаль, передача :mixinне допомагає в цьому випадку, оскільки реблема робиться на підкласі того, створеного через Metamodel::Primitives.create_type. Підклас використовує нормальний Perl6::ClassHOW.

Я працюю над головним рефактором, щоб в першу чергу позбутися від злому rebless. Я знову відкриваю цю проблему, щоб менеджер випусків усвідомлював, що не існує робочого Inline :: Perl5 щодо кандидата на випуск rakudo.

jnthn: Чи створюєте ви цей клас за допомогою MOP? Ви можете перейти :is_mixinдо Perl6::ClassHOW.new_typeцього.

Нінер: Ні, це для цієї ситуації:class Bar is Foo { }

Допомога з документами

У коментарі нижче цієї відповіді ви написали:

Я можу допомогти в частині документації

Це звучить для мене як дуже відповідна і корисна відповідь на питання, що лежить в основі вашої SOQ. Я сподіваюся, що нам пощастило, що це сталося.

якщо це допомагає

Я вважаю, що ваш технічний текст є чудовим, тому я би сподівався, що кінцевий результат роботи з іншими учасниками вдосконалення буде чудовою справою.

Основні обмеження щодо вмісту docs.raku.org

Значна частина причини, по якій я написав решту цієї дуже обширної відповіді на таке, здавалося б, просте запитання, і відновив його після того, як спочатку видалив його, коли Джонатан відповів на нього, - це обговорення принципів та практики підходу TDD, який лежить в основі роботи. мову програмування Raku та пов'язані з нею артефакти, такі як компілятор Rakudo та вміст docs.raku.org .

Aiui, бажаний взаємозв'язок між тим, як повинні працювати речі в Раку, і тим, як вони насправді працюють в Ракудо, і тим, як речі повинні бути задокументовані на docs.raku.org, зводиться до:

  • ВСЕ ОБОВ'ЯЗКОВО припускати, що воно назавжди підпорядковане фундаментальному характеру волонтерського проекту; і в межах цього обмеження:

  • Поведінка в смаженому ДОЛЖЕН бути задокументованим, а інша поведінка НЕ ​​БУДЕ ЗАПОВІДНА.

(Враховуючи доступний час, інтерес та консенсус для добровольців, періодично робляться винятки для документування поведінки належної QA'd Rakudo, яка не покрита смаженою. У сучасній практиці це, мабуть, означає поведінку версії Rakudo у випущеній Rakudo Star.)

Марна документація

Документація не є корисною

Я вважав це справедливим коментарем. Враховуючи все, документація, як це було під час написання запитання, не була корисною.

документація була марною [у 2018 році]

Це зовсім інше твердження.

На той час не було покриття смаженого входу rebless.

Якщо сторінка docs.raku.org на rebless була описана його поведінку , як це було в 2018 році, то це було б гірше , ніж марно , тому що це було б неправильно вважати , що то поточна поведінка була підтримана. Насправді існували можливості для прориву в майбутній версії Ракудо без розумних перспектив, що поведінку 2018 року буде відновлено основними розробниками. І справді це сталося: його непідтримувана поведінка з 2018 року зламалася і не була відновлена.

Отже, враховуючи консенсус щодо того, що належить до docs.raku.org, а що ні (див. Вище), найкорисніше, що його reblessсторінка могла зробити, - це взагалі не документувати reblessабо, можливо, краще включати сторінку для цього, але переконайтесь, що він не описав її поведінку. Яка така була ситуація: сторінка існувала; не була безпосередньо корисною; і це було, мабуть, краще, ніж нічого.

(Неважко уявити, що все ще краще. Наприклад, що, якщо функції документування сторінок включали відсоток, що документує стан тестового покриття, пов'язаного з цією функцією, у версії Ракудо в останній Rakudo Star? 0% може негайно зрозуміти читача до усвідомлення того, що ця функція не була охоплена смаженою. Ось це сказало, хоча ця функція документа легко уявити , хто збирається її реалізувати? Так само легко уявити, що це може тривати календарний рік або більше сумлінної роботи та співпраця для корисного впровадження та розгортання, а також те, що люди думають, що інші речі є важливішими.)

вона спрацювала ... раптом не стала ... документація ... повинна документувати дзвінок

це спрацювало

Це "удача" це спрацювало.

це раптом більше не працювало

Тому що Ракудо вдосконалювався.

документація ... повинна документувати дзвінок

Як пояснювалося раніше, AIUI поточного консенсусу спільноти та / або робочої практикою є: документація слід документувати конкретну версію виклику, а саме смажені «D поводжень для версії Rakudo в останній Rakudo Star; і МОЖЕ поводити документи в інших версіях.

і не посилатися на щось інше

Aiui, сучасний консенсус та / або робоча практика полягає в тому, що те, що деякі можуть вважати "слабким" вкладом док., Наприклад, короткий, поспішаючи написаний вміст та / або посилання поза документами, МОЖЕ бути введено, якщо добровольці вважають, що негайна зміна гарантована для відображення. деяке занепокоєння, яке висловив користувач (наприклад, цей SO), і що зробити "слабку" зміну було б краще, ніж робити взагалі нічого. Ви, звичайно, можете зробити PR, щоб поліпшити його (або скасувати його, якщо ви дійсно відчуваєте, що зміна настільки "слабка", що робить справи гіршими).

посилання на зміни у 2019.11, за моїм підрахунком, відсутнє 7 місяців

(Щось таке, на моєму рахунку теж, хоч я бачив компілятор, який претендував на 2019.03.1 з такою ж перервою в поведінці. [3] )

Я думаю, що Дж. Дж. Змінив документ, і він просто неправильно прокоментував коментар jnthn про те, як адаптуватися до змін. На даний момент я думаю, що це краще, ніж нічого, але з нетерпінням чекаю, що ви оновите це. :)

Виноски

[1] Наступне було сказане через кілька хвилин після того, як Ларрі вперше оголосив про проект, який призвів до Раку в його виступі 2000 року "Держава цибулі" :

Питання: Чи буде у [Раку] специфікацій?

Ларрі: те, що ми особливо хочемо наголосити ... - це, мабуть, не стільки специфіка [дизайну мови], скільки розробка нашого поточного тесту на регресію ... в тест на перевірку того, що мова означає насправді, і насправді вийти та вивчити всі куточки і ручки і кажуть: "Це [Раку], це не [Раку]", і тоді ми маємо фактично машиночитані характеристики. А для мене це насправді набагато важливіше, ніж те, що говорить багатослівність у читаній людині речі.

[2] Звичайно, смаження добре справляється з даним користувачем, якщо його тести достатньо задовольняють потреби користувача. Проблема Арна демонструє, як отвори в покритті можуть дивувати. Щоб обговорити ці діри, коли вони стояли у 2018 році, див. У розділі Про характеристики, версії, зміни та… Порушення . Хороша новина полягає в тому, що смаження - це просто багато тестів, написаних в Раку, щоб перевірити, чи вирази або конструкції з певними значеннями роблять певну справу. Тому людям або корпораціям легко надати нові тести, щоб поліпшити охоплення тесту. І все це знаходиться під контролем версій (git), тому спеціальні теги, гілки та вилки вниз за течією є життєздатними, стійкими та керованими. ( На насправді, це як нові мовні версії ( Christmas, Diwali, Eid(?), І т.д.) управляються.)

[3] Я бачив спробу змінити новий клас, створений за допомогою регулярного newclass is oldclassсинтаксису як на робочому столі (на моєму ноутбуці), так і не на роботі (на repl.it), використовуючи компілятори, на які претендує 2019.03.1. (Імовірно, repl.it встановив версію вихідного коду компілятора або двійковий файл, зібраний з нього, взятий з головного голови незабаром після оновлення версії компілятора 2019.03.1, із зміною місця на місці. Зауважу, що repl.it haven ' t оприлюднив їхній інтернет-репл-репл - я виявив це випадково - тому немає нічого спільного в цій ситуації, але це підкреслило для мене необхідність $RAKU.compiler.verbose-configметоду, який використовується у відпрацьованих / розбитих результатах, які я щойно пов'язав.)


Я знайшов цю статтю, коли спробував розібратися, як працює "rebless", оскільки документація була марною: stackoverflow.com/questions/44486985/… І тоді це спрацювало. А потім раптом більше не працювало, а документація все ще була марною. Це все одно, як слід документувати дзвінок, а не посилатися на щось інше. І посилання на зміни в 2019.11 - це мій перелік 7 місяців.
Арне Соммер

Я можу допомогти з частиною документації, якщо це допоможе.
Арне Соммер

@ArneSommer Перегляньте нові розділи моєї відповіді, починаючи з Допомога з документами .
raiph

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.