ResultBuilder学习笔记三:支持循环

本文介绍了如何在ResultBuilder的ConcatBuilder类中添加对循环的支持,包括处理不同数据类型(如整数、字符串和自定义类型Star)的循环输出,以及buildArray函数的实现。ResultBuilder的自动识别、调度和转换机制使得开发者无需关注细节。
摘要由CSDN通过智能技术生成

ResultBuilder学习笔记三:支持循环

我们在前面的博文中创建了一个非常简单的结果构建器ConcatBuilder,用于连接多个字符串,随后在后续博文中对之进行了扩展,使其可以支持自定义的输入数据类型,这个特性非常重要,它是DSL的基础。 这篇博文将继续对ConcatBuilder进行扩展,这次,我们讨论如何增加对循环的支持。

理解循环

ConcatBuilder 已经可以支持IntStringStar为输入。只要愿意,还可以增加更多的数据类型。但是,如果要使用它拼接1到10 个整数,该如何呢?,当然可以像下面这样:

 @ConcatBuilder var str:String  { 
                 1
                 2
                 3
                 4
                 5
                 6
                 7
                 8
                 9
                 10    
         }
         print( str ) 

但是,100个1000个整数呢,总不至于写100遍1000遍吧。 我们当然希望按下述循环方式:

 @ConcatBuilder var str:String  { 
            "春眠不觉晓"
            "处处闻啼鸟"
            for i in 1...100 
            {
                i    
            }
        }

这时,就需要ResultBuilder能够支持循环了。

支持循环

就像能够轻易支持多种输入数据类型一样,ResultBuilder也可以轻易支持循环, 只需要增加某种类型的buildArray函数即可。对于我们的场景, 在ConcatBuilder中像下面这样实现buildArray函数:

  static func buildArray(_ components: [String]) -> String {
            return components.joined(separator: "")
        }

再次运行,结果如下:

春眠不觉晓处处闻啼鸟123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100

没错,就这么简单!可能你已经注意到,为什么上述buildArray的输入参数不是整数而是字符串类型呢?答案是前面的buildExpression (_ component: Int) 函数,ResultBuilder会使用该函数将for-in循环中的每个整数首先转换成字符串,最终构成一个临时的字符串数组,然后再调用buildArray函数输出。这些识别,调度和转换都由ResultBuilder自动完成,我们无需关心。这也正是ResultBuilder设计精妙之处。

由于有了不同的buideExpression()函数,如下循环代码都可以正常工作:

 @ConcatBuilder var str:String  { 
            "春眠不觉晓"
            "处处闻啼鸟"
            //整数
            for i in 1...5
            {
                i 
            }
            //自定义类型
            for i in 1...3
            {
                Star(length:i)
            }
            //混合
            for i in 1...3
            {
                i
                Star(length:i)  
                "字符串\(i)"
            }
         }

ConcatBuilder 完整代码


  struct Star
  {
      let length:Int
      func getString()->String
      {
         return    Array(repeating:"*",count:length).joined()
       }
  }

 @resultBuilder
  struct ConcatBuilder {
        //最终输出
        static func buildBlock(_ components: String...) -> String {
            return components.joined(separator: "")
        }
        //支持整数输入
        static func buildExpression (_ component: Int) -> String {
            return "\(component)" 
        }
        //支持字符串输入
        static func buildExpression (_ component: String) -> String {
            return  component 
        }
        //支持自定义类型输入 
        static func buildExpression (_ component: Star) -> String {
            return  component.getString() 
        }
         //支持for-in循环
        static func buildArray(_ components: [String]) -> String {
            return components.joined(separator: "")
        } 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值