2016-04-08 15:28:04 a981583536 阅读数 116
1.做了一个函数程序例子,函数的表达效果就是这个函数的评价,避免改变状态和可变数据?什么鬼?
陈述性编程包括函数+数据流图+?响应式编程 然后命令式编程里面有面向对象编程.
swift是一个响应式函数,就是他是面向对象和过程的两种编程方式的合体。
后面是swift同样一段代码会产生不同的结果。
弱类型?强类型?告诉我们除非不得已不要使用继承(父类的属性方法等给子类继承),用enum,struct,extension
(告诉我们用枚举,延展,结构体)。。。好难懂
2018-07-28 04:15:47 weixin_34205076 阅读数 14

上一篇文章里,我们已经完成了 AST 的创建。接下来我们开始具体的来定义 Parser,并且会给出一个通用的单字符 Parser 的实现。如果有疑问,可以对照着项目代码的实现一起阅读。

定义 Parser 的正确姿势

根据本例中的需求,所谓 Parser,就是完成接受字符串,并解析成 AST 结构的过程。用一个函数来定义它,就是:

Parser : String -> AST
复制代码

因为解析过程是逐步的解析,并不能一瞬间就完成所有的解析,为了表示逐步的思想,我们得出一个改进版本的 Parser:

Parser : String -> (AST, String)
复制代码

输入的是一个 String,输出的是一个 tuple,前面是解析出的 AST。后面的 String 代表解析完前面的 AST 后还剩下的 String。

继续细化,既然是逐步解析的,那即便是一个最普通的 AST,比如之前的 Exp.Constant(1234),也是得先解析出一个个的单个数字,再将其组合成一个整数,然后再形成 AST。为了表示更加细化的,比如解析单个数字这样的形式。我们继续改进:

Parser : String -> (a,String)
复制代码

和上一个版本相比,我们把 AST,换成了a, a是泛型变量,代表任意类型。也就是说 Parser 解析的结果可以是character, string, Int, AST 等等。

现在看来,我们已经有了看起来不错的形式。现在问题来了,我们如何来表示解析失败呢?返回某种特殊的 (ERROR, String) ? 还是返回(a,"") ? 为了表示解析失败,我们把结构修改如下:

Parser : String -> [(a,String)]
复制代码

和上一个版本相比,我们把返回一个 tuple 改为了返回一个 tuple 的 list。这样就可以用空 list [] 来表示解析失败。 如果解析成功,就返回一个包含单个 tuple 的 list。 至于为何不用上述两种方法,读者可以带着这个问题看下来的文章。

在 Swift 中定义 Parser

根据我们 Parser 定义的形式,不能想象所谓 Parser 的类型就是一个函数。为了方便书写,我们把它放在结构体中。

函数式编程一个重要的思想方法就是从类型开始思考代码的意义。

struct Parser<a>{
    let p : String -> [(a,String)]
}
复制代码

来审视 Parser 结构:

  • 首先需要一个泛型参数a,代表这个 Parser 解析的结果的类型。
  • 有一个成员变量, p 其类型是一个函数,该函数接受一个 String 为输入,返回一个[(a,String)]

实现第一个 Parser

我们从最简单的例子,比如要定义一个解析字符"H"的 Parser。什么意思呢? 就是这个 parser 会尝试去字符串里解析一个字符 H 出来(从字符串的开头开始),如果解析成功,则返回[("H",剩下的字符串)], 如果解析失败则返回[].

换句话来说,这个 Parser 会检测字符串首字母是否是 H,如果是则成功,否则就失败。

let par1 = Parser<Character> { x in
    guard let head = x.characters.first where head == "H" else{
        return []
    }
    return [("H",String(x.characters.dropFirst()))]
}
复制代码

要创建一个 Parser,首先就是要用结构体的构造器并指定泛型的类型。 比如Parser<Character>(...)。 因为结构体只有一个成员且这个成员是一个函数类型,所以...的部分要传入的就是一个闭包。也就是Parser<Character>({....}),又因为 Swift 的尾闭包特性,闭包可以从()移动到外面,所以构造 Parser 的最终形式就是Parser<Character>{x in ...}, 上面的代码便是这样的结构,最终把创建好的Parser 赋值给了变量 par1

