Как заставить необязательный тип (для элемента массива) во время компиляции в Swift?

struct MyStruct {
    @ArrayOfNonOptionalElements var arr: [SomeNonOptionalType]
}

где @ArrayOfNonOptionalElements — это propertyWrapper.
Итак, как обеспечить необязательность для типа внутри? Возможно ли это вообще? 🙄
Я имею в виду, как реализовать оболочку свойства таким образом, чтобы тип элемента массива был необязательным.

Обновление:
Ну, похоже, мой вопрос никто не понял 😣
Я хочу, чтобы компилятор не ставил вопросительный знак внутри квадратных скобок 😃

Обновление 2:
Скопирую/вставлю сюда один из моих комментариев из-под поста, чтобы все могли его увидеть:

Я пишу свойство @Compact для безопасного декодирования массива. Итак результат гарантированно не будет содержать нулей. Это свойство обертка может работать с любыми типами массивов. Так что это скорее просто своего рода перфекционистского вызова 🙂

Что на самом деле делает ваша оболочка свойств? Вы просто пытаетесь добиться того, чтобы свойство не могло быть необязательным? Для этого вам не нужна оболочка свойств. Или вы на самом деле пытаетесь создать оболочку свойства, которая делает что-то полезное, но не может работать с опциями?

David Pasztor 25.04.2024 15:44

@DávidPásztor Я пишу propertyWrapper "@Compact" для безопасного декодирования массива. Таким образом, результат гарантированно не будет содержать нулей. Эта оболочка свойства может работать с любыми типами массивов. Так что это скорее своего рода перфекционистский вызов 🙂

Roman 25.04.2024 15:53

если ваш массив определен как [SomeNonOptionalType], он уже гарантированно не будет иметь нулей. Иметь ноль было бы [SomeNonOptionalType?]. Так что именно вы пытаетесь предотвратить?

timbre timbre 25.04.2024 16:13

Я думаю, ОП хочет, чтобы wrappedValue как [T] для оболочки свойств был прикреплен @ArrayOfNonOptionalElements var arr: [T?]. Не уверен, потому что сам вопрос говорит об обратном, но их ответ предполагает это.

iSpain17 25.04.2024 16:18

Чтобы прояснить ваш вопрос, можете ли вы показать попытку и описать, почему она не работает?

Sweeper 25.04.2024 16:23

Пост обновлен ✅

Roman 25.04.2024 16:42

В Swift нет «противоположного» типа Optional, поэтому я не думаю, что вы сможете добиться такой проверки времени компиляции.

Joakim Danielson 25.04.2024 16:46

@JoakimDanielson Похоже на идею для предложения Swift Evolution 😃

Roman 25.04.2024 16:48

Вы пытаетесь гарантировать, что разработчик случайно не наберет [SomeNonOptionalType?] вместо [SomeNonOptionalType], требуя от того же разработчика аннотировать строку @ArrayOfNonOptionalElements? Почему? Компилятор уже помогает вам без какой-либо специальной обертки. Если массив случайно объявлен разрешающим необязательные параметры, то для каждого доступа к массиву потребуется код для обработки необязательного, а не необязательного.

HangarRash 25.04.2024 17:11

@HangarRash Я снова обновил пост. Пожалуйста, посмотрите 🙂

Roman 25.04.2024 17:30

Я правильно понимаю, что @Compact будет содержать ненулевые значения, даже если закодированные данные содержат нули?

Cy-4AH 25.04.2024 17:34

@Roman Ваши обновления не отвечают на мои вопросы. Какую предполагаемую выгоду вы ожидаете получить, пытаясь заставить разработчика добавить @ArrayOfNonOptionalElements к строке кода на случай, если тот же разработчик случайно добавит ? к остальной части объявления массива? Как я уже сказал, компилятор уже помогает вам, не нуждаясь в каких-либо аннотациях.

HangarRash 25.04.2024 17:35

@Cy-4AH ✅ В этом вся суть 😃

Roman 25.04.2024 17:35

@HangarRash Возможно, ты прав. Ну... похоже, это всё равно невозможно 😅

Roman 25.04.2024 17:45

@ Cy-4AH На самом деле даже больше. Он также «отфильтрует» любые ошибки декодирования. Таким образом, ошибка в одном элементе массива декодирования больше не приведет к сбою всего вашего приложения 😅 Проблемный элемент будет просто пропущен.

Roman 25.04.2024 17:49

