LINUX.ORG.RU

Вопрос про zig

 , абстракция


0

2

Это правда, что зиг не поддерживает интерфейсы (а ля чисто-абстрактные классы в c++, impl в rust и т.д.)? Т.е. надо в коде всё время бойлерплейт вставлять, типа:

fn add(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
    comptime {
        if (!@hasDecl(@TypeOf(a), "add"))
            @compileError("type must support add");
    }
    return a + b;
}

Если реально так, то не понимаю, кому может понравиться така поделка. Как вообще документировать интерфейсы либ, фреймворков? А если никто не написал документацию (стандартный сценарий развития разработки)?

★★★★★

Последнее исправление: seiken (всего исправлений: 1)

Офигеть, в языке без интерфейсов неудобно работать с интерфейсами!Какой позор!

Может, стоит выбрать соотв. язык к задаче, а не ругать, что язык не может во всё?

Зигу не нужны такие конструкции, у него мощный комптайм и он не нуждается в подобной яме, как классы и прочее…

anonymous
()

Я чёт, подозреваю, что это вопрос из разряда -«а хде в этих ваших расто-хаскелях наследование, чтоб прямо вот дословно как в жабке?». У языка заметно другая идиоматика. Вот это:

    comptime {
        if (!@hasDecl(@TypeOf(a), "add"))
            @compileError("type must support add");
    }

просто вынесется в отдельную компилтайм функцию предикат is_addable(comptime T: type), один раз и в одном месте и где надо будет «вызываться». И отличие от, например, растового «where T: Add» будет, что называется, с точностью до переобозначения. И небольшая проблема тут только отсутсвие перегрузки операторов. Зиг особо не знаю, так краем глаза посматриваю, язык так-то занятный и подкупает как раз вот этой непосредственной вербозностью работы с типами

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

чёт, подозреваю, что это вопрос из разряда -«а хде в этих ваших расто-хаскелях наследование

нет. Вопрос был вообще не про наследование. Интерфейсы есть уже в С. Это структура с членами-указателями на функции. Для разраба вызываемых функций (коллбеков) такие таблицы указателей служат compile-time проверкой, что в вызывающем коде все функции имеют корректную сигнатуру. Для разраба вызывающих функций такая структура - декларация того, что пользовательский код можно вызывать безопасно, т.е. что в подсовываемые реализации интерфейса содержат функции с нужными сигнатурами.

В случае с зигом такое ощущение, что он отказался от интерфейсов по каким-то своим психиатрическим причинам. Детский лепет про неэффективность vtbl поскипан.

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

Вопрос был вообще не про наследование.

Да, это как отдалённый пример, в смысле, искомая фича в данном языке или выглядит по другому или вообще не нужна.

Интерфейсы есть уже в С

Пфф, в зиге тоже можно указатели на функции в структуру напихать, да и просто и методы есть и модульность

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

Zig does not have an interface keyword — and that’s a feature, not a bug.

Прочитав статью я склоняюсь, что это скорее баг, а не фича.

Авторы языка (стандартной библиотеки) явно используют этот паттерн, то есть аргумент «не нужно» отметаем.

Остается аргумент «DIY», чтобы как бы прочувствовать цену абстракции и принимать осознанное решение. Но, видишь ди ты эту цену при, возможно неявном, вызове аллокаторов или стриминговых функций? Так ли это действительно важно? Со стороны это выглядит скорее как эпатажное «фи» чем продуманный и обоснованный дизайн.

Это классно, что можно сделать самому. Очевидно, это даст определенную гибкость (как в примере стриминговых функций). Но опыт подсказывает, что на практике подавляющее использование этого паттерна будет простой копипастой, которую имело бы смысл скрыть за дефолтной реализацией с удобным синтаксисом. Оставить DIY-фичу для редких случаев, когда это действительно нужно.

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

которую имело бы смысл скрыть за дефолтной реализацией с удобным синтаксисом

Так функции же пишутся. И реализацию можно сделать с произвольными параметрами и условиями, а не тем куцым огрызком, который в качестве отдельного языка времени компиляции в Си/Расте (ладно, в Расте можно полнофункциональный макрос наваять, но так не пишут).

Условным неудобством является только то, что тип не виден в заголовке, а надо смотреть ещё несколько строк. Но в Си++ с шаблонами та же проблема (посмотри на итераторы).

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

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

Так в этом уже как минимум одна проблема. А если автор занимается проверкой типов на строке 197 функции abcdxyz?

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

Таким образом, зиг способствует написанию write-only лапши. А в 21м веке даже малограмотные знают, что программист тратит больше времени и усилий на чтение единицы исходных кодов, чем на её написание.

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

Так в этом уже как минимум одна проблема. А если автор занимается проверкой типов на строке 197 функции abcdxyz?

Тогда при компиляции увидишь ошибку. Причём нормальную, а не «в строке 197 abcdxyz не удалось подобрать кандидат реализации шаблона … и тут 500 строк …».

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

а не «в строке 197 abcdxyz не удалось подобрать кандидат реализации шаблона

в С++ скоро всё переведут на концепты, надо только потерпеть

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

Это где это в расте куцый огрызок?

Как в расте написать

fn f(comptime T: type, a: T, b: T) T {
    return switch (@typeInfo(T)) {
        .comptime_int => f_comptime(a, b),
        .int => |info| if (info.bits <= 16)
            f_runtime(a, b)
        else
            @compileError("ints too large"),
        else => @compileError("only ints accepted"),
    };
}

Тем более на фоне сишки.

То в сишке и расте куцый на фоне зига.

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

Например. Или можно сделать что-то вроде

fn mult(a: matrix, b: matrix) Matrix(a.n, b.m) {
  comptime {
    if (a.m != b.n)
       @compileError("должно совпадать количество колонок в a и строк в b");
  }
  ...
}
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от seiken

А зачем здесь comptime?

Чтобы проверка была при компиляции у программиста, а не при запуске у пользователя.

А если я передаю матрицы из кода на zig в код на C?

Тогда если размерность известна при компиляции, используешь тип, который я привёл, если неизвестна, значит ставишь массив произвольного размера, который при компиляции проверяться не будет.

Можно сделать общий код, который будет работать как с динамическими (для которых будет проверка времени выполнения), так и со статическими матрицами.

monk ★★★★★
()