Development Tip

함수 호출에 Swift에서 매개 변수 이름이 필요한 이유는 무엇입니까?

yourdevel 2020. 11. 17. 21:11
반응형

함수 호출에 Swift에서 매개 변수 이름이 필요한 이유는 무엇입니까?


클래스에이 함수가 있습니다.

func multiply(factor1:Int, factor2:Int) -> Int{
    return factor1 * factor2
}

나는 이것을 사용하여 함수를 호출하려고합니다.

var multResult = calculator.multiply(9834, 2321)

문제는 컴파일러가 다음과 같이 보이기를 원한다는 것입니다.

var multResult = calculator.multiply(9834, factor2: 2321)

첫 번째 오류가 왜 발생합니까?


Swift 2.0 업데이트 : 이제 함수는 기본적으로 메소드와 동일하게 작동합니다.

  • 첫 번째 매개 변수에는 외부 이름이 없습니다.
  • 다른 매개 변수는 내부 이름과 동일한 외부 이름을 갖습니다.

그 외에는 #속기 구문이 사라 졌다는 점을 제외하면 아래 규칙이 계속 적용됩니다 .


보다 일반적인 대답은 다음과 같습니다. 함수는 클래스 외부에서 실제 함수로 정의 될 때와 메서드로 정의 될 때 다르게 작동합니다. 또한 init 메소드에는 특별한 규칙이 있습니다.


기능

이것을 정의한다고 가정합니다.

func multiply1(f1: Double, f2: Double) -> Double {
    return f1 * f2
}

매개 변수 이름은 여기 에서 함수에 국한 되며 함수를 호출 할 때 사용할 수 없습니다.

multiply1(10.0, 10.0)

함수를 호출 할 때 명명 된 매개 변수를 강제로 사용하려면 할 수 있습니다. 각 매개 변수 선언 앞에 외부 이름을 붙입니다. 여기에서의 외부 이름은 f1입니다 f1param.의 경우 로컬 이름이 외부 이름으로도 사용됨을 나타 내기 위해 f2접두어를 붙이는 축약 형을 사용합니다 #.

func multiply2(f1param f1: Double, #f2: Double) -> Double {
    return f1 * f2
}

그런 다음 명명 된 매개 변수를 사용해야합니다.

multiply2(f1param: 10.0, f2: 10.0)

행동 양식

방법은 상황이 다릅니다. 기본적으로 첫 번째 매개 변수를 제외하고 모두 이름이 지정됩니다. 이것이 있다고 가정하고 multiply1방법을 고려하십시오 .

class Calc {
    func multiply1(f1: Double, f2: Double) -> Double {
        return f1 * f2
    }
    func multiply2(f1param f1: Double, f2: Double) -> Double {
        return f1 * f2
    }
    func multiply3(f1: Double, _ f2: Double) -> Double {
        return f1 * f2
    }
}

그런 다음 두 번째 (및있는 경우 다음) 매개 변수의 이름을 사용해야합니다.

let calc = Calc()
calc.multiply1(1.0, f2: 10.0)