现在我们来看,创建这个 Parser 的闭包长什么样。我们都知道这个闭包是String->[(a,String)]的类型,我们把输入的参数命名为x,代表要解析的 String,我们通过一个 guard 来看他的首字母是否是 H,如果不是则解析失败,返回[],否则就构造[(a,String)]返回。这里的 a,就是字符"H", String 则是去除首字母剩下的字符串(因为解析成功的话,输入字符串对应的部分要被消费掉)。

测试一下。

print(par1.p("HELLO WORLD"))
print(par1.p("NIHAO"))
复制代码

输出:

[("H", "ELLO WORLD")]
[]
复制代码

我们分别用 par1去尝试解析了两个字符串,第一个首字母是 H 所以解析成功,返回了 H 和剩下的”ELLO WORLD“组成的tuple,另一个解析失败了。

Parser 生成器

仔细想一下,我们刚才的 par1,其实并没什么卵用。现在尝试修改一下形式,来让它稍微有点用:

func parserChar(c : Character) -> Parser<Character>{
    return Parser { x in
        guard let head = x.characters.first where head == c else{
            return []
        }
        return [(c,String(x.characters.dropFirst()))]
    }
}
复制代码

我们定义了一个函数,parserChar,依然是从他的类型来分析他的工作原理。它接受一个单个字符,然后返回一个 Parser,相当于parserChar是一个“解析单个字符 Parser ” 的构造器,比如我们调用 parserChar("E")就能生成一个解析字符E的 Parser。这看起来似乎就是我们刚才 hardcode 版本实现的 parser 通用多了。

按照惯例,我们还是来测试一下:

let result = parserChar("H").p("HELLO WORLD")
print(result)
let result1 = parserChar("E").p(result[0].1)
print(result1)
复制代码

输出:

[("H", "ELLO WORLD")]
[("E", "LLO WORLD")]
复制代码

这里我们把第一个 parser 的结果,喂给了第二个 parser。然后第二个 parser 在此基础上成功解析出了字符“E”。

抽象无止境

还是在单字符 Parser 的前提下。在解析中,我们往往解析的不仅仅是某个特定的字符,而是某一类字符,比如解析所有的数字字符,或者运算符字符。对于这样的需求,我们第一次抽象的结果parserChar似乎就不够用了。我们来稍微修改一下:

func satisfy(condition : Character -> Bool) -> Parser<Character>{
    return Parser { x in
        guard let head = x.characters.first where condition(head) else{
            return []
        }
        return [(head,String(x.characters.dropFirst()))]
    }
}
复制代码

为了更通用,我们把函数的名字改为了satisfy, 其实内部实现都差不多。区别就是现在不再是接受一个单个字符的参数,而是接受一个函数condition, 什么样的函数呢? 还是从他的类型看起:Character->Bool ,代表判断某个字符是否符合条件,符合返回 true,否则返回 false。相当于我们可以通过这个condition 函数,来定义字符的范围。然后在实现的时候,我们不再是用首字母去做某种判等,而是把首字母传给 condition 函数,让这个函数来告诉 Parser 首字母是否符合条件。

比如,假设存在isDigit(Character) -> Bool这样一个函数,来判断一个字符是否是数字。 我们就可以通过 satisy(isDigit) 来构造一个识别任何数字的 Parser。 让我们来试一下:

首先实现 isDigit

func isDigit(c : Character) -> Bool{
    let s = String(c)
    return Int(s) != nil
}
复制代码

然后通过satisfy构造 Parser

let pNum = satisfy(isDigit)
print(pNum.p("abcde"))
print(pNum.p("1asd"))
print(pNum.p("6asd"))
print(pNum.p("12asd"))
复制代码

输出:

[]
[("1", "asd")]
[("6", "asd")]
[("1", "2asd")]
复制代码

