<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>whyself blog</title>
  <link>https://blog.whyself.cn/</link>
  <description>Recent posts from whyself blog</description>
  <language>zh-CN</language>
  <lastBuildDate>Sun, 05 Jul 2026 04:13:41 GMT</lastBuildDate>
  <atom:link href="https://blog.whyself.cn/rss.xml" rel="self" type="application/rss+xml" xmlns:atom="http://www.w3.org/2005/Atom" />
<item>
  <title>用 LambdaiCJ 迁移 gcoord</title>
  <link>https://blog.whyself.cn/posts/migrate-gcoord-to-lambdaicj/</link>
  <guid>https://blog.whyself.cn/posts/migrate-gcoord-to-lambdaicj/</guid>
  <description>记录把 gcoord 坐标转换库迁移到仓颉的过程：从目录拆分、公开入口，到 GeoJSON 支持和测试补齐。</description>
  <content:encoded><![CDATA[<p>最近试着用 LambdaiCJ 做了一个 <code>gcoord</code> 的仓颉版。</p>
<p><code>gcoord</code> 是一个地理坐标系转换库，原版由 TypeScript 实现，支持 WGS84、GCJ02、BD09、BD09MC、EPSG3857 等常见坐标系之间的转换。我的目标不是重新设计它，而是尽量按照原项目的结构和测试思路，把核心能力迁移到仓颉里。</p>
<h2>参考的 TypeScript 项目结构</h2>
<p>原仓库真正需要关注的是 <code>src/</code> 和 <code>test/</code>。</p>
<pre><code class="language-text">gcoord/
├─ src/
│  ├─ index.ts                  # JS/TS 对外入口
│  ├─ transform.ts              # 统一转换 API
│  ├─ helper.ts                 # 工具函数 + GeoJSON 坐标遍历
│  ├─ geojson.ts                # GeoJSON 类型定义
│  └─ crs/                      # 各坐标系转换公式
│     ├─ index.ts               # CRS 枚举、别名、转换路由表
│     ├─ GCJ02.ts               # WGS84 &#x3C;-> GCJ02
│     ├─ BD09.ts                # GCJ02 &#x3C;-> BD09
│     ├─ BD09MC.ts              # BD09 &#x3C;-> BD09MC
│     ├─ EPSG3857.ts            # WGS84 &#x3C;-> EPSG3857/WebMercator
│     └─ WGS84.ts               # 空壳注释文件
│
├─ test/
│  ├─ fixtures/
│  │  ├─ china-cities.json      # 坐标样本数据
│  │  └─ each.ts                # 测试读取 fixture 的辅助函数
│  ├─ helpers/
│  │  └─ geojson.ts             # 构造 GeoJSON 的辅助函数
│  └─ unit/
│     ├─ transform.spec.ts      # transform 总入口测试
│     ├─ helper.spec.ts         # helper / coordEach 测试
│     └─ crs/                   # 各 CRS 转换测试
</code></pre>
<p>其中 <code>transform.ts</code> 是核心入口。</p>
<pre><code class="language-typescript">export default function transform&#x3C;T extends GeoJSON | Position>(
  input: T | string,
  crsFrom: CRSTypes,
  crsTo: CRSTypes
): T
</code></pre>
<p>它大致支持三类输入：</p>
<ul>
<li>普通坐标数组：<code>[lng, lat]</code></li>
<li>GeoJSON 对象</li>
<li>GeoJSON 字符串</li>
</ul>
<p>处理流程也很直接：先检查输入和坐标系是否合法，如果 <code>from == to</code> 就原样返回；否则从 <code>crsMap</code> 里找到对应的转换函数。输入是字符串时先 <code>JSON.parse</code>，输入是坐标数组时直接转换，输入是 GeoJSON 时则遍历所有坐标并原地修改。</p>
<h2>第一阶段：先迁移坐标数组</h2>
<p>一开始我没有直接做完整 GeoJSON 支持，而是先把坐标数组的转换跑通。第一版目录大概是这样：</p>
<pre><code class="language-text">gcoord_cj/
├─ cjpm.toml                    # 仓颉项目配置
├─ README.md                    # 使用说明
├─ CHANGELOG.md                 # 版本变更记录
├─ LICENSE                      # 开源许可证
├─ src/
│  ├─ transform.cj              # 对外 transform API
│  ├─ helper/
│  │  └─ helper.cj              # 断言、函数组合、数值辅助等
│  ├─ geojson/
│  │  └─ geojson.cj             # 第一阶段只定义 Position
│  └─ crs/
│     ├─ index.cj               # CRSType 与转换路由
│     ├─ gcj02.cj
│     ├─ bd09.cj
│     ├─ bd09mc.cj
│     ├─ epsg3857.cj
│     └─ wgs84.cj
├─ test/
│  └─ china-cities.json         # 从原项目保留的坐标样本数据
└─ scripts/
   └─ smoke_test.sh             # 快速构建或手动冒烟验证脚本
</code></pre>
<p>这里踩到的第一个点是：仓颉项目并不一定需要 <code>index.cj</code> 作为唯一入口文件，而是可以直接根据包路径暴露能力。所以我最后把 <code>transform.cj</code> 作为主要入口。</p>
<p>当时设计的暴露边界是：</p>
<ul>
<li><code>public</code>：<code>transform()</code>、<code>Position</code>、<code>CRSType</code></li>
<li><code>protected</code>：<code>getConverter()</code>、各 CRS 公式函数、<code>helper</code> 里的 <code>TransformFn</code> / <code>assert</code> / <code>compose</code></li>
</ul>
<p>根包里的 <code>transform.cj</code> 负责转发 <code>gcoord.geojson.*</code> 和 <code>gcoord.crs.*</code>，同时内部调用 <code>gcoord.crs.getConverter</code> 做路由。这样外部用户仍然只需要：</p>
<pre><code class="language-text">import gcoord.*
</code></pre>
<p>另外，仓颉库项目需要把 <code>cjpm.toml</code> 里的输出类型从可执行程序改成静态库：</p>
<pre><code class="language-toml">[package]
output-type = "static"
</code></pre>
<p>其他项目使用时再通过本地路径依赖引入：</p>
<pre><code class="language-toml">[dependencies]
gcoord = { path = "../gcoord_cj" }
</code></pre>
<p>第一轮迁移后，几个核心模块基本成型：</p>
<ul>
<li><code>transform.cj</code>：完成 <code>transform()</code> 的迁移，通过重载支持 <code>GeoPosition</code> 和字符串输入，暂时不处理完整 GeoJSON 对象</li>
<li><code>helper/helper.cj</code>：按 TypeScript 原实现迁移 <code>assert()</code>、<code>compose()</code> 等工具函数</li>
<li><code>geojson/geojson.cj</code>：先定义 <code>GeoPosition</code> 类型</li>
<li><code>crs/index.cj</code>：把枚举换成 <code>String</code> 类型的 <code>CRSType</code>，定义坐标系常量、别名和双层 HashMap 转换路由表</li>
</ul>
<h2>关于 Position 重名</h2>
<p>迁移过程中还遇到过一次看起来像导入机制的问题。</p>
<p>我一开始以为，同 package 下在多个文件里 import 同一个 <code>Position</code> 类型，会在函数顶级签名里造成重复导入。后来发现真实原因不是这个，而是 <code>import lambdai4cj.prelude.*</code> 里也有一个叫 <code>Position</code> 的类型，导致了重名。</p>
<p>最后的解决方式很简单：把自己的坐标类型改名为 <code>GeoPosition</code>。</p>
<h2>用 LambdaiCJ 迁移计算函数</h2>
<p>坐标转换里最适合交给 AI 的部分，其实是纯运算函数。</p>
<p>我的做法是先把常量和函数依赖关系整理好，再让 <code>@ai</code> 模块参照原 TypeScript 文件生成仓颉代码：<code>@files</code> 里放源码文件，<code>@AIDeps</code> 描述原函数调用关系，再从 <code>china-cities.json</code> 中挑几个样本作为 <code>@test</code>。</p>
<p>这类任务涉及的仓颉语言特性不算多，更多是公式和数值误差控制，所以成功率比预期高。真正需要人工盯住的地方，反而是项目边界、包结构、公开入口和测试组织。</p>
<h2>第二阶段：补上 GeoJSON 支持</h2>
<p>后来我开始继续加 GeoJSON 支持。</p>
<p>最初的想法是照搬 TypeScript 的类型检查，但很快发现这条路不太顺。仓颉没有 TypeScript 那种根据返回值类型参与推断函数重载的写法，强行模仿原版的类型结构只会把代码变复杂。</p>
<p>找到仓颉 <code>stdx</code> 里的 JSON 支持后，我换了一个方案：不再强行还原 TS 类型系统，而是直接对 <code>JsonValue</code> 递归遍历。遇到坐标数组就转换，其他结构原样保留。</p>
<p>这样会少一些静态类型约束，但代码干净很多，也更符合这个阶段的目标：先让任意 GeoJSON 对象能完成坐标转换。</p>
<p>整理后的 <code>transform.cj</code> 入口变成了这样：</p>
<pre><code class="language-text">public func transform&#x3C;T>(input: Array&#x3C;T>, crsFrom: CRSType, crsTo: CRSType): Array&#x3C;Float64> where T &#x3C;: ToString {
    return transformArrayPosition(input, crsFrom, crsTo)
}

