WedX - журнал о программировании и компьютерных науках

Зачем мне нужны символы подчеркивания в Swift?

Здесь говорится: «Примечание: _ означает« Меня не волнует это значение ». ", но исходя из JavaScript, я не понимаю, что это значит.

Единственный способ получить эти функции для печати - использовать символы подчеркивания перед параметрами:

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(7, 3))
print(divmod(5, 2))
print(divmod(12,4))

Без подчеркивания я должен написать это так, чтобы избежать ошибок:

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(a: 7, b: 3))
print(divmod(a: 5, b: 2))
print(divmod(a: 12,b: 4))

Я не понимаю этого использования подчеркивания. Когда, как и почему я использую эти подчеркивания?

21.09.2016

Ответы:


1

В разных вариантах использования есть несколько нюансов, но обычно подчеркивание означает «игнорировать это».


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

func myFunc(label name: Int) // call it like myFunc(label: 3)

«label» - это метка аргумента, которая должна присутствовать при вызове функции. (А начиная с Swift 3, по умолчанию для всех аргументов требуются метки.) «Name» - это имя переменной для этого аргумента, которое вы используете внутри функции. Более короткая форма выглядит так:

func myFunc(name: Int) // call it like myFunc(name: 3)

Это ярлык, который позволяет использовать одно и то же слово как для метки внешнего аргумента, так и для имени внутреннего параметра. Это эквивалент func myFunc(name name: Int).

Если вы хотите, чтобы ваша функция могла быть вызвана без меток параметров, вы используете подчеркивание _, чтобы метка была пустой / игнорировалась. (В этом случае вам необходимо указать внутреннее имя, если вы хотите использовать параметр.)

func myFunc(_ name: Int) // call it like myFunc(3)

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

_ = someFunction()

Или, как в статье, на которую вы ссылаетесь, игнорировать один элемент возвращаемого кортежа:

let (x, _) = someFunctionThatReturnsXandY()

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

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

Точно так же при объявлении функции, которая принимает протокол или переопределяет метод суперкласса, вы можете использовать _ для имен параметров, чтобы игнорировать параметры. Поскольку протокол / суперкласс также может определять, что параметр не имеет метки, вы можете даже получить два символа подчеркивания подряд.

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

В некоторой степени связано с двумя последними стилями: при использовании конструкции управления потоком, которая связывает локальную переменную / константу, вы можете использовать _, чтобы игнорировать ее. Например, если вы хотите повторить последовательность без необходимости доступа к ее членам:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

Если вы привязываете случаи кортежа в операторе switch, подчеркивание может работать как подстановочный знак, как в этом примере (сокращено от одного в Язык программирования Swift):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

И последнее, что не совсем связано, но которое я включу, поскольку (как отмечено в комментариях), похоже, оно приводит людей сюда: подчеркивание в идентификаторе - например, var _foo, func do_the_thing(), struct Stuff_ - ничего особенного для Swift не имеет, но имеет несколько применений среди программистов.

Подчеркивание в имени - это выбор стиля, но не предпочтительный в сообществе Swift, которое имеет строгие соглашения об использовании UpperCamelCase для типов и lowerCamelCase для всех других символов.

Добавление префикса или суффикса к имени символа с помощью подчеркивания - это соглашение о стилях, которое исторически использовалось для различения частных / предназначенных только для внутреннего использования символов от экспортируемого API. Однако в Swift для этого есть модификаторы доступа, поэтому это соглашение обычно рассматривается в Swift как неидиоматическое.

Несколько символов с префиксом двойного подчеркивания (func __foo()) скрываются в глубинах SDK Apple: это символы (Obj) C, импортированные в Swift с использованием атрибута NS_REFINED_FOR_SWIFT. Apple использует это, когда они хотят сделать "более Swifty" версию (Obj) C API - например, , чтобы преобразовать метод, не зависящий от типа, в общий метод. Им необходимо использовать импортированный API, чтобы усовершенствованная версия Swift работала, поэтому они используют __, чтобы сохранить ее доступность, скрывая ее от большинства инструментов и документации.

21.09.2016
  • @rickster, каково значение подчеркивания в начале метода, как этот - ›func _copyContents (инициализация ptr: UnsafeMutableBufferPointer ‹Element›) -› (Iterator, UnsafeMutableBufferPointer ‹Element› .Index)} из протокола Sequence. 19.05.2017
  • @devgr: Совершенно не связано, поэтому я бы рекомендовал задать отдельный вопрос. 19.05.2017
  • Конечно, я поставлю отдельный вопрос. 19.05.2017
  • Спасибо, что ничего не назначаете для возврата функции. Это было то, что я искал. 12.01.2018

  • 2

    В дополнение к принятому ответу, один из вариантов использования _ - это когда вам нужно написать длинное число в коде

    Более читаемый номер

    ???? Это непросто для восприятия человеком:

    let x = 1000000000000
    

    ✅ Вы можете добавить _ в число, чтобы сделать его более читабельным:

    let x = 1_000_000_000_000
    

    Интерфейсы с пониженной оценкой

    Вы можете столкнуться с тем, что где-нибудь в Swift интерфейсы начинаются с _. Хотя технически они объявлены public, но начинаются с подчеркивания, НЕ считаются частью открытого интерфейса этого пакета. Мы можем удалить или изменить их в любом выпуске без предварительного уведомления, включая незначительные точечные выпуски.

    Например @_exportedImport или другие примеры здесь, в официальном репозитории Swift Collections

    ⚠️ Просто не используйте их, иначе вам придется вручную отслеживать изменения.

    01.11.2019


    4
    func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
        return (a / b, a % b)
    }
    
    func divmod(a: Int, b:Int) -> (Int, Int) {
        return (a / b, a % b)
    }
    

    _ - это имя-заполнитель для имени параметра. В вашем примере вы вызываете их по-другому, во второй функции вам нужно написать имя параметра a: 1.

    Соглашение об именах функций Swift - funcName(param1:param2:), и для создания имени функции требуется _ в качестве заполнителя.

    В имени имя

    divmod(_:_:)
    

    В то время как второй

    divmod(a:b:)
    
    21.09.2016
    Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: wedx@cp9.ru