lambda表达式 StringBuilder
时间: 2023-11-07 22:53:56 浏览: 138
在Kotlin中,lambda表达式是一种函数式编程的特性,它可以作为参数传递给其他函数或方法。Kotlin中的lambda表达式可以分为普通的lambda表达式和带接收者的lambda表达式两种类型。普通的lambda表达式没有接收者,而带接收者的lambda表达式可以在lambda体内访问接收者对象的成员。
Kotlin中的lambda表达式具有真正的闭包特性,与Java中的lambda表达式相比更加灵活,访问的限制也更少。这是因为Kotlin中的lambda表达式会自动捕获外部的变量,使得在lambda表达式内部可以访问和修改这些变量。
在Kotlin中,lambda表达式的变量捕获是通过将外部变量包装成一个对象,并将该对象作为lambda表达式的隐藏参数来实现的。这样,在lambda表达式内部就可以访问和修改这些变量了。
在Kotlin中,lambda表达式的返回值是自动推断的。如果lambda表达式的最后一个表达式是一个返回值,那么这个返回值就是lambda表达式的返回值。
回答完问题后的
相关问题
实验I中,只需要根据以下的词法规则,实现Lexer类中的nextToken()方法,成功解析字符串的tokentype序列即可。 ``` public enum TokenType { //注意:输入中的所有空格应该忽略 EOF,//标识lambda表达式的结束 LAMBDA,// '\',即lambda表达式中的lambda,注意转义 LPAREN,// 左括号 RPAREN,// 右括号 LCID,// 标识符,要求小写字母开头,大写或小写字母组成 DOT// lambda表达式中的'.' } ``` Lexer类的构造函数需要接收一个待解析的String类型lambda表达式,该类的构造函数与成员变量均可自行设计,只要保证nextToken()方法输出指定的结果即可。 nextToken()方法需要解析出字符串表达式的未解析的下一个token,**需要换行打印**并返回解析出的TokenType,测试中会检查输出的TokenType序列是否正确。 比如: ```java String ZERO = "(\\f.\\x.x)"; ``` 此时第一个未解析的字符是"(",它需要被解析为LPAREN,输出出来。 需要注意的是,lexer被parser调用时,对于LCID类型的token,不仅需要得到待解析token的类型,还需要得到待解析token的内容,这点并不影响实验I的实现,但在设计时可能需要考虑这点。 除了nextToken()方法外,在Lexer类中还提供了三个待实现的工具方法next(),match()与return(),在接下来的实验中提供给parser调用,请自行阅读注解,**本次作业可以酌情实现** **编写建议** ```java public class Lexer{ public TokenType token; public String tokenvalue; //........ } ```
根据词法规则,我们可以先定义一些常量,例如:
```java
public class Lexer {
private final String input; // 待解析的字符串
private int pos = 0; // 当前字符的索引
private char currentChar; // 当前字符
// TokenType常量
private static final TokenType EOF = TokenType.EOF;
private static final TokenType LAMBDA = TokenType.LAMBDA;
private static final TokenType LPAREN = TokenType.LPAREN;
private static final TokenType RPAREN = TokenType.RPAREN;
private static final TokenType LCID = TokenType.LCID;
private static final TokenType DOT = TokenType.DOT;
// 构造函数
public Lexer(String input) {
this.input = input.replaceAll("\\s", ""); // 去除空格
this.currentChar = this.input.charAt(pos);
}
// 工具方法next(),返回当前字符并将pos指针后移
private char next() {
pos++;
if (pos > input.length() - 1) {
currentChar = '\0'; // 到达字符串结尾
} else {
currentChar = input.charAt(pos);
}
return currentChar;
}
// 工具方法match(),如果当前字符匹配上了传入的字符,则将pos指针后移
private void match(char c) {
if (currentChar == c) {
next();
} else {
throw new IllegalArgumentException("Unexpected character: " + currentChar);
}
}
// 工具方法return(),将pos指针回退一格
private void returnBack() {
pos--;
currentChar = input.charAt(pos);
}
// 解析下一个token
public TokenType nextToken() {
while (currentChar != '\0') {
if (currentChar == '\\') {
match('\\');
return LAMBDA;
} else if (currentChar == '(') {
match('(');
return LPAREN;
} else if (currentChar == ')') {
match(')');
return RPAREN;
} else if (Character.isLowerCase(currentChar)) {
StringBuilder sb = new StringBuilder();
while (Character.isLetterOrDigit(currentChar)) {
sb.append(currentChar);
next();
}
returnBack();
return LCID;
} else if (currentChar == '.') {
match('.');
return DOT;
} else {
throw new IllegalArgumentException("Unexpected character: " + currentChar);
}
}
return EOF;
}
}
```
在Lexer类中,我们定义了一个input成员变量,用于存储待解析的字符串。在构造函数中,我们去除了所有空格,方便后续解析。我们还定义了三个工具方法next()、match()和return(),用于parser调用。其中,next()方法返回当前字符并将pos指针后移,match()方法判断当前字符是否匹配传入的字符,如果匹配则将pos指针后移,否则抛出异常。return()方法将pos指针回退一格。
在解析下一个token时,我们依次判断当前字符的类型,如果匹配上了就返回对应的TokenType。如果是LCID类型的token,需要使用StringBuilder来依次读取所有的字母和数字,直到遇到非字母数字字符为止。最后,我们使用returnBack()方法将pos指针回退一格,因为在读取完LCID后,当前字符是非字母数字字符,需要重新解析该字符。如果当前字符不匹配任何类型,则抛出异常。
注意,在判断LCID时,我们使用了while循环来读取所有的字母和数字,因此需要在循环结束后调用returnBack()方法将pos指针回退一格。否则,如果下一个字符是非字母数字字符,就会误判为新的token类型。
fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder的第二个StringBuilder.是什么意思
在这个函数中,`StringBuilder.()` 是一个 lambda 表达式的类型标识符。它的意思是在 lambda 表达式中,我们可以通过 `this` 关键字来引用 `StringBuilder` 对象本身。换句话说,`StringBuilder.() -> Unit` 表示一个接受 `StringBuilder` 对象并且没有返回值的 lambda 表达式。通过这个 lambda 表达式,我们可以在 `StringBuilder` 对象上执行一些操作或者调用其方法。
阅读全文