summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormuqiuhan <[email protected]>2025-03-25 08:21:31 +0000
committermuqiuhan <[email protected]>2025-03-25 08:21:31 +0000
commit2f22b38f0c543ebf5cf0a846673ae36c5a626e45 (patch)
treec274bcaec5dbe1eb1db785357b3a1b6ecb803812
parentd583a9dc930ba250135ca795c5207f8343ba7411 (diff)
downloadblog-2f22b38f0c543ebf5cf0a846673ae36c5a626e45.tar.gz
deploy: 47f156d45ef91f54d4a5d64b8031416344ebba64
-rw-r--r--2025/03/20/TDD-和-DDD-的一些小想法/index.html5
-rw-r--r--2025/03/25/Scala-3-Capture-Checking/index.html413
-rw-r--r--archives/2025/03/index.html18
-rw-r--r--archives/2025/index.html36
-rw-r--r--archives/2025/page/2/index.html18
-rw-r--r--archives/index.html36
-rw-r--r--archives/page/10/index.html36
-rw-r--r--archives/page/11/index.html36
-rw-r--r--archives/page/12/index.html18
-rw-r--r--archives/page/2/index.html36
-rw-r--r--archives/page/3/index.html36
-rw-r--r--archives/page/4/index.html36
-rw-r--r--archives/page/5/index.html36
-rw-r--r--archives/page/6/index.html36
-rw-r--r--archives/page/7/index.html36
-rw-r--r--archives/page/8/index.html36
-rw-r--r--archives/page/9/index.html36
-rw-r--r--search.xml225
-rw-r--r--tags/Technique/index.html38
-rw-r--r--tags/Technique/page/2/index.html38
-rw-r--r--tags/Technique/page/3/index.html38
-rw-r--r--tags/Technique/page/4/index.html38
-rw-r--r--tags/Technique/page/5/index.html236
23 files changed, 1193 insertions, 324 deletions
diff --git a/2025/03/20/TDD-和-DDD-的一些小想法/index.html b/2025/03/20/TDD-和-DDD-的一些小想法/index.html
index 94292f10..1e8f4bae 100644
--- a/2025/03/20/TDD-和-DDD-的一些小想法/index.html
+++ b/2025/03/20/TDD-和-DDD-的一些小想法/index.html
@@ -204,6 +204,11 @@
<nav class="post-nav">
<div class="prev-item">
+ <div class="icon arrow-left"></div>
+ <div class="post-link">
+ <a href="/2025/03/25/Scala-3-Capture-Checking/">Prev</a>
+ </div>
+
</div>
<div class="next-item">
diff --git a/2025/03/25/Scala-3-Capture-Checking/index.html b/2025/03/25/Scala-3-Capture-Checking/index.html
new file mode 100644
index 00000000..e30b1c26
--- /dev/null
+++ b/2025/03/25/Scala-3-Capture-Checking/index.html
@@ -0,0 +1,413 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>Scala 3 (Capture Checking) | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.alicdn.com/polyfill.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+<script src="/js/menu.js"></script>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <article id="post">
+
+
+ <div class="post-head">
+ <div class="post-info">
+ <div class="tag-list">
+
+
+ <span class="post-tag">
+ <a href="/tags/Technique/">
+ Technique
+ </a>
+ </span>
+
+
+ </div>
+ <div class="post-title">
+
+
+ Scala 3 (Capture Checking)
+
+
+ </div>
+ <span class="post-date">
+ Mar 25, 2025
+ </span>
+ </div>
+ <div class="post-img">
+
+ <div class="h-line-primary"></div>
+
+ </div>
+</div>
+ <div class="post-content">
+ <blockquote>
+<p><a target="_blank" rel="noopener" href="https://docs.scala-lang.org/scala3/reference/experimental/cc.html">https://docs.scala-lang.org/scala3/reference/experimental/cc.html</a></p>
+</blockquote>
+<p>Scala 3 在其类型系统的演进过程中,引入了诸多实验性特性,旨在提升语言的表达能力和代码的可靠性。Capture Checking 是其中一项引人注目的创新。目前还在试验阶段,其通过增强静态分析的能力,在编译时捕获潜在的错误,从而减少运行时问题的发生。</p>
+<p>Capture Checking引入了一系列核心概念,这些概念共同构成了其类型系统的基础:</p>
+<ul>
+<li><strong>捕获类型 (Capturing Types):</strong> 捕获类型采用 <code>T^&#123;c₁, ..., cᵢ&#125;</code> 的形式,其中 <code>T</code> 是一个普通的 Scala 类型,而 <code>&#123;c₁, ..., cᵢ&#125;</code> 则是一个捕获的 Capabilities 集合。这个捕获集合明确地列出了类型 <code>T</code> 的值所依赖或能够访问的 Capabilities。这种类型表示方式为类型信息增加了一个新的维度,它不仅描述了数据的结构,还包含了数据交互的环境或资源的相关信息。</li>
+<li><strong>Capabilities:</strong> 在 Capture Checking 的语境下,Capabilities 指的是方法或类的参数、局部变量,或者其类型本身就是一个具有非空捕获集合的捕获类型的封闭类的 <code>this</code> 引用。这些实体之所以需要被跟踪,是因为它们通常代表了执行某些操作或访问某些资源的“权限”或“授权”。跟踪这些 Capabilities 意味着可以控制这种影响在程序中的传播方式和范围。</li>
+<li><strong>通用 Capability (<code>cap</code>):</strong> 通用 Capability <code>cap</code> 是一个最基本的 Capability,所有的其他的 Capabilities 都派生自它。类型 <code>T^</code> 是 <code>T^&#123;cap&#125;</code> 的简写形式,表示类型 <code>T</code> 的值可以捕获任意的 Capability。<code>cap</code> 的存在为 Capture Checking 系统提供了一种 <strong>处理精确跟踪并非必需或不可行</strong> 的场景的方式。它充当了一种通配符,表明一个值可能依赖于任何 Capability。</li>
+<li><strong>纯函数 vs. 非纯函数 (Pure vs. Impure Functions):</strong> Capture Checking 显式地区分了纯函数和非纯函数。类型为 <code>A =&gt; B</code> 的函数被认为是非纯函数,它可以捕获任意 Capability,等价于 <code>A -&gt;&#123;cap&#125; B</code> 1。而类型为 <code>A -&gt; B</code> 的函数则是纯函数,它不能捕获任何 Capability。此外,还可以使用 <code>A -&gt;&#123;c, d&#125; B</code> 的形式来显式指定函数只能捕获 Capability <code>c</code> 和 <code>d</code>。这种区分使得类型系统能够强制执行函数式编程的原则,其中纯函数因其可预测性和可测试性而备受推崇。</li>
+<li><strong>子捕获 (Subcapturing):</strong> 子捕获描述了捕获集合之间的关系。如果一个捕获集合 <code>C₁</code> 中的每个元素都包含在另一个捕获集合 <code>C₂</code> 中,那么我们说 <code>C₁</code> 是 <code>C₂</code> 的子捕获,记作 <code>C₁ &lt;: C₂</code> 1。子捕获关系在类型系统中扮演着重要的角色,例如在判断类型兼容性时。它允许具有较小捕获集合的值在需要具有较大捕获集合的地方使用,这基于一种替代原则,即更受限制的 Capability 集合是较少受限制的集合的子类型。</li>
+<li><strong>Capability Classes:</strong> 扩展了 <code>caps.Capability</code> trait 的类被称为 Capability Class。它们的类型捕获集合始终为 <code>&#123;cap&#125;</code>。Capability Class 似乎提供了一种在类型系统中显式定义和管理基本 Capability 的方法。它们与通用 Capability <code>cap</code> 的关联表明,它们具有与环境进行广泛交互的潜力。</li>
+</ul>
+<blockquote>
+<p>Capture Checking 的主要目标是通过静态地跟踪资源或能力的使用情况,从而防止与资源生命周期和可访问性相关的错误。这尤其在涉及资源管理和并发编程的场景中显得至关重要。通过这种静态跟踪,Capture Checking 旨在提高代码的整体安全性,并增强程序的鲁棒性。</p>
+</blockquote>
+<p>Capture Checking 试图解决编程语言中长期存在的一些问题:</p>
+<ul>
+<li><strong>不安全的资源管理:</strong> 例如,传统的 <code>try-with-resources</code> 模式旨在确保资源在使用后被正确关闭。Capture Checking 通过跟踪与资源相关的 Capabilities,可以防止在资源关闭或失效后继续使用它的情况。文档中提到的 <code>usingLogFile</code> 示例就展示了这一点,其中一个闭包尝试写入一个已经关闭的文件,而Capture Checking可以捕获这种不安全的操作:</li>
+</ul>
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">usingLogFile</span></span>[<span class="type">T</span>](op: <span class="type">FileOutputStream</span> =&gt; <span class="type">T</span>): <span class="type">T</span> =</span><br><span class="line"> <span class="keyword">val</span> logFile = <span class="type">FileOutputStream</span>(<span class="string">&quot;log&quot;</span>)</span><br><span class="line"> <span class="keyword">val</span> result = op(logFile)</span><br><span class="line"> logFile.close()</span><br><span class="line"> result</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">usingLogFile</span></span>[<span class="type">T</span>](op: <span class="type">FileOutputStream</span>^ =&gt; <span class="type">T</span>): <span class="type">T</span> =</span><br><span class="line"> <span class="comment">// same body as before</span></span><br></pre></td></tr></table></figure>
+
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">| val later = usingLogFile &#123; f =&gt; () =&gt; f.write(0) &#125;</span><br><span class="line">| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span><br><span class="line">|The expression&#x27;s type () =&gt; Unit is not allowed to capture the root capability `cap`.</span><br><span class="line">|This usually means that a capability persists longer than its allowed lifetime.</span><br></pre></td></tr></table></figure>
+
+<ul>
+<li><strong>Effect Polymorphism:</strong> Capture Checking 提供了一种更灵活和精确地推理和控制副作用的机制。它可以被视为一种 Effect system,允许类型系统跟踪和控制代码可能产生的副作用。</li>
+<li><strong>“函数的颜色”问题:</strong> 在异步编程中,区分同步和异步操作一直是一个挑战。Capture Checking 有可能帮助区分和管理同步与异步计算,这通过跟踪与异步操作相关的 Capabilities 来实现。</li>
+<li><strong>基于区域的内存分配:</strong> Capture Checking 可以通过推理与内存位置相关的Capability,来促进更安全的内存管理。这暗示了 Capture Checking 与内存管理之间可能存在更深层次的集成,从而可能实现更高效和更安全的内存使用。</li>
+<li><strong>CE:</strong> Scala 3 通过使用 <code>CanThrow</code> 跟踪抛出特定异常的Capability,实现了一个干净且完全安全的 CE 系统。这提供了一种类型安全的替代方案,相较于传统的 CE,这种方式可能更加灵活和有原则。</li>
+<li><strong>逃逸分析:</strong> Capture Checking 可以防止局部Capability逃逸其预期的作用域。例如,当一个闭包捕获了一个局部Capability,并且这个闭包被赋值给一个全局变量或者以不安全的方式从函数返回时,Capture Checking 可以检测到这种潜在的风险。</li>
+</ul>
+<hr>
+<p>在 Scala 3 中,函数类型 <code>A =&gt; B</code> 被认为是<strong>不纯的</strong>,它可以捕获任意 Capability。实际上,<code>A =&gt; B</code> 是 <code>A -&gt;&#123;cap&#125; B</code> 的别名,明确地表明了它可能捕获 “通用 Capability”。这种默认行为反映了 Scala 过去函数可以拥有任意副作用的特点。然而,随着 Capture Checking 的引入,开发者被鼓励更明确地表达函数的纯度。</p>
+<p>与不纯函数相对的是<strong>纯函数</strong>,其类型为 <code>A -&gt; B</code>,表示该函数不能捕获任何 Capability。纯函数是函数式编程中的核心概念,Capture Checking 提供了一种在类型层面强制执行纯性的方法。确保函数的纯性可以使代码更具可预测性和可测试性,因为纯函数的输出完全取决于其输入,并且没有副作用。</p>
+<p>开发者还可以<strong>指定函数可以捕获的特定 Capability</strong>,语法为 <code>A -&gt;&#123;c, d&#125; B</code>,表示该函数可以捕获 Capability <code>c</code> 和 <code>d</code>。这种语法允许对函数可以使用的Capability 进行精确控制,从而提高了资源管理的细粒度。通过显式列出捕获的 Capability,编译器可以验证函数是否遵守这些约束,并防止其意外访问其他资源。</p>
+<p><strong>捕获注解</strong> <code>^</code> 的优先级高于 <code>-&gt;</code> 。理解运算符的优先级对于正确解释和编写带有捕获注解的函数类型至关重要。不正确的解析可能导致意想不到的行为或类型错误。例如,<code>A ^ C -&gt; B</code> 表示一个从捕获的 <code>A</code> 到 <code>B</code> 的纯函数。</p>
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span></span>(x: -&gt;&#123;c&#125; <span class="type">Int</span>): <span class="type">Int</span></span><br></pre></td></tr></table></figure>
+
+<p>Capture Checking 也适用于<strong>上下文函数</strong>。不纯的上下文函数使用 <code>?=&gt;</code>,行为类似于 <code>=&gt;</code>,可以捕获任意Capability。纯的上下文函数使用 <code>?-&gt;</code>,行为类似于 <code>-&gt;</code>,不能捕获任何Capability。这表明,Capture Checking扩展到了上下文函数,允许控制在它们的隐式参数作用域内捕获的 Capability。</p>
+<p>值得注意的是,<strong>方法</strong>本身并不是值,因此它们不直接捕获Capability。相反,它们对 Capability 的引用会被计入封闭对象的捕获集中。这种区分很重要,因为方法的捕获行为与它们所属对象的状态和Capability相关联,这反映了 Scala 的面向对象特性。</p>
+<p>与函数类型类似,Capture Checking的概念也延伸到了<strong>命名参数类型</strong>。<code>=&gt; Int</code> 允许任意Capability引用,类似于不纯函数类型。<code>-&gt; Int</code> 禁止任何Capability引用,类似于纯函数类型。而 <code>-&gt;&#123;c&#125; Int</code> 则只允许引用Capability <code>c</code>。这种一致性确保了即使是延迟求值的表达式也遵循Capability约束。</p>
+<p><strong>子捕获</strong>(<code>C₁ &lt;: C₂</code>)定义了捕获集之间的关系。捕获集 <code>C₁</code> 是 <code>C₂</code> 的子类型,如果 <code>C₂</code> 包含了 <code>C₁</code> 中的每一个元素,并且满足以下条件之一:<code>c ∈ C₂</code>(直接包含);<code>c</code> 是一个类参数,且 <code>C₂</code> 包含 <code>Cls.this</code>(Capability 来源于封闭的类实例);<code>c</code> 的类型具有捕获集 <code>C</code>,且 <code>C &lt;: C₂</code>(基于 Capability 类型的递归子捕获)。子捕获定义了 Capability 依赖的层级结构,这对于类型系统判断一个需要特定 Capability 集合的值是否可以在提供不同 Capability 集合的上下文中使用至关重要。</p>
+<p>对于<strong>捕获类型的子类型</strong>,存在以下规则:纯类型是捕获类型的子类型(<code>T &lt;: C T</code>);较小的捕获集会产生子类型(如果 <code>C₁ &lt;: C₂</code> 且 <code>T₁ &lt;: T₂</code>,则 <code>C₁ T₁ &lt;: C₂ T₂</code>)。这意味着一个依赖较少 Capability 的值通常更通用,可以在更广泛的场景中使用。根 Capability <code>&#123;cap&#125;</code> 覆盖了所有其他捕获集,因此任何特定的捕获集都是 <code>&#123;cap&#125;</code> 的子类型。这允许具有特定捕获要求的类型在允许任何 Capability 的上下文中使用。</p>
+<p><strong>Capability widening</strong>(也称为 _avoidance_)是一种简化局部变量类型的机制。局部变量的类型会被 widening 到不提及该变量本身的最小超类型,这个过程通常会涉及到变量的捕获集。这种加宽有助于改善类型推断和代码清晰度,避免局部变量的类型变得过于复杂。</p>
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">fs: <span class="type">FileSystem</span>^</span><br><span class="line">ct: <span class="type">CanThrow</span>[<span class="type">Exception</span>]^</span><br><span class="line">l : <span class="type">Logger</span>^&#123;fs&#125;</span><br><span class="line"></span><br><span class="line">&#123;l&#125; &lt;: &#123;fs&#125; &lt;: &#123;cap&#125;</span><br><span class="line">&#123;fs&#125; &lt;: &#123;fs, ct&#125; &lt;: &#123;cap&#125;</span><br><span class="line">&#123;ct&#125; &lt;: &#123;fs, ct&#125; &lt;: &#123;cap&#125;</span><br></pre></td></tr></table></figure>
+
+<p>继承自 <code>caps.Capability</code> 的类具有隐式的 <code>&#123;cap&#125;</code> 捕获集。这表明这些类的实例本质上代表了一种 Capability。Capability 类提供了一种将 Capability 显式定义和管理为类型系统中的一等公民的方式。开发者可以创建具有特定语义和使用模式的自定义 Capability。</p>
+<p>在使用 Capability 类的场景中,通常会结合 using clauses 和<strong>隐式参数</strong>来减少在代码中显式传递 Capability 的需要。这两种方法提供了一种自动将必要的 Capability 提供给函数和方法的方式,从而减少了样板代码并提高了代码的可读性。</p>
+<p><strong>闭包</strong>会捕获在其主体中引用的来自其周围环境的 Capability。这导致闭包的函数类型中包含捕获集。例如,如果一个闭包引用了一个局部变量 <code>fs</code>,而 <code>fs</code> 是一个 Capability,那么该闭包的类型可能就是 <code>String -&gt;&#123;fs&#125; Unit</code>。这意味着闭包继承了其封闭代码的 Capability 要求,确保它们只能在这些 Capability 可用的上下文中被使用。</p>
+<p>此外,闭包还会捕获它们调用的函数的 Capability。如果一个闭包调用了一个需要特定 Capability 的函数,那么该闭包的捕获集也会包含该 Capability。这种传递性的捕获机制确保了所有 Capability 依赖,无论是直接的还是间接的,都会被闭包所跟踪。</p>
+<p>类会将其方法中使用的 Capability 保留为(私有)字段。这意味着如果一个方法使用了作为构造函数参数传递的Capability,该类很可能会存储对它的引用。这会导致类的类型中包含捕获集。例如,一个使用文件系统Capability <code>xfs</code> 的 <code>Logger</code> 类可能具有类型 <code>Logger^&#123;xfs&#125;</code>。这表明类封装了它们所依赖的Capability,并将这些依赖作为其类型签名的一部分。</p>
+<p><code>@constructorOnly</code> 注解可以用于标记一个仅在构造函数中使用而不会作为字段保留的类参数。这有助于减少类的捕获集。如果一个参数仅用于初始化,后续不再访问,那么类就没有必要将其保留为一种 Capability。</p>
+<p>类的<strong>捕获引用</strong>包括从类外部使用的局部 Capability 以及具有捕获类型的构造函数参数(参数Capability)。局部Capability会被内部类继承。</p>
+<p>类实例的 <code>this</code> 的捕获集是根据捕获的引用、父类以及类内部的使用约束来推断的 1。这种自动推断机制在很多情况下减少了手动指定类捕获集的需要。</p>
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> caps.<span class="type">Capability</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileSystem</span> <span class="keyword">extends</span> <span class="title">Capability</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Logger</span>(<span class="params">using <span class="type">FileSystem</span></span>)</span>:</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">log</span></span>(s: <span class="type">String</span>): <span class="type">Unit</span> = ???</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span></span>(<span class="keyword">using</span> fs: <span class="type">FileSystem</span>) =</span><br><span class="line"> <span class="keyword">val</span> l: <span class="type">Logger</span>^&#123;fs&#125; = <span class="type">Logger</span>()</span><br><span class="line"> ...</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Logger</span>(<span class="params">using <span class="type">FileSystem</span>^&#123;cap&#125;</span>)</span>:</span><br><span class="line"> ^^^^^^^^^^^^^^</span><br><span class="line"> redundant capture: <span class="type">FileSystem</span> already accounts <span class="keyword">for</span> cap</span><br></pre></td></tr></table></figure>
+
+
+<p><strong>捕获隧道 (Capture Tunnelling)</strong> 是指当一个类型变量被一个捕获类型实例化时,捕获信息不会立即传播到外层的泛型类型。相反,捕获会“穿过隧道”,并在类型变量被访问或其成员被使用时重新出现。这种机制有助于以更简洁和可管理的方式处理泛型代码中的捕获集,避免类型签名过于复杂。</p>
+<p><strong>逃逸检查</strong>施加了一些限制。作为类型变量实例的捕获类型不能携带通用Capability <code>cap</code> 。可变变量也不能拥有通用捕获集 。逃逸检查阻止了在参数化类型的参数中返回或分配带有局部 Capability 的闭包,因为这可能导致 Capability 逃逸其预期的作用域。<strong>单调性规则</strong>指出,在一个带有字段 <code>f</code> 的类中,<code>&#123;this&#125;</code> 覆盖了 <code>&#123;this.f&#125;</code> 以及 <code>this.f</code> 对纯参数的应用。这意味着如果类实例本身被视为一种 Capability,那么其字段所持有的任何 Capability 也会被隐式地覆盖。逃逸检查对于维护 Capability 跟踪的完整性至关重要,它可以防止 Capability 在其预期生命周期或作用域之外被使用,尤其是在泛型和可变状态的上下文中。</p>
+<p><strong>受检异常</strong>可以通过导入 <code>language.experimental.saferExceptions</code> 来启用。方法上的 <code>throws</code> 子句会扩展为一个隐式的 <code>CanThrow</code> Capability参数,表明该方法可能抛出指定类型的异常。<code>throw</code> 表达式需要 <code>CanThrow</code> Capability,而 <code>try</code> 表达式会创建这种Capability。在 <code>language.experimental.captureChecking</code> 下,由于逃逸的 Capability 而导致未处理异常的代码会被拒绝。为了实现这种集成,<code>CanThrow</code> 需要继承 <code>Capability</code>,并且需要将逃逸检查扩展到 <code>try</code> 表达式,以防止捕获 <code>cap</code>。Capture Checking 与受检异常的集成确保了异常的可能性也被作为一种 Capability 需求来跟踪,从而加强了语言的整体资源管理和错误处理 Capability。</p>
+<hr>
+<p>文档中提供了一个关于<strong>惰性列表</strong>(Lazy Lists)的较大示例,很好地展示了 Capture Checking 如何在更复杂的数据结构中工作。<code>LzyList</code> 的 <code>tail</code> 具有一个捕获注解,表明它可以捕获与列表相同的引用。诸如 <code>map</code>、<code>filter</code> 和 <code>concat</code> 等操作在惰性列表上能够正确地推断出捕获集,这取决于原始列表和所使用的函数。值得注意的是 effect polymorphism的概念,传递给这些操作的纯函数不会出现在结果的捕获集中。这与严格列表形成对比,严格列表通常不需要捕获注解,因为它们的副作用不会被延迟。惰性列表的例子具体说明了Capture Checking 如何应用于非平凡的数据结构,展示了其在涉及延迟求值的复杂场景中跟踪依赖关系的Capability。effect polymorphism 是一个显著的优点,它允许在不影响捕获集的情况下使用纯计算。</p>
+<hr>
+<p><strong>表 1: 代码示例与演示概念</strong></p>
+<table>
+<thead>
+<tr>
+<th></th>
+<th></th>
+<th></th>
+</tr>
+</thead>
+<tbody><tr>
+<td><strong>代码片段</strong></td>
+<td><strong>演示概念</strong></td>
+<td><strong>捕获行为解释</strong></td>
+</tr>
+<tr>
+<td><code>import language.experimental.captureChecking</code></td>
+<td>启用Capture Checking</td>
+<td>必须通过此导入才能使用Capture Checking特性。</td>
+</tr>
+<tr>
+<td><code>T^&#123;c₁, ..., cᵢ&#125;</code></td>
+<td>捕获类型的声明</td>
+<td>表示类型 <code>T</code> 的值可能依赖或访问Capability <code>c₁, ..., cᵢ</code>。</td>
+</tr>
+<tr>
+<td><code>A =&gt; B</code></td>
+<td>不纯函数类型</td>
+<td>函数可以捕获任意Capability,是 <code>A -&gt;&#123;cap&#125; B</code> 的别名。</td>
+</tr>
+<tr>
+<td><code>A -&gt; B</code></td>
+<td>纯函数类型</td>
+<td>函数不能捕获任何Capability。</td>
+</tr>
+<tr>
+<td><code>A -&gt;&#123;c, d&#125; B</code></td>
+<td>指定捕获Capability的函数类型</td>
+<td>函数只能捕获Capability <code>c</code> 和 <code>d</code>。</td>
+</tr>
+<tr>
+<td><code>=&gt; Int</code></td>
+<td>允许任意Capability引用的命名参数类型</td>
+<td>类似于不纯函数类型。</td>
+</tr>
+<tr>
+<td><code>-&gt; Int</code></td>
+<td>禁止任何Capability引用的命名参数类型</td>
+<td>类似于纯函数类型。</td>
+</tr>
+<tr>
+<td><code>-&gt;&#123;c&#125; Int</code></td>
+<td>只允许特定Capability引用的命名参数类型</td>
+<td>只允许引用Capability <code>c</code>。</td>
+</tr>
+<tr>
+<td><code>class C extends caps.Capability</code></td>
+<td>Capability类的定义</td>
+<td>类 <code>C</code> 的实例本身代表一种Capability,具有隐式的 <code>&#123;cap&#125;</code> 捕获集。</td>
+</tr>
+<tr>
+<td><code>@constructorOnly val p: Int</code></td>
+<td>构造函数专用参数</td>
+<td>参数 <code>p</code> 仅在构造函数中使用,不会作为类的字段保留,有助于减少类的捕获集。</td>
+</tr>
+<tr>
+<td><code>() -&gt; Iterator^</code></td>
+<td>具有存在性Capability的函数结果类型</td>
+<td>返回一个迭代器,该迭代器可能捕获某种Capability,但具体是哪种Capability在编译时未知。</td>
+</tr>
+<tr>
+<td><code>ops*</code></td>
+<td>可达Capability</td>
+<td>表示通过Capability <code>ops</code> 可访问的任何协变出现的Capability。</td>
+</tr>
+<tr>
+<td><code>type Source[X^] = ...</code></td>
+<td>使用Capability多态的类型定义</td>
+<td>类型 <code>Source</code> 被参数化为可以持有Capability集 <code>X^</code>。</td>
+</tr>
+</tbody></table>
+<p>当 <code>cap</code> 出现在函数的结果类型中时,通常表示一个由存在性量词绑定的未知类型(例如,<code>() -&gt; Iterator^</code> 意味着 <code>() -&gt; Exists x. Iterator^x</code>)。这表明返回的迭代器可能捕获了某种 Capability,但具体的哪种 Capability 在静态类型检查时是未知的。在内部,这种存在性 Capability 使用带有 sealed trait <code>Exists</code> 的依赖函数类型来表示 。结果类型中协变的 <code>cap</code> 会被替换为一个新的 existential variable。当应用一个具有 existential result 类型 <code>Exists ex.T</code> 的函数时,结果是 <code>T</code>,其中 <code>ex</code> 被 <code>cap</code> 替换。Existential Capability 允许类型系统表达在编译时具体捕获的 Capability 未知的情况,从而提供了灵活性,同时仍然保持了一定程度的跟踪。</p>
+<p>**Reach Capability **用于表达一个变量引用了通过另一个Capability“Reach”的任何操作。例如,如果 <code>ops</code> 是一个表示一组操作的Capability,那么 <code>ops*</code> 就表示出现在 <code>ops</code> 类型中且通过 <code>ops</code> 访问的任何协变 Capability。Reach Capability 提供了一种间接推理和跟踪 Capability 的方式,这对于建模具有相互连接资源的复杂系统非常有用。</p>
+<p><strong>Capability 多态</strong>允许使用带有上界 <code>CapSet</code> 的类型变量来参数化操作的捕获集。这使得定义诸如 <code>Source[X^]</code> 这样的类型成为可能,其中 <code>X^</code> 表示监听器可以持有的一组 Capability。Capability 多态增强了代码的表达性和可重用性,因为它允许函数和数据结构在它们可能依赖的 Capability 集上进行参数化。</p>
+<hr>
+<p>Scala 3 提供了几个与 Capture Checking 相关的编译选项,。<code>-Xprint:cc</code> 选项会打印出带有推断捕获类型的程序代码 1。这对于理解编译器是如何推断捕获集的以及调试与类型相关的错误非常有用。另一个选项是 <code>-Ycc-debug</code>,它提供了关于 Capture Checking 过程的详细的、面向实现的的信息。这个选项对于需要深入了解 Capture Checking 器工作原理或者遇到复杂问题的开发者来说很有帮助。这些编译选项是使用 Capture Checking 的开发者的重要工具,它们允许开发者检查编译器的推理并诊断问题。</p>
+<p>Capture Checking被实现为一个传播约束求解器,它在标准的类型检查阶段之后运行,未知的捕获集由约束变量表示。在类型中显式编写的捕获集被求解器视为常量。类型之间的子类型要求会转化为它们各自捕获集上的子捕获测试。求解器根据程序的结构和类型约束,将 Capability 传播给约束变量及其超集。捕获集的映射受到类型参数的变性(协变、逆变、不变)的影响。<strong>装箱</strong>(boxing)和<strong>拆箱</strong>(unboxing)是用于隐藏和恢复捕获集的虚拟操作,特别是在类型参数的上下文中用于管理捕获隧道。<code>-Ycc-debug</code> 的输出提供了关于变量依赖关系和Capture Checking器在编译过程中的状态的深入信息。</p>
+
+</div>
+
+<script>
+ window.onload = detectors();
+</script>
+ <div class="post-footer">
+ <div class="h-line-primary"></div>
+ <nav class="post-nav">
+ <div class="prev-item">
+
+ </div>
+ <div class="next-item">
+
+ <div class="icon arrow-right"></div>
+ <div class="post-link">
+ <a href="/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/">Next</a>
+ </div>
+
+ </div>
+ </nav>
+</div>
+
+
+ <div class="post-comment">
+
+
+
+
+
+
+
+</div>
+
+
+</article>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/archives/2025/03/index.html b/archives/2025/03/index.html
index 9b83f5cd..50d41453 100644
--- a/archives/2025/03/index.html
+++ b/archives/2025/03/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/03/25/Scala-3-Capture-Checking/">
+
+ Scala 3 (Capture Checking)
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 25, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/">
TDD 和 DDD 的一些小想法
diff --git a/archives/2025/index.html b/archives/2025/index.html
index 03c326ce..678bcf32 100644
--- a/archives/2025/index.html
+++ b/archives/2025/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/03/25/Scala-3-Capture-Checking/">
+
+ Scala 3 (Capture Checking)
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 25, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/">
TDD 和 DDD 的一些小想法
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/02/11/%E4%BB%8E%E4%BA%8B%E4%BB%B6%E9%A3%8E%E6%9A%B4%E7%9C%8B%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/">
-
- 从事件风暴看领域驱动设计
-
- </a>
- </div>
-
- <span class="post-date">Feb 11, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/2025/page/2/index.html b/archives/2025/page/2/index.html
index ed8ffb97..bda9f2f7 100644
--- a/archives/2025/page/2/index.html
+++ b/archives/2025/page/2/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/02/11/%E4%BB%8E%E4%BA%8B%E4%BB%B6%E9%A3%8E%E6%9A%B4%E7%9C%8B%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/">
+
+ 从事件风暴看领域驱动设计
+
+ </a>
+ </div>
+
+ <span class="post-date">Feb 11, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/02/10/%E5%AE%9E%E6%97%B6%E6%90%9C%E7%B4%A2%E4%B8%AD%E7%9A%84%E9%98%B2%E6%8A%96%E5%87%BD%E6%95%B0/">
实时搜索中的防抖函数
diff --git a/archives/index.html b/archives/index.html
index 6cf1cbbb..142a24d6 100644
--- a/archives/index.html
+++ b/archives/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/03/25/Scala-3-Capture-Checking/">
+
+ Scala 3 (Capture Checking)
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 25, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/">
TDD 和 DDD 的一些小想法
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/02/11/%E4%BB%8E%E4%BA%8B%E4%BB%B6%E9%A3%8E%E6%9A%B4%E7%9C%8B%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/">
-
- 从事件风暴看领域驱动设计
-
- </a>
- </div>
-
- <span class="post-date">Feb 11, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/10/index.html b/archives/page/10/index.html
index 1b03e151..a39b7d87 100644
--- a/archives/page/10/index.html
+++ b/archives/page/10/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/04/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
+
+ 二零二三年四月二十五日
+
+ </a>
+ </div>
+
+ <span class="post-date">Apr 25, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/04/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
二零二三年四月二十二日
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/02/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
-
- 二零二三年二月二十五日
-
- </a>
- </div>
-
- <span class="post-date">Feb 25, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/11/index.html b/archives/page/11/index.html
index f1bd4503..bfb1f9f5 100644
--- a/archives/page/11/index.html
+++ b/archives/page/11/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/02/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
+
+ 二零二三年二月二十五日
+
+ </a>
+ </div>
+
+ <span class="post-date">Feb 25, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/02/24/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/">
二零二三年二月二十四日
@@ -302,24 +320,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
-
- 二零二二年八月二十一日
-
- </a>
- </div>
-
- <span class="post-date">Aug 21, 2022</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/12/index.html b/archives/page/12/index.html
index 57b0e00d..163573b3 100644
--- a/archives/page/12/index.html
+++ b/archives/page/12/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
+
+ 二零二二年八月二十一日
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 21, 2022</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2022/03/14/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E5%9B%9B%E6%97%A5/">
二零二二年三月十四日
diff --git a/archives/page/2/index.html b/archives/page/2/index.html
index af02e0a5..03dc2922 100644
--- a/archives/page/2/index.html
+++ b/archives/page/2/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/02/11/%E4%BB%8E%E4%BA%8B%E4%BB%B6%E9%A3%8E%E6%9A%B4%E7%9C%8B%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/">
+
+ 从事件风暴看领域驱动设计
+
+ </a>
+ </div>
+
+ <span class="post-date">Feb 11, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/02/10/%E5%AE%9E%E6%97%B6%E6%90%9C%E7%B4%A2%E4%B8%AD%E7%9A%84%E9%98%B2%E6%8A%96%E5%87%BD%E6%95%B0/">
实时搜索中的防抖函数
@@ -302,24 +320,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/10/18/Dealing-with-complex-dependency-injection-in-FSharp/">
-
- Dealing with complex dependency injection in FSharp
-
- </a>
- </div>
-
- <span class="post-date">Oct 18, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/3/index.html b/archives/page/3/index.html
index 6366d4d8..63061be0 100644
--- a/archives/page/3/index.html
+++ b/archives/page/3/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/10/18/Dealing-with-complex-dependency-injection-in-FSharp/">
+
+ Dealing with complex dependency injection in FSharp
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 18, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/10/06/Obsidian-Vault-%E7%9A%84-obsidian-%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E5%90%84%E6%96%87%E4%BB%B6%E4%BD%9C%E7%94%A8/">
Obsidian Vault 的 .obsidian 目录中的各文件作用
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
-
- 藿香正气水和藿香正气口服液的区别
-
- </a>
- </div>
-
- <span class="post-date">Sep 1, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/4/index.html b/archives/page/4/index.html
index 79dc7274..a2741c57 100644
--- a/archives/page/4/index.html
+++ b/archives/page/4/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
+
+ 藿香正气水和藿香正气口服液的区别
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 1, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/08/12/%E7%9B%B4%E7%B3%BB%E8%A1%80%E4%BA%B2%E4%B9%8B%E9%97%B4%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%BE%93%E8%A1%80/">
直系血亲之间不能直接输血
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
-
- 二〇二四年五月十六日
-
- </a>
- </div>
-
- <span class="post-date">May 16, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/5/index.html b/archives/page/5/index.html
index 37b67cf3..5dc4ba1b 100644
--- a/archives/page/5/index.html
+++ b/archives/page/5/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
+
+ 二〇二四年五月十六日
+
+ </a>
+ </div>
+
+ <span class="post-date">May 16, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/05/13/%E7%BB%99%E5%B0%B8%E4%BD%93%E4%B8%8A-ECMO-%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3/">
给尸体上 ECMO 并维持心跳
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
-
- 慢性肺源性心脏病
-
- </a>
- </div>
-
- <span class="post-date">Jan 23, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/6/index.html b/archives/page/6/index.html
index 075b9b54..b6be2c43 100644
--- a/archives/page/6/index.html
+++ b/archives/page/6/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
+
+ 慢性肺源性心脏病
+
+ </a>
+ </div>
+
+ <span class="post-date">Jan 23, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/">
二〇二四年一月二十三日
@@ -302,24 +320,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/11/06/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%85%AD%E6%97%A5/">
-
- 二零二三年十一月六日
-
- </a>
- </div>
-
- <span class="post-date">Nov 6, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/7/index.html b/archives/page/7/index.html
index 1c253946..197eb09c 100644
--- a/archives/page/7/index.html
+++ b/archives/page/7/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/11/06/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%85%AD%E6%97%A5/">
+
+ 二零二三年十一月六日
+
+ </a>
+ </div>
+
+ <span class="post-date">Nov 6, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/10/25/%E5%84%BF%E7%AB%A5%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92Omicron%E6%A0%AA%E5%92%8C%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B7%B7%E5%90%88%E6%84%9F%E6%9F%93%E9%87%8D%E7%97%87%E8%82%BA%E7%82%8E1%E4%BE%8B/">
儿童新型冠状病毒Omicron株和肺炎支原体混合感染重症肺炎1例
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
-
- A Brief History of Just-In-Time
-
- </a>
- </div>
-
- <span class="post-date">Sep 28, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/8/index.html b/archives/page/8/index.html
index 031d20eb..1ba3d192 100644
--- a/archives/page/8/index.html
+++ b/archives/page/8/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
+
+ A Brief History of Just-In-Time
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 28, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/09/13/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%B8%89%E6%97%A5/">
二零二三年九月十三日
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
-
- 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
-
- </a>
- </div>
-
- <span class="post-date">Jun 28, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/9/index.html b/archives/page/9/index.html
index d8cd49fd..391f67ff 100644
--- a/archives/page/9/index.html
+++ b/archives/page/9/index.html
@@ -145,6 +145,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
+
+ 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
+
+ </a>
+ </div>
+
+ <span class="post-date">Jun 28, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/06/28/caml-release-runtime-system%E5%AF%BC%E8%87%B4%E7%9A%84%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98/">
caml_release_runtime_system导致的死锁问题
@@ -300,24 +318,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/04/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
-
- 二零二三年四月二十五日
-
- </a>
- </div>
-
- <span class="post-date">Apr 25, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/search.xml b/search.xml
index eae9967c..3fca634f 100644
--- a/search.xml
+++ b/search.xml
@@ -1829,6 +1829,167 @@
</tags>
</entry>
<entry>
+ <title>Scala 3 (Capture Checking)</title>
+ <url>/2025/03/25/Scala-3-Capture-Checking/</url>
+ <content><![CDATA[<blockquote>
+<p><a href="https://docs.scala-lang.org/scala3/reference/experimental/cc.html">https://docs.scala-lang.org/scala3/reference/experimental/cc.html</a></p>
+</blockquote>
+<p>Scala 3 在其类型系统的演进过程中,引入了诸多实验性特性,旨在提升语言的表达能力和代码的可靠性。Capture Checking 是其中一项引人注目的创新。目前还在试验阶段,其通过增强静态分析的能力,在编译时捕获潜在的错误,从而减少运行时问题的发生。</p>
+<p>Capture Checking引入了一系列核心概念,这些概念共同构成了其类型系统的基础:</p>
+<ul>
+<li><strong>捕获类型 (Capturing Types):</strong> 捕获类型采用 <code>T^&#123;c₁, ..., cᵢ&#125;</code> 的形式,其中 <code>T</code> 是一个普通的 Scala 类型,而 <code>&#123;c₁, ..., cᵢ&#125;</code> 则是一个捕获的 Capabilities 集合。这个捕获集合明确地列出了类型 <code>T</code> 的值所依赖或能够访问的 Capabilities。这种类型表示方式为类型信息增加了一个新的维度,它不仅描述了数据的结构,还包含了数据交互的环境或资源的相关信息。</li>
+<li><strong>Capabilities:</strong> 在 Capture Checking 的语境下,Capabilities 指的是方法或类的参数、局部变量,或者其类型本身就是一个具有非空捕获集合的捕获类型的封闭类的 <code>this</code> 引用。这些实体之所以需要被跟踪,是因为它们通常代表了执行某些操作或访问某些资源的“权限”或“授权”。跟踪这些 Capabilities 意味着可以控制这种影响在程序中的传播方式和范围。</li>
+<li><strong>通用 Capability (<code>cap</code>):</strong> 通用 Capability <code>cap</code> 是一个最基本的 Capability,所有的其他的 Capabilities 都派生自它。类型 <code>T^</code> 是 <code>T^&#123;cap&#125;</code> 的简写形式,表示类型 <code>T</code> 的值可以捕获任意的 Capability。<code>cap</code> 的存在为 Capture Checking 系统提供了一种 <strong>处理精确跟踪并非必需或不可行</strong> 的场景的方式。它充当了一种通配符,表明一个值可能依赖于任何 Capability。</li>
+<li><strong>纯函数 vs. 非纯函数 (Pure vs. Impure Functions):</strong> Capture Checking 显式地区分了纯函数和非纯函数。类型为 <code>A =&gt; B</code> 的函数被认为是非纯函数,它可以捕获任意 Capability,等价于 <code>A -&gt;&#123;cap&#125; B</code> 1。而类型为 <code>A -&gt; B</code> 的函数则是纯函数,它不能捕获任何 Capability。此外,还可以使用 <code>A -&gt;&#123;c, d&#125; B</code> 的形式来显式指定函数只能捕获 Capability <code>c</code> 和 <code>d</code>。这种区分使得类型系统能够强制执行函数式编程的原则,其中纯函数因其可预测性和可测试性而备受推崇。</li>
+<li><strong>子捕获 (Subcapturing):</strong> 子捕获描述了捕获集合之间的关系。如果一个捕获集合 <code>C₁</code> 中的每个元素都包含在另一个捕获集合 <code>C₂</code> 中,那么我们说 <code>C₁</code> 是 <code>C₂</code> 的子捕获,记作 <code>C₁ &lt;: C₂</code> 1。子捕获关系在类型系统中扮演着重要的角色,例如在判断类型兼容性时。它允许具有较小捕获集合的值在需要具有较大捕获集合的地方使用,这基于一种替代原则,即更受限制的 Capability 集合是较少受限制的集合的子类型。</li>
+<li><strong>Capability Classes:</strong> 扩展了 <code>caps.Capability</code> trait 的类被称为 Capability Class。它们的类型捕获集合始终为 <code>&#123;cap&#125;</code>。Capability Class 似乎提供了一种在类型系统中显式定义和管理基本 Capability 的方法。它们与通用 Capability <code>cap</code> 的关联表明,它们具有与环境进行广泛交互的潜力。</li>
+</ul>
+<blockquote>
+<p>Capture Checking 的主要目标是通过静态地跟踪资源或能力的使用情况,从而防止与资源生命周期和可访问性相关的错误。这尤其在涉及资源管理和并发编程的场景中显得至关重要。通过这种静态跟踪,Capture Checking 旨在提高代码的整体安全性,并增强程序的鲁棒性。</p>
+</blockquote>
+<p>Capture Checking 试图解决编程语言中长期存在的一些问题:</p>
+<ul>
+<li><strong>不安全的资源管理:</strong> 例如,传统的 <code>try-with-resources</code> 模式旨在确保资源在使用后被正确关闭。Capture Checking 通过跟踪与资源相关的 Capabilities,可以防止在资源关闭或失效后继续使用它的情况。文档中提到的 <code>usingLogFile</code> 示例就展示了这一点,其中一个闭包尝试写入一个已经关闭的文件,而Capture Checking可以捕获这种不安全的操作:</li>
+</ul>
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">usingLogFile</span></span>[<span class="type">T</span>](op: <span class="type">FileOutputStream</span> =&gt; <span class="type">T</span>): <span class="type">T</span> =</span><br><span class="line"> <span class="keyword">val</span> logFile = <span class="type">FileOutputStream</span>(<span class="string">&quot;log&quot;</span>)</span><br><span class="line"> <span class="keyword">val</span> result = op(logFile)</span><br><span class="line"> logFile.close()</span><br><span class="line"> result</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">usingLogFile</span></span>[<span class="type">T</span>](op: <span class="type">FileOutputStream</span>^ =&gt; <span class="type">T</span>): <span class="type">T</span> =</span><br><span class="line"> <span class="comment">// same body as before</span></span><br></pre></td></tr></table></figure>
+
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">| val later = usingLogFile &#123; f =&gt; () =&gt; f.write(0) &#125;</span><br><span class="line">| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span><br><span class="line">|The expression&#x27;s type () =&gt; Unit is not allowed to capture the root capability `cap`.</span><br><span class="line">|This usually means that a capability persists longer than its allowed lifetime.</span><br></pre></td></tr></table></figure>
+
+<ul>
+<li><strong>Effect Polymorphism:</strong> Capture Checking 提供了一种更灵活和精确地推理和控制副作用的机制。它可以被视为一种 Effect system,允许类型系统跟踪和控制代码可能产生的副作用。</li>
+<li><strong>“函数的颜色”问题:</strong> 在异步编程中,区分同步和异步操作一直是一个挑战。Capture Checking 有可能帮助区分和管理同步与异步计算,这通过跟踪与异步操作相关的 Capabilities 来实现。</li>
+<li><strong>基于区域的内存分配:</strong> Capture Checking 可以通过推理与内存位置相关的Capability,来促进更安全的内存管理。这暗示了 Capture Checking 与内存管理之间可能存在更深层次的集成,从而可能实现更高效和更安全的内存使用。</li>
+<li><strong>CE:</strong> Scala 3 通过使用 <code>CanThrow</code> 跟踪抛出特定异常的Capability,实现了一个干净且完全安全的 CE 系统。这提供了一种类型安全的替代方案,相较于传统的 CE,这种方式可能更加灵活和有原则。</li>
+<li><strong>逃逸分析:</strong> Capture Checking 可以防止局部Capability逃逸其预期的作用域。例如,当一个闭包捕获了一个局部Capability,并且这个闭包被赋值给一个全局变量或者以不安全的方式从函数返回时,Capture Checking 可以检测到这种潜在的风险。</li>
+</ul>
+<hr>
+<p>在 Scala 3 中,函数类型 <code>A =&gt; B</code> 被认为是<strong>不纯的</strong>,它可以捕获任意 Capability。实际上,<code>A =&gt; B</code> 是 <code>A -&gt;&#123;cap&#125; B</code> 的别名,明确地表明了它可能捕获 “通用 Capability”。这种默认行为反映了 Scala 过去函数可以拥有任意副作用的特点。然而,随着 Capture Checking 的引入,开发者被鼓励更明确地表达函数的纯度。</p>
+<p>与不纯函数相对的是<strong>纯函数</strong>,其类型为 <code>A -&gt; B</code>,表示该函数不能捕获任何 Capability。纯函数是函数式编程中的核心概念,Capture Checking 提供了一种在类型层面强制执行纯性的方法。确保函数的纯性可以使代码更具可预测性和可测试性,因为纯函数的输出完全取决于其输入,并且没有副作用。</p>
+<p>开发者还可以<strong>指定函数可以捕获的特定 Capability</strong>,语法为 <code>A -&gt;&#123;c, d&#125; B</code>,表示该函数可以捕获 Capability <code>c</code> 和 <code>d</code>。这种语法允许对函数可以使用的Capability 进行精确控制,从而提高了资源管理的细粒度。通过显式列出捕获的 Capability,编译器可以验证函数是否遵守这些约束,并防止其意外访问其他资源。</p>
+<p><strong>捕获注解</strong> <code>^</code> 的优先级高于 <code>-&gt;</code> 。理解运算符的优先级对于正确解释和编写带有捕获注解的函数类型至关重要。不正确的解析可能导致意想不到的行为或类型错误。例如,<code>A ^ C -&gt; B</code> 表示一个从捕获的 <code>A</code> 到 <code>B</code> 的纯函数。</p>
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span></span>(x: -&gt;&#123;c&#125; <span class="type">Int</span>): <span class="type">Int</span></span><br></pre></td></tr></table></figure>
+
+<p>Capture Checking 也适用于<strong>上下文函数</strong>。不纯的上下文函数使用 <code>?=&gt;</code>,行为类似于 <code>=&gt;</code>,可以捕获任意Capability。纯的上下文函数使用 <code>?-&gt;</code>,行为类似于 <code>-&gt;</code>,不能捕获任何Capability。这表明,Capture Checking扩展到了上下文函数,允许控制在它们的隐式参数作用域内捕获的 Capability。</p>
+<p>值得注意的是,<strong>方法</strong>本身并不是值,因此它们不直接捕获Capability。相反,它们对 Capability 的引用会被计入封闭对象的捕获集中。这种区分很重要,因为方法的捕获行为与它们所属对象的状态和Capability相关联,这反映了 Scala 的面向对象特性。</p>
+<p>与函数类型类似,Capture Checking的概念也延伸到了<strong>命名参数类型</strong>。<code>=&gt; Int</code> 允许任意Capability引用,类似于不纯函数类型。<code>-&gt; Int</code> 禁止任何Capability引用,类似于纯函数类型。而 <code>-&gt;&#123;c&#125; Int</code> 则只允许引用Capability <code>c</code>。这种一致性确保了即使是延迟求值的表达式也遵循Capability约束。</p>
+<p><strong>子捕获</strong>(<code>C₁ &lt;: C₂</code>)定义了捕获集之间的关系。捕获集 <code>C₁</code> 是 <code>C₂</code> 的子类型,如果 <code>C₂</code> 包含了 <code>C₁</code> 中的每一个元素,并且满足以下条件之一:<code>c ∈ C₂</code>(直接包含);<code>c</code> 是一个类参数,且 <code>C₂</code> 包含 <code>Cls.this</code>(Capability 来源于封闭的类实例);<code>c</code> 的类型具有捕获集 <code>C</code>,且 <code>C &lt;: C₂</code>(基于 Capability 类型的递归子捕获)。子捕获定义了 Capability 依赖的层级结构,这对于类型系统判断一个需要特定 Capability 集合的值是否可以在提供不同 Capability 集合的上下文中使用至关重要。</p>
+<p>对于<strong>捕获类型的子类型</strong>,存在以下规则:纯类型是捕获类型的子类型(<code>T &lt;: C T</code>);较小的捕获集会产生子类型(如果 <code>C₁ &lt;: C₂</code> 且 <code>T₁ &lt;: T₂</code>,则 <code>C₁ T₁ &lt;: C₂ T₂</code>)。这意味着一个依赖较少 Capability 的值通常更通用,可以在更广泛的场景中使用。根 Capability <code>&#123;cap&#125;</code> 覆盖了所有其他捕获集,因此任何特定的捕获集都是 <code>&#123;cap&#125;</code> 的子类型。这允许具有特定捕获要求的类型在允许任何 Capability 的上下文中使用。</p>
+<p><strong>Capability widening</strong>(也称为 _avoidance_)是一种简化局部变量类型的机制。局部变量的类型会被 widening 到不提及该变量本身的最小超类型,这个过程通常会涉及到变量的捕获集。这种加宽有助于改善类型推断和代码清晰度,避免局部变量的类型变得过于复杂。</p>
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line">fs: <span class="type">FileSystem</span>^</span><br><span class="line">ct: <span class="type">CanThrow</span>[<span class="type">Exception</span>]^</span><br><span class="line">l : <span class="type">Logger</span>^&#123;fs&#125;</span><br><span class="line"></span><br><span class="line">&#123;l&#125; &lt;: &#123;fs&#125; &lt;: &#123;cap&#125;</span><br><span class="line">&#123;fs&#125; &lt;: &#123;fs, ct&#125; &lt;: &#123;cap&#125;</span><br><span class="line">&#123;ct&#125; &lt;: &#123;fs, ct&#125; &lt;: &#123;cap&#125;</span><br></pre></td></tr></table></figure>
+
+<p>继承自 <code>caps.Capability</code> 的类具有隐式的 <code>&#123;cap&#125;</code> 捕获集。这表明这些类的实例本质上代表了一种 Capability。Capability 类提供了一种将 Capability 显式定义和管理为类型系统中的一等公民的方式。开发者可以创建具有特定语义和使用模式的自定义 Capability。</p>
+<p>在使用 Capability 类的场景中,通常会结合 using clauses 和<strong>隐式参数</strong>来减少在代码中显式传递 Capability 的需要。这两种方法提供了一种自动将必要的 Capability 提供给函数和方法的方式,从而减少了样板代码并提高了代码的可读性。</p>
+<p><strong>闭包</strong>会捕获在其主体中引用的来自其周围环境的 Capability。这导致闭包的函数类型中包含捕获集。例如,如果一个闭包引用了一个局部变量 <code>fs</code>,而 <code>fs</code> 是一个 Capability,那么该闭包的类型可能就是 <code>String -&gt;&#123;fs&#125; Unit</code>。这意味着闭包继承了其封闭代码的 Capability 要求,确保它们只能在这些 Capability 可用的上下文中被使用。</p>
+<p>此外,闭包还会捕获它们调用的函数的 Capability。如果一个闭包调用了一个需要特定 Capability 的函数,那么该闭包的捕获集也会包含该 Capability。这种传递性的捕获机制确保了所有 Capability 依赖,无论是直接的还是间接的,都会被闭包所跟踪。</p>
+<p>类会将其方法中使用的 Capability 保留为(私有)字段。这意味着如果一个方法使用了作为构造函数参数传递的Capability,该类很可能会存储对它的引用。这会导致类的类型中包含捕获集。例如,一个使用文件系统Capability <code>xfs</code> 的 <code>Logger</code> 类可能具有类型 <code>Logger^&#123;xfs&#125;</code>。这表明类封装了它们所依赖的Capability,并将这些依赖作为其类型签名的一部分。</p>
+<p><code>@constructorOnly</code> 注解可以用于标记一个仅在构造函数中使用而不会作为字段保留的类参数。这有助于减少类的捕获集。如果一个参数仅用于初始化,后续不再访问,那么类就没有必要将其保留为一种 Capability。</p>
+<p>类的<strong>捕获引用</strong>包括从类外部使用的局部 Capability 以及具有捕获类型的构造函数参数(参数Capability)。局部Capability会被内部类继承。</p>
+<p>类实例的 <code>this</code> 的捕获集是根据捕获的引用、父类以及类内部的使用约束来推断的 1。这种自动推断机制在很多情况下减少了手动指定类捕获集的需要。</p>
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> caps.<span class="type">Capability</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileSystem</span> <span class="keyword">extends</span> <span class="title">Capability</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Logger</span>(<span class="params">using <span class="type">FileSystem</span></span>)</span>:</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">log</span></span>(s: <span class="type">String</span>): <span class="type">Unit</span> = ???</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span></span>(<span class="keyword">using</span> fs: <span class="type">FileSystem</span>) =</span><br><span class="line"> <span class="keyword">val</span> l: <span class="type">Logger</span>^&#123;fs&#125; = <span class="type">Logger</span>()</span><br><span class="line"> ...</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight scala"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Logger</span>(<span class="params">using <span class="type">FileSystem</span>^&#123;cap&#125;</span>)</span>:</span><br><span class="line"> ^^^^^^^^^^^^^^</span><br><span class="line"> redundant capture: <span class="type">FileSystem</span> already accounts <span class="keyword">for</span> cap</span><br></pre></td></tr></table></figure>
+
+
+<p><strong>捕获隧道 (Capture Tunnelling)</strong> 是指当一个类型变量被一个捕获类型实例化时,捕获信息不会立即传播到外层的泛型类型。相反,捕获会“穿过隧道”,并在类型变量被访问或其成员被使用时重新出现。这种机制有助于以更简洁和可管理的方式处理泛型代码中的捕获集,避免类型签名过于复杂。</p>
+<p><strong>逃逸检查</strong>施加了一些限制。作为类型变量实例的捕获类型不能携带通用Capability <code>cap</code> 。可变变量也不能拥有通用捕获集 。逃逸检查阻止了在参数化类型的参数中返回或分配带有局部 Capability 的闭包,因为这可能导致 Capability 逃逸其预期的作用域。<strong>单调性规则</strong>指出,在一个带有字段 <code>f</code> 的类中,<code>&#123;this&#125;</code> 覆盖了 <code>&#123;this.f&#125;</code> 以及 <code>this.f</code> 对纯参数的应用。这意味着如果类实例本身被视为一种 Capability,那么其字段所持有的任何 Capability 也会被隐式地覆盖。逃逸检查对于维护 Capability 跟踪的完整性至关重要,它可以防止 Capability 在其预期生命周期或作用域之外被使用,尤其是在泛型和可变状态的上下文中。</p>
+<p><strong>受检异常</strong>可以通过导入 <code>language.experimental.saferExceptions</code> 来启用。方法上的 <code>throws</code> 子句会扩展为一个隐式的 <code>CanThrow</code> Capability参数,表明该方法可能抛出指定类型的异常。<code>throw</code> 表达式需要 <code>CanThrow</code> Capability,而 <code>try</code> 表达式会创建这种Capability。在 <code>language.experimental.captureChecking</code> 下,由于逃逸的 Capability 而导致未处理异常的代码会被拒绝。为了实现这种集成,<code>CanThrow</code> 需要继承 <code>Capability</code>,并且需要将逃逸检查扩展到 <code>try</code> 表达式,以防止捕获 <code>cap</code>。Capture Checking 与受检异常的集成确保了异常的可能性也被作为一种 Capability 需求来跟踪,从而加强了语言的整体资源管理和错误处理 Capability。</p>
+<hr>
+<p>文档中提供了一个关于<strong>惰性列表</strong>(Lazy Lists)的较大示例,很好地展示了 Capture Checking 如何在更复杂的数据结构中工作。<code>LzyList</code> 的 <code>tail</code> 具有一个捕获注解,表明它可以捕获与列表相同的引用。诸如 <code>map</code>、<code>filter</code> 和 <code>concat</code> 等操作在惰性列表上能够正确地推断出捕获集,这取决于原始列表和所使用的函数。值得注意的是 effect polymorphism的概念,传递给这些操作的纯函数不会出现在结果的捕获集中。这与严格列表形成对比,严格列表通常不需要捕获注解,因为它们的副作用不会被延迟。惰性列表的例子具体说明了Capture Checking 如何应用于非平凡的数据结构,展示了其在涉及延迟求值的复杂场景中跟踪依赖关系的Capability。effect polymorphism 是一个显著的优点,它允许在不影响捕获集的情况下使用纯计算。</p>
+<hr>
+<p><strong>表 1: 代码示例与演示概念</strong></p>
+<table>
+<thead>
+<tr>
+<th></th>
+<th></th>
+<th></th>
+</tr>
+</thead>
+<tbody><tr>
+<td><strong>代码片段</strong></td>
+<td><strong>演示概念</strong></td>
+<td><strong>捕获行为解释</strong></td>
+</tr>
+<tr>
+<td><code>import language.experimental.captureChecking</code></td>
+<td>启用Capture Checking</td>
+<td>必须通过此导入才能使用Capture Checking特性。</td>
+</tr>
+<tr>
+<td><code>T^&#123;c₁, ..., cᵢ&#125;</code></td>
+<td>捕获类型的声明</td>
+<td>表示类型 <code>T</code> 的值可能依赖或访问Capability <code>c₁, ..., cᵢ</code>。</td>
+</tr>
+<tr>
+<td><code>A =&gt; B</code></td>
+<td>不纯函数类型</td>
+<td>函数可以捕获任意Capability,是 <code>A -&gt;&#123;cap&#125; B</code> 的别名。</td>
+</tr>
+<tr>
+<td><code>A -&gt; B</code></td>
+<td>纯函数类型</td>
+<td>函数不能捕获任何Capability。</td>
+</tr>
+<tr>
+<td><code>A -&gt;&#123;c, d&#125; B</code></td>
+<td>指定捕获Capability的函数类型</td>
+<td>函数只能捕获Capability <code>c</code> 和 <code>d</code>。</td>
+</tr>
+<tr>
+<td><code>=&gt; Int</code></td>
+<td>允许任意Capability引用的命名参数类型</td>
+<td>类似于不纯函数类型。</td>
+</tr>
+<tr>
+<td><code>-&gt; Int</code></td>
+<td>禁止任何Capability引用的命名参数类型</td>
+<td>类似于纯函数类型。</td>
+</tr>
+<tr>
+<td><code>-&gt;&#123;c&#125; Int</code></td>
+<td>只允许特定Capability引用的命名参数类型</td>
+<td>只允许引用Capability <code>c</code>。</td>
+</tr>
+<tr>
+<td><code>class C extends caps.Capability</code></td>
+<td>Capability类的定义</td>
+<td>类 <code>C</code> 的实例本身代表一种Capability,具有隐式的 <code>&#123;cap&#125;</code> 捕获集。</td>
+</tr>
+<tr>
+<td><code>@constructorOnly val p: Int</code></td>
+<td>构造函数专用参数</td>
+<td>参数 <code>p</code> 仅在构造函数中使用,不会作为类的字段保留,有助于减少类的捕获集。</td>
+</tr>
+<tr>
+<td><code>() -&gt; Iterator^</code></td>
+<td>具有存在性Capability的函数结果类型</td>
+<td>返回一个迭代器,该迭代器可能捕获某种Capability,但具体是哪种Capability在编译时未知。</td>
+</tr>
+<tr>
+<td><code>ops*</code></td>
+<td>可达Capability</td>
+<td>表示通过Capability <code>ops</code> 可访问的任何协变出现的Capability。</td>
+</tr>
+<tr>
+<td><code>type Source[X^] = ...</code></td>
+<td>使用Capability多态的类型定义</td>
+<td>类型 <code>Source</code> 被参数化为可以持有Capability集 <code>X^</code>。</td>
+</tr>
+</tbody></table>
+<p>当 <code>cap</code> 出现在函数的结果类型中时,通常表示一个由存在性量词绑定的未知类型(例如,<code>() -&gt; Iterator^</code> 意味着 <code>() -&gt; Exists x. Iterator^x</code>)。这表明返回的迭代器可能捕获了某种 Capability,但具体的哪种 Capability 在静态类型检查时是未知的。在内部,这种存在性 Capability 使用带有 sealed trait <code>Exists</code> 的依赖函数类型来表示 。结果类型中协变的 <code>cap</code> 会被替换为一个新的 existential variable。当应用一个具有 existential result 类型 <code>Exists ex.T</code> 的函数时,结果是 <code>T</code>,其中 <code>ex</code> 被 <code>cap</code> 替换。Existential Capability 允许类型系统表达在编译时具体捕获的 Capability 未知的情况,从而提供了灵活性,同时仍然保持了一定程度的跟踪。</p>
+<p>**Reach Capability **用于表达一个变量引用了通过另一个Capability“Reach”的任何操作。例如,如果 <code>ops</code> 是一个表示一组操作的Capability,那么 <code>ops*</code> 就表示出现在 <code>ops</code> 类型中且通过 <code>ops</code> 访问的任何协变 Capability。Reach Capability 提供了一种间接推理和跟踪 Capability 的方式,这对于建模具有相互连接资源的复杂系统非常有用。</p>
+<p><strong>Capability 多态</strong>允许使用带有上界 <code>CapSet</code> 的类型变量来参数化操作的捕获集。这使得定义诸如 <code>Source[X^]</code> 这样的类型成为可能,其中 <code>X^</code> 表示监听器可以持有的一组 Capability。Capability 多态增强了代码的表达性和可重用性,因为它允许函数和数据结构在它们可能依赖的 Capability 集上进行参数化。</p>
+<hr>
+<p>Scala 3 提供了几个与 Capture Checking 相关的编译选项,。<code>-Xprint:cc</code> 选项会打印出带有推断捕获类型的程序代码 1。这对于理解编译器是如何推断捕获集的以及调试与类型相关的错误非常有用。另一个选项是 <code>-Ycc-debug</code>,它提供了关于 Capture Checking 过程的详细的、面向实现的的信息。这个选项对于需要深入了解 Capture Checking 器工作原理或者遇到复杂问题的开发者来说很有帮助。这些编译选项是使用 Capture Checking 的开发者的重要工具,它们允许开发者检查编译器的推理并诊断问题。</p>
+<p>Capture Checking被实现为一个传播约束求解器,它在标准的类型检查阶段之后运行,未知的捕获集由约束变量表示。在类型中显式编写的捕获集被求解器视为常量。类型之间的子类型要求会转化为它们各自捕获集上的子捕获测试。求解器根据程序的结构和类型约束,将 Capability 传播给约束变量及其超集。捕获集的映射受到类型参数的变性(协变、逆变、不变)的影响。<strong>装箱</strong>(boxing)和<strong>拆箱</strong>(unboxing)是用于隐藏和恢复捕获集的虚拟操作,特别是在类型参数的上下文中用于管理捕获隧道。<code>-Ycc-debug</code> 的输出提供了关于变量依赖关系和Capture Checking器在编译过程中的状态的深入信息。</p>
+]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
<title>TDD 和 DDD 的一些小想法</title>
<url>/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/</url>
<content><![CDATA[<p>Test-Driven Development (TDD) 和 Domain-Driven Design (DDD) 是两种不同的软件开发方法论,各自有其独特的优缺点和应用场景。</p>
@@ -2414,18 +2575,6 @@
</categories>
</entry>
<entry>
- <title>二〇二五年二月二十四日</title>
- <url>/2025/02/24/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/</url>
- <content><![CDATA[<p>街上的人躲进建筑,道路上的车变得缓慢。路边的黑猫坐在屋檐下张望,在雨天,它也有了思考的地方与时间。除了淅淅沥沥的雨声再无其他。</p>
-<p>衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。</p>
-<p>家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。</p>
-<p>这雨天,世界都温柔的可以掐出水来。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>二〇二四年一月二十三日</title>
<url>/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/</url>
<content><![CDATA[<p>有人在桥上并肩走过,孩子们举着风车大笑着跑开,热乎乎的米糕新鲜出炉,香气混着夜风传去老远。</p>
@@ -2456,6 +2605,18 @@
</categories>
</entry>
<entry>
+ <title>二〇二五年二月二十四日</title>
+ <url>/2025/02/24/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/</url>
+ <content><![CDATA[<p>街上的人躲进建筑,道路上的车变得缓慢。路边的黑猫坐在屋檐下张望,在雨天,它也有了思考的地方与时间。除了淅淅沥沥的雨声再无其他。</p>
+<p>衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。</p>
+<p>家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。</p>
+<p>这雨天,世界都温柔的可以掐出水来。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二〇二四年三月二十二日</title>
<url>/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/</url>
<content><![CDATA[<p>毛毛在人群中牵着我,却很难融入人群,我在林中面对着毛毛,树木的思想却千姿百态地向我涌来。<br>它说,它要将灵魂撕裂,让它暴露在最灼热的阳光下灼烧,要让风刺进来,硬生生扯开一道口子,要让原有的赤色消失殆尽,只留下一堆松散的灰色颗粒,任雨打浮萍。</p>
@@ -2526,6 +2687,26 @@
</categories>
</entry>
<entry>
+ <title>二〇二四年五月十六日</title>
+ <url>/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/</url>
+ <content><![CDATA[<p>无眼耳鼻舌身意,无色声香味触法,四下皆空,但万物有实,活在真实世界,而非活在一系列参照物之中。</p>
+<p>不要有所谓自信或自卑的概念。要意识到,心态这玩意本质就是从比较中产生的,镜花水月般的东西,毫无力量可言。</p>
+<p>人若把自己的心态放置在客观事实和规律前面,无可避免就会产生内耗。而现代人这一生绝大多数的痛苦,都是内耗所带来的。</p>
+<p>多尝试点事情吧,试得越多,就能越快判断出自己是不是这块料。如果是,很好;如果不是,过,下一个。在这期间不要有任何心态波澜,行就是行,不行就是不行。反正不是非行不可。</p>
+<p>人自信不是样样精通、事事皆成,凡事都做得比别人更好;自信是一个高级陷阱,仰赖自信的人终有一日会崩塌于自信的毁灭。</p>
+<p>用生命力来取代往日的自信心,用绝对强大的权力意志来取代往日相对成功的小胜小利。</p>
+<p>不放弃的理由不是因为自信,而是因为知道这事必须得干&#x2F;行得通;放弃的理由也不是因为不自信,而是因为知道这事不能去干&#x2F;行不通。</p>
+<p>而一旦在理性和感性层面都认为必须办成某件事,那就不顾一切去办成。哪怕绕再多的路,要办的事就是要办。</p>
+<p>当不再局限于自信或自卑,而是立足于实事求是去布局和行动,一切都会变得更加清晰明了。若想成事,首先要花时间去搞明白自己的长处与短板,然后学会在面对具体事项之际快速判断自己行不行、是不是非做不可、要做的话又有几分把握、失败了要如何应对、要不要改变其中某些变量再多试几次。</p>
+<p>当有了一个目标,需要的不是豪言壮志,不是任何心理建设,而是尽快上手去做。<br>做一件事,无关心态,只要去做就是了。发挥最大的主观能动性,遇到问题就解决,碰到障碍就破开,需要帮助就求助。别因为所谓的自信就盲目冒进,也别因为所谓的自卑就胆小退缩,那俩玩意都不存在。</p>
+<p>尊重事情本身的客观发展规律,什么样的人匹配什么样的事,什么样的条件匹配什么样的理想。别把心态想得太重要,更别花太多时间精力去建设心态,客观规律不会因为心态就发生奇迹般地转变。</p>
+<p>你最好趁早学会尊重客观规律。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二〇二四年八月一日</title>
<url>/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/</url>
<content><![CDATA[<p>阿公烧烟成老瘾,<br>阿公饮酒会面红,<br>他说日子要开心,<br>他说人生要尽兴。</p>
@@ -2554,26 +2735,6 @@
</categories>
</entry>
<entry>
- <title>二〇二四年五月十六日</title>
- <url>/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/</url>
- <content><![CDATA[<p>无眼耳鼻舌身意,无色声香味触法,四下皆空,但万物有实,活在真实世界,而非活在一系列参照物之中。</p>
-<p>不要有所谓自信或自卑的概念。要意识到,心态这玩意本质就是从比较中产生的,镜花水月般的东西,毫无力量可言。</p>
-<p>人若把自己的心态放置在客观事实和规律前面,无可避免就会产生内耗。而现代人这一生绝大多数的痛苦,都是内耗所带来的。</p>
-<p>多尝试点事情吧,试得越多,就能越快判断出自己是不是这块料。如果是,很好;如果不是,过,下一个。在这期间不要有任何心态波澜,行就是行,不行就是不行。反正不是非行不可。</p>
-<p>人自信不是样样精通、事事皆成,凡事都做得比别人更好;自信是一个高级陷阱,仰赖自信的人终有一日会崩塌于自信的毁灭。</p>
-<p>用生命力来取代往日的自信心,用绝对强大的权力意志来取代往日相对成功的小胜小利。</p>
-<p>不放弃的理由不是因为自信,而是因为知道这事必须得干&#x2F;行得通;放弃的理由也不是因为不自信,而是因为知道这事不能去干&#x2F;行不通。</p>
-<p>而一旦在理性和感性层面都认为必须办成某件事,那就不顾一切去办成。哪怕绕再多的路,要办的事就是要办。</p>
-<p>当不再局限于自信或自卑,而是立足于实事求是去布局和行动,一切都会变得更加清晰明了。若想成事,首先要花时间去搞明白自己的长处与短板,然后学会在面对具体事项之际快速判断自己行不行、是不是非做不可、要做的话又有几分把握、失败了要如何应对、要不要改变其中某些变量再多试几次。</p>
-<p>当有了一个目标,需要的不是豪言壮志,不是任何心理建设,而是尽快上手去做。<br>做一件事,无关心态,只要去做就是了。发挥最大的主观能动性,遇到问题就解决,碰到障碍就破开,需要帮助就求助。别因为所谓的自信就盲目冒进,也别因为所谓的自卑就胆小退缩,那俩玩意都不存在。</p>
-<p>尊重事情本身的客观发展规律,什么样的人匹配什么样的事,什么样的条件匹配什么样的理想。别把心态想得太重要,更别花太多时间精力去建设心态,客观规律不会因为心态就发生奇迹般地转变。</p>
-<p>你最好趁早学会尊重客观规律。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>二〇二四年十一月十七日</title>
<url>/2024/11/17/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%8D%81%E4%B8%83%E6%97%A5/</url>
<content><![CDATA[<p>快乐是正面情绪的原型,人类的所作所为,最终都是为了追求快乐。我们之所以想追求财富、健康或名声,都是为了借此得到快乐。然而,追求快乐也不是因为它可以带给我们其他好处,因为快乐本身就是目的。</p>
diff --git a/tags/Technique/index.html b/tags/Technique/index.html
index ba7d1977..0f731a94 100644
--- a/tags/Technique/index.html
+++ b/tags/Technique/index.html
@@ -152,6 +152,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/03/25/Scala-3-Capture-Checking/">
+
+ Scala 3 (Capture Checking)
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 25, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/03/20/TDD-%E5%92%8C-DDD-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%83%B3%E6%B3%95/">
TDD 和 DDD 的一些小想法
@@ -309,30 +327,12 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/10/18/10-Tips-for-Productive-FSharp-Scripting/">
-
- 10 Tips for Productive FSharp Scripting
-
- </a>
- </div>
-
- <span class="post-date">Oct 18, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <span class="page-number current">1</span><a class="page-number" href="/tags/Technique/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/4/">4</a>
+ <span class="page-number current">1</span><a class="page-number" href="/tags/Technique/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/5/">5</a>
</nav>
</div>
diff --git a/tags/Technique/page/2/index.html b/tags/Technique/page/2/index.html
index e54f7186..360b9eb6 100644
--- a/tags/Technique/page/2/index.html
+++ b/tags/Technique/page/2/index.html
@@ -152,6 +152,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/10/18/10-Tips-for-Productive-FSharp-Scripting/">
+
+ 10 Tips for Productive FSharp Scripting
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 18, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/10/18/Building-custom-fibers-library-in-FSharp/">
Building custom fibers library in FSharp
@@ -307,30 +325,12 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
-
- .NET AOT 下的 F# 命令行参数解析库选择
-
- </a>
- </div>
-
- <span class="post-date">Jun 6, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/tags/Technique/">1</a><span class="page-number current">2</span><a class="page-number" href="/tags/Technique/page/3/">3</a><a class="page-number" href="/tags/Technique/page/4/">4</a>
+ <a class="page-number" href="/tags/Technique/">1</a><span class="page-number current">2</span><a class="page-number" href="/tags/Technique/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/5/">5</a>
</nav>
</div>
diff --git a/tags/Technique/page/3/index.html b/tags/Technique/page/3/index.html
index f44a3921..fa4c1429 100644
--- a/tags/Technique/page/3/index.html
+++ b/tags/Technique/page/3/index.html
@@ -152,6 +152,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
+
+ .NET AOT 下的 F# 命令行参数解析库选择
+
+ </a>
+ </div>
+
+ <span class="post-date">Jun 6, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/05/20/Rescript-genType-import-%E9%97%AE%E9%A2%98/">
Rescript @genType import 问题
@@ -309,30 +327,12 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
-
- A Brief History of Just-In-Time
-
- </a>
- </div>
-
- <span class="post-date">Sep 28, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/tags/Technique/">1</a><a class="page-number" href="/tags/Technique/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/tags/Technique/page/4/">4</a>
+ <a class="page-number" href="/tags/Technique/">1</a><a class="page-number" href="/tags/Technique/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/tags/Technique/page/4/">4</a><a class="page-number" href="/tags/Technique/page/5/">5</a>
</nav>
</div>
diff --git a/tags/Technique/page/4/index.html b/tags/Technique/page/4/index.html
index c8e77b8e..b393777e 100644
--- a/tags/Technique/page/4/index.html
+++ b/tags/Technique/page/4/index.html
@@ -152,6 +152,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
+
+ A Brief History of Just-In-Time
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 28, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/08/15/tick-thread%E5%9C%A8Multicore-OCaml%E4%B8%AD%E7%9A%84%E4%BD%9C%E7%94%A8/">
tick thread在Multicore OCaml中的作用
@@ -307,30 +325,12 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/">
-
- TypeScript With Rust Errors, No Try Catch, Heresy
-
- </a>
- </div>
-
- <span class="post-date">Apr 30, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/tags/Technique/">1</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/3/">3</a><span class="page-number current">4</span>
+ <a class="page-number" href="/tags/Technique/">1</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/tags/Technique/page/5/">5</a>
</nav>
</div>
diff --git a/tags/Technique/page/5/index.html b/tags/Technique/page/5/index.html
new file mode 100644
index 00000000..4253f067
--- /dev/null
+++ b/tags/Technique/page/5/index.html
@@ -0,0 +1,236 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>Tag: Technique | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.alicdn.com/polyfill.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+<script src="/js/menu.js"></script>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <div id="tag">
+
+
+ <p class="tag-title">
+ / <a href="/tag/">tags</a>
+ / <a href="">Technique</a> /
+ </p>
+ <div class="post-list">
+
+
+
+
+
+
+ <div class="year-title">2023</div>
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/">
+
+ TypeScript With Rust Errors, No Try Catch, Heresy
+
+ </a>
+ </div>
+
+ <span class="post-date">Apr 30, 2023</span>
+ </div>
+
+
+ <div id="paginator">
+
+ <div class=paginator>
+ <div class="h-line-primary"></div>
+ <nav class="pagination">
+ <a class="page-number" href="/tags/Technique/">1</a><span class="space">&hellip;</span><a class="page-number" href="/tags/Technique/page/4/">4</a><span class="page-number current">5</span>
+ </nav>
+ </div>
+
+ </div>
+</div>
+
+
+
+
+</div>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>