함수와 같이 외부 이름을 제공하여 첫 번째 인수에 대해 명명 된 매개 변수를 강제로 사용할 수 있습니다 (또는 로컬 이름과 #동일한 외부 이름을 사용하려는 경우 로컬 이름 접두사 ). 그런 다음 사용해야합니다.

calc.multiply2(f1param: 10.0, f2: 10.0)

마지막으로 _다음과 같이 명명 된 매개 변수를 사용하지 않고 메서드를 호출 할 것임을 나타내는 다른 다음 인수 대한 외부 이름을 선언 할 수 있습니다 .

calc.multiply3(10.0, 10.0)

상호 운용성 참고 : 주석 을 접두사 class Calc@objc사용하면 Objective-C 코드에서 사용할 수 있으며 다음 선언과 동일합니다 (매개 변수 이름 참조).

@interface Calc
- (double)multiply1:(double)f1 f2:(double)f2;
- (double)multiply2WithF1param:(double)f1 f2:(double)f2;
- (double)multiply3:(double)f1 :(double)f2;
@end

초기화 방법

init모든 매개 변수가 기본적으로 외부 이름을 갖는 메소드 의 경우 규칙이 약간 다릅니다 . 예를 들어 다음과 같이 작동합니다.

class Calc {
    init(start: Int) {}
    init(_ start: String) {}
}

let c1 = Calc(start: 6)
let c2 = Calc("6")

여기에서를 start:허용하는 오버로드에 대해 지정 Int해야하지만를 허용하는 오버로드 에 대해서는이를 생략해야합니다 String.

상호 운용성 참고 : 이 클래스는 다음과 같이 Objective-C로 내보내집니다.

@interface Calc
- (instancetype)initWithStart:(NSInteger)start __attribute__((objc_designated_initializer));
- (instancetype)init:(NSString *)start __attribute__((objc_designated_initializer));
@end

폐쇄

다음과 같이 클로저 유형을 정의한다고 가정합니다.

typealias FancyFunction = (f1: Double, f2: Double) -> Double

매개 변수 이름은 메소드의 이름과 매우 유사하게 작동합니다. 외부 이름을 _로 명시 적으로 설정하지 않는 한 클로저를 호출 할 때 매개 변수에 이름을 제공해야합니다.

예를 들어, 클로저 실행 :

fund doSomethingInteresting(withFunction: FancyFunction) {
    withFunction(f1: 1.0, f2: 3.0)
}

경험상으로, 당신이 그들을 싫어하더라도, 당신은 아마도 두 개의 매개 변수가 같은 유형을 가질 때마다 그것들을 명확하게하기 위해 명명 된 매개 변수를 계속 사용해야 할 것입니다. 나는 또한 그것의 좋은 또한 적어도 모든 이름을 주장 거라고 IntBoolean매개 변수를.


The parameter names in the function call are called keyword names, and they are trace their roots back to the Smalltalk language.

Classes and objects are often re-used from somewhere else, or form part of very large complex systems, and will not have active maintenance attention for long periods at a time.

Improving the clarity and legibility of the code is very important in these situations, as code often ends up as the only documentation, when developers are under deadline pressure.

Giving each parameter a descriptive keyword name allows maintainers to quickly see what the purpose of a function call by glancing at the function call, as opposed to delving deeper into the function code itself. It makes the implied meaning of the parameters explicit.

The latest language to adopt keyword names for parameters in function calls is Rust (link) - described as "a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety."

High uptime systems require greater code quality. Keyword names allow development and maintenance teams much more opportunity to avoid and to catch errors from sending the wrong parameter, or calling parameters out of order.

They can be wordy or terse, but Smalltalkers prefer wordy and descriptive to terse and meaningless. They can afford to be, because their IDE will do the bulk of such typing for them.


since you used calculator.multiply() in the example code I'm assuming this function is a method of the calculator object.

Swift inherits a lot of things from objective-c and this is one of them:

When in objective-c you would do (hypothetically):

[calculator multiply:@9834 factor2:@2321];

the equivalent in Swift is:

calculator.multiply(9834, factor2:2321);

Because your "multiply" function is a method, and like Objective-c, the parameters in methods are part of the name.

For example you can do this.

class Calculator {

    func multiply(factor1:Int, factor2:Int) -> Int{
        return factor1 * factor2
    }

    func multiply(factor1:Int, factor2:Int, factor3:Int) -> Int{
        return factor1 * factor2 * factor3
    }

}

Here there are two different methods, with different names, multiply(factor2) and multiply(factor2 factor3).

This rule only apply to methods, if you declare this like a functions outside of a class, then the function call don't require parameter name.


The reason is historical. This is how it worked in Smalltalk and it survived into its descendants. Squeak, Scratch, Blockly, Objective C and Swift.

The kiddy languages (Squeak, Scratch and Blockly) held to it, because beginning programmers tend to struggle with the arity and parameter order. That was the original reason why Smalltalk did it that way. I do not know why ObjC and Swift decided to adopt the convention, but they did.

Scratch example program


A note about passing in a method as an argument that returns no value:

func refresh(obj:Obj, _ method: (Obj)->Void = setValue) {
    method(element)
}
func setValue(obj:Obj){
    obj.value = "someValue"
}
refresh(someObj,setValue)

참고URL : https://stackoverflow.com/questions/24045890/why-does-a-function-call-require-the-parameter-name-in-swift

반응형