Swift 5, можно ли факторизовать задания - PullRequest
1 голос
/ 06 февраля 2020

Поскольку SwiftUI и его способность разбивать методы на квадратные скобки (благодаря компоновщику функций), вот так:

struct ContentView : View {
    var body: some View {
        VStack {
            Text("Hello World!")
            Text("by Purple Giraffe").color(.gray)
        }

    }

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

Мне было интересно, можно ли факторизовать назначения (с чем-то еще) в скобки, например:

struct AnimationViewConfiguration {
    var contentMode:Int = 0
    var mainTitle:String = "test"
    var subTitle:String = ""
    var alternativeSubtitle:String = ""
    var numberOfIteration:Int = 0
    var frameRate = 40
    var maximumSimultaneousParalax:Int = 5
    var minimumSimultaneousParalax:Int = 2
}

class someViewController: UIViewController {
    var mainBackgroundAnimationViewConfig = AnimationViewConfiguration()

    func animateBackground(_ useAlternativeBackground:Bool) {
        // The normal bulky way
        if useAlternativeBackground == false {
            mainBackgroundAnimationViewConfig.contentMode = 3
            mainBackgroundAnimationViewConfig.mainTitle = "Your super animation"
            mainBackgroundAnimationViewConfig.subTitle = "A subtitle anyway"
            mainBackgroundAnimationViewConfig.alternativeSubtitle = "Hey another one!"
            // partial or complete assignation
            // mainBackgroundAnimationViewConfig.numberOfIteration = 4
            mainBackgroundAnimationViewConfig.frameRate = 40
            mainBackgroundAnimationViewConfig.maximumSimultaneousParalax = 19
            mainBackgroundAnimationViewConfig.minimumSimultaneousParalax = 3
        } else {
            // The way I'd like it to be
            mainBackgroundAnimationViewConfig with { // imaginary `with` keyword
                contentMode = 0
                mainTitle = "Your super animation"
                subTitle = "A subtitle anyway"
                alternativeSubtitle = "Hey another one!"
                // partial or complete assignation
                // numberOfIteration = 4
                frameRate = 40
                maximumSimultaneousParalax = 19
                minimumSimultaneousParalax = 3
            }
        }
    }
}

Весь смысл в том, чтобы избежать повторения длинного имени переменной 15 раз, зная, что вы часто делаете это с уже 2,3,4 отступа (что делает еще более раздражающим , чтобы ухватиться за ).

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


Спасибо @matt за упоминание ключевого слова with, используемого для этой цели в других языках ~

Если его не существует, это приходит в swift5.1 +?

Разве вы не нашли бы это удобным?

Ответы [ 3 ]

3 голосов
/ 06 февраля 2020

Разве вы не нашли бы это удобным?

Нет. Что не так с

var test = Test(
                a : 3,  
                c : 4, 
                s : "hey" 
            )

для начала? Это оставляет другие свойства в их значениях по умолчанию.

Или, если вы измените позже,

test.c = 4
test.a = 3
test.s = "hey"

Или

(test.c, test.a, test.s) = (4, 3, "hey")

? Я не понимаю, насколько желателен другой слой сахара syntacti c. Есть языки, которые используют конструкцию with, которая выполняет то, что вы описываете (распределение свойств по одной ссылке вместо явной точечной записи каждый раз), но я не тоскую по этому в Swift.


Редактировать после редактирования: Если вы просто возражаете против длинного имени , скопируйте его в временную переменную с коротким именем, установите нужные свойства и скопируйте обратно:

var thisIsAReallyLongName = Whatever()
do {
    var temp = thisIsAReallyLongName
    temp.c = 4
    temp.a = 3
    temp.s = "hey"
    thisIsAReallyLongName = temp
}
1 голос
/ 07 февраля 2020

ближайший к тому, что вы хотите, это

struct Test {
    var a:Int = 0
    var b:Int = 0
    var s:String = ""
    mutating func update(_ closure: (inout Int, inout Int, inout String)->Void)->Void {
        closure(&a, &b, &s)
    }
}

var test = Test()

test.update { (a, b, c) in
    a = 10
    b = 20
    c = "Alfa"
}

или лучше (с поддержкой частичного обновления, а xcode дает вам то, что доступно)

struct Test {
    var a:Int = 0
    var b:Int = 0
    var s:String = ""
    mutating func update(_ closure: (inout Self)->Void)->Void {
        closure(&self)
    }
}

var test = Test()

test.update { (v) in
    v.a = 20
    v.s = "Alfa"
}

ОБНОВЛЕНИЕ: кто знает будущее?

Новые функции Swift

Вы можете вызывать значения типов, которые объявляют методы func callAsFunction, такие как функции. Синтаксис вызова является сокращением для применения забавных c методов callAsFunction.

struct Adder {
    var base: Int

    func callAsFunction(_ x: Int) -> Int {
      return x + base
    }
}

var adder = Adder(base: 3)
adder(10) // returns 13, same as 
adder.callAsFunction(10)

Вы должны включить забавные c метки аргументов callAsFunction на сайтах вызовов. Вы можете добавить несколько забавных c методов callAsFunction для одного типа и пометить их как изменяющиеся. func callAsFunction работает с бросками и повторными бросками, а также с замыкающими замыканиями. (59014791)

0 голосов
/ 06 февраля 2020

Я думаю, вы немного запутались. Здесь есть несколько концепций, и создатели функций не играют так хорошо, как вы думаете об этом.

Когда код помещается между двумя скобками, мы называем его блоком * 1004. * кода. Это хороший способ помочь в организации наших программ, потому что мы можем разместить связанные части последовательной логики c вместе. Наиболее распространенное место для появления блока кода - функция. Например, у меня есть функция, которая вычисляет зарплату пользователя:

func calculateSalary() {
   let monthly = 3500
   let yearlyTotal = monthly * 12
   print("Your salary is \(yearlyTotal)")
}

Тогда мы можем вызвать функцию, например, так:

calculateSalary()

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

let calculateSalary: () -> Void = {
   let monthly = 3500
   let yearlyTotal = monthly * 12
   print("Your salary is \(yearlyTotal)")
}

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

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

/** 
 * this is a stupid, pointless class (but it demonstrates
 * closures-as-parameters nicely)
 */

class SalaryCalculator {

    let closure: () -> Void

    init(closure: () -> Void) {
        self.closure = closure
    }

}

let calculator = SalaryCalculator(closure: {
   let monthly = 3500
   let yearlyTotal = monthly * 12
   print("Your salary is \(yearlyTotal)")
})

// call the closure!
calculator.closure()

Это также может быть написано с использованием синтаксиса trailing closure , где мы можем удалить метку аргумента, если замыкание является последним параметром для нашего инициализатора (или функции):

let calculator = SalaryCalculator {
   let monthly = 3500
   let yearlyTotal = monthly * 12
   print("Your salary is \(yearlyTotal)")
}

// call the closure!
calculator.closure()

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

Разработчики функций в SwiftUI используют этот же принцип, но он немного более тонкий и сложный, чем мне хотелось бы сейчас разобраться.

Итак, , чтобы ответить на ваш вопрос более прямо - если вы хотите разбить ваш код на более управляемые части, я бы создал class или struct, который инкапсулирует некоторые logi c, затем разбейте последовательно связанные вызовы на функции в этом новом class или struct. Я не уверен, почему вы хотели бы выполнять задания так, как показано в вашем вопросе, в действительности это не имеет смысла, особенно с инициализаторами Swift, обеспечивающими так много настраиваемости в любом случае.

...