swift 5.1 неправильно оценивают закрытие - PullRequest
1 голос
/ 19 января 2020

У меня проблема с оценкой одной строки кода, если я разделю ее на две строки, она работает, но в одной строке кода она просто оценивается как «новая» или «неправильная».

моя главная причина для того, чтобы задать этот вопрос, не в том, чтобы решить его, я знаю, что могу использовать скобки, чтобы решить его, и разбить его на две строки, но не хочу решать, я просто хочу знать, почему он оценивается так, и если есть решение для этого: какой-то параметр для исправления, в порядке, чтобы он работал в ОДНОЙ СТРОКЕ КОДА:

Вот код, который работает в две строки

working code

Вот код, который пытается сделать то же самое, но выдает ошибку, как вы можете видеть:

error code

полный код работающего и не работающего:

class ClosuresStack {

var dic = Dictionary<String,(()->String)->String >()

subscript(_ str:String)-> (()->String)->String {
get {
return dic[str]!

}
set {
dic[str] = newValue
}

}


}

func createClosuresStak() -> ClosuresStack {

   let cs =  ClosuresStack()
    func takesAClosureReturnA_string(_ closure:()->String) ->String {
        return closure() + " Two"
    }

    cs["C"] = takesAClosureReturnA_string

    return cs
}

let c = createClosuresStak()["C"]
let str = c{"One"}
print(str)  // print:  One Two



let c = createClosuresStak()["C"]{"One"} // error -->

Теперь я хочу как-то понять, как его изменить, чтобы он работал в ОДНОЙ СТРОКЕ КОДА: это означает, что оценка 'createClosuresStak()["C"]{"One"}' создаст замыкание после ["C"], а затем с этой точки записи g * {"One"} сделает полную оценку строки:

let c = createClosuresStak()["C"]{"One"}

делает 'c' String

, если это невозможно, мне нужно знать это слишком, tnx :)

ОБНОВЛЕНИЕ

tnx для комментариев, это помогает мне лучше понять проблему:

1) Я понимаю, что createClosuresStak()["C"]{"One"} остро пытается добавить строку 'One' в качестве другого параметра в суб-сценарий, и там из-за ошибки от компилятора было то, что не может подписываться (String, () -> String}, 'C 'как строка внутри [] и другой параметр {"One"} -> НО, разве это не какая-то ошибка? Разве то, что я использую [], очистить компилятор, чтобы он "понял", что Я хочу подписать строку, также с помощью умозаключения, что swift имеет,

2) теперь я все еще пытаюсь заставить этот синтаксис работать как есть, поэтому я пытаюсь изменить некоторые вещи, чтобы заставить его работать:

, поэтому я создал функцию, которая принимает строку и возвращает словарь типа: * 104 5 *, а затем попытаться так подписать его, и компилятор не выдаст ошибку таким образом:

func closuresDictionary(_ s:String) -> Dictionary<String,()->String> {

    var dic = Dictionary<String,()->String>()
    func foo()->String {
        return s + " Two"
    }
    dic["C"] = foo
    return dic
}




let c = closuresDictionary("One")["C"]{ "SomeString" }

c теперь является закрытием типа ()->String, которое не относится к строке, которую я поставил внутри, так что синтаксис работает, но результат ничего не делает.

когда я меняю тип возвращаемого словаря на другое закрытие: (String)->String вместо ()->String, я получаю ту же старую ошибку , что я пытаюсь подписать (String,(String)->String)

и мне нужна функция, которая возьмет строку внутри {} и создаст из нее что-то, означающее, что мне нужно подписать, чтобы вернуть закрытие (String)->String

кажется, что нет никакого способа сделать это

Я добавляю еще две картинки моей последней попытки, чтобы заставить эту строку кода в текущем синтаксисе работать

требуемый синтаксис работает, но результат не является результатом того, что ничего не происходит со строкой внутри {}:

the wanted syntax working but the outcome is not an outcome not doing any thing with the string inside the {}

та же ошибка, путем изменения функция до (String)->String

imageString">

1 Ответ

1 голос
/ 19 января 2020

Ваш пример:

let c = createClosuresStak()["C"]{"One"}

использует синтаксис трейлинг-закрытия .

Синтаксис трейлинг-закрытия работает с включением трейлинг-замыкания как дополнительный параметр к вызову функции. Подписание массива на самом деле является вызовом функции изнутри (функции, называемой subscript), и Swift пытается передать это замыкание в качестве второго параметра для вызова подписки, что объясняет ошибка:

Невозможно добавить значение типа 'ClosuresStack' с аргументом типа '(String, () -> String)'.

Другими словами, вы не можете передать оба "C" и закрытие {"One"} для функции подписки.


Существует как минимум 3 способа исправить это и все же поместить его в одну строку:

Опция 1: используйте явный вызов для передачи замыкания вместо использования синтаксиса конечного замыкания

Оберните замыкание в (), чтобы сделать вызов явным:

let c1 = createClosuresStak()["C"]({"One"})
print(c1)

Вариант 2: обернуть createClosureStak()["C"] в скобки

Это позволяет Swift знать, что подписка получает только "C" в качестве параметра и позволяет синтаксису замыкания замыкания работать должным образом:

let c2 = (createClosuresStak()["C"]){"One"}
print(c2)

Вариант 3: Добавить .self к Результат перед синтаксисом завершающего замыкания:

Это снова завершает вызов подписки и позволяет избежать путаницы.

let c3 = createClosuresStak()["C"].self {"One"}
print(c3)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...