在函数内创建闭包时出错

时间:2018-05-30 00:58:11

标签: swift

非常感谢你的回复。确实,我正在学习在这个阶段编写闭包。实际上我在某处读到了关于集合的“forEach”函数,它将一个参数作为参数(即闭包)。

forEach的语法是“Void forEach(body:(Int)throws - > Void)重新抛出”

我要做的是使用单个参数(即闭包)编写一个类似的函数,它将计算一个数字的因子,因此我们可以打印该数字的因子。我不想将该数字作为该函数的第二个参数传递。

我理解forEach是Collections类的成员函数,它逐个处理每个元素。所以它从数组中获取元素。类似地,我在我的类中创建了一个私有属性(factorialNumber)(我可以使用公共函数“setFactorialNumber”设置其值)。现在我正在尝试为我的类创建一个公共函数(factorial),它只有一个参数(即闭包),它将在内部使用“factorialNumber”属性的值,并计算我们可以从外部打印的那个数字的阶乘当我们从其他代码调用该函数时。

以下是我的班级..

public class MyArray {
    private var factorialNumber = 0

    public func setFactorialNumber(factorialNumber value: Int) {
        factorialNumber = value
    }

    public func factorial(body closure: (Int) -> Void) -> Void {
        var outputString: String?
        var result = 1

        if factorialNumber <= 0 {
            outputString = nil
        } else {
            outputString = ""
            while(factorialNumber >= 1) {
                if factorialNumber == 1 {
                    outputString = outputString! +  "\(factorialNumber) = \(result)"
                    break
                } else {
                    outputString = outputString! + "\(factorialNumber) x "
                }
                result = result * factorialNumber
                factorialNumber -= 1
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

闭包基本上是一个想要被调用的函数 在您的情况下,您正在定义它,但您没有使用它。

我在factorial(body:)中看到的问题:

  1. 你应该至少执行一次关闭。
    即在某个时间点执行以下操作:

    closure(someValue)
    
  2. 您似乎维持outputString,这看起来就像您想要关闭的东西。
    在这种情况下,您的关闭应采用String而不是Int

    func factorial(body closure: (String?) -> Void) -> Void { //...
    
  3. 最后,这就是函数应该是这样的:

    func factorial(body closure: (String?) -> Void) -> Void {
        var outputString: String?
    
        //...your factorial logic as:
        if factorialNumber <= 0 {
            outputString = nil
        } else {
            outputString = ""
            while(factorialNumber >= 1) {
                if factorialNumber == 1 {
                    outputString = outputString! +  "\(factorialNumber) = \(result)"
                    break
                } else {
                    outputString = outputString! + "\(factorialNumber) x "
                }
                result = result * factorialNumber
                factorialNumber -= 1
            }
        }
    
        //Finally, the closure call
        closure(outputString)
    }
    

    看着你的结构,它的用法是:

    let factorial = MyArray()
    factorial.setFactorialNumber(factorialNumber: 20)
    factorial.factorial { (result) in
        print(result)
    }
    

    它的输出是:

      

    20 x 19 x 18 x 17 x 16 x 15 x 14 x 13 x 12 x 11 x 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 = 2432902008176640000

    注意:您的课程是Crashable

    上述答案对于您的问题的特定背景是足够的,但要适当注意:

    1. 您的逻辑使用Int,因此高于20的数字会导致代码崩溃

      <强>解决方案:

      • 使用Double
      • 保护您的逻辑不会因输入太大而无法处理
      • 而崩溃
    2. 如果您不是setFactorialNumber(factorialNumber:),并直接跳转到致电factorial(body:),您的代码就会崩溃。

    3. 改进:?

      • 将类名从MyArray更改为FactorialFinder或其他
      • 在此课程中添加init

        init(with number: Int) {
            self.factorialNumber = number
        }
        
      • 既然我们有自定义初始化,请将默认init设为私有:

        private init() {}
        
        • 所以这样的事情是不可能的FactorialFinder()
        • FactorialFinder(with:)成为初始化此类的唯一方法

答案 1 :(得分:0)

你的第一个例子很好地暗示了你的问题:

factorial {
 print("Factorial is: \($0)")
}

您希望此功能打印的确切文字是什么? “因子是:100”,“因子是:200”?

这是一个技巧问题,因为答案是不可知的:你的函数不接受一个数来计算阶乘,它只接受一个尾随闭包来定义如何处理结果。