public func transform(input: String, crsFrom: CRSType, crsTo: CRSType): Any {
    let value = JsonValue.fromStr(input)
    match (value.kind()) {
        case JsArray =>
            return transformJsonPosition(value.asArray(), crsFrom, crsTo)
        case JsObject =>
            transformJsonGeoJSONInPlace(value.asObject(), crsFrom, crsTo)
            return value
        case _ =>
            throw IllegalArgumentException("Invalid input coordinate: ${input}")
    }
}

public func transform(input: JsonValue, crsFrom: CRSType, crsTo: CRSType): JsonValue {
    match (input.kind()) {
        case JsArray =>
            let output = transformJsonPosition(input.asArray(), crsFrom, crsTo)
            return JsonArray(output.map&#x3C;JsonValue>({ value => JsonFloat(value) }))
        case JsObject =>
            transformJsonGeoJSONInPlace(input.asObject(), crsFrom, crsTo)
            return input
        case _ =>
            throw IllegalArgumentException("Invalid input coordinate: ${input}")
    }
}
</code></pre>
<p>这时目录结构也随之调整：</p>
<pre><code class="language-text">gcoord_cj/src/
├─ transform.cj
│  └─ 只放公开 transform 重载，负责分派 Array / String / JsonValue 输入
│
├─ coord/
│  └─ position.cj
│     ├─ GeoPosition
│     ├─ Array&#x3C;T> -> GeoPosition
│     ├─ JsonArray -> Array&#x3C;Float64>
│     └─ JsonArray 坐标写回工具
│
├─ geojson/
│  └─ json_transform.cj
│     ├─ JsonValue / JsonObject GeoJSON 原地转换逻辑
│     ├─ Feature / FeatureCollection
│     ├─ Point / LineString / Polygon
│     ├─ MultiPoint / MultiLineString / MultiPolygon
│     └─ GeometryCollection
│
├─ crs/
│  ├─ index.cj
│  │  ├─ CRSType 常量和别名
│  │  ├─ CRS 转换矩阵
│  │  ├─ assertCRS()
│  │  └─ getTransformFn()
│  ├─ wgs84.cj
│  ├─ gcj02.cj
│  ├─ bd09.cj
│  ├─ bd09mc.cj
│  └─ epsg3857.cj
│
└─ helper/
   └─ helper.cj
      └─ assert / compose 等通用工具
</code></pre>
<p>公开给用户使用的入口仍然只保留 <code>transform</code>。</p>
<h2>测试与收尾</h2>
<p>最后让 GPT 根据 <code>gcoord/test/</code> 里的测试思路补了一个 shell 测试脚本。这个脚本还真测出了一个问题：仓颉的 <code>toString()</code> 在某些数值转换场景下会带来精度丢失。</p>
<p>后来加了一个兼容函数 <code>toFloat64()</code>，问题就解决了。</p>
<p>这次迁移下来，我对 LambdaiCJ 的感觉是：它很适合帮忙迁移纯运算函数，尤其是已有源码、调用关系和测试样本都比较明确的时候。但包结构、公开 API、依赖边界、测试策略这些东西，还是需要人站在项目层面盯着。</p>
<p>换句话说，AI 可以很快把“代码块”写出来，但一个库能不能真的像库一样被别人使用，仍然取决于你有没有把入口、边界和验证方式想清楚。</p>]]></content:encoded>
  <pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Cangjie01-环境配置</title>
  <link>https://blog.whyself.cn/posts/cangjie01-环境配置/</link>
  <guid>https://blog.whyself.cn/posts/cangjie01-环境配置/</guid>
  <description>记录在 Ubuntu 24.04 上安装仓颉工具链、配置 VS Code 插件，以及让仓颉项目获得完整补全的过程。</description>
  <content:encoded><![CDATA[<p>我努力在学习 Cangjie 语言的时候弥补我的 Linux 命令行知识以及编程语言基础知识……</p>
<h1>安装工具链</h1>
<p>我使用的是 Ubuntu24.04 需要安装以下依赖：</p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y binutils libc6-dev libc++-dev gcc g++ libstdc++6 openssl libssl3t64
</code></pre>
<p>完成之后，我去官网下载了 Cangjie 1.1.0-beta.25</p>
<p>下载之后一般可以解压到 <code>/home/&#x3C;user_name>/opt</code></p>
<pre><code class="language-bash">mkdir -p ~/opt
cd ~/opt
tar xvf ~/Downloads/cangjie-sdk-linux-x64-*.tar.gz
</code></pre>
<p>当然如果你想像我装到 <code>/opt</code> 的系统级目录里用 <code>sudo</code> 搞来搞去也可以（）</p>
<p>启动环境配置脚本，输出版本号就安装好了</p>
<pre><code class="language-bash">source ~/opt/cangjie/envsetup.sh
cjc -v
cjpm -v
</code></pre>
<p>要让以后每次开终端都自动生效，把这一行加到 ~/.bashrc 最后，然后立即重新读取并执行 Bash 配置文件：</p>
<pre><code class="language-bash">echo 'source ~/opt/cangjie/envsetup.sh' >> ~/.bashrc
source ~/.bashrc
</code></pre>
<p>然后在 vscode 里新装一下官方的插件：</p>
<p><img src="/images/posts/cangjie-environment/extension.png" alt="VS Code 中的仓颉扩展"></p>
<p>顺便在 vscode settings.json (/home/why/.config/Code/User/settings.json) 里补上：</p>
<pre><code class="language-json">"CangjieSdk.Option": "CJNative",
"CangjieSdkPath.CJNativeBackend": "~/opt/cangjie"
</code></pre>
<p>给插件调用</p>
<h1>配置项目启动完整补全</h1>
<p>写完代码了发现仓颉只有一些关键字补全，然后才知道，不是仓颉项目文件没有完整的补全，于是大刀阔斧改了项目结构</p>
<pre><code>leetcode_cj/
|-- .gitignore
|-- cjpm.toml // 项目配置文件
|-- cjpm.lock // 依赖锁定文件
|-- README.md
|-- src/
|   |-- main.cj // 项目主入口负责启动各个代码
|   |-- hello.cj
|   |-- addTwoNumbers/
|   |   `-- Solution.cj
|   |-- twoSum/
|   |   `-- Solution.cj
|   `-- twoSumHash/
|       `-- Solution.cj
|-- notes/ // 笔记
|   |-- CJLearning01.md
|   |-- extension.png
|-- skill/ // 本地仓颉文档 skill
|   `-- cangjielearning/
|       `-- SKILL.md
</code></pre>
<p>对于 main.cj：</p>
<pre><code>package leetcode_cj

import leetcode_cj.twoSum
import leetcode_cj.twoSumHash

main(): Int64 {
    printHello()

    let nums = [2, 7, 11, 15]
    let target = 9

    let brute = twoSum.Solution()
    let hash = twoSumHash.Solution()
    println(brute.twoSum(nums, target))
    println(hash.twoSum(nums, target))
    return 0
}
</code></pre>
<p><code>package xxx</code> 与项目文件 <code>cjpm.toml</code> 里的名字保持一致，类似于 C 语言的 <code>namespace</code>，是该项目的 root 包名</p>
<p>对于题目子包里的 <code>Solution.cj</code>：</p>
<pre><code>package leetcode_cj.twoSumHash

import std.collection.*

public class Solution {
    public func twoSum(nums: Array&#x3C;Int64>, target: Int64): Array&#x3C;Int64> {
        let len = nums.size
        var mp = HashMap&#x3C;Int64, Int64>()
        
        if (len &#x3C; 2) {
            return []
        }
        for (i in 0..len) {
            if (mp.contains(target - nums[i])) {
                return [mp[target - nums[i]], i]
            }
            mp[nums[i]] = i
        }
        return []
    }
}
</code></pre>
<p><code>public</code> 声明让外部 <code>main.cj</code> 可以调用，具体来说：</p>
<ul>
<li>private：仅类型/当前定义内部可见</li>
<li>internal（默认）：当前包及子包可见</li>
<li>protected：当前模块可见（并有继承相关规则）</li>
<li>public：模块内外都可见</li>
</ul>]]></content:encoded>
  <pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>玄武湖旁的柳树</title>
  <link>https://blog.whyself.cn/posts/玄武湖旁的柳树/</link>
  <guid>https://blog.whyself.cn/posts/玄武湖旁的柳树/</guid>
  <description>所以你问我，玄武湖旁的柳树可真被裁剪过？</description>
  <content:encoded><![CDATA[<p>清明之际，花开烂漫，蜂飞花瓣绿叶之间，这是玄武湖的景，难得的景。玄武湖处处都是景，但唯有举起手机，向上探望，才能捕捉到这么纯的景。</p>
<p>那在这景之外又是什么呢？自然是人声鼎沸、摩肩接踵，人被人流往前驱赶，不知何时，不知为何，驻足在这棵花树下。</p>
<p>一路走来，人们总是在赏景，我们尝试望风景，却总少不了拥人景。好在，这人景除了人，还有景。老爷爷老奶奶围坐在凉亭底下，年轻人围站在他们周围，看着听着，排练一遍又一遍的《送你一朵小红花》；人流旁支起的桌子，几位老大爷攥着一手扑克打得津津有味；迎面跑来的，是穿着便装的退休老人，向前跑去的，是穿戴整齐的职业跑者。</p>]]></content:encoded>
  <pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>个人博客搭建记</title>
  <link>https://blog.whyself.cn/posts/个人博客搭建记/</link>
  <guid>https://blog.whyself.cn/posts/个人博客搭建记/</guid>
  <description>零代码构建完全自定义个人博客的全过程记录</description>
  <content:encoded><![CDATA[<h1>前言</h1>
<p>发现自己整整一周没有写文档了，于是决定在这周结束前，将自己这一周主要干的事，没错，就是又尝试了一遍从零自建博客，花点时间记录下来</p>
<p>建博客的初衷就是希望自己能多看看书、看看影视作品，也多写一些文档，沉淀一些知识</p>
<p>虽然自建博客的大部分时间都花在 ui 设计，以及博客页面逻辑的设计上，但与之相反，这篇文章应该会更注重如何部署以及优选的一些配置上，正好能补充自己在这方面匮乏的知识</p>
<p><strong>当然，这次搭建也有鲜明的时代性：重前端的应用目前已经可以不写代码做到很好了，偶尔几个点可能懂一点前端布局会快一点</strong></p>
<p>所以这次依旧是零代码搭建，很符合大 vibe 时代的特征了</p>
<h1>技术栈的选择</h1>
<ul>
<li><a href="https://stitch.withgoogle.com/">stitch</a> 设计前端大概的 ui</li>
<li><a href="https://astro.build/">astro</a> 作为博客引擎</li>
<li>codex <del>作为 vibe 工具</del></li>
<li><del>netlify</del>  <a href="https://vercel.com/">vercel</a> 做博客托管 （netlify 额度也太少了一天就搞完了）</li>
<li><a href="https://github.com/xingpingcn/enhanced-FaaS-in-China">IP 优选</a> 提升了访问速度</li>
</ul>
<h1>UI 设计</h1>
<h2>stitch</h2>
<blockquote>
<p>我想要一个简约黑白风格可以切换暗黑和亮色风格的博客，模仿微信布局，最顶上是横着的大图片，图片下方左侧是我的头像，个性签名，github账号，About，在下方就是各种文章栏目，暂且分为 All、Articles、Books、Shows and Movies四部分，点击某个栏目右侧的文章列表就是对应分类从新到旧的文章卡片，卡片上可以放置图片，但至少有标题摘要时间字数，最下面有换页，文章列表右侧有当前大分类（四个类别）下的所有tags可以筛选，点击就筛选中间文章区的文章，点击文章卡片跳转至文章阅读界面，顶部头图不变，有一个&#x3C;- back to the list 按钮，剩下就是展示的文章内容一直可以向下滑右侧有mardown的目录可以跳转到对应位置，后面引擎我应该用 astro</p>
</blockquote>
<p>这是我最初的 prompt 算是有一个大概布局的模糊想法，当然美术感觉是一点没有的全靠 gemini 自己的想象</p>
<p>后续也是在和 ai 的交互中有了一个风格布局上较为满意的 ui</p>
<p>当然 stitch 似乎可以选中某个组件单独修改会精准一点，但是我没仔细研究，直接描述有时确实会改错东西</p>
<p>不过最终结果还算满意</p>
<h2>astro</h2>
<p>为什么选择 astro？即答：ai 推荐的。其实就是一个利好于内容展示平台的前端引擎，我将 stitch 中的设计（应该是纯 html）导出到了本地的文件夹里，然后将 astro 的文档链接丢给 codex 让它使用 astro 作为博客引擎迁移这个前端设计就 ok 了</p>
<p>接下来就是和 codex 拉扯让它改出我想要的设计以及交互逻辑，刚迁移好的项目是一个纯静态的前端，大部分逻辑 codex 都可以一次成功，不过要是描述中越详细，可以定位到工程细节，那么成功率确实大大提高</p>
<h1>前端托管 + IP 优选</h1>
<p>Vercel、Netlify 等都有免费网页托管服务，但是很多 IP 中国大陆访问的速度过慢，优选 IP 解决的问题就是将 DNS 解析到好的 IP 上，我最后选择的是 Vercel （Netlify 怎么一下子就到限额了（恼））</p>
<h2>原理</h2>
<p>如果你在阿里云上买的域名，那么在域名管理这里最终应该类似于下面这样：</p>
<p>所谓 DNS 解析就是当你访问一个域名时，浏览器得知道域名背后的实际服务器 IP 地址是什么</p>
<p>记录类型 A 就代表地址记录，直接指向 IPv4 这里是因为根域名一般只能指向 IP 地址，所以 Vercel 给了一个 IP 地址，删掉 A 记录并不影响 CNAME 这些域名的访问，因为他们走的完全不是一条链路</p>
<p>前者是：直接解析到 216.198.79.1 这个官方给的地址</p>
<p>后者是：域名 -> 优选域名 -> 别人整理好的动态优选 IP -> Vercel 服务器</p>
<p>测速还是有一些区别的</p>
<h2>Vercel 上线配置</h2>
<ul>
<li>找到官方文档关于配置 Vercel 的教程，丢给 codex 让它生成相应文件，可以配置推送即重新构建、</li>
<li>推送到 Github 仓库上，在 Vercel 里链接这个仓库，等它构建好</li>
<li>再在 Domains 里面添加自己的域名，将 vercel 提供的 A 记录地址和 CNAME 地址在购买域名的服务商的管理页面配置好</li>
<li>然后确定等 Vercel 生成 SSL 证书，再将 CNAME 的地址改为优选的网址</li>
</ul>
<h1>结语</h1>
<p>这样你就获得了 Vibe coding 时代零代码构建的完全自定义个人博客</p>
<p>欢迎来玩</p>
<p><a href="https://blog.whyself.cn/">Blog | whyself</a></p>]]></content:encoded>
  <pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Gifted</title>
  <link>https://blog.whyself.cn/posts/gifted/</link>
  <guid>https://blog.whyself.cn/posts/gifted/</guid>
  <description>We need life,but more importantly,we need a life.</description>
  <content:encoded><![CDATA[<p>We need life,</p>
<p>but more importantly,</p>
<p>we need a life.</p>
<p>看完《天才少女》，</p>
<p>第一感觉是电影对人物感情的刻画很细腻。</p>
<p>另外大概就是最近所想就有所思了。</p>
<p>the price you have to pay for greatness 但是人不应该也不能抛弃自己的生活去追求所谓的远大前程，所有人都应当有“生活”的权利。</p>
<p>多么幸福的生活啊，小孩子就该这样（）。</p>
<p>这样，然后这样。</p>
<p>酒文化对于我的意义除了借酒消愁，大概也就只有酒后吐真言的游戏了，说实话真的很甜。</p>
<p>这里可以看得出来，对于弗兰克他也有自己的矛盾点，不只是玛丽的生活被束缚住了，其实他自己的生活也在无形中被束缚了。</p>
<p>这句话很有意思，弗兰克举出玛丽所说的玩笑的确不是真心话，但是你说的这句话其实本就有违你的内心。</p>
<p>这是玛丽妈妈相册的最后一张照片，这个特写好啊，她……真的没有看上去那么快乐。</p>
<p>喝酒谈心，羡慕了。</p>
<p>这让我想到了我们小时候，谁不想出人头地。虽然可能没有玛丽的天赋，想法却都是一致的。但是无论是谁，长大了，面对自己的生活，真的能再说出口吗？</p>
<p>无论喜欢有何理由，不带自己私人目的的喜欢，才是最纯粹的。</p>
<p>这段在讨论弗兰克继父的退休生活，隐居养马之类的。可以看得出来伊芙琳是完全不理解的，我觉得她是否也在找补自己的生活呢。70 岁啊，最近正值壮年就去世的人可不少。</p>
<p>玛丽觉得自己是没人要的孩子，而弗兰克去告诉她：无所谓血缘，你出生的时候，总有人为你高兴。</p>
<p>律师质问伊芙琳，黛安的生活难道只有数学吗？很显然，她做出过很多自救的尝试，但却被一一阻止了。最后只能狂热地追求数学的黛安，在完成 proof 之后，丧失了生命的意义。</p>
<p>这段看得出来弗兰克在发泄对法院判决的不满、对自己的不满，后面再努力说服自己克制内心的懊悔。</p>
<p>黛安的生活因为数学的消散而毫无锚点，失去了活下去的意义。</p>
<p>伊芙琳看黛安的手稿，字字都在宣泄对母亲的愤怒与不满。</p>
<p>故事的结尾，玛丽依旧上了所谓的天才学校。但此时的玛丽，未来的玛丽，她们的生命早已不止是为数学而活，而是真正意义上有了自己的生活。</p>
<p>写在最后，也是写给自己的。如果你感到迷茫，你要去做的不是急着找到前进目标。多看看书，多看看电影，多出去走走，努力去找寻属于你自己的生活。</p>
<p>Never bet your life on a single thing.</p>
<p>Everyone knows that's crazy.</p>]]></content:encoded>
  <pubDate>Sun, 29 Mar 2026 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>