Skip to content
Himxh edited this page Oct 4, 2026 · 1 revision

Lambda 表达式 / Lambda Expressions

什么是 lambda / What a Lambda Is

到目前为止,你写的每个函数都有一个名字。Lambda 是没有名字的函数——一段可以被传来传去的代码。它最常见的用途是给 GUI 按钮和事件处理器注册回调。

Every function you have written so far has a name. A lambda is a function without a name — a block of code you can pass around. Its most common use is registering callbacks for GUI buttons and event handlers.

最简单的 lambda:

The simplest lambda:

var f = (int x) -> x * 2;
int y = f.apply(5);      // 10

这里 (int x) -> x * 2 是一个 lambda:接收一个整数,返回它的两倍。f 是一个变量,持有这个 lambda。f.apply(5) 调用它。

Here (int x) -> x * 2 is a lambda: takes an integer, returns twice it. f is a variable holding the lambda. f.apply(5) invokes it.


语法 / Syntax

Lambda 有两种写法:

Two syntactic forms:

// 单参数:可以省略括号和类型
x -> x * 2

// 多参数:括号,逗号分隔,类型可省
(a, b) -> a + b

完整的写法带类型声明:

Full form with type declarations:

(int x) -> x * 2
(int a, int b) -> a + b

省略类型时,HimDSL 会根据上下文推断。推断不出来时会报错,这时需要补上类型。

Types may be omitted when the context can infer them. If inference fails, add them back.


表达式体与块体 / Expression Body vs Block Body

箭头右侧可以是一个表达式:

The right side of the arrow may be an expression:

var square = (int x) -> x * x;

也可以是一个语句块(用花括号):

Or a block (braces):

var log = (string msg) -> {
    string line = "[INFO] " + msg;
    runcmd("CONSOLE", "say " + line);
};

块体适合逻辑超过一行的情况。表达式体适合一行就能写完的计算。

Block bodies suit multi-line logic. Expression bodies suit one-liners.

块体里的返回值 / Return Inside a Block Body

块体需要返回时,必须显式写 return:

A block body must write return explicitly to produce a value:

var safeDiv = (int a, int b) -> {
    if (b == 0) {
        return 0;
    }
    return a / b;
};

表达式体不需要 return,箭头右侧的值就是返回值。

Expression bodies need no return; the value on the right is the result.


Lambda 是值 / Lambdas Are Values

和数字、字符串一样,lambda 可以:

Like numbers and strings, a lambda can be:

  • 存进变量。

  • Stored in a variable.

var f = (int x) -> x + 1;
  • 作为参数传给其他函数。

  • Passed as a function argument.

void applyTwice(var f, int x) {
    int y = f.apply(x);
    int z = f.apply(y);
    runcmd("CONSOLE", "say " + z);
}

int main() {
    applyTwice((int v) -> v * 3, 2);    // ((2*3)*3) = 18
}
  • 作为函数的返回值。

  • Returned from a function.

var makeAdder(int n) {
    return (int x) -> x + n;
}

int main() {
    var add5 = makeAdder(5);
    runcmd("CONSOLE", "say " + add5.apply(10));   // 15
}

最后这个例子体现了 lambda 的闭包能力:它记住了定义时周围的变量 n。即使 makeAdder 已经结束,lambda 依然能用 n 的值。

The last example shows closure: the lambda remembers n from its defining scope. Even after makeAdder returns, the lambda still uses n.


调用 lambda / Calling a Lambda

调用 lambda 使用 .apply(...):

Invoke with .apply(...):

var f = (int a, int b) -> a + b;
int result = f.apply(3, 4);      // 7

无参数的 lambda:

A lambda with no parameters:

var hello = () -> runcmd("CONSOLE", "say hello");
hello.apply();

块体无返回值时,apply 返回 null。

When the block body returns nothing, apply returns null.


闭包与作用域 / Closures and Scope

Lambda 能读取定义位置可见的所有变量:

A lambda reads every variable visible at its definition site:

int base = 100;
var addBase = (int x) -> x + base;

