<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Thus spoke misaka10987</title><description>Blog</description><link>https://misaka10987.github.io/</link><language>en</language><item><title>所有超速超载罚分整理（科目一）</title><link>https://misaka10987.github.io/posts/random/overspeed-and-overload/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/overspeed-and-overload/</guid><pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;所有超速超载罚分整理（科目一）&lt;/h1&gt;
&lt;p&gt;下文「客车」「货车」是指营运性质的客车和货车。特别地，出租车在处罚时，服从私人轿车的标准。&lt;/p&gt;
&lt;h2&gt;超速&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;车型&lt;/th&gt;
&lt;th&gt;道路类型&lt;/th&gt;
&lt;th&gt;超速比例&lt;/th&gt;
&lt;th&gt;记分&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;不记分&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;20%～50%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;不记分&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;20%～50%&lt;/td&gt;
&lt;td&gt;3&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;20%～50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;高速 / 城市快速路&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;3&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;20%～50%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车 / 货车&lt;/td&gt;
&lt;td&gt;普通道路&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;超载&lt;/h2&gt;
&lt;p&gt;货车的超载比例以质量计。超载不作高速/普通道路差分。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;车型&lt;/th&gt;
&lt;th&gt;超载比例&lt;/th&gt;
&lt;th&gt;记分&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;3&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;轿车&lt;/td&gt;
&lt;td&gt;≥20%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车&lt;/td&gt;
&lt;td&gt;＜20%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车&lt;/td&gt;
&lt;td&gt;20%～50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;客车&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;货车&lt;/td&gt;
&lt;td&gt;＜30%&lt;/td&gt;
&lt;td&gt;3&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;货车&lt;/td&gt;
&lt;td&gt;30%～50%&lt;/td&gt;
&lt;td&gt;6&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;货车&lt;/td&gt;
&lt;td&gt;＞50%&lt;/td&gt;
&lt;td&gt;12&apos;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content:encoded></item><item><title>禁用 VS Code 的操作系统密钥环支持</title><link>https://misaka10987.github.io/posts/random/vscode-disable-keyring/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/vscode-disable-keyring/</guid><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;禁用 VS Code 的操作系统密钥环支持&lt;/h1&gt;
&lt;p&gt;编辑&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/.vscode/argv.json
{
    &quot;password-store&quot;: &quot;basic&quot;
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>固件更新或导致 AMD 显卡频繁重置</title><link>https://misaka10987.github.io/posts/random/amdgpu-reset-fw-update/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/amdgpu-reset-fw-update/</guid><pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;固件更新或导致 AMD 显卡频繁重置&lt;/h1&gt;
&lt;p&gt;在 Arch Linux 上自从 &lt;a href=&quot;https://archlinux.org/packages/core/any/linux-firmware-amdgpu/&quot;&gt;&lt;code&gt;linux-firmware-amdgpu&lt;/code&gt;&lt;/a&gt; 版本 20251125-1 起，AMD 显卡可能在低负载下不必要的重置，表现为约 15-30min 出现一次。&lt;/p&gt;
&lt;p&gt;可以考虑锁定版本。&lt;/p&gt;
</content:encoded></item><item><title>部署 SolidStart 项目到 Cloudflare Workers</title><link>https://misaka10987.github.io/posts/random/solidstart-cloudflare/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/solidstart-cloudflare/</guid><pubDate>Sat, 06 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;部署 SolidStart 项目到 Cloudflare Workers&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://start.solidjs.com/&quot;&gt;SolidStart&lt;/a&gt; 是一个基于 &lt;a href=&quot;https://www.solidjs.com/&quot;&gt;SolidJS&lt;/a&gt; 的 Web 全栈开发框架。然而，其对 &lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt; 部署的适配器已 &lt;a href=&quot;https://www.npmjs.com/package/solid-start-cloudflare-workers&quot;&gt;弃用&lt;/a&gt; ，而 SolidStart 的官方文档并未更新。如果选择部署到 &lt;a href=&quot;https://developers.cloudflare.com/pages/framework-guides/deploy-a-solid-start-site/&quot;&gt;Pages&lt;/a&gt; , 则会失去 SSR 支持。本文描述如何将最新的 SolidStart 项目部署到 Cloudflare Workers.&lt;/p&gt;
&lt;p&gt;SolidStart 采用 &lt;a href=&quot;https://nitro.build/&quot;&gt;Nitro&lt;/a&gt; 作为服务器实现。因此，我们可以很方便地利用 Nitro 的 Cloudflare 集成。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app.config.ts
export default defineConfig({
  server: {
    preset: &apos;cloudflare-module&apos;,
    cloudflare: {
      deployConfig: true,
    },
  }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;参考 Nitro &lt;a href=&quot;https://nitro.build/deploy/providers/cloudflare#cloudflare-workers&quot;&gt;文档&lt;/a&gt; ，我们将服务器的编译后端配置为 &lt;code&gt;cloudflare-module&lt;/code&gt; , 即 Cloudflare Workers. &lt;code&gt;deployConfig&lt;/code&gt; 会自动为我们生成 &lt;a href=&quot;https://developers.cloudflare.com/workers/wrangler/&quot;&gt;Wrangler&lt;/a&gt; 的配置文件。此时生成的 &lt;code&gt;.output&lt;/code&gt; 目录是可以直接通过 Wrangler 部署的。&lt;/p&gt;
&lt;p&gt;如果项目托管在 GitHub 上，则可以使用 Cloudflare 的 GitHub App 监听存储库来自动部署。这需要在 Cloudflare 网页端创建新的 Worker 并绑定到指定的存储库。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;/p&gt;
&lt;p&gt;在配置 Worker 构建时，务必注意将构建目录设置为相对于仓库根目录正确的路径，并将部署命令设为 &lt;code&gt;npx wrangler --cwd .output deploy&lt;/code&gt;（ &lt;code&gt;npm run build&lt;/code&gt; 所提示的命令）。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>代数视角下的秩零度定理</title><link>https://misaka10987.github.io/posts/random/rank-nullity/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/rank-nullity/</guid><pubDate>Thu, 06 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;代数视角下的秩零度定理&lt;/h1&gt;
&lt;p&gt;我们可能见过如下关于矩阵的结论&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;线性代数基本定理&lt;/strong&gt; 对于矩阵 $A : \R^{m \times n}$ , 有&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\dim(\operatorname{Col} A) = \dim(\operatorname{Row} A) = \operatorname{rank} A$ ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\dim(\operatorname{Null} A) = n - \operatorname{rank} A$ ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\dim(\operatorname{Null} A^\mathrm T) = m - \operatorname{rank} A$ .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;或者，去掉两个关于 $A^\mathrm T$ 的结论，我们可以得到一个方向上的等价形式&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;秩零度定理&lt;/strong&gt; 对于矩阵 $A : \R^{m \times n}$ , $\operatorname{rank} A + \operatorname{nullity} A = n$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;初学线性代数时，通常采用朴素方法直接考虑向量空间的基来处理该问题。本文旨在从代数视角下重新审视这一定理，并作出证明。&lt;/p&gt;
&lt;h2&gt;从矩阵到线性变换&lt;/h2&gt;
&lt;p&gt;一个矩阵 $A : \R^{m \times n}$ 可以看作线性变换 $f_A : \R^n \to \R^m = \mathbf x \mapsto A \mathbf x$ , 而矩阵之间的乘法就是函数之间的复合。有了这种对应关系，我们在下文中可以始终从线性变换的视角来看待矩阵。&lt;/p&gt;
&lt;p&gt;同时，在线性变换的视角下，矩阵作为函数的话，不难注意到其零空间和列空间直接就是映射的 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%A0%B8_(%E4%BB%A3%E6%95%B0)&quot;&gt;核&lt;/a&gt; 与 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%83%8F_(%E6%95%B8%E5%AD%B8)&quot;&gt;像&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;因此，我们可以将秩零度定理改写成这样的形式&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$A : \R^n \to \R^m$ , $\dim(\operatorname{im} A) + \dim(\ker A) = n$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;即，线性变换的定义域的维度等于像的维度加上核的维度。&lt;/p&gt;
&lt;h2&gt;推广形式&lt;/h2&gt;
&lt;p&gt;由于 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%B6%AD%E5%BA%A6&quot;&gt;维度&lt;/a&gt; 被定义为基向量的数量，类似的命题在所有 $\mathbb F$ - 向量空间内都可以定义。我们给出线性代数基本定理在这样推广后的版本&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;线性代数基本定理&lt;/strong&gt; 设 $V$ , $W$ 是向量空间，$A : V \to W$ 是其间的线性变换，则有&lt;/p&gt;
&lt;p&gt;$$
\dim(\operatorname{im} A) + \dim(\ker A) = \dim V
$$&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;而这个定理的证明可以从向量空间的视角来展开思考。我们直觉认为 $\ker A$ 中的元素都被映到 $\mathbf 0_W$ 上，可以视作「对像的维度没有任何贡献」，而去掉这部分之后的定义域应该和像有相同的维度，也就是线性同构于像。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;证明&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;将目标简单恒等变换即&lt;/p&gt;
&lt;p&gt;$$
\dim(\operatorname{im} A) = \dim V - \dim (\ker A)
$$&lt;/p&gt;
&lt;p&gt;显然 $\ker A$ 是 $V$ 的子空间。我们 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%95%86%E7%A9%BA%E9%97%B4_(%E7%BA%BF%E6%80%A7%E4%BB%A3%E6%95%B0)#%E4%BE%8B%E5%AD%90%E4%B8%8E%E6%80%A7%E8%B4%A8&quot;&gt;商&lt;/a&gt; 掉它即&lt;/p&gt;
&lt;p&gt;$$
\dim(\operatorname{im} A) = \dim(V / \ker A)
$$&lt;/p&gt;
&lt;p&gt;维度相等等价于线性同构，即&lt;/p&gt;
&lt;p&gt;$$
\operatorname{im} A \cong V / \ker A
$$&lt;/p&gt;
&lt;p&gt;要证线性同构，我们构造一个映射&lt;/p&gt;
&lt;p&gt;$$
T : V / \ker A \to \operatorname{im} A = [\mathbf v] \mapsto A(\mathbf v)
$$&lt;/p&gt;
&lt;p&gt;并证明它是线性同构。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Quotient_space_(linear_algebra)#First_Isomorphism_Theorem&quot;&gt;&lt;strong&gt;第一同构定理&lt;/strong&gt;&lt;/a&gt; 令 $T : V \to W$ 是 $\mathbb F$ - 向量空间 $V$ , $W$ 之间的线性变换，则 $\tilde T : V / \ker T \to W = [\mathbf v] \mapsto T(\mathbf v)$ 是良定义的线性同构。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;证明&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;良定义&lt;/strong&gt; 令 $\mathbf v_1, \mathbf v_2 \in [\mathbf v]$ , 则 $\mathbf v_1 - \mathbf v_2 \in \ker T$ , $T(\mathbf v_1 - \mathbf v_2) = \mathbf 0_W$ , $T(\mathbf v_1) = T(\mathbf v_2)$ .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;双射&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;单射&lt;/strong&gt; 若 $\tilde T([\mathbf v_1]) = \tilde T([\mathbf v_2])$ , 则 $T(\mathbf v_1) = T(\mathbf v_2)$ , $T(\mathbf v_1 - \mathbf v_2) = \mathbf 0_W$ , $\mathbf v_1 - \mathbf v_2 \in \ker T$ , 由定义可知 $[\mathbf v_1] = [\mathbf v_2]$ .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;满射&lt;/strong&gt; 因为 $T$ 是到 $\operatorname{im} T$ 的满射，对定义域中的每个元素取其生成的等价类，显然 $\tilde T$ 是满射。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;线性&lt;/strong&gt; $\tilde T([\mathbf v_1] + [\mathbf v_2]) = \tilde T([\mathbf v_1 + \mathbf v_2]) = T(\mathbf v_1 + \mathbf v_2) = T(\mathbf v_1) + T(\mathbf v_2) = \tilde T([\mathbf v_1]) + \tilde T([\mathbf v_2])$ .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$\square$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;$\square$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这是一个纯代数角度的证明，对所有的向量空间都有效。&lt;/p&gt;
&lt;h2&gt;秩零度定理的本质含义&lt;/h2&gt;
&lt;p&gt;一种从「信息」出发的理解方式是，线性映射 $T : \mathbb F^n \to \mathbb F^m$ 输入的信息量一共有 $n$ , 输出的信息量却只有 $m$ , 因此，有 $n - m$ 的信息在这个过程中被摧毁了，这是通过重复映射到 $0$ 上从而不可逆来实现的。被摧毁的部分即 $\ker T$ .&lt;/p&gt;
&lt;p&gt;类似地，在群论中也有表达这一结论的定理&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;第一同构定理&lt;/strong&gt; 若 $G$ , $H$ 是群，$f : G \to H$ 是同态，则 $G / \ker f \cong \operatorname{im} f$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这些结论通过 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E9%98%BF%E8%B2%9D%E7%88%BE%E7%AF%84%E7%96%87&quot;&gt;阿贝尔范畴&lt;/a&gt; 统一描述。&lt;/p&gt;
</content:encoded></item><item><title>双曲角实在是太简单了</title><link>https://misaka10987.github.io/posts/xite/hyp-angle/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/xite/hyp-angle/</guid><description>双曲角，双曲函数，Minkowski 空间</description><pubDate>Thu, 16 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;双曲角实在是太简单了&lt;/h1&gt;
&lt;p&gt;我们在微积分学中见过自然对数 $\ln$ . 聪明的读者可能还见过 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8F%8C%E6%9B%B2%E8%A7%92&quot;&gt;双曲函数&lt;/a&gt; $\sinh x = \frac{1}{2} (\exp x - \exp -x)$ , $\cosh x = \frac{1}{2} (\exp x + \exp -x)$ . 本文讨论 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8F%8C%E6%9B%B2%E8%A7%92&quot;&gt;双曲角&lt;/a&gt; , 并利用这一概念互相联系地重新定义上述对象。为了简便，本文的讨论在平面上进行。&lt;/p&gt;
&lt;h2&gt;角&lt;/h2&gt;
&lt;p&gt;如果你接受过中国大陆的中学教育，你可能会有印象于这些角的描述：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;平面内，一点引两条射线；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一条射线绕其端点旋转；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;单位圆上一条圆弧的长度。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们接下来将这些「传统意义上」的角称为 &lt;strong&gt;圆角&lt;/strong&gt; 。在角的弧度制定义下这是名副其实的。一个角的大小被定义为单位圆的圆周角对应圆弧的长度（我们假装没有看见 $[0, 2\pi)$ 以外的角）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;circ.svg&quot; alt=&quot;圆角&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在极坐标意义下，圆角还可以用来确定欧几里得空间中到选定点距离恒定的所有点的其中一个。或者说，圆角是圆上某一点的身份。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;/p&gt;
&lt;p&gt;此处的表达不严谨。向量 $\mathbf u$ , $\mathbf v$ 的夹角 $\theta$ 是用空间中的内积诱导的。&lt;/p&gt;
&lt;p&gt;$$
\cos \theta =
\frac {\left&amp;lt; \mathbf u, \mathbf v \right&amp;gt;}
{\lVert \mathbf u \rVert \cdot \lVert \mathbf v \rVert}
$$&lt;/p&gt;
&lt;p&gt;其中范数定义为&lt;/p&gt;
&lt;p&gt;$$
\lVert \mathbf v \rVert = \sqrt { \left&amp;lt; \mathbf v, \mathbf v \right&amp;gt; }
$$&lt;/p&gt;
&lt;p&gt;以上适用于实内积空间，对于 $\mathbb C$ 或者其他数域，角度的定义不一定一样方便。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在欧式几何中到定点距离恒定的点的集合是圆。这也是我们在定义圆角时选择使用了单位圆 $x^2 + y^2 = 1$ 的原因。&lt;/p&gt;
&lt;h2&gt;圆的推广&lt;/h2&gt;
&lt;p&gt;「圆」在通常的定义下使用的是 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E8%B7%9D%E7%A6%BB&quot;&gt;欧几里得范数&lt;/a&gt; 。但是，我们研究的所有空间并不都是欧几里得空间。事实上，只要我们得到一个赋范向量空间，就可以类比地得到所谓的「圆」。例如，一个采用 $L_1$ 曼哈顿范数而非 $L_2$ 的「圆」。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;manhattan.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;进一步地，我们也可以用这个实则为正方形的「圆」上的「弧」，实则为周长上的折线段来定义「角」。通过这种朴素方法，我们在没有内积的情况下，也能够定义角度。这自然有局限性，例如角度不是线性的。&lt;/p&gt;
&lt;h2&gt;方法一：Minkowski 伪内积空间&lt;/h2&gt;
&lt;p&gt;虽然角度严格上是通过内积定义的，但事实上，我们不一定需要内积空间这样强的结构，就可以定义角度。这样能够得到双曲角的一种定义，通过 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA#%E6%95%B0%E5%AD%A6%E7%BB%93%E6%9E%84&quot;&gt;Minkowski 伪内积&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;有 $\R^2$ 中的 Minkowski 伪内积定义（采用西海岸度规）&lt;/p&gt;
&lt;p&gt;$$
\left&amp;lt; \mathbf u, \mathbf v \right&amp;gt;
= \mathbf u_0 \mathbf v_0 - \mathbf u_1 \mathbf v_1
$$&lt;/p&gt;
&lt;p&gt;Minkowski 伪内积不满足正定性（即 $\left&amp;lt; \mathbf v, \mathbf v \right&amp;gt;$ 始终非负），因此不是标准的内积，但这没有太大影响。我们可以用类似的方式把它当作内积使用来推导角度的定义。&lt;/p&gt;
&lt;p&gt;对于向量 $\mathbf u$ , $\mathbf v$ , 其夹角 $\theta$ 可以定义为&lt;/p&gt;
&lt;p&gt;$$
\cosh \theta =
\frac{\left&amp;lt; \mathbf u, \mathbf v \right&amp;gt;}
{\sqrt{\left| \left&amp;lt; \mathbf u, \mathbf u \right&amp;gt; \right|
\cdot \left| \left&amp;lt; \mathbf v, \mathbf v \right&amp;gt; \right|}}
$$&lt;/p&gt;
&lt;p&gt;这就是标准的双曲角的定义。我们使用双曲余弦而非余弦，是因为在 Minkowski 伪内积下，两个向量的内积 $\left&amp;lt; \mathbf u, \mathbf v \right&amp;gt;$ 可能比「范数」的乘积还要大。&lt;/p&gt;
&lt;p&gt;我们不难发现上述定义下的「单位圆」其实是双曲线。这可以由方程&lt;/p&gt;
&lt;p&gt;$$
\left&amp;lt; \mathbf v, \mathbf v \right&amp;gt; = 1
$$&lt;/p&gt;
&lt;p&gt;展开内积的定义&lt;/p&gt;
&lt;p&gt;$$
\mathbf v_0^2 - \mathbf v_1^2 = 1
$$&lt;/p&gt;
&lt;p&gt;得到 $x^2 - y^2 = 1$ .&lt;/p&gt;
&lt;p&gt;推广到任意 $n: \N$ , $\R^{1+n}$ 中，始终可以定义 Minkowski 伪内积&lt;/p&gt;
&lt;p&gt;$$
\left&amp;lt; \mathbf u, \mathbf v \right&amp;gt;
= \mathbf u_0 \mathbf v_0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\sum_{i = 1}^n \mathbf u_i \mathbf v_i
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从而继续得到双曲角。特别地，装配 Minkowski 伪内积的 $\R^{1+3}$ , 或者称为 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA&quot;&gt;Minkowski 时空&lt;/a&gt; 被用于书写 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%8B%AD%E4%B9%89%E7%9B%B8%E5%AF%B9%E8%AE%BA&quot;&gt;狭义相对论&lt;/a&gt; 。&lt;/p&gt;
&lt;h2&gt;方法二：从「单位圆」出发&lt;/h2&gt;
&lt;p&gt;我们刚才通过赋予内积得到了「单位圆」为双曲线的结构。我们也可以反向操作，要求「单位圆」是双曲线来定义角。&lt;/p&gt;
&lt;p&gt;我们采用直角双曲线 $xy = 1$ 作为单位圆，并且先考虑第一象限的情况。顺其自然地可以采用对称轴 $y = x$ 的方向作为角度 $0$ . 一个朴素的想法是采用 $(1, 1)$ 与 $(x, \frac{1}{x})$ 之间的双曲线弧长作为角度，但事实上由于双曲线上的弧长没有初等表达（ &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%A4%AD%E5%9C%86%E7%A7%AF%E5%88%86&quot;&gt;椭圆积分&lt;/a&gt; ），我们选择了退而求其次地使用原点连线、双曲线与直线 $y = x$ 约束的 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E9%9B%99%E6%9B%B2%E7%B7%9A%E6%89%87%E5%BD%A2&quot;&gt;双曲扇形&lt;/a&gt; 的面积作为角度。人为规定向 $x$ 轴方向为正，$y$ 轴方向为负。显然这个双曲扇形的面积是单调的，「单位圆」双曲线上的点与双曲角一一对应。&lt;/p&gt;
&lt;p&gt;注意到 $\frac{1}{x}$ 的积分发散。因此，双曲角可以在 $\R$ 上任意取值。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;hyp.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;双曲对数&lt;/h3&gt;
&lt;p&gt;在推导上述定义的过程中，还存在一个简单的结论：点 $(x, \frac{1}{x})$ 的双曲角，或者标准双曲扇形的面积是 $\ln x$ . 聪明的读者可以利用 $\frac{1}{x}$ 的积分是 $\ln x$ , 以及双曲线 $xy = 1$ 下的矩形面积相等的性质容易地证明这一结论。&lt;/p&gt;
&lt;p&gt;事实上，人们最早定义了函数 $\ln$ 来表达这个面积，并将其称为双曲对数。此后因为发现其是指数函数 $\exp$ 的反函数，而改成自然对数。&lt;/p&gt;
&lt;h2&gt;双曲函数&lt;/h2&gt;
&lt;p&gt;我们发现第一种定义下的「单位圆」是 $x^2 - y^2 = 1$ , 第二种是 $xy = 1$ , 并不相同。虽然这两者相似，在现代化的作法中，我们会直接采用 $x^2 - y^2 = 1$ 来定义双曲角。这将第二种的情景旋转 $45 \degree$ 即可。&lt;/p&gt;
&lt;p&gt;这样做的一大好处是可以将双曲函数和双曲角的关系同三角函数和圆角的关系统一起来。因为我们知道 $(\cosh x)^2 - (\sinh x)^2 = 1$ 的形式和单位双曲线 $x^2 - y^2 = 1$ 相同，我们可以参数化单位双曲线为&lt;/p&gt;
&lt;p&gt;$$
\begin{cases}
x = \cosh \theta \
y = \sinh \theta
\end{cases}
$$&lt;/p&gt;
&lt;p&gt;这就和圆角的正余弦和边长的关系完全一致。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;hyp-trig.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;需要注意的是，按照传统定义，点 $(\cosh \theta, \sinh \theta)$ 的双曲角是参数 $\theta$ 的一半而非 $\theta$ 本身。&lt;/p&gt;
&lt;p&gt;$$
\begin{align*}
\int_0^\theta \frac{1}{2} (x ,\mathrm d y - y ,\mathrm d x) \
&amp;amp; = \frac{1}{2} \int_0^\theta
\cosh \phi ,\mathrm d \sinh \phi - \sinh \phi ,\mathrm d \cosh \phi \
&amp;amp; = \frac{1}{2} \int_0^\theta
(\cosh \phi)^2 ,\mathrm d \theta - (\sinh \phi)^2 ,\mathrm d \theta \
&amp;amp; = \frac{1}{2} \int_0^\theta ,\mathrm d \theta \
&amp;amp; = \frac{1}{2} \theta
\end{align*}
$$&lt;/p&gt;
&lt;p&gt;这和单位圆上的结论是类似的，点 $(\cos \theta, \sin \theta)$ 对应扇形的面积是 $\frac{1}{2} \theta r^2 = \frac{1}{2} \theta$ . 为了避免这个麻烦，现代有时候直接将 $(\cosh \theta, \sinh \theta)$ 的参数 $\theta$ 定义为双曲角，而非双曲扇形的面积。&lt;/p&gt;
</content:encoded></item><item><title>常用积分快速参考手册</title><link>https://misaka10987.github.io/posts/random/integral-handbook/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/integral-handbook/</guid><pubDate>Fri, 10 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;常用积分快速参考手册&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;/p&gt;
&lt;p&gt;如果需要计算不定积分，请注意本文中均省略了常数 $+C$ .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;幂函数&lt;/h2&gt;
&lt;p&gt;幂函数&lt;/p&gt;
&lt;p&gt;$$
\int x^p ,\mathrm d x
= \frac{1}{p+1} x^{p+1}
$$&lt;/p&gt;
&lt;p&gt;特别地，$x^{-1}$ , 如果积分有定义&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{x} ,\mathrm d x
= \ln \left| x \right|
$$&lt;/p&gt;
&lt;h2&gt;指数函数&lt;/h2&gt;
&lt;p&gt;指数函数&lt;/p&gt;
&lt;p&gt;$$
\int \exp x ,\mathrm d x
= \exp x
$$&lt;/p&gt;
&lt;p&gt;以任意 $a: \R &amp;gt; 0$ 为底&lt;/p&gt;
&lt;p&gt;$$
\int a^x ,\mathrm d x
= \frac{1}{\ln a} a^x
$$&lt;/p&gt;
&lt;h2&gt;对数函数&lt;/h2&gt;
&lt;p&gt;自然对数&lt;/p&gt;
&lt;p&gt;$$
\int \ln x ,\mathrm d x
= x \ln x - x
$$&lt;/p&gt;
&lt;p&gt;以任意 $a: \R &amp;gt; 0$ 为底&lt;/p&gt;
&lt;p&gt;$$
\int \log_a x ,\mathrm d x
= \frac{1}{\ln a}(x \ln x - x)
$$&lt;/p&gt;
&lt;h2&gt;三角函数&lt;/h2&gt;
&lt;p&gt;正弦&lt;/p&gt;
&lt;p&gt;$$
\int \sin x ,\mathrm d x
= \cos x
$$&lt;/p&gt;
&lt;p&gt;余弦&lt;/p&gt;
&lt;p&gt;$$
\int \cos x ,\mathrm d x
= -\sin x
$$&lt;/p&gt;
&lt;p&gt;正切，如果积分有定义&lt;/p&gt;
&lt;p&gt;$$
\int \tan x ,\mathrm d x
= - \ln \left| \cos x \right|
$$&lt;/p&gt;
&lt;h2&gt;反三角函数&lt;/h2&gt;
&lt;p&gt;反正弦导数&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{1 - x^2}} ,\mathrm d x
= \arcsin x
$$&lt;/p&gt;
&lt;p&gt;反正切导数&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{1 + x^2} ,\mathrm d x
= \arctan x
$$&lt;/p&gt;
&lt;h2&gt;双曲函数&lt;/h2&gt;
&lt;p&gt;双曲正弦&lt;/p&gt;
&lt;p&gt;$$
\int \sinh x ,\mathrm d x
= \cosh x
$$&lt;/p&gt;
&lt;p&gt;双曲余弦&lt;/p&gt;
&lt;p&gt;$$
\int \cosh x ,\mathrm d x
= \sinh x
$$&lt;/p&gt;
&lt;h2&gt;反双曲函数&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]&lt;/p&gt;
&lt;p&gt;这与反三角函数类似。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;反双曲正弦导数&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{x^2 + 1}} ,\mathrm d x
= \operatorname{arsinh} x
$$&lt;/p&gt;
&lt;p&gt;反双曲余弦导数&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{x^2 - 1}} ,\mathrm d x
= \operatorname{arcosh} x
$$&lt;/p&gt;
&lt;h2&gt;二级结论&lt;/h2&gt;
&lt;p&gt;导数除以自身&lt;/p&gt;
&lt;p&gt;$$
\int \frac{f&apos;(x)}{f(x)} ,\mathrm d x
= \ln \left| f(x) \right|
$$&lt;/p&gt;
&lt;p&gt;反正弦推广，如果积分有定义&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{a^2 - x^2}} ,\mathrm d x
= \arcsin \frac{x}{a}
$$&lt;/p&gt;
&lt;p&gt;反正切推广&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{a^2 + x^2} ,\mathrm d x
= \frac{1}{a} \arctan \frac{x}{a}
$$&lt;/p&gt;
&lt;p&gt;反双曲正弦推广&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{x^2 + a^2}}
= \operatorname{arsinh} \frac{x}{\left| a \right|}
$$&lt;/p&gt;
&lt;p&gt;反双曲余弦推广，如果积分有定义&lt;/p&gt;
&lt;p&gt;$$
\int \frac{1}{\sqrt{x^2 - a^2}}
= \operatorname{arcosh} \frac{x}{\left| a \right|}
$$&lt;/p&gt;
</content:encoded></item><item><title>Cargo 会自动使用 Git 的 HTTP 代理</title><link>https://misaka10987.github.io/posts/random/cargo-use-git-http-proxy/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/cargo-use-git-http-proxy/</guid><pubDate>Wed, 01 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Cargo 会自动使用 Git 的 HTTP 代理&lt;/h1&gt;
&lt;p&gt;Cargo（ Rust 包管理器）采用了 &lt;a href=&quot;https://github.com/rust-lang/crates.io-index&quot;&gt;Git 仓库&lt;/a&gt; 作为包注册索引。因此，在执行 Cargo 事务时，其会先尝试同步更新 Git 仓库。在这个过程中，Cargo 被实现为自动采用 Git 的 &lt;code&gt;http.proxy&lt;/code&gt; 指定的 HTTP 代理。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;/p&gt;
&lt;p&gt;较新版本的 Cargo 实现了稀疏索引机制，允许快速地通过 HTTP API 检索包。虽然，尊重 &lt;code&gt;http.proxy&lt;/code&gt; 的机制没有受到影响。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个问题的起因是作者发现当本地的 HTTP 代理服务尚未启动时，Cargo 表现为不能执行几乎任何事务，即使在配置文件 &lt;code&gt;$HOME/.cargo/config.toml&lt;/code&gt; 中未指定任何 HTTP 代理也是如此。造成这一令人困惑的现象的原因就是 Cargo 隐式地读取了 Git 的配置项。&lt;/p&gt;
</content:encoded></item><item><title>关于一个逆矩阵问题的构造思路</title><link>https://misaka10987.github.io/posts/random/i-minus-ab-inverse/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/random/i-minus-ab-inverse/</guid><description>如果 I - AB 可逆，是否 I - BA 可逆？</description><pubDate>Thu, 25 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;关于一个逆矩阵问题的构造思路&lt;/h1&gt;
&lt;p&gt;这事实上是笔者遇到的某道作业题。我们有结论&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果 $A: \R^{m \times n}$ , $B: \R^{n \times m}$ , 如果 $\mathbf 1_m - AB$ 可逆，则 $\mathbf 1_n - BA$ 可逆。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个结论的证明不难检验。我们构造&lt;/p&gt;
&lt;p&gt;$$
X = \mathbf 1_n + B (\mathbf 1_m - AB)^{-1} A
$$&lt;/p&gt;
&lt;p&gt;并计算&lt;/p&gt;
&lt;p&gt;$$
\begin{align*}
(\mathbf 1_n - BA) X
&amp;amp; = (\mathbf 1_n - BA) (\mathbf 1_n + B (\mathbf 1_m - AB)^{-1} A) \
&amp;amp; = \mathbf 1_n + B (\mathbf 1_m - AB)^{-1} A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BA + BAB (\mathbf 1_m - AB)^{-1} A \
&amp;amp; = \mathbf 1_n - BA&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;B ((\mathbf 1_m - AB)^{-1} + AB (\mathbf 1_m - AB)^{-1}) A \
&amp;amp; = \mathbf 1_n - BA + B (\mathbf 1_m + AB) (\mathbf 1_m - AB)^{-1} A \
&amp;amp; = \mathbf 1_n - BA + BA \
&amp;amp; = \mathbf 1_n
\end{align*}
$$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;即可。但是，这个构造似乎有些复杂，直接猜想多半是找不到的。因此，我们事实上需要通过某些方式「解」出这个构造。&lt;/p&gt;
&lt;p&gt;直接设 $(\mathbf 1_n - BA)^{-1} = X$ 并不是一个好主意，读者可以自行尝试如此，我们除了应用定义以外似乎做不了任何事情。因此我们需要让问题复杂化一点。&lt;/p&gt;
&lt;p&gt;观察条件，事实上我们需要求一个 $X$ , 使得 $(\mathbf 1_n - BA) X = \mathbf 1_n$ . 我们发现等式的两边都有 $\mathbf 1_n$ , 或许可以联想到 $\mathbf 1_n \mathbf 1_n = \mathbf 1_n$ 这一事实。我们可以设 $X = \mathbf 1_n + X_1$ 的形式。这样，等式的左边就已经有一个 $\mathbf 1_n$ , 只要让 $X_1$ 满足能够抵消掉其他的项即可。&lt;/p&gt;
&lt;p&gt;$$
X_1 - BA - BAX_1 = \mathbf 0_{n \times n}
$$&lt;/p&gt;
&lt;p&gt;这个方程至少有了更多可处理的方式。现在是整个过程中最难想到的一步。我们想要利用上 $(\mathbf 1_m - AB)^{-1}$ , 就需要有 $AB$ 的形式。但是现在等式中只有 $BA$ . 我们希望在与 $X_1$ 的乘法中出现 $AB$ , 观察到现在 $(\mathbf 1_n - BA)$ 结尾已经有一个 $A$ , 我们让 $X_1$ 的开头补上一个 $B$ 来凑成 $AB$ .&lt;/p&gt;
&lt;p&gt;设 $X_1 = B X_2$ . 则有&lt;/p&gt;
&lt;p&gt;$$
BX_2 - BA - BABX_2 = \mathbf 0_{n \times n}
$$&lt;/p&gt;
&lt;p&gt;化简&lt;/p&gt;
&lt;p&gt;$$
B (\mathbf 1_m - AB) X_2 = BA
$$&lt;/p&gt;
&lt;p&gt;这时就可以看出令 $X_2 = (\mathbf 1_m - AB)^{-1} A$ 即可。于是就有了 $X = \mathbf 1_n + B (\mathbf 1_m - AB)^{-1} A$ .&lt;/p&gt;
</content:encoded></item><item><title>厄尔尼诺-南方涛动实在是太简单了</title><link>https://misaka10987.github.io/posts/xite/enso/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/xite/enso/</guid><pubDate>Tue, 16 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;厄尔尼诺-南方涛动实在是太简单了&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;本质上是南方涛动指数的周期性变化&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;南美洲暴雨&lt;/h2&gt;
&lt;p&gt;人类的气象观测发现，在一部分年份，赤道地区太平洋东岸（主要是南美洲）地区气候显著暖湿，引发洪水、传染病等灾害；相反地，在太平洋西岸（主要是印尼、澳大利亚等地区），气候显著干冷，导致干旱或森林大火，西北太平洋台风等级增强。秘鲁人将其称为 &lt;strong&gt;厄尔尼诺 (El Niño)&lt;/strong&gt; , 因南美多在圣诞节前后感受，以西班牙语 &lt;em&gt;El Niño de Navidad&lt;/em&gt; （「新生的耶稣」）名。&lt;/p&gt;
&lt;h2&gt;从 Walker 环流开始&lt;/h2&gt;
&lt;p&gt;在太平洋赤道地区，信风（东风）会推动海水自东向西流动，形成 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8D%97%E8%B5%A4%E9%81%93%E6%B4%8B%E6%B5%81&quot;&gt;南&lt;/a&gt; 、&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8C%97%E8%B5%A4%E9%81%93%E6%9A%96%E6%B5%81&quot;&gt;北&lt;/a&gt; 赤道暖流（注意赤道无风区有补偿的 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%B5%A4%E9%81%93%E9%80%86%E6%B5%81&quot;&gt;赤道逆流&lt;/a&gt; ）。暖流驱使表层温暖海水在西岸堆积，深层冷水在东岸 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%B8%8A%E5%8D%87%E6%B5%81&quot;&gt;上升&lt;/a&gt; 形成 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%A7%98%E9%AD%AF%E6%B6%BC%E6%B5%81&quot;&gt;秘鲁&lt;/a&gt; 和 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8A%A0%E5%88%A9%E7%A6%8F%E5%B0%BC%E4%BA%9E%E6%B4%8B%E6%B5%81&quot;&gt;加利福尼亚&lt;/a&gt; 寒流。这使得太平洋整体呈现出西热东冷的热量分布。&lt;/p&gt;
&lt;p&gt;这个过程是正反馈的。由于西太平洋较东太平洋温暖，低压热空气在西太平洋上升，驱动热力环流加强东风，从而将更多暖水向西搬运。这个环流命名为 &lt;strong&gt;Walker 环流&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;walker.png&quot; alt=&quot;Walker 环流&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;南方涛动指数&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;南方涛动指数 (Southern Oscillation Index, SOI)&lt;/strong&gt; 是反映 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%A4%A7%E6%BA%AA%E5%9C%B0%E5%B3%B6&quot;&gt;大溪地&lt;/a&gt;（法属波利尼西亚，东太平洋）与 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%BE%BE%E5%B0%94%E6%96%87_(%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A)&quot;&gt;达尔文&lt;/a&gt;（澳大利亚，西太平洋）气压差值的函数。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.bom.gov.au/climate/enso/soi/&quot;&gt;澳大利亚气象局&lt;/a&gt; 具体定义为，若某月大溪地平均气压 $P_\mathrm{Tahiti}$ , 达尔文平均气压 $P_\mathrm{Darwin}$ , 令 $\Delta$ 和 $\sigma$ 分别为 1951-2000 年当月的气压差平均值和标准差，则标准化的南方涛动指数为&lt;/p&gt;
&lt;p&gt;$$
\mathrm{SOI}=10 \cdot \frac{P_\mathrm{Tahiti} - P_\mathrm{Darwin} - \Delta}{\sigma}
$$&lt;/p&gt;
&lt;p&gt;展开定义，SOI 标志 Walker 环流的强度。SOI 越大时，东太平洋气压高出西太平洋更多，相应东风更强，反之亦然。&lt;/p&gt;
&lt;h2&gt;周期性变化&lt;/h2&gt;
&lt;p&gt;在现实中，Walker 环流并非恒常处于平衡，而正反馈特点与气象系统的混沌性使得它对多种扰动较为敏感。这在气象记录上显示出近似于以 4 年为周期的反复振动。振动的具体机制或许是因为海水不允许凭空出现或消失，在正反馈循环进行到一定程度时会发生过冲，触发 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%BC%80%E5%B0%94%E6%96%87%E6%B3%A2&quot;&gt;开尔文波&lt;/a&gt; 等负反馈。&lt;/p&gt;
&lt;p&gt;SOI 也因此得名「震荡」指数。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;soi-20yr.svg&quot; alt=&quot;近 20 年 SOI 变化&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;拉尼娜现象&lt;/h2&gt;
&lt;p&gt;当南方涛动位于高峰期时，Walker 环流强大，东风盛行，南北赤道暖流活跃，东太平洋海水超常降温。与东太平洋海水升温的厄尔尼诺现象对应，命名为 &lt;strong&gt;拉尼娜现象 (La Niña)&lt;/strong&gt;（西班牙语「女孩」）。&lt;/p&gt;
&lt;h3&gt;西岸&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;更强的东风输送了更多太平洋暖湿水汽，造成东南亚与澳大利亚地区暴雨，气温异常上升；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;暖水在西太平洋堆积，海平面升高；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;西北太平洋面升温，支持更多台风形成，但台风强度可能减小。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;东岸&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;涌升寒流加强，海面营养增加，秘鲁地区渔获增加；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;南北美洲气候干燥凉爽。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;气象系统的不确定性可能造成众多其他后果。例如，2008 年 &lt;a href=&quot;https://zh.wikipedia.org/wiki/2008%E5%B9%B4%E4%B8%AD%E5%9B%BD%E9%9B%AA%E7%81%BE&quot;&gt;南方雪灾&lt;/a&gt; 是拉尼娜现象引起的。&lt;/p&gt;
&lt;h2&gt;厄尔尼诺现象&lt;/h2&gt;
&lt;p&gt;在南方涛动处于低谷期时，Walker 环流被逆转或削弱，信风减弱或转为西风，赤道暖流消失，暖水滞留在东太平洋造成海面异常升温。这就是秘鲁的渔民观察到的厄尔尼诺现象。&lt;/p&gt;
&lt;h3&gt;西岸&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;水汽输运停止，降水减少，气候转冷，东南亚与澳大利亚地区受到干旱与森林大火威胁；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;西北太平洋暖池向东退却，台风生成更少且更偏远，但更有可能加强威力。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;东岸&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;冷水上升停止，营养含量下降，赤道海面异常升温，造成鱼类死亡和渔获减少；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;南美洲暴雨多发，造成洪灾。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;厄尔尼诺现象在美国（AP ES 内容）&lt;/h2&gt;
&lt;p&gt;AP 环境科学额外包含了厄尔尼诺现象对美国不同地区的影响，这些包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;加利福尼亚暴雨；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;西北、阿拉斯加、中西部和新英格兰温暖干燥，容易出现暖冬；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;南部凉爽潮湿，降水可造成洪灾；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;东海岸飓风活动倾向于减弱。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Ad: 华师大二附中国际课程班高三数学</title><link>https://misaka10987.github.io/posts/advertise/efzgkb-g12-math/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/advertise/efzgkb-g12-math/</guid><pubDate>Mon, 15 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Ad: 华师大二附中国际课程班高三数学&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;/p&gt;
&lt;p&gt;本项目被迁移至 &lt;a href=&quot;https://efzgkb-g12-math.pages.dev/&quot;&gt;Cloudflare&lt;/a&gt; , 原有 &lt;a href=&quot;https://misaka10987.github.io/site-efzgkb-g12-math&quot;&gt;Github Pages&lt;/a&gt; 链接作废。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://efzgkb-g12-math.pages.dev/&quot;&gt;链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;实时更新各类课程资料。&lt;/p&gt;
</content:encoded></item><item><title>在 Maxima 中计算矩阵的简化行阶梯形式</title><link>https://misaka10987.github.io/posts/maxima-rref/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/maxima-rref/</guid><pubDate>Sat, 06 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;在 Maxima 中计算矩阵的简化行阶梯形式&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://maxima.sourceforge.io/&quot;&gt;Maxima&lt;/a&gt; 中仅提供了 &lt;code&gt;echelon&lt;/code&gt; 函数用于计算矩阵的行阶梯形式 (row echelon form), 默认并不能计算简化行阶梯形式 (reduced row echelon form).&lt;/p&gt;
&lt;p&gt;笔者在完成数学作业时具有计算简化行阶梯形式的需求，最终在这一 &lt;a href=&quot;https://stackoverflow.com/questions/30693793/how-to-find-the-reduced-row-echelon-form-of-a-matrix-in-maxima&quot;&gt;Stack Overflow&lt;/a&gt; 找到了手动实现。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rref(a):=block([p,q,k],[p,q]:matrix_size(a),a:echelon(a),
    k:min(p,q),
    for i thru min(p,q) do (if a[i,i]=0 then (k:i-1,return())),
    for i:k thru 2 step -1 do (for j from i-1 thru 1 step -1 do a:rowop(a,j,i,a[j,i])),
    a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实现采用了朴素的循环方法，将矩阵化为行阶梯形式后从上到下消每一个主元上面的元素。&lt;/p&gt;