@Роман, твои недавние вопросы кажутся XY-проблемами . Вместо того, чтобы чрезмерно упрощать реальную проблему, которую вы пытаетесь решить, стоило бы задать вопрос о реальной проблеме в форме минимального воспроизводимого примера. Вопрос «Как мне декодировать массив JSON таким образом, чтобы, если один элемент не может быть декодирован, он не терпел неудачу во всем декодировании, а просто пропускал этот элемент», будет совершенно другим вопросом, чем тот, который вы в конечном итоге задали. , но, похоже, проблема, которую вы на самом деле пытаетесь решить.

David Pasztor 25.04.2024 17:59

@Dávid Pásztor «Как мне декодировать массив JSON таким образом, чтобы, если один элемент не может быть декодирован, он не терпел неудачу во всем декодировании, а просто пропускал этот элемент» - это не мой вопрос, это не проблема. Я знаю, как это сделать. На самом деле я уже это сделал, и все работает отлично 😃 Проблема, которую я сейчас пытаюсь решить, заключается именно в том, о чем я спросил: «Я хочу, чтобы компилятор не ставил вопросительный знак внутри квадратных скобок»

Roman 25.04.2024 18:04

Я не могу придумать, как это сделать, и вполне логично, что вы не можете. По аналогии, это было бы похоже на наличие некоторого func i<T>(_ value: T) -> T { value }, но ограничение его настолько T произвольным не может быть Int. Какой вред был бы, если бы ограничения не существовало? Обобщенные значения связаны с ограничением значений протоколами, что, в свою очередь, дает этим обобщенным значениям больше возможностей (поскольку у вас есть доступ к требованиям протокола). Если есть что-то, что необязательный может сделать, а необязательный не может, вам следует отразить это в ограничении протокола.

Alexander 25.04.2024 19:15

Вам нужно написать свой макрос вместо propertyWrapper. Плохо, что ваш вопрос закрыт и вы признали, что это невозможно. Идея хорошая 👍

Cy-4AH 26.04.2024 09:10

@ Cy-4AH Cy-4AH Я закончил свою работу и открыл ее исходный код. Так что теперь каждый может воспользоваться результатом (или даже внести свой вклад 😉). Надеюсь, вам это будет полезно 🙂 gitlab.com/roman.kisliaченко/decodable-kit

Roman 27.04.2024 12:15
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
20
94
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, как обеспечить необязательность для типа внутри? Возможно ли это вообще? 🙄

Нет. В Swift нет способа выразить «нет» в системе типов. (Появится новый ~Copyable, но он не означает «не копируемый». Это означает «устраняет неявное предположение о копируемости».)

Я пишу свойство @Compact для безопасного декодирования массива. Таким образом, результат гарантированно не будет содержать нулей. Эта оболочка свойства может работать с любыми типами массивов.

Это не совсем точно. Опциональные параметры являются декодируемыми, если их оболочка является декодируемой. Таким образом, справедливо следующее:

try JSONDecoder().decode([Int?].self, from: Data("[1]".utf8)) // [Optional(1)]

Это говорит о том, что ваш @Compact все еще может возвращать массив опционалов. И если он может вернуть опциональные параметры, он может вернуть nil. Система типов должна быть в состоянии доказать во время компиляции, что это невозможно, и, судя по тому, что вы описали, это возможно, вы просто «обещаете», что этого не произойдет. И система типов не позволит вам избежать наказания за это, как и ее работа.

Но даже если бы вы действительно могли пообещать то, что обещаете, система типов Swift не сможет это выразить.

Да, я думаю, что уже нашел хорошее компромиссное решение. Вместо того, чтобы бороться с системой, я буду использовать ее, чтобы получить еще больше функциональности для моей обертки. Я просто немного изменю семантику, переименовав «@Compact» в «@Exemptify». И не будет отфильтровывать "нули" в случае, если разработчик явно поставил "?" внутри "[]". В этом случае он будет только отфильтровывать ошибки декодирования. Если нет "?" внутри "[]" тогда "nils" сами по себе становятся ошибками декодирования и автоматически отфильтровываются. Ощущение очень последовательного поведения 🙂

Roman 26.04.2024 05:00

Я закончил свою работу и открыл исходный код. Буду признателен, если вы посмотрите. Надеюсь, вам будет интересно 🙂 gitlab.com/roman.kisliaченко/decodable-kit

Roman 27.04.2024 12:21

Лично я не большой поклонник оберток свойств для подобных вещей. Если у вас это работает, это здорово, но я считаю их слишком хрупкими для сложных систем. Ошибки легко выбросить, но трудно с ними справиться таким образом. Я немного рассказываю об этом и о том, как я предпочитаю это делать, здесь: youtube.com/watch?v=-k_vipGhugQ&t=340

Rob Napier 27.04.2024 15:52

Другие вопросы по теме