int main() {
    runcmd("CONSOLE", "say " + addBase.apply(5));    // 105
}

注意 lambda 捕获的是变量,不是值。如果捕获的变量后来被修改,lambda 看到的是最新的值:

Note that lambdas capture variables, not values. If the captured variable is later modified, the lambda sees the latest value:

int counter = 0;
var bump = () -> {
    counter = counter + 1;
    return counter;
};

int main() {
    runcmd("CONSOLE", "say " + bump.apply());    // 1
    runcmd("CONSOLE", "say " + bump.apply());    // 2
    runcmd("CONSOLE", "say " + bump.apply());    // 3
}

Lambda 内部对 counter 的修改会影响外层。用这一点可以实现"计数器"之类的效果,但也要小心意外的副作用。

Modifications to captured variables propagate outward. This enables "counters" but also risks unintended side effects.


在 GUI 里用 lambda / Lambdas in GUI

Lambda 最常见的应用是给 GUI 槽位注册点击回调:

The most common lambda use is registering GUI click callbacks:

int main() {
    var gui = new GUI(1, "菜单");
    var slot = new GUISlot(Material.DIAMOND);
    slot.name = "点击领奖";
    slot.onLeftClick = () -> {
        player p = @s;
        runcmd(p.name, "give " + p.name + " diamond 1");
    };
    gui[0][4] = slot;
    gui.updateAll();
}

这里的 () -> { ... } 是点击时执行的代码。@s 在回调里可用,指向点击的玩家。

Here () -> { ... } is the code executed on click. @s works inside the callback, pointing at the clicking player.

(GUI 的完整用法在后面章节,这里只需要感受 lambda 的形状。)

(Full GUI usage is later; here we only need to feel the shape of a lambda.)


与函数的关系 / Relation to Named Functions

Lambda 和具名函数做的是同一件事,区别在于有没有名字:

A lambda and a named function do the same thing; the difference is whether they have a name:

// 具名函数
int doubleIt(int x) { return x * 2; }

// 等价 lambda
var doubleIt2 = (int x) -> x * 2;

调用方式不同:具名函数直接 doubleIt(5);lambda 用 doubleIt2.apply(5)。

The call syntax differs: a named function is invoked as doubleIt(5); a lambda as doubleIt2.apply(5).

如果一个逻辑只在一处使用,用具名函数更清楚。只有当它要被"传出去"——作为参数、返回值、回调——lambda 才体现价值。

If a piece of logic is used in one place, a named function is clearer. A lambda earns its keep only when passed around — as an argument, a return value, or a callback.


小结 / Summary

  • Lambda 是无名函数,用 -> 定义。

  • 表达式体一行,块体多行。

  • 用 .apply(...) 调用。

  • Lambda 是值,可以存、传、返回。

  • Lambda 捕获定义位置的变量,修改会传回。

  • GUI 点击回调是它的典型应用。

  • 只在一处使用时,用具名函数更好。

  • A lambda is a nameless function, defined with ->.

  • Expression bodies are one-liners; block bodies are multi-line.

  • Invoke with .apply(...).

  • Lambdas are values: store, pass, return.

  • Lambdas capture variables; writes propagate back.

  • GUI click callbacks are a classic use.

  • For single-use logic, a named function is better.


下一步 / Next Steps

下一章 [函数式接口 / Functional-Interfaces] 介绍 lambda 与 Java 类型系统的衔接,例如把 lambda 传给 Runnable 之类的接口。

Next, [函数式接口 / Functional-Interfaces] covers how lambdas connect to Java types, such as passing a lambda to Runnable.


HimDSL 文档 / Documentation

入门 / Getting Started

语言基础 / Language Basics

控制流 / Control Flow

函数 / Functions

数据结构 / Data Structures

自定义类型 / Custom Types

Minecraft 集成 / Minecraft Integration

事件与调度 / Events & Scheduling

GUI 系统 / GUI System

内置函数参考 / Built-ins Reference

进阶 / Advanced

扩展 API / Extension API

你真的需要 API 吗?/ Do you really need the API?

Clone this wiki locally