</content:encoded></item><item><title>单子实在是太简单了</title><link>https://misaka10987.github.io/posts/xite/monad/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/xite/monad/</guid><description>使用 TypeScript 的简明单子解释</description><pubDate>Mon, 01 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;单子实在是太简单了&lt;/h1&gt;
&lt;p&gt;你或许在复数场合下的讨论中见到一些 Haskell 用户使用这样讨嫌的话语：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Monad 就是一个自函子范畴中的幺半群。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是，笔者（或许和你一样）并不懂 Haskell 语言。此时，你并不知道对方究竟是理解了某些问题的本质，还是在堆砌名词和复制话术。你也不知道 TA 说的东西关乎正在 Web 前端编程的你什么事。如果这是真实的，那本文旨在解决你的问题。&lt;/p&gt;
&lt;h2&gt;先决条件&lt;/h2&gt;
&lt;p&gt;本文假设你会熟练的 TypeScript 编程，可以听懂一些编程中的高级概念，并且对于类型论有非常浅薄的理解。你不需要有对 TypeScript 类型体操的深入了解。&lt;/p&gt;
&lt;p&gt;需要注意的是，本文可能包括一些数学定义。你可能需要作在阅读中浏览维基百科或其他外部资料链接的准备。你同样有可能阅读相关的 TypeScript 文档，或者打开代码编辑器做一些实验。&lt;/p&gt;
&lt;h2&gt;从异步编程开始&lt;/h2&gt;
&lt;p&gt;你知道 TypeScript 中可以这样异步编程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async () =&amp;gt; {
  const result = await getSomeAsync()
  return await getAnotherAsync(result)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你对历史有些了解的话，你还知道可以这样异步编程（通过 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot;&gt;Promise&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;getSomeAsync().then(getAnotherAsync)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这看上去不如 &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; 直观。对大多数人来说，现代方法才是我们想要的。&lt;/p&gt;
&lt;p&gt;当然，如果你观察得更仔细一些的话，你或许会注意到 &lt;code&gt;async&lt;/code&gt; 其实隐式地构造了一个 &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; , 而 &lt;code&gt;await&lt;/code&gt; 做的事情其实就是从这个 &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; 中取出 &lt;code&gt;T&lt;/code&gt; . 我们的异步编程终究没能离开 &lt;code&gt;Promise&lt;/code&gt; .&lt;/p&gt;
&lt;h3&gt;为什么要有 &lt;code&gt;Promise&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;此时的你或许会开始想：有没有不使用 &lt;code&gt;Promise&lt;/code&gt; 的异步编程？&lt;em&gt;有的。&lt;/em&gt; 只不过它的形式可能与你想象的不太一样。&lt;/p&gt;
&lt;p&gt;「异步」是什么？如果我们暂时放下建立起的高级抽象，观看异步过程的实现的话，类似于一个「把水烧着，然后去做别的事，等听到水开了，过来把水倒进热水壶中」的操作。我们告诉机器需要做什么，然后并不等待执行完成，而是告诉机器现在可以去做别的工作。执行完成后，机器再回来继续我们告诉它的第一个工作。&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; 是对这种操作的好的建模。&lt;code&gt;async&lt;/code&gt; 就相当于「告诉机器，这项任务需要等待」，而 &lt;code&gt;await&lt;/code&gt; 相当于「告诉机器，现在不必坐等，去做些别的事情」。&lt;/p&gt;
&lt;p&gt;不用 &lt;code&gt;Promise&lt;/code&gt; 怎么告诉机器这样的概念？这不困难。想象我们先有一个阻塞版本的烧水函数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const boil = () =&amp;gt; {
  // do something
  return &apos;boiled&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们会写这样的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// this blocks current thread
const boiled = boil()
// do some other work
const bottle = new Bottle()
pourInto(bottle, boiled)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果我们想把 &lt;code&gt;boil&lt;/code&gt; 改成非阻塞的，那么直接使用上面的代码不能够保证在我们「把水倒进热水壶」时「水已经被烧好了」。轮询 &lt;code&gt;boil&lt;/code&gt; 的完成情况会愚蠢地退化为同步情况。既然我们并不能知道 &lt;code&gt;boil&lt;/code&gt; 是否完成，我们可以让知道的角色—— &lt;code&gt;boil&lt;/code&gt; 的实现来判断。但 &lt;code&gt;boil&lt;/code&gt; 的实现并不能知道我们接下来要做什么。或许你想到了解决方案：给它一个回调在完成后执行。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const boil = &amp;lt;T&amp;gt;(next: (_: string) =&amp;gt; T) =&amp;gt; {
  // do something
  const result = &apos;boiled&apos;
  return next(&apos;boiled&apos;)
}

boil((boiled) =&amp;gt; {
  const bottle = new Bottle()
  pourInto(bottle, boiled)
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;很好！对于用户来说，使用 &lt;code&gt;boil&lt;/code&gt; 的体验与异步编程一样。我们并不用关心 &lt;code&gt;boil&lt;/code&gt; 的具体实现，而假装这个函数是异步的（事实上，由于 JavaScript 是单线程的，你完全不会想要手动轮询，而我们使用的异步函数本质上由 JavaScript 运行时的事件循环统一轮询）。从始至终我们没有使用 &lt;code&gt;Promise&lt;/code&gt; , 只用回调就解决了问题。&lt;/p&gt;
&lt;h3&gt;回调地狱&lt;/h3&gt;
&lt;p&gt;你掌握了通过回调进行异步编程的技巧。现在有很多异步任务，需要被顺序执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const task1 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {}
const task2 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {}
const task3 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {}
const task4 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {}
const task5 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;于是你写出这样的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;task1(() =&amp;gt; {
  task2(() =&amp;gt; {
    task3(() =&amp;gt; {
      task4(() =&amp;gt; {
        task5(() =&amp;gt; {})
      })
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不停地嵌套回调让你的代码变得丑陋。这种现象被称为 &lt;strong&gt;回调地狱&lt;/strong&gt; 。为了实现异步编程，你不得不忍受这些恶心的语法噪音，破坏了可读性与可维护性。&lt;/p&gt;
&lt;h3&gt;展平回调嵌套&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Promise&lt;/code&gt; 就是为了解决这个问题。&lt;/p&gt;
&lt;p&gt;这可能有些技巧性，或者并不容易想到。你可以这样认为，&lt;code&gt;Promise&lt;/code&gt; 之所以能工作，是利用了「带有回调的回调可以被转化成两个回调」这一特性。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const task1 = &amp;lt;T&amp;gt;(next: () =&amp;gt; T) =&amp;gt; {
  // do something
  return next()
}
const task2 = &amp;lt;T, U&amp;gt;(next: (_: T) =&amp;gt; U) =&amp;gt; {
  const result = /* do something */
  return next(result)
}
task1(() =&amp;gt; {
  task2(() =&amp;gt; {})
})

const combined = &amp;lt;T, U&amp;gt;(next1: () =&amp;gt; T, next2: (_: T) =&amp;gt; U) =&amp;gt; {
  // do something
  const result = next1()
  return next2(result)
}
combined(
  () =&amp;gt; {},
  () =&amp;gt; {}
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但在签名中添加回调的数量只会让情况变得更糟。我们想要在签名中用一个类型的参数表示「任意数量的回调」，并且帮我们自动将展平后的回调嵌套起来。这个类型就是 &lt;code&gt;Promise&lt;/code&gt; . 一个相对标准库的简化版不含 &lt;code&gt;reject&lt;/code&gt; 的 &lt;code&gt;Promise&lt;/code&gt; 定义如下。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MyPromise&amp;lt;T&amp;gt; {
  #poll: () =&amp;gt; T | null

  private constructor(poll: () =&amp;gt; T | null) {
    this.#poll = poll
  }

  static resolve&amp;lt;T&amp;gt;(value: T): MyPromise&amp;lt;T&amp;gt; {
    return new MyPromise(() =&amp;gt; value)
  }

  then&amp;lt;U&amp;gt;(next: (_: T) =&amp;gt; U | MyPromise&amp;lt;U&amp;gt;): MyPromise&amp;lt;U&amp;gt; {
    const poll = () =&amp;gt; {
      const result = this.#poll()
      if (result === null) {
        return null
      }
      const promise = next(result)
      if (promise instanceof MyPromise) {
        return promise.#poll()
      } else {
        return promise
      }
    }
    return new MyPromise(poll)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;#poll: () =&amp;gt; T | null&lt;/code&gt; 是我们的（嵌套起来的）轮询函数，&lt;code&gt;null&lt;/code&gt; 表示尚未完成；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;static resolve&amp;lt;T&amp;gt;(value: T): MyPromise&amp;lt;T&amp;gt;&lt;/code&gt; 用来构造一个直接返回不必等待的轮询。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;then&amp;lt;U&amp;gt;(next: (_: T) =&amp;gt; U | MyPromise&amp;lt;U&amp;gt;): MyPromise&amp;lt;U&amp;gt;&lt;/code&gt; 是最有趣的一部分。我们来看它做了什么：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果当前 &lt;code&gt;MyPromise&lt;/code&gt; 尚未完成，则新的 &lt;code&gt;MyPromise&lt;/code&gt; 尚未完成；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果当前 &lt;code&gt;MyPromise&lt;/code&gt; 完成了，将 &lt;code&gt;next&lt;/code&gt; 应用于结果并等待新的结果完成。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;声明为 &lt;code&gt;U | MyPromise&amp;lt;U&amp;gt;&lt;/code&gt; 是为了兼容普通函数的便利，不必每次手写 &lt;code&gt;MyPromise.resolve&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这相当于利用我们刚才提到的特性，将两个函数复合为了一个函数。这样，在不断应用 &lt;code&gt;then&lt;/code&gt; 时，我们得到的并不是 &lt;code&gt;MyPromise&amp;lt;MyPromise&amp;lt; /* ... */ &amp;gt;&amp;gt;&lt;/code&gt; 这样的多层嵌套，而始终只有一层 &lt;code&gt;MyPromise&lt;/code&gt; ! 这就是 &lt;code&gt;MyPromise&lt;/code&gt; 如何工作的。以下是一个使用 &lt;code&gt;MyPromise&lt;/code&gt; 的实例，注意标准库的 &lt;code&gt;Promise&lt;/code&gt; 不允许手动轮询。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const task1 = () =&amp;gt; {
  // do something
  return MyPromise.resolve(&apos;result1&apos;)
}
const task2 = (input: string) =&amp;gt; {
  console.info(`task2 input is ${input}`)
  return MyPromise.resolve(&apos;result2&apos;)
}
const task3 = (input: string) =&amp;gt; {
  console.info(`task3 input is ${input}`)
  return MyPromise.resolve(&apos;result3&apos;)
}

task1().then(task2).then(task3).blocking_poll()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到，我们现在用链式调用替代了原先的回调嵌套。这极大增加了可读性。通过 &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; 语法糖，我们可以用现代化的范式异步编程。这种形式被称为单子化 (Monadic) API.&lt;/p&gt;
&lt;h2&gt;其它 TypeScript 单子&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Promise&lt;/code&gt; 并不是唯一的 TypeScript 单子。事实上，单子化 API 在许多语言中相当普遍。例如，我们可以使用数组的 &lt;code&gt;Array.flatMap&lt;/code&gt; 将嵌套数组展平，而不必写多重循环；&lt;code&gt;?.&lt;/code&gt; 运算符其实是 Option, 或者说 &lt;code&gt;T | undefined&lt;/code&gt; 单子的语法糖，它将 &lt;code&gt;(T | undefined) | undefined&lt;/code&gt; 展平成 &lt;code&gt;T | undefined&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;我们甚至可以通用地描述一个单子的行为（注意 &lt;code&gt;unit&lt;/code&gt; 其实应该是静态方法，这里限于 TypeScript 语法）。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;interface Monad&amp;lt;T&amp;gt; {
  unit(value: T): Monad&amp;lt;T&amp;gt;
  flatMap&amp;lt;U&amp;gt;(fn: (_: T) =&amp;gt; Monad&amp;lt;U&amp;gt;): Monad&amp;lt;U&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对于 &lt;code&gt;Promise&lt;/code&gt; , &lt;code&gt;resolve&lt;/code&gt; 就是 &lt;code&gt;unit&lt;/code&gt; , &lt;code&gt;then&lt;/code&gt; 就是 &lt;code&gt;flatMap&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;换句话说，单子的核心就是 &lt;code&gt;flatMap&lt;/code&gt; : 将一个对 &lt;code&gt;Monad&amp;lt;T&amp;gt;&lt;/code&gt; 应用 &lt;code&gt;(_ : T) =&amp;gt; Monad&amp;lt;U&amp;gt;&lt;/code&gt; 得到 &lt;code&gt;Monad&amp;lt;U&amp;gt;&lt;/code&gt; . 配合 &lt;code&gt;flatMap&lt;/code&gt; 将嵌套的类型展平（从 &lt;code&gt;Monad&amp;lt;Monad&amp;lt; /* */ &amp;gt;&amp;gt;&lt;/code&gt;）是单子的主要特性。这种特性允许我们方便地通过单子建模代码的某些「效应」，例如异步性、数组（迭代器）、可空性等。严谨地说，这是用来实现 &lt;strong&gt;代数效应&lt;/strong&gt; 的方式。&lt;/p&gt;
&lt;p&gt;以下文字由 ChatGPT 生成：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;代数效应是一种 &lt;strong&gt;将副作用（effect）抽象化为操作（operation）&lt;/strong&gt; 的方式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;传统副作用：例如打印、读写文件、抛异常、状态修改。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;代数效应：把这些副作用当作&lt;strong&gt;可定义的操作&lt;/strong&gt;，然后由 &lt;strong&gt;处理器（handler）&lt;/strong&gt; 来解释它们的行为。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;换句话说，你不直接执行副作用，而是&lt;strong&gt;声明“我想要做这个副作用”&lt;/strong&gt;，然后由另一个部分来决定如何实现它。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;抽象&lt;/h2&gt;
&lt;p&gt;让所有 TypeScript 类型构成一个 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%AF%84%E7%96%87_(%E6%95%B8%E5%AD%B8)&quot;&gt;范畴&lt;/a&gt; $\mathscr T$ . 其中，每一个 TypeScript 类型都是范畴中的对象，每一组 TypeScript 类型之间的函数都是一个 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%80%81%E5%B0%84&quot;&gt;态射&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;我们考虑这个范畴上的 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%87%BD%E5%AD%90#%E5%AE%9A%E7%BE%A9&quot;&gt;自函子&lt;/a&gt; 。以 &lt;code&gt;Promise&lt;/code&gt; 为例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对每一个 TypeScript 类型，都映到了一个 TypeScript 类型；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于函数 &lt;code&gt;(x: T) =&amp;gt; y as U&lt;/code&gt; , 可以构造 &lt;code&gt;const f = (x: Promise&amp;lt;T&amp;gt;) =&amp;gt; x.then((x: T) =&amp;gt; y as U) as Promise&amp;lt;U&amp;gt;&lt;/code&gt; 来处理态射;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你可以利用 &lt;code&gt;Promise.then&lt;/code&gt; 验证结合律和单位态射的保持。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，在通过 &lt;code&gt;Promise.then&lt;/code&gt; 提升函数的情况下，&lt;code&gt;Promise&lt;/code&gt; 构成了一个自函子 $P:\mathscr T \to \mathscr T$ .&lt;/p&gt;
&lt;p&gt;在范畴论中，一个 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%B9%BA%E5%8D%8A%E7%BE%A4#%E5%92%8C%E7%AF%84%E7%96%87%E8%AB%96%E7%9A%84%E9%97%9C%E4%BF%82&quot;&gt;幺半群 (Monoid)&lt;/a&gt; 是一个单对象范畴。通常，我们会将幺半群定义为一个 $(M,*:M\times M \to M, 1:M)$ , 满足：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\forall a, b, c \in M, (a * b) * c = a * (b * c)$ ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\forall a \in M, a * 1 = 1 * a = 1$ .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在范畴 $\mathscr C$ 中，我们可以选取一个对象 $M$ , 如果有态射&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\mu: M \times M \to M$ 作为乘法，满足结合律；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\eta: 1 \to M$ 作为单位元。其中 $1$ 是 $\mathscr C$ 的单位对象（满足 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E8%AE%8A%E6%8F%9B#%E5%87%BD%E5%AD%90%E7%AF%84%E7%96%87&quot;&gt;自然同构&lt;/a&gt; $1 \times X \cong X \cong X \times 1$ 对于任意 $X \in \mathrm{Obj}(\mathscr C)$ ）.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那么 $(M,\mu,\eta)$ 就组成一个 &lt;strong&gt;幺半群对象 (Monoid Object)&lt;/strong&gt; . 和群一样，我们经常在不需要时记作 $M$ . 对于我们在抽象代数中研究的 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%B9%BA%E5%8D%8A%E7%BE%A4&quot;&gt;幺半群&lt;/a&gt; ，就是一个集合范畴中的幺半群对象 $(M,\mu,\eta)$ , 其中 $M$ 是群元的集合，$\mu$ 是群的乘法，$\eta$ 是群的单位元。集合范畴的单位对象是单点集 $\left{ * \right}$ .&lt;/p&gt;
&lt;p&gt;让我们回到 &lt;code&gt;Promise&lt;/code&gt; . 在自函子范畴 $\mathscr T \to \mathscr T$ 中，考虑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Promise&lt;/code&gt; 这个自函子，或者说类型函数作为对象；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于任何两个 &lt;code&gt;Promise&lt;/code&gt; 的对象 &lt;code&gt;Promise&lt;/code&gt; （或者说 &lt;code&gt;T&lt;/code&gt; $\mapsto$ &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; ）, 其乘积 &lt;code&gt;Promise&lt;/code&gt; $\times$ &lt;code&gt;Promise&lt;/code&gt; （或者说 &lt;code&gt;T&lt;/code&gt; $\mapsto$ &lt;code&gt;Promise&amp;lt;Promise&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; ）被 &lt;code&gt;Promise.then&lt;/code&gt; 展平成 &lt;code&gt;T&lt;/code&gt; $\mapsto$ &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; , 也就是将 &lt;code&gt;Promise.then&lt;/code&gt; 作为封闭的乘法运算。你可以验证它满足结合律；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\mathscr T$ 的单位对象是恒等类型函数 &lt;code&gt;type Id&amp;lt;T&amp;gt; = T&lt;/code&gt; . 而 &lt;code&gt;Promise&lt;/code&gt; 的单位元是 &lt;code&gt;Promise.resolve&lt;/code&gt; : &lt;code&gt;Id&lt;/code&gt; $\to$ &lt;code&gt;Promise&lt;/code&gt; .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以 $(\mathtt{Promise}, \mathtt{then}, \mathtt{resolve})$ 是一个幺半群对象。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Monad 就是一个自函子范畴中的幺半群。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;这有什么用&lt;/h2&gt;
&lt;p&gt;事实上，你完全没有必要了解「自函子范畴中的幺半群」来利用单子化 API. 笔者以为在许多语境下，一些人不合适宜地恰当或不恰当地使用范畴论名词来讨论编程设计，是不利于理解的。最直观的，符合人类直觉的方式就是将单子理解为 &lt;code&gt;flatMap&lt;/code&gt; , 一个将 &lt;code&gt;Monad&amp;lt;Monad&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; 展平成 &lt;code&gt;Monad&amp;lt;T&amp;gt;&lt;/code&gt; 的工具。但这带来了一点数学，不是吗？我们可以从更高的抽象层次来设计我们的 API.&lt;/p&gt;
&lt;p&gt;单子亦有其局限性。例如，乘法交换律并不总是成立，这会使我们面临类似 &lt;code&gt;Promise&amp;lt;T[]&amp;gt;&lt;/code&gt; $\ne$ &lt;code&gt;Promise&amp;lt;T&amp;gt;[]&lt;/code&gt; 的问题，需要我们手动处理。&lt;em&gt;我们需要更好的代数效应。&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Pacman 数据库文件锁</title><link>https://misaka10987.github.io/posts/pacman-db-lock/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/pacman-db-lock/</guid><pubDate>Sun, 31 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Pacman 数据库文件锁&lt;/h1&gt;
&lt;p&gt;Pacman 会创建锁文件 &lt;code&gt;/var/lib/pacman/db.lck&lt;/code&gt; 以确保软件包数据库不被并发修改。&lt;/p&gt;
&lt;p&gt;在非正常退出时，可能会出现锁文件未释放的情况。此时可能会出现类似错误：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:: 正在同步软件包数据库...
错误：未能同步所有数据库（无法锁定数据库）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;确保没有 &lt;code&gt;pacman&lt;/code&gt; 进程正在运行，然后删除文件即可。&lt;/p&gt;
</content:encoded></item><item><title>曲面的分类</title><link>https://misaka10987.github.io/posts/migrate/class-of-surface/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/class-of-surface/</guid><pubDate>Wed, 23 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;曲面的分类&lt;/h1&gt;
&lt;h2&gt;无边界曲面&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%9B%B2%E9%9D%A2#%E9%97%AD%E6%9B%B2%E9%9D%A2%E5%88%86%E7%B1%BB&quot;&gt;紧致无边界曲面分类定理&lt;/a&gt;给出，任意一个紧致、连通、无边界的曲面，必然同胚于以下某一曲面。进一步地，如果已知曲面的欧拉数与可定向性，即可具体确定哪一种类。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;曲面&lt;/th&gt;
&lt;th&gt;欧拉数 $\chi$&lt;/th&gt;
&lt;th&gt;可定向性&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;球 $\mathbb S^2$&lt;/td&gt;
&lt;td&gt;$2$&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;环的连通和 $#^g\mathbb T^2$ , 其中 $g\in\N^*$ 为&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%BA%8F%E6%A0%BC&quot;&gt;亏格&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$2-2g$&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;实射影平面的连通和 $#^n\mathbb{RP}^2$ , $n\in\N^*$&lt;/td&gt;
&lt;td&gt;$2-n$&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;有边界曲面&lt;/h2&gt;
&lt;p&gt;所有柄数和边界数相等的可定向有边界紧致连通曲面同胚；所有交叉柄数和边界数相等的不可定向有边界紧致连通曲面同胚。&lt;/p&gt;
&lt;h2&gt;通用形式&lt;/h2&gt;
&lt;p&gt;任何紧致连通曲面 $M$ 一定同胚于以下形式的曲面：&lt;/p&gt;
&lt;p&gt;$$
\mathbb S^2\mathbin#(#^g\mathbb T^2)\mathbin#(#^c\mathbb{RP}^2)\mathbin#(#^bD)
$$&lt;/p&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\mathbb S^2$ 球面为没有其它项时的默认结果，与之作连通和不改变曲面的种类；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$#^g\mathbb T^2$ 项表示添加 $g$ 个环面来构建曲面，$g$ 表示曲面的亏格；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$#^c\mathbb{RP}^2$ 引入 $c$ 个交叉柄，如果至少有一个 $\mathbb{RP}^2$ , 曲面不可定向；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$#^bD$ 表示挖去 $b$ 个圆盘，或为曲面引入 $b$ 条边界。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，一个莫比乌斯环 $M_\mathrm{M&quot;{o}bius}$ 同胚于&lt;/p&gt;
&lt;p&gt;$$
\mathbb{RP}^2\mathbin#D
$$&lt;/p&gt;
&lt;p&gt;即实射影平面挖去一个圆盘。&lt;/p&gt;
</content:encoded></item><item><title>Arch Linux 睡眠后唤醒时黑屏问题</title><link>https://misaka10987.github.io/posts/migrate/archlinux-wakeup-blackscreen/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/archlinux-wakeup-blackscreen/</guid><pubDate>Fri, 18 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Arch Linux 睡眠后唤醒时黑屏问题&lt;/h1&gt;
&lt;p&gt;如果您的 Arch Linux 正在使用 AMD 显卡与 &lt;code&gt;amdgpu&lt;/code&gt; 驱动，系统可以正常启动，但在睡眠后唤醒时，显示黑屏，或睡眠前的最后一帧画面，则可能是显卡驱动未及时加载所导致。此时内核日志很可能不记录任何睡眠后，尝试唤醒的消息。&lt;/p&gt;
&lt;p&gt;经测试，一种可行的解决方法是要求内核先加载显卡驱动：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MODULES+=(amdgpu)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;记得重新生成镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkinitcpio -P
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>给 Hugo 网站添加 Live2D 看板娘</title><link>https://misaka10987.github.io/posts/migrate/live2d-widget/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/live2d-widget/</guid><pubDate>Tue, 15 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;UPDATE: 由于很多细节不够完善，我暂时禁用了 Live2D.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;params.toml&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[live2d]
enable = false
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;给 Hugo 网站添加 Live2D 看板娘&lt;/h1&gt;
&lt;p&gt;完成效果参考本站左下角。Live2D 基于 &lt;a href=&quot;https://www.live2d.com/en/&quot;&gt;Cubism&lt;/a&gt; 模型，通过 &lt;a href=&quot;https://github.com/stevenjoezhang/live2d-widget&quot;&gt;Live2D Widget&lt;/a&gt; 在网页端渲染。此处的胡桃模型由 &lt;a href=&quot;https://space.bilibili.com/23315579&quot;&gt;@根瘤菌rkzj&lt;/a&gt; 创作。&lt;/p&gt;
&lt;h2&gt;准备模型&lt;/h2&gt;
&lt;p&gt;一个 Cubism 模型资源一般以目录的形式存在，通过指向其下 &lt;code&gt;model3.json&lt;/code&gt; 的 URL 引用。由于 Live2D 模型多体积较大，可使用 CDN 加快分发。本站使用了 &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Pages&lt;/a&gt; 部署静态文件。&lt;/p&gt;
&lt;h3&gt;贴图大小&lt;/h3&gt;
&lt;p&gt;有些模型的贴图分辨率过高，可适当缩小贴图，减小文件体积以加速。&lt;/p&gt;
&lt;h2&gt;Hugo 自定义 JavaScript 加载&lt;/h2&gt;
&lt;p&gt;Hugo 会将网站渲染为静态 HTML. 因此，我们需要在客户端插入 JavaScript 来渲染自定义组件。&lt;/p&gt;
&lt;p&gt;本站使用 &lt;a href=&quot;https://stack.jimmycai.com/&quot;&gt;Stack&lt;/a&gt; 主题。查阅其文档可知：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There are two empty files reserved for custom HTML in the theme, useful for adding custom scripts or stylesheets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;layouts/partials/head/custom.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layouts/partials/footer/custom.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Live2D 的加载较为费时，因此我们将其插入到页脚中，不拖慢网页主体加载。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;layouts/partials/footer/custom.html&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;module&quot; src=&quot;/live2d/main.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将加载我们将会放在 &lt;code&gt;static/live2d/main.js&lt;/code&gt; 下的脚本。Hugo 将 &lt;code&gt;static/$path&lt;/code&gt; 下的文件映射到 &lt;code&gt;/$path&lt;/code&gt; 路由上。&lt;/p&gt;
&lt;h2&gt;安装依赖&lt;/h2&gt;
&lt;p&gt;我们从 Live2D Widget 仓库的分发中下载其代码库本体 &lt;code&gt;waifu-tips.js&lt;/code&gt; 与 Cubism 渲染器依赖 &lt;code&gt;live2d.min.js&lt;/code&gt; , 置于静态目录中。&lt;/p&gt;
&lt;h2&gt;编写 JavaScript&lt;/h2&gt;
&lt;p&gt;我们使用 ES Module 来简化动态资源的加载过程。导入并调用 Live2D Widget 库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &apos;./waifu-tips.js&apos;

initWidget({
  waifuPath: &apos;/live2d/config.json&apos;,
  cubism2Path: &apos;/live2d/live2d.min.js&apos;,
  cubism5Path:
    &apos;https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js&apos;,
  tools: [&apos;hitokoto&apos;, &apos;asteroids&apos;, &apos;photo&apos;, &apos;info&apos;, &apos;quit&apos;],
  logLevel: &apos;warn&apos;,
  drag: false,
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;initWidget&lt;/code&gt; 的参数可在原仓库 &lt;a href=&quot;https://github.com/stevenjoezhang/live2d-widget?tab=readme-ov-file#%E9%85%8D%E7%BD%AE&quot;&gt;README&lt;/a&gt; 找到解释。&lt;/p&gt;
&lt;h2&gt;配置模型&lt;/h2&gt;
&lt;p&gt;注意到，我们在 JavaScript 中引用了 &lt;code&gt;/live2d/config.json&lt;/code&gt; , 这是模型的配置文件，我们现在需要编写它。&lt;/p&gt;
&lt;p&gt;我们从仓库的分发中复制 &lt;code&gt;waifu-tips.json&lt;/code&gt; 进行修改。为加载自定义的模型，修改 &lt;code&gt;.models&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
    {
      &quot;name&quot;: &quot;Hu Tao&quot;,
      &quot;paths&quot;: [&quot;https://hutao-live2d.pages.dev/model3.json&quot;],
      &quot;message&quot;: &quot;太阳出来我晒太阳，月亮出来我晒月亮~&quot;
    }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其余选项亦可参照默认配置进行修改。&lt;/p&gt;
&lt;h2&gt;调整样式&lt;/h2&gt;
&lt;p&gt;默认的 CSS 在不同网站上可能显示效果不佳。可以复制并修改原仓库的 &lt;code&gt;waifu.css&lt;/code&gt; 来自定义样式。&lt;/p&gt;
&lt;p&gt;记得在脚本加载前引入自定义的 CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/live2d/waifu.css&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;完成！&lt;/p&gt;
&lt;h2&gt;跨域请求问题&lt;/h2&gt;
&lt;p&gt;如果我们要从互联网上请求 Live2D 模型资源，而非直接在网站上静态部署，则可能需要处理跨域请求：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;window.Image = new Proxy(window.Image, {
  construct: (target, args) =&amp;gt; {
    const img = new target(...args)
    img.crossOrigin = &apos;anonymous&apos;
    return img
  },
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此处提供了一种暴力方法，给所有 &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; 添加 &lt;code&gt;crossorigin=&apos;anonymous&apos;&lt;/code&gt; .&lt;/p&gt;
</content:encoded></item><item><title>BTRFS 踩坑：根目录下的子卷</title><link>https://misaka10987.github.io/posts/migrate/btrfs-subvol-under-root/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/btrfs-subvol-under-root/</guid><pubDate>Sat, 05 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;BTRFS 踩坑：根目录下的子卷&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;TL; DR:&lt;/strong&gt; 不能假设你的 &lt;code&gt;/&lt;/code&gt; 是文件系统的「根目录」，可能是任何东西的挂载点，例如 BTRFS 子卷 &lt;code&gt;/@&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;事件的起因是我们希望给 &lt;code&gt;/srv&lt;/code&gt; 目录一个单独的子卷，以便增量备份。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;btrfs subvolume create /@srv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是，在我们尝试挂载新创建的子卷时，会得到如下错误：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# mount -o subvol=@srv /dev/nvme0n1p2 /srv
mount: /srv: fsconfig() failed: 没有那个文件或目录.
       dmesg(1) may have more information after failed mount system call.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这看似很奇怪，因为如果我们尝试列出子卷：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# btrfs subvolume list /
ID 256 gen 85363 top level 5 path @
ID 257 gen 85363 top level 5 path @home
ID 258 gen 85363 top level 5 path @log
ID 259 gen 85170 top level 5 path @pkg
ID 260 gen 68985 top level 5 path @.snapshots
ID 261 gen 13 top level 256 path var/lib/portables
ID 262 gen 13 top level 256 path var/lib/machines
ID 271 gen 85142 top level 5 path @srv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;会发现同样的操作可以成功挂载类似的子卷（如 &lt;code&gt;@home&lt;/code&gt; ），却无法挂载我们的 &lt;code&gt;@srv&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;问题的原因在于，此时我们系统的根目录 &lt;code&gt;/&lt;/code&gt; 并不是 BTRFS 文件系统的根目录 &lt;code&gt;/&lt;/code&gt; , 而是其下的子卷 &lt;code&gt;@&lt;/code&gt; 的挂载点（这是 Arch Linux 默认安装下的行为）。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# mount -t btrfs /dev/nvme0n1p2 /tmp/rootfs
# ls /tmp/rootfs
&apos;@&apos;/  &apos;@home&apos;/  &apos;@log&apos;/  &apos;@pkg&apos;/  &apos;@.snapshots&apos;/
# ls /tmp/rootfs/@
 bin@    dev/  &apos;@foo&apos;/   lib@     logs/   opt/    root/   sbin@   sys/   usr/
 boot/   etc/   home/    lib64@   mnt/    proc/   run/    srv/    tmp/   var/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因此，在我们创建子卷 &lt;code&gt;/@srv&lt;/code&gt; 时，看似在「根目录」&lt;code&gt;/&lt;/code&gt; 下创建的子卷，实际上位于 &lt;code&gt;/@/@srv&lt;/code&gt; . 这也是我们无法通过 &lt;code&gt;@srv&lt;/code&gt; 访问的原因。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# btrfs subvolume show /@srv | head -n 2
@/@srv
	Name: 			@srv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为解决这个问题，可以将 BTRFS 挂载到其它挂载点后再操作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mount -t btrfs /dev/nvme0n1p2 /tmp/rootfs
btrfs subvolume create /tmp/rootfs/@srv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或使用 &lt;code&gt;@/@srv&lt;/code&gt; 而非 &lt;code&gt;@srv&lt;/code&gt; 引用这个子卷。&lt;/p&gt;
</content:encoded></item><item><title>Minecraft 1.12.2 依赖于 X RandR 扩展</title><link>https://misaka10987.github.io/posts/migrate/mc-1122-require-xrandr/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/mc-1122-require-xrandr/</guid><pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Minecraft 1.12.2 依赖于 X RandR 扩展&lt;/h1&gt;
&lt;p&gt;如 &lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=292015&quot;&gt;Arch 论坛&lt;/a&gt; 提到，对于 Minecraft 启动时&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No OpenGL context found in the current thread&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;崩溃问题，需要安装 X RandR 扩展。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pacman -S xorg-xrandr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;经测试，该问题存在于 Minecraft 1.12.2 中。Minecraft 1.16.5 及更新版本无此问题。&lt;/p&gt;
</content:encoded></item><item><title>一个 Minecraft 用 log4j 配置文件</title><link>https://misaka10987.github.io/posts/migrate/my-log4j-config/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/my-log4j-config/</guid><pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;一个 Minecraft 用 log4j 配置文件&lt;/h1&gt;
&lt;p&gt;采用类似 &lt;a href=&quot;https://crates.io/crates/tracing-subscriber&quot;&gt;tracing-subscriber&lt;/a&gt; 库的格式化输出。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;Configuration status=&quot;WARN&quot;&amp;gt;
    &amp;lt;Appenders&amp;gt;
        &amp;lt;Console name=&quot;SysOut&quot; target=&quot;SYSTEM_OUT&quot;&amp;gt;
            &amp;lt;PatternLayout pattern=&quot;%style{%d{yyyy-MM-dd&apos;T&apos;HH:mm:ss.SSSSSS&apos;Z&apos;}}{dim} %highlight{%5level}{ERROR=RED, WARN=Yellow, INFO=Green, DEBUG=Blue, TRACE=Magenta} %style{%c:%L:}{dim} %msg%n&quot; /&amp;gt;
        &amp;lt;/Console&amp;gt;
        &amp;lt;Queue name=&quot;ServerGuiConsole&quot;&amp;gt;
            &amp;lt;PatternLayout pattern=&quot;%style{%d{yyyy-MM-dd&apos;T&apos;HH:mm:ss.SSSSSS&apos;Z&apos;}}{dim} %highlight{%5level}{ERROR=RED, WARN=Yellow, INFO=Green, DEBUG=Blue, TRACE=Magenta} %style{%c:%L:}{dim} %msg%n&quot; /&amp;gt;
        &amp;lt;/Queue&amp;gt;
        &amp;lt;RollingRandomAccessFile name=&quot;File&quot; fileName=&quot;logs/latest.log&quot; filePattern=&quot;logs/%d{yyyy-MM-dd}-%i.log.gz&quot;&amp;gt;
            &amp;lt;PatternLayout pattern=&quot;%d{yyyy-MM-dd&apos;T&apos;HH:mm:ss.SSSSSS&apos;Z&apos;} %5level %c:%L: %msg%n&quot; /&amp;gt;
            &amp;lt;Policies&amp;gt;
                &amp;lt;TimeBasedTriggeringPolicy /&amp;gt;
                &amp;lt;OnStartupTriggeringPolicy /&amp;gt;
            &amp;lt;/Policies&amp;gt;
        &amp;lt;/RollingRandomAccessFile&amp;gt;
    &amp;lt;/Appenders&amp;gt;
    &amp;lt;Loggers&amp;gt;
        &amp;lt;Root level=&quot;info&quot;&amp;gt;
            &amp;lt;filters&amp;gt;
                &amp;lt;MarkerFilter marker=&quot;NETWORK_PACKETS&quot; onMatch=&quot;DENY&quot; onMismatch=&quot;NEUTRAL&quot; /&amp;gt;
            &amp;lt;/filters&amp;gt;
            &amp;lt;AppenderRef ref=&quot;SysOut&quot;/&amp;gt;
            &amp;lt;AppenderRef ref=&quot;File&quot;/&amp;gt;
        &amp;lt;/Root&amp;gt;
    &amp;lt;/Loggers&amp;gt;
&amp;lt;/Configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Distribution Cheetsheet</title><link>https://misaka10987.github.io/posts/migrate/old/202410/distr-cheetsheet/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202410/distr-cheetsheet/</guid><pubDate>Mon, 14 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;分布&lt;/h2&gt;
&lt;p&gt;分布是一个高阶函数。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;二项分布：$B:\Z\Rightarrow\R\Rightarrow(\Z\Rightarrow\R)=(n,p)\mapsto x\mapsto{n\choose x}p^x(1-p)^{n-x}$ ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;超几何分布：$H:\Z\Rightarrow\Z\Rightarrow\Z\Rightarrow(\Z\Rightarrow\R)=(n,K,N)\mapsto x\mapsto\frac{{K\choose x}{N-K\choose n-x}}{N\choose n}$ ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;正态分布：$N:\R\Rightarrow\R\Rightarrow(\R\Rightarrow\R)=(\mu,\sigma)\mapsto x\mapsto\frac{1}{\sigma\sqrt{2\pi}}\exp(-\frac{(x-\mu)^2}{2\sigma^2})$ .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;期望&lt;/h2&gt;
&lt;p&gt;$$
{\rm E}:({\rm Dom}\Rightarrow\R)\Rightarrow\R=f\mapsto x\mapsto\int_{\rm Dom}xf(x){\rm d}x
$$&lt;/p&gt;
&lt;p&gt;${\rm E}(l\circ f)=l\circ{\rm E}(f)$ 对于线性映射 $l$ .&lt;/p&gt;
&lt;p&gt;${\rm E}(x\mapsto f(x)g(x))=E(f)E(g)$ 当 $f$ 与 $g$ 无关。&lt;/p&gt;
&lt;h2&gt;方差&lt;/h2&gt;
&lt;p&gt;$$
\begin{align*}
{\rm D}&amp;amp;:({\rm Dom}\Rightarrow\R)\Rightarrow\R\newline
&amp;amp;=f\mapsto x\mapsto \int_{\rm Dom}(x-{\rm E}(f))^2{\rm d}x\newline
&amp;amp;=f\mapsto {\rm E}((x\mapsto x^2)\circ f)-{\rm E}(f)^2
\end{align*}
$$&lt;/p&gt;
&lt;p&gt;${\rm D}((x\mapsto x+a)\circ f)={\rm D}(f)$ .&lt;/p&gt;
&lt;p&gt;${\rm D}((x\mapsto ax)\circ f)=a^2{\rm D}(f)$ .&lt;/p&gt;
&lt;h2&gt;协方差&lt;/h2&gt;
&lt;p&gt;$$
\begin{align*}
{\rm cov}&amp;amp;:(\R\Rightarrow\R)\Rightarrow(\R\Rightarrow\R)\Rightarrow\R\newline
&amp;amp;=(f,g)\mapsto{\rm E}(x\mapsto(f(x)-{\rm E}(f))(g(x)-{\rm E}(g)))\newline
&amp;amp;={\rm E}(x\mapsto f(x)g(x))-{\rm E}(f){\rm E}(g)
\end{align*}
$$&lt;/p&gt;
&lt;p&gt;${\rm cov}(f,f)={\rm D}(f)$ .&lt;/p&gt;
&lt;p&gt;${\rm cov}(f,g)={\rm cov}(g,f)$ .&lt;/p&gt;
&lt;p&gt;${\rm cov}((x\mapsto ax)\circ f,(x\mapsto bx)\circ g)=ab{\rm cov}(f,g)$ .&lt;/p&gt;
&lt;h2&gt;常用公式&lt;/h2&gt;
&lt;p&gt;${\rm E}(B(n,p))=np$ .&lt;/p&gt;
&lt;p&gt;${\rm D}(B(n,p))=np(1-p)$ .&lt;/p&gt;
&lt;p&gt;${\rm E}(H(n,K,N))=\frac{Kn}N$ .&lt;/p&gt;
&lt;p&gt;${\rm D}(H(n,K,N))=\frac{n(N-n)K(N-K)}{N^2(N-1)}$ .&lt;/p&gt;
&lt;p&gt;${\rm D}(x\mapsto af(x)+bg(x))=a^2{\rm D}(f)+b^2{\rm D}(g)+2ab{\rm cov}(f,g)$ .&lt;/p&gt;
&lt;p&gt;${\rm D}(\sum_nf_n)=\sum_{i=0}^n{\rm D}(f_i)+2\sum_{j=0}^i{\rm cov}(f_i,f_j)$ .&lt;/p&gt;
&lt;p&gt;${\rm cov}(\sum_nf_n,\sum_mg_m)=\sum_n\sum_m{\rm cov}(f_n,g_m)$ .&lt;/p&gt;
</content:encoded></item><item><title>通量和散度</title><link>https://misaka10987.github.io/posts/migrate/old/202410/flux/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202410/flux/</guid><pubDate>Sun, 13 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;通量&lt;/h2&gt;
&lt;p&gt;通量 (Flux) 用以描述一个向量场“穿过”曲面的部分的大小。&lt;/p&gt;
&lt;p&gt;向量场 $\bold A$ 在曲面 $\Sigma$ 上的通量 $\Phi_{\bold A}(\Sigma)$ 定义为：&lt;/p&gt;
&lt;p&gt;$$
\Phi_{\bold A}(\Sigma)=\iint_\Sigma\bold A\cdot\bold n{\rm d}S
$$&lt;/p&gt;
&lt;p&gt;其中 $\bold n$ 为曲面在每一点上的&lt;strong&gt;单位法向量&lt;/strong&gt;。一点上的单位法向量是自这一点垂直曲面向外的单位向量。&lt;/p&gt;
&lt;p&gt;上述形式的通量是标量。&lt;/p&gt;
&lt;h3&gt;混乱邪恶&lt;/h3&gt;
&lt;p&gt;在一些情境下，通量还可以指向量场在曲面上&lt;strong&gt;某一点&lt;/strong&gt;的&lt;strong&gt;向量&lt;/strong&gt;在其&lt;strong&gt;单位法向量&lt;/strong&gt;上的投影。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;相当于上文中 $\bold A\cdot\bold n$ .&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;我们不采用这种说法。在需要时，用「通量密度」代替。&lt;/p&gt;
&lt;h2&gt;散度&lt;/h2&gt;
&lt;p&gt;散度 (Divergence) 用以描述向量场中的某一点附近的向量“趋向”或“远离”该点的趋势。标量。&lt;/p&gt;
&lt;p&gt;向量场 $\bold A$ 在点 $x$ 的散度 ${\rm div}\bold A(x)$ 定义为：&lt;/p&gt;
&lt;p&gt;$$
{\rm div}\bold A(x)=\lim_{\delta V\rightarrow{x}}\frac{\Phi_\bold A(\Sigma)}{|\delta V|}
$$&lt;/p&gt;
&lt;p&gt;其中 $\Sigma$ 是包含点 $x$ 的一个封闭曲面， $\delta V$ 为该曲面内的微小体元， $|\delta V|$ 为此微小体元的体积。上述定义可直观理解为以 $x$ 为球心的无穷小球上的通量。&lt;/p&gt;
&lt;p&gt;向量场 $\bold A$ 的散度场记作 $\nabla\cdot\bold A$ .&lt;/p&gt;
&lt;h2&gt;散度定理&lt;/h2&gt;
&lt;p&gt;散度定理（或高斯散度定理）指出：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;曲面上的通量等于散度在曲面内体积上的积分。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;即对于曲面 $\Sigma$ , 围起的体积为 $\Omega$ 时：&lt;/p&gt;
&lt;p&gt;$$
\iiint_\Omega{\rm div}\bold A(x){\rm d}v=\Phi_\bold A(\Sigma)
$$&lt;/p&gt;
&lt;p&gt;可以如是直观理解：向量从体积中的所有点“涌出”的的相加，就是向量在整个体积内“产生”的量，也就是通过曲面“外溢”的量。&lt;/p&gt;
&lt;p&gt;「散度是通量的体密度。」&lt;/p&gt;
</content:encoded></item><item><title>歪诗一首</title><link>https://misaka10987.github.io/posts/migrate/old/202410/poem-1/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202410/poem-1/</guid><pubDate>Sun, 13 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;近日读网络小说《赛博英雄传》有感作。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;沁园春&lt;/h1&gt;
&lt;p&gt;人死神留，万代千秋，本性难移。&lt;/p&gt;
&lt;p&gt;纵水泥为肉，钢筋作骨，捉鳖揽月，不改其一。&lt;/p&gt;
&lt;p&gt;僭主高踞，营私建党，每罄南山未可极。&lt;/p&gt;
&lt;p&gt;无妨便，即易筋换血，尽算天机。&lt;/p&gt;
&lt;p&gt;方得自在毫厘。智人种，当绝禽兽习。&lt;/p&gt;
&lt;p&gt;教暴秦夺魄，懦夫增气，中天不济，万世风激。&lt;/p&gt;
&lt;p&gt;旧法尘封，铅华尽洗，我以六龙回日低。&lt;/p&gt;
&lt;p&gt;循苦旅，抵群星所在，寰宇雄奇。&lt;/p&gt;
</content:encoded></item><item><title>Y-组合子及其推导过程</title><link>https://misaka10987.github.io/posts/migrate/old/202409/y-combinator/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202409/y-combinator/</guid><pubDate>Sat, 21 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在传统方法下，我们很难在无类型 $\lambda$ - 演算这样的&lt;strong&gt;匿名&lt;/strong&gt;上下文中进行函数的递归。&lt;/p&gt;
&lt;p&gt;为解决此问题，我们希望有一个函数用以“得到函数自身”，即为 Y - 组合子。&lt;/p&gt;
&lt;p&gt;Y - 组合子使用 $\lambda$ - 演算定义为：&lt;/p&gt;
&lt;p&gt;$$
Y=\lambda f.(\lambda x.f(x\space x))\space(\lambda x.f(x\space x))
$$&lt;/p&gt;
&lt;p&gt;Y - 组合子应用于函数：&lt;/p&gt;
&lt;p&gt;$$
\begin{align}
Y\space f
&amp;amp;=(\lambda x.f(x\space x))\space(\lambda x.f(x\space x))\newline
&amp;amp;=f\space((\lambda x.f(x\space x)\space(\lambda x.f(x\space x)))\newline
&amp;amp;=f(Y\space f)
\end{align}
$$&lt;/p&gt;
&lt;p&gt;即进行两次 $\beta$ - 规约并将 (1) 代入 (3)。最终我们得到：&lt;/p&gt;
&lt;p&gt;$$
Y\space f=f\space(Y\space f)
$$&lt;/p&gt;
&lt;p&gt;Y - 组合子或称不动点组合子，因其将函数映射到其不动点上。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;若 $f\space x=x$ ，则称 $x$ 是 $f$ 的一个不动点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;推导&lt;/h2&gt;
&lt;p&gt;Y - 组合子的推导过程实质上就是解不动点方程 $Y\space f=f\space(Y\space f)$ 的过程。&lt;/p&gt;
&lt;p&gt;考虑不断迭代该不动点方程：&lt;/p&gt;
&lt;p&gt;$$
Y\space f=f\space(Y\space f)=f\space f\space(Y\space f)=f\space f\space f\space...
$$&lt;/p&gt;
&lt;p&gt;将这个无限长的序列称作 $g$ ，则有 $g = f\space g$.&lt;/p&gt;
&lt;p&gt;由于序列无限长，不妨将其截半，设 $g=g&apos;\space g&apos;$. 这是因为我们希望可以得一个带有函数的参数的表达式在方程中，以便于解得函数。&lt;/p&gt;
&lt;p&gt;则有&lt;/p&gt;
&lt;p&gt;$$
g&apos;\space g&apos;=f(g&apos;\space g&apos;)
$$&lt;/p&gt;
&lt;p&gt;如此构成了一个合法的函数定义：&lt;/p&gt;
&lt;p&gt;$$
g&apos;=\lambda x.f(x\space x)
$$&lt;/p&gt;
&lt;p&gt;代入原方程即可得：&lt;/p&gt;
&lt;p&gt;$$
Y\space f=g=g&apos;\space g&apos;=(\lambda x.f(x\space x))\space(\lambda x.f(x\space x))\
Y=\lambda f.(\lambda x.f(x\space x))\space(\lambda x.f(x\space x))
$$&lt;/p&gt;
&lt;p&gt;这样就得到了 $Y$ 的定义。&lt;/p&gt;
</content:encoded></item><item><title>epsilon-delta极限定义的思维过程</title><link>https://misaka10987.github.io/posts/migrate/old/202409/lim-of-fn/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202409/lim-of-fn/</guid><pubDate>Tue, 10 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Attempt 1&lt;/h2&gt;
&lt;p&gt;“极限就是越来越近。”&lt;/p&gt;
&lt;p&gt;定义 $\lim_{x\rightarrow a^-}f(x)=L$ iff:&lt;/p&gt;
&lt;p&gt;$\forall \Delta_x&apos;\le\Delta_x$, $|f(a-\Delta_x&apos;)-L|\le|f(a-\Delta_x)-L|$.&lt;/p&gt;
&lt;p&gt;依样定义右极限，并定义左右极限相等时极限存在。&lt;/p&gt;
&lt;p&gt;容易发现根据上述定义，$\lim_{x\rightarrow+\infin}\frac{1}{x}$ 鉴于在 $\R^+$ 上单调减，其极限可以是任意非正实数。&lt;/p&gt;
&lt;p&gt;这不是我们所期待的。我们希望上述极限定义为 $0$ 。&lt;/p&gt;
&lt;h2&gt;Attempt 2&lt;/h2&gt;
&lt;p&gt;“极限是越来越近，且可以无限接近。”&lt;/p&gt;
&lt;p&gt;定义 $\lim_{x\rightarrow a^-}f(x)=L$ iff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\forall \Delta_x&apos;\le\Delta_x$ , $|f(a-\Delta_x&apos;)-L|\le|f(a-\Delta_x)-L|$; and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\forall \Delta_y\in\R^+$, $\exist\Delta_x$ s.t. $|f(a-\Delta_x)-L|\le\Delta_y$.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上述定义成功排除了多余的极限值。但是，可以发现，鉴于其对函数整个定义域上的单调性作要求，这似乎严格地排除了过多函数，使得定义不甚实用。&lt;/p&gt;
&lt;p&gt;我们希望得到能使类似于 $\lim_{x\rightarrow0}\cos x=1$ 的极限定义（而非现在的未定义）。&lt;/p&gt;
&lt;h2&gt;Attempt 3&lt;/h2&gt;
&lt;p&gt;“在 $a$ 上的极限是在一个包含 $a$ 的范围内越来越近，且可以无限接近。”&lt;/p&gt;
&lt;p&gt;定义 $\lim_{x\rightarrow a^-}f(x)=L$ iff $\exist\Delta_0\in\R^+$ s.t.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\forall0\lt\Delta_x&apos;\le\Delta_x&amp;lt;\Delta_0$ , $|f(a-\Delta_x&apos;)-L|\le|f(a-\Delta_x)-L|$; and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\forall \Delta_y\in\R^+$, $\exist\Delta_x\le\Delta_0$ s.t. $|f(a-\Delta_x)-L|\le\Delta_y$.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上述定义允许更多函数的极限被定义。&lt;/p&gt;
&lt;p&gt;这似乎是完备的。但是，知晓数列极限的定义，依然能容易地给出定义的不足之处：此定义对于不断振荡——不单调，但在接近确定值的函数未能给出定义。例如，我们希望像 $\lim_{x\rightarrow0}x\sin\frac{1}{x}$ 这样的极限被定义为 $0$ ，而非未定义。&lt;/p&gt;
&lt;h2&gt;Attempt 4&lt;/h2&gt;
&lt;p&gt;“在 $a$ 上的极限是在一个包含 $a$ 的范围内可以无限接近，且对于某个值，总存在一个更小的值使得在更小的值以后的所有函数值都要更近。”&lt;/p&gt;
&lt;p&gt;定义 $\lim_{x\rightarrow a^-}f(x)=L$ , iff $\exist \Delta_0\in\R^+$ s.t.:&lt;/p&gt;
&lt;p&gt;let $g(x)=|f(a-x)-L|$ ;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$\forall \Delta y\in\mathbb{R}^+$ , $\exist \Delta x\le\Delta_0$ s.t. $g(\Delta x)\le\Delta y$ ; and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$\forall \Delta_1\le\Delta_0$ , $\exist\Delta x\le\Delta_1$ s.t. $\forall\Delta&apos;x\le\Delta x$ , $g(\Delta&apos;x)\le g(\Delta_1)$ .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个定义很完美！&lt;/p&gt;
&lt;h2&gt;简化版本&lt;/h2&gt;
&lt;p&gt;我们对 Attempt 4 作出一些简化，便可以得到极限的 $\epsilon$ - $\delta$ 定义：&lt;/p&gt;
&lt;p&gt;$\lim_{x\rightarrow a}f(x)=L$ iff $\forall\epsilon\in\R^+$, $\exist\delta$ s.t. $\forall|x-a|&amp;lt;\delta$, $|f(x)-L|&amp;lt;\epsilon$.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;很显然此定义满足 Attempt 4 的第一条；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于 Attempt 4 的第二条，由于规定了差小于 $\delta$ 的所有值，因此函数确实在越来越近；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;此定义不会排除 Attempt 3 类似的函数，这是由于 $\delta$ 可以任意小。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>`serde_derive` amazingly smart</title><link>https://misaka10987.github.io/posts/migrate/old/202407/serde-is-good/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/migrate/old/202407/serde-is-good/</guid><pubDate>Mon, 22 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Within context like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct Id&amp;lt;T: Register&amp;gt; {
    id: &amp;amp;&apos;static str,
    _phantom: PhantomData&amp;lt;T&amp;gt;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;serde_derive&lt;/code&gt; intelligently recognizes that there is no need to serialize &lt;code&gt;_phantom&lt;/code&gt; and the &lt;code&gt;#[serde(transparent)]&lt;/code&gt; flag simply works.&lt;/p&gt;
</content:encoded></item><item><title>Markdown Extended Features</title><link>https://misaka10987.github.io/posts/markdown-extended/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/markdown-extended/</guid><description>Read more about Markdown features in Fuwari</description><pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;GitHub Repository Cards&lt;/h2&gt;
&lt;p&gt;You can add dynamic cards that link to GitHub repositories, on page load, the repository information is pulled from the GitHub API.&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;Fabrizz/MMM-OnSpotify&quot;}&lt;/p&gt;
&lt;p&gt;Create a GitHub repository card with the code &lt;code&gt;::github{repo=&quot;&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;&quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;saicaca/fuwari&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Admonitions&lt;/h2&gt;
&lt;p&gt;Following types of admonitions are supported: &lt;code&gt;note&lt;/code&gt; &lt;code&gt;tip&lt;/code&gt; &lt;code&gt;important&lt;/code&gt; &lt;code&gt;warning&lt;/code&gt; &lt;code&gt;caution&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::note
Highlights information that users should take into account, even when skimming.
:::&lt;/p&gt;
&lt;p&gt;:::tip
Optional information to help a user be more successful.
:::&lt;/p&gt;
&lt;p&gt;:::important
Crucial information necessary for users to succeed.
:::&lt;/p&gt;
&lt;p&gt;:::warning
Critical content demanding immediate user attention due to potential risks.
:::&lt;/p&gt;
&lt;p&gt;:::caution
Negative potential consequences of an action.
:::&lt;/p&gt;
&lt;h3&gt;Basic Syntax&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;:::note
Highlights information that users should take into account, even when skimming.
:::

:::tip
Optional information to help a user be more successful.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Custom Titles&lt;/h3&gt;
&lt;p&gt;The title of the admonition can be customized.&lt;/p&gt;
&lt;p&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;GitHub Syntax&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;a href=&quot;https://github.com/orgs/community/discussions/16925&quot;&gt;The GitHub syntax&lt;/a&gt; is also supported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]
&amp;gt; The GitHub syntax is also supported.

&amp;gt; [!TIP]
&amp;gt; The GitHub syntax is also supported.
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Expressive Code Example</title><link>https://misaka10987.github.io/posts/expressive-code/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/expressive-code/</guid><description>How code blocks look in Markdown using Expressive Code.</description><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here, we&apos;ll explore how code blocks look using &lt;a href=&quot;https://expressive-code.com/&quot;&gt;Expressive Code&lt;/a&gt;. The provided examples are based on the official documentation, which you can refer to for further details.&lt;/p&gt;
&lt;h2&gt;Expressive Code&lt;/h2&gt;
&lt;h3&gt;Syntax Highlighting&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/syntax-highlighting/&quot;&gt;Syntax Highlighting&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Regular syntax highlighting&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;This code is syntax highlighted!&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Rendering ANSI escape sequences&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;ANSI colors:
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
- Bold:    [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
- Dimmed:  [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m

256 colors (showing colors 160-177):
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m

Full RGB colors:
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m

Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Editor &amp;amp; Terminal Frames&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/frames/&quot;&gt;Editor &amp;amp; Terminal Frames&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Code editor frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Title attribute example&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src/content/index.html --&amp;gt;
&amp;lt;div&amp;gt;File name comment example&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Terminal frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;This terminal frame has no title&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;Write-Output &quot;This one has a title!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Overriding frame types&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Look ma, no frame!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;# Without overriding, this would be a terminal frame
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
New-Alias tail Watch-Tail
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Text &amp;amp; Line Markers&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/text-markers/&quot;&gt;Text &amp;amp; Line Markers&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Marking full lines &amp;amp; line ranges&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Line 1 - targeted by line number
// Line 2
// Line 3
// Line 4 - targeted by line number
// Line 5
// Line 6
// Line 7 - targeted by range &quot;7-8&quot;
// Line 8 - targeted by range &quot;7-8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting line marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;this line is marked as deleted&apos;)
  // This line and the next one are marked as inserted
  console.log(&apos;this is the second inserted line&apos;)

  return &apos;this line uses the neutral default marker type&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding labels to line markers&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}
  value={value}
  className={buttonClassName}
  disabled={disabled}
  active={active}
&amp;gt;
  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding long labels on their own lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}

  value={value}
  className={buttonClassName}

  disabled={disabled}
  active={active}
&amp;gt;

  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Using diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;+this line will be marked as inserted
-this line will be marked as deleted
this is a regular line
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+this is an actual diff file
-all contents will remain unmodified
 no whitespace will be removed either
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Combining syntax highlighting with diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;  function thisIsJavaScript() {
    // This entire block gets highlighted as JavaScript,
    // and we can still add diff markers to it!
-   console.log(&apos;Old code to be removed&apos;)
+   console.log(&apos;New and shiny code!&apos;)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Marking individual text inside lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  // Mark any given text inside lines
  return &apos;Multiple matches of the given text are supported&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Regular expressions&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;The words yes and yep will be marked.&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Escaping forward slashes&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Test&quot; &amp;gt; /home/test.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting inline marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;These are inserted and deleted marker types&apos;);
  // The return statement uses the default marker type
  return true;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Word Wrap&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/word-wrap/&quot;&gt;Word Wrap&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Configuring word wrap per block&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Configuring indentation of wrapped lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent (enabled by default)
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Collapsible Sections&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/collapsible-sections/&quot;&gt;Collapsible Sections&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// All this boilerplate setup code will be collapsed
import { someBoilerplateEngine } from &apos;@example/some-boilerplate&apos;
import { evenMoreBoilerplate } from &apos;@example/even-more-boilerplate&apos;

const engine = someBoilerplateEngine(evenMoreBoilerplate())

// This part of the code will be visible by default
engine.doSomething(1, 2, 3, calcFn)

function calcFn() {
  // You can have multiple collapsed sections
  const a = 1
  const b = 2
  const c = a + b

  // This will remain visible
  console.log(`Calculation result: ${a} + ${b} = ${c}`)
  return c
}

// All this code until the end of the block will be collapsed again
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: &apos;End of example boilerplate code&apos; })
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Line Numbers&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/line-numbers/&quot;&gt;Line Numbers&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Displaying line numbers per block&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// This code block will show line numbers
console.log(&apos;Greetings from line 2!&apos;)
console.log(&apos;I am on line 3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Line numbers are disabled for this block
console.log(&apos;Hello?&apos;)
console.log(&apos;Sorry, do you know what line I am on?&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Changing the starting line number&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Greetings from line 5!&apos;)
console.log(&apos;I am on line 6&apos;)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Simple Guides for Fuwari</title><link>https://misaka10987.github.io/posts/guide/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/guide/</guid><description>How to use this blog template.</description><pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Cover image source: &lt;a href=&quot;https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/208fc754-890d-4adb-9753-2c963332675d/width=2048/01651-1456859105-(colour_1.5),girl,_Blue,yellow,green,cyan,purple,red,pink,_best,8k,UHD,masterpiece,male%20focus,%201boy,gloves,%20ponytail,%20long%20hair,.jpeg&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blog template is built with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;. For the things that are not mentioned in this guide, you may find the answers in the &lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Front-matter of Posts&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: My First Blog Post
published: 2023-09-09
description: This is the first post of my new Astro blog.
image: ./cover.jpg
tags: [Foo, Bar]
category: Front-end
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The title of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The date the post was published.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short description of the post. Displayed on index page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The cover image path of the post.&amp;lt;br/&amp;gt;1. Start with &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;: Use web image&amp;lt;br/&amp;gt;2. Start with &lt;code&gt;/&lt;/code&gt;: For image in &lt;code&gt;public&lt;/code&gt; dir&amp;lt;br/&amp;gt;3. With none of the prefixes: Relative to the markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The tags of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The category of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If this post is still a draft, which won&apos;t be displayed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Where to Place the Post Files&lt;/h2&gt;
&lt;p&gt;Your post files should be placed in &lt;code&gt;src/content/posts/&lt;/code&gt; directory. You can also create sub-directories to better organize your posts and assets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── post-1.md
└── post-2/
    ├── cover.png
    └── index.md
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Markdown Example</title><link>https://misaka10987.github.io/posts/markdown/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/markdown/</guid><description>A simple example of a Markdown blog post.</description><pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;An h1 header&lt;/h1&gt;
&lt;p&gt;Paragraphs are separated by a blank line.&lt;/p&gt;
&lt;p&gt;2nd paragraph. &lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, and &lt;code&gt;monospace&lt;/code&gt;. Itemized lists
look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this one&lt;/li&gt;
&lt;li&gt;that one&lt;/li&gt;
&lt;li&gt;the other one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that --- not considering the asterisk --- the actual text
content starts at 4-columns in.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Block quotes are
written like so.&lt;/p&gt;
&lt;p&gt;They can span multiple paragraphs,
if you like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., &quot;it&apos;s all
in chapters 12--14&quot;). Three dots ... will be converted to an ellipsis.
Unicode is supported. ☺&lt;/p&gt;
&lt;h2&gt;An h2 header&lt;/h2&gt;
&lt;p&gt;Here&apos;s a numbered list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;first item&lt;/li&gt;
&lt;li&gt;second item&lt;/li&gt;
&lt;li&gt;third item&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note again how the actual text starts at 4 columns in (4 characters
from the left side). Here&apos;s a code sample:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Let me re-iterate ...
for i in 1 .. 10 { do-something(i) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you probably guessed, indented 4 spaces. By the way, instead of
indenting the block, you can use delimited blocks, if you like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;define foobar() {
    print &quot;Welcome to flavor country!&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(which makes copying &amp;amp; pasting easier). You can optionally mark the
delimited block for Pandoc to syntax highlight it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import time
# Quick, count to ten!
for i in range(10):
    # (but not *too* quick)
    time.sleep(0.5)
    print i
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;An h3 header&lt;/h3&gt;
&lt;p&gt;Now a nested list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, get these ingredients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;carrots&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;lentils&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boil some water.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dump everything in the pot and follow
this algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; find wooden spoon
 uncover pot
 stir
 cover pot
 balance wooden spoon precariously on pot handle
 wait 10 minutes
 goto first step (or shut off burner when done)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do not bump wooden spoon or it will fall.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice again how text always lines up on 4-space indents (including
that last line which continues item 3 above).&lt;/p&gt;
&lt;p&gt;Here&apos;s a link to &lt;a href=&quot;http://foo.bar&quot;&gt;a website&lt;/a&gt;, to a &lt;a href=&quot;local-doc.html&quot;&gt;local
doc&lt;/a&gt;, and to a &lt;a href=&quot;#an-h2-header&quot;&gt;section heading in the current
doc&lt;/a&gt;. Here&apos;s a footnote [^1].&lt;/p&gt;
&lt;p&gt;[^1]: Footnote text goes here.&lt;/p&gt;
&lt;p&gt;Tables can look like this:&lt;/p&gt;
&lt;p&gt;size material color&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;9 leather brown
10 hemp canvas natural
11 glass transparent&lt;/p&gt;
&lt;p&gt;Table: Shoes, their sizes, and what they&apos;re made of&lt;/p&gt;
&lt;p&gt;(The above is the caption for the table.) Pandoc also supports
multi-line tables:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;keyword text&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;red Sunsets, apples, and
other red or reddish
things.&lt;/p&gt;
&lt;p&gt;green Leaves, grass, frogs
and other things it&apos;s
not easy being.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A horizontal rule follows.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here&apos;s a definition list:&lt;/p&gt;
&lt;p&gt;apples
: Good for making applesauce.
oranges
: Citrus!
tomatoes
: There&apos;s no &quot;e&quot; in tomatoe.&lt;/p&gt;
&lt;p&gt;Again, text is indented 4 spaces. (Put a blank line between each
term/definition pair to spread things out more.)&lt;/p&gt;
&lt;p&gt;Here&apos;s a &quot;line block&quot;:&lt;/p&gt;
&lt;p&gt;| Line one
| Line too
| Line tree&lt;/p&gt;
&lt;p&gt;and images can be specified like so:&lt;/p&gt;
&lt;p&gt;Inline math equations go in like so: $\omega = d\phi / dt$. Display
math should get its own line and be put in in double-dollarsigns:&lt;/p&gt;
&lt;p&gt;$$I = \int \rho R^{2} dV$$&lt;/p&gt;
&lt;p&gt;$$
\begin{equation*}
\pi
=3.1415926535
;8979323846;2643383279;5028841971;6939937510;5820974944
;5923078164;0628620899;8628034825;3421170679;\ldots
\end{equation*}
$$&lt;/p&gt;
&lt;p&gt;And note that you can backslash-escape any punctuation characters
which you wish to be displayed literally, ex.: `foo`, *bar*, etc.&lt;/p&gt;
</content:encoded></item><item><title>Include Video in the Posts</title><link>https://misaka10987.github.io/posts/video/</link><guid isPermaLink="true">https://misaka10987.github.io/posts/video/</guid><description>This post demonstrates how to include embedded video in a blog post.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just copy the embed code from YouTube or other platforms, and paste it in the markdown file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Include Video in the Post
published: 2023-10-19
// ...
---

&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;YouTube&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bilibili&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;//player.bilibili.com/player.html?bvid=BV1fK4y1s7Qf&amp;amp;p=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>