前缀表达和二分表达可用来在简短语句中使用运算符。简单表达从概念上讲是获取值的最简单方式。后缀表达和前缀表达和二分表达相似,都可以让你建立更为复杂的表达方式;例如函数调用和成员获取等。我们将在本章节中详细解释每种表达方式。
GRAMMAR OF AN EXPRESSION expression → prefix-expressionbinary-expressionsopt expression-list → expression expression,expression-list
作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:130 595 548,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)
除了上面的标准库运算符,当一个变量作为参数在函数调用中传递时,& 可以放在变量名前面,这种参数称为In-Out Parameters。
GRAMMAR OF A PREFIX EXPRESSION prefix-expression → prefix-operatoroptpostfix- expression prefix-expression → in-out-expression in-out-expression → &identifier
右移
大于
= 大于等于
= 右移并赋值
注意: 在解析的时候,二分运算符组成的表达式将被拆解为一个列表的形式。这个列表将被转化为一个序列来计算。例如,二分表达式的语法: binary-expression → binary-operatorprefix-expression binary-expression → assignment-operatorprefix-expression binary-expression → conditional-operatorprefix-expression binary-expression → type-casting-operator binary-expressions → binary-expressionbinary-expressionso2 + 3 * 5最开始被理解为一个有五个元素的列表:2,+,3,*,5。然后才转换为序列的形式(2+(3*5))。
1. (a, _, (b, c)) = ("test", 9.45, (12, 3))
2. // a 是 "test", b 是 12, c 是 3, 9.45 被自动忽略了。
赋值运算符没有返回值。
1. class SomeSuperType {}
2. class SomeType: SomeSuperType {}
3. class SomeChildType: SomeType {}
4. let s = SomeType()
6. let x = s as SomeSuperType
7. // 成功,则返回值 SomeSuperType
8. let y = s as Int
9. // 失败,编译期错误
10. let z = s as SomeChildType
11. // 可能在运行期失败,返回值类型为SomeChildType?
对编译器来说,使用 as来确定类型 和 类型声明 具有相同的作用。下面的例子可以说明:
1. let y1 = x as SomeType // 使用as表明类型
2. let y2: SomeType = x // 使用类型声明
is操作符将字运行时检查表达式是否为特定类型。如果是则返回真(true),否则返回假(false)。
在编译期检查的结果必须不确定,下面的例子是不合法的:
1. “hello" is String
2. "hello" is Int
更多关于类型转换的解释和例子请参考 [类型转换](for linkage)。
GRAMMAR OF A PRIMARY EXPRESSION primary-expression → identifiergeneric-argument-clauseopt primary-expression → literal-expression primary-expression → self-expression primary-expression → superclass-expression primary-expression → closure-expression primary-expression → parenthesized-expression primary-expression → implicit-member-expression primary-expression → wildcard-expression
init和subscript中,它是关键字的名字;在文件的顶层,它是当前模型名。
数组的文字声明是一个包含有序值的集合。其结构如下:
[value1, value2, ... ]
数组内最后一个表达式可以跟句号。一个空数组声明可以用一个空的中括号代表([])。数组值的类型为T[],T代表数组内部表达式的类型。如果其中的元素类型不统一,T代表他们最小超类。
字典的文字声明是一个有键值对的无序集合。它有如下表达:
[key:value1, key:value2, ... ]
字典内最后一个表达式可以跟句号。一个空字典的声明是中括号内加一个冒号([:])以此和空数组的表达形式区分。
字典的类型为Dictionary<keytype, ValueType>,keytype是键的类型,ValueType是其对应值的类型。如果字典有多种类型,keytype和ValueType使他们代表值类型的最小超类。
GRAMMAR OF A LITERAL EXPRESSION literal-expression → literal literal-expression → array-literal dictionary-literal literal-expression → FILE LINE COLUMN FUNCTION array-literal → [array-literal-itemsopt] array-literal-items → array-literal-item,opt array-literal-item,array-literal-items array-literal-item → expression dictionary-literal → [dictionary-literal-items] [:] dictionary-literal-items → dictionary-literal-item,opt dictionary-literal-item,dictionary-literal-items dictionary-literal-item → expression:expression
self是对当前类型或当前类的实例的一种显式引用。其使用方法如下:
1. self
2. self.`member name`
3. self[`subscript index`]
4. self(`initializer arguments`)
5. self.init(`initializer arguments`)
在构造器,子脚本或实例方法中,self指当前实例的引用。在静态方法或类方法中,self指当前类的引用。
self用于当同一作用域存在同名变量的时候来明确指代以访问成员变量,例如临时变量与成员变量同名的情况:
1. class SomeClass {
2. var greeting: String
3. init(greeting: String) {
4. self.greeting = greeting
5. }
6. }
在一个mutating类型值的方法中,你可以为一个新的实例赋值为self,例如:
1. struct Point {
2. var x = 0.0, y = 0.0
3. mutating func moveByX(deltaX: Double, y deltaY: Double) {
4. self = Point(x: x + deltaX, y: y + deltaY)
5. }
6. }
GRAMMAR OF A SELF EXPRESSION self-expression → self self-expression → self.identifier self-expression → self[expression] self-expression → self.init
1. super.`member name`
2. super[`subscript index`]
3. super.init(`initializer arguments`)
第一种形式可以获取超类的成员。第二种形式可以获取超类的角标方法实现。第三种形式可以用来访问超类的初始化器。
子类使用超类来实现他们自己的成员,子脚本和初始化器。
GRAMMAR OF A SUPERCLASS EXPRESSION superclass-expression → superclass-method-expression superclass-subscript-expression superclass-initializer-expression superclass-method-expression → super.identifier superclass-subscript-expression → super[expression] superclass-initializer-expression → super.init
1. { (`parameters`) -> `return type` in
2. `statements`
3. }
这里的参数和形式与函数的声明的形式相同。
它具有一些更简洁的写法:
in关键字;如果无法推断其类型,则会产生编译时错误。
1. myFunction { (x: Int, y: Int) -> Int in return x + y }
2. myFunction { (x, y) in return x + y }
3. myFunction { return $0 + $1 }
4. myFunction { $0 + $1 }
关于闭包在函数中传参的问题可参考 [函数调用的使用](for link)。
使用抓取列表(capture list),闭包可以显式的得到特定值。抓取列表内容由中括号括起,由逗号分隔,后面是参数列表。当你使用抓取列表时,即使你省略参数名,参数类型和返回值类型,你也必须写in关键字。
抓取列表的每个入口可以标明weak或unowned来抓取值的弱引用或无主引用。
1. myFunction { print(self.title) } // strong capture
2. myFunction { [weak self] in print(self!.title) } // weak capture
你也可以向其中的非匿名值加入判断表达,当闭包执行时,将对表达式做出判断,并使用特定的引用强度抓取。例如:
1. // Weak capture of "self.parent" as "parent"
2. myFunction { [weak parent = self.parent] in print(parent!.title) }
更多闭包的信息和实例,请参考[闭包](for link)。
GRAMMAR OF A CLOSURE EXPRESSION closure-expression → {closure-signatureoptstatements} closure-signature → parameter-clausefunction-resultoptin closure-signature → identifier-listfunction-resultoptin closure-signature → capture-listparameter-clausefunction-resultoptin closure-signature → capture-listidentifier-listfunction-resultoptin closure-signature → capture-listin capture-list → [capture-specifierexpression] capture-specifier → weak unowned unowned(safe) unowned(unsafe)
member name
例如:
1. var x = MyEnumeration.SomeValue
2. x = .AnotherValue
GRAMMAR OF A IMPLICIT MEMBER EXPRESSION implicit-member-expression → .identifier
identifier 1: expression 1, identifier 2: expression 2,...)
利用括号表达式我们可以为函数调用传参。如果括号内只有一个值,其括号表达式的类型即为此值的类型。例如(1)的类型是Int,不是(Int)。
GRAMMAR OF A PARENTHESIZED EXPRESSION parenthesized-expression → (expression-element-listopt) expression-element-list → expression-element expression-element,expression-element-list expression-element → expression identifier:expression
x,20则被忽略。
(x, _) = (10, 20)
GRAMMAR OF A WILDCARD EXPRESSION wildcard-expression → _
GRAMMAR OF A POSTFIX EXPRESSION postfix-expression → primary-expression postfix-expression → postfix-expressionpostfix-operator postfix-expression → function-call-expression postfix-expression → initializer-expression postfix-expression → explicit-member-expression postfix-expression → postfix-self-expression postfix-expression → dynamic-type-expression postfix-expression → subscript-expression postfix-expression → forced-value-expression postfix-expression → optional-chaining-expression
function name(argument value 1, argument value 2)
函数名可以以任意具有函数类型的名字来命名。
如果函数声明中定义了参数名,那么函数调用时,参数名必须在参数值前面,并用冒号分开,示例如下:
function name(argument name 1: argument value 1, argument name 2: argument value 2)
函数的调用时可以在闭合括号的后面紧跟一个闭包后缀。这个后缀代码块也是这个函数的后加的参数。下面的两个函数调用等效:
// someFunction 的参数列表由一个参数x和一个闭包组成 someFunction(x, {$0 == 13}) someFunction(x) {$0 == 13}
如果闭包是唯一参数,小括号可以省略。
// someFunction 只有一个参数 myData.someMethod() {$0 == 13} myData.someMethod {$0 == 13}
GRAMMAR OF A FUNCTION CALL EXPRESSION function-call-expression → postfix-expressionparenthesized-expression function-call-expression → postfix-expressionparenthesized-expressionopttrailing-closure trailing-closure → closure-expression
expression.init(initializer arguments)
初始化器的调用方法与函数调用相同,但与函数不同的是,初始化器不是一个值。例如:
1. var x = SomeClass.someClassFunction // 正确 var y = SomeClass.init // 错误
你也可以使用初始化器来调用超类的初始化器。
1. class SomeSubClass: SomeSuperClass { init() { // subclass initialization goes here super.init() } }
3. GRAMMAR OF AN INITIALIZER EXPRESSION
5. initializer-expression → postfix-expression.init
expression.member name
有名成员变量可作为类的声明的一部分或其拓展。例如:
1. class SomeClass {
2. var someProperty = 42
3. }
4. let c = SomeClass()
5. let y = c.someProperty
6. // Member access
元组的命名是用数字由零开始按顺序隐式命名的。例如:
var t = (10, 20, 30) t.0 = t.1 // 现在 t 是 (20, 20, 30)
组件成员可以获取其最顶层声明。
GRAMMAR OF AN EXPLICIT MEMBER EXPRESSION explicit-member-expression → postfix-expression.decimal-digit explicit-member-expression → postfix-expression.identifiergeneric-argument-clauseopt
expression.self
type.self
第一种形式得到表达式的值。例如x.self就是x值。
第二种形式将获得类型的值。利用这种形式可以以值的形式获得类型。例如。SomeClass.self就是SomeClass类,你可以将其传递给接受类类型参数的函数或方法。
GRAMMAR OF A SELF EXPRESSION postfix-self-expression → postfix-expression.self
expression.dynamicType
表达式不能是类名。完整的dynamicType表达式获得表达式的运行时类名值。如下例:
1. class SomeBaseClass {
2. class func printClassName() {
3. println("SomeBaseClass")
4. }
5. }
6. class SomeSubClass: SomeBaseClass {
7. override class func printClassName() {
8. println("SomeSubClass")
9. }
10. }
11. let someInstance: SomeBaseClass = SomeSubClass()
12. // someInstance的编译时类型是SomeBaseClass , 但是
13. // someInstance的运行时类型是SomeSubClass
14. someInstance.dynamicType.printClassName()
15. // 打印 "SomeSubClass"
GRAMMAR OF A DYNAMIC TYPE EXPRESSION dynamic-type-expression → postfix-expression.dynamicType
expression[index expressions]
为了获取亚脚本表达式的值,将亚脚本表达方式作为参数调用角标的get方法。当然,为了设置它的值,亚脚本的set方法也用同样的方式调用。
更多关于亚脚本声明,请参见[亚脚本声明。
GRAMMAR OF A SUBSCRIPT EXPRESSION subscript-expression → postfix-expression[expression-list]
expression!
expression.?
后缀?将以可选值的形式返回其参数。
在后缀表达中,自判断链接的取值方式很特别。如果自判断链接为空,后面其他的表达式不会被执行且整个表达式返回空。如果自判断链接结果不是空,表达式将被拆包并用继续执行余下的后缀表达式。不论何种情况,后缀表达式的值都是一个可选值类型。
如果自判断链接是嵌套的,只返回最外层的的可选值类型。在下面的例子中,如果c不是nil,它的值将被拆包,并用以获得.property 和 .performAction()的值。整个c?.property.performAction()是可选值类型。
var c: SomeClass?
var result: Bool? = c?.property.performAction()
下面的例子则示意了不使用自判断链接的情形。
1. if let unwrappedC = c {
2. result = unwrappedC.property.performAction()
3. }
GRAMMAR OF AN OPTIONAL-CHAINING EXPRESSION optional-chaining-expression → postfix-expression?
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
@raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://
我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
这是一个例子:s="abcd+subtext@example.com"s.match(/+[^@]*/)Result=>"+subtext"问题是,我不想在其中包含“+”。我希望结果是“潜台词”,没有+ 最佳答案 您可以在正则表达式中使用括号来创建匹配组:s="abcd+subtext@example.com"s=~/\+([^@]*)/&&$1=>"subtext" 关于ruby-正则表达式-排除一个字符,我们在StackOverflow上找到一个类似的问题:
我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/
我正在尝试通过正则表达式拆分参数列表。这是一个带有我的参数列表的字符串:"a=b,c=3,d=[1,3,5,7],e,f=g"我想要的是:["a=b","c=3","d=[1,3,5,7]","e","f=g"]我试过先行,但Ruby不允许使用动态范围后行,所以这行不通:/(?如何让正则表达式忽略方括号中的所有内容? 最佳答案 也许这样的东西对你有用:str.scan(/(?:\[.*?\]|[^,])+/)编辑再三考虑。简单的非贪婪匹配器在某些嵌套括号的情况下会失败。 关于Ruby正则
我想找到给定字符串中的所有匹配项,包括重叠匹配项。我怎样才能实现它?#Example"a-b-c-d".???(/\w-\w/)#=>["a-b","b-c","c-d"]expected#Solutionwithoutoverlappedresults"a-b-c-d".scan(/\w-\w/)#=>["a-b","c-d"],but"b-c"ismissing 最佳答案 在积极的前瞻中使用捕获:"a-b-c-d".scan(/(?=(\w-\w))/).flatten#=>["a-b","b-c","c-d"]参见Rubyde
我想为名字验证编写一个正则表达式。正则表达式应包括所有字母(拉丁/法语/德语字符等)。但是我想从中排除数字并允许-。所以基本上它是\w(减)数(加)-。请帮忙。 最佳答案 ^[\p{L}-]+$\p{L}匹配anykindofletterfromanylanguage. 关于ruby-on-rails-rails中的正则表达式匹配[\w]和"-"但不匹配数字,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
这就是我做的a="%span.rockets#diamonds.ribbons.forever"a=a.match(/(^\%\w+)([\.|\#]\w+)+/)putsa.inspect这是我得到的#这就是我想要的#帮助?我尝试过但失败了:( 最佳答案 通常,您不能获得任意数量的捕获组,但如果您使用扫描,您可以为您想要捕获的每个标记获得一个匹配:a="%span.rockets#diamonds.ribbons.forever"a=a.scan(/^%\w+|\G[.|#]\w+/)putsa.inspect["%span","