isDigit实现很简单就不讲了,后来我们通过satisfy构造了一个识别任何数字的 Parser pNum, 然后分别尝试解析了4个字符串,第1个并不包含数字,所以失败了。后面分别都解析出了不同的数字。至少最后一个例子里后面的2为什么没有一起解析出来,是因为目前还没有实现多字符的逻辑。

整理一下今天的任务

今天说了很多,其实在 Parser 的实现上的进展来看,我们只是增加了如下代码:

struct Parser<a>{
    let p : String -> [(a,String)]

}

func isDigit(c : Character) -> Bool{
    let s = String(c)
    return Int(s) != nil
}

func satisfy(condition : Character -> Bool) -> Parser<Character>{
    return Parser { x in
        guard let head = x.characters.first where condition(head) else{
            return []
        }
        return [(head,String(x.characters.dropFirst()))]
    }
}
复制代码

PS:

  • 函数式编程前期理解起来可能会比较绕,但熟悉了以后很容易就能写出非常简洁的代码。
  • satisfy 其实非常强大。可多试试看配合不同的 condition 来产生不同的 Parser

有多强大?可以下载完整项目, 先查看一下都是被怎么用的。


想看更多内容? 可以关注我的知乎

2018-02-09 14:54:36 ZY_FlyWay 阅读数 1606

Swift 4.0访问权限关键字

    目前有 open  public  internal  fileprivate  private 这五个访问权限,都可以修饰属性和方法。下面通过例子来分析五个访问权限的使用。


不同点分析:

  • 是否可以被子类继承访问
  • 同文件不同类下是否可以访问
  • 不同文件是否可以被访问
  • 不同组件下是否可以被访问

1、private

被private修饰的属性和方法  ,只可以在该类下使用(extension可使用,因为是同类。)

例如:下面图片,即使在同文件下不同类也是不能调用的,继承的话子类也不能调用。



2、fileprivate

      fileprivate和private 想比较一下,区别一目了然,相同文件下是可以调用的,其他和private一样。

 

3、internal 

 

      默认权限,如果项目没有进行组件化开发,整个APP项目内都是可以访问的。

 

4、public

 可以被任何人访问,但是在其他module中不可以被继承和重写,在当前module内可以


5、open  


  最高权限,可以被任何module和文件访问和继承重写


2018-04-23 09:13:07 wide288 阅读数 249

手上李刚的第三本书。都是疯狂讲义系列。
2015年1月出的,2016年他又出了本《疯狂讲义IOS提高篇》,我就没买了。
暂时也不准备买了。
而这本书也有第二版了。出版时间:2016-03-01。我读的是第一版。这里的笔记也是基于第一版写的。

目录
第1章,语言与开发环境
第2章,基本数据类型
第3章,运算符与表达式
第4章,流程控制
第5章,集合
第6章,函数
第7章,面向对象(上)
第8章,面向对象(下)
第9章,泛型
第10章,运算符函数
第11章, Foundation 框架详解
第12章,使用 swift 开发 ios 应用
第13章,混编
第14章,俄罗斯方块

这个没有太细看。真的买的书看的比借的要差一些。
呵呵。
还有就是 object-c 的还是主流 swift 还没有在生产环境应用起来。
不是没有,是大多项目还是 object-c 的,需要时间。
所以我这还不是生产的人更是没有紧迫感了。

2015-05-26 10:25:00 weixin_30909575 阅读数 3

swift自从2014年6月之后出世,就赢得了广大ios开发者的喜爱.它融合了目前主流语言的相关特性,在它身上能看到几乎所有高级语言所拥有的特性.并且引入了类似C++的lamda,java的匿名函数的闭包.作为具有动态特征的静态语言,可以说编译器做了很大的贡献.截止到目前,我个人感觉写的(或者翻译的)比较权威的书籍有老码和cocoachina翻译的官方的pdf版的swift编程语言指南,swift和oc及c的混编,再者就是我们的"喵神"的著作,switf开发的100个tips,非常的实用和精炼.这几本书我已放在博客上,有用的着的同学,自取哦.

转载于:https://www.cnblogs.com/joykang/p/4529929.html

没有更多推荐了,返回首页