From 5df106df613826690f6f71e80d5277a276357383 Mon Sep 17 00:00:00 2001 From: eltrac Date: Sun, 8 Mar 2026 12:10:34 +0800 Subject: docs!(section): merge `essays` and `posts` into `article` A `url` parameter is added to each old markdown file, so their url stay `posts/...` and `essays/...`, but they're treated as the new `article` page by Hugo. The `url` is kept for Webmentions and other external resources, where a simple rediret or alias won't work. Also, Page Bundles are removed. Now only bare markdown files are present. --- ...212\251\346\210\221\351\230\205\350\257\273.md" | 117 ++++ content/article/2025-wrapped.md | 304 +++++++++ content/article/A-Librarian-Heart.md | 58 ++ ...207\252\344\273\245\344\270\272\346\230\257.md" | 86 +++ content/article/Blood-Sweetened-Cruelty.md | 118 ++++ .../FUCK-\345\267\245\344\275\234\346\263\225.md" | 130 ++++ content/article/Fly-Me-To-The-Moon.md | 125 ++++ content/article/IN-LIBRIS-LIBERTAS.md | 359 +++++++++++ ...235\242\346\212\230\350\205\276\350\256\260.md" | 158 +++++ content/article/Notion-sickness.md | 99 +++ content/article/Profitez de votre vie.md | 131 ++++ .../Safari\347\232\204\344\274\230\351\233\205.md" | 99 +++ content/article/The Gay Oedipus.md | 77 +++ ...226\260\346\265\217\350\247\210\345\231\250.md" | 78 +++ content/article/abstraction.md | 139 ++++ content/article/beast-inside.md | 54 ++ content/article/buy-the-thing-not-the-brand.md | 100 +++ content/article/clean-home.md | 204 ++++++ content/article/deleting-bookkeeping-app.md | 22 + content/article/deploying-static-sites.md | 220 +++++++ content/article/entitlement-is-sickness.md | 50 ++ content/article/everything-in-plain-text.md | 376 +++++++++++ content/article/exhausted-perfectionist.md | 54 ++ content/article/git-with-trolley.md | 119 ++++ content/article/go-philosophy.md | 699 +++++++++++++++++++++ content/article/he-is-not-your-soulmate.md | 33 + content/article/home-sick.md | 74 +++ content/article/in-the-mirror-i-get-weak.md | 45 ++ content/article/jack-in-fitness.md | 109 ++++ content/article/lets-make-friday-cryday.md | 33 + ...274\200\345\217\221\346\227\245\345\277\227.md" | 307 +++++++++ content/article/lost-in-gui.md | 119 ++++ content/article/love-lost-in-xmas-eve.md | 49 ++ content/article/no-sugar-in-my-coffee.md | 71 +++ content/article/on-wording.md | 119 ++++ content/article/perfect-day.md | 74 +++ content/article/prejudice-of-college-education.md | 141 +++++ content/article/reading-as-an-experience.md | 135 ++++ .../article/river-in-my-eyes-poem-in-my-throat.md | 79 +++ content/article/ruled-living-space.md | 76 +++ content/article/self-loathing-growth.md | 77 +++ content/article/shortcuts.md | 185 ++++++ content/article/site-report-3.md | 134 ++++ content/article/site-report-4.md | 151 +++++ content/article/tarot-the-tower.md | 104 +++ content/article/thinking-privilege.md | 130 ++++ content/article/true-love.md | 55 ++ content/article/wandering.md | 28 + content/article/webpage-as-lists.md | 301 +++++++++ content/article/why-blog-weekly.md | 107 ++++ content/article/writathon-review-alpha.md | 44 ++ content/article/zero-js-chart.md | 277 ++++++++ ...257\273\344\270\211\346\234\254\344\271\246.md" | 48 ++ ...255\220\345\201\232\345\217\252\347\214\253.md" | 86 +++ ...230\257\345\245\275\350\257\273\350\200\205.md" | 96 +++ ...267\261\345\261\214\346\233\264\345\244\247.md" | 73 +++ ...277\206\351\207\214\346\212\271\345\216\273.md" | 25 + ...270\215\350\257\273\346\226\260\351\227\273.md" | 51 ++ ...256\266\347\232\204\347\233\264\350\247\211.md" | 92 +++ ...\256\351\242\230\345\234\250\345\223\252-II.md" | 100 +++ ...227\256\351\242\230\345\234\250\345\223\252.md" | 109 ++++ ...216\251\346\211\221\345\205\213\345\221\242.md" | 202 ++++++ ...227\266\345\206\231\346\211\271\346\263\250.md" | 115 ++++ ...225\245\346\230\276\347\254\250\346\213\231.md" | 76 +++ ...15\345\206\231-now-\351\241\265\351\235\242.md" | 71 +++ ...277\215\345\272\246\346\233\264\344\275\216.md" | 59 ++ ...216\214\346\210\220\345\212\237\345\255\246.md" | 117 ++++ ...244\247\347\274\235\345\220\210\346\200\252.md" | 133 ++++ ...205\266\347\233\270\344\274\274\357\274\237.md" | 115 ++++ ...232\204\344\277\241\344\273\273\351\223\276.md" | 137 ++++ ...214\256\344\270\212\345\277\203\350\204\217.md" | 206 ++++++ ...270\273\344\275\223\347\274\272\345\244\261.md" | 63 ++ ...247\202\347\232\204\344\273\243\344\273\267.md" | 61 ++ ...230\262\347\254\221\347\233\264\347\224\267.md" | 114 ++++ ...210\233\351\200\240\344\273\267\345\200\274.md" | 89 +++ ...203\234\346\201\220\346\203\247\345\220\227.md" | 105 ++++ ...202\262\347\232\204\346\230\245\346\242\246.md" | 137 ++++ ...270\215\344\274\232\345\217\221\347\254\221.md" | 38 ++ ...201\232\347\232\204\350\211\272\346\234\257.md" | 72 +++ ...216\237\347\224\237\345\256\266\345\272\255.md" | 54 ++ ...210\221\347\232\204\350\272\253\344\275\223.md" | 98 +++ ...270\215\347\210\261\345\260\261\346\255\273.md" | 169 +++++ ...263\273\347\232\204\346\225\205\344\272\213.md" | 72 +++ ...232\204\344\270\273\350\247\202\346\200\247.md" | 116 ++++ ...232\204\351\207\215\350\246\201\346\200\247.md" | 106 ++++ ...270\216\347\234\237\345\260\217\344\272\272.md" | 120 ++++ ...275\225\344\273\245\344\270\272\344\272\272.md" | 74 +++ "content/article/\344\275\231\351\234\207.md" | 68 ++ ...275\277\347\224\250\346\227\266\351\227\264.md" | 55 ++ ...257\240\351\207\212\346\226\271\345\274\217.md" | 36 ++ ...277\241\344\273\260\346\202\262\345\243\256.md" | 61 ++ ...256\244\345\220\214\345\215\261\346\234\272.md" | 79 +++ ...227\240\350\266\243\344\271\213\347\211\251.md" | 73 +++ ...203\226\347\232\204\346\235\202\350\260\210.md" | 67 ++ ...265\233\345\215\232\347\214\216\345\267\253.md" | 84 +++ ...257\264\347\232\204\345\214\272\345\210\253.md" | 80 +++ ...0 2023 \347\232\204\345\274\200\345\244\264.md" | 86 +++ ...0 2024 \347\232\204\345\274\200\345\244\264.md" | 293 +++++++++ ...2502025\347\232\204\345\274\200\345\244\264.md" | 377 +++++++++++ ...262\276\345\274\217\345\210\233\344\275\234.md" | 48 ++ ...204\217\350\257\206\346\216\242\347\264\242.md" | 85 +++ ...211\262\347\214\253\345\244\264\351\271\260.md" | 72 +++ ...211\215\346\217\220\351\207\215\346\216\267.md" | 59 ++ ...275\231\347\232\204\346\235\202\350\264\250.md" | 112 ++++ ...210\235\347\252\245\351\227\250\345\276\204.md" | 153 +++++ ...215\210\345\244\234\345\220\273\346\210\221.md" | 36 ++ ...273\241\345\230\264\345\226\267\347\262\252.md" | 124 ++++ ...\240\350\266\263\350\275\273\351\207\215-ii.md" | 107 ++++ ...227\240\350\266\263\350\275\273\351\207\215.md" | 33 + .../\345\216\214\350\240\242\347\227\207.md" | 141 +++++ ...205\247\344\270\215\350\266\263\345\220\227.md" | 159 +++++ ...220\221\344\270\213\345\275\222\347\272\263.md" | 90 +++ ...244\247\350\204\221\345\274\200\346\210\230.md" | 132 ++++ ...211\272\351\235\222\345\271\264\344\273\254.md" | 106 ++++ ...216\214\346\201\266\344\270\216\346\201\250.md" | 56 ++ ...67\261\347\232\204S\345\261\236\346\200\247.md" | 137 ++++ ...245\255\345\220\216\351\232\217\346\203\263.md" | 71 +++ ...270\201\345\246\204\346\203\263\347\227\207.md" | 99 +++ ...205\253\347\202\271\345\233\236\345\256\266.md" | 33 + ...244\217\346\227\245\351\200\203\344\272\241.md" | 70 +++ ...233\250\347\232\204\345\205\263\347\263\273.md" | 21 + ...232\204\345\261\200\351\231\220\346\200\247.md" | 170 +++++ ...210\221\347\232\204\346\201\266\351\255\224.md" | 137 ++++ ...272\272\347\232\204\350\265\236\347\276\216.md" | 80 +++ ...232\204\346\216\250\351\224\200\345\221\230.md" | 79 +++ ...232\204\350\213\261\346\226\207\345\220\215.md" | 161 +++++ ...240\267\347\232\204\347\235\241\347\234\240.md" | 126 ++++ ...227\240\347\227\233\346\227\251\350\265\267.md" | 125 ++++ ...267\250\345\244\247\351\230\264\350\260\213.md" | 100 +++ ...206\231\344\275\234\347\201\265\346\204\237.md" | 121 ++++ ...210\251\344\272\216\345\255\246\344\271\240.md" | 93 +++ ...234\211\350\207\264\346\255\273\351\207\217.md" | 121 ++++ ...256\214\347\276\216\345\271\273\350\247\211.md" | 299 +++++++++ ...272\206\350\247\243\346\227\240\347\237\245.md" | 64 ++ ...272\233\345\206\215\346\200\235\350\200\203.md" | 41 ++ ...214\272\351\207\214\347\213\202\345\245\224.md" | 155 +++++ ...216\204\345\255\246\344\277\241\344\273\260.md" | 56 ++ ...275\223\344\270\213\346\266\210\345\244\261.md" | 25 + ...205\250\351\203\250\346\231\272\350\257\206.md" | 149 +++++ ...220\215\347\232\204\347\210\261\344\272\272.md" | 86 +++ ...270\215\346\230\257\345\205\205\345\256\236.md" | 65 ++ ...207\252\347\204\266\351\200\211\346\213\251.md" | 58 ++ ...274\202\344\271\213\345\274\202\345\220\214.md" | 46 ++ ...203\205\347\273\252\346\255\273\351\224\201.md" | 57 ++ ...275\223\347\232\204\346\203\205\347\273\252.md" | 95 +++ ...275\240\347\232\204\346\213\247\345\267\264.md" | 90 +++ ...270\215\345\205\261\346\210\264\345\244\251.md" | 60 ++ ...244\276\344\272\244\345\252\222\344\275\223.md" | 75 +++ ...226\234\346\254\242\346\225\264\347\220\206.md" | 90 +++ ...260\217\345\255\251\345\255\220\357\274\237.md" | 40 ++ ...270\252\345\260\217\345\255\251\345\255\220.md" | 64 ++ ...270\213\345\234\260\347\213\261\345\216\273.md" | 133 ++++ ...225\260\345\255\227\350\256\260\345\275\225.md" | 260 ++++++++ ...204\237\345\212\250\350\277\207\346\225\217.md" | 72 +++ ...247\243\345\206\263\346\226\271\346\241\210.md" | 103 +++ ...273\252\345\203\217\346\262\263\346\265\201.md" | 185 ++++++ ...256\250\345\216\214\344\270\212\347\217\255.md" | 74 +++ ...210\221\350\256\250\345\216\214\350\275\246.md" | 56 ++ ...256\250\345\216\214\350\276\251\350\256\272.md" | 57 ++ ...207\214\347\232\204\346\226\271\345\274\217.md" | 27 + ...211\251\345\274\240\346\203\257\346\200\247.md" | 71 +++ ...217\221\345\225\206\345\200\274\345\220\227.md" | 152 +++++ ...256\244\347\237\245\350\276\271\347\225\214.md" | 85 +++ ...255\246\347\224\237\346\200\235\347\273\264.md" | 87 +++ ...5\347\211\251\346\227\245\345\277\227 Vol-2.md" | 108 ++++ ...5\347\211\251\346\227\245\345\277\227-Vol-1.md" | 177 ++++++ ...5\347\211\251\346\227\245\345\277\227-vol-3.md" | 98 +++ ...5\347\211\251\346\227\245\345\277\227-vol-4.md" | 214 +++++++ ...5\347\211\251\346\227\245\345\277\227-vol-5.md" | 90 +++ ...5\347\211\251\346\227\245\345\277\227-vol-6.md" | 195 ++++++ ...5\347\211\251\346\227\245\345\277\227-vol-7.md" | 168 +++++ ...5\347\211\251\346\227\245\345\277\227-vol-8.md" | 115 ++++ ...264\271\347\232\204\345\205\263\347\263\273.md" | 87 +++ ...211\223\345\215\241\347\263\273\347\273\237.md" | 270 ++++++++ ...211\213\345\246\202\346\230\257\350\257\264.md" | 130 ++++ ...270\210\347\232\204\345\202\262\346\205\242.md" | 89 +++ ...254\224\347\232\204\346\204\217\344\271\211.md" | 91 +++ ...234\200\344\275\263\345\256\236\350\267\265.md" | 195 ++++++ ...215\216\344\271\213\347\230\276\347\227\207.md" | 59 ++ ...230\257\347\234\237\345\256\236\347\232\204.md" | 50 ++ ...272\225\345\220\203\344\270\215\345\220\203.md" | 78 +++ ...256\272\347\232\204\350\214\203\345\233\264.md" | 107 ++++ ...244\252\344\275\216\344\272\206\345\220\227.md" | 42 ++ ...216\207\346\226\271\346\263\225\350\256\272.md" | 114 ++++ ...234\200\345\217\227\345\201\217\347\210\261.md" | 95 +++ ...222\247\345\234\260\347\224\237\346\264\273.md" | 83 +++ ...230\257\346\200\216\346\240\267\347\232\204.md" | 98 +++ ...270\215\344\272\210\347\275\256\350\257\204.md" | 105 ++++ ...\241\350\256\241\345\210\222\344\271\246-II.md" | 119 ++++ ...272\241\350\256\241\345\210\222\344\271\246.md" | 101 +++ ...256\276\350\256\241\345\223\262\345\255\246.md" | 139 ++++ ...264\250\346\230\257\346\216\247\345\210\266.md" | 72 +++ ...\252\346\274\253\344\270\273\344\271\211-II.md" | 74 +++ ...265\252\346\274\253\344\270\273\344\271\211.md" | 74 +++ ...256\270\346\233\264\346\234\211\347\224\250.md" | 348 ++++++++++ ...246\201\347\232\204\347\203\255\346\203\205.md" | 53 ++ ...257\253\346\227\240\346\225\254\346\204\217.md" | 107 ++++ ...205\263\345\277\203\345\256\266\344\272\272.md" | 53 ++ .../\346\263\274\345\206\267\346\260\264ADHD.md" | 98 +++ ...223\201\347\232\204\350\247\243\346\224\276.md" | 67 ++ ...230\257\344\270\272\344\272\272\345\274\200.md" | 182 ++++++ ...216\260\345\256\236\344\271\213\346\257\222.md" | 108 ++++ ...275\240\347\232\204\347\211\251\346\254\262.md" | 135 ++++ ...237\213\350\221\254\350\207\252\345\267\261.md" | 62 ++ ...234\213\346\212\223\345\250\203\345\250\203.md" | 13 + ...2\347\264\242\346\227\245\345\277\227-vol-1.md" | 133 ++++ ...2\347\264\242\346\227\245\345\277\227-vol-2.md" | 205 ++++++ ...2\347\264\242\346\227\245\345\277\227-vol-3.md" | 102 +++ ...271\266\344\270\215\345\245\275\347\224\250.md" | 107 ++++ ...257\221\350\200\205\347\264\240\345\205\273.md" | 198 ++++++ ...212\261\345\234\250\345\267\246\350\276\271.md" | 125 ++++ ...227\240\347\237\245\344\277\241\345\276\222.md" | 109 ++++ ...214\216\345\267\253\350\241\214\345\212\250.md" | 87 +++ ...256\241\347\220\206\346\227\266\351\227\264.md" | 104 +++ "content/article/\347\273\277\350\211\262.md" | 39 ++ ...255\230\345\234\250\350\207\252\345\276\213.md" | 64 ++ ...212\233\344\270\215\350\256\250\345\245\275.md" | 103 +++ ...211\262\345\274\217\345\210\233\344\275\234.md" | 40 ++ ...270\216\350\241\250\350\276\276\346\254\262.md" | 94 +++ ...207\252\346\201\213\346\203\205\347\273\223.md" | 156 +++++ ...207\252\346\235\200\345\212\250\345\233\240.md" | 71 +++ ...275\252\345\220\215\345\260\217\350\265\217.md" | 118 ++++ ...270\216\346\201\220\344\272\272\347\227\207.md" | 134 ++++ ...224\231\345\244\261\346\201\220\346\203\247.md" | 155 +++++ ...242\216\347\232\204\345\244\247\350\204\221.md" | 102 +++ ...232\204\344\275\223\351\207\215\347\247\244.md" | 65 ++ ...255\246\345\257\237\350\255\246\345\257\237.md" | 78 +++ ...270\200\347\261\273\347\224\267\344\272\272.md" | 68 ++ ...256\272\344\273\252\345\274\217\346\204\237.md" | 104 +++ ...256\242\347\232\204\350\257\204\350\256\272.md" | 96 +++ ...257\215\344\270\215\350\276\276\346\204\217.md" | 165 +++++ ...200\203\347\232\204\350\276\271\347\225\214.md" | 142 +++++ ...200\235\347\273\264\345\267\256\345\274\202.md" | 61 ++ ...245\236\350\257\235\346\256\213\345\223\215.md" | 182 ++++++ ...273\217\351\252\214\345\210\206\344\272\253.md" | 98 +++ ...200\237\344\271\213\345\256\242\344\273\254.md" | 130 ++++ ...213\254\345\261\205\347\224\237\346\264\273.md" | 117 ++++ ...276\244\345\261\205\347\224\237\346\264\273.md" | 147 +++++ ...211\245\347\246\273\346\204\217\344\271\211.md" | 155 +++++ ...256\244\350\257\206\351\243\216\345\221\263.md" | 77 +++ ...223\252\351\207\214\345\216\273\344\272\206.md" | 120 ++++ ...202\243\345\260\261\346\230\257\347\210\261.md" | 56 ++ ...216\267\345\217\226\347\237\245\350\257\206.md" | 73 +++ ...222\274\345\215\263\347\234\237\347\220\206.md" | 39 ++ 244 files changed, 26907 insertions(+) create mode 100644 "content/article/2024\345\271\264-\346\210\221\344\275\277\347\224\250\344\273\200\344\271\210\345\267\245\345\205\267\345\270\256\345\212\251\346\210\221\351\230\205\350\257\273.md" create mode 100644 content/article/2025-wrapped.md create mode 100644 content/article/A-Librarian-Heart.md create mode 100644 "content/article/AI-\346\255\243\345\234\250\350\256\251\344\272\272\345\217\230\345\276\227\345\211\215\346\211\200\346\234\252\346\234\211\345\234\260\350\207\252\344\273\245\344\270\272\346\230\257.md" create mode 100644 content/article/Blood-Sweetened-Cruelty.md create mode 100644 "content/article/FUCK-\345\267\245\344\275\234\346\263\225.md" create mode 100644 content/article/Fly-Me-To-The-Moon.md create mode 100644 content/article/IN-LIBRIS-LIBERTAS.md create mode 100644 "content/article/Manjaro \346\241\214\351\235\242\346\212\230\350\205\276\350\256\260.md" create mode 100644 content/article/Notion-sickness.md create mode 100644 content/article/Profitez de votre vie.md create mode 100644 "content/article/Safari\347\232\204\344\274\230\351\233\205.md" create mode 100644 content/article/The Gay Oedipus.md create mode 100644 "content/article/The-Browser-Company-\347\232\204\346\226\260\346\265\217\350\247\210\345\231\250.md" create mode 100644 content/article/abstraction.md create mode 100644 content/article/beast-inside.md create mode 100644 content/article/buy-the-thing-not-the-brand.md create mode 100644 content/article/clean-home.md create mode 100644 content/article/deleting-bookkeeping-app.md create mode 100644 content/article/deploying-static-sites.md create mode 100644 content/article/entitlement-is-sickness.md create mode 100644 content/article/everything-in-plain-text.md create mode 100644 content/article/exhausted-perfectionist.md create mode 100644 content/article/git-with-trolley.md create mode 100644 content/article/go-philosophy.md create mode 100644 content/article/he-is-not-your-soulmate.md create mode 100644 content/article/home-sick.md create mode 100644 content/article/in-the-mirror-i-get-weak.md create mode 100644 content/article/jack-in-fitness.md create mode 100644 content/article/lets-make-friday-cryday.md create mode 100644 "content/article/libra-js-\345\274\200\345\217\221\346\227\245\345\277\227.md" create mode 100644 content/article/lost-in-gui.md create mode 100644 content/article/love-lost-in-xmas-eve.md create mode 100644 content/article/no-sugar-in-my-coffee.md create mode 100644 content/article/on-wording.md create mode 100644 content/article/perfect-day.md create mode 100644 content/article/prejudice-of-college-education.md create mode 100644 content/article/reading-as-an-experience.md create mode 100644 content/article/river-in-my-eyes-poem-in-my-throat.md create mode 100644 content/article/ruled-living-space.md create mode 100644 content/article/self-loathing-growth.md create mode 100644 content/article/shortcuts.md create mode 100644 content/article/site-report-3.md create mode 100644 content/article/site-report-4.md create mode 100644 content/article/tarot-the-tower.md create mode 100644 content/article/thinking-privilege.md create mode 100644 content/article/true-love.md create mode 100644 content/article/wandering.md create mode 100644 content/article/webpage-as-lists.md create mode 100644 content/article/why-blog-weekly.md create mode 100644 content/article/writathon-review-alpha.md create mode 100644 content/article/zero-js-chart.md create mode 100644 "content/article/\344\270\200\346\254\241\350\257\273\344\270\211\346\234\254\344\271\246.md" create mode 100644 "content/article/\344\270\213\350\276\210\345\255\220\345\201\232\345\217\252\347\214\253.md" create mode 100644 "content/article/\344\270\215\344\274\232\350\257\264\344\271\246\347\203\202\347\232\204\350\257\273\350\200\205\344\270\215\346\230\257\345\245\275\350\257\273\350\200\205.md" create mode 100644 "content/article/\344\270\215\350\204\261\350\243\244\345\255\220\345\246\202\344\275\225\350\257\201\346\230\216\350\207\252\345\267\261\345\261\214\346\233\264\345\244\247.md" create mode 100644 "content/article/\344\270\215\350\246\201\346\212\212\346\210\221\344\273\216\344\275\240\347\232\204\350\256\260\345\277\206\351\207\214\346\212\271\345\216\273.md" create mode 100644 "content/article/\344\270\215\350\257\273\346\226\260\351\227\273.md" create mode 100644 "content/article/\344\270\223\345\256\266\347\232\204\347\233\264\350\247\211.md" create mode 100644 "content/article/\344\270\272\344\272\206\345\201\232\350\200\214\345\201\232\347\232\204\351\227\256\351\242\230\345\234\250\345\223\252-II.md" create mode 100644 "content/article/\344\270\272\344\272\206\345\201\232\350\200\214\345\201\232\347\232\204\351\227\256\351\242\230\345\234\250\345\223\252.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\344\270\215\347\216\251\346\211\221\345\205\213\345\221\242.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\344\275\240\344\270\215\345\272\224\350\257\245\345\234\250\351\230\205\350\257\273\346\227\266\345\206\231\346\211\271\346\263\250.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\345\260\235\350\257\225\347\220\206\350\247\243\345\271\264\350\275\273\344\272\272\347\232\204\345\271\264\351\225\277\350\200\205\351\203\275\347\225\245\346\230\276\347\254\250\346\213\231.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\346\210\221\344\270\215\345\206\231-now-\351\241\265\351\235\242.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\346\210\221\345\257\271\347\224\267\346\200\247\347\232\204\345\256\271\345\277\215\345\272\246\346\233\264\344\275\216.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\350\256\250\345\216\214\346\210\220\345\212\237\345\255\246.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\350\257\264\350\213\261\350\257\255\346\230\257\350\257\255\350\250\200\347\225\214\347\232\204\346\234\200\345\244\247\347\274\235\345\220\210\346\200\252.md" create mode 100644 "content/article/\344\270\272\344\273\200\344\271\210\350\257\267\346\225\231AI\345\222\214\345\215\240\345\215\234\347\256\227\345\221\275\346\236\201\345\205\266\347\233\270\344\274\274\357\274\237.md" create mode 100644 "content/article/\344\270\272\344\275\225\344\273\245\345\217\212\345\246\202\344\275\225\345\273\272\347\253\213\350\207\252\345\267\261\347\232\204\344\277\241\344\273\273\351\223\276.md" create mode 100644 "content/article/\344\270\272\346\210\230\346\226\227\347\214\256\344\270\212\345\277\203\350\204\217.md" create mode 100644 "content/article/\344\270\273\344\275\223\347\274\272\345\244\261.md" create mode 100644 "content/article/\344\271\220\350\247\202\347\232\204\344\273\243\344\273\267.md" create mode 100644 "content/article/\344\272\222\350\201\224\347\275\221\344\270\272\344\273\200\344\271\210\345\226\234\346\254\242\345\230\262\347\254\221\347\233\264\347\224\267.md" create mode 100644 "content/article/\344\272\247\347\224\237\346\225\260\346\215\256\344\270\215\347\255\211\344\272\216\345\210\233\351\200\240\344\273\267\345\200\274.md" create mode 100644 "content/article/\344\272\272\344\270\200\345\256\232\350\246\201\346\210\230\350\203\234\346\201\220\346\203\247\345\220\227.md" create mode 100644 "content/article/\344\272\272\345\256\232\350\203\234\345\244\251\345\217\257\350\203\275\346\230\257\344\272\272\347\261\273\346\234\200\345\217\257\346\202\262\347\232\204\346\230\245\346\242\246.md" create mode 100644 "content/article/\344\272\272\347\261\273\344\270\200\346\200\235\350\200\203-AI\344\271\237\344\270\215\344\274\232\345\217\221\347\254\221.md" create mode 100644 "content/article/\344\273\200\344\271\210\344\271\237\344\270\215\345\201\232\347\232\204\350\211\272\346\234\257.md" create mode 100644 "content/article/\344\273\200\344\271\210\346\230\257\345\201\245\345\272\267\347\232\204\345\216\237\347\224\237\345\256\266\345\272\255.md" create mode 100644 "content/article/\344\273\200\344\271\210\347\273\217\350\277\207\346\210\221\347\232\204\350\272\253\344\275\223.md" create mode 100644 "content/article/\344\273\212\345\244\234\344\270\215\347\210\261\345\260\261\346\255\273.md" create mode 100644 "content/article/\344\273\213\347\263\273\347\232\204\346\225\205\344\272\213.md" create mode 100644 "content/article/\344\273\216\344\270\273\344\275\223\346\200\247\347\232\204\347\224\250\350\257\215\347\234\213\347\224\250\350\257\215\347\232\204\344\270\273\350\247\202\346\200\247.md" create mode 100644 "content/article/\344\273\216\347\204\246\350\231\221\345\222\214\350\207\252\345\215\221\350\260\210\346\204\237\345\217\227\344\270\216\344\275\223\351\252\214\347\232\204\351\207\215\350\246\201\346\200\247.md" create mode 100644 "content/article/\344\274\252\345\220\233\345\255\220\344\270\216\347\234\237\345\260\217\344\272\272.md" create mode 100644 "content/article/\344\275\225\344\273\245\344\270\272\344\272\272.md" create mode 100644 "content/article/\344\275\231\351\234\207.md" create mode 100644 "content/article/\344\275\240\345\244\247\346\246\202\344\270\215\351\234\200\350\246\201\346\216\247\345\210\266\345\261\217\345\271\225\344\275\277\347\224\250\346\227\266\351\227\264.md" create mode 100644 "content/article/\344\275\240\346\211\271\350\257\204\347\232\204\345\217\252\346\230\257\347\254\254\344\270\211\350\200\205\347\232\204\350\257\240\351\207\212\346\226\271\345\274\217.md" create mode 100644 "content/article/\344\277\241\344\273\260\346\202\262\345\243\256.md" create mode 100644 "content/article/\345\201\217\346\211\247\347\213\202\347\232\204\350\207\252\346\210\221\350\256\244\345\220\214\345\215\261\346\234\272.md" create mode 100644 "content/article/\345\201\245\345\272\267\347\232\204\347\201\265\351\255\202\346\230\257\344\270\226\344\270\212\346\234\200\346\227\240\350\266\243\344\271\213\347\211\251.md" create mode 100644 "content/article/\345\205\263\344\272\216\350\202\245\350\203\226\347\232\204\346\235\202\350\260\210.md" create mode 100644 "content/article/\345\206\215\350\260\210\350\265\233\345\215\232\347\214\216\345\267\253.md" create mode 100644 "content/article/\345\206\231\345\222\214\350\257\264\347\232\204\345\214\272\345\210\253.md" create mode 100644 "content/article/\345\206\231\345\234\250 2023 \347\232\204\345\274\200\345\244\264.md" create mode 100644 "content/article/\345\206\231\345\234\250 2024 \347\232\204\345\274\200\345\244\264.md" create mode 100644 "content/article/\345\206\231\345\234\2502025\347\232\204\345\274\200\345\244\264.md" create mode 100644 "content/article/\345\210\206\345\250\251\345\274\217\345\210\233\344\275\234\345\222\214\345\260\204\347\262\276\345\274\217\345\210\233\344\275\234.md" create mode 100644 "content/article/\345\210\233\344\275\234\347\232\204\346\275\234\346\204\217\350\257\206\346\216\242\347\264\242.md" create mode 100644 "content/article/\345\210\253\345\206\215\347\203\246\346\210\221\344\272\206\357\274\214\347\273\277\350\211\262\347\214\253\345\244\264\351\271\260.md" create mode 100644 "content/article/\345\211\215\346\217\220\351\207\215\346\216\267.md" create mode 100644 "content/article/\345\211\224\351\231\244\346\257\217\344\270\200\345\257\270\345\244\232\344\275\231\347\232\204\346\235\202\350\264\250.md" create mode 100644 "content/article/\345\215\201\345\205\253\345\271\264\347\244\276\346\201\220\347\232\204\345\210\235\347\252\245\351\227\250\345\276\204.md" create mode 100644 "content/article/\345\215\210\345\244\234\345\220\273\346\210\221.md" create mode 100644 "content/article/\345\216\214\345\245\263\347\224\267\344\270\272\344\275\225\345\217\252\344\274\232\346\273\241\345\230\264\345\226\267\347\262\252.md" create mode 100644 "content/article/\345\216\214\346\201\266\345\234\250\344\270\252\344\275\223\344\271\213\345\244\226\346\227\240\350\266\263\350\275\273\351\207\215-ii.md" create mode 100644 "content/article/\345\216\214\346\201\266\345\234\250\344\270\252\344\275\223\344\271\213\345\244\226\346\227\240\350\266\263\350\275\273\351\207\215.md" create mode 100644 "content/article/\345\216\214\350\240\242\347\227\207.md" create mode 100644 "content/article/\345\216\214\350\240\242\347\232\204\344\272\272\344\270\200\345\256\232\346\231\272\346\205\247\344\270\215\350\266\263\345\220\227.md" create mode 100644 "content/article/\345\220\221\344\270\213\345\275\222\347\272\263.md" create mode 100644 "content/article/\345\222\214\350\207\252\345\267\261\347\232\204\345\244\247\350\204\221\345\274\200\346\210\230.md" create mode 100644 "content/article/\345\226\234\346\254\242\345\220\246\345\256\232\344\272\272\346\200\247\347\232\204\346\226\207\350\211\272\351\235\222\345\271\264\344\273\254.md" create mode 100644 "content/article/\345\226\234\346\254\242\345\222\214\347\210\261-\345\216\214\346\201\266\344\270\216\346\201\250.md" create mode 100644 "content/article/\345\226\235\345\222\226\345\225\241\345\246\202\344\275\225\345\270\256\346\210\221\345\274\200\345\217\221\350\207\252\345\267\261\347\232\204S\345\261\236\346\200\247.md" create mode 100644 "content/article/\345\233\242\345\271\264\351\245\255\345\220\216\351\232\217\346\203\263.md" create mode 100644 "content/article/\345\233\255\344\270\201\345\246\204\346\203\263\347\227\207.md" create mode 100644 "content/article/\345\234\250\346\270\205\346\231\250\345\205\253\347\202\271\345\233\236\345\256\266.md" create mode 100644 "content/article/\345\244\217\346\227\245\351\200\203\344\272\241.md" create mode 100644 "content/article/\345\244\247\346\246\202\346\230\257\344\270\213\351\233\250\347\232\204\345\205\263\347\263\273.md" create mode 100644 "content/article/\345\245\275\344\270\272\344\272\272\345\270\210\345\246\202\344\275\225\345\270\256\346\210\221\345\217\215\346\200\235\347\216\260\344\273\243\347\247\221\345\255\246\347\232\204\345\261\200\351\231\220\346\200\247.md" create mode 100644 "content/article/\345\245\275\346\242\246-\346\210\221\347\232\204\346\201\266\351\255\224.md" create mode 100644 "content/article/\345\246\202\344\275\225\345\272\224\345\257\271\344\273\226\344\272\272\347\232\204\350\265\236\347\276\216.md" create mode 100644 "content/article/\345\246\202\344\275\225\345\272\224\345\257\271\347\203\246\344\272\272\347\232\204\346\216\250\351\224\200\345\221\230.md" create mode 100644 "content/article/\345\246\202\344\275\225\346\213\245\346\234\211\344\270\200\344\270\252\344\273\244\344\272\272\346\204\211\346\202\246\347\232\204\350\213\261\346\226\207\345\220\215.md" create mode 100644 "content/article/\345\246\202\344\275\225\346\213\245\346\234\211\347\214\252\344\270\200\346\240\267\347\232\204\347\235\241\347\234\240.md" create mode 100644 "content/article/\345\246\202\344\275\225\346\227\240\347\227\233\346\227\251\350\265\267.md" create mode 100644 "content/article/\345\246\202\344\275\225\346\236\204\345\273\272\346\203\212\344\270\226\351\252\207\344\277\227\347\232\204\345\267\250\345\244\247\351\230\264\350\260\213.md" create mode 100644 "content/article/\345\246\202\344\275\225\350\216\267\345\276\227\345\217\226\344\271\213\344\270\215\345\260\275\347\232\204\345\206\231\344\275\234\347\201\265\346\204\237.md" create mode 100644 "content/article/\345\255\246\344\271\240\350\200\205\347\232\204\345\247\277\346\200\201\346\210\226\350\256\270\345\271\266\344\270\215\345\210\251\344\272\216\345\255\246\344\271\240.md" create mode 100644 "content/article/\345\256\211\347\234\240\350\215\257\344\271\237\346\234\211\350\207\264\346\255\273\351\207\217.md" create mode 100644 "content/article/\345\256\214\347\276\216\345\271\273\350\247\211.md" create mode 100644 "content/article/\345\256\235\345\211\221\345\205\253-\344\272\206\350\247\243\346\227\240\347\237\245.md" create mode 100644 "content/article/\345\257\271\350\201\214\344\270\232\346\226\271\345\220\221\347\232\204\344\270\200\344\272\233\345\206\215\346\200\235\350\200\203.md" create mode 100644 "content/article/\345\260\275\346\203\205\345\234\250\350\210\222\351\200\202\345\214\272\351\207\214\347\213\202\345\245\224.md" create mode 100644 "content/article/\345\271\264\351\276\204\344\270\216\347\216\204\345\255\246\344\277\241\344\273\260.md" create mode 100644 "content/article/\345\275\223\344\273\226\344\273\216\345\275\223\344\270\213\346\266\210\345\244\261.md" create mode 100644 "content/article/\345\275\223\344\275\240\345\244\261\345\216\273\350\272\253\344\270\272\344\272\272\347\232\204\345\205\250\351\203\250\346\231\272\350\257\206.md" create mode 100644 "content/article/\345\275\223\346\210\221\346\270\264\346\234\233\346\213\245\346\212\261\346\227\240\345\220\215\347\232\204\347\210\261\344\272\272.md" create mode 100644 "content/article/\345\277\231\347\242\214\344\270\215\346\230\257\345\205\205\345\256\236.md" create mode 100644 "content/article/\346\200\247\345\260\221\346\225\260\347\276\244\344\275\223\347\232\204\350\207\252\347\204\266\351\200\211\346\213\251.md" create mode 100644 "content/article/\346\201\220\345\220\214\344\270\216\346\201\220\345\274\202\344\271\213\345\274\202\345\220\214.md" create mode 100644 "content/article/\346\203\205\347\273\252\346\255\273\351\224\201.md" create mode 100644 "content/article/\346\204\244\346\200\222\346\230\257\344\270\200\347\247\215\346\255\243\345\275\223\347\232\204\346\203\205\347\273\252.md" create mode 100644 "content/article/\346\210\221\344\270\215\347\220\206\350\247\243\344\275\240\347\232\204\346\213\247\345\267\264.md" create mode 100644 "content/article/\346\210\221\344\270\216\347\201\260\345\260\230\344\270\215\345\205\261\346\210\264\345\244\251.md" create mode 100644 "content/article/\346\210\221\344\270\216\347\244\276\344\272\244\345\252\222\344\275\223.md" create mode 100644 "content/article/\346\210\221\344\270\272\344\273\200\344\271\210\345\226\234\346\254\242\346\225\264\347\220\206.md" create mode 100644 "content/article/\346\210\221\344\270\272\344\273\200\344\271\210\350\256\250\345\216\214\345\260\217\345\255\251\345\255\220\357\274\237.md" create mode 100644 "content/article/\346\210\221\344\273\216\346\234\252\350\242\253\345\205\201\350\256\270\345\201\232\344\270\252\345\260\217\345\255\251\345\255\220.md" create mode 100644 "content/article/\346\210\221\344\274\232\345\270\246\347\235\200\346\210\221\347\232\204\350\247\202\347\202\271\344\270\213\345\234\260\347\213\261\345\216\273.md" create mode 100644 "content/article/\346\210\221\345\205\250\351\235\242\346\212\233\345\274\203\344\272\206\346\225\260\345\255\227\350\256\260\345\275\225.md" create mode 100644 "content/article/\346\210\221\345\257\271\346\204\237\345\212\250\350\277\207\346\225\217.md" create mode 100644 "content/article/\346\210\221\347\232\204-RSS-\350\247\243\345\206\263\346\226\271\346\241\210.md" create mode 100644 "content/article/\346\210\221\347\232\204\346\200\235\347\273\252\345\203\217\346\262\263\346\265\201.md" create mode 100644 "content/article/\346\210\221\350\256\250\345\216\214\344\270\212\347\217\255.md" create mode 100644 "content/article/\346\210\221\350\256\250\345\216\214\350\275\246.md" create mode 100644 "content/article/\346\210\221\350\256\250\345\216\214\350\276\251\350\256\272.md" create mode 100644 "content/article/\346\210\221\350\256\276\346\203\263\344\272\206\344\270\200\347\231\276\347\247\215\344\275\240\351\207\215\346\226\260\350\277\233\345\205\245\346\210\221\347\224\237\345\221\275\351\207\214\347\232\204\346\226\271\345\274\217.md" create mode 100644 "content/article/\346\211\251\345\274\240\346\203\257\346\200\247.md" create mode 100644 "content/article/\346\212\212\351\222\261\347\273\231\350\275\257\344\273\266\345\274\200\345\217\221\345\225\206\345\200\274\345\220\227.md" create mode 100644 "content/article/\346\214\221\351\243\237\345\246\202\344\275\225\345\270\256\346\210\221\345\217\221\347\216\260\350\207\252\345\267\261\347\232\204\350\256\244\347\237\245\350\276\271\347\225\214.md" create mode 100644 "content/article/\346\214\243\346\211\216\345\234\260\346\221\206\350\204\261\345\255\246\347\224\237\346\200\235\347\273\264.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227 Vol-2.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-Vol-1.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-3.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-4.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-5.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-6.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-7.md" create mode 100644 "content/article/\346\217\275\347\211\251\346\227\245\345\277\227-vol-8.md" create mode 100644 "content/article/\346\220\254\345\256\266\345\246\202\344\275\225\345\270\256\346\210\221\347\220\206\350\247\243\347\216\260\344\273\243\344\272\272\344\270\216\346\266\210\350\264\271\347\232\204\345\205\263\347\263\273.md" create mode 100644 "content/article/\346\220\255\345\273\272\346\233\264\351\200\202\345\220\210\350\207\252\345\267\261\347\232\204\344\271\240\346\203\257\346\211\223\345\215\241\347\263\273\347\273\237.md" create mode 100644 "content/article/\346\221\207\346\231\203\345\260\270\344\275\223\347\232\204\345\207\266\346\211\213\345\246\202\346\230\257\350\257\264.md" create mode 100644 "content/article/\346\225\231\345\270\210\347\232\204\345\202\262\346\205\242.md" create mode 100644 "content/article/\346\225\260\345\255\227\346\227\266\344\273\243\347\272\270\347\254\224\347\232\204\346\204\217\344\271\211.md" create mode 100644 "content/article/\346\226\260\346\227\266\344\273\243\347\213\254\347\253\213\345\215\232\345\256\242\350\265\260\345\274\257\350\267\257\345\274\217\346\220\255\345\273\272\347\232\204\346\234\200\344\275\263\345\256\236\350\267\265.md" create mode 100644 "content/article/\346\227\240\344\272\213\345\215\207\345\215\216\344\271\213\347\230\276\347\227\207.md" create mode 100644 "content/article/\346\227\242\347\204\266\346\204\237\345\217\227\346\230\257\347\234\237\345\256\236\347\232\204.md" create mode 100644 "content/article/\346\227\251\351\244\220\345\210\260\345\272\225\345\220\203\344\270\215\345\220\203.md" create mode 100644 "content/article/\346\230\216\347\241\256\350\256\250\350\256\272\347\232\204\350\214\203\345\233\264.md" create mode 100644 "content/article/\346\230\257\346\210\221\345\256\271\344\272\272\350\203\275\345\212\233\345\244\252\344\275\216\344\272\206\345\220\227.md" create mode 100644 "content/article/\346\233\264\351\200\202\345\220\210 P \344\272\272\347\232\204\346\225\210\347\216\207\346\226\271\346\263\225\350\256\272.md" create mode 100644 "content/article/\346\234\200\345\271\264\350\275\273-\346\234\200\344\270\215\350\256\262\347\220\206-\346\234\200\345\217\227\345\201\217\347\210\261.md" create mode 100644 "content/article/\346\234\211\345\244\251\346\210\221\345\260\206\344\270\215\345\206\215\350\271\221\346\211\213\350\271\221\350\204\232\345\217\210\351\252\202\351\252\202\345\222\247\345\222\247\345\234\260\347\224\237\346\264\273.md" create mode 100644 "content/article/\346\234\211\346\211\215\345\215\216\347\232\204\345\220\214\344\272\272\344\275\234\345\223\201\346\230\257\346\200\216\346\240\267\347\232\204.md" create mode 100644 "content/article/\346\234\252\347\237\245\345\205\250\350\262\214\357\274\214\344\270\215\344\272\210\347\275\256\350\257\204.md" create mode 100644 "content/article/\346\236\201\345\256\242\346\255\273\344\272\241\350\256\241\345\210\222\344\271\246-II.md" create mode 100644 "content/article/\346\236\201\345\256\242\346\255\273\344\272\241\350\256\241\345\210\222\344\271\246.md" create mode 100644 "content/article/\346\236\201\345\256\242\346\255\273\344\272\241\350\256\241\345\210\222\347\232\204\350\256\276\350\256\241\345\223\262\345\255\246.md" create mode 100644 "content/article/\346\236\201\347\256\200\347\232\204\346\234\254\350\264\250\346\230\257\346\216\247\345\210\266.md" create mode 100644 "content/article/\346\255\273\344\272\241\346\265\252\346\274\253\344\270\273\344\271\211-II.md" create mode 100644 "content/article/\346\255\273\344\272\241\346\265\252\346\274\253\344\270\273\344\271\211.md" create mode 100644 "content/article/\346\257\224\350\265\267\350\256\260\345\275\225\346\227\266\351\227\264-\350\256\241\347\256\227\344\272\247\345\207\272\346\210\226\350\256\270\346\233\264\346\234\211\347\224\250.md" create mode 100644 "content/article/\346\257\253\346\227\240\345\277\205\350\246\201\347\232\204\347\203\255\346\203\205.md" create mode 100644 "content/article/\346\257\253\346\227\240\346\225\254\346\204\217.md" create mode 100644 "content/article/\346\260\270\350\277\234\344\270\215\350\246\201\346\217\220\351\206\222\350\207\252\346\235\200\350\200\205\345\205\263\345\277\203\345\256\266\344\272\272.md" create mode 100644 "content/article/\346\263\274\345\206\267\346\260\264ADHD.md" create mode 100644 "content/article/\347\211\251\345\223\201\347\232\204\350\247\243\346\224\276.md" create mode 100644 "content/article/\347\216\253\347\221\260\344\270\272\350\207\252\345\267\261\350\277\230\346\230\257\344\270\272\344\272\272\345\274\200.md" create mode 100644 "content/article/\347\216\260\345\256\236\344\271\213\346\257\222.md" create mode 100644 "content/article/\347\224\250\344\270\200\345\274\240\350\241\250\346\240\274\346\216\247\345\210\266\344\275\240\347\232\204\347\211\251\346\254\262.md" create mode 100644 "content/article/\347\224\250\346\226\207\345\255\227\345\237\213\350\221\254\350\207\252\345\267\261.md" create mode 100644 "content/article/\347\224\250\350\247\243\346\236\204\344\270\273\344\271\211\347\234\213\346\212\223\345\250\203\345\250\203.md" create mode 100644 "content/article/\347\225\231\345\255\246\346\216\242\347\264\242\346\227\245\345\277\227-vol-1.md" create mode 100644 "content/article/\347\225\231\345\255\246\346\216\242\347\264\242\346\227\245\345\277\227-vol-2.md" create mode 100644 "content/article/\347\225\231\345\255\246\346\216\242\347\264\242\346\227\245\345\277\227-vol-3.md" create mode 100644 "content/article/\347\225\252\350\214\204\351\222\237\345\271\266\344\270\215\345\245\275\347\224\250.md" create mode 100644 "content/article/\347\234\213\345\212\250\347\224\273\347\211\207\345\246\202\344\275\225\345\270\256\346\210\221\346\217\220\345\215\207\350\257\221\350\200\205\347\264\240\345\205\273.md" create mode 100644 "content/article/\347\235\241\350\247\211\347\232\204\346\227\266\345\200\231\350\246\201\346\212\212\347\210\261\344\272\272\346\212\261\345\234\250\345\267\246\350\276\271.md" create mode 100644 "content/article/\347\247\221\345\255\246\347\232\204\346\227\240\347\237\245\344\277\241\345\276\222.md" create mode 100644 "content/article/\347\256\200\344\270\255\344\272\222\350\201\224\347\275\221\346\234\211\350\207\252\345\267\261\347\232\204\347\214\216\345\267\253\350\241\214\345\212\250.md" create mode 100644 "content/article/\347\256\241\347\220\206\346\227\266\351\227\264\347\232\204\346\234\200\345\245\275\346\226\271\346\263\225\345\260\261\346\230\257\344\270\215\347\256\241\347\220\206\346\227\266\351\227\264.md" create mode 100644 "content/article/\347\273\277\350\211\262.md" create mode 100644 "content/article/\347\276\244\344\275\223\344\270\255\344\270\215\345\255\230\345\234\250\350\207\252\345\276\213.md" create mode 100644 "content/article/\347\277\273\350\257\221\347\232\204\345\220\203\345\212\233\344\270\215\350\256\250\345\245\275.md" create mode 100644 "content/article/\350\207\252\346\210\221\345\210\207\345\211\262\345\274\217\345\210\233\344\275\234.md" create mode 100644 "content/article/\350\207\252\346\210\221\345\244\226\345\214\226\344\270\216\350\241\250\350\276\276\346\254\262.md" create mode 100644 "content/article/\350\207\252\346\210\221\346\204\217\350\257\206\344\270\216\350\207\252\346\201\213\346\203\205\347\273\223.md" create mode 100644 "content/article/\350\207\252\346\235\200\345\212\250\345\233\240.md" create mode 100644 "content/article/\350\213\261\346\226\207\347\275\252\345\220\215\345\260\217\350\265\217.md" create mode 100644 "content/article/\350\231\232\346\213\237\347\244\276\344\272\244\344\276\235\350\265\226\344\270\216\346\201\220\344\272\272\347\227\207.md" create mode 100644 "content/article/\350\242\253\344\270\226\347\225\214\346\212\233\345\274\203\347\232\204\351\224\231\345\244\261\346\201\220\346\203\247.md" create mode 100644 "content/article/\350\242\253\344\272\272\347\261\273\350\207\252\345\267\261\345\211\201\347\242\216\347\232\204\345\244\247\350\204\221.md" create mode 100644 "content/article/\350\242\253\347\254\246\345\217\267\345\214\226\347\232\204\344\275\223\351\207\215\347\247\244.md" create mode 100644 "content/article/\350\255\246\345\257\237\350\255\246\345\257\237\344\270\216\350\255\246\345\257\237\350\255\246\345\257\237\350\255\246\345\257\237.md" create mode 100644 "content/article/\350\256\272\344\270\200\347\261\273\347\224\267\344\272\272.md" create mode 100644 "content/article/\350\256\272\344\273\252\345\274\217\346\204\237.md" create mode 100644 "content/article/\350\256\272\347\213\254\347\253\213\345\215\232\345\256\242\347\232\204\350\257\204\350\256\272.md" create mode 100644 "content/article/\350\257\215\344\270\215\350\276\276\346\204\217.md" create mode 100644 "content/article/\350\257\255\350\250\200\346\250\241\347\263\212\347\232\204\346\230\257\346\200\235\350\200\203\347\232\204\350\276\271\347\225\214.md" create mode 100644 "content/article/\350\257\255\350\250\200\350\241\250\346\204\217\346\225\210\347\216\207\345\267\256\345\274\202\345\257\274\350\207\264\347\232\204\346\200\235\347\273\264\345\267\256\345\274\202.md" create mode 100644 "content/article/\350\257\255\350\250\200\351\207\214\347\232\204\350\241\214\346\230\237\350\212\202\345\276\213\345\222\214\347\245\236\350\257\235\346\256\213\345\223\215.md" create mode 100644 "content/article/\350\267\221\346\255\245\347\232\204\344\270\200\344\272\233\347\273\217\351\252\214\345\210\206\344\272\253.md" create mode 100644 "content/article/\350\277\233\345\205\245\344\270\255\346\226\207\347\232\204\344\270\215\351\200\237\344\271\213\345\256\242\344\273\254.md" create mode 100644 "content/article/\351\200\203\347\246\273\347\213\254\345\261\205\347\224\237\346\264\273.md" create mode 100644 "content/article/\351\200\203\347\246\273\347\276\244\345\261\205\347\224\237\346\264\273.md" create mode 100644 "content/article/\351\207\215\345\244\215\345\234\250\345\211\245\347\246\273\346\204\217\344\271\211.md" create mode 100644 "content/article/\351\207\215\346\226\260\350\256\244\350\257\206\351\243\216\345\221\263.md" create mode 100644 "content/article/\351\222\261\351\203\275\350\212\261\345\210\260\345\223\252\351\207\214\345\216\273\344\272\206.md" create mode 100644 "content/article/\351\227\255\345\230\264\345\220\247-\351\202\243\345\260\261\346\230\257\347\210\261.md" create mode 100644 "content/article/\351\230\205\350\257\273\347\232\204\347\233\256\347\232\204\344\273\216\346\235\245\344\270\215\346\230\257\350\216\267\345\217\226\347\237\245\350\257\206.md" create mode 100644 "content/article/\351\234\207\346\222\274\345\215\263\347\234\237\347\220\206.md" (limited to 'content/article') diff --git "a/content/article/2024\345\271\264-\346\210\221\344\275\277\347\224\250\344\273\200\344\271\210\345\267\245\345\205\267\345\270\256\345\212\251\346\210\221\351\230\205\350\257\273.md" "b/content/article/2024\345\271\264-\346\210\221\344\275\277\347\224\250\344\273\200\344\271\210\345\267\245\345\205\267\345\270\256\345\212\251\346\210\221\351\230\205\350\257\273.md" new file mode 100644 index 00000000..5b91315c --- /dev/null +++ "b/content/article/2024\345\271\264-\346\210\221\344\275\277\347\224\250\344\273\200\344\271\210\345\267\245\345\205\267\345\270\256\345\212\251\346\210\221\351\230\205\350\257\273.md" @@ -0,0 +1,117 @@ ++++ +date = 2024-09-13 +draft = false +title = "2024年,我使用什么工具帮助我阅读" +categories = "生产力报告" +tags = [ "阅读", "每日写作计划α",] +toc = true +aliases = [ "/posts/2024年-我使用什么工具帮助我阅读",] +url = "/essays/2024年-我使用什么工具帮助我阅读/" + ++++ + +目前我使用效率工具的逻辑是,如果有数量一定的个人数据需要管理,我就会使用 Notion 的数据库,尤其是这些数据有一定相似性的时候。 + +自己阅读过或想要阅读的图书就属于这类数据。将一本书视为一条记录,每条记录包含多个数据项,若干记录就组成了一个数据表。以 Notion 为工具,可以这样建造出自己的个人图书馆。 + +![](https://r2.eltr.ac/blog/2024/notion-library.jpg) + +## 用 Notion 建立个人图书馆 + +在这个 Notion 数据库中,每条记录由以下属性组成: + +- **状态**(Status):尚未开始、中断阅读、正在阅读、放弃阅读…… +- **名字**(Name) +- 作者(Author) +- 分类(Category) +- 标签(Tags) +- ISBN:图书的唯一标识 +- 语言(Language) +- 来源(Source):实体书、借阅、电子书…… +- 封面(Cover) +- **开始阅读日期**(Started) +- **完成阅读日期**(Finished) +- **持续时间**(Duration):由前两个属性计算得出 +- …… + +未加粗体部分的属性可能显得有些冗余,但是在必要的时候可以发挥用处。例如可以通过统计各个语言、来源在数据库中的占比,制作出图表直观地看到自己在一段时间里读了多少英文书、占比是多少,哪一段时间里读的电子书比较多…… + +好吧,好像确实用处不大。 + +不过,Notion 最好用的部分并不是存储数据,而是各类视图、操作按钮和公式函数等,能用来处理数据的工具。 + +## 阅读进度的追踪闭环 + +借助 Notion 的「按钮属性」,我们可以将一些较为繁琐的数据管理操作一键化。比如在我的 Notion 图书馆中的「选一本书读」这个视图中,我设置了「开始阅读」这个按钮,按下之后,Notion 会执行两个操作。 + +1. 将这条记录的「状态」设置为 In Progress +2. 将这条记录的「开始阅读时间」设置为现在 + +![](https://r2.eltr.ac/blog/2024/notion-library-pick-a-book.jpg) + +相应地,在「正在读」这个视图中,也有一个「读完了」按钮,按下他之后会一键执行以下操作。 + +1. 将这条记录的「状态」设置为 Finished +2. 将这条记录的「完成阅读时间」设置为现在 + +![](https://r2.eltr.ac/blog/2024/notion-library-done-reading.png) + +利用 Notion 的甘特图(时间轴)视图,可以直观地看到自己近期读过的书,以及各自花费的时间。通过筛选,左侧的列表还能显示出今年读过的所有书籍,方便复盘。 + +![](https://r2.eltr.ac/blog/2024/notion-library-calendar.jpg) + +其中,用于表示甘特图中每个项目持续时间的属性是 Duration,它实际上是一个 Notion 函数,源码如下: + +```formula +if ( + empty(Finished), + dateRange(Started, today()), + dateRange(Started, Finished) +) +``` + +这是一个很简单的逻辑:如果「完成阅读时间」为空,则将「开始阅读时间」作为起始时间,将今天的日期作为结束时间;否则将「完成阅读时间」作为结束时间。 + +## 读书笔记管理 + +在以前,我一直使用 Obsidian 的 Dataview 插件制作书架视图,然后用手动更改 metadata 的方式进行管理。 + +![](https://r2.eltr.ac/blog/2024/old-obsidian-vault.jpg) + +每一本书都有一个主要的笔记文件(和上文提到的「记录」的概念一样,但你可以理解为 Notion 管理数据库,但是 Obsidian 更擅长管理磁盘里的文件),这个笔记文件可能还链接着其他的卡片笔记。当时的我仍在尝试各种笔记方法,没有意识到这样反而让阅读的流程变得繁琐了。 + +现在这个 Obsidian 笔记库已经有了很大的变化,极客死亡计划上的所有文章都是用它编写的。由于 Obsidian 更擅长处理文件的特性,我已经把几乎所有 Markdown 文章的编写都交给了它。 + +在 Notion 的图书数据库中,我将以前的读书笔记原样迁移了上去。 + +![](https://r2.eltr.ac/blog/2024/notion-book-note.jpg) + +这样的笔记算是有好处的,我写了不少自己的理解,未来的我如果看到这些话就能知道这是一本什么样的书。我还写了好多卡片笔记——不过问题就在这里,当我看到那些标题的时候,我一点也不想点进去看。 + +笔记不回顾就没有价值。 + +我目前使用 flomo 来管理所有类型的图书笔记。使用 flomo 记录的过程非常丝滑,用户可以设置打开 app 就自动弹出输入框,如果是 iOS,还可以设置快捷指令。这比 Obsidian 从 iCloud 下载数据,然后再花好几十秒加载仓库要快多了。编辑体验也要比 Notion 好不少。 + +![](https://r2.eltr.ac/blog/2024/flomo-reading-tags.jpg) + +最棒的是它有自带的每日回顾功能,可以自己设置回顾范围和数量,能提醒自己每天回顾笔记。 + +让 App 帮自己决定回顾内容的好处是,自己不需要纠结当天需要回顾哪些内容,不需要看着一个一个的标题陷入选择困难。这就像 YouTube 和抖音,前者需要自己看着封面和标题做选择,后者只需要一条一条往下滑就好了。 + +如果由额外的精力,还可以用 flomo 的相关笔记功能,针对回顾的笔记中自己感兴趣的一条,查看与之相关的其他笔记。 + +至于 Notion 这边,每一条记录里会写上这本书对应的 flomo 标签,方便我找到这本书的笔记。同时,也会简单写上两句对这本书内容的概况和自己的一些评价。 + +![](https://r2.eltr.ac/blog/2024/notion-new-book-note-example.jpg) + +有时候,也会简单列出几条自己觉得有启发性的要点以供参考。 + +## 一些反思和困顿 + +我的笔记体系和我的博客一样,经常推翻重来或者经历大改,但唯一一直保留下来的,就是阅读和写作这两个对我来说最重要的需求。 + +对我来说,目前我的管理方法还有些混乱,尤其是读书笔记经历了 Obsidian+ 导图 + 大纲式笔记 + 卡片笔记这个阶段,再转到用 Notion 和 flomo 两个工具分开管理读书本身和笔记,笔记的内容还是挺乱的。 + +或许我有些过于关注工具的使用了,至少读书这件事情本身我是没有落下的。至于现在的系统要不要改、怎么改,或许还需要一些时间的沉淀和思考,或者,我得找本书来读读。 + +另外,如果你感兴趣,可以通过 [这个链接](https://eltrac.notion.site/d8be16d4974d435dabb0ad77923f00b3?v=8fa9861a863347a7baaef713b8be2c31) 访问我的 Notion 图书馆。 \ No newline at end of file diff --git a/content/article/2025-wrapped.md b/content/article/2025-wrapped.md new file mode 100644 index 00000000..3fec1354 --- /dev/null +++ b/content/article/2025-wrapped.md @@ -0,0 +1,304 @@ ++++ +title = "写在 2026 的开头" +subtitle = "2025 年的真理与自由" +categories = "年终总结" +date = 2026-01-01T00:00:00 +draft = false +toc = true +endnotes = [ "第一节的四个小标题是四句没写完的话,完整版本分别是「我会带着我的观点下地狱去」「创业未半而中道崩殂」「杀不死我的会让我更强大」和「认识你自己」。", "本文六个小节的标题是拉丁文,意思分别是「过去」「真理」「自由」「爱」「黑客」和「结束」,不过第五个词 Hackerita 是我生造的,不是拉丁语也不遵循拉丁语的变化规则。",] +slug = "2025-wrapped" +url = "/posts/2025-wrapped/" + ++++ + +今年排在我的 Apple Music 2025 年度榜单榜首的音乐是 Lady Gaga 的《Abracadabra》,《MAYHEM》也是我今年的年度专辑。总感觉今年没有听太多音乐,或者说音乐已经成为我通勤路上的背景音,对耳机里播放的声音没有了感知。我知道自己需要静下心来多感受,但这显然不是能一蹴而就的。如何获得内心的宁静,真的是很重要的人生课题呢,至少,我现在还处在*混乱*之中。 + +{{< music cover="https://r2.eltr.ac/geedeapro/posts/almanac/2025-wrapped/0-mayhem.png" title="Abracadabra" artist="Lady Gaga" apple="https://music.apple.com/cn/album/abracadabra/1792666546?i=1792667005" >}} + + + +对了,本博客年终总结的惯例是要在开头展示 GitHub 贡献热力图来着。 + +![](4-contribution.png) + +好了,我们正式开始吧。 + +--- + +## 01 | Praeteritum + +这几年养成了一个自我折磨的习惯,就是在每年的年终总结最后留下几个问题,用来拷打第二年的自己,那我就先来看看去年的自己留下了什么问题吧。 + +> 1. 今年,你写博客有什么新的感悟? +> 2. 今年,你的 10 个游戏 prototype 做完了吗? +> 3. 今年有特别想要感谢的人吗? +> 4. 今年发生在自己身上的,最新奇的事情是什么? +> 5. 到目前为止,你认为一生中最宝贵的财富是什么? + +我已经脚趾抠地、虎躯一震,快要脑死亡直接升天了——不仅因为自己提问的方式,还因为有些问题我真的不敢回答。不过,人毕竟不能对自己不诚实。 + +### 我会带着我的观点…… + +> 今年,你写博客有什么新的感悟? + +相比 2024 年,今年写博客的频率的确要高很多,几乎可以说是「爆发」。 + +![](1-wordcount.png "博客的每月字数统计,截取于 2025 年 12 月 30 日") + +极客死亡计划这个博客实际上是在去年七月份正式开始运行的,之前的博客都推倒重来,旧的文章只保留了一部分。*再次*重建博客的契机,应该是[这个旧博客](https://github.com/BigCoke233/Taco)托管在 Vercel 上的时候被攻击了,导致我的 Vercel 免费账号超出使用限额,博客无法正常访问。当我尝试把这个用 Next.js 写出来的屎山代码迁移到别的平台上时,我遇到了各种奇奇怪怪的问题。后来直接放弃折腾,把文章内容迁移到了 [xLog](https://xlog.app/) 这个基于区块链的博客平台,可我在绑定域名这一步遇到了莫名其妙的问题。笔者的计算机网络学得一般,所以没能排查究竟是 DNS 的哪一部分出了问题,在 xLog 的 Discord 上求助也没能得到解决,遂再次迁移,待 Vercel 账号恢复后又用 [Hugo](https://gohugo.io/) 重构了博客。如此辗转之后,博客又在我写完《[我会带着我的观点下地狱去](/essays/我会带着我的观点下地狱去/)》这篇文章之后被打到限额[^1],最后我直接迁移到了 Cloudflare,总算是脱离了无聊人士的骚扰。 + +嗯,所以感悟之一大概就是:真的要把网络安全学好啊! + +写作对思维方式有难以言喻的影响,这和[阅读对思维的影响](/posts/阅读的目的从来不是获取知识/)还不太一样,非常微妙。一个比较直观的变化是,如今的我肯定不会问出「今年,你写博客有什么新的感悟?」这种问题了,因为我要是真的有感悟,那我早就写成一篇单独的文章了,不会单独留到年终总结里来写。 + +既然如此,那就从今年的文章里挑选出一些能回答这个问题的放在下面吧: + +- 《[如何获得取之不尽的写作灵感?](/essays/如何获得取之不尽的写作灵感/)》——好的表达者是好的观察者。 +- 《[愤怒是一种正当的情绪](/essays/愤怒是一种正当的情绪/)》——表达者无需避讳在输出观点时展露情绪。 +- 《[你凭什么往我的咖啡里加糖?](/essays/no-sugar-in-my-coffee/#写作者译者和他们的读者)》——表达者不应沉浸在表达的自嗨情绪里。 +- 《[不做信息的消费者,从写周刊开始](/essays/why-blog-weekly/)》——好的表达者是好的读者。 + +今年我关于写博客的认识,算得上是完善并发展了我去年十一月写下的一篇文章《[自我外化与表达欲](/essays/自我外化与表达欲/)》,我把创作定义为「自我的表达」,而 2025 年,这个博客上除了我自己的思考、我自己的体验、我自己听到的看到的、我自己经历过生活过的,别无所写。 + +### 创业未半而…… + +> 今年,你的 10 个游戏 prototype 做完了吗? + +~~我就怕你问这个……~~ 可以确定的是,一直到[今年四月份](/posts/weekly/26/#-这个月做了什么),我都还在设计一个暂定名为《Subscriptions》(订阅制)的卡牌游戏,而在那之后这场挣扎就停了下来。现在回忆起来,今年五月份刚好是我[搬出宿舍](/posts/逃离群居生活/)的时间,而搬家之后,那些自制的卡牌和骰子就全部放在书架的底层了,随着[第二次搬家](/posts/逃离独居生活/),它们也跟着我到了衣柜的最深处。然而,不管有没有搬家,我都还有两个未完工的游戏源代码放在 GitHub 上,他们也很久没有被我克隆到本地了。 + +所以究竟发生了什么? + +说实话,我不知道,可能是某种内阻力在作祟。虽然我不太喜欢《[夏日幽灵](/library/2025/夏日幽灵/)》这本小说,但其中有一句话的确让我在读到的时候,感到了些许震撼。主角友也本来热爱绘画,但为了不受到母亲的批评,当着母亲的面撕掉了画作,这种行为被他解读为「背叛」,而他的创作欲望也因此溜走。 + +> 或许正是我对绘画的这种背叛行为导致自我厌恶,才使心中的创作欲望溜走了吧? + +我想,我也用相似的方式背叛了自己。 + +> 去年年底,自己为了出国留学(学游戏设计)翻遍了欧洲各个学校的官网,信息多到我感觉自己快要溺死在互联网的北冰洋里;到了今年年初,我却等到一场和父亲的尴尬的谈话(说起谈话,其实是单方面的说教),他反复跟我强调国内的好,在往后的我为数不多的回家的期间,他也不断向我提及「中国就是最好的」,仿佛我这个终于在压抑的国内高校环境里找到一线生机的年轻人,犯了一个可怕的政治错误。我暗暗下定决心要在自己赚够钱之后,为自己支付留学的费用,可我要怎么拿到这笔「Fuck you money」,我究竟应该从事什么岗位、做什么事情,我几乎没有头绪。如果完成学校作业都会让我被完美主义的幽灵附身,神经紧绷,失去对生活的感知,没办法静下心来写一个字,我真的能忍受朝九晚五的职场生活吗? + +{{< right "——《[这个世界会累死完美主义者吗?](/posts/exhausted-perfectionist/)》" >}} + +虽然那个时候的我还没满二十岁,但好歹也是个成年人了,我竟然没有表现出一点捍卫自己理想的勇气和决心,仅仅因为自己和父亲的关系很差,我想要尽可能快地逃离那个地方。我还记得,那个时候我本来拿了一副 Uno 教我弟弟玩,本来要叫父亲一起,可刚上楼,他就把我拉进了那场我不愿意再回忆起、十个月后还令我感到窒息的对话。我认输了,我放弃了留学的想法,我想要快点逃走,回到我的房间里,可是他又指责起我来,指责我没有多花时间陪弟弟,指责我没有一点家庭观念——这样的指责我听过无数遍,我再也不想因为想解释自己而陷入那样可怕的境地里。在高三的某个晚上,我累得只想要吃点东西,在计算机的世界里寻求庇护,可他突然闯过来,问我为什么没有带点吃的给弟弟,我怒了,接下来发生的事情是他把我桌上的奖状卷起来打我的头,我的书桌晃得快要散架,我只想要把它抱住,不让所有东西都散落到地上摔碎。十七岁的我掏出手机已经按下了 1-1-0 三个数字,我的爷爷在旁边大吼「你报警有什么用!」,我才意识到自己只会被民警当作一个不孝顺的小屁孩儿,可当时的我真的不知道还有谁能帮我…… + +几天前,那个男人问我有没有想他,什么时候回家。除了撒谎,我不知道我还能说些什么。 + +人的大脑真是奇怪,理性上毫不相关的事情一件一件联系起来,在潜意识里,竟然成为了阻碍我当下行动的力量,还让正在写这段文字的我浑身发抖,眼睛被泪水糊住。 + +今年总共做了四个游戏原型和 Demo,其中有两个发布在了博客上——《[Expoker](https://www.geedea.pro/posts/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E7%8E%A9%E6%89%91%E5%85%8B%E5%91%A2/)》(一个基于扑克牌设计的桌面游戏)和《[Heart Hunter](/posts/为战斗献上心脏/)》(8-bit 风格的 Rouge-like 游戏;在这个游戏里,子弹、血量和道具都是心脏)。至于另外两个,一个是基于 React 的占星主题的双人对战桌游,源代码在 [GitHub](https://github.com/BigCoke233/warstro) 上,名字叫做《Warstro》,但远远没有做完;另一个就是在开始提到的从未发布的《Subscriptions》,一个借鉴了小丑牌的模拟经营卡牌游戏。我印象中还有一个单人竞速游戏,但源代码和设计文档都不知道被我扔到哪里去了。 + +这么看来其实不算少,但明年会不会继续做游戏,我不知道。 + +行了,快点结束这个痛苦的话题吧。 + +### 杀不死我的…… + +> 今年有特别想要感谢的人吗? + +我记得我在手帐上写 2025 年的新年目标的时候,分了四个板块,前三个是「个人成长」「未来职业」和「健康」(包括身体健康和心理健康),这三个其实达成得都还算不错,但第四个从一开始就是空着的,我根本不知道应该写什么目标,这个板块的名字叫「人际关系」。 + +截止 2025 年 12 月 21 日,这个博客的 [#人际交往](/tags/人际交往/) 标签下一共有 39 个条目,是内容第二多的标签。我回顾的时候才发现,这些内容无外乎是和沟通表达相关的,而那些更感性的内容,也都是在写「我如何挣扎地面对人群」「我容人能力是不是太低了?」,甚至是在批评某些人待人接物的方式。 + +我在教培机构兼职做助教老师的时候,一个学生告诉我,我有一种「生人勿近」的气质。我不是没有反思过这个问题,我只是没能得出答案——是我面对陌生人的小心翼翼让人们觉得我不好接近吗?我确实不太喜欢和人说话,我喜欢和同频的人说话,可如果一开始交流就没有发生,那要怎么找到同频的人呢?我的室友说他有很多工具朋友(他甚至把我评价为一个很「方便」的人),目的是为了让自己不感到寂寞,可我傲慢地说「我宁愿忍受孤独,也不愿意和蠢人打交道」——可见,我俩都不是什么好东西。 + +所以,当我在思索我今年有没有特别要感谢的人的时候,我最先开始思考的是:天哪,我今年和哪些人有过密切的交流?——没有。硬要说有的话,大概就是在今年夏天一不小心爱上的那个直男吧。 + +我逐渐意识到自己是「焦虑-矛盾型依恋」(或许也有些倾向于「焦虑-回避型」)。我渴望亲密,却又害怕被拒绝,或者被冷漠地对待,又或者,我害怕对方做出我难以预料的回应;最致命的是,我倾向于过度解读大大小小的信号,任何一个肢体动作、一个表情、某个措辞上的细节,一旦被我捕捉到,就会立马被大脑自动处理成一个或许天才或许荒诞不经的故事。面对一般人,我已经学会了不去关注言外之意,只处理那些被说出口的话,但面对爱恋,人的脑子是不会清醒的。 + +> 在一颗热情的心里,爱情往往会把最细微的差别夸大,得出最可笑的结论。 + +{{< right "——司汤达《帕尔马修道院》" >}} + +我想,并不是「智者不入爱河」,而是入了爱河的人没法做智者。我翻到今年三月份的日记,我发现那个时候的我真的完全相信他爱我,尽管我写在本子里的原文是「我不知道他想要什么,我真的不知道」。不过,我真的只是被太过强烈的情感冲昏了头脑而已吗?我记得,在我对他的感情真正萌生之前,我就发觉他的言行举止里有怪异之处,所以,在我真正沦陷的时候,才会对假象深信不疑吧。 + +他是一名抑郁症患者。他偶尔会跟我讲起他高中的事情,我大概能感觉到,他在大学里并不快乐,尽管专业排名第一,却还是对未来感到迷茫,最关键的是,他也没有太多朋友,或者说和我一样对人际关系感到手足无措,所以才会时常回忆起高中时代的纯真友谊吧。当时的我忽略了这一点,误把那些在我眼中有些尴尬、暧昧的举动当做爱情,却没想到,那是一个抑郁症患者对友情的渴望。当他终于把话说明白的时候,我感觉我脑子里所有美好的记忆瞬间都有了一个丑陋的解释。 + +在他把话说清楚之前,我做了不少蠢事,但做这些蠢事的主要原因是当时的我也陷入了极难摆脱的抑郁情绪。有好几天,我在骑车上班的路上,都在想,我能不能就这样直接死掉,死在通勤路上,因为通勤的时候我的脑子没有被任务填满,只能任由情绪奔涌而来。不用上班的时候,有好几天,我躺在床上把自己哭晕过去,睡醒之后又打开手机查看消息…… 夏天,对我而言,真的是残忍的季节。 + +我不能在这里把故事讲得太详细,不过,你可以阅读我因为他而写下的十篇文章,已经按照时间顺序排好,时间从今年三月跨越到九月底,真的是很疯狂了。 + +1. [In the Mirror I Get Weak](/posts/in-the-mirror-i-get-weak/) +2. [情绪死锁](/posts/情绪死锁/) +3. [不要把我从你的记忆里抹去](/posts/不要把我从你的记忆里抹去/) +4. [当我渴望拥抱无名的爱人](/posts/当我渴望拥抱无名的爱人/) +5. [自杀动机](/posts/自杀动因/) +6. [夏日逃亡](/posts/夏日逃亡/) +7. [睡觉的时候要把爱人抱在左边](/posts/睡觉的时候要把爱人抱在左边/) +8. [完美幻觉](/posts/完美幻觉/) +9. [余震](/posts/余震/) +10. [当他从当下消失](/posts/当他从当下消失/) + +说到底,我还是很感谢他,即使在我干了这么多蠢事之后,他还愿意跟我把话说清楚。那个时候他把我的 QQ 和微信都拉黑了,如果他没有理会我的道歉短信,我大概会一直陷在纠结、愧疚和苦恼等一系列难以罗列的情绪里。 + +现在我还会在学校里偶尔遇见他,和他打招呼的时候,我非常确定,我已经把那件事情放下了,而他似乎也没有太在乎。 + +*不过,他为什么会在前几天询问我的跨年夜安排呢?该死,我是完全不应该去想这种问题的。* + +### 认识你…… + +> 今年发生在自己身上的,最新奇的事情是什么? + +如今的我不太喜欢「发生在……身上」这个说法,尽管在英文里,「things happen to people」的说法很自然,但在中文里,总给我一种无力感——很多事情明明是我自己选择的啊!无论好事坏事,好处和坏处都得我自己担着,这才是成年人的态度吧。 + +另一件只有小孩子才会做的事情是只选一个。双子座是没有办法只选择一个「最新奇」的事情出来的,我写下这个问题的时候,我真的知道了解我自己吗? + +> 到目前为止,你认为一生中最宝贵的财富是什么? + +谁会问一个二十岁的人这种问题啊?! + +我已经想象到去年这个时候的 Eltrac 如何绞尽脑汁给今年的自己出难题了,我想当时的我怎么也不会想到,今年的我会选择把过去的我狠狠骂一顿,然后用这样一句话结尾:*老子不答了!* + +新年就是要这样嘛,把去年的自己爽骂一顿,然后自洽地走进新的一年。 + +## 02 | Veritās + +![](2-notebook.jpeg "我给 2026 年预备的手帐本的扉页") + +年底的时候总是会开始构思第二年的手帐体系,2024 年年底给 2025 年构想的体系坚持了一个季度,在之后不断更新迭代,和一开始完全不一样了。今年我的设置稍微谨慎了一些,从 2025 年 11 月就开始试行,到现在已经做了不少调整。 + +目前的设置大概是这样的。用一个 A5Slim 尺寸的本子做主计划和周期复盘,计划是从时间和项目两个维度进行的,时间指月度和周度的计划(至于年度计划,怎么能跟 P 人开这种玩笑!),项目是指以结果为导向的任务管理。关于这一本 A5Slim 手帐本的设计,你可以参考《[我全面抛弃了数字记录](/essays/我全面抛弃了数字记录/)》这篇文章。 + +此外,我还在十二月增设了一个 M5 尺寸的手帐本(把一张 A4 纸对折四次的尺寸,比手机还要小一些),用于随身携带,我会每天从周计划里选一些任务抄写在这个本子上,一些习惯打卡也会在这里进行。总之,这个十分便携的本子让我关注「当下」,使用了半个多月之后,我感到它的存在的确让我多办成了很多事情,便签一样的大小也很适合用来收集灵感。 + +具体的介绍我就得单独写一篇文章了。之所以在年终总结里提及对手帐体系的规划,原因之一是我在今年的最后两个月彻底抛弃了数字化的效率工具,把纸笔变成了我的生活方式。另一个很重要的原因是,就算我没有抛弃数字记录,「我如何计划和记录生活」也是一种生活态度的体现。我还在教培机构兼职的时候,我的上司问我是怎么坚持阅读、运动和做计划的,可以分享给学生。我当时不知道怎么回答,因为我从没觉得坚持这些事情很难——这就是我的生活态度吧。 + +不过,这种生活态度具体是什么呢? + +有一次回家的时候,我的姑姑说我过得有些小资情调,又很自律。自律这个评价我听过很多次(我甚至写过一篇[相关的文章](/essays/群体中不存在自律/)),不过,似乎有不少人都把自律想象成一种苦行僧的生活,并对其敬而远之。我想,真正自律的人大概不会觉得自己自律,这并非是出于谦逊,而是因为他真的不觉得自己在逼自己。 + +我在这一年里养成了不少好习惯,尤其是在我在今年五月底[搬出宿舍](https://www.geedea.pro/posts/%E9%80%83%E7%A6%BB%E7%BE%A4%E5%B1%85%E7%94%9F%E6%B4%BB/)过后,我开始自己做饭,也开始关注饮食健康,在十月份读了《[控糖革命](/library/2025/控糖革命/)》之后,我也开始关注食物对血糖的影响。渐渐地,我对奶茶和可乐竟然提不起一点兴趣了!我记得我在一个繁忙的周二点了一杯草莓杨枝甘露,喝了一半,只觉得齁甜,并且对摄入的糖分感受到了非常明显的排斥——我一点也不享受。这种改变不是在一夜之间发生的,它循序渐进,让我一点也没有察觉。如今的我每天都会从一个梅森罐里挖混合着燕麦和蓝莓的无糖酸奶吃,有时会换成羽衣甘蓝粉和奇亚籽,低糖高纤维的食物已经能让我感到很满足了。不过,我依然不会拒绝偶尔胡吃海塞,那也是一种快乐! + +谈到饮食,就不得不谈锻炼。在 2023 年高中毕业之后,我用三个月的暑假减掉了 40 斤赘肉,这也让我一直对身材和外貌很上心,可以说是我 2024 年生活的很大一部分。在 2024 年的年终总结里,我是这样写的: + +> 我从初中开始就被人说丑,高中也一直是在肥胖的困扰中度过的。这样的变化也让我意识到,所谓的帅和美,可能只是一种「生活态度」。只要愿意下功夫,人人都能变得有气质;相反,如果总是自怨自哀,搞不好真的会一直丑下去。 + +{{< right "——《[写在 2025 的开头](/posts/almanac/写在2025的开头/#02--与生活和解)》" >}} + +今年我没那么关注外貌了,去年挑染的绿色头发,也早就被剪掉,换回黑发了。在搬出宿舍之前我只会坚持夜跑(偶尔晨跑),当时只想让自己能更瘦一些。胖过一回真的会给自己留下难以磨灭的痕迹,主要是心理上的,我直到最近才接受自己买衣服竟然可以买 L 码而不是 2XL 甚至 3XL 的事实。也不知道从何时起,我看着镜子里的自己,会觉得自己的手臂太细了,于是这个夏天我开始了力量训练。我当然是没有去健身房和一大群身材比我好的陌生人一起撸铁的勇气的,我也不想花这个钱,所以我主要在家做自重训练和核心训练。 + +九月到十月的时候,我还开始每天拉伸。在十一月份大学生体质健康测试的时候,我才惊喜地发现,自己的坐位体前屈成绩竟然能达到 19cm。尽管有些阴暗,但看着旁边的人颤抖了半分钟才推出去 9cm,真的会觉得很爽。[^2]现在,我虽然还没有到能够劈竖叉的程度,但已经能把额头贴膝盖上,能毫无压力地做犁式拉伸了![^3] + +无论是饮食还是运动习惯,我都没有逼自己。我的睡眠质量也有了很大提升,关于这点,你可以阅读《[如何拥有猪一样的睡眠?](/essays/如何拥有猪一样的睡眠/)》这篇文章,这也是一个循序渐进的过程。所以,这种改变究竟是怎么发生的?就算是循序渐进,也总得有一直支撑着我坚持的东西吧? + +我想,不如浪漫地把它称作生活的「真理」。 + +我之所以刻意地在饮食里添加大量的绿叶菜,并不是爹味地规劝自己说「吃菜对身体好!」,而是在有了相关知识和生活经验过后,得到了一个真理:*自己做饭,拉屎才顺!现在我的大便都能在五分钟内拉完,实在是太厉害了!* + +我的每一个更健康的生活决定,都不是为了「健康」这个抽象概念本身,而是对一种真理的实践。 + +==我不追求硕大的肌肉,因为大是没有止境的,我更愿意像雕塑家一样雕刻自己的身体线条;我不追求热量的消耗,因为热量是短见的,我更愿意像原始人祖先一样靠规律运动维持自己的生命质量;我不追求完全清淡无味的饮食,因为人体本来就需要无机盐和糖分,我相信并听从自己的身体真实的信号、培养自然的食欲,任由贪欲无限生长只会导致痛苦,而这种痛苦我经历过数次;我不关注我面部的缺陷,因为我知道我的情绪、信心和身体状态,能带给我真正有魅力的气场。== + +这是我自己的真理,不是社交媒体上的健身教练为了卖课而传播的观点,不是另一个不是我的人对他生活的态度,也不是任何人的说教,我更不会因为这一点小小的对他人无足轻重的成果就去说教别人。这是我通过学习和实践整合的认知,而这种认知本身又能给我带来驱动力,让我完全不需要靠意志力强撑。不过,同样的真理,放在另一个人的生活里,就不是真理了。 + +比起向人讨教,过着充满戒条的生活折磨自己,不如先像一个什么也不懂的愚人一样去生活,去找到自己的真理。In vita veritas,生命中自有真理。 + +*哦,原来说到底,我还是能够回答「你认为一生中最宝贵的财富是什么?」这个问题的。对不起啦,2024 年的我。* + +## 03 | Libertās + +2024 年是我正式开始规律阅读的一年,而 2025 年也没有丢掉这个习惯。去年,[@Broca](https://brocalife.com/) 送了我一本书,里面附带了一张明信片,上面写着 [IN LIBRIS LIBERTAS](/posts/in-libris-libertas/),是拉丁谚语,意思是「书中自由」。我以此为题写了一篇年度读书总结,今年的话,就不一本一本地盘点了,2025 年的书单都在[这个页面](/library/2025/)里。 + +> 那么,最后,明年的目标是读 40 本书。 + +{{< right "——[IN LIBRIS LIBERTAS](/posts/in-libris-libertas/)" >}} + +这个目标果然是没有达成呢,只读了 38 本。不过也很接近了,十二月我有两本没读完的书,一本是五百页长的《帕尔玛修道院》,另一本是 *The Design of Everyday Things*,我读英文的速度还是有些慢的。如果算上这两本,那勉强能算得上达成目标。 + +那么,明年的目标依然是 40 本书! + +今年尝试了不少新的领域,阅读了更多的外国文学,以前钟爱的日本悬疑推理小说和各种自助书籍明显少了很多(但也有在读),而我涉猎的外国文学又主要集中在法国文学,读得最多的法国作家应该是司汤达和加缪。我对法国文化一直有好感,原因有很多:一是我自学的第二门外语就是法语(虽然到目前还停留在幼儿园水平……);二是我最感兴趣的哲学分支「存在主义」中的代表人物有不少来自法国,人们想起现代存在主义时,时常想象在法国巴黎的某个咖啡馆里,雷蒙·阿隆、萨特和波伏娃正在大谈现象学、人本主义和如何生活;三是,法国文学总给我一种反叛感,这可能与我阅读的作品的年代有关;四是,*加缪实在是长得太帅了,简直是法兰西顶流帅哥,世界上怎么会有这么帅又如此有智慧的男人*。 + +![](3-wallpaper.jpeg "加缪是我 MacBook 的壁纸") + +明年也会继续读法国文学。目前我读的作品主要是以司汤达和福楼拜为代表的 19 世纪现实主义文学,和 20 世纪萨特以及加缪所写的存在主义文学,希望在明年,我至少能勾勒起法国文学的一个整体面貌。今年其实还看了一些拉美文学,主要是马尔克斯的一些作品,还有略萨的《[城市与狗](/library/2025/城市与狗/)》,不过只看了一段时间,一起买的几本看完了就没有继续探索了。 + +此外呢,今年的文娱生活也有丰富起来。今年开始看了一些老电影。翻手帐的时候,我才发现,我在元旦节的时候,看了《香水》这部电影,在二月份看了《马戏之王》,在之后又经历了很长的空窗期,有看《人生切割术》和《办公室》等电视剧打发时间(以及,我应该又重刷了很多遍《老友记》),在十月份我又看了一位博客读者推荐给我的《魂断威尼斯》,写了[观后感](/posts/健康的灵魂是世上最无趣之物/)。当然,也不能忘了在年底播出的《怪奇物语》第五季和 Apple 的新剧《同乐者》,但如果要把每一部剧都盘点完,恐怕也太冗长了。 + +我总觉得自己难以静下心来看电影,如果有较大块的时间和平静的心情,我更有可能选择一本厚厚的书。我更喜欢把看电影当作一种外出活动,因此,当电影院里没有什么让我感兴趣的作品时,我就很少出门看电影。今年出门看电影的次数屈指可数,除了《浪浪山小妖怪》《小林家的龙女仆》和《魔法坏女巫 2》(Wicked: For Good)之外,应该就没别的了。值得一提的是,今年倒是第一次去剧院看了一次音乐剧,是著名的《雨中曲》。 + +写到这里,我想起了 Owen 在他博客里提到的,他的生活哲学。 + +> 追求注意力自由而不是财富自由。 + +{{< right "——[Owen《关于我和这个博客》](https://www.owenyoung.com/about/)" >}} + +能有大把的时间用来看书和欣赏艺术,哪怕是看剧和看电影,何尝不是注意力自由的体现呢?闲暇对人类来说是个好东西,当人如奢侈品般地拥有了闲暇,他就不再为生存而奔波、为别人而奔波。在历史上,某个时期的人们拥有闲暇,也是诞生哲学家的重要条件。希腊语中的 _skholē_,本身是「闲暇」的含义,在后来才演变成了 *school*(学校)。苏格拉底和柏拉图要是每天为了保住工作而忧心忡忡,如今的西方文明就不会是这个样子(当然,苏格拉底也不会背负败坏雅典青年的罪名而死,搞哲学是有代价的)。 + +在《[数字极简](/library/2024/数字极简/)》这本书里,Cal Newport 倡议读者放下电子设备,「重拾闲暇时光」。闲暇不仅是一种娱乐,还是人类所能触及的最高的娱乐,也是自由的真正体现。比起追求有钱,我更愿意追求有闲。尽管这两者在很多时候是绑定的,但仍然是两种截然不同的追求。 + +我想,今年写博客的爆发式增长,和我日渐丰富的精神生活脱不开关系。那么,来年也要做一个思想自由的怪胎! + +## 04 | Amor + +关于爱人,我已经在前文提及过。在二十岁的年纪,不擅长爱大概是可以理解的。我自然不能一上来就装作自己什么都懂,仿佛参透了人性,不然怎么成长呢?这一小节我想谈的并非是对人的爱恋,而是对生活的爱恋。 + +加缪在《[在我身上有个不可战胜的夏天](/library/2025/在我身上有个不可战胜的夏天/)》里写到: + +> 若无对生活的绝望,就无对生活的爱恋。 + +绝望我已经感受到不少,毕竟今年夏天的的确确想在某些时候死去。我想,尽管没有直接的联系,这样的绝望也促使我好好生活。 + +我是个爱好很广泛的人,自然也容易陷入三分钟热度的陷阱。不知从何时起,我已经接受了自己的这个特质,因为我逐渐意识到,我只是在广撒网,那些真正能吸引我的东西,最终还是会留下来,那些不值得我继续花时间的东西,我们也好聚好散。 + +我去年入门了手冲咖啡,在那之后,每个月都花了不少钱买豆子。作为一个 N 人,通过比商业咖啡更注重风味表达的精品咖啡,我的感官能力(Sense)得到了不小的锻炼;品鉴咖啡也是需要调动直觉(iNtuition)的活动,需要发散想象力。总之是很神奇的一种爱好。为此我还写了一篇博客文章,题为《[喝咖啡如何帮我开发自己的 S 属性?](/essays/喝咖啡如何帮我开发自己的s属性/)》。今年冲咖啡没学什么新技巧,也没有换设备(唯一的例外是购入一个带温控功能的手冲壶),但每天早上或中午,都有安静下来冲咖啡这个环节,也算是给我的生活提供了一个支点。 + +从高中就开始探索的塔罗牌,在今年也给我带来了不少新鲜感。和以前比起来,最大的区别是,比起理论储备和探索象征含义,今年我开始更多地给别人占卜。我还在教培机构做兼职上班的时候经常不务正业,导致学生也不干正事,排队来找我算命。占卜师和问卜者之间建立起来的联结很微妙,尽管我不是专业的,但在这种场景下,人们似乎更愿意敞开心扉。这对不善社交的我也是一个较为舒适的与不熟悉的人相处的环境,总而言之,我还挺喜欢的。为此,我还写了一篇《[好为人师如何帮我反思现代科学的局限性?](/essays/好为人师如何帮我反思现代科学的局限性/)》。 + +搬出宿舍之后,我对生活有了更多的掌控感。今年五月份左右,我从四人宿舍搬到了一个单间,麻雀虽小,但我住得还算舒服,就是健身的时候有点伸展不开,书桌也不够宽敞。九月份的时候,我和一个朋友选择了合租,住进了三室一厅,我甚至拥有了独立的书房、被我布置得很温馨的卧室、一个设备齐全的吧台、可以生火做饭的厨房,以及宽敞的空间,让我可以铺上瑜伽垫健身和拉伸。搬家给了我一些焦虑,生活方式的转变总归是让我害怕的,为此,我还写了一篇《[搬家如何帮我理解现代人与消费的关系?](/essays/搬家如何帮我理解现代人与消费的关系/)》。焦虑是难免的,如果生活中没有那些不如意,我现在也不会觉得这个空间让我感到如此安全和舒适。 + +说来说去,我发觉自己说的也不算是对生活的爱恋,到头来,我在今年学到的最宝贵的事情,大概是学会了好好爱自己吧。我现在已经成为了填心理健康问卷时看到「我担心其他人不喜欢我」这种题目时感到困惑无比的人——*怎么没有「我不喜欢其他人」这个选项?* + +{{< gallery >}} +![](5-old-dorm.jpeg "大一时住的六人寝") +![](6-dorm.jpeg "大二搬到了四人寝") +![](8-studio.jpeg "大二快结束的时候搬进了一个单间") +![](7-studio.jpeg "现在大三,住进了自己租的房子") +{{}} + +要说我对以后的生活还有什么展望,就是希望能进早住进一间完全属于自己的家。 + +## 05 | Hackerita + +我似乎从来没有跟人讲过:作为一名程序员,我的启蒙编程语言其实是易语言,一门不入流的中文编程语言。小学的时候,我的成绩还是班级一二名的水准,但我几乎没有朋友,直到中学都还会在情人节的时候跟身边的人讲:2 月 14 日是世界上第一台电子计算机 ENIAC 诞生的日子!那个时候,我最好的朋友就是一台电脑(一台放在现在会令我嗤之以鼻的、装载 Windows XP 的台式机),从十几年前开始,我就无法想象没有电脑的生活了。我记得有一次,我意外地在我父亲新装的一台电脑上安装了病毒软件(那是一台邪恶的装载 Windows 10 的电脑,~~它活该~~),导致接下来好长一段时间内我都没办法使用电脑,那段时间的生活很是沉闷。 + +我想,小学的我之所以走弯路去学了易语言,一部分原因是我直到初中才开发了自己的语言天赋,所以那个时候对英文编程敬而远之。当时的我,只想着做出属于自己的软件,所以选择了当时我认为最简单的路径。每天沉浸在计算机世界里的我,找到了能带我暂时离开现实世界的避难所。直到现在,电子设备对我而言都远远不是娱乐的载体,任何一种技术都不只是为我争得一碗饭的工具,探索本身就足以让我感到无穷的快乐。 + +在我还会跟室友闲聊的时候,我经常跟他吐槽 Java 这门语言有多啰唆、开发过程有多繁琐、性能有多差,并且时不时地赞美 Go,调侃 JavaScript。他们反应是「现在的确有很多公司会招到 Java 工程师之后让他们写 Go」「实验室也有人推荐我学 Go,我当时看他负责的也不是什么重要的项目,就没当回事」「我已经习惯 Java 了,哎,对新东西都有了些抵触」——*他是怎么把计算机描述得这么无聊的?* + +我花了一段时间才意识到一个事实:**他不是黑客**。我说的「黑客」,不是指攻击计算机系统的黑帽黑客,也不是指编程能力高超、掌握了很多技术的程序员,而是那些把探索计算机科学、学习新技术、创造软件和为开源做贡献当作乐趣,不随大流,不接受默认设计,追求技术自由的人。我很快意识到另一个令人沮丧的事实:我的身边没有一个我的同道中人,他们不觉得写代码本身是令人愉悦的——我的室友桌面上有这样一行字「不工作就没有饭吃」;辅导员只会劝学生去参加竞赛,跟着学校做项目、申报课题、写论文,偶尔会在她不知道从谁那里拿到的 PPT 里把 GitHub 描述为一个「学习平台」;他们除了课堂上学到的技术,不会在电脑上下更多的工夫了。 + +我踩着 2025 年的尾巴加入了 Fediverse(联邦宇宙),一个去中心化的社交网络。弃用 Twitter 等大公司软件一年有余过后,我终于又拥有了社交媒体账号。我一开始没觉得加入 Fediverse 是一个很「黑客」的举动,毕竟联邦宇宙很包容。开始在一个能收到更多回应的地方分享自己的想法和折腾之后,我才真实地感受到:有活生生的人对计算机软件有着和我相似的态度,并且已经在我希望走的道路上走了很远了。 + +比如,我只是简单地对自建 Fediverse 实例一事提出了[疑问](https://c7.io/@eltrac/115806971655874632),就引来了一大堆黑客分享经验。分享 RIME 输入法、NeoVim 配置和各种工具的折腾,也都有回响。我想,我大概已经接受了自己暂时无法在现实生活中找到共鸣的事实。做个黑客就跟学第二门外语一样,在现实生活中几乎不能遇到能和自己说法语的人[^4],但只要想,总能在互联网上找到人畅聊语言学,至少能找到听众。 + +我在去年全面转向了苹果生态,把主力机换成了 MacBook。今年,记不清从合适开始,我电脑上安装的软件倍加关注。我会不定期地扫视一遍 macOS 的 Applications 目录,移除那些很久没有使用的,替换那些资源占用过高的。今年,我可以很自豪地宣布,我的电脑上只有两个 Chromium 内核的应用(Obsidian 和 Trae,这两个编辑器都可以在我配置好 NeoVim 之后光荣下岗)。 + +为了保证 Homebrew 包干净整洁,我还用 Go 写了一个简单的命令行工具 [wthis](https://github.com/BigCoke233/wthis),用于以可读性更强的格式显示某个 Formula 或 Cask 的信息(因为我在运行 `brew list` 之后经常发现我不认识的软件包,我不喜欢这种陌生感!)。尽管没有什么技术含量,但遇到问题、产生需求过后自己设计和编码解决问题,的确是很像黑客的思维方式。 + +今年学习的第一门编程语言是 Lua,那个时候还想用 LÖVE 做游戏;今年年底又捡起了 Lua,原因是我要用这门语言配置 NeoVim——*比起 Emacs Lisp,Lua 还是太友好了;不过今年差点就学到了编程界的拉丁语 Lisp,真是可惜呢*。今年学习的第二门,也是最后一门编程语言是 Go,相见恨晚,刚入门就已经爱上。Go 大概会成为我的首选语言,其次是 JavaScript 和 Lua,至于 Java…… 什么不入流的东西?我甚至懒得在 NeoVim 里给他配置 LSP。今年完全没碰的一门语言,是 PHP——*无论如何,你是一门好语言*。 + +Anyway, happy hacking! + +## 06 | Fīnis + +这篇文章的草稿是 12 月 1 日创建的,尽管我写了一万一千多字,但这些内容并不是平均分布在这一个月内的。可以说,这篇文章 80% 的内容是用 20% 的时间写的,而剩下 80% 的时间我都在努力劝说自己挤出时间来写年终总结。出于某种奇怪的心理,我总觉得要是连一万字的年终总结都写不出来,这一年就白过了,而这中焦虑又让我下意识地对打开编辑器感到抵触。当我终于停下来,感觉自己写得足够时,却又觉得没能完全覆盖这一年里发生的大大小小的事情,记录得不够完全。 + +过去的就让他过去吧,我知道,真正重要的东西会以另一种被我的生命本身记住,我会被潜移默化地塑造和改变。只要我的生活还没有浑浑噩噩到每天过得没有什么区别,只要我还能够对技术、哲学和生活本身保持好奇心,我就不需要感到害怕。 + +哦对了,本博客的传统是要在年终总结的最后给明年的自己留几个问题来着。 + +1. 去年的你一直很迷茫来着,现在你有答案了吗? +2. 去年的你探索了 Fediverse,安装了 Nix,折腾了 NeoVim,爱上了 Go 语言,现在的你又做了些什么? +3. 夏天对你总是残酷的,这句话对 2026 年的你依然正确吗? +4. 无论是爱情还是友情,在过去的一年里,你找到你爱的人了吗? + +就这样,用四个问题鞭打明年的自己就足够了。 + +最后,谢谢你读到这里,祝你新年快乐! + +[^1]: 大概是某个读者真的想让我下地狱去吧,还挺艺术的。Kind of poetic. + +[^2]: 比长度什么的,有点太奇怪了吧! + +[^3]: 犁式:要进入犁式,首先要躺在地上,把下半身抬到空中,把脚往头的方向伸,慢慢把脊柱也抬起来,最终用脖子和头撑地,脚碰到地面,腿打直。 + +[^4]: 至少我在身边只能找到觉得外语很酷,于是滥用语言的人,比如我那个室友。实际上,全世界人民都这样,比如英语、法语、西班牙语使用者常常滥用意大利语 bravo,对女性也用这个词,实际上应该用阴性形式 brava。 \ No newline at end of file diff --git a/content/article/A-Librarian-Heart.md b/content/article/A-Librarian-Heart.md new file mode 100644 index 00000000..64c8cc10 --- /dev/null +++ b/content/article/A-Librarian-Heart.md @@ -0,0 +1,58 @@ ++++ +title = "A Librarian Heart" +date = 2024-12-13T16:39:00 +draft = false +categories = "乱章" +tags = [ "塔罗",] +aliases = [ "/posts/a-librarian-heart",] +url = "/posts/A-Librarian-Heart/" + ++++ + +> Steve is very shy and withdrawn, invariably helpful but with little interest in people or in the world of reality. A meek and tidy soul, he has a need for order and structure, and a passion for detail. +> +> Steve is more likely to be a library or a farmer? + + + +——《Thinking, Fast and Slow》 + +简单翻译一下上面那句引用:Steve 非常害羞且内敛,总是乐于助人,但对人和真实世界不感兴趣。一个安静、整洁的灵魂,他对秩序结构有着需求,对细节有着热情。 + +Steve 更有可能是一个图书管理员,还是农民呢? + +这个例子原本是作者用于说明「系统一」的作用的,也就是直觉。但读完这句话之后,我对这个并不存在的 Steve 心生好感,我喜欢这样的灵魂,或者说,我在他身上看到了我自己灵魂的缩影。 + +在一次冥想快结束时,音频引导我「允许自己想任何事情」,我想象了一个图书馆——那里的墙纸是绿色的,上面有古朴细致的花纹,墙壁的边框是深色的木板,书架也是相同的材质;书架之间的间隙很窄,仅容一人通行,我在其间徘徊,没有去到任何一个开阔的、像是大厅和柜台一样的空间,这里就只有书架;当我找到一本好书,我可以在任何地方坐下来读,没有人会来打扰我。在那里,似乎时间也不存在了。 + +(我怀疑我后室的故事写得太多了,但这样的空间应该就是我潜意识的投射吧) + +第一次听到「图书管理员」这个词,是小时候玩 Minecraft 的时候,所以对这个中文词语没有太多感觉,只是一个游戏 NPC 而已。几个月前读的英文书籍变多了,偶尔也见到 librarian 这个词。我对这个词似乎更有好感,中文的「管理员」总让我联想到 administrator,有些冰冷冷的。 + +不知何时,我心中萌生起「做个 librarian 吧」的想法,但只是时不时出现,很快就被我抛之脑后。 + +这个想法出现时,总伴随着轻松美好的幻想,让我感叹「这才是生活啊」。我会想象,在我工作的图书馆里,有一位严肃但非常和蔼的年长女士,她有一头卷卷的白发,还带着单片眼镜,她的服装是绿色的,和她的做事风格一样有条理(我在想,她有没有可能是我小学语文老师的投影)。 + +我们平日里不在图书馆里交谈,但她总是笑脸相迎。她不会强硬的向别人灌输思想,我很喜欢听她讲故事。一位真正拥有智慧的长者——我会这样形容她。 + +我还有一则说出来有些羞耻的想象,出于母语羞涩,我就用英文写出来吧——Maybe I'll be the young hot librarian everybody talks about. 我还想象,或许会有常来图书馆的学生记住我,会有一位面相善良、安静、聪明的男生给我留下印象,但我们之间什么也不会发生,那种停留在想象里的化学反应,足以让我感到快乐。那种快乐,是最让我感到安心的。 + +这是我第一次,真正地注意到我的这种幻想。它揉杂了很多我说不清楚的东西,但它和我立志要追求的东西,似乎相差甚远。 + +我前几天看了好多欧洲的学校,条件反射式地在不同的学校官网搜索 Game Design 相关的硕士项目(就算是陌生的网页,我也非常熟练,先找到 Education,然后找到 Programmes and Courses,然后只看 Master's Programmes,然后再看项目的学费、授课语言、学制,再细看申请要求……)。我看得很累,辅导员问起我的规划之后,也没能提供多少有用的建议,还是比赛、实习、刷分老三样,然后叫找中介多了解一下。 + +我告诉自己,她当然不了解我,我自己的想法很明确,别人的意见听着就好。但我没法骗自己,我谈及这些话题的时候,我整个人都控制不住的发抖,我要很费力才能控制住,不让人发现。 + +有些可怕,不是吗?关在我身体里的、掩盖在理性和外皮之下的,还是个没长大的小孩子,我显然没有照顾好他。 + +抽牌两次,都出现战车牌。我对这张牌的印象一直不好,因为我觉得他带着某种面具,压抑着内心的想法,很是可怕。我对战车所象征的成功表示鄙夷,但显然,我最终还是逃不过。显然,我需要做好「战斗」准备,需要极致的付出,需要不问结果、不计反馈地大干一场。我当然能喊出「他妈的跟你拼了!」这种口号,但当我回归到自己的空间里,我还是会感到害怕,但我又说不清楚自己在怕什么。 + +我似乎渴望到一个没人的地方,就像是意识里的绿色图书馆,做自己的 Librarian。兴许,我也真的希望能够到某个安静的小镇,找一份图书管理员的工作。我似乎不清楚自己想要什么了。 + +我才意识到我现在的状态,确实很像塔罗牌里的战车。战车牌在占星意义上对应的是巨蟹座。我花了好多时间和精力,构建起了一个坚硬的外壳,我的人格面具似乎逐渐成型了,但最近,我在看电影时会有些没来头的忧虑,我在入睡前会难以抑制地胡思乱想;想起几个月前认识的某个男孩,想起自己是怎么和他渐渐地没了联系,想象自己会钻进他怀里哭诉——我心里总归是有什么东西没能得到满足。 + +当我问自己:你真的想要做游戏设计吗?我的答案无疑是肯定的。可是,当这个形象变得具体起来之后,我就开始犹豫。我真的想要去某个游戏公司找工作吗?不想当螺丝的话,你真的有勇气开一家自己的工作室吗?我不知道。 + +或许问题不在于计划和勇气,而在于我不了解自己。就算我知道自己想要,我也没法让自己停止忧虑和害怕。 + +我似乎得想办法,驯服心底那个最不讲理的自己。但我还是不明白,我到底想做一个能被人记住的 Game Designer,还是想做一个安安静静的 Librarian。 \ No newline at end of file diff --git "a/content/article/AI-\346\255\243\345\234\250\350\256\251\344\272\272\345\217\230\345\276\227\345\211\215\346\211\200\346\234\252\346\234\211\345\234\260\350\207\252\344\273\245\344\270\272\346\230\257.md" "b/content/article/AI-\346\255\243\345\234\250\350\256\251\344\272\272\345\217\230\345\276\227\345\211\215\346\211\200\346\234\252\346\234\211\345\234\260\350\207\252\344\273\245\344\270\272\346\230\257.md" new file mode 100644 index 00000000..c3bb60cf --- /dev/null +++ "b/content/article/AI-\346\255\243\345\234\250\350\256\251\344\272\272\345\217\230\345\276\227\345\211\215\346\211\200\346\234\252\346\234\211\345\234\260\350\207\252\344\273\245\344\270\272\346\230\257.md" @@ -0,0 +1,86 @@ ++++ +title = "AI 正在让人变得前所未有地自以为是" +tags = [ "AI", "认知", "编程", "工程", "精选",] +date = 2025-04-02T13:33:10 +draft = false +toc = true +aliases = [ "/posts/ai-正在让人变得前所未有地自以为是",] +url = "/essays/AI-正在让人变得前所未有地自以为是/" + ++++ + +就我所观察到的,人们对于生成式 AI 和大语言模型的讨论中,最值得注意的,是人工智能与人类智慧的关系,例如「AI 能不能代替人思考?」「AI 的思考能力有没有超越人类?」以及「AI 是否拥有真正的思考能力」的问题。 + +我对 AI 没什么负面想法,就像我对我的书桌没什么负面想法一样。这篇文章是一篇批评,但批评的对象是使用和讨论 AI 的一部分人,不是 AI 本身。如果你不清楚两者的区别,请先阅读《[你批评的只是第三者的诠释方式](/posts/你批评的只是第三者的诠释方式.md)》。 + + + +## 你可以站在巨人的肩膀上,但不应该给自己邀功 + +> [!warning] +> 接下来的文字言辞激烈,或许会有些伤人 + +我观察到的一些人,尤其是已经在某些领域有些许作为,拥有某种称号的人,在接触到 AI 产品且读了一些零零散散的关于 AI 的文章、看了些视频,觉得自己把握住了「AI 时代」[^1]的风向标,把计算机和互联网行业的一面墙(甚至是一块砖)当作自己的一间房(甚至是一幢楼),觉得自己可以付出相对较少的时间、精力和金钱,快速地用 AI 在另一个领域有所作为,甚至**不要脸**地给自己冠上另一个称号。 + +其中最让我愤怒的,就是那些对软件开发毫无了解,没有学过任何相关知识,觉得开发软件就是写代码,所以让 AI 帮自己写代码,就可以把自己称作「程序员」了。他们的无知令人发笑,他们觉得一个计算机学生在大学一年级干的事情就是这个行业内所有人做的绝大部分工作。 + +不懂得软件设计的基本原则,不懂得模块化设计,不懂得什么是高内聚低耦合,不懂得任何一种软件过程模型,不懂得需求分析和需求的灵活性以及如何在设计软件时就考虑到灵活性设计,更不懂得软件工程背后的思想,觉得自己花了钱、订阅了 AI 产品,没有一点理智消费者的基本素养就相信了过度粉饰的广告,觉得一个技术等同于实习生的不是人的东西,加上技术和知识储备都不如机器的自己,就能开发出真正的好软件,实际上,这两东西拼起来都凑不出一个好程序员。我在他们言谈和行为中看到的,除了无知,还有一种我怎么也想不明白的傲慢和自负。 + +你他妈的不仅自己在丢人现眼,还侮辱了所有的程序员。 + +你可以用 Cursor 这样的工具把你的好想法[^2]变成现实,但别把自己当成程序员,更别他妈的说,因为会用 AI,自己早上是程序员,下午是作家,晚上是自媒体人这种自负得令人作呕的话了,请停止侮辱更多的群体。你不过是个付了钱,连提示词都不一定写得清楚的用户而已。 + +## 砖头与房子 + +借用梦妮在她的一期播客节目《[普通人想获得点靠谱的知识,怎么还是这么难?](https://podcasts.apple.com/cn/podcast/%E7%A2%B3%E5%9F%BA%E7%94%9F%E7%89%A9%E7%94%9F%E5%AD%98%E6%8C%87%E5%8D%97/id1707385930?i=1000681970666)》作的比喻,在这一节,我想讨论科技和社会发展中的「砖头」与「房子」——它们是什么?为什么要区分它们?为什么有的人不能区分它们,要把砖头说成是房子? + +如果有人发现每天喝咖啡,能在某些条件下预防糖尿病,这样的科学研究就是「砖头」。如果有更多的人做了类似的研究,发现每天喝咖啡在很多条件下都能预防糖尿病,那他们的「砖头」兴许就建成了一面「墙」。如果有更多的「墙」被建立起来,发现每天喝咖啡不仅能预防糖尿病,还有其他的许多好处,证明了咖啡是非常健康的饮品,当然,也有一些喝咖啡的坏处,被这样的「墙」充分证明了,我们或许就能说,这些科学家和研究员,共同地建成了一栋「房子」。 + +为了宣传,或者出于某种「娱乐精神」,或者就是纯粹地蠢,有的人会把「砖头」当作「房子」。当有科学研究得出了「每天喝咖啡可能预防糖尿病」的结论时,他们便兴奋起来,手舞足蹈地按起键盘来报道、张开大嘴喷着唾沫来宣传,也不读研究报告的内容,完全不看文章提到的研究局限性,把「可能」两个字去掉,甚至把「每天」这个条件也去掉了,仿佛要把「咖啡」吹成治疗糖尿病的神药才行。 + +对生成式 AI 也是一样,当有人听到了这些手指在键盘上乱舞、张着大嘴的蠢蛋,他们自己也变成了蠢蛋,觉得那个正在批量产出冗余代码,甚至会忘记自己几秒钟之前写过的东西,遇到从没见过的问题就无能为力的计算机程序,简直是能彻底改变时代的发明,并且自己是极大的受益者。 + +无知者的夸张反应是最大的问题。生成式 AI 或许会成为改变世界的摩天大楼,但他目前顶多是面墙,借助娱乐至死的人们的口水,被吹上天了而已。就算真的了解 AI 的现状,畅想未来 AI 会怎样改变人类也只是科幻小说作家的工作,去干你该干的事情。 + +如果把砖头当成房子,就等着在一个风雪交加的夜晚冻死在砖头旁边吧,不过,更可恶的是,在你死之前,还拉了一大群和你一样无知的人下水。 + +## 别指望 AI 能帮你思考 + +**那些拿 AI 当作自己的第二大脑的人,很可能连第一个大脑都没好好用过**。如果让 AI 生成了一大串回答,仅因为「我觉得很有道理啊」就把它视为可以用自己的嘴复述出来的*思想*(尽管很多时候都是复制粘贴),那这话到底是 AI 说的还是你说的,你到底有没有思考,**你的脑子到底有没有动过**? + +继续这个话题之前,我不得不停下来捋一捋「思考」到底是什么。 + +[一位大学教授](https://hilariusbookbinder.substack.com/p/the-average-college-student-today)在评价当今的大学生时,非常生动地描述了他所认为的大部分学生,是如何完成他交付的阅读任务的: + +> The most charitable interpretation is that they looked at some of the words, didn’t understand anything, pretended that counted as reading, and returned to looking at TikTok. +> +> 最友善的解释是,他们看了一些字,什么也没懂,装作那就算是自己读了,然后回去刷抖音了。 + +其实我觉得他说的不只是大学生,说的也不止是阅读。有的人面对一个问题,**脑子里冒出来一个想法,不用思维去判断其逻辑连贯性,也不用情感去判断其价值取向与自己是否契合,仅仅是觉得这个想法出现的方式、被阐述的方式让自己觉得很有道理,就觉得自己思考了**,美其名曰「通过思考得出了结论」。 + +尽管洞察式的解决问题有不小的作用,但仅仅依靠灵光乍现而不关注其真实性、可行性,也不设想可能性,是不可靠的。更重要的是,这样的思维过程根本算不上思考,最多只能算「运气好」。 + +使用 AI 帮助自己“思考”,其实就是把面对问题时「冒出想法」的概率事件变成了机器计算得出的必然事件,这个过程就算没有 AI 参与也不能算得上思考。 + +如果一个人习惯并善于通过推理和价值取向的判断得出结论,或者是在得到某个想法时用相似的判断方式进行初步的检验,那么他在使用大语言模型时,想必也多半不会抛弃原先的思维方式。而那些觉得 AI 说得有道理,于是欣然接受,甚至当作是自己想法的人,显然不属于此类。 + +一个人若是觉得生成式 AI 为自己打开了新世界的大门,能帮助自己思考,那他多半在使用 AI 之前就没有真正地思考过,因为只有不知道思考是什么样子的人,才会觉得直接阅读 AI 给出的结论能算作思考。[^3] + +## 无辜的 AI 与无知的人 + +今年一月发布的[一篇研究报告](https://journals.sagepub.com/doi/10.1177/00222429251314491)发现,对 AI 了解越少的消费群体,对 AI 产品的接受程度更高(“lower literacy-higher receptivity”)。那些了解算法、训练数据和计算模型背后原理的人,不会觉得科技是什么神秘事物,而其他人,则更有可能觉得 AI 像是魔法一样神秘,进而吸引他们去使用 AI,把 AI 当做法器一样,以为可以带着它去屠龙了,*小心别被路上的小怪灭了*。 + +用 AI 算命,把 AI 当作心理咨询师,就是这种无知的具体表现。就连 AI 所擅长的编程工作[^4],真正的程序员都还在担心 AI 会不会让自己变成文盲,而另一些可笑的人,做着相反的事情,还认为 AI 能让自己变得更聪明,能在一夜之间换一个职业,肆无忌惮地生产垃圾产品污染行业。 + +请认识到 AI 只是一种工具。你并不会因为学会了如何使用 Photoshop 就变成图像处理大师,更何况这个版本的 Photoshop 还只有一个对话框让你输入文字,这是多么反人类的 UI 设计! + +也请认识到,AI 是一个计算机程序。对于一套算法来说,固定的输入总是得到固定的输出,AI 只不过有大量的训练数据输入、你的提示词输入和对话的前后文而已。你的想法作为提示词输入程序,可能连总体输入的 0.01% 都不到。而 AI 生成结果的过程,在底层,不过是大量的概率运算。AI 之所以不能一次性给你答案,是因为它在通过计算不断预测下一个词最有可能是什么。**一味地服从统计学规律,能被你称作思考吗?** + +而那些鼓吹用 AI 代替全部或部分思考的无知者,又引发了另一部分人对 AI 的负面情绪,作为一种中立的技术[^5],AI 真的很无辜。 + + +[^1]: 尚不谈生成式 AI 兴起的这几年时间能不能称得上一个「时代」 +[^2]: 前提是你真的有好想法。**他妈的别再做那些毫无创新的笔记软件和 ToDo 软件了** +[^3]: 我强烈怀疑这些人在阅读 AI 生成的内容时都是跳读且不求理解的。 +[^4]: 请注意编程和软件工程的区别,此外,我认为 AI 无法独立编写完整的项目,至少无法编写设计优良的完整项目。现在还没有能真正将人类语言作为编程语言的 AI 产品出现,就算有,那也仅仅是作为程序设计语言而已,和真正的软件开发还差远了。 +[^5]: 另一种观点是技术都有倾向,不存在中立的技术,但这是另一个话题了 \ No newline at end of file diff --git a/content/article/Blood-Sweetened-Cruelty.md b/content/article/Blood-Sweetened-Cruelty.md new file mode 100644 index 00000000..23ca65af --- /dev/null +++ b/content/article/Blood-Sweetened-Cruelty.md @@ -0,0 +1,118 @@ ++++ +title = "Blood-sweetened Cruelty" +draft = false +date = 2024-12-26T17:20:00 +categories = "乱章" +tags = [ "爱",] +aliases = [ "/posts/blood-sweetened-cruelty",] +url = "/posts/Blood-Sweetened-Cruelty/" + ++++ + +我之前一直在找一个词来形容似乎发生在胸腔内的某种感受,比起「心碎」这个词的痛苦感,它更像是「酸胀」,像是一颗肉球慢慢地向外浸出血来,把甜味和酸味都传入我的神经。 + + + +写作帮我抛下了很多东西,因为我相信文字在被写下的那一刻就死去了。用写作向过去告别,是我的一种「[仪式感](/posts/论仪式感/)」。 + +有一类体验,我很难脱离其影响,它触及我内心非常敏感的东西,每当我谈论它时,我的身体都会不受控制地发抖,我似乎也很难有勇气在公众面前把那些经历和感受用语言再回忆一遍。 + +今天我过得还不错,心里的重担放下了,因为各种琐事而搁置的游戏项目也终于有了不错的进展,所以我想:*为什么不揭揭伤疤毁掉这一天呢?* 于是我就开始写这篇文章了。 + +--- + +## 狼虎之词 + +> "I love you.", ain't that the worst thing you've ever heard? + +—— Cruel Summer - Taylor Swift + +除非是极端幸运,喜欢上直男几乎是每个*小男同*一生中必须经历的事情。我的情况或许有些不同,因为,*我他妈还是个恋爱脑*。 + +或许是金星落在巨蟹座的缘故,我在感情方面表现得像个黑箱,当我陷入某种爱恋的遐想中,我的脑中会不断上演十分幼稚的情节,这些桥段俗套、事后想来也恶心、羞耻无比。 + +和每个经历过监狱式恋情的小学生、中学生一样,我会在课上盯着那个人的脑袋发神。我会把这些情感埋在心里,但也藏得不深,甚至希望对方能够奇迹般地、隐秘地发现并作出回应。 + +要说我干过什么蠢事,那一篇文章估计是数不完的。简单罗列几条的话,大概有:在冬天的时候以取暖为借口把手伸进对方的兜帽下面;在夜晚听歌黯然神伤,几乎是每天给对方分享歌曲,几个月后发现对方其实早就把自己拉黑了;在 QQ 空间发表仅对方可见的动态;发表所有人可见的动态,包含非常明显的暗示,认识自己的所有人都能看笑话;把情书和礼物明目张胆地装在一个信封里放在对方的桌子上,结果对方看到的时候,举起来问身边的人“这是谁放在我桌子上的啊”,然后在众目睽睽之下打开来,看到最后一页写着我的名字…… + +最蠢的,大概是在最后,终于憋不住情感,以质问的语气和架势对峙对方的时候。这种行为,确实很像巨蟹座把藏在心底阴暗、潮湿、抓心挠肺的情感终于爆发出来的情况。 + +对方当然是一脸懵,要么是「我去你居然想泡我」,要么是「我去我早就知道了但你平时都好好的今天怎么一下子就炸了」。面对不实的指控,扣「6」和评价「牛逼」了事的情况也不在少数,不过那确实是因为我的臆想太过天马行空。 + +这种不健康的、和 crush 的相处模式,直到最近才到了头。因为我的心理变得有些「过于健康」,把每一个行为和每一种感受都拆得明明白白,已经不允许自己坠入那种不理智的漩涡里了——*或许,在内心深处,我害怕在我中学时代上演过无数次的剧情,会再次发生*。 + +## 模糊的边界线 + +> 在高中亲过一个喜欢的男孩, +> +> 他懵了,他以为我们是最好的朋友。 +> +> 几年过后的今天, +> +> 凌晨一点, +> +> 他发来短信,邀请我去参加他的婚礼, +> +> 这个点,他是醉了吗?到底是为什么? +> +> 但我知道,我不会去的,我也不会回复, +> +> 只有这样,他留在我心里的, +> +> 才只有美好的回忆。 + +—— 别人的故事 + +跟一些比较关心我情感生活的女性朋友聊天时,我时常跟他们抱怨:我分不清直男的友情和同志的爱情。很多直男看起来与朋友之间正常的互动,在我眼里已经越过某条边界。 + +这里有一个非常微妙,但至关重要的「信息差」。如果你是直男,有一个男同朋友。你知道自己「绝对是直的」,而你认为对方应该了解这一点,所以你认定你们之间只是非常纯粹的朋友关系;从对方的角度来看,他并不能确定「你真的是直的」,因为不是所有性少数都能非常坦诚地公开自己的性取向,说不定他见过不少「已经弯到天上去了」但还是找了女朋友的*小男同*,**对方要怎样才能明白你的「有些亲密」的小举动,不是某种形式的暗示呢**? + +如果你愿意听我的建议的话:不要把身边的男同性恋者当作和其他直男兄弟一样的普通朋友,请保持正常的社交距离,这对你和他来说都好。除非对方表明你不需要这样做,除非你们的友谊非同一般地牢固。 + +当然,我不是在请求你照顾我那些天马行空的幻想。那些能把任何互动都解读为暗示的性缘脑,就让他们自己花时间体会、吃吃教训吧。 + +不可否认的是,同性之间的相处,因为有了不同取向的存在,人与人之间的关系变得复杂起来。(除非你们是一个非常同质的异性恋群体,这种情况下你们的关系应该会非常轻松、直率,挺令人羡慕的) + +## The Four-letter Word + +> "Love" is a four-letter word. +> +> So is "Hate". + +我认为,喜欢的反义词应该是「漠不关心」,而不是憎恨。憎恨和喜欢、爱一样,是对另一个体的非常强烈的情感,它们甚至能够相互转换。 + +走出一段感情的阴影不简单,一个快速的方法是找个能让自己在理性和感性层面都为之信服的理由,让自己憎恶对方。我为了走出一段不健康的爱恋,就曾要求对方撕掉我写给他的三页情书。那天我趴在书桌上哭了好久,但其实我没有真的哭,我挤不出一滴眼泪,因为我一直都知道他对我没感觉,我哭只是为了骗过自己——*那个混蛋伤了你的心,从现在开始离他远点吧!* + +但事实是,从始至终,我都没有放下过。我把他用纸包起来的碎屑放在抽屉深处,骗自己说「这是为了提醒自己不要再犯傻」,但事实是,我丢不掉那包纸,因为我从始至终都没有真正恨过他,我从始至终都没能做到「漠不关心」。 + +好在,这段经历已经过去了足够长的时间,这种混合了各种复杂情感的体验,对我而言已经变成一段遥远的记忆了。 + +## 失智体验 + +如今我害怕再次经历一段感情的原因之一,是我会被剥夺理智。 + +我很讨厌酒吧这样的场所。那天我和一群朋友出游,其中有他。我有一个很会当僚机的朋友,她非常巧妙地把他的位置换到了我旁边。几局真心话大冒险之后,我感到心累。那晚,我被他的眼神、他的言辞和我的想象形成的混沌状态、矛盾局面、理不清楚的事实和感受,和人群的嘈杂声冲得头昏脑胀。 + +晚上我们在 KTV 过夜,他去他朋友家留宿,我躺在又硬又臭的沙发上,已经没有办法思考。半夜我爬起来上厕所,从厕所出来之后,我下意识地跟着从厕所出来的另外两个人找出口,结果对方是从入口进来的,我差点跟着进了女厕,两个女生回过头盯着我,把我当成了变态。我慌张逃离了现场,在心里暗暗地咒骂他,又回去躺在了那张让人浑身不舒服的沙发上。 + +也是在那晚,我又感受到了心口快要溢出来的酸胀感,但其中似乎还参杂着血一般的甜;也就是那晚,我第一次写下了 blood-sweetened cruelty 这个词。 + +那晚,我在自己的笔记软件里写下来二十几条骂他的话,我过度强烈的情绪反应,已经侵犯了我理性的领域。 + +这很可怕,我不想再经历一次。 + +## 当个健康的人好是无趣 + +这是我数次写在便签上的灵感提示。用 [ONO](https://onojyun.com/) 的话来说,我或许是一个「痛苦驱动型」的作者,没了那些体验之后,我已经没办法写出那些拥有强烈情绪体现的自我表达类的小说作品了。 + +读完 ONO 的《[混为一谈的爱](https://onojyun.com/2024/12/12/混为一谈的爱/)》,我很有体会,因为我发现自己真的可以清楚地拆分自己的喜欢和感受。当我发现自己对某人产生好感时,我不会让自己陷入不着边际的幻想,告诉自己「你喜欢的不过是你的想象,你并不了解他」。 + +当我把对一个人的「评价」推迟之后,我就会发现他身上的我不喜欢的特质,进而合理地逃脱。 + +当我发现自己在回忆上一段情感经历时,竟然连一丝丝的惆怅都快消失殆尽的时候,当我发现有人开始把自己称作「阳光大男孩」的时候,当我发现自己在夜里入睡前,竟然不会再在脑海里想象某个人的形象的时候,我才真的发现,自己离那个会在夜里哭三次的我,已经有些太远了。 + +刚开始意识到这一点的时候会有些失落,但现在想想,我的生活已经有了不少值得自己投入的事情,我也能在其他地方找到不错的创作题材,不需要再次陷入那种自虐式的情感当中了。 + +--- + +让我没有想到的是,把一些非常私密的情绪体验写下来之后,我已经不会像以前那样感到难堪了。看来通过写这样一篇文章来毁掉我这一天的目的,还是没有达成啊 😊 \ No newline at end of file diff --git "a/content/article/FUCK-\345\267\245\344\275\234\346\263\225.md" "b/content/article/FUCK-\345\267\245\344\275\234\346\263\225.md" new file mode 100644 index 00000000..b73f406b --- /dev/null +++ "b/content/article/FUCK-\345\267\245\344\275\234\346\263\225.md" @@ -0,0 +1,130 @@ ++++ +title = "F.U.C.K. 工作法" +tags = [ "笔记方法", "效率", "断舍离",] +date = 2025-08-05T21:25:00 +categories = "生产力报告" +draft = false +toc = true +aliases = [ "/posts/fuck-工作法",] +url = "/essays/FUCK-工作法/" + ++++ + +标题显然是对 CODE 和 PARA 等用四字母缩略词作为名称的效率方法论的戏仿,我这么做的理由是: + +1. 我想证明想出一个首字母缩写刚好是一个单词的词组并不难,甚至可以很草率; +2. 我不想否认缩略词让方法论更容易传播的事实,但我想说易于传播的东西([口号](/posts/重复在剥离意义/))和[表意效率](/posts/语言表意效率差异导致的思维差异/)极高的词组,实际上非常容易导致滥用和误解——很多人并不理解 CODE 中每一个单词分别代表什么但依然能够使用;很多人实际上不需要 PARA 背后的思想,没有对应的需求。 +3. 口号和朗朗上口的名字会转移注意力,比如一些读者点进这篇文章大概并不是为了学到什么,而是纯粹觉得 FUCK 这个单词出现在标题里很有趣。这对从事宣传和广告工作的人来说很有用,对一般的表达者来说并不添彩。 + +不过我的确有一些和高效工作话题相关的经验想要分享,如果你还没有被冒犯到的话,就请继续往下读吧。 + +## F.U.C.K. 代表什么? + +我是认真的。 + +### Forget + +人记笔记是为了对抗「遗忘」,这也是为什么「第二大脑」这个概念在笔记圈很火,也很讽刺——人们把想要记住的知识、观点和想法写进了一个并非是自己大脑的「大脑」里,就以为自己记住了它,然而,使用和创造性工作依赖的是真正的理解,光是知道「在哪里能找到它」根本不够。 + +是的,我认为「第二大脑」这个名字具有欺骗性,因为纸笔和耗资巨大开发的软件系统,都不能帮助你形成理解。**知识必须用你能接受的方式经过你的大脑**,就像消化食物一样,放在冰箱里并不会帮你摄取养分。用 AI 总结内容生成笔记的方法更是讽刺,总是让我想起 Rick and Morty 里的某个场面——Rick 和 Morty 被困在太空里太久,Rick 说这个时候吃固体食物可能会让身体休克,于是用消化机器人将食物转化为“营养泥”给 Morty 吃。 + +{{< gallery >}} +![](https://r2.eltr.ac/picgo2025/PixPin_2025-08-04_16-44-58%E5%A4%A7.jpeg) +![](https://r2.eltr.ac/picgo2025/PixPin_2025-08-04_16-45-16%E5%A4%A7.jpeg) +![](https://r2.eltr.ac/picgo2025/PixPin_2025-08-04_16-46-06%E5%A4%A7.jpeg) +{{}} + +这里我要讲的 Forget 有两层含义: + +1. **“忘了吧,你是记不住的”**:承认自己身为人类的局限性,不应该强迫自己记住所有的知识,如无底洞一般的学习欲或许不会让自己的大脑过载,但多半会让自己开始用复制粘贴、AI 总结、“我等会再写”的方式欺骗自己,让自己以为学了很多。 +2. **允许大脑遗忘**:我始终相信大脑会记住它认为重要的事情,人体其实有自带的信息过滤网,就像大脑会自动忘记梦境的具体内容一样。那些不重要的东西,就忘了呗,写成笔记也会在数日后再次感到陌生。 + +可见,F.U.C.K. 工作法的第一条总则便是:去你妈的,老子不学了。 + +至于忘记什么、怎么忘、什么东西不该学,就应该看下一条标准了。 + +### Use + +笔记应当具有实用价值,否则写下来就没有意义。我以前为了让 Obsidian 的知识图谱看起来好看一点,写了很多“我以后就会写”的空笔记,以便享受创造知识网络的快感,就好像我在玩 Minecraft 一样。显然,这种做法就是没有用、没有意义的记笔记,因为我记笔记的原因不是为了用,而是为了满足某种虚荣心,白白浪费了我的时间和创造力。 + +笔记应当具有怎样的作用呢?第一条显然是帮人记住应该记住的东西。辅导员办公室不常去记不住在哪?那就写在备忘录里吧!上司罗列了许多工作需要自己完成怕忘记?那就写在工作笔记里吧!脑子里突然冒出来了灵感和想法?那得赶快记在便签上才行!总而言之,笔记的首要用处和前一条标准相关——防止自己遗忘应该记住的东西。 + +什么样的东西应该记住?答案是有用的东西。如果一个东西你想不出来在什么时候会用到,那就不应该写在笔记里。这里的「用处」其实很主观,也很容易产生自欺欺人的空间——前文提到的「创建空笔记构造知识网络」就是一种主观的「有用」,因为这让我「快乐」。为了防止自欺欺人,记笔记的时候应该关注当下要写下来的笔记本身,而不是整个系统会被构建成什么样子。 + +F.U.C.K. 工作法的第二条总则是:这他妈有用吗? + +### Clean + +当笔记失去了实用价值,尤其是一些临时写下的记录,就应该删除,及时清理,因为笔记存在的意义已经没有了。什么样的情况下笔记会失去实用价值?举个例子,当你为了写一篇小说去调查有关凶杀案的知识,而你知道你自己对侦探题材并不感兴趣,只会用这一次。那么,当小说完成之后,你就应该把相关的笔记都删掉,不管你有多想把它留着。 + +堆积成山的过时笔记和对在屋子里的老旧物品没有什么区别,明明几个月甚至一两年都没用过了,自己却还是觉得「万一有用呢?」「扔了多可惜啊!」不舍得丢掉。过时的笔记若是不及时删除,就会导致这些问题: + +1. **占据存储空间**。我对待所有数据的态度都是如此,我从来没有存储焦虑,MacBook 毫不犹豫买了丐版的原因之一就是——256GB 对我而言真的够用了。我会删掉我所有不想留下的照片,项目文件只会留下最终的版本(如果项目文件在近期不会更新,我会安心地将它保存在 GitHub 或者移动磁盘里,删掉本地的副本),至于笔记——当作品做出来之后,我为什么要留下过程的证明来展示自己的努力? +2. **整理分类的灾难**。如果你没有太多的笔记,就不需要太多的标签和分类,也就不需要在整理这件事情上劳神费心。相反,如果你有各种老旧的笔记堆积在一起,就需要经常调整分类策略和标签系统,来保证过去和未来的自己想法一致,不然标签和分类也会变得混乱,最终你会获得比别人笔记数量都还要多的标签数量。 +3. **助长囤积心理**。换个说法就是「仓鼠症」。当你已经囤了很多不舍得删掉的笔记,那么之后留存笔记的数量和速率只会增加。**当你不再需要用笔记的数量向自己和别人证明自己的努力,转而关心干成的事情和作品的质量时,你将不再需要用一个完美的笔记系统来填补自己一事无成的空虚感。** + +F.U.C.K. 工作法的第三条总则是:这他妈你还留着干嘛? + +### Karma + +Karma 的意思是「因果报应」,这是整个工作法的核心思想——新建一个文件夹、新建一个标签、新建一个笔记、写下一个字之前,都要先三思「如果我这样做了,会对以后产生什么影响?」。 + +如果我容忍了今天的我因为贪恋实用信息带来的满足感,把我原本不需要的笔记放进了我的笔记库里,这会不会加深我对「遗忘」的恐惧?会不会让整个笔记库的实用价值降低?会不会让笔记库变重变乱?你不需要关注这条笔记本身会带来什么影响,而应该关注这个行为会对你的思维带来什么样的影响,就像减肥的时候多吃两口并不会让你长胖,但这么做会助长多吃两口的习惯,长期来看,你的体重和体脂率就会居高不下。 + +F.U.C.K. 工作法的第四条总则显然是我在瞎扯,因为我需要一个 K 开头的单词把 FUCK 凑齐。 + +## 你只需要三个文件夹 + +在这一小节,我将详细阐述有关 Clean 的思想,以及为什么一个干净、简单、有序的笔记库对记笔记来说很重要。 + +我的苹果备忘录里只有三个文件夹(除了自带的没办法删掉也没办法改名的「备忘录」文件夹之外),他们分别名叫: + +1. INBOX(收集箱) +2. WORKSPACE(工作区) +3. HIPPOCAMPUS(海马体) + +名称不重要,重要的是他们分别用来做什么: + +1. **待处理的笔记**:突然冒出来的想法、上司的安排、突然收到的需要一会再处理的事情…… 收集箱的概念相信很多人都已经熟悉了,无需赘述。总之,你需要一个可以倾倒你想法、清空你大脑的地方。 +2. **正在处理的笔记**:正在收集的信息、还没落实的会议记录、某条从「收集箱」里移动出来需要进一步拓展完善的笔记…… 这个文件夹用来存放所有「你正在做的事情」。如果你觉得一个文件夹无法详细分类,那么你可能需要反思一下自己为什么需要给正在进行的事项分类——太忙了?事情处理得太慢了?效率太低了?有的东西,是不是可以跟它说「去你妈的」? +3. **真的需要长期保存的笔记**:亲人的血型、[赞美录](/posts/如何应对他人的赞美/)、人生遗愿清单…… 就像断舍离的时候不能把家中常备的创可贴和药物扔掉,一些近期不会用到但确实有用的信息不应该被删掉,也不应该放在临时储存的「工作笔记」里。一些你在未来一定会用到但不会频繁取用的信息,就可以放在这里,作为大脑记忆的补充。 + +请注意,我没有设置一个用于「归档」的文件夹,因为我相信对于个人知识管理而言,真正重要的东西才需要留存下来。个人不是机构或公司,需要把历史记录放在档案库里,那些不再被使用的笔记就应该删掉,还需要使用的笔记就应该留着,不应该有中间状态。 + +如果你迫切地需要把工作、生活和个人项目分开,那么创建多个「工作区」兴许是有用的。这些工作区可以共享一个「收集箱」,在检查收集箱时,可以将笔记放进对应的「工作区」里,需要留下来的就放进「海马体」里,已经完成的、不再需要的,就删掉。 + +我使用的笔记软件是苹果自带的备忘录,备忘录的好处是删除的内容会自动保存 30 天,这在一定程度上缓解了我的焦虑——即使我真的删错了,我还有一个月的容错时间,这足够了。 + +## 谨慎对待标签 + +本博客的标签已经超过了 100 个,其中有很多标签的词义模糊,不知道具体指代什么,我计划在近期删除和合并不必要的标签,让词义变得更明确。我创建这么多标签的原因之一是我在写文章的时候,会产生一种「我正在探索一个新的话题」的感觉,但实际上我谈的东西可能已经谈过了,只是暂时还没有意识到它们的共性。 + +模糊不清的标签不好。本博客同时存在「English」和「英语」这两个标签,他们的区别是什么?博客的许多文章都有「心理学」这个标签,但我谈的真的全是正经心理学吗?尽管「情感」和「爱」这两个词有明显的词义区别,但我在使用时,真的有分清楚它们吗?博客同时存在「形而上学」「存在主义」等标签,他们都属于哲学,它们和「哲学」这个标签属于包含关系,那为什么「存在主义」或「形而上学」标签出现时,「哲学」这个标签没有一同出现?「技术」这个标签具有二义性,我写的究竟是讨论某一技术的文章,还是把技术当作一种现象和抽象概念来讨论呢(比如讨论「技术是不是中立的?」)? + +标签看似比目录结构更灵活,但也会增加系统的复杂性,让其中的一些部分变得难以解释。另一个事实是,在我的博客里没有几个访客会通过标签来查找文章,这从后台的分析统计可以看出来。我自己不常用,访客也不使用,这种不具有实用性的东西到底还要不要留着? + +不只是博客这样的内容管理系统,笔记的标签管理也可以从中学到一些教训——不要创建你不需要的标签;如果你发现自己很少通过标签查找笔记,要不要试试写笔记的时候不打标签呢?仅仅是因为工具自带了这个功能,别人也使用这个功能,不代表你一定要用它。 + +## 权衡成本与收益 + +人们总是调侃那些花两个小时编写程序来解决两分钟内能手动解决的问题的人,我认为这要分情况讨论。如果这个问题频繁出现且无法根除,那么用两个小时省下无数个两分钟是有益的,但事实往往并非如此。 + +我在折腾个人知识管理系统的时候,遇到的最大问题就是——花在折腾上的时间远大于系统真正造福于我的时间——这个问题是后知后觉的。简单来说,我会花很多时间尝试想出一个完美的目录层次结构、一个完美的标签体系、一个完美的笔记格式或模板,但真正使用的时间很少。一是因为我记笔记没那么频繁,二是因为折腾系统这件事情本身就很上头,让我没心思写笔记,三是因为想象往往与实际出入很大,做好的系统要修修补补甚至推翻重来。 + +如果你发现三个文件夹也实在是太多了,自己根本没心思做分类,或者说花在分类上的时间远远大于写笔记和读笔记的时间,那就「去他妈的」,谁说不能把笔记全部放在一个地方?事实上,只要起好名字,用搜索功能就能更快的找到笔记。 + +## 锻炼真正的记忆 + +F.U.C.K. 工作法这个名字其实是在对笔记这个令人又爱又恨的东西说「去你妈的」。生在古希腊的哲学家柏拉图,早就表达了他对笔记的不屑,甚至是对「书写」的不信任: + +> For this invention will produce forgetfulness in the minds of those who learn to use it, because they will not practice their memory. Their trust in writing, produced by external characters which are no part of themselves, will discourage the use of their own memory within them. You have invented an elixir not of memory, but of reminding; and you offer your pupils the appearance of wisdom, not true wisdom, for they will read many things without instruction and will therefore seem to know many things, when they are for the most part ignorant and hard to get along with, since they are not wise, but only appear wise. +> +> 这一发明会在使用者的头脑里产生遗忘,因为他们不会锻炼他们的记忆。由外部的、不是他们自己一部分的字符产生的对书写的信任,会让他们对自己记忆的使用变得消极。你发明的不是记忆的灵丹妙药,而是提醒的魔药;你向你的学生们提供了智慧的外表,而不是真正的智慧,因为他们会在没有指导的情况下阅读很多,会因此显得博学,然而他们大部分时无知且难以相处的,因为他们并不智慧,只是看起来智慧。 + +{{< right "——[Plato, Phaedrus, page 274](https://www.perseus.tufts.edu/hopper/text?doc=Perseus%3Atext%3A1999.01.0174%3Atext%3DPhaedrus%3Apage%3D274)" >}} + +第二大脑听起来很诱人,但有多少东西是你不能立马从维基百科或者其他网站上搜索到的呢?诚然,你记下的笔记也会被自己遗忘,需要重新阅读才能理解;你自己的思维也一直在迭代变更,读着以前写的东西也难免感到困惑。那么,你曾写下的东西和随时能在网络上搜索到的东西又有什么区别呢? + +我相信真正博学且智慧的人,不会在和你交谈到一半的时候告诉你:「停一停,这一部分我需要读一读我的笔记才行」。即便真的遇到这种情况,那也是因为有些事实类的信息需要查证,与对观点和理论的理解无关。 + +真正追求智慧的人不需要第二个大脑来获得学问,因为他们**懂得善加利用自己生来就拥有的大脑**。 \ No newline at end of file diff --git a/content/article/Fly-Me-To-The-Moon.md b/content/article/Fly-Me-To-The-Moon.md new file mode 100644 index 00000000..ef6a510a --- /dev/null +++ b/content/article/Fly-Me-To-The-Moon.md @@ -0,0 +1,125 @@ ++++ +title = "Fly Me to The Moon" +date = 2024-11-19T23:55:00 +description = "我需要一场距离足够遥远的逃亡" +categories = "乱章" +draft = false +tags = [ "教育", "留学",] +aliases = [ "/posts/fly-me-to-the-moon",] +url = "/posts/Fly-Me-To-The-Moon/" + ++++ + +{{< quotecard >}} +“月球,我想去月球。” + +“为了什么?财富?名利?总得有个为什么吧” + +“我也不知道,就是想去。 +{{}} + +每周一情绪起伏都很大。 + +早上赖了会床起来,大概是七点半,磨好豆子冲了咖啡,便打开 Apple 提醒事项查看自己的清单。例行地备份了数据,更新了放在 Notion 上的理财页面,从抽屉里拿出塔罗抽了周运,把写好的《稻草人周刊 Vol.3》发布了。 + +之后又打开 VS Code 修整博客的外观。我感觉自己像个花匠,要把每处细节都打理到称心才罢休。最近没怎么整理桌子和床铺,大概是因为把注意力转移到网站上了。 + +忙活了大概半小时,总算觉得满意了,隔着耳机听到室友关门的声音,才知道又要去教室了。他们总是提前半个小时出门,而我也总是等他们走了之后再收拾,时间对我来说刚刚好。 + +周一第一节课是 Java 高级程序设计,要见到我一直很不喜欢的一个老师。我一般不想理他,就连在课上看他发在群里的 PPT 我也觉得是在浪费时间。他似乎很自信,这课没教材,说自己曾花了一年时间备课,但我看到的是一些排版糟糕、各个章节之间逻辑连贯性不强、每一部分的内容也很浅的课件。他给的资料最大的用处,就是当作目录和索引,让我知道我应该在网上查什么内容来看。 + +他学的似乎是网络通信相关的专业,其他的我不好说,但他对他教的内容,Java Web 开发,似乎并没有到精通的程度,至少我认为,这种程度要当老师教学生还够呛。他老是犯一些让我觉得愤怒的错误: + +- 他把运行在浏览器里的 JavaScript 中的 `window` 对象看成 `Windows`,然后说这是微软提供的方法。 +- 他在第一节课,以及之后的某些课里,向我们强调英文的重要性(尽管大部分时候我都认为他只是在吹嘘自己并不怎么样的英文能力),比如 IDEA 的界面不要设置中文,就用英文,变量命名也用英文,不知道就自己查。但是,他的英文能力可以说是非常烂。 + - 他做的《Java 高级程序设计》这门课的课件的前缀名是 `GaoChapter`,其中 Gao 是「高」的拼音…… + - 他把产品(product)写成 produce,读成“普罗打死” + - 他的课间里,把 pay 写成 puy,倒是和上面写的 buy“押韵”了 + - 他把 Java 念成 Jawa + - 他把 quartz 念成 crazy + - 他把 jQuery 念成 jKuyi + - 他一会把 var 读成 value,一会又读成“哇” + - 他把 person 读成 po森 + - 他把 session 读成 section + - 他见我用英文写注释,还用到了 javadoc,而且没用 `if-else` 就写了一行布尔表达式,就一口认定我下的「判断三角形是否正确」的方法是在网上复制粘贴的(我数不清他布置过多少次「判断三角形」这种作业了……) +- 他在讲前端的时候(实际上也就某节课提了一嘴)反复说“把界面做漂亮点好伐”,然后接下来就教我们怎么写 CSS 把标题变成“大红字体”。 +- 作为教育工作者,明明可以光明正大地用教育版软件,却鼓励学生在淘宝上购买盗版的软件账号…… + +上他的课我第一次有了逃课的想法,但他偏偏是唯一一个发现学生逃课会把名单报给辅导员的老师。我不知道他哪来的自信,他总觉得自己直觉超强,说自己看一眼觉得不对就知道有人没来齐。于是这天课间,他跟辅导员说他就是觉得人没来齐,本来想点名的嘞。 + +但是点完之后没有人没到。 + +我要是这么写下去,你大概会觉得可笑吧,看着这个本科生像小孩子一样抱怨自己的老师…… 我也觉得自己可笑,明明把自己的生活安排得好好的,只因为台上那个自我感觉良好的男人能对自己指指点点,心情就一落千丈。 + +但我实在难以接受,自己每周要被他浪费 270 分钟的宝贵时间,听他用 20 分钟解释我 5 分钟能理解的概念,然后听他时不时爹味爆发,教我们要怎样过好自己的生活,还发表一下自己对于哪些人应该拿毕业证、哪些人就不该发毕业证的看法,全是不着边际的空谈,没有任何实在的方法和新颖独到的思想。我每次听他讲课,心里都在呐喊:**你能不能不要再浪费我的时间了**! + +--- + +辅导员来查课的这天,我听见她和这门课的课代表交谈,他同时也是所谓的“生涯委员”。辅导员似乎给他找了个活干,他用学校里学到的技术做了一个小项目,用于学校里的某个活动。我又想到之前她也在专业集中时讲过,别的同学做过什么什么项目。 + +我当然承认这些项目对他们专业技能带来的帮助,但我总有一种感觉:**那些被辅导员和老师认可的、有上进心的“好学生”,其实都只是掌握了学校里的「规则」的学生**。我并不是说熟悉并利用规则是任何形式的投机取巧,我只是说这种规则的存在,创造了一种「范式」。 + +只有符合这种「范式」的人才能得到认可和鼓励,要得到这种鼓励,就要努力依照「范式」的思想行事,而不是直接朝着自己的「目标」行事。如此一来,思考自己的「目标」是什么就不必了,只需要遵循「规则」和「范式」就好了,规则就成了自己的目标。这也是为什么我在之前的几篇文章里多次提到「规则」。规则让人感到安心,**因为有了规则,个体就不用思考了**。 + +如果只是存在这样的、无形的规律也还好。最让我感到痛苦的,是「规则是被强制执行的」这一事实,至少在学校这样的秩序中是如此。就算个体不违反规则,不依照规则所暗示的「范式」所行事,在这个秩序下也只能是普普通通、不受认可的凡人。而这样的凡人,是会被视为「不上进」的,会被秩序的维护者视作「摆烂者」「坏学生」的同类,因为无论你在做什么、没在做什么,只要不依照范式行事,你就是「规则的漠视者」,是会被认为「学风不好」的祸根。 + +具体的例子是,那些整日在宿舍里打游戏的人,和那些在校外机构学习、做有助于自己能力提升的兼职、参与开源项目贡献的学生,被视作同类,仅仅是因为他们没有在学校的秩序里做些什么值得褒奖的事情。 + +**正是因为这种「无力感」,让我感受到了异常强烈的逃离欲望**。 + +{{< quotecard rotate="-2" >}}我只是不甘心成为淹没在芸芸众生中的平凡一员而已。{{}} + + +下课后我掏出耳机,播放《For River(Johnny's Version)》,这是我很喜欢的游戏《To The Moon》里具有代表性的一首曲子。听这首时常会让我平静下来,但这天,当我戴着耳机在挤满了人的路上穿行时,我只能感到无力和厌恶。 + +*我要逃,逃到离这里很远的地方*。 + +如果我能回到过去劝高中的自己好好学习,我一定不会说「为了自己的大好前途」之类的话,我一定会说「你绝对不想要在大学还遇到你初高中班主任那样自以为是的人的」。我想象自己一定会被吓到,奋发图强好好学那门我从高二以来就没及格过的数学了。 + +光是逃到那个程度就没事了吗? + +我在校外一家培训机构做兼职,每周都能遇到很多附近 985 高校的同龄人。在我的印象里,那些更好的高校大抵是有更好的教育资源和更好的学风的,但**这些区别足够让我摆脱让我感到无力的东西吗**? + +现在想来,我最厌恶的是「被当作学生」的感觉。 + +在「教师-学生」这一对立关系中,教师似乎拥有某种绝对的约束力,这是「身份」带来的优势,而非资历、知识技能,或者别的什么东西。当然,获得这种「身份」的前提是资历和知识技能,但拥有这些东西的人不一定有「身份」。也就是说,就算学生在任何领域拥有高于教师的智识,教师也因其「身份」认为自己拥有约束力。 + +就算是计算机专业的老师,也必然有自己不熟悉的技术,比如那个因为不清楚 JavaScript 中的 `window` 对象是什么而犯下可笑错误的老师。我从高中开始因为兴趣自学 Web 前端,我自然看出了他的错误。我相信其他学生,若是在空余时间有研究过相关内容,也能发现他的疏漏。 + +我不是说教师必须熟悉所有的知识,关键在于,「教师」的身份给了他们自信,让他们以为自己可以对自己实际上并不熟悉的内容发表意见。当然,这背后的原因可能不仅仅是「教师」身份那么简单,可能还牵扯到「父权制社会」的文化影响——*想象一下过年饭桌上自以为很懂当今政治形势的男性长辈,你就知道我在说什么了*。 + +身份只是一个因素,有的教师并不会因为身份发展出[令人讨厌的傲慢](/posts/教师的傲慢/)。我很喜欢我高一时的地理老师,她讲话时透露着一种「*温柔的严谨态度*」。我记得我有一次问了一个刁钻的问题,题目大概是分析一颗星球是否有生命存在的可能,我将这颗星球的质量和体积与木星作比,又基于「木星主要由气体组成」的认识,得出了「这颗星球是一颗气体行星」的结论,但题目给出的其他条件似乎都在暗示这颗星球很宜居。 + +当我向老师发表了我的看法之后,她回答说「嗯,我认为是这样的」。然后我反问:「那它怎么会有生命存在呢?」。我忘记她之后说了什么了,但那一句「嗯,我认为是这样的」给我留下的印象很深——*「嗯」表示她在意并明白了我的观点,「我认为」则展现出了一种严谨的态度*。 + +*唔,说到底,我厌恶的其实是父权制和部分的男性气质吗*? + +还是别上升到这个程度了,仅从学术的角度来谈,我大概是希望看到更少的傲慢态度和更多的谦逊和严谨吧。 + +你很难不承认这个事实,至少在初中和高中里,包括教师和家长在内的「长辈」都是对学生有偏见的。每个个体的性格、学习方式、目标、心理状况等都有所不同,但在教师的眼里,就被简单、扁平地归类为遵循规则的范式学生,和不在乎规则的坏学生了。 + +我真的认为,**很多老师的想象力过于丰富、思维过度发散、注意力太过不集中,以至于他们在本应该专注于教学的时候,开始想象一个周末只知道出去玩、回到寝室就是打游戏、一天天散漫混日子、没有目标不知进取的学生,树立起这样一个「假想敌」之后,就开始在台上讲些不着边际、毫无逻辑的道理**。 + +这些道理他大概也是从自己的老师那里听来的,他曾经追随的也只是那一个「范式」而已,所以现在选择了留在一个熟悉的环境里——这里有自己熟悉的规则,有「悲壮地学习就能有好日子」的神话故事,有那些能让自己感到「骄傲」的「范式学生」,以及那些让自己抱怨的「非范式学生」。 + +**他们在这样的规则里做着美梦,而我做梦都想逃离这个地方**。 + +{{< quotecard rotate="1" >}} +“你不喜欢人多的地方吗?” + +“我也是" +{{}} + +我深知,凭自己现在的学历是干不成什么事情的,我也对自己能接触到的教育资源持悲观态度。对于考研,我犹豫不决;要是直接找工作,也不想在企业里当齿轮磨灭创造力。现在想,**要是要逃的话,就逃得再远点吧**。 + +于是我便开始收集有关留学的资料,还翻出了之前和 Zeee 的邮件记录,思考自己需要做什么准备。我想,语言对自己绝不是问题,就算是要学新的语言,我也相信我的语言天赋,只要我有足够长的时间投入。 + +但其他的因素又让我感到不安,我的 GPA 并不好看,费用也是一笔不小的负担,关于去哪里、去哪所学校、选什么专业,我也需要花时间做功课,而我现在却被各种琐事缠身,每天晚上还能睡着觉,是因为上床的时候实在太累了。 + +我之所以每天还能抽出时间阅读和写作,是因为那些时间,是我实在宝贵的独处的时间啊。我厌恶人群,路边陌生人自以为是的发言都让我感到本能地排斥,想到这里,我又开始怀疑自己。 + +我的星盘上,北交点落在白羊座。龙女说,北交白羊喜欢泼人冷水,也喜欢泼自己冷水,觉得自己不行,老把自己的机会拱手让人,就是少些勇气。在心里暗暗咒骂不认识的蠢货,我也依稀记得自己好几次跟别人说“你以为自己很行了吗”,我现在明白,那大抵是心理学上的投射——*我觉得自己不行*。 + +这大概是,我这一生必须要解决的课题,**我需要那些没什么来头的勇气**。 + +那么,我想我不应该,光只是做梦了? \ No newline at end of file diff --git a/content/article/IN-LIBRIS-LIBERTAS.md b/content/article/IN-LIBRIS-LIBERTAS.md new file mode 100644 index 00000000..2892b077 --- /dev/null +++ b/content/article/IN-LIBRIS-LIBERTAS.md @@ -0,0 +1,359 @@ ++++ +title = "IN LIBRIS LIBERTAS" +subtitle = "2024 读书总结" +date = 2024-12-12T23:33:00 +draft = false +tags = [ "阅读",] +toc = true +categories = "年终总结" +aliases = [ "/posts/in-libris-libertas",] +url = "/posts/IN-LIBRIS-LIBERTAS/" + ++++ + +收到了 [Broca](https://brocalife.com) 寄来的书,在赠书的包裹里,还附上了一张明信片,上面写着拉丁格言——IN LIBRIS LIBERTAS,意思是「书中自由」。 + + + +![](https://r2.eltr.ac/uPic/2024/12/IMG_2133.jpeg "IN LIBRIS LIBERTAS") + +这份礼物来得恰到好处。2024 年,正好是我 19 年来,读书最多的一年。用它作为我今年读书总结的开头,同时也是我第一次年度读书总结的开头,再合适不过了。 + +## 我与书本 + +我不记得我在 2023 年之前读过什么书,似乎都是一些小说,其中有很多东野圭吾的作品。今年读东野圭吾的《无名之町》,又觉得失望。我记得高中要求阅读的《红楼梦》,我一页都没翻开过,高考那题空着。总而言之,在今年之前,我从没觉得自己是个「读书人」。 + +但我其实一直很喜欢被装订起来的纸张,我喜欢手指触碰到书页的手感,热衷于收集好看的纸品。就像我常买本子不常写一样,书的封面似乎更吸引我。 + +今年的开头,我也一直在读小说。一月,一位友人赠我一本《字母杀手俱乐部》,故事给了我不少写自己小说的灵感。三月,我买了一册江户川乱步的小说集《乱步异人馆》。 + +> 愚人节是开始做一件事情的好时间。 + +我忘记我是从哪读到这句话的了,也不觉得它真有什么道理。但说来也巧,我真正开始像一个读者一样读书,就是在今年的 4 月 1 日。我下载了《如何阅读一本书》的电子版,在我的 iPad Air 上读了起来。 + +现在想想,这本书算是很好的开局。作为我「某种程度上的启蒙读物」,它恰好就是一本教人怎么读书的书。除了读书方法,《如何阅读一本书》还让我在阅读过程中,渐渐地萌生起一种「读者的使命感」。 + +花了一个月的时间,我才读完这本书。在这之后,我的阅读热情只增不减,前前后后加起来,今年读了三十多本书。几乎每本书都对我的思想产生了或大或小的影响。不少书还教会了我很多有用的思维模型,体现在我今年的博客文章中。 + +不夸张地讲,今年读的书,很有可能是我目前为止,读书总量的一半。 + +## 今年的书单 + +接下来,我会把今年我读过的书都列出来,用《如何阅读一本书》里的方法,为你呈现这本书的主旨思想。如果你已经读过这本书,我希望我的视角能给你一些新的想法;如果你没读过,并且读完我写的摘要之后,想要找这本书来读的话,我会很高兴。 + +{{< book title="字母杀手俱乐部" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/s33857152.jpg" >}} + +对我来说是有些新奇的叙事方式,在一条主线里穿插了好几多个无关的独立故事。主线其实没怎么看懂,俱乐部成员讲的小故事有没有联系或者什么深刻的含义,我也不知道。 + +作者对「作家与文字的关系」或许有深入的思考,但具体是什么,我没怎么看懂。 + +{{< /book >}} + +{{< book title="乱步异人馆" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/s34734929.jpg" >}} + +日本悬疑推理大师江户川乱步的作品集,不过真正让我拍案叫绝的故事也不多,书的中间有很多现在看来很普通的作品。比较喜欢《阴兽》《人间椅子》《大青虫》《顶楼的漫步者》《地狱的滑稽大师》《火枪绳》。 + +可以说,读完江户川乱步的作品,我才真正懂得如何欣赏推理文学。 + +{{< /book >}} + +{{< book title="如何阅读一本书" rating="⭐️⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/s1670978.jpg" >}} + +很全面的读书方法论,涵盖了至少 90% 的读书场景。检视阅读、分析阅读和主题阅读的方法,非常受用。 + +此外,作者在写如何读实用类书籍时,写道,如果没有反驳的理由,读完之后按照书中的方法实践,是读者的义务。这样的话看起来死板,但令我印象深刻,也就是我提到的一种「读者的使命感」的来源。 + +{{< /book >}} + +{{< book title="将死未死的青" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212150932675.png" >}} + +之前也读过乙一的作品,这篇的风格很不一样。我喜欢作者对小学生心理的描述,让我感觉「他是真的当过学生」,乙一对主人公扭捏的心理,描述得非常容易令人共情。 + +这篇《将死未死的青》,让我窥见了人类最丑恶也是最令人无奈的一面——从众心。 + +{{< /book >}} + +{{< book title="悲剧人偶" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212151411120.png" >}} + +高中买的,但一直没读。花了两天读完。对于一篇悬疑推理小说,设定在类似豪门和大家庭的背景里,人物关系是最大的亮点。可以说,案件之所以复杂,很大程度上是人物关系复杂。 + +氛围烘托和一点点接近真相的感觉很不错,总之阅读体验是很好的。 + +{{< /book >}} + +{{< book title="路边野餐" rating="⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212151809902.png" >}} + +也是高中买的。虽然是科幻,但对人性的描写其实更多。故事里的男主人公,不太能让我共情。里面有些很酷很厌世的思想,但不太对我胃口。 + +书里的某些话有点像对对人类智慧的羞辱,在外星文明面前不值一提,我很喜欢。 + +{{< /book >}} + +{{< book title="认知觉醒" rating="⭐️⭐️+" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212152206540.png" >}} + +里面有很多流行的思想,但流行不代表对错。了解一下「元认知」「舒适区」「心智宽带」「理智脑和情绪脑」的概念名词也未尝不可。 + +作者自己也承认,整本书的逻辑架构没有很合理,经常在很多章节里提到相同的事情,阅读体验一般般。 + +{{< /book >}} + +{{< book title="暗流" rating="N/A" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212152651304.png" >}} + +读过的除了《哆啦A梦》以外,第一本日漫。 + +朋友借给我看的,看完之后似乎有些感触,但是忘了,大概不重要吧。 + +{{< /book >}} + +{{< book title="在世界上找到你的位置" rating="⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212152839821.png" >}} + +据称是「成年生活的说明书」,书中的建议确实有些用处。作者给我的感觉是一个自认为开明的,尝试理解青年人思想的教育者。 + +整本书其实是从美国人的视角来写的,我印象中还提到了投票权之类的。总之帮助很有限,不太建议读。 + +{{< /book >}} + +{{< book title="无名之町" rating="⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212153223392.png" >}} + +东野圭吾 2021 年的作品。读完很失望。 + +最直观的感受是:比起小说,写成剧本杀或许更有意思。构思很巧妙,嫌疑人有很多,大家也都有动机。故事进展到了最后,作者也很巧妙地把所有嫌疑人集中到了一起,然后逐个击破,最后找出了真正的犯人。真的是很标准的剧本杀配置。 + +{{< /book >}} + +{{< book title="卡片笔记写作法" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212153415681.png" >}} + +喜欢折腾笔记软件的人怎么可能不读这本。 + +但说实话,比起卢曼的卡片盒,这本书对我帮助最大的反而是那些思想上的东西。比如「自以为心胸开阔的人反而更容易固执己见」「不要只看到自己的想法,要看到文本实际所表达的意思」等等。 + +{{< /book >}} + +{{< book title="诱惑的艺术" rating="⭐️⭐️+" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212153740352.png" >}} + +表白被拒之后买了这本书(咳咳 + +最大的感受:太长不看。这本书我确实没读完,作者做了很多分类,每部分都写了很多故事,方法论也很牵强。有意思的观点当然不少,但浓度太低。如果喜欢读故事的话,这本书里有不少。 + +{{< /book >}} + +{{< book title="被讨厌的勇气" rating="⭐️⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212154031509.png" >}} + +这是一本写给大众、有关阿德勒心理学的书籍,采用了常见于古典哲学的对话体,语言通俗易懂且容易代入。 + +基本没有阅读门槛,是很好的心理学启蒙读物。有很多思想值得反复品味,比如「可以带马去水边,但不能强迫马喝水」。 + +{{< /book >}} + +{{< book title="晨间日记的奇迹" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212154425269.png" >}} + +小小的一本书,一天就读完了。 + +最有启发的一点:早上复盘前一天的工作和学习是最好的。这个时候既没有忘记感受,也不会太情绪化。 + +{{< /book >}} + +{{< book title="Steal Like An Artist" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212154631292.png" >}} + +「原创只是未被发现的剽窃」 + +这本书教读者研究思想而不是学习形式,如何 Fake it 'till you make it,以及其他很多适用于各类创作者的思想和方法论。 + +{{< /book >}} + +{{< book title="生活黑客" rating="⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212155034791.png" >}} + +偏向社会研究的书,写了很多事例和故事,而且写得挺无聊的,大概就是有哪些人是生活黑客、他们干了什么,然后做了一些莫名其妙的分类。 + +没太多方法论,我想不出来有谁会需要看这本书。 + +{{< /book >}} + +{{< book title="手机大脑" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212155908976.png" >}} + +让我第一次接触到了进化心理学相关的概念。 + +虽然名字看起来只和手机有关,但实际上也能学到不少有关脑科学的知识。有不少内容是我觉得现代人都应该了解的,推荐阅读。 + +{{< /book >}} + +{{< book title="The Hacker's Diet" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212160225866.png" >}} + +没出版的电子书,作者很厉害,是 Autodesk 的创始人。他用计算机和工程学的思想控制自己的体重,这本书讲他使用的系统,这套系统帮他在短时成功脱离肥胖,并且没有反弹过。 + +但书里的很多思想其实能在很多现在的减肥博主那里听到,书本有用,但如果你不想读也可以去网上搜其他的视频。 + +{{< /book >}} + +{{< book title="78 度的智慧" rating="⭐️⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212160624675.png" >}} + +学塔罗一直没读过书,这是第一本。 + +作者把占卜和心理学概念联系在一起了,同时这本书也重塑了我对四元素、78 张牌的认知。作者对整个塔罗体系的理解,甚至可以轻易拓展到其他领域,我在读其他与塔罗无关的书时,也能想到这本书的内容。 + +{{< /book >}} + +{{< book title="你的善良必须有点锋芒" rating="⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212214816941.png" >}} + +茶余饭后拿起来读读是很好的,但整体上主旨没有很清晰,尤其是后面一部分,似乎是大杂烩什么都有。要说是「心灵开悟书」倒也算吧,但似乎和「有锋芒的善良」关系没有很强。 + +作者主要的主张是应该在保持善良的同时多考虑自己的感受,清楚地表达自己的想法,让沟通交流更加顺畅,在对别人好的同时也不委屈自己。 + +{{< /book >}} + +{{< book title="非暴力沟通" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212215130604.png" >}} + +这本书的方法论其实很明确,作者很早就开门见山给出了主要观点:非暴力沟通的四个要素是观察、感受、需求和请求。这四个要素同时适用于讲话和倾听。 + +不过作者的语气会显得有些「站着说话不腰疼」,但给了很多事例,读起了也令人信服。我认为这是一本好书,不长,而且没有什么废话,几乎每一章的内容都非常有启发性。 + +{{< /book >}} + +{{< book title="疼痛部" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212215422560.png" >}} + +如果你想知道战争除了杀死人、让人流亡、无家可归之外,还会对人做些什么,可以读读这本小说。作者从语言(以及文学)作为切入点,讨论文化的死亡。 + +题外话:书名「疼痛部」是小说中只出现了一次的一个*SM俱乐部*的名字。我读完也没搞明白这本书为什么叫这个名字。 + +{{< /book >}} + +{{< book title="厌女" rating="⭐️⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212215609764.png" >}} + +印象最深刻的是有关「男性同性社会同盟」的论述,很有启发性,作者还把这个概念和「厌女」及「恐同」联系起来,逻辑很紧密。 + +总之是一本把厌女讲得比较透彻的书,但是只涉及到厌女这一部分,而不是女性主义。如果希望说服别人,这本书不是很好的教材,自己读的话会有启发的。 + +{{< /book >}} + +{{< book title="思辨力35讲" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212220241867.png" >}} + +一本讲逻辑学和思辨力的书,给出了很多日常生活中的例子,便于理解,是很不错的逻辑学入门书籍。 + +{{< /book >}} + +{{< book title="翻译研究" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212220431164.png" >}} + +两三年前 Broca 推荐给我的,之前没读完,今年捡起来重读。 + +这本书令我印象最深刻的,其实不是「翻译」,而是「怎么写中文」。这本书又让我意识到,有很多自然而然说出口的话,其实收到了潜移默化的西文影响。有很多诸如字眼,比如「一个」这样的量词,很多时候完全不必要。读完之后,我开始有意识地审视自己写下的文字。 + +{{< /book >}} + +{{< book title="算法之美" rating="⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212220855904.png" >}} + +用计算机科学和算法的思想解决生活中的实际问题,实际上是非常有意思的一本书。 + +但作者废话太多了。不仅写得啰嗦,而且本来是明摆着要写方法论的,写得又不完全,给人一种「你再多讲一两句总结的话,我就知道我该怎么做了」,而作者偏不,写一半就停了让你自己感受,或者是讲点别的东西绕一绕。不明不白的让我在读的时候像胸口有东西在抓一样难受。 + +再者,自己是学计算机的,所以书里讲的很多东西,我其实懂,所以有的时候会嫌啰嗦。但遇到不懂的,又嫌他讲得不够清晰,还得自己去搜维基百科才能明白。如果你没有计算机相关的基础,兴许读起来会感觉不一样。 + +{{< /book >}} + +{{< book title="How to Deal With Idiots" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212221336611.png" >}} + +~~学到了很多 idiots 的同义词~~ + +作者花了很多时间讲「为什么」,具体的方法一般是收尾的时候才提及。但无奈,我的英文阅读能力还不足以支持我认真读完那些多少有些弯弯绕绕的长篇大论。不过,如果认真读的话,能学到除了方法论以外的很多为人处世的底层逻辑。作者在哲学方面的造诣应该不低。 + +{{< /book >}} + +{{< book title="Atomic Habits" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212221725746.png" >}} + +风格其实和认知觉醒很像,毕竟也标榜畅销书。 + +一本实用类型的书,讲如何养成好习惯、戒除坏习惯的书,作者提供了多种理论模型和实践方法,很值得一读。尤其是 cue-craving-response-reward 的思维模型,非常受用。 + +{{< /book >}} + +{{< book title="娱乐至死" rating="⭐️⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212221918261.png" >}} + +上世纪的书,就算放在现在,也具有十足的批判意义。 + +主要观点是,真理不能,也从来没有毫无修饰地存在。传播媒介会影响认识论,媒介也是真理的一部分。技术不是中立的,技术有自己的倾向,这种倾向造就了媒介。现如今有关短视频看多了容易变成二极管的论调,并非没有来头,正如上世纪沉迷电视的人们不如以往热爱读书的人聪明一样。 + +{{< /book >}} + +{{< book title="素食者" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212222247468.png" >}} + +今年诺贝尔文学奖得主韩江的代表作。 + +小说里经常出现「短短的一句话反映了多惨酷的社会现实啊」这种句子,作者一定是深有体会,才能用那样的细节打动读者。三个故事也提供了三个不同的视角,故事叙述者的不同身份也让整本书的思想更加立体。 + +{{< /book >}} + +{{< book title="数字极简" rating="⭐️⭐️⭐️" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212222616104.png" >}} + +提到了不少和《手机大脑》相似的观点,不过这本书并不是从脑科学和进化心理学的角度来谈的。 + +这是一本讲解何为「数字极简主义」的书,意图通过重新思考人与技术的关系,严谨且有目的地改善手机等数字产品的使用,来帮助读者获得更高的工作效率和更好的生活。这本书还提供了很多的实践方法,能够帮助读者更合理地利用科技。 + +{{< /book >}} + +{{< book title="Thinking, Fast and Slow" rating="N/A" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212224017306.png" >}} + +大名鼎鼎的《思考,快与慢》,和许多畅销书不同,这本书有很多深刻的、基于一手研究资料的思想,但写得很通俗。 + +不过这本书我只读了前面一点,因为年末事情多起来,就没什么脑力读英文书了。等之后读完了,再做评价吧。 + +{{< /book >}} + +{{< book title="乌合之众" rating="N/A" + cover="https://r2.eltr.ac/uPic/2024/12/image-20241212224247701.png" >}} + +现在正在读的书,没读完先不评分。 + +这是一本讲群体心理学的书。当数个个体满足某些条件,形成一定的连接之后,就会形成心理学意义上的群体。在群体中,无意识会占主导,个体的理性思考会受到压抑。群体受到情绪和简单观念的驱使,很强大,但其实并不讲道理。 + +{{< /book >}} + +还有一些书,读了一部分没有继续读,或者是因为实在感兴趣,先做了检视阅读,准备日后细度。这不是个好习惯,要改。 + +## 阅读为我带来了什么 + +读完《[影子幽灵与植物人类](https://www.velasx.com/am/6309)》,我既佩服,也羡慕 [Zeee](https://www.velasx.com) 能如此自然地写出这样的文字。在我表达了我的感受之后,他说: + +> Eltrac 现在的创作方向其实是我不擅长的,我也很羡慕那种观点明确、逻辑严谨的写作方法。 + +Zeee 说他写作不会提前列大纲,其实我也不会。之前还在逛别人的博客时,偶然看到有人评价自己是一个很「严肃严谨」的人。看到这样的评价固然很开心,但开心之余,我也会反思,为什么我会给人留下这样的印象? + +我认为,文章之所以能给人留下观点明确和逻辑严谨的印象,是因为写文章的一开始,我就是「带着观点去写作」。我往往是有了一个灵感的苗头,然后就着感觉一口气写下去。在这个过程中,若是没有相应的知识储备,没有大量阅读所塑造的思维方式,没有对「文章应该给读者什么样的阅读感受」的印象,我是无法做到的。 + +可以说,阅读锻炼了我对文字的直觉。这个过程,说是一种「熏陶」,完全不足为过。知识的增加是一时的,直觉,甚至是体现在语言中的气质,才是能够长期发挥效用的。 + +不过,我其实很讨厌被当作书呆子,我也不想把自己框定在非虚构写作和严肃文学的范围里。我想明年,我应该读更多小说,同时也更广泛地输入以电影和游戏为载体的故事。毕竟,我的目标可是游戏设计师啊! + +那么,最后,明年的目标是读 40 本书。 + +祝阅读愉快。 \ No newline at end of file diff --git "a/content/article/Manjaro \346\241\214\351\235\242\346\212\230\350\205\276\350\256\260.md" "b/content/article/Manjaro \346\241\214\351\235\242\346\212\230\350\205\276\350\256\260.md" new file mode 100644 index 00000000..fca8d25d --- /dev/null +++ "b/content/article/Manjaro \346\241\214\351\235\242\346\212\230\350\205\276\350\256\260.md" @@ -0,0 +1,158 @@ ++++ +date = 2024-02-14 +title = "Manjaro 桌面折腾记" +tags = [ "Geek", "Linux", "旧博客文章",] +categories = "代码炼金术" +url = "/posts/Manjaro 桌面折腾记/" + ++++ + +我的本科导师在大一刚开学,还未正式行课的时候,给我们发了一份二十多页的 Word 文档,要求我们在两周内按照文档的指导自行安装 Windows 和 Manjaro 的双系统,原因是程序设计作业需要在 Linux 系统上编写、调试和运行。 + +我向来不喜欢未经思考就接受别人交给我的任务,所以当我面对这一个多少有些强人所难的要求和一份三十多 GB 出头的定制系统文件时,我是很抗拒的。 + +于是,当天我就尝试了 Arch Linux 的 WSL(Windows Sub-system for Linux,适用于 Windows 的 Linux 子系统)和虚拟机安装 Manjaro 系统这两个自以为聪明的方案。除了个别基础不错的同学,其他不少刚接触计算机的大学生连续几周都被安装系统这个任务搞得心神不宁,而我还泡在自己的舒适圈里,在 Windows 11 系统上畅玩各种电子游戏。 + +故事讲到这里,你一定会期待一段这样的情节——一个刚获得些许自由的大学生我行我素,最后被残酷的现实击倒在地,开始后悔自己为什么没有早点醒悟。 + +好吧,或许你没有,我也没有为了我自己的决定后悔。安装双系统的做法的确不太聪明,不但麻烦,真正发挥用武之地的地方又很少,只能算是一个对大部分人都有效的解决方案。*而当我掏出我的第二台笔记本电脑,阁下又该如何应对?* + +## 冷淡的接待 + +我有一台陪伴了我整个高中的戴尔灵越轻薄本,在我毕业之后光荣退役,因为我有了一台性能更好的游戏本。于是这台笔记本一直闲置了好几个月,不过这下终于有用武之地了。我决定在这台并不常用的电脑上安装 Manjaro 系统,以应付作业的需求。 + +由于我打算完全抛弃之前旧的 Windows 系统,安装一个单独的 Manjaro 系统,而导师提供的文档却只给出了双系统的操作指导,其中涉及到各种复杂的分区,大部分内容对我没有太大的参考价值。于是我先根据文档制作用于安装系统的启动盘,我得先从 Manjaro 官网上下载 KDE 版本的系统镜像,然后用 Ventoy 和一个 U 盘制作启动盘,系统安装好之后再把导师发在群里的三十多个 GB 的系统快照在安装好的新系统上恢复,省区自己安装软件的麻烦。 + +**不过我很快就把自己唯一的 U 盘搞坏了。**大概是在操作时出现了失误,又或是什么令人摸不着头脑的问题,我在按照教程使用 Ventoy 制作启动盘时,软件弹出了一个文档中没有提到的报错,然后我发现我无法在 Windows 中访问 U 盘了。于是我格式化 U 盘后并重新设置了分区,好在这个盘里没有什么重要数据。但第二次尝试的时候还是发生了同样的错误,第三次、第四次也一样。最后我还是放弃了,借用了室友已经制作好的启动盘。 + +后来我又照常使用这个被我格式化数次的 U 盘,结果在好几次拷贝文件的时候发现文件损坏。直到一次上台展示的时候,发现自己做好的 PPT 无法打开,才意识到这个 U 盘已经没办法正常使用了。我至今也没弄明白是哪一步出了问题。 + +由于 Manjaro 的安装程序有图形界面,只需要一些简单的配置就可以自动安装。我打算直接抹除原来的 Windows 系统,Manjaro 也在安装时提供了直接覆盖原系统的选项,不过我常试了几次都报错,表示无法正常安装。具体的细节我已经因为过了太久而遗忘了,但我记得我百思不得其解,被这个错误搞得焦头烂额,最后又在导师给的文档里找到了答案——**好嘛,是我没改 BIOS 设置**。 + +在全英文还没法用鼠标控制的界面了找了好久,我终于找到了正确的设置项。之后便顺利地安装好了,没出什么差错,只是我才发现导师给的那三十多 GB 的系统快照是双系统的结构,也就是说,本质上我得在自己的机器上百分百还原他电脑的文件分区,然后把他系统里所有的文件恢复到我的电脑上。而我并没有装双系统,所以这个快照我是用不了的。 + +不过系统都装好了,软件什么的自己装就好了。 + +## 吃豆人欢呼 + +Arch Linux 的软件生态在各大 Linux 发行版中算是不错的,许多人选择 Manjaro 也是因为它是基于 Arch 开发的。尽管国内大部分桌面端应用只提供了更常见的 `.deb` 包,以供国产系统 deepin 和麒麟使用,但因为 AUR(Arch User's Repository)的存在,Arch 用户可以将适用于 Arch 发行版的软件包发布在所有人都可以访问的公共仓库中, 而 AUR 可以用 `yay` 这个命令行工具直接访问。 + +也就是说,如果一个软件包没有被收录在 `pacman` 能够访问的 Arch 官方库中,**用户仍然能通过 AUR 安装社区维护的软件包**。 + +对于 Arch 用户来说,使用 `yay` 访问 Arch 官方库和 AUR 安装软件是最好的选择,但当时刚接触 Linux 软件生态的我什么也不懂,导致我安装软件的方法十分混乱,大概可以这样描述: + +1. 在 Manjaro 提供的软件管理器中搜索,如果有,就安装这里的包; +2. 尝试用 `sudo pacman -S 包名称` 搜索这个包; +3. 如果软件提供了 AppImage,则使用 AppImage Launcher 安装; +4. 直接从官网上下载 `.deb` 包,强行安装在 Manjaro 上(**千万不要这么做,可能会损坏软件包的依赖关系!**) +5. 使用 `flatpak` 和 `flathub` 安装软件包。 + +由于之前没有发现 `yay` 这个好用的工具,而且发现了之后也不会上 AUR 查找软件包,所以在刚开始使用 Manjaro 的时候我是很痛苦的。**我花了两天的时间才安装好 QQ、WSL** 和某个小猫咪软件。 + +不过之后就学聪明了,在安装软件前会先在 AUR 上搜索是否有直接可用的包,如果没有也可以下载 `deb` 包,然后用 `debtap` 这个工具将其转换为适用于 Arch 的包。 + +很难想到,我在 Manjaro 上安装软件遇到最大的坎居然是——**微信**。微信的官方 Linux 版本似乎很久没有维护了,并且也没有做 Arch 的包;AUR 上有很多第三方的微信客户端,但好多都年久失修,虽然能用,但总没有原生软件的那种舒爽;我还尝试了使用 Wine 在 Linux 上安装适用于 Windows 的微信,结果 Wine 没有办法正常显示中文。 + +到现在,我这台电脑上都只安装了 QQ,没有找到合适的微信客户端。 + +## 你的下一台 MacBook + +Linux 桌面环境最让人着迷的一点就是极高的自定义性,我花了一些零碎的时间折腾了一下 KDE 桌面,现在我的 Manjaro 看起来是这样的。 + +![](https://r2.eltr.ac/blog/2024%2F02%2F2024-02-14_15-37.png) + +为了实现这个效果,我是用了 KDE / Plasma 全局主题 [WhiteSur](https://github.com/vinceliuice/WhiteSur-kde),这个主题提供了仿 Mac OS 的风格、窗口样式等。同时,我还使用了 [Latte Dock](https://github.com/KDE/latte-dock) 代替原本的停靠栏,使用 WhiteSur 作者提供的 Latte 主题美化了停靠栏。 + +当然,如果仅仅是美化,那也不是不敢称作「MacBook」的。MacBook 被很多人奉为生产力工具和效率工具,而不仅仅是一台笔记本。 + +生产力并不是由机器本身决定的,而是由软件和软件的使用者决定的。既然谈到软件,那就离不开软件生态。Mac OS 的软件生态不必多说,要在 Arch 中找到 MacOS 大部分效率工具的替代品,这确实需要多下一点工夫。 + +### 用你的键盘做更多 + +Alfred 是 Mac OS 上的一个应用启动器,可以通过快捷键呼出,然后输入应用的名字(大部分时候,只需要应用名字的前一两个字母即可)即可启动应用。在这个过程中,手不需要离开键盘,不需要用鼠标在桌面和 Dock 栏的图标里寻找自己想要的应用,节省了切换输入设备和寻找图标位置的时间。在 Linux 上也有不少类似的应用,最终我选择了 Ulauncher。 + +![](https://r2.eltr.ac/blog/2024%2F02%2F2024-02-14_16-02.png) + +我之所以选择额外安装一个应用启动器,而不是使用 KDE 桌面自带的开始菜单(可以用原 Windows 系统上的 WIN 键呼出),是因为 Ulauncher 提供了更模糊的检索方式,是我更容易找到自己想要打开的应用。同时,我还能把他当作一个快速的搜索入口,如果我输入的字符不匹配任何一个应用的名称,Ulauncher 就会显示在 Google / Stack Overflow / Wikipedia 搜索该关键字的选项。 + +有了 Ulauncher 的加持,再搭配 `Alt + Tab` 快速切换已经打开的窗口,就能快速地在各个应用之间来去自如。而且,我还要继续强调,完成这些操作,**你的手完全不需要离开键盘**。 + +### 编辑器的文艺复兴 + +我卸载了 Manjaro 自带的文本编辑器,因为它并不好用,于是,不熟悉 Linux 软件生态的我安装了 Sublime Text 作为敲代码之外的主力编辑器。但使用一段时间之后,我发现我并不习惯 Sublime 这款编辑器,原因有以下几点: + +1. 如果用来写代码,它提供的功能太少了,不如用拓展性更强的 VS Code; +2. 如果单纯用来编辑文本和一些配置文件,它的某些功能又显得有些多余; +3. 我不喜欢它的界面,默认的 Tab 缩进太短了。 + +于是我开始寻找一款真正简单好用的编辑器。恰好,我在少数派上读到「沉浸式翻译」的作者 Owen 一直使用 Neovim 作为他的主力编辑器。我一直听闻 Vim 作为编辑器的效率极高,而 Neovim 作为 Vim 更现代的续作必然不简单,所以就打算尝试一下。 + +不过,当我看到 Vim 和 Neovim 冗杂的配置文件时,顿时产生了十分抵触的心理——**我不喜欢需要花大把时间在配置上的软件**。于是我尝试了开箱即用的 [Helix](https://helix-editor.com/),它自称「后现代」的编辑器,不需要过多的配置,操作与 Vim 也十分相似。 + +开始使用 Helix 我才发现,对于纯粹的文字编辑器来说,图形界面是完全可以抛弃的。文本编辑器该有的查找、替换、文件切换,终端驱动的 Helix 都能做到,同时它还实现了窗口分割,跨行多选文本、多种语言的语法检查和代码高亮等。总之,一开始的体验非常舒服。 + +不过,我很快又发现了一个叫做 [NvChad](https://nvchad.com/) 的项目,它是 Neovim 的一个配置文件和插件集,也就是说,使用 NvChad 就能实现 Neovim 的开箱即用。这也完美解决了 Helix 没有插件系统,拓展性差的问题。通过 NvChad 配置的 Neovim 拥有文件目录树、对 Git 的适配、语法检查、对各种 Linter 的支持、标签页打开多个文件等功能,**这已经是能替代 VS Code 和许多 IDE 的工具了**。 + +![](https://r2.eltr.ac/blog/2024%2F02%2F2024-02-14_16-40.png) + +于是我很快抛弃了 Helix 和 VS Code,开始使用 Neovim 作为自己的主力编辑器。毕竟它在终端里启动,速度很快,而且什么样的编辑任务都能胜任,无论是简单修改配置文件还是开发一整个项目,而且你还能享受原生的 Vim 编辑模式。 + +如果不是因为早已经购买了 Typora 的软件序列号,我甚至会考虑用 Neovim 代替我所有的文本编辑器。不过仔细想想这样也有些太激进了,Typora 这样的可视化编辑器比起 Neovim 这样的纯文本编辑器,能够好地帮助撰写者把注意力放在文字本身上。 + +### 实打实的生产力工具 + +大概是收到身边人的影响,我也开始关注起办事效率和知识管理了。说到生产力工具和知识管理,很难不想到 Notion 和它优秀的数据库系统。虽然我在 [我的思绪像河流](https://www.guhub.cn/blog/i-think-like-a-river) 这篇文章里提到我并不喜欢 Notion 的模式,因为我觉得它不适合个人知识管理。不过人家的产品定位的确不是以知识管理为主,而是一个提升团队协作效率的工具,而我最近也的确体会到了它在这方面的强大。 + +关于 Notion 的数据库和各种视图都是老生常谈了,比起写一篇产品说明书,不如谈一谈真实有用的案例。 + +我在 [后室中文维基](http://backrooms-wiki-cn.wikidot.com/) 担任版主,网站内大大小小的事务虽然不算困难,但的确又多又杂。网站里十多个管理人员唯一常用的交流渠道只是一个「单线程交流」的 QQ 群。单线程的意思是,即使当下有好几件事务需要讨论和处理,也只能排着队一个一个来。不过,单线程并不是最大的问题,最大的问题是有不少需要处理的事情随着这条线性的溪流流走了——**较好的情况是一件事情已经敲定了,但是当时没来得及查看消息的职员不知道这个决策,还在按照以前的方式办事;比较坏的情况是,有些事情因为一直没有讨论出结果,很快就被大家忘记了,最后不了了之**。 + +最近的某一天我又突然想起了 Notion 这个被推上神坛,随后又渐渐淡出视野的工具。我有了个大概的构想,在群里和其他人介绍了一下,随后便开工了。 + +![](https://r2.eltr.ac/blog/2024%2F02%2F2024-02-14_22-15.png) + +邀请其他人进入工作区后就能一起查看和编辑页面了。这样可以把任务按照*待办事项、正在进行的事项、已经完成的事项、过去时间太久所以已经归档的事项*这四个类别分好,这样大家就能知道该做什么,什么事情已经敲定了。由于网站的管理人员都是为爱发电,难免会出现有一段时间因为个人原因无法参与工作的情况;当他们再次回归网站事务时,只需要查看 Notion 工作区的看板就能大概了解最近发生了些什么事情。 + +每个任务标注了「负责人」和「优先级」,这样大家就能知道哪些事情比较重要,哪些事情还没有人负责,并以此为依据选取无人负责且较为重要的事情优先完成。如果点进每个任务各自的页面,就能看到这个任务的「标签」,标签标明了这个任务属于哪一方面,可能是技术性问题,也可能是政策修订问题,也有可能是社区内的事务,这时职员可以根据自己的职权范围选择是否接手这个任务;如果接手,就可以继续往下读,参考写下这个任务的人留下的详细说明。 + +另外,因为站点工作人员大部分的讨论都在 QQ 群,而 QQ 群是单线程的,所以开设一个「提案区」能帮助所有人搞清楚还要哪些事项没有讨论出结果,同时也方便提出新的想法,还有一个更重要的作用是,**让所有人都静下心来组织一下自己的想法,写成有条理的文字再发给大家看**,这样也提升了效率。 + +尽管 Notion 免费版无法给协作者分配「成员」权限组(也就是说加入工作区的所有人都有最高权限,不会用 Notion 的人要是有误操作可能会留下比较棘手的烂摊子),但对效率的提升是显著的。 + +我似乎跑题了,但我不得不提到 Notion,因为我想要介绍一下我目前安装在 Manjaro 上的生产力工具,它们之间形成了十分良好的分工。 + +- Obsidian 作为一款双链笔记软件,作为我的「第二大脑」存在,储存着我所有成体系的知识和笔记; +- Flomo 作为一款卡片式笔记软件,储存着我零碎的、未经处理的想法; +- Notion 作为一款效率工具,用于团队协作分配任务; +- X-Mind 作为思维导图软件,用于在做事前理清思路(目前我正在尝试使用更轻量、功能更丰富的「幕布」替代有些臃肿的 X-Mind); +- 滴答清单作为一款规划工具,用于计划我个人近期和长期要完成的事项,同时,其内置的课表和番茄时钟功能也十分好用。 + +如果要把任何设备称作「生产力工具」,对我来说,以上工具一定得有至少三个。 + +--- + +## 后记 + +因为我的主力笔记本暗影精灵惨遭黑屏,在送修前和寄回前都没办法继续使用 Windows 系统的电脑,于是这台开学前几个月装好系统之后就没怎么用过的轻薄本临危受命,成为了我最近的主力。于是就有了这么一篇折腾记录。 + +另外,这些是写这篇文章时的一些奇思: + +- 第一个副标题「冷淡的接待」致敬了《饥荒》冒险模式中一个关卡的名字。 +- 第二个副标题「吃豆人欢呼」包含两个要素:Pacman(吃豆人,同时也是 Arch Linux 自带的包管理器的名字)和 Yay(用于安装 AUR 包的工具,全名 Yet another Yogurt,和英语中表示欢呼的拟生词拼写相同)。*拜托,想个更好的双关语吧。* + +顺带一提,今天是一个很重要的日子: + +> 1946 年 2 月 14 日,世界上第一台电脑 ENIAC 在美国宾夕法尼亚大学诞生。 + +望周知。 + +## TL;DR + +1. 因为专业需求,在一台闲置电脑上安装了 Manjaro 系统; +2. 探索 Arch Linux 的软件生态; +3. 美化 KDE / Plasma 桌面环境,仿造 Mac OS; +4. 寻找效率工具和生产力软件。 + +--- + +*封面图源:[Christin Hume on Unsplash](https://unsplash.com/photos/person-using-laptop-computer-Hcfwew744z4)* \ No newline at end of file diff --git a/content/article/Notion-sickness.md b/content/article/Notion-sickness.md new file mode 100644 index 00000000..4f39edf9 --- /dev/null +++ b/content/article/Notion-sickness.md @@ -0,0 +1,99 @@ ++++ +title = "Notion-Sickness" +subtitle = "从「宇宙第一生产力」逃离" +description = "在几个月的拉扯之后,我终于抛弃了 Notion,这个完全能用「狂妄自大」来形容的笔记软件,似乎一切都要更简单明了了。" +draft = false +date = 2024-12-11T22:50:00 +categories = "生产力报告" +tags = [ "Notion", "笔记方法", "效率",] +toc = true +aliases = [ "/posts/notion-sickness",] +url = "/essays/Notion-sickness/" + ++++ + +> [!note] 🧑‍🏫 +> 标题取自「晕动症」—— Motion Sickness + +> [!warning] +> 如果你认为 Notion 用起来很舒服,不必在乎我的意见 + +在几个月的拉扯之后,我终于抛弃了 Notion,这个完全能用「狂妄自大」来形容的笔记软件,似乎一切都要更简单明了了。 + + + +我无意诋毁 Notion 本身的质量,仅从功能性上来看,他绝对是同类软件中的佼佼者。作为团队协作软件,它一站式地解决了许多管理难题。虽然不能做到开箱即用,但搭建好工作区之后,绝对是一个能打十个的存在。 + +问题在于,当普通用户把这个主要面向企业和团队的产品当作个人知识管理应用,并妄图利用其全部的功能搭建自己的空间时,就很容易陷入需求的无中生有,还容易把简单的问题复杂化。 + +比如,在之前可能从来不会有人想过,自己可以把衣柜里的衣服裤子都拍照、归类、编辑元信息,然后放在数据库里做一个「赛博衣柜」。再比如,原本用一个 Excel 表格,最多再加一个数据透视表和图表就能完成的事情(需求不大的情景下,手写都能满足),非得建几个数据库,还要升级 Plus 版或者折腾教育版,来获得无限数量的图表。 + +请不要被冒犯到,我只是在骂以前的自己,这些都是我干过的事情,详见: + +- 《[搭建更适合自己的习惯打卡系统](/posts/搭建更适合自己的习惯打卡系统/)》 +- 《[用一张表格控制你的物语](/posts/用一张表格控制你的物欲/)》 +- 《[比起记录时间,计算产出或许更有用](/posts/比起记录时间-计算产出或许更有用/)》 + +并不是只有 Notion 才有这样的问题,准确来说,这并不是 Notion 的问题,而是「重器轻用」所带来的矛盾。就像有人送了你一个电动牙刷,你却告诉自己,我不需要电动的功能,于是只把它当作一个普通牙刷来用,但你真的不会有一天心血来潮,按下他的开关试一试吗?试过之后,你还会继续自己手动刷牙吗? + +我的观点很明显了:**大部分人不需要 Notion**,至少不需要用它来提高生产力,如果只是满足折腾和玩玩的想法,那无可厚非。和 Notion 类似的其他产品也是一样,这也是为什么,当我现在看到一个新的笔记软件时,我会抑制一切想要了解更多的想法,不会多花一点时间看它——因为不用看我也知道,我根本不需要它。 + +## 我对 Notion 的各种不爽 + +Notion 的 Block(块),在当时算是非常有创新意义的设计。不过它并没能真正意义上降低笔记的「颗粒度」,没法像其他双链笔记应用那样实现丝滑的块引用。Block 只是一个花哨的名字,再加上 Notion 并没有「标签」功能,它的内容管理方式,一直都是基于传统的「标题-文档」的(数据库里的确可以通过多选属性来实现标签的效果,但远不如原生的标签用起来丝滑)。 + +网状笔记、双链笔记、标签分类的概念早都是陈词滥调了,这里先不谈这些不新也不旧的笔记概念能不能真正地为所有用户带来效率的提升,我想说的是,在使用方面,Notion 支持的笔记管理方法,在其他笔记软件面前,的确是相形见绌。 + +我也一直很想吐槽 Notion 的排版,尤其是中文排版,行间距、字体简直没法看。也就多栏布局有些优势,写笔记真的用得到它吗? + +插入、引用的体感也不舒服,就算是网络环境好的情况下,Notion 在搜索工作区的页面时也需要加载一段时间,这点时延还是很明显的。再加上没有离线版本、数据不能本地保存,已经让患有「数据洁癖」的我浑身不舒服了。 + +## 从笔记软件过渡到个人数据中心 + +尽管有诸多不适,但 Notion 还是以他强大的数据库功能把我留住了。很长一段时间里,我都是把 Notion 当作一个万能的多维表格来用。 + +![](https://r2.eltr.ac/uPic/2024/12/image-20241211215903957.png "用 Notion 搭建的专注时间统计") + +当我把对 Notion 的定位,从「笔记软件」变成「数据中枢」之后,我就发现我很少打开它了,基本只有每周一整合上周数据时才会用。但我还一直把它留在程序坞里,总觉得离不开它。 + +由于定位是数据中枢,就难免用到各种统计表格。因为 Notion 只为免费用户提供一个图表的使用权,我还专门换了教育邮箱,用来获得 Notion 的教育 Plus 版。也正是有「我都有教育版了,不用多可惜」的心态,我还疯狂给自己洗脑自己需要 Notion。直到有一天我突然意识到:**这些功能,Excel 不能做吗**? + +一个令人尴尬的事实是,Excel 和 Apple 的 Numbers 表格,在数据处理方面完胜 Notion。Notion 至今还没办法把每一列的总数用于函数计算,使得很多数据处理的需求难以实现。专门的表格应用也没有图表数量的限制,排版也更灵活。 + +我固执地继续用 Notion,不是给自己找了个祖宗供着吗? + +## 拥抱原生应用 + +于是,我尝试用 Numbers 表格实现之前用 Notion 实现的需求。导出 csv 后用 Numbers 打开,加上数据透视表和原生支持的图表,花了几分钟调色,再加上了一些图片修饰,就获得了这样的一张表。 + +![](https://r2.eltr.ac/uPic/2024/12/image-20241211220938501.png "原数据和数据透视表已隐去") + +然后我又陆续用 Numbers 表格做了自己数字资产(订阅管理)和每月收支的统计,基本上我认作是「个人数据」的东西,都能用 Numbers 表格轻易实现,当然 Excel 也是一样的。 + +我花在折腾外观设计上的时间,也比不上在 Notion 里折腾数据库设计的时间。 + +唯一不太能被代替的,可能就是这样的一些东西吧: + +![](https://r2.eltr.ac/uPic/2024/12/image-20241211220231808.png "我像个仓鼠一样收集自己用过的 App 和服务,还把这张表与订阅管理的表关联起来,很是「优雅」") + +我还喜欢在 Notion 囤积一些信息,有的信息囤积也不坏,比如灵感收集之类的,我还学《Steal Like An Artist》这个作者,把别人对我作品的赞美收集起来,给日后的自己看。 + +这些内容,被我移动到了 Apple Notes,也就是备忘录里。 + +![](https://r2.eltr.ac/uPic/2024/12/image-20241211221906384.png "我用了「PARA 管理法」,不过文件目录怎样设计其实不重要。") + +你可以发现,我的需求完全可以用备忘录和传统表格满足,做起来也不困难。备忘录的收集、整理体验甚至更好,从网页和其他应用分享内容时,也不会像 Notion 一样加载老半天。这几天整理各种留学相关的信息,我都是用备忘录帮我搞定的。 + +## 丢掉积木 + +Notion 在宣传时喜欢把自己的产品叫做 Building Blocks(积木),我回想起我接触 Notion 的经历,大概也只是喜欢 Building 的感觉,就像是玩 Minecraft 一样。 + +在建立极客死亡计划这个博客之后,我一直把写作当作「给文字下葬」的过程,我也发现,在某种程度上,写作真的能帮助我杀死某些东西。我是写完了《[别再烦我了,绿色猫头鹰](/posts/别再烦我了绿色猫头鹰/)》之后,才合理化了自己卸载多邻国的选择。要是没写这篇文章,我也不能毫无顾忌地卸载 Notion。 + +大概,当你需要做些断舍离的时候,把自己的感受、经历、理由写下来,一方面能帮你做出更理性的决策,另一方面也能让你在感受上,能够做出这个决策。把东西写下来的行为,满足了个体[自我外化的需求](/posts/自我外化与表达欲/)。 + +谈到笔记软件,「不创造需求」似乎也成陈词滥调了,但有多少人能忍住不把工具当玩具把玩呢。综合考虑各个软件的长处,还用各种中间工具将它们连接起来,搭建起一套完善的工作流,做一个快乐的 nerd,似乎也不坏。 + +我放弃 Notion,不能说是突然对「生产力」有了多大的感悟,而只是我早就玩腻它了而已,我对它的厌恶情绪也早有堆积。我现在能做的就是阻止自己去下载另一个笔记软件,让自己关注更重要的事情。 + +说到底,人们对「生产力」的讨论大多都离不开对工具的把玩。就算是这篇文章,我也有在向读者展示我的新玩具(备忘录和 Numbers 表格)。要脱离这种状态,就得停止讨论「生产力」本身,这个虚无缥缈的概念,而是专注下来,关注当下应该做的事情。因为,**这个语境下的「生产力」本身就是玩具**,怎样讨论都只是在说「用什么样的方式玩玩具」而已。 \ No newline at end of file diff --git a/content/article/Profitez de votre vie.md b/content/article/Profitez de votre vie.md new file mode 100644 index 00000000..562f6e24 --- /dev/null +++ b/content/article/Profitez de votre vie.md @@ -0,0 +1,131 @@ ++++ +date = 2024-03-20 +title = "Profitez de votre vie." +tags = [ "语言", "旧博客文章", "français",] +aliases = [ "/posts/profitez-de-votre-vie",] +url = "/posts/Profitez de votre vie/" + ++++ + +去年的 [年终总结](/posts/写在-2024-的开头) 洋洋洒洒写了一万字,竟然漏掉了我在去年做出的一项重要决定。大概是因为坚持到现在,已经成为习惯了,所以不觉得很重要吧。这件事情确实说大不小的,但讲给其他人听的时候,对方还是会感到惊讶或是赞许——我在高考后的暑假开启了法语学习。 + +Oui, vous avez bien entendu. + +## 与语言的缘分 + +我一直都想学一门英语以外的外语,甚至更多,因为我觉得掌握多门语言是一件很酷的事情。之前在 Bilibili 上看到一位 up 主采访一名会讲二十多门语言的老人,看见视频里的两个人用中文、英语和日语聊天觉得很有意思,不只是因为两人在交谈时能够在多门语言之间无缝切换,也有感受到这位老人印在灵魂里的「有趣」,真的能看出那位老人的博学,以及他侃侃而谈时的自信和对语言的热爱。当时我就想,等我老了,我一定要做一个有意思的老头子。 + +至于为什么选择法语,其实并非是因为那些有关法语的刻板印象(像是法语很浪漫、法语很性感之类的说辞),所以一直心心念念想要学法语,而是当我第一次打开 Duolingo 的时候,列表上为数不多供中文母语者学习的语言里,只有法语最吸引我。**嗯,其实就是凭感觉稀里糊涂瞎选的。** + +刚刚谈到的法语的刻板印象,其实多少也会有,我似乎一直感觉法语是一门优雅的语言。这应该是因为受到了文化的耳濡目染。诺曼征服之后,英格兰从政治制度和语言文化上都永久地改变了;在那个时代,几乎所有的达官贵族都说法语,英语里有许多常用词汇都源自于法语;到现在,我们也能在一些较为古典的音乐剧或者一些人物个性鲜明的电视剧里,听到不少法语词汇。我有印象的是《歌剧魅影》里经常用 monsieur 代替 my sir(当然这与原著本来就是法国人写的也有关系),《Hamilton》里也有一个重要角色是法国人,还有不少著名的音乐剧都是用法语演出的。至少对我来说,法语很容易和古典、高雅等词语联系起来。 + +一方面是因为对法语有这样的印象,另一方面也是因为我对其他语言几乎没有什么印象,学日语的话又懒得背五十音图,而且自己也不是二次元,所以选了法语。 + +## 令人无语的猫头鹰 + +现在我的 Duolingo 连胜记录已经是 238 天了,不过我还是不能确定自己是否真正入门。至少,在尝试说一个完整的句子时,我还是不免会因为不了解某些单词或语法而停下来查阅,不过这个过程也还算有意思。 + +一开始,Duolingo 的教学方法给我一种领先时代但又有些像幼儿园老师的美,可学语言不就得从小孩子的白话开始嘛。话是这么说,Duolingo 的题目却时常有种反人类的怪异感,有点像是把学过的单词按照正确的语法组合起来,筛掉了一些如「无色的绿色想法愤怒的睡觉」一类的逆天句子,但还是有漏网之鱼。当我看到一个卡通小屁孩一脸正经地跟我说「J'ai besoin de seize salles.(我需要十六个大厅)」的时候,我真的觉得又好笑又好气。 + +> What you gonna do with them, you freaking bastard. + +抛开这些鸡毛蒜皮,Duolingo 听说式的学习方法也还算不错,单元之间不断地重复练习也能让人更深刻地记住一个单词和语法知识。尽管 Duolingo 给每一章节都提供了语法知识手册,但我几乎没有点开看过,因为只要做几道题,听几个句子就能大概弄明白。等有了一定的语法基础,再去看更专业、更详尽的语法书,会是更好的选择。 + +Duolingo 在宣传的时候常常把自己的教学方式比喻成「做游戏」,以此来吸引眼球,因此的确有不少人认为在 Duolingo 学语言就是在玩游戏。最近我在少数派上读到一篇讲语言学习的文章,作者就是这么发表他对 Duolingo 的看法的。**Duolingo 上学语言没那么严肃是真的,有不少游戏元素也是真的,但也不至于是收效极低的「玩」。** + +当然,我不是在维护 Duolingo 课程的有效性,因为比起最适合我的学习方式(which is yet to be found),它的效率的确不怎么高,大概是为了照顾到大多数人(我一直觉得自己还是有一些语言天赋的)。**Duolingo 的体系对我影响最大的点是养成了每天学一点的习惯。**它在对游戏设计的借鉴当中最成功的一项就是排行榜的设计——每一周用户都会和其他人一起竞争,排在前面的人才有机会进入下一个等级,否则就留在当前等级,或者因为排名太靠后而掉回上一个等级;排名的依据是在每一次学习之后积攒的「经验」,每周揭榜后都会清空。这个设计不仅让用户为了保住排名而每天坚持学习,还会因为等级越高而变得越来越卷,不得不每天学习更多的内容赚取更多的经验。 + +另外,Duolingo 的宣传,从商业的角度看,也是成功的。一方面,Duolingo 官方有在运营自己的社交媒体,而且不只是每天发文单纯做宣传,还会在其他品牌、产品、游戏甚至是艺人的推文下留言(看到 Duolingo 这个语言学习 App 和《咩咩启示录》这个不正经的游戏之间在推文下互动的时候还觉得挺魔幻的),最好笑的是 Duolingo 还会做有关自己品牌形象的 Meme(他们的吉祥物是一只绿色的猫头鹰,我印象最深刻的是他们在推特上恶搞了好几张流行专辑的封面,把图片上的歌手都换成了这只猫头鹰,其中恶搞 Taylor Swift 重录版《Red》的那张成为了我的新微信头像)。 + +在 Bilibili 或者 YouTube 上搜索 Duolingo,大概还能看到有关猫头鹰绑架杀人的恶搞视频。这是因为 Duolingo 每天都会给用户发“威胁”短信,催促用户该学习了,其中的某些句子大概是为了显得亲切,所以带有些戏谑和埋怨的意味。如果用户一天都没有学习,大概会收到好几条来自 Duolingo 的消息,这样看就有点像是在「索命」了。 + +我好像跑题了。 + +## 揭开面纱 + +开始学法语之后,这门语言在我这里的高贵形象真的是碎了一地。 + +### 不太好的第一印象 + +在法语里,表示男孩和儿子是两个不同的词——garçon 和 fils;但是女儿和女孩都是同一个词——fille。法语里的 femme 既可以表示女人,也可以表示妻子,但法语里的丈夫和男人(homme)并不是同一个词,而是一个单独的词——mari。 + +不知道是不是我反应过度了,但**我觉得这门语言要是一个活人的话,放在英语互联网上是要被冲爆的程度**。因为这种男女相关的词汇上的差别,反映了一种思想,即强调女性作为妻子和女儿的身份,而认为男性与丈夫以及儿子这两个身份是可以分离的。这并不是说,男性不结婚、不尊重自己的父亲是被允许或者视为正常的,而是说,人们在讨论男性时,更多地会关注这个人本身的为人和成就;而讨论女性时,更多地会关注她作为女儿是否服从父母管教,作为妻子是否贤惠体贴。 + +我还可以继续谈论有关性别的问题,但我决定点到为止。我还得我自己辩解一下,我并不是用这一点来批评法语这门语言,因为世界上大部分的语言都有很久的历史,必定会受到旧时代文化的影响;我也不是在批评法国人,只因为某一方面不合就批评一个人乃至一个团体是不聪明的做法。**我只是在就事论事,我观察到的现象让我有了这样的猜测,给我留下了不太好的印象罢了。** + +此外,法语某些方面表意能力不如中文,甚至不如英文,比如「宠物」这个词在英语里只有简简单单的三个字母 pet,但是在法语里有长长的三个词——animal de compagnie,直译过来就是 animal of company(陪伴的动物)。 + +### 除了折磨人没有什么用的动词变位 + +和许多欧洲语言一样,法语也有不少令人抓狂的、莫名其妙的语法规则。如果你被英语的语法惯坏了,学法语一定会不适应。在法语里,每个人称都有对应的动词变化:动词 prendre 的第一人称单数形式是 prend,第一人称复数形式是 prenons,第二人称单数形式是 prends,第二人称复数形式是 prenez,第三人称单数形式是 prend,第三人称复数形式是 prennent。 + +再看看法语的时态,每个人称还有对应时态的版本。这是未完成过去时: + +- je **prenais** +- tu **prenais** +- il/elle **prenait** +- nous **prenions** +- vous **preniez** +- ils/elles **prenaient** + +这是将来时: + +- je **prendrai** +- tu **prendras** +- il/elle **prendra** +- nous **prendrons** +- vous **prendrez** +- ils/elles **prendront** + +动词条件式: + +- je **prendrais** +- tu **prendrais** +- il/elle **prendrait** +- nous **prendrions** +- vous **prendriez** +- ils/elles **prendraient** + +还有简单过去时、过去完成时、将来完成时、先过去时。如果句子是虚拟语气,这些动词变位还有一套全新的版本。 + +### 匪夷所思的性别 + +然后我们再来盘一盘欧洲语言里要命的名词阴阳性。法语里所有的名词都有性别,也就是说,在这门语言眼里,世间的一切都有性别,比如 jardin(花园)是男性,idėe(想法)是女性,banque(银行)也是女性。 + +这有什么影响呢?在同一个句子里所有和这个名词有关联的句子成分,除了动词,都要受到阴阳性的影响,也就是说,如果你是初学者,在下笔或者张嘴之前得好好想一想这么名词的阴阳性,然后想一想其他句子成分对应的阴性或阳性形式。比如 vie(生活)这个词是阴性,那么定冠词要用 La,而不能说 Le vie;如果我要说,好的生活,用 excellent 这个形容词,它也得用阴性形式,得说 La vie excellente。 + +与中文逻辑相反的是,对于物主形容词来说,用阴性还是阳性取决于其修饰的名词而不是物主的阴阳性。比如,我要说我的母亲,我是男性,但我不能用阳性形式的 mon mėre,因为母亲是女性,所以要用 ma mėre。 + +对于形容词来说,要关注的不仅是性别,还有单复数。如果要说「我的姐姐很有趣」,因为姐姐是阴性,所以形容词也要用阴性——ma sœur est **amusante**;但如果我说的是「我的姐妹很有趣」,姐妹就变成复数了,就得说 mes sœurs sont **amusantes**。 + +最好笑的是,法语里除了 f 以外的词尾辅音不发音,也就是说 amusante 和 amusantes 在读音上没有任何区别。~~那你还变你妈啊~~。 + +### 并不是优雅的美 + +~~好了,骂爽了,认真点吧~~。 + +要谈法语的美,从句法和文法上我说不出太多,但有一点让我感到很有意思。因为在法语里没有「它」和 it 这样的代词,而每个名词都有性别,所以在法语里,指物的代词和指人的代词一致,男性用 il,女性用 elle。 + +如此,即使你不写诗,也可以若无其事地把月亮(la lune)称作她。 + +> Il y a pleine lune ce soir. Elle est trės belle. + +我不清楚其他人会不会和我一样有这样的想法,我学过阴阳性之后,逐渐能够从字缝里看出鲜活的人物来,觉得还挺可爱的。idėe(idea)这个词看着小小的,是女性,给人感觉像是女孩子。banque(bank)这个词也是女性,从字形上看像是那种很有气质,平常穿一身正装,不穿裙子,话不多但办事能力很强的大姐大(越描述越像是塔罗牌里的星币女王,「银行」的词义和星币也挺贴合的)。jardin(garden)是男性,开头是字母 j,给我的感觉是二三十岁不等,有些瘦,站得很直,讲话有些幽默(j 下半部分的弯钩给人不太严肃的感觉)的园丁。 + +不过,地铁站(la station de mėtro)这样的词也是女性,所以有些时候还挺奇怪的。 + +从读音上看的话,法语最有标志性的发音应该是 r 的读音了。这个音并不是卷舌音,更像是 h 的音,实际上是小舌音或者说颤音,但法语里的颤音并不如西语等其他欧洲语言那般明显,倒更像是破擦音了。这个音学起来有些难,因为气流集中在喉咙和口腔后部,如果夸张一点就有点像吐痰的声音。 + +法语里也比较少见 /i/ 这样需要把嘴合成一条缝的音,就连 importante 和 simple 这样拼写上本来就有 i 的单词,im 的发言也是 /am/。常见的音都需要送出大股的气流。 + +听完一些法语歌曲之后,我发现法语和英语在读音上的差别其实不算大,但明显能感觉出法语其实会更加「奔放」。 + +--- + +## 后记 + +其实本来还想谈谈人文相关的话题,但自己了解其实并不多,另外 Duolingo 又发消息催我学法语了,所以就写到这吧。 + +这篇文章的标题「Profitez de votre vie.」来自我在 Bilibili 上看过的一个视频,一位流浪街头的老太太在离开临时收留她过夜的中国女孩时对她说了这样一句话,意思是「Make the most of your life.」。 + +好好生活。 \ No newline at end of file diff --git "a/content/article/Safari\347\232\204\344\274\230\351\233\205.md" "b/content/article/Safari\347\232\204\344\274\230\351\233\205.md" new file mode 100644 index 00000000..251e7b77 --- /dev/null +++ "b/content/article/Safari\347\232\204\344\274\230\351\233\205.md" @@ -0,0 +1,99 @@ ++++ +title = "Safari 的优雅" +subtitle = "Chrome vs. Safari" +date = 2025-01-18T22:57:00 +tags = [ "Apple", "Geek", "软件", "设计",] +categories = "软件杂谈" +draft = false +toc = true +aliases = [ "/posts/safari的优雅",] +url = "/posts/Safari的优雅/" + ++++ + +购入 [MacBook](/posts/揽物日志-vol-3/) 之后,我就抛弃了 Chrome 浏览器,也没有去使用很火的 Arc 浏览器。与很多人不同,Safari 并不是我下载 Chrome 的工具,在过去一个月的使用体验中,它作为我的主力浏览器,极大程度地改变了我的 Web 体验。 + + + +## 用户界面 + +先横向对比一下 Safari 和 Chrome 的用户界面。 + +{{< gallery >}} +![](https://r2.eltr.ac/uPic/2025/01/PixPin_2025-01-18_09-56-12.png) +![](https://r2.eltr.ac/uPic/2025/01/PixPin_2025-01-18_09-56-42.png) +{{}} + +Chrome 的标签栏和地址栏分界很明显,在任何时候,浏览器最上方都被分成了两栏。而 Safari 只有在存在多个标签页时才会显示标签页栏,而且 Apple 也没有把它分成割裂的两部分,颜色仍然是相似的,当前标签页和顶部的地址栏是连在一起的,一体化的感觉会更强。 + +![](https://r2.eltr.ac/uPic/2025/01/PixPin_2025-01-18_09-59-45.png) + +你也可以在设置里将 Safari 标签设置为紧凑布局,这样地址栏和标签页栏就可以融合在一起。更棒的是,此时的顶栏会匹配当前网站顶部的颜色,和网页的设计融合在一起。 + +{{< gallery >}} +![](https://r2.eltr.ac/uPic/2025/01/image-20250118110522601.png) +![](https://r2.eltr.ac/uPic/2025/01/image-20250118111307594.png) +!{}(https://r2.eltr.ac/uPic/2025/01/image-20250118111439987.png) +{{}} + +我认为这样的设计能让我在访问网站的时候更专注网站本身提供的内容,不会有太多的工具按钮分散我的注意力,让我一直想着「我能在这个网站上做点什么」。 + +尽管配色很和谐,但 Chrome 颜色分界明显的设计仍然产生了一种割裂感(至少对我来说),不仅标签页和地址栏有分界,地址栏和其他的工具按钮之间也有明显的分界。 + +此外,Chrome 右侧工具图标也很扎眼(长时间使用 Safari 再使用 Chrome,这种感觉就非常明显),我不明白为什么那个头像不能收进菜单里,它并不常用;以及那些浏览器拓展,真的有必要吗? + +## 太多的浏览器拓展 + +Safari 和 Chrome 的使用体验最大的不同,可能是拓展程序的使用。Safari 的拓展程序远远不如 Chrome 丰富,我确实花了很多时间适应。没了 Dark Reader,在访问一些没有夜间模式的网站时我感到非常不适;没了 Notion Webclipper、Cubox 等插件,收藏网页内容也十分不便;Safari 使用油猴脚本也没那么方便(我才发现我到现在还没有尝试在 Safari 上使用过油猴脚本)。 + +使用 Safari 一个月之后,我发现自己并没有花多少时间折腾浏览器拓展。我不禁开始思考,自己之前给 Chrome 安装各种拓展以获得额外功能,真的有必要吗? + +> 会不会是他对于额外功能永不满足的欲望,拖慢了他的浏览器? +> +> ——[告诉你为什么Chrome这么慢(不是内存的锅)#linus谈科技](https://www.bilibili.com/video/BV1Ut421K7bP/) + +我不打算花时间讨论剪藏、文献管理、自定义用户脚本等功能的必要与否,因为每个人的需求都是不同的。至少对我来说,之前我认为很重要的 Webclipper 等功能,完全可以舍弃,或者用更简单的功能替代。 + +作为 Apple 原生应用,Safari 可以很方便地「共享」内容。如果我发现一篇不错的文章,打算稍后再读,比起添加到 Notion、Cubox 或者 Obsidian,我可以直接使用原生的「添加到阅读列表」,之后在 Safari 的首页看到我要读的内容。 + +阅读列表的设计对比 Cubox 这样专门的「稍后读」应用显得有些简陋,但其实完全够用,至少对我来说。 + +{{< gallery >}} +![](https://r2.eltr.ac/uPic/2025/01/image-20250118105724547.png) +![](https://r2.eltr.ac/uPic/2025/01/image-20250118225343611.png) +{{}} + +## 垂直标签页 + +Safari 也带有垂直标签页和标签分组的设计,并且单独建立的标签页组可以在 Safari 关闭后保留,下次打开依然可以访问。尽管不如 Arc 浏览器的垂直标签页一般优雅便捷,但若是没有很强的需求,偶尔需要打开大量标签页查询资料时用一用完全够了。 + +![](https://r2.eltr.ac/uPic/2025/01/image-20250118110144024.png) + +Chrome 的话,一直没有垂直标签页的设计,我试过好几个利用 Chrome 侧边栏制作的垂直标签页拓展,都不太好用。 + +## 不适合开发者 + +刚用 Safari 浏览器的时候,我怎么也找不到清除缓存的按钮。就算用过一次,下一次也要在设置里找半天才能找到。这确实是很大的缺点。 + +Safari 也没有开发者工具,将它作为默认浏览器的弊端是,每次从 IDE 或者一些 CLI 工具打开本地运行的 Web 应用时,我都必须手动复制链接,再用 Chrome 打开。没有开发者工具真的会让调试变得很困难。 + +通过一些工具跑分发现,Safari 的性能也远不如 Chrome,在加载一些页面时可能会更慢,表现不如 Chrome。 + +我的 Mac 上装了两个浏览器,Safari 用于日常的浏览和资料查询,而 Chrome 用作开发。这样做可以最大程度上发挥两个浏览器各自的优势,也能让我将开发者和用户这两个身份分离开来。 + +## 对一般用户不友好 + +我本来想再写写多台苹果设备一起使用 Safari 有多么方便,比如 iCloud 标签页和无感同步的书签、访问记录、不装拓展就能直接用 Apple 的密码管理器等等。 + +转念一些,这些都是所谓的「Apple 全家桶」用户才能享受到的好处。Apple 给其他浏览器做的书签同步插件非常难用,不太能做到设备之间的无缝切换。Apple 的密码管理器我没在 Windows 上用过(以前用的是跨平台的 Enpass),这里就不讲了。 + +如果主力设备中有非苹果的,那 Safari 的使用体验大概会大打折扣。 + +--- + +## ☕️ TL;DR + +- 试着用用装不了什么拓展的 Safari(或者关闭 Chrome 等浏览器的所有拓展程序),说不定你会发现自己根本不需要那些额外功能 +- 如果你偏好简洁的设计,Safari 会比 Chrome 更适合你 +- Safari 不适合开发者,如果你有前端开发的需求,你仍然需要 Chrome 或者其他带有开发者工具的浏览器 +- 如果你的主力设备中不全是苹果设备,那么使用 Safari 的体验或许没那么好;但如果你使用苹果全家桶,就试试 Safari 吧! \ No newline at end of file diff --git a/content/article/The Gay Oedipus.md b/content/article/The Gay Oedipus.md new file mode 100644 index 00000000..f48aebbf --- /dev/null +++ b/content/article/The Gay Oedipus.md @@ -0,0 +1,77 @@ ++++ +date = 2024-08-23 +description = "只是有些仇父而已" +draft = false +title = "The Gay Oedipus" +toc = true +tags = [ "原生家庭",] +aliases = [ "/posts/the-gay-oedipus",] +url = "/posts/The Gay Oedipus/" + ++++ + +昨天没精神写文章,「每日」写作计划中断了一天,原因是前一天晚上被父亲酒后说的某些话弄得几乎整夜未眠,晚上最后一次看时间是凌晨三点,我不记得我是什么时候睡下的。 + +其实也不是什么大事,只是我感到一种深深的无力感。我不能完全赞同他的话是其次——观点的不合很正常——最大的问题是我和他根本没办法交流。 + +## The Evil Baby + +尽管没有任何理性的认识,我一直觉得婴儿是邪恶的。我很喜欢恶搞之家里的 Stewie,创造出这个角色的编剧一定很有才,他把我对「邪恶婴儿」的印象以一种非常奇妙的方式表现了出来。 + +婴儿从一出生开始就在哭闹,以获取他身边所有人的关注。尽管我知道他们大哭的原因可能是为了呼吸,但在他们长大了一阵子之后,便渐渐学会了使用哭闹作为武器,胁迫家长把注意力放在自己身上。 + +对不满一岁的小孩子做出「邪恶」的评价似乎有些好笑,但我确实不太喜欢他们。我觉得这不仅仅是对噪音和这种操纵行为本身的厌恶,更多的是恐惧——和一个能被称作「人」的东西根本无法交流,而他与这个世界交流的唯一方式就是笑和哭(大多时候是让人掏心挠肺的大哭),引起其他人注意,**让其他人为自己的行为作出反应来满足自己的需求**。 + +认真来讲,婴儿完全没有自理能力,哭闹是他们与外界交流的唯一方式,吸引注意力也是解决自己的需求的唯一方式。 + +所以人们讨厌巨婴,因为他们完全可以为自己负责,却什么事情都要用和婴儿一样的逻辑吸引其它人的注意力,让其他人为自己的行为买单。 + +当然,这是一个极端,一个人并不需要是「巨婴」才能变得「像婴儿一样讨厌」。有些时候,我们很容易从一个成年人身上嗅到一丝婴儿的味道——把自己的问题招摇过市般地摆在别人面前,被动式地攻击(passive-agressive)他人,就像在人群中扔下一颗手雷;无论做什么都要把自己放在聚光灯下,总是在争夺群众的注意力,希望大家都听自己的——除了母性泛滥的另一种极端,我真的很难想象有什么人会真心地喜欢这样的特质。 + +把自己的问题摆出来,指望别人解决;在人群里用各种手段吸引注意力,希望大家看到自己——这是婴儿的「邪恶」之处,也是很多成年人的「可怜」之处。 + +## The Crying Deaf + +婴儿哭闹是为了吸引母亲的注意力,让这个人把所有心思都放在自己身上;婴儿长大了,却丝毫没有边界感,希望身边的人把注意力都放在自己身上,不会考虑其他人的需求。 + +正是因为这样,**婴儿靠自己完全学不会如何去照顾另一个婴儿,当另一个婴儿向他哭喊的时候,他什么都听不见,他可能还会因为对方为什么不能满足自己的需求而感到疑惑和愤怒,更大声地哭闹**。 + +这么说有些大逆不道——我喝醉了酒的父亲就是这样的。 + +晚上凌晨三点,我试图通过阅读让自己冷静下来。我读的那本书叫做《你的善良,必须有点锋芒》,刚好那几页在讲一些有关边界感、付出感和回报感的问题,我就一边读一边在心里发火。 + +那个时候我早就明白了,我讲话的逻辑完全是自洽的,我能用自己的知识体系解释自己的观点,真理就是我的宝剑和盾牌。其实能做到这点,我就应该不会被反对的观点困扰了。但那天晚上的对话却一直在我的脑海里挥之不去——于是我的困扰变成了「我为什么会困扰?」。 + +问题的答案是:**坐在我对面的那个醉汉完全听不进去我在说什么**。 + +再仔细回想,当时的场景是:我那醉得已经有些说话不利索的父亲,时不时放出一句暴论,我的奶奶(他的母亲)一脸担忧地盯着他,我的干妈(他好友的妻子)在一旁支持我的观点,我的母亲(他的妻子)也不耐烦地重复“别人一直在说……,根本不是你说的那样,你还在这里讲些什么……”。 + +再往前回想,类似场景发生过很多次,这大概也是我*讨厌酒精*的原因。 + +他一直在输出自己的观点,我知道自己是正确的,其他人都理解明白赞同我说的话,而对面那个醉汉却一直在重复他自以为是的话语。**他希望满足自己被听到的需求,却完全忽视了我相同的需求,因为他根本没想过我也有这种需要**。 + +## The Brazen Theft + +你大概会疑惑,我为什么要和一个喝醉了酒的人斤斤计较?事实是,这次让我感到极度不舒适而他却对他履行了父亲的教育义务这一“事实”感到非常满意的谈话,就是我们半年,甚至一年内,交流最多的一次,因为他和他的朋友都说:“不喝点酒有些话说不出来。” + +用阿德勒心理学的话来说,“不喝点酒有些话说不出来”就是一个*为了让自己心安理得地不坦诚交流*的「人生谎言」。**因为自己有心理障碍,因为自己没胆量,因为自己想要逃避坦诚交流,所以用这样的一个伪事实来合理化自己的行为**。 + +我回家时,坐上他的车,我不知道能和他说些什么,因为我们的生活近乎完全脱节。而他认为我至少应该叫他一声「爸」——**他从来不和我说他的需求,而是向他的母亲诉苦**,让我的奶奶告诉我,我应该显得亲切一点。 + +事实是,这个我称作父亲的男人,在我小学和初中的时候近乎完全缺席。每晚回到家,我都不知道自己的父亲在哪里,其他的家人都在家里吃饭,而他却在外面和朋友喝酒。作为一个心智未成熟的小孩子,我时常听到我的母亲晚上十一点在我的隔壁卧室给我的父亲打电话,骂他为什么还不回家;我时常坐在后座,听着那个喝了酒的男人对给他开车的妻子指指点点,甚至恶语相向,即使车里还有我,甚至还有除了我以外的其他人,把别人也置于尴尬的境地里…… + +很多人会把酒精作为借口,说「喝了酒说的话不作数」、「他喝醉了你别计较」。我从小就觉得这句话可笑之极,因为这个逻辑同时也质疑了「酒驾」和「醉驾」相关的法律规定,在某种程度上可以说是「违法」的思想——**难道一个人喝了酒,就不应该为自己的不负责行为负责吗?如果付不起这个责,那为什么还要喝酒**?这种「既要又要」,和那些稍微开了些智的小孩子,既要母亲的疼爱,又要母亲别管自己,不是同样的“邪恶”? + +所以,恕我实在不能理解,那个男人是怎么心安理得地向其他人炫耀,**自己是如何培养出了两个这么优秀的儿子的**。 + +他一直在跟我讲家庭是如何重要,即使不在乎社会,不在乎世界,也要关注家庭;我很想用「共同体感觉」的理论反驳,但我为什么要和喝了酒、最高学历是初一、买了一堆书放在柜子里却从来没读过的人说这些话? + +在他的世界观里,家庭就是一个完全绑定的集体。我的成就,尽管出自我自己的努力,他也要不断强调自己的“浇灌”有多么重要。我当然认可没有他们我做不到,但很显然他说这些话的时候,是为了跟我强调他在我的生命中有多么重要。 + +我试图用尽可能平静的语气告诉他:“这些话你应该早几年跟我说。”因为我已经是一个有自己思想的成年人了,你早就因为对我的不上心错过了教育我的年纪,现在你只能承认你给你儿子留下的心理创伤比实际的思想要多得多。可惜,**酒精和自负,是最好的耳塞**。 + +也因为这样的交流模式,我们开口说话要么吃饭喝水之类的日常琐事,要么就是让双方都不爽的吵闹(至少有一方,也就是我,会非常不爽;这也不是什么交流和理论,因为交流需要两个人发表意见和倾听,理论也需要逻辑和理性的参与)。我很长一段时间害怕被指责,很难敞开心扉,大概也和我一认真说话就引发矛盾的父亲有关。 + +我本来不怪他的,毕竟他是第一次当父亲。可他完全看不到他造成的伤害,反而认为他应该为他所“造就”的“我”获得回报,哪有这样的道理? + +哦,这样的道理确实有,可不就是“孝道”嘛。 \ No newline at end of file diff --git "a/content/article/The-Browser-Company-\347\232\204\346\226\260\346\265\217\350\247\210\345\231\250.md" "b/content/article/The-Browser-Company-\347\232\204\346\226\260\346\265\217\350\247\210\345\231\250.md" new file mode 100644 index 00000000..31ae970e --- /dev/null +++ "b/content/article/The-Browser-Company-\347\232\204\346\226\260\346\265\217\350\247\210\345\231\250.md" @@ -0,0 +1,78 @@ ++++ +title = "The Browser Company 的新浏览器" +date = 2024-12-04T22:38:00 +draft = false +tags = [ "时事", "Geek",] +categories = "软件杂谈" +aliases = [ "/posts/the-browser-company-的新浏览器",] +url = "/posts/The-Browser-Company-的新浏览器/" + ++++ + +很少在博客谈时事和热点新闻,一是不想引发争议,觉得麻烦,二是自己确实不关心。不过最近倒是看到了自己很感兴趣的话题,所以还是想试试在博客谈一谈对这些「新闻」的看法。 + + + +Arc 浏览器的制作公司 The Browser Company 不久前宣布停止开发 Arc,并预告了新的浏览器。这个浏览器将会抛弃 Arc 最具特色的垂直标签页和各种操作逻辑,重点将会聚焦在 AI 上。 + +而就在最近,The Browser Company 发布了新的预告,并宣布了新浏览器的名字,进一步阐述了设计理念。新浏览器叫做 Dia,你可以在[它的官网](https://www.diabrowser.com)上看到。目前这个产品除了一个 11 分钟长的招募视频,什么也没有。 + +有人做出了这样的评价: + +> 产品稀烂,全靠营销 + +似乎一针见血,令人称快。可我有些不同的看法。 + +首先,如果你评价某个东西,无论好坏,它都得先存在。目前这个名叫 Dia 的浏览器除了官网和招募人员的视频,什么也没有,也就是说,这个「产品」就不存在。什么样的预言家,才能在产品不存在的情况下,做出「产品稀烂」这种评价呢? + +至于「全靠营销」,这点我认可,因为目前 Dia 浏览器除了营销确实什么都没有,这整个品牌和莫须有的产品,都是靠「营销」撑起来的。 + +--- + +The Browser Company 在那个 11 分钟的视频里都讲了些什么?听我说其实没什么用,如果你感兴趣,你可以花点时间去他们的官网上观看原视频;如果你听不懂英文,[这里](https://www.bilibili.com/video/BV1Sp6TYkEe6/)有机翻的中文字幕版。 + +视频大概是在讲 Dia 浏览器的理念,总结下来,就是「AI 不应该局限于一个应用程序或者附加在某个应用里的功能按钮,AI 应该是一个更广泛的概念——环境」。 + +简单来说,The Browser Company 希望用 AI 重新设计浏览器——浏览器不同于其他应用程序,你在数字时代的一切都可以在 Web 上发生,而浏览器正是一个窗口,是这「一切」的重要载体。浏览器了解你在 Web 上的一切,如果它拥有智慧,它能帮助进行更个性化的操作。 + +比如,如果你使用 Gmail,而 Gmail 只有网页客户端,这就意味着你必须在浏览器内使用 Gmail。The Browser Company 所宣传的浏览器会记住你的行为,同时他也了解你以前浏览过、现在正在浏览的内容,所以「把我现在正在查看的商品整理成列表发给 XXX」这样的操作,浏览器可以帮你完成。 + +The Browser Company 多次在视频里强调「personalized」这个词,显然这才是他们的核心理念。但这样的「个性化」又会引出另一个非常值得关注的问题——我的数据交给 AI 真的安全吗? + +要知道,X(原 Twitter)的用户大量流失,就是因为他们发表在平台上的内容可能会被用于训练 AI。The Browser Company 整出这样一个能够完全记忆你隐私信息(甚至可能包括银行卡密码)的浏览器,却没有在视频里提到自己会如何解决安全问题。在我看来,这个 Dia 浏览器的安全隐患和隐私问题,和 Windows 11 之前测试的 Recall 功能[^1]一样值得怀疑。 + +要知道,Arc 浏览器是一个必须要登录才能使用的浏览器,我没有理由相信 Dia 会有任何不同。Dia 这个基于 AI 的浏览器要想做到更好,就必定会收集用户数据以训练模型。就算我相信 The Browser Company 不会对我的数据做什么,但我能相信这样一个小公司,有能力保障我的数据不落入其他人之手吗? + +你可能会说,在互联网上,隐私早就不存在了。但是,这可是一个官方声称有「记忆」功能的浏览器,它对我隐私的收集显然不止电话号码、身份证号码那么简单。 + +我认为这才是最值得关注的。然而在那些贬低的评论中,我居然没有看到任何人对 Dia 的数据安全提出质疑,大部分都在表达对 Arc 停更的不满,和对这个新浏览器的不看好,即使这个产品甚至没有一个公开的可供测试的原型。 + +--- + +除了潜在的安全性问题(其实都不能说潜在,这个问题就像是「房间里的大象」一样,The Browser Company 自己没挑明罢了),很大一部分凑热闹的网友没有看到的是,The Browser Company 的确有不少独到的慧心巧思。 + +生成式 AI 相关应用高速发展的这一两年,有不少 App 都接入了 AI 功能。无论这个 App 本身是否真的需要,总之加上 AI 就会更好。 + +生成式 AI 的成功应用有不少,以 GitHub Copilot 为首的注重代码生成的应用就非常好用。 + +整体表现中规中矩的应用很多,比如 flomo 的「找一找」,问一个问题让 AI 帮你找笔记,使用场景其实非常少,不如多花点心思写笔记,如果写笔记真的花了心思,也不需要额外的工具帮你找笔记,除非是需要更智能的整理工作。 + +我接触到的还有 Cush 的账单分析功能,这个还算不错,但它基本上是在套模板,能告诉我的只有我在各个方面的花费占卜,然后给出一些显而易见的建议。 + +很烂的也不少,有金镶屎边,屎镶金边,屎上加屎的。 + +The Browser Company 能在这股生成式 AI 热潮过后,发现其中的问题,并尝试换一个视角重新看待 AI 应用,可以说,是值得褒奖的。他们认为 AI 不只是简单的附属品,而应该是重塑环境的动力,是真正能够改变人们使用万维网方式的技术。 + +暂且不谈这样的改变是否必要,也不谈在实际的表现中,这样的思想是否真的能发挥理想的效用,The Browser Company 的洞察力、创造力都是新奇的。作为小公司,它也有着大公司没有的激进和勇气。 + +--- + +在 Dia 浏览器还没有成为事实的存在之前,我认为我不应该做出太多评价;仅从现有的事实,也就是他们在视频中阐述的思想来看,我认为 Dia 浏览器至少是值得期待的。 + +诚然,他也有很多令人产生顾虑的点,比如前文提到的数据安全性,以及 The Browser Company 在浏览器还没有成型之前就如此大张旗鼓地宣传自己的理念,是否有些太轻狂了? + +最后,我想提醒网友,不应把对「Arc 停更」的不满情绪带到对 Dia 的评价上来。有多少人连 11 分钟的视频都看不完,就急着发表意见了?这样一个年轻的公司的做法确实不成熟,但他的思想和行动力是可圈可点的。 + +好了,不多说了,毕竟教人思考可不讨喜,说多了我自己也觉得讨厌。 + +[^1]: 详见 [Recall 概述 | Microsoft Learn](https://learn.microsoft.com/zh-cn/windows/ai/apis/recall) \ No newline at end of file diff --git a/content/article/abstraction.md b/content/article/abstraction.md new file mode 100644 index 00000000..947fb307 --- /dev/null +++ b/content/article/abstraction.md @@ -0,0 +1,139 @@ ++++ +title = "被错误抽象的抽象" +tags = [ "语言", "计算机", "逻辑", "哲学",] +mentioned_books = [ "娱乐至死",] +endnotes = [ "「抽象」一词在艺术等领域也有使用,「抽象画」「抽象艺术」中「抽象」的意思是「没有物理实体」的,与本文讨论的内容关联不大,所以没有提及。", "封面图来自 [Unsplash](https://unsplash.com/photos/blue-and-white-round-illustration-LpbyDENbQQg)",] +date = 2025-06-10T16:55:43 +categories = "猫头鹰化石" +banner = "https://r2.eltr.ac/uPic/2025/06/sebastian-svenson-LpbyDENbQQg-unsplash-2.jpg" +slug = "abstraction" +draft = false +toc = true +aliases = [ "/posts/abstraction",] +url = "/essays/abstraction/" + ++++ + +因为工作需要,我的上司要求我和另一个助教老师准备一场英文辩论,在周六的英语角之前在学生面前展示,辩题是「Are smartphones making us stupid?」(智能手机在让我们变笨吗?),我抽到了反方。 + +我一开始很不想占反对的一边,但做了一些研究之后,我找到了一个很方便的论点:技术是中立的,是人们使用智能手机的方式让自己变笨,责怪技术是本末倒置。 + +为了应付工作,我用大语言模型生成了一些辅助材料,其中有一条很有意思:苏格拉底在书写诞生之时,曾经反对这项「技术」,认为文字、书籍会让人们认为自己不再需要锻炼记忆,智慧变得浮于表面——换句话说,**苏格拉底认为「书让人变笨」**。[^1] + +当我质问正方辩手「书在古希腊,和智能手机在现代,都是让人免去记忆之劳的新技术;那么,你认为书会让人变笨吗?如果不是,那智能手机作为相似的技术,为什么会让人变笨?」 + +对方表示不理解,认为我和她说的根本不是同一件事情,即便在私下与她再关于此话题展开讨论,她依然认为书和智能手机完全不能类比,认为我在玩文字游戏。她似乎没能看到背后的逻辑,我认为,这可能是因为她不熟悉「抽象」的概念。 + +--- + +「抽象」这个词被广泛地滥用了,如今的年轻人用这个词来形容所有他们不理解的东西,以及他们觉得好笑或不正常的东西。这一语言现象可能会被解读为语言的自然演变,就像 extravert 这个词,因为反义词 introvert 中间的字母是 o,所以被许多人错误地拼写为 extrovert,后来竟然被词典承认,成了正确的英文。即便如此,我也认为溯本清源,理解「抽象」一词的原本含义,依然重要。 + +你正在阅读「猫头鹰化石」,探讨词源学的一系列文章。今天我们来研究中文的词源,尝试透过各个学科、多种视角,理解「抽象」这个词所指的概念。 + +--- + +## 抽象一词的来源 + +「抽象」其实并非是纯血的汉语词汇,而是日语的舶来词,而这个词也不能算是日本人造的,而是一个叫井上哲次郎的日本哲学家,从英语的 abstract 一词翻译过来的(果然还是逃不过英语啊……)。这个词首次出现在《哲学字彙》(哲学字典)一书中,于 1881 年出版,是日本的学术词典。[^3] + +至于井上哲次郎为什么要这样翻译,为什么选用了「抽」和「象」这两个字,我一直没有找到来源可靠的解释,但可以从英语词源入手。 + +Abstract 一词乍一看和 Extract(提取、抽取)一词很像,它们的确有相同的词根——后半部分的 -tract 来自拉丁语 trahere,意思是「移动、拖动」;而 ab- 的意思是「远离,离开」。Abstract 其实来自于拉丁语单词 abstrahere 的过去分词形式 abstractus,意思是「drawn away」(被抽离的)。 + +所以,英语和其他大部分由拉丁语发展而来的语言当中,抽象(abstract)的本意都是「被抽离的」,只有「抽」之意,没有「象」之意。中文和日文里的「象」字是怎么来的,我还没有找到说法,但我觉得可以把「象」理解为「表象」「具体的」——==「抽象」就是把事务的本质、多种事物的共同特征,从具体的表象中抽离出来认识的过程。== + +## 计算机科学与哲学 + +学计算机的对「抽象」这个概念应该不陌生,实际上,计算机中的抽象与哲学的抽象化非常相似。浪漫地讲,抽象思维能力可能是人类智慧的根源,是人类的智能不同于地球上其他生物的智能的原因。 + +要理解「抽象」,可以先来看看哲学的一个分支,即形而上学。形而上学很难定义,但简单来说,是研究事物本质、宇宙本源的学科。[^2]形而上学的一个分支是本体论,本体论的一个任务就是「给实体分类」,这种分类是有级别的,有的实体属于较为基本的实体,是较高层的。 + +> 本体论者经常尝试确定类别或最高类别是什么,以及它们如何形成一个类别系统,该系统提供所有实体的包含分类。通常提出的类别包括实体(英语:Substance)、性质、关系(英语:Relations)、事态(英语:State of affairs)和事件。 + +{{< right "——[本体论 (哲学) - 维基百科,自由的百科全书](https://zh.wikipedia.org/zh-cn/本体论_(哲学))" >}} + +如果你是一个熟悉面向对象编程和关系型数据库的程序员,你大概会觉得这些概念非常眼熟。实际上,程序员在编程时也一直在构造抽象(create abstractions)。本体论想要研究的「类别」系统,在计算机世界里也存在,例如,面向对象编程中的类和类的继承等概念,就构成了这样一个分类系统。 + +在 Java 语言中,所有类都继承自 `Object` 类,Java 中的任何数据类型都属于 `Object`;往下还有 `Number`、`String`、`Collection` 和 `Throwable` 等类;其中,`Throwable` 指「可以抛出的」,子类是可以抛出的错误(`Error`)和异常(`Exception`);再往下,还有表示更具体异常类型的子类,比如 `IOException` 表示执行 I/O 操作时发生了异常。 + +![](https://r2.eltr.ac/uPic/2025/06/Xo3L9M.jpg) + +只是划分出了层级结构还不行,无论是本体论还是计算机科学,在抽象化实体时,分类系统必须体现出这样一种层级关系:==层级越高,实体越抽象,元素越基本,在物理世界中能找到具体指代物的可能性就越小;层级越低则反之==。在这样一个分级系统的顶端,是一个最基本的类别,所有事物都可以被抽象为这个类别——在 Java 中是 `Object`,是本体论中的「最高类别」,也就是形而上学想要研究的「事物的本源」。 + +## 程序设计中的抽象 + +有关面向对象编程的教材,往往喜欢用学生熟悉的人和动物作为例子,让学生设计类并实现继承,比如,程序员可以编写一个 `Animal` 类,然后编写两个继承自 `Animal` 的 `Dog` 和 `Cat` 类;类设计好之后,程序员可以构建类的实例,比如: + +```java +Dog spot = new Dog(); +Dog lucky = new Dog(); +Cat elsa = new Cat(); +``` + +拿这个例子中的 `spot` 举例,它直接属于 `Dog` 类,程序员可以用它来表示一只名叫 spot(点点)的狗,同时,它又属于 `Animal` 类,可以访问 `Animal` 类的非私密成员方法和成员变量。 + +从另一个意义上将,这只叫做 `spot` 的狗,不仅有狗(`Dog`)的特征,也有动物(`Animal`)的特征。而同一个例子中的 `elsa`,属于 `Cat` 类,`Cat` 类也继承自 `Animal` 类。`spot` 和 `elsa` 有相同的特征,因为它们都可以被抽象为动物(`Animal`)。 + +抽象还可以继续往上或往下,我们可以 `Animal` 抽象化为 `Organism`(有机体),或者将 `Dog` 具象化为 `GoldenRetriever`(金毛)。如前文所述,这个过程不是简单的分类,而是将具体的特征抽离,留下共同的、更接近底层的特征,最终抽象出所有事物的共同特征。 + +==形而上学之所以想要认知事物的本源,其实是想要找到广泛适用的第一性原理,即对一切事物都有意义的真理==。在 Java 语言中,`Object` 类定义了 `toString()`(转换为字符串)的公开方法,我们可以把这个方法理解为 `Object` 的基本特征、适用于 `Object` 的一般原理。由于我们知道,`Object` 类在 Java 语言中是层级最高的、最基本的类,是形而上学的「事物本源」,那么,适用于事物本源的基本原理,当然就是适用于所有事物的第一性原理——在 Java 语言中,所有的类都可以调用 `toString()` 方法。 + +程序设计中之所以存在抽象层次,其实是为了帮助程序员更好地分解、理解和设计软件系统。程序员可以关注每一个抽象层次应该关注的任务,比如,在设计 `Animal` 类的时候,只考虑怎样让实体具有动物的特征,而不需要考虑如何让实体拥有生命(这是高层 `Organism` 应该考虑的事情),也不需要考虑如何让实体学会狗叫(这是低层 `Dog` 应该考虑的事情)。 + +简而言之,==抽象地认知事物、学会分辨概念的抽象层级,能帮助个体更准确地认识世界。选取合适的抽象层级研究事物、讨论事物,才能得出在某个语境下有价值的真理;如果选取的是最高级的抽象层次,那么得出的结论就是适用于所有实体的第一性原理——这是形而上学之本体论的目标==。 + +## 智能手机和书 + +回过头来看我在开头提到的辩论,我的论证材料是如何对书和智能手机进行抽象的呢? + +说是「书」,其实不太准确,我选用这个词只是为了归谬出「书让人变笨」的结论,用来反驳对手。苏格拉底反对的其实是「书写」(writing)。在引文中[^1],他将书写称作一种发明(invention)。「发明」其实就是对「书写」的一种抽象,与此同时,智能手机也是一种发明,也就是说,在这个语境下,智能手机和书处于同一个抽象层次上。 + +如果只是因为「书写是一种发明,智能手机也是一种发明」,就说「书写不会让人变笨,所以智能手机也不会让人变笨」,闹笑话的显然是我。**这样的逻辑谬误其实挺常见的,原因就在于选取的抽象层次太高了**,还不够具体。 + +智能手机和书写的共同特征还有「免去使用者的记忆之劳」——如果能把文字写下来随时查阅,人就会觉得自己不需要记住什么东西了;如果知道自己可以随时用手机查到需要的消息,人就会觉得自己不需要记住什么东西了。显然,这才是我需要抽离出的共同特征。 + +至此,我构建了这样的抽象层次结构:发明 → 免去使用者的记忆之劳的发明 → 智能手机、书写。这个结构是不完整的,各个抽象层次之间还能进一步地抽象,但在这个语境下已经足够了(软件设计时,程序员也不应该构建自己不需要的抽象)。我指出智能手机和书写处于同样的抽象层次「免去使用者的记忆之劳的发明」,并试图用「书不会让人变笨」来证明「智能手机也不会让人变笨」。 + +我自认为这个逻辑尽管用到了抽象,但显然是连贯的。如果要反驳,对手可以进一步指出智能手机和书的差异,比如引用《娱乐至死》中有关技术倾向的观点,指出智能手机是为娱乐而生的,而书不具有这样的特征——即,尽管书和手机同属于「免去使用者的记忆之劳的发明」这一抽象层次,但手机还属于「娱乐至死的产物」这一抽象层次,而书则不属于——对方辩手可以指责我讨论问题的方式太抽象,没能考虑到两种事物之间更具体的差异。 + +## 抽象的适用范围 + +抽象化的认知过程构建的其实是是一种「树」,可以表示为计算机科学中的一种数据结构。树这种数据结构并不能表示任意数据,因为它有一定的限制。 + +前文提到,书和手机处于「免去使用者的记忆之劳的发明」这一抽象层次下,而正方辩手可以指出,手机同时还属于一层书不属于的抽象层次,以此来反驳我的归纳不够具体。如果这样的话,对方辩手就构建了这样的抽象层次结构: + +![](https://r2.eltr.ac/uPic/2025/06/tCAcMD.jpg) + +但「娱乐至死的产物」一定属于「免去使用者的记忆之劳的发明」吗?反例:电视广告。如果把电视广告也加入到这张图中,会发现这个层次结构并不正确。我们只是抽象出了实体的一种特征,却不是最具有代表性的特征。不过,如果只是用来辩论,或就某一话题展开讨论,这样不完善甚至不正确的抽象层次也是够用的,因为我们的目的并不是像本体论哲学家一样构建所有事物的抽象层次,也不需要探寻事物的本源是什么。 + +对于本体论哲学来说,抽象是基于世间万物进行的,所有的实体都可以归类到同一个分类系统中。为了让这样一个庞大的抽象系统不因树形结构的局限性而发生错乱,每一层抽象的过程,都需要找到事物最接近本源的基本特征。在一层一层地抽象过后,就能找到所有事物的基本特征,完全符合这个基本特征且不包含其他额外特征的实体就是事物的本源。 + +对于一般的认知过程来说,抽象的目的不是为了找到事物的本源,也无需抽象出最接近本源的基本特征。抽象的目的是由语境而决定的,就像计算机程序的抽象是由软件需求决定的。通俗来讲,抽象就是「通过现象看本质」的过程。 + +## 抽象的词义演变 + +扯了太多哲学和计算机科学,我们回到语言这个层次上来。 + +抽象的动词释义是: + +> (2) 将复杂物体的一个或几个特性抽出去而只注意其他特性的行动或过程(如头脑只思考树本身的形状或只考虑树叶的颜色,不受它们的大小和形状的限制) +> +> (3) 将几个有区别的物体的共同性质或特性形象地抽取出来或孤立地进行考虑的行动或过程 + +{{< right "——[漢典](https://www.zdic.net/hans/抽象)" >}} + +由于抽象的反面是「具体」,所以作为形容词时,抽象也可以表示「笼统的」。我们说一个人讲话「太抽象了」,意思其实就是「太笼统了,让人摸不着头脑」。抽象的、笼统的的确要比具体的更难以理解,但将「抽象」等同于「难以理解的」是不恰当的用词,实际上,这是错误的抽象过程——不能因为「抽象」有「难以理解的」的特征,就说「难以理解的」就是「抽象的」,这两个概念不在同一个抽象层级上,「难以理解的」还有可能是多义词导致的「模棱两可」。 + +不过,语言的演变本身就充斥着各种误解和归纳错误。实际上,「形而上学」的英文 Metaphysics 就是一个被错误理解的单词。哲学家亚里士多德著作的编辑写下了 Metaphysics 这个单词作为标题,意为「在物理学之后」,表示这些内容应该在读过亚里士多德写的 Physics 之后再读,却被后人理解成了「超越物理学的」,形成了一门单独的学科。[^4] + +在文章的一开始我提到,「抽象」其实是来自日语的词,一开始是用来指代哲学概念的。不过,就像 WC(Water Closet)其实是一个建筑学专有名词,但到如今已经变成中国人委婉表达如厕地点的方式一样,==术语被挪用然后通俗化的现象,在语言的演变过程中非常常见==。 + +尽管这种误用可以被当作语言的自然演变,但我仍然倡导写作时应该精确地用词。在用「抽象」一词描述搞笑的东西和难以理解的东西之前,即使不刻意纠正,也应该想一想它原本的意思。 + +[^1]: “For this invention will produce forgetfulness in the minds of those who learn to use it, because they will not practice their memory. Their trust in writing, produced by external characters which are no part of themselves, will discourage the use of their own memory within them. You have invented an elixir not of memory, but of reminding; and you offer your pupils the appearance of wisdom, not true wisdom, for they will read many things without instruction and will therefore seem to know many things, when they are for the most part ignorant and hard to get along with, since they are not wise, but only appear wise.” ——[Plato, Phaedrus, page 274](https://www.perseus.tufts.edu/hopper/text?doc=Perseus%3Atext%3A1999.01.0174%3Atext%3DPhaedrus%3Apage%3D274) + +[^2]: 参见:[形上学 - Wikipedia](https://zh.wikipedia.org/zh-cn/形上學) + +[^3]: 参见:[抽象 - Wiktionary, the free dictionary](https://en.wiktionary.org/wiki/抽象) + +[^4]: “Aristotle did not use the term metaphysics but his editor (likely Andronicus of Rhodes) may have coined it for its title to indicate that this book should be studied after Aristotle's book published on physics: literally 'after physics'. The term entered the English language through the Latin word metaphysica.” 参见:[Metaphysics - Wikipedia](https://en.wikipedia.org/wiki/Metaphysics) \ No newline at end of file diff --git a/content/article/beast-inside.md b/content/article/beast-inside.md new file mode 100644 index 00000000..accd99a2 --- /dev/null +++ b/content/article/beast-inside.md @@ -0,0 +1,54 @@ ++++ +title = "被无限放大的动物性" +slug = "beast-inside" +tags = [ "生活", "性",] +categories = "乱章" +date = 2026-02-08T00:46:54 +draft = false +toc = false +toot = "https://akk.eltr.ac/objects/d3f404dc-4a5e-4404-9e0c-1fb75c98155b" +url = "/posts/beast-inside/" + ++++ + +在写下这行字的前一天晚上,我有了一段还算惊险刺激的经历。这件事情过去之后,我这个一直有些厌男的男人,终于发现了自己确实有着刻板印象里的男人的特征(或者说弱点)——无法避免被自己的下半身牵着走。别误会,我什么出格的事情都没干,但我的确有了些非常真实的体会。 + +事情是这样的,寒假我没有找到专业相关的实习,便回到了之前待过的教培机构工作,担任助教。学生基本是大学生,所以都还算能聊得来。前一天刚好结课,于是就有了一些出游的安排。还需要事先说明的是,我是一个会把感知和判断分开的人,也就是说,我感受到了某种东西并不代表我一定会基于这个感知做出决定,比如我觉得花很香,并不代表我一定会去摘这朵花。每天和我相处的基本上都是只比我小一两岁的学生(还有不少和我同岁甚至比我大的),虽然鱼龙混杂,教室里充满了臭直男的味道(字面意义上的臭,汗臭和不知道来源的味道),但偶尔也能见到对我有吸引力的男性。出于职业道德,以及不想惹麻烦上身,我从没有做出过任何行动,而且一两年内也就只遇见过一两个吧。 + +过去一个月,有在隔壁班见到一个矮矮的男生,经常能看到他在前台和客服姐姐聊天。两位客服姐姐跟我也算老朋友了,比较聊得来,所以上班摸鱼的时候都会跑到前台去跟她们聊天。因此,我经常能和那个男生打上照面。我觉得他的长相和行为都很可爱,尤其是笑起来的时候,所以见到了会忍不住多看几眼,仅此而已,毕竟也没有更多的交集了。 + +结课的那天下午,他所在的班级比我早结课,可他一直待前台没有走。到了下午,学生走了之后,还有员工的年前茶话会,一直持续到六点,然后就是聚餐。一直到我们出发去聚餐的时候,他都还没有离开,还问他的老师能不能加入我们,最后他也跟着来了。要补充的是,在开会之前,一位客服姐姐突然找到我,带着聊八卦的眼神跟我说那个男生的事情,大致意思是另一位客服姐姐认为他可能是双性恋,而他没有反驳,表示不确定、有些迷茫;然后他们顺水推舟,说可以把我介绍给他,而他对此的回应是:「他肯定不会喜欢我的。」最后,客服姐姐让我自己努力,我当时并不觉得会发生什么事情,直到聚餐快结束的时候。吃过饭之后,他先和朋友离开了,走之前我和他对视,然后他走过来问能不能加我的微信。嗯…… 我当然是很矜持地扫了他递过来的二维码。 + +聚餐结束后,我和两位客服姐姐以及一位年轻老师去酒吧玩,特地选了比较安静的小酒馆。之前说好要来的还有几位比较熟悉的学生,毕竟年龄差距不大,能玩到一起,但令人气愤的是,在等了将近一个小时之后,有四个学生突然改口说不来了。最后到场的的只有前面提到的那个男生。嗯…… 另外三个人当然在暗中用尽手段让他和我坐在一起了。 + +每次去酒吧的时候,我都会开玩笑说「我要做全场唯一一个清醒的人」,因为我患有的疾病不允许我喝酒。我点了一杯无酒精的莫吉托,另外三人点的是度数不低的饮品,坐我旁边的男生一边看菜单一边问什么酒度数高,最后还是点了啤酒,大概是碍于价钱的缘故。他一直在酒桌上说自己想要喝醉,因为之前从来没有喝醉过,然后另外三人似乎接上了他们之前就聊过的话题,我没太听明白。大概是说,她们认为他买醉的原因是受了情伤,因为他的一个好朋友在最近变得很冷漠,她们认为他实际上对那个朋友有近似恋爱的情感,所以会觉得对方的女朋友配不上他、会因为对方突然和自己交流变少而念念不忘。他当然没有承认,反复说自己只是因为之前没有喝醉过,想要试试而已。这部分话题我实在不太兴趣,剩下的就略去了。 + +这个男生很快就把一杯啤酒喝完了,在点第二杯之前,他还尝了另外三个人的饮料,我的没有被动过,因为没有酒精。后来玩游戏和聊天的时候,他显然已经酒意上头了。他还在纠结要点什么的时候,凑过来问我点的什么,知道我点的无酒精饮料之后他把头靠在我的肩膀上,抬着头瞪大眼睛问我为什么不喝酒。后面他借着酒劲儿,好几次往我身上靠,我记得有很长一段时间,我们两个的腿都是贴着的。如果要说我一点反应都没有,那肯定是骗人的。不过,这件事对我这个从来没有过恋爱经历的人(不算单恋的话),属实让人不知所措。 + +大概是因为觉得他太可爱,所以他性格里那些幼稚的部分没有被我注意到。他的一些行为的确很像小孩子,在事后想起来才觉得出格,比如他趁人不注意偷偷喝别人的饮料(据我朋友后来所说,那杯酒有四分之三都是被他喝掉的),为了引起注意往别人杯子里丢瓜子壳。后来,我们一致认为他真的有些神智不清了,想要让他打车回家。可是一而再再而三地都劝不走,他一直表示自己没醉(每个喝醉的人都会说的话),并且在气氛冷下来的时候叫其他人一起继续聊天。我们知道他第二天还有安排,八点就要到场,他在得知已经过了凌晨的时候,有些犹豫,但很快又恢复笑脸,劝朋友们继续玩,说他早上起得来。这种不愉快的气愤僵持了大概半个小时,才终于拖着他出了酒馆。 + +嗯,接下来就是惊心动魄的部分了。 + +出门没多久,他就拉着我的衣袖,带着我往前走。我不知道读者们能不能想象,一个比你矮一个头、有些娇小的、长相可爱还有点小帅的男孩子,轻轻拉住你,和你靠得很近的那种感觉。他有时还摇摇晃晃地,抬起头盯着我问我问题。我不知道怎么描述这种感觉,用诚实又带点粗俗的口气来讲就是:*不行了我真的要硬了。* I'm only human! + +不知不觉地,他就把我拉到了和朋友们间隔十几米的位置。他用软软的声音问我接下来要去哪,我说我要回家,他又问我我家住哪,很快,他又低下头,说他没有地方去。这里要补充一个背景信息:来这个机构学习的学生有很多都就读于距离较远的高校,通勤时间在四十分钟以上,所以不能住宿舍,一般会在附近的公寓短租。他的意思是,他租的地方到期了,想问今晚能不能住我家。他真的醉了,说完这句话之后就停下来,闭着眼睛说了两遍「就一晚、就一晚」。要说我真的没有一点把他带回家的冲动,那也是骗人的,但我非常清楚自己不应该这么做——我们正式认识才第一天,而且他现在意识不清醒。 + +我无助地回头,看见朋友们还在后面聊天(后来他们告诉我,是在商量要怎么把我救出来)。我正好手上还拿了东西,于是*战术性地*装作很忙,把东西收进包里,也顺便把挎包移到身体前面,~~压一压不应该起来的东西~~。听到我的呼喊过后朋友们加快脚步走了过来,我告诉她们他没地方去,她们一开始都不敢相信。据他所说,他一开始和一个同学合租,后来和前文提到的那个好朋友一起住,但现在那里的住处到期了,那个好朋友走了,他的行李放在机构那边,现在确实没有地方去。 + +是的,一个喝醉的大学生没有去处,现在另外四个清醒的人要帮他想办法。一个客服姐姐帮他出主意,联系了一开始和他合租的那个同学,还找了另一个靠谱的住在同一所公寓的学姐接应他;另一个客服姐姐确认他没有神智不清填错打车的目的地;同行的那位老师靠在我肩膀上[^1],一方面她也有些醉了,站不稳,另一方面她想护着我一下。很令人安心的组合,很快就把他安全送上车,也从接应的人那里得知他安全到达了。车到达之前,男生站在路边啪啪掉眼泪,大概原因是感觉我们想要赶他走。我是看不了人哭的,无论怎么样都会因为同理心想要照顾对方的情绪(除非对方真的疯狂试探我的原则底线,让我觉得他不值得我的善良)。他当时拿起我手上的一盒桌游,一边打量,一边带着哭腔问我之后还能不能一起玩,还问以后能不能去我家玩。还好朋友们帮我打掩护,不然我可能已经约时间了…… + +后来我们四个人决定走回家,好好聊聊刚才的经历,时间不早了,也好相互护送。其实今天的局进行到一半的时候,一个朋友就向我眼神暗示,告诉我「这个不行!」很显然,当时的我很上头,完全没有听进去。*全场唯一一个没喝酒的人竟然比全场喝得第二醉的人还不清醒。* 可其实就算事情进行到了这个地步,我也没有觉得刚才他做的事情是绝对不能接受的。在我看来他似乎只是害怕一个人,所以从今天下午结课开始就没有离开,晚上的酒局也想一直玩、不愿意散场,最后打车的时候也很不想一个人走。无论背后的原因是失恋了所以不愿意回到暗恋对象住过的地方,还是真的如他所说只是好朋友心情不好很早就走了,这种在极端情绪下不能忍受一个人待着的心情,我是能够理解的。我知道自己的同理心似乎有些过头了,大概是很容易被人精神控制的类型。此外,除了同理心还有另一个不可忽视的因素,就不必再提了。 + +回家路上我去上了个厕所,习惯性地掏出手机看消息,发现十几分钟前那个男生给我连续打了两个视频电话。我的手机一直是免打扰模式,所以没有接到。朋友很关心我现在的精神状态,建议我明天晚些时候再回,今晚不要再想和他有关的事情。 + +我向朋友们承认,他大概是激起了我的某种照顾欲,自然地,我受到了猛烈的批评,这种心态确实是不能有的。一天之后再回想起来,他的确有点像一个情绪黑洞,而且有好多事情都自己憋着不愿意说出口,很多像小孩子一样的行为实际上是为了引起别人的注意,很想和大家一起玩,但又不太能考虑其他人的感受。或许,在一开始,他吸引我的是那种像小孩子一样不会顾虑太多的简单和纯真吧,不过这很不成熟,而这种不成熟也给其他人带来了麻烦。 + +或许会有~~不怀好意~~参透人性的读者猜测我有没有在当天晚上睡觉之前做一些奇怪的事情,我只想说这个问题的答案是不言自明的。我在清醒的时候永远无法想象自己为什么在那种时候变得像动物一样渴望性爱。不过,这就是人嘛,人性也有动物性的部分。人可以靠近神性产生智慧,也可以临时降级为动物被简单的生理冲动支配,只是还好理智的人在大多数时候有自制力。 + +唔,越写越像个臭男人了,还是在合适的地方赶快结束为妙。 + +第二天早上七点四十,他给我发来消息:「学长,没有迟到」——因为昨天想让他早点回家的原因之一就是他早上八点有安排。我注意到,在我们四个朋友的小群里,有一个朋友说他在早上十点半的时候收到了类似的消息,也就是说,我是第一个收到消息的。我不知道如何解读。后来他发消息为昨晚的行为道歉,接下来的一天里都很太平。 + +希望在这样的小插曲之后,这个冬天能安安稳稳地过去吧。 + +[^1]: 写到这里突然想问问读者中的男同,你们的异性朋友也会这样毫无顾忌地靠在自己身上吗?或者女性读者能不能接受和熟悉的男同朋友有这样亲密的举动。印象中有好几个和我关系不错的女性都有这样的动作,不过基本上都是喝了酒之后。我倒是不介意,只是好奇这是不是普遍现象。 \ No newline at end of file diff --git a/content/article/buy-the-thing-not-the-brand.md b/content/article/buy-the-thing-not-the-brand.md new file mode 100644 index 00000000..7d0a38bd --- /dev/null +++ b/content/article/buy-the-thing-not-the-brand.md @@ -0,0 +1,100 @@ ++++ +title = "所有人都在交智商税" +subtitle = "Buy the thing, not the brand." +slug = "buy-the-thing-not-the-brand" +tags = [ "理财", "消费主义", "经济学", "自由",] +date = 2026-02-05T11:15:46 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/7a857559-700e-4922-9eb0-4cd63927aa47" +url = "/essays/buy-the-thing-not-the-brand/" + ++++ + +对经济学很感兴趣那一阵子,我读过一本叫《How to Teach Economics to Your Dog》(如何教你的狗经济学)的书,半途而废了,没有读完,不过有一句话我印象很深刻:*没有人能独自制成一台烤面包机。* + +仔细想想,烤面包机的技术含量实际上不高,它要做的只是把面包加热而已,但要制作出能够加热的电器,对包括机械工程师在内的所有人来说,都不是可能独自完成的事情。独自完成意味着你要独自研究烤面包机的工作原理,自己制作零件,甚至自己熔炼钢铁、开凿铁矿,在此之前还要想办法搞到一把用来挖矿的工具,*现实世界里可不能用两根木棍和三块圆石做镐子*。除非你把「自己动手制作一台烤面包机」当作自己的人生目标并为之奋斗,那么你是没有办法在闲暇时间里仅靠自己做出一台小家电的。 + +回到标题,我所说的「智商税」,实际上是指更广泛的因能力、智力、精力和**注意力**不足,而不得不通过花钱将一部分工作外包出去的做法。这对现代社会的运转来说是必要的,而且是有益的,每个人都可以提供用自身的能力、智力、精力和注意力创造的东西,换取金钱,再使用金钱兑换其他人的产物。人们能够通过发挥自己的比较优势创造出更多的价值。所谓的「用金钱购买别人的时间,以此让自己省心」,在我看来,并不算消费主义。消费主义是指认为不断购买商品和为服务支付是有益于经济的意识形态[^1],我在本文中不会从社会和经济层面讨论消费,我也没有那个能力,我想谈的是个体在进行消费决策时,应该如何平衡「花精力」和「花钱」这两件事。 + +## 一般意义的智商税 + +一些商品因为价格虚高、宣传噱头和实际效用不佳等性质,导致人们认为「购买这件商品的人都是傻子」,所以把这些消费者花出去的钱比作「智商税」,就像是在给低智商、没有判别能力的人征税一样。事到如今,这个词由于太传神,被广泛传播,也导致了滥用,成为了标签。我要说的是,那些动不动就称某件商品是智商税的人,和他们批评的人,也就是真的交了智商税的人,实际上没有什么两样。[^2] + +交智商税的人多半是因为自己没有判别能力,听信了宣传话术,继而做出了不理性的消费决策。然而,我观察到的大部分使用「智商税」这个词的人,并不会阐述某件商品是智商税的理由。我经常听到这样的对话: + +> “我买了一包洗衣凝珠。” +> +> “那不是智商税吗?” +> +> “啊,可是我觉得很好用啊?” +> +> “不如用洗衣液。” + +批评者可能有道理,但并没有办法证实,因为对方并没有给出理由,没有逻辑就没有逻辑漏洞。交智商税的消费者,实际上是听信了一种「说法」,也就是来自商家的说法,这种说法是具有迷惑性的糖衣炮弹;而批评者,许多时候,是听信了另一种说法,这种说法不来自商家,而是来自网络上的意见领袖、测评博主和身边的其他人。他们只是换了个队伍站而已。 + +从我有限的经验来看,能给出实在理由的人,也就是对商品的性质、种类、设计和原理都更加了解的人,并不会使用「智商税」这个词,或者,不会只使用「智商税」一锤定音。举个例子,我不推荐大部分人购买编程课程,因为程序员是最爱在互联网上分享的一群人,任何编程语言和构建软件的技术,几乎都有公开的文档和热心人士制作的教程,这些教程不仅是免费的,而且质量更好。与此同时,我理解有人会花上万的钱购买编程课程,原因可能有三个:一、权衡后选择将搜索和整理学习资料的工作外包出去,直接学习已经归纳好、更容易吸收的课程;二、受到十几年来的教育影响,认为学习必须通过上课来完成,不了解有其他途径;三、信仰知识付费,愿意支持知识工作者,通过支付金钱的方式鼓励更高质量的内容创作。除了第二个可以被视作低智商的某种表现以外,另外两种消费决策都很难说得上是交了智商税。[^3] + +简单来说,交智商税的人听信宣传话术,批评其他人交智商税的人听信评测博主。如果没有自己的思考,两者没有本质区别。 + +那么,要如何做出「自己的思考」呢? + +## 花费精力还是花费金钱? + +首先要明确的是,一些智商税是不得不交的,而另一些是可以通过支付精力来获得的。所以,在进行消费决策时,问自己的第一个问题就是:我愿意为这个东西耗费精力吗?第二个问题是:如果我不愿意,消费能够帮助我把精力用在别的更重要的地方吗? + +举个例子,前阵子有一家咖啡器具品牌推出了新的咖啡称,要价三百多。这个称的设计的确很好,在读数精准的基础上,配备了显示屏,能够直观地切换模式、查看冲煮曲线,以便更好地控制变量(总觉得手冲咖啡越来越像实验室制取咖啡因……)。在相关的内容下,我看到有人自己改装了一台称,把线缆接入开发板,连接显示屏,也实现了冲煮曲线的绘制。 + +尽管我已经被邪恶的消费主义文化改造得认为「三百多块钱买个称好像也没有很贵」,但看到有人愿意付出时间精力自己动手,还是觉得佩服。私以为,在商品经济建立起来以前,人们在大多数情况下都是需要自己动手的,而自己动手并不只是为了满足生活所需,还提供了某种满足感,就是生活的一部分。然而,现在却有越来越多的人把自己的生活外包出去,不去体会自己动手的乐趣了。我的想法是,对于自己并不在意、不感兴趣的物件,以消费的形式外包是很好的,比如我就没心思研究一台冰箱的工作原理,然后自己造一台冰箱。当然,有的人可能会感兴趣,但他多半会对造冰箱的某些部分不感兴趣,比如如何制造冰箱的外壳、如何制造感应灯、如何在冰箱太久没关门的时候发出警报…… + +我每过一两个月,就会想换新的手机壳(也有过裸奔的想法,但最终还是狠不下心来)。我的新想法是,与其在购物网站上浪费大把的时间找自己喜欢的手机壳,不如买一个透明的壳子自己设计图案,毕竟自己已经会做手帐了,而且我也真的很感兴趣。简而言之,我选择了把一部分原料的制造外包了出去,交了这一部分的「税」,把设计交给了自己,在这一部分上投入时间和精力。 + +我想,每个人的生活中一定有某些部分是愿意交给自己完成的,而不需要通过消费外包出去。做出了花费精力还是花费金钱的选择后,就可以继续论述了。如果你选择了花费金钱,那要如何确保自己交的不是「智商税」呢? + +## 如何筛选商品相关的信息? + +你可能会以为我要开始大谈「现在有了 AI 我们所有人都可以低成本、快速地了解到商品的基本信息并做出理性客观的判断了,现在买东西比以前更容易!」之类的话了——醒醒吧!OpenAI 已经在给 ChatGPT 添加广告了![^4]而且,有关商品的很多信息都被挡在平台上,完整的评论多半要登录才能查看,大语言模型是不会有这一部分数据的访问权限的,它只能收集到一些新闻报道、开放的评测网址和诸如 Reddit 这种平台上的讨论,来自中文互联网的内容更是少之又少。 + +更不用说,判断和决策这件事情本来就应该交给人类。我之所以坚持不乱用 AI 这个词,而使用更精确的 LLM(Large Language Models)和对应的中文名「大语言模型」,一方面是因为 AI 是一个非常广泛的概念,另一方面是因为,大语言模型做的事情真的只是「处理自然语言」而已——因为不具备产生意识的结构,所以无法在意识的层面处理想法,只能在语言的层面处理文字,把东西拼凑在一起。让这样的东西帮人做决策,是很可怕的。此外,你知道吗?由于日益增长的算力需求,电力需求也大幅增长,导致天然气发电量增大,温室气体排放也随之上升。如果美国目前计划的所有数据中心全部建成,二氧化碳排放量将来到所有能源年排放量的两倍。[^5]更不用提给服务器降温消耗的水资源了!不要觉得人工智能的成本很低,也不要再什么事情都求助 AI 助手了! + +回到文章的话题上来。显然,不同类型的商品有不同的考量。对于机械,无论是家电还是电子产品,需要关注「参数」,这是毋庸置疑的。这个思路也可以推广到其他商品上,比如,一个杯子有器型、材质、涂层和容量等性质,这些信息也可以抽象为「参数」。所以,==要筛选与商品有关的信息,就是要先明确应当关注哪些参数,然后在充满话术和噱头的商品详情页找到这些真正重要的信息。== + +任何空气净化器都会声称他们的净化能力很强,但了解之后就会知道这与滤网有关。一般来说,要达到好的净化效果,应该使用 HEPA 滤网(High Efficiency Particulate Arrestment,高效空气颗粒物拦截),这是一种技术规范。欧洲标准化委员会有为其指定等级标准,一般来说要购买 H13[^6] 等级及以上的空气净化器,才会有比较好的效果。此外,还有颗粒物 CCM,简单来说,这个参数的等级越高,表示滤网能够净化的颗粒物总重量越多,寿命也就越长,不容易出现频繁更换耗材的情况。相关的参数还有很多,要逐个了解,比较好的方式是搜索有经验的人写下的文章,另一个方式是查看相关产品的参数列表,把常见的名词记录下来,再一个一个地查询。 + +此外,适当地在社交媒体或商品评论区搜索评价也有帮助,比如我就在得知玻璃吸管可能会在日常使用中产生微小的破裂,是人眼很难发现的,玻璃渣可能会随着水一起进入身体,划伤食道。这是我通过搜索材质的性质和了解各种参数都无法得知的。之所是说要「适当」,是因为这些信息很杂,而且充斥着广告和水分,寻找有用的信息就像在辣子鸡里翻开辣椒找鸡肉一样。 + +在我看来最好的方式是寻找身边的真实用户,听他们的反馈和建议。我之前有一段时间想买一台用来洗袜子和内裤的小洗衣机,但我的朋友告诉我那个东西很难用。不过我没有听劝,购买之后才发现是真的难用:需要手动加水,中途漂洗的时候还要再加一次水;容量太小,一次也洗不了太多东西;还有红光杀菌,完全是噱头。后来我把它退掉了,购买了隔菌洗衣袋和除菌的洗衣液,这样就可以把内裤和袜子放在洗衣机里清洗。如果我当时听劝,或许早就想到这个方法了。 + +此外,一定要避免任何广告,广告非常擅长创造需求,诱导人购买他们根本不需要的东西。真正理性的消费决策应该是在了解自身需求,并且确定需要购买一个产品来满足这个需求,再对产品本身进行研究和评估之后做出的。是的,这很麻烦,但不费点精力怎么能守好自己的钱包呢? + +在一个理想的世界里,商家会把产品参数放在最显眼的位置,商品详情页不会有人和误导人的话术,各种技术指标都会公开,消费者可以清晰地了解到自己是在为了什么而付费,为什么商品要定这个价。可惜我们并不生活在这样的世界里,所以需要自己把这些信息筛选出来,再做判断。 + +## 如何处理与品牌的关系? + +在《[制造消费者](/library/2025/制造消费者/)》这本书里,作者提出了一个有意思的观点: + +> 现代人与市场的关系让我们对物品感到越来越陌生,也因此觉得它们越来越「神秘」,并产生一种类似宗教信仰的崇拜。如今人们不再关心商店里售卖的清洁剂是不是白醋和小苏打的混合物,只关心商品的品牌,用品牌和品牌对商品的塑造判断清洁能力的高低。 + +==之所以要自己筛选信息,就是要重新建立对物品的关怀,而不是相信甚至崇拜品牌。== 判断一块清洁海绵能不能把盘子刷干净,看的不是海绵的品牌,而是海绵的材质和设计,更重要地,要看自己能不能亲手用这块海绵把盘子刷干净。与其买看起来很可靠的清洁品牌的除水垢剂,不如直接买一斤一水柠檬酸粉末,只要五块钱左右,能用很久,而且除水垢效果真的很棒。 + +简而言之,某个产品好用,并不是因为品牌施展了魔法,而是因为它本身的性质使得它很好用,后者才是最应该关心的。 + +诚然,品牌无处不在,一些品牌的确把品质控制得很好,值得信赖,他们的产品也值得反复购买。不过,我想要提出的观点是:人们应该自己建立与品牌的信任。如果只是因为看到其他人在使用这个品牌,或者听信了社交媒体和视频平台上的宣传,就对某个品牌产生好感,是不恰当的。 + +可以把品牌理解为一个黑箱,毕竟他们真的不公开透明。与其把这个黑箱贴上好用或难用的标签,不如自己做黑箱测试,试试看好不好用,有没有更好的选择。更好的方法是做白盒测试,把黑箱拆开,了解和验证产品的参数和规格。完成测试并得出结论之后,在持续的与品牌「合作」的过程中评估这个品牌是否值得信赖。比如,我比较信任的咖啡烘焙商是 Collin Plus 和绝对小孩,这种信任是在反复从他们那里购买商品并使用后建立起来的。对于品牌的信任不像对人,需要随时评估和做判断,如果发现原来值得信任的品牌突然变得不可信,也要相信自己的判断,寻找新的「合作关系」。比如,嗯…… 我现在就不太信任 Apple 了。 + +减少对品牌的依赖也是重要的。不过,就像使用开源自由软件而非 SaaS 一样,更自由、更开放也不用依赖于某个中心,这也会带来一些麻烦,使用开源软件就是会比包装好的商业软件更难,这是自由必须支付的代价。==购买商品也是如此,无论如何你都要支付代价,要么放弃思考、打开钱包,大喊「Shut up and take my money!」,交上你的智商税;要么做个吝啬但敏锐的人,选择支付精力和时间,换取自由、更少的花费和完全属于自己的生活。== + +这两种都是不错的,全看自己的选择。至于我,我选择后者。 + +[^1]: 参见:[Consumerism - Wikipedia](https://en.wikipedia.org/wiki/Consumerism) + +[^2]: 这里可以联系到《[警察警察与警察警察警察](/essays/警察警察与警察警察警察/)》这篇文章中的观点:人们相互讨厌,可能只是因为他们是同类人。 + +[^3]: 还有一个原因:一些人觉得自己花了钱就一定能学好,以此来获得心理安慰,到真的没学好的时候,还能把责任转嫁给课程制作者,指责课程设计不合理,继而避免质疑自己的学习能力。这是心理学的话题了。 + +[^4]: 来源:[Ars Technica](https://arstechnica.com/information-technology/2026/01/openai-to-test-ads-in-chatgpt-as-it-burns-through-billions/) + +[^5]: 来源:[The Guardian](https://www.theguardian.com/environment/2026/jan/29/gas-power-ai-climate) + +[^6]: 滤净率达 99.95% 以上 \ No newline at end of file diff --git a/content/article/clean-home.md b/content/article/clean-home.md new file mode 100644 index 00000000..fa41a5a1 --- /dev/null +++ b/content/article/clean-home.md @@ -0,0 +1,204 @@ ++++ +title = "程序员和整洁的 Home" +slug = "clean-home" +tags = [ "Geek",] +date = 2026-01-11T13:19:37 +draft = false +toc = true +toot = "https://c7.io/@eltrac/115874785708787310" +url = "/essays/clean-home/" + ++++ + +去年八月,我在少数派上读到了一篇题为《[码农的自我修养之保持干净的 $HOME 目录](https://sspai.com/post/101780)》的文章,从那个时候我就开始注意自己的 Home 目录。如果你不知道 Home 目录是什么:它是多用户操作系统中,系统为每个用户单独分配的目录,其中存放与该用户相关的文件,比如只为这一个用户安装的软件、下载文件、系统回收站、配置文件、数据文件和缓存等。 + +在类 Unix 系统下,可以用 `~` 表示当前用户的 Home,在终端执行 `cd ~` 就可以「回家」。Windows 系统下比较少提及 Home 目录,常见的是 `%APPDATA%`,这也是存放在用户的 Home 目录下的子目录。有不少操作系统有名为「文档」或 Documents 的用户目录,也是存放在 Home 目录里的。 + +Home 目录常被用来存放该用户的数据文件、配置文件和缓存文件,所有应用程序都可以进行读写。然而,不是所有用户程序都遵守规范(实际上也没有**强制**执行的使用 Home 目录的规范),有的软件会在「文档」而非 Home 目录下存储数据文件,有的软件会在 Home 根目录下创建多个点文件(dotfiles),有的软件相对守规矩,会把各种类型的文件都放在一个点目录里。不少操作系统默认的文件管理器都有提供 Home 目录的快捷方式,不少用户也会直接在 Home 目录下存储各种文件。 + +总而言之,如果不主动干预,Home 目录就会变得非常混乱。用户可以选择眼不见为净,毕竟点文件默认是隐藏的,不主动查看就难以发掘。如果你和我一样对自己的电脑有着奇怪的掌控欲,那我建议你继续读下去。 + +## 为什么要保持 Home 的整洁? + +简单来说,混乱的 Home 目录会导致以下问题。 + +配置文件、数据文件和缓存文件没有分离。一般而言,配置文件和数据文件是用户需要保留的,即便更换设备,配置也可以迁移;配置文件往往是需要用户直接编辑的,而数据是操作软件时产生的,由软件读写;配置文件可以分享(例如 NvChad、LazyVim 等就是 NeoVim 的配置文件),而数据涉及到隐私,往往需要保护;缓存文件可以随时删除,不会影响软件正常运行[^1]。 + +我不太想把保持 Home 的整洁称作某种程序员应有的素养,因为这并不会让你的开发能力有任何提升,就像在中小学值日做清洁并不会让你的学习成绩有提升一样。让各种软件在同一个目录下打架并不会影响软件运行和日常工作,只是增加了管理成本——如果你完全不管理,那就无需在意了。 + +但如果你在意自己的数据,容忍这些文件乱作一团真的是件坏事。这和家政是一样的,如果你在意这件事情,那么容忍熵增只会让自己难受;如果不在意,以素养或责任一类的说辞裹挟自己也不利于自己的心理健康。 + +## 如何保持 Home 的整洁? + +整洁就是「整」和「洁」——有条理,且没有杂质。还是用家政举例,我们把食物放在冰箱里,把衣物放在衣柜里,把书本放在书架里,物品有了各自的、确定的去处之后,它们就不会乱作一团了。在我们需要某种物品的时候,我们也能通过分类来快速定位。 + +分类其实不是件难事,真正困难的是处理人与人之间的矛盾。假设你喜欢把扫把放在阳台,而你的室友总是把它留在客厅,你大概就会对室友的行为感到不爽。现在请想象,你是一间公寓的房东,你的房子里住了很多人。出于某些原因,他们全都共享同一个空间。每个人对物品的分类标准都有所不同,把扫把放阳台还是客厅的争论肯定少不了,而你作为房东,大概也有自己的偏好,看到自己的房子被弄得乱七八糟,心里肯定也会觉得不舒服。到底有没有办法解决这个局面呢? + +最简单的解决方式当然是设置统一的分类标准,强制要求大家都把扫把放在杂物间就好了。然而,计算机的世界要比合租更复杂一些。在前面的比喻里,房东是用户,租客是用户安装的软件,我们假设软件在哪里存放数据是能够自由更改的,并且一个软件只会存在于一个用户的电脑上。在计算机世界里,软件是可复制的,同样的软件会被分发给不同的用户,不同的用户可能有不同的存放数据的偏好。 + +单房东和多租客的情况下很容易达成共识,大家都听房东的话就好了。多房东和多租客的情况则复杂得多。假设房东告诉你应该把扫把放在阳台,二房东告诉你扫把要放在杂物间,而二房东的丈夫则要求你把扫把放在客厅,那你到底要听谁的? + +作为租客,你需要考虑的其实只有「把东西放在该放的地方」这个问题,在这个比喻里,就是要「把扫把放在专门放扫把的地方」。现在的情况是这样的: + +- 房东眼中的「专门放扫把的地方」 = 阳台 +- 二房东眼中的「专门放扫把的地方」 = 杂物间 +- 二房东的丈夫眼中的「专门放扫把的地方」 = 客厅 + +这些值表达的语义是相同的,但在不同的人眼里,实际的值是不同的。引用名相同,但是在不同的情况下赋值不同,这有让你想到什么东西吗?没错,就是「环境变量」。 + +现在我们脱离有关租房的比喻,回到计算机的世界来。如果程序员在开发时不武断地硬编码一个存放数据的文件路径,而是读取相关的环境变量,了解用户希望某种类型的数据文件应该被放在什么地方,前面提到的问题就迎刃而解了,而且,用户真正地掌控了自己数据的存放位置。 + +事实上,大部分程序员已经在这样做了。Home 目录的具体路径就是一个环境变量,这个变量一般由操作系统维护,赋值为当前用户的 Home 目录绝对路径。比如,在 macOS 下,如果以 `eltrac` 的身份登录,环境变量 `HOME` 的值就是 `/Users/eltrac/`。 + +但我们需要更进一步,因为现在的做法就和「应该把扫把放在家里」没有区别。有没有一个类似于现有的 `HOME` 目录的规范,让程序员能够分门别类地将不同的数据存放在用户通过环境变量指定的目录里呢? + +## XDG 基本目录规范 + +XDG 基本目录规范(XDG Base Directory specification,缩写 XDG BDS)是由 Waldo Bastian、Allison Karlitskaya、Lennart Poettering 和 Johannes Löthberg 提出的。XDG 是 X Desktop Group,现名 freedesktop.org。名称中的 Free 指代的是「自由软件」的概念,这个项目致力于为自由软件桌面环境制定规范,让它们能够互通和共享基本技术。 + +如果你不清楚什么是「桌面环境」,请想象你的操作系统和你正在操作的桌面、图形界面和光标等元素是分离的,不是所有操作系统都有这些东西。桌面环境运行于操作系统之上,为用户提供图形界面,对于现代的个人电脑来说是必要的。Windows 和 macOS 和许多 Linux 发行版自带桌面环境,对于 Linux 这样的开源操作系统来说,用户可以自己选择桌面环境。我自己比较熟悉的是 KDE 和 Gnome。 + +文件系统并非是通过桌面环境实现的,所以看到 freedesktop.org 编撰这样一个规范,我是觉得有些奇怪的。不过细想也合理,毕竟如此在意文件整洁的人,可不就是喜欢折腾开源自由软件的桌面端 PC 用户嘛。 + +完整的规范可以在[这里](https://specifications.freedesktop.org/basedir/latest/)阅读全文,本文主要提及此规范为指定文件存储路径所规定的几个环境变量。这些定义有系统级和用户级的,由于我们在本文只讨论 Home 目录,固然只会涉及用户层级。此外,如果你还没有意识到——本文内容只适用于类 Unix 系统用户,也就是 macOS 用户和各大 Linux 发行版的用户。 + +- `XDG_CONFIG_HOME`:储存软件的配置文件。用户可以更改这些文件来调整软件行为;用户在更换设备之后也能迁移这些配置文件,在新设备上获得相同的软件体验。 +- `XDG_CACHE_HOME`:不重要、可以被删除的数据,即缓存。 +- `XDG_DATA_HOME`:持久的数据,是用户拥有的「内容」。假设你有一个遵循此规范的笔记软件,而你没有指定笔记的存储位置,它就可以默认把笔记写在这个位置。 +- `XDG_STATE_HOME`:持久的数据,是软件的「状态」记录。假设你有一个遵循此规范的笔记软件,它可能会把编辑历史、窗口布局都软件在运行时产生的数据存放在这里。 + +用户层级下还有一个 `XDG_RUNTIME_DIR`,但默认情况下这个环境变量并不会指向 Home,大部分用户也不会用到它,本文就略过了。 + +对于用户来说,这样的划分使得 Home 目录更整齐了,与系统交互时也更省心——要更改配置,就在 `XDG_CONFIG_HOME` 找相应的文件;要清理缓存,就把 `XDG_CACHE_HOME` 目录下所有的文件都放心地删掉;要迁移或备份数据,直接操作 `XDG_DATA_HOME` 目录就好;至于 `XDG_STATE_HOME`,用户在大部分情况下不用管。 + +对于开发者来说,在读写文件时直接使用系统的环境变量很方便,例如 Go 语言提供了 `os.Getenv()` 方法访问环境变量。当然,不是所有的用户都设置了 XDG 环境变量,如果没有找到相关的环境变量,软件可以回退到直接在 `HOME` 目录下读写。 + +## 现实中的 XDG BDS + +freedesktop.org 算不上什么权威组织,基本上只有使用 Linux 桌面系统的黑客才会在意 XDG BDS 规范,当然,如今也有不少 macOS 用户会关注 Home 目录是否整洁,但总体而言是比较小众的需求。XDG BDS 不像 RFC(Request for Comment)的一系列互联网技术规范,理应被严格遵守。它更像是一种观点、一个流派,没有人必须遵守,就像尽管提升柔韧度有助于避免运动受伤,也不是所有健身人士都注重拉伸。 + +开源、自由软件一般都会遵守目录规范,即便维护者本人没有这个意识,用户中的黑客也会有人提出建议或贡献代码,要求实现 XDG BDS。如果你使用的软件大部分都是自由软件,那你基本上不会遇到特别令人头疼的钉子户…… 不过,先让我们搞清楚什么是真正的自由软件。有不少软件有着自由的开源协议,但实际上是由某个公司开发的,不受开源社区控制。 + +我举一些我遇到的钉子户案例。 + +1. Logseq:设计和 org-mode 气质相似的大纲式笔记软件,算是我最喜欢的笔记软件。它是自由、开源软件(free and open-source),但是并不支持 XDG BDS。它实际上由 Logseq Inc 开发和运营。在 2021 年十二月,[@Hsins](https://github.com/hsins) 提交了 [Issue#3462](https://github.com/logseq/logseq/issues/3462),提议遵循 XDG 规范,但直到现在,这个提议没有任何代码层面的进展。如果你现在安装 Logseq,它仍然会在你的 Home 目录下直接生成一个 `.logseq` 目录。 +2. Claude Code:很受欢迎的 LLM 编码工具实际上是闭源的,现在他们的 GitHub 仓库里有 4.5k 个 Issues,其中有三四条和 XDG BDS 相关。相关的 Issues 几乎都没有收到开发者的回复。根据某条 Issue 的内容,Claude Code 的某个版本曾支持了 XDG BDS,但在后来的某个版本又撤回了这个更改。可以看出,Claude Code 开发团队里几乎没人在乎这个规范。现在,Claude Code 仍然肆无忌惮地在你的 Home 目录下生成三个乱七八糟的文件——`.claude` 目录、`.claude.json` 和 `.claude.json.backup`。 +3. Codex:OpenAI 提供的类似于 Claude Code 的产品,也不支持 XDG BDS,但开发团队有直接回应: + - ![](codex-issue.png) + - 大概意思是,经过团队讨论,为了保证实现简单和各个平台的一致性,我们决定现在不支持这个规范。 +4. Bun:很受欢迎的用 C++ 编写的 JavaScript 运行时和开发工具,速度很快,近期被 Anthropic 收购了。Bun 的 GitHub 仓库下有相关的 [Issue#1678](https://github.com/oven-sh/bun/issues/1678),有很多提议和讨论,但仍然没有代码层面的实现。因为我无法忍受 Home 目录下有一个无法删除和移动的 `.bun` 目录,所以我仍然在使用 Node.js。 +5. Maven:Java 的依赖管理器,会在 Home 目录下生成一个 `.m2` 目录存放依赖文件。嗯,我是不指望 Java 系的工具支持 XDG 规范的。所以在我完成了大学里所有 Java 相关的课程后,直接卸载了所有的 Java 开发工具。[^2] + +简单来说,XDG BDS 的现状就是:它本身不是强制执行的规范,只是一种观点,不是所有软件都支持。对于闭源软件和商业软件,可能没有太多的操作空间,但是对于开源软件,还是可以通过提交反馈和直接提交代码来促进规范实现的。我最近在用又拍云的 CLI 工具 [upx](https://github.com/upyun/upx),它就不支持 XDG BDS,代码是用 Go 语言写的,很亲切,与是我就自己实现了规范并提交了 Pull Request。就算他们不合并也没什么关系,因为我已经构建了支持 XDG BDS 的版本并替换了安装在我电脑里的二进制文件——这是开源软件的好处之一,如果有用着不习惯的地方,就可以自己 Fork 一份修改。 + +值得一提的是,有不少开源软件尽管没有直接实现 XDG BDS,但是有定义专用于这个软件的环境变量,用户可以自由指定数据文件的存储路径。比如 GNU PGP Guard 就会读取 `GNUPGHOME` 这个环境变量,如果读取到了用户自定义的值,就会把文件写在指定的位置。对于这样的软件,用户需要手动设置环境变量来支持 XDG BDS。以下是我的 `.zshrc` 文件中的一行。 + +```zsh +export GNUPGHOME="$XDG_DATA_HOME"/gnupg +``` + +综上,如果你想要通过 XDG 基本目录规范来整理你的 Home 目录和点文件,你需要做好以下心理准备: + +* 你会遇到你无法改变的、不支持 XDG 规范的软件 +* 你可能需要作为规范的推进者,向开源软件提交建议和贡献代码 +* 你需要做很多额外的配置,甚至用歪门邪道调教软件,让它们把文件放在你想要的地方 +* 你需要迁移现有的配置文件和数据文件 + +如果你准备好了,甚至觉得这很好玩,那我们就继续吧。 + +## 作为用户实现 XDG BDS + +首先,你需要配置环境变量,先告诉那些本身就尊重 XDG BDS 的软件:我也遵循 XDG BDS,我希望你们把文件放在以下这些目录里。默认的、最简单的配置如下: + +```zsh +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_CACHE_HOME="$HOME/.cache" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_STATE_HOME="$HOME/.local/state" +export XDG_RUNTIME_DIR="/run/user/$UID" +``` + +你需要先知道你用的是什么 Shell(常见的有 zsh、bash 和 fish),你可以通过在终端输出环境变量 `SHELL` 来查看你所使用的 Shell 的二进制文件路径,这样一来就能确定你用的 Shell 是什么了。 + +```zsh +➜ ~ echo $SHELL +/bin/zsh +``` + +我用的是 zsh,接下来也使用 zsh 作为示范。 + +首先把上面的环境变量配置复制粘贴放在 `/etc/zshenv` 这个文件里,如果是其他 Shell,则需要自行查阅添加环境变量的位置。写在 `.zshrc` 这样的用户级配置里也是可以的,但 `.zshrc` 的默认存放位置是 `~/.zshrc`…… 是的,它本身就在 Home 目录下随意地摆着。如果你想把 `.zshrc` 也移动到它该待的地方(`~/.config/zsh/.zshrc`),你应该在系统级的配置下操作,因为 zsh 默认不会在符合 XDG BDS 规范的目录下查找配置文件。 + +在 `/etc/zshenv` 文件里写入以下内容: + +```zsh +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_CACHE_HOME="$HOME/.cache" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_STATE_HOME="$HOME/.local/state" +export XDG_RUNTIME_DIR="/run/user/$UID" + +export ZDOTDIR="$XDG_CONFIG_HOME/zsh" +``` + +请注意我还在最后添加了一个 `ZDOTDIR`(Z Dot Directory)环境变量,这是为了告诉 zsh 把点文件放在 `XDG_CONFIG_HOME` 下,因为正如前文所提到的,zsh 不会读取 XDG 相关的环境变量。 + +接下来重启 Shell,尝试输出这些环境变量确认配置是否完成。 + +```zsh +➜ ~ echo $XDG_CONFIG_HOME +/Users/eltrac/.config +``` + +能正常输出就没有问题了,你已经完成了环境变量的配置。接下来,支持 XDG BDS 的软件就会自觉地把文件放在你指定的地方。根据我们的默认配置,这些位置分别是: + +- 配置文件:`~/.config` +- 缓存文件:`~/.cache` +- 数据文件:`~/.local/share` +- 状态文件:`~/.local/state` + +你可以随意修改,把数据放在你想要的位置,编辑环境变量即可。不过我偏好保留默认配置。 + +不过,你的 Home 目录还是和以前一样乱,因为支持 XDG BDS 的软件并不会自动帮你把原先的文件移动到环境变量里指定的位置,它们只是会优先在你指定的位置进行读写而已。然而,鱼龙混杂的软件中免不了有好几个不默认支持 XDG BDS、需要额外配置的软件,甚至有的完全不支持。如果贸然把所有的文件都迁移到 XDG BDS 目录下,会有大量的软件无法读取到原先的数据文件而出现问题。更致命的是,我的 Home 目录本来就很乱,我怎么分得清哪些是配置文件,哪些又是缓存和数据文件? + +## Ninja to the rescue! + +你可以安装 [xdg-ninja](https://github.com/b3nj5m1n/xdg-ninja) 这个命令行工具,它会扫描你的 Home 目录,列出他识别到的文件,给出配置、迁移指南和注意事项——哪些文件可以直接删除、哪些软件需要额外配置环境变量、哪些软件需要用到一些歪门邪道,全都罗列得很清楚。不过,xdg-ninja 也并非万能,如果你遇到没有识别到的目录或文件,可以考虑自行寻找解决方案后为 xdg-ninja 提交 Pull Request。 + +![](xdg-ninja.png "xdg-nija 的输出示例。") + +xdg-ninja 会引导你配置额外的环境变量,你可以放在系统级的 `/etc/zshenv` 里,也可以放在用户级的 `~/.config/zsh/.zshrc` 里。由于有不少开发环境和系统工具不会读取用户级配置,所以我的做法是把所有 XDG BDS 相关的配置都放在 `/etc/zshenv` 里。 + +记得每次更改之后都重启 Shell,也可以执行 `source /etc/zshenv` 或 `source ~/.config/zsh/.zshrc`。由于我频繁操作 zsh 配置,所以我写了一个命令行 alias: + +```zsh +# Quickly edit zsh config +alias zshconf="nvim ~/.config/zsh/.zshrc && source ~/.config/zsh/.zshrc" +alias zshenv="sudo nvim /etc/zshenv && source /etc/zshenv" + +``` + +在终端执行 `zshconf` 就可以用 NeoVim 打开用户级配置文件(用 `zshenv` 打开系统级配置文件),保存并退出之后就会执行 `source` 命令应用更改。 + +依照 xdg-ninja 的文档进行配置之后,就可以放心地把文件移动到它该待的地方了。这会花点工夫,而且不是一劳永逸的——如果有新的软件被安装,你可能还需要进行配置,不然 Home 又会随着时间推移而变乱。 + +至于那些不支持 XDG BDS 的软件,我的建议是提交 Issues 或贡献代码,推进规范的实现。如果是闭源软件,那…… 换成开源的替代品,嗯。我就把 Claude Code 换成了 [OpenCode](https://opencode.ai/),好用,开放,还能让我的 Home 变干净。 + +--- + +这是我目前的 Home: + +```text +/Users/eltrac +📁 .cache 📁 Applications 📁 Movies ⚙️ .CFUserTextEncoding +📁 .config 📁 Desktop 📁 Music ⚙️ .DS_Store +📁 .local 📁 Documents 📁 Pictures 🔗 .nix-profile +📁 .ssh 📁 Downloads 📁 Projects 📝 Brewfile +📁 .Trash 📁 Library 📁 Public +``` + +其中 `.Trash`、`.CFUserTextEncoding` 和 `.DS_Store` 是 macOS 在 Home 目录下生成的无法移除的文件,是 macOS 用户不得不接受的事实。除此之外,我对我现在的 Home 很满意。以及,我也会允许个别系统级工具在 Home 目录下占有一席之地。 + +[^1]: 其实还可以细分出更多的文件类型,比如状态数据和运行时文件,这里就略过了。 + +[^2]: 不过,这玩意好像很难彻底移除,我能不用 Java 开发,但我无法避免用 Java 编写的软件。在写这篇文章的前一天我开始折腾 Clojure(一门 Lisp 方言),结果发现 `.m2` 目录又回来了,里面装了一个 Clojure 的依赖…… \ No newline at end of file diff --git a/content/article/deleting-bookkeeping-app.md b/content/article/deleting-bookkeeping-app.md new file mode 100644 index 00000000..739d7aa9 --- /dev/null +++ b/content/article/deleting-bookkeeping-app.md @@ -0,0 +1,22 @@ ++++ +title = "我删掉了记账软件" +subtitle = "我不是财务,维护账目是痛苦的。" +slug = "" +tags = [ "个人理财",] +categories = "生产力报告" +date = 2026-02-23T17:33:15+08:00 +draft = true +toc = true +url = "/posts/deleting-bookkeeping-app/" + ++++ + +使用常规记账软件对我来说是痛苦的,因为既然要记录收支,那就理应精准无误,漏记或误记会让我感到不安。一些记账软件还提供了资产管理功能,即把每笔消费都和一个账户关联起来,余额随收支记录变动,要维护的数据更多。这大概不是软件设计问题,至少软件的内部逻辑很通顺,只是实操上没办法取悦我这个多少有些强迫症的用户。简单来说,维护账目要消磨太多精力了,我又不是财务,我的资产也不需要像企业一样管理。 + +我养成记账习惯快三年了。进入大学时,每个月会拿到一笔数目不小的钱,必须好好规划,避免超支,还是大一的我就意识到自己应该使用记账工具,而不是每隔一段时间盯着微信余额发懵。我不是自律,只是焦虑而已。 + +很快我就因为记账流程太繁琐而再次感到焦虑。请想象我站在人满为患的食堂里,刚排完队付完款、拿到餐食,由于担心漏记账目,于是一手拿手机,一手拿盘子,一边找位置一边在记账软件里添加新条目,还要避让从面前走过来的人,其中的一些还*非常吓人地*端着油辣的汤水。后来我发现了带有自动记账功能的软件,可以通过 iPhone 的辅助功能触发,比如轻敲手机背面两下触发某个快捷指令,快捷指令触发截图,截图再交给 App 处理,识别文字填写金额。之后我还发现了具备 AI 功能的自动记账软件,能从截图中获取除了金额外的其他信息,比如消费类别、消费名称和购物软件的名称等等。 + +先不谈把交易信息上传到云端,交给来历不明的大模型进行处理,对隐私的威胁有多大,我很快发现了新问题:我对消费的感知降低了。 + +小心翼翼逐字输入的记账方式,让我实在地感知到「我花出去了一笔钱」。数字支付取代现金支付后,大部分人应该都有体会,如今花钱不如现金支付那样有实感,只要数字的变化没有特别大,就不容易感到「肉疼」。对我而言,记账弥补了负反馈的缺失,每一次手动键入都在提醒我「我花钱了」。然而,自动化又把这种负反馈剥夺了。事实上,我不喜欢自动化工作流的很大一部分原因也在于反馈的缺失。笔记内容会不知不觉地发生变化,想想就很可怕。我不看好用 LLM 记笔记也是这个原因:如果全都自动化了,人脑没有参与,放在笔记库里的文字又和互联网上的内容有什么区别? \ No newline at end of file diff --git a/content/article/deploying-static-sites.md b/content/article/deploying-static-sites.md new file mode 100644 index 00000000..06e1c1bb --- /dev/null +++ b/content/article/deploying-static-sites.md @@ -0,0 +1,220 @@ ++++ +title = "如何优雅地部署一个静态网站?" +tags = [ "DevOps", "Geek", "Web",] +slug = "deploying-static-sites" +categories = "代码炼金术" +date = 2026-01-28T18:07:29 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/45dac016-6cd7-4874-b919-5107f5d9fdf3" +url = "/essays/deploying-static-sites/" + ++++ + +PaaS 软件用了太久,导致自己对部署网站这件事产生了很多不切实际的想象,总感觉不使用 Vercel、Netlify 和 Cloudflare Pages 就不够现代。实际上,静态网站就是一系列 HTML 文件和必要的静态资源而已,即便是用 Hugo 和 Hexo 等静态网站生成器,得到的也是相同的文件。这些文件如果被用户下载到本地,用浏览器直接打开,也能够正常浏览,毕竟不涉及任何服务端的计算,那为什么还要把事情弄得这么复杂呢? + + + +## 使用 PaaS + +PaaS 的意思是平台即服务(Platform as a Service),可以把平台理解为开发和运行应用的基础设施,PaaS 提供了这些设施,降低了开发者进行运维工作和开发过程中部分工作的复杂度。比如,你编写了一个 Web 应用,通常情况下你需要购置一台服务器,然后配置应用的运行环境、配置 Web 服务器和反向代理、申请 SSL 证书并管理续期、设置防火墙和其他必要的安全措施、维护数据库、维护依赖等等,当应用的代码更新之后,你还需要重新部署。 + +PaaS 能让开发者做到,直接提交代码库给平台,应用就能跑起来并且运转良好,并且往往具有持续集成和持续部署(CI/CD)的能力,使得新的代码在推送到仓库主分支过后就能自动构建并部署应用。 + +与之相似的架构是 Serverless,也就是无服务器架构。这两种架构其实都极大地弱化了后端的存在,不过 Serverless 更偏向通过事件触发的云函数,而非随时在线的常规 Web 应用。这里略过不谈。 + +使用 Vercel、Netlify 和 Cloudflare Workers/Pages 这样的服务构建和部署静态网站是可行的,并且非常简单,一般来说步骤是这样的: + +1. 将你的网站源代码推送到远程 Git 仓库。 +2. 在 PaaS 平台创建一个新的应用,设置 Git 仓库并选择软件架构(如果是 Node.js 等常见技术栈,成熟的 PaaS 平台往往会自动识别) +3. PaaS 克隆仓库,运行构建脚本,然后将构建产物部署到他们提供的网络上。 +4. 此后每次有新的推送,PaaS 都会重新克隆仓库、构建和部署。 + +简单来说,你只需要把代码准备好就行,几乎不需要做任何运维操作。 + +问题在于,部署一个静态网站并不复杂,运行脚本构建好网站之后,将构建产物上传到一个可以分发文件(静态资源)的服务器上就好了。这个服务器甚至不需要有计算能力,可以是对象储存桶。印象中 Vercel 会把应用部署到他们的边缘网络(edge network)上,所谓「边缘」,指的是靠近端系统(end system)也就是用户的网络,网络的边缘部分离用户最近,所以响应速度往往很快。对于静态网站而言,这跟 CDN(内容分发网络)差不多。 + +所以,如果不用 PaaS,能把这个过程自动化吗? + +## 使用自动化工作流部署 + +由于我只使用过 GitHub Actions 和 Forgejo Actions,所以这里只谈这两个。Forgejo 的 Actions 几乎是和 GitHub 完全兼容的,语法也相似,所以在下文统称 Actions。 + +Actions 是自动化的工作流,有多种触发条件,最常见的是 `push`,也就是在有代码推送到远程仓库后触发;也可以限定分支,比如只有代码被合并到主分支之后才触发工作流。工作流可以执行命令,自然也可以执行用于构建静态网站的脚本,比如 `npm run build` 和 `hugo --minify` 等等。 + +需要说明的是,Actions 往往跑在与其他运行环境隔离的容器里,不能直接在宿主服务器上运行代码,并且工作流被执行完毕之后,往往会恢复现场,运行的结果不会保留在容器里,所以除了执行构建步骤,还要执行部署操作。如果要部署到一个对象储存桶,可以使用 `rclone`;如果要同步到远程服务器上,可以使用 `rsync`;如果要部署到 Cloudflare Workers 上,可以使用官方提供的 Wrangler 工具(不过你为什么不直接用 Cloudflare Workers 构建呢?)。 + +可以把工作流理解为「剧本」,程序员是编剧,把剧本交给 Actions 之后,它就会在规定的场合下按照剧本表演,结束后,会有人收拾舞台,一切都会恢复成原来的样子。如果要把舞台上的表演保留下来,就需要在表演进行时拍照和录像。 + +同样地,不同的剧目所需要的道具不同,就像不同的软件和脚本运行所需要的依赖项不同,戏班子上场的时候要把道具带上,编剧也要把道具在剧本里写清楚。Actions 一般跑在一个最小的、容器化、只有一个 CPU 核心的 Linux 系统上,以下称作 Runner。Runner 比较轻量,可以在 Docker 里运行,甚至给我一种 WSL(Windows Sub-system Linux)的感觉,上面预装的软件包很少,所以工作流里还要写安装依赖的步骤。 + +比如,构建一个 Hugo 网站,部署远程服务器上,工作流可能需要这样写: + +1. 安装 Node.js(如果有 Node.js 依赖) +2. `npm install`[^1] +3. `npm run build`(运行 Node.js 工具,比如构建 UnoCSS) +4. 安装 Go 语言依赖 +5. 安装 Hugo +6. `hugo --minify`(构建网站) +7. 安装 Rsync +8. `rsync ./public user@host.ip:/path/to/site`(部署网站到服务器)\ + +由于在远程服务器上写入文件往往需要认证,最安全的方法是生成一对 SSH 密钥,在 `rsync` 之前先配置 SSH 私钥,保证目标服务器上有储存对应的公钥,这样才能正常访问目标服务器。此外,还需要在目标服务器上配置目录权限,保证工作流有权限写入。 + +具体的 `workflow.yml` 可能是这样的: + +```yaml +name: Build and Deploy Hugo + +on: + push: + branches: + - master + +jobs: + deploy: + runs-on: docker + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + - name: setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.25.1" + - name: setup Hugo + uses: https://github.com/peaceiris/actions-hugo@v3 + with: + hugo-version: "latest" + extended: false + - name: build site + run: hugo --minify + - name: Install rsync + run: | + apt-get update && apt-get install -y rsync + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts + - name: Deploy via rsync + run: | + rsync -avz --delete public/ \ + ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:/home/eltrac/homepage/ +``` + +之后在服务器上配置好 Web 服务器,将通过自动流程部署的文件公开就好了。以下是一个 `Caddyfile` 示例: + +```Caddyfile +eltr.ac { + root * /home/eltrac/homepage/ + file_server +} +``` + +这个方案的缺点非常明显,我用这个方法搭了一个网站之后就再也不想搭第二个了。 + +1. 你需要管理一对 SSH 密钥,并且你允许了外部程序向你的服务器直接写入文件,这有安全风险。 +2. Actions 没法在本地测试,必须推送到远程仓库后,Forgejo/GitHub 才会运行工作流,这使得调试工作流变得**非常**痛苦。 +3. 每次运行工作流都需要下载并安装依赖项,对于 Hugo 这种构建速度非常快,甚至不会超过一秒的静态网站生成器,大部分的构建时间都花费在「准备运行环境」上了;而且,这个运行环境在跑完一次之后就会被恢复。如果你使用自己管理的 Forgejo Runner,可以在 Runner 里预安装自定义的依赖项,但复杂度不亚于维护一个单独的服务器。 +4. *用 YAML 写工作流十分反人类。* + +既然如此,我能不能直接在已经安装好运行环境的宿主服务器上直接运行构建脚本呢?构建产物直接在宿主服务器上生成。这样就可以省去与服务器通过 SSH 密钥认证并建立连接的过程,也不需要把大量的时间浪费在准备运行环境上了。 + +## 使用 Webhook 触发远程服务器部署 + +构建和部署静态网站之所以使用自动化工作流,是想要实现持续集成和持续部署,也就是在**确认**代码更改后就立刻更新生产环境的代码。一般来说,将代码合并到主分支就代表代码可以运行在生产环境了,自动化工作流可以以此为触发点,在有代码推送到主分支后就执行构建和部署步骤。在服务器上直接构建代码而不是用 Git 仓库的自动化工作流部署,最大的不足在于无法通过 `git push` 自动触发构建,但这个问题并非没有解决方案。 + +我不清楚 GitHub 的情况,Forgejo 可以在仓库设置里配置 Webhook,即在某些事件发生时向指定的 Webhook 端口发送 HTTP 请求。只要在服务器上开放一个 Webhook 端口,在接收到 HTTP 请求时拉取新代码并重新构建网站,然后配置 Forgejo 仓库在 `master` 分支收到新的代码推送时向这个 Webhook 端口发送 HTTP 请求,就能够实现 `git push` 后自动更新网站。宿主服务器不是容器化的最小运行环境,只要配置好了依赖和必要的软件,就不需要像自动化工作流那样,每次构建都需要重新安装依赖,更新可以在几秒内完成,体验上不会比动态网站慢。 + +具体而言,要先在服务器上配置好必要的工具。我使用 Hugo,也就需要在服务器上安装好 Go、Git 以及 Hugo。我的 VPS 安装的是 Ubuntu 系统,所以这里用 Aptitude 包管理器安装。 + +```shell +sudo apt update +sudo apt install golang-go +sudo apt install git +``` + +使用 Aptitude 安装 Hugo 的时候,我发现版本不是最新的,因此遇到了一些问题。所以我打算直接从源代码编译,先克隆仓库,然后编译,将编译后得到的二进制文件移动到 `bin`,测试能否在终端运行。 + +```shell +git clone https://github.com/gohugoio/hugo.git +cd hugo +go build . +mv hugo /usr/local/bin/ +hugo version +``` + +其实也可以直接用 Go 安装,但我忘记当时遇到了什么问题,可能是没有把 Go 的 `bin` 添加到 `$PATH`,总之没能成功安装。 + +```shell +go install github.com/gohugoio/hugo@latest +hugo version +``` + +接下来准备构建网站的脚本。先把网站的源代码克隆到本地,安装好依赖之后,创建一个 `.sh` 文件 + +```shell +# 这是托管在我自己的 Forgejo 实例上的网站 +git clone https://src.eltr.ac/eltrac/jar.git +cd jar +pnpm install # 安装 Node.js 依赖 +vim build.sh +``` + +这个文件里,按照**实际情况**编写构建网站的步骤。由于需要被执行,所以要在开头写上 `#!/bin/sh` + +```shell +#!/bin/sh + +git pull # 先拉取最新的更改 +pnpm unocss "**/*.{html,md}" -o assets/uno.css +hugo --minify +``` + +运行这个 Shell 脚本,测试能够正常构建网站。如果输出正常,就可以继续配置 Webhook 了。这里使用 adnanh 的 [webhook 实现](https://github.com/adnanh/webhook),这是一个命令行工具,能够读取 JSON 或 YAML 配置。以下是示例配置文件,用 JSON 编写。 + +```shell +# 先安装 Webhook +sudo apt-get install webhook +``` + +```JSON +// hooks.json +[ + { + "id": "build-hugo", + "execute-command": "/home/eltrac/jar/build.sh", + "command-working-directory": "/home/eltrac/jar" + } +] +``` + +执行 `webhook -hooks hooks.json`,API 就会运行在 `:9000` 端口上,我们刚刚配置的 API 路径是 `localhost:9000/hooks/build-hugo`。要允许公网访问,可以用 Caddy 配置反向代理。这里建议用 `systemctl` 运行和管理 Webhook 服务,具体步骤此处略去。 + +```Caddyfile +hooks.example.com { + reverse_proxy localhost:9000 +} +``` + +然后,在 Forgejo 仓库配置 Webhook,当有代码被推送到主分支上时,就向我们刚刚配置好的 API 端口发送 HTTP 请求。运行在服务器上的 Webhook 收到请求后,就会运行我们刚才编写好的 `build.sh`,网站就会被重新构建。 + +![](https://r2.eltr.ac/geedeapro/essays/deploying-static-sites/forgejo-repo-webhook.png "在 Forgejo 仓库设置找到 Webhook") +![](https://r2.eltr.ac/geedeapro/essays/deploying-static-sites/1Capture_2026-01-28_17.42.31.png "添加 Webhook") + +完成后,向 Forgejo 远程仓库推送更新,测试构建脚本有没有被触发。不出问题的话,你就能获得一个几乎能在 `git push` 一秒后更新的静态网站。 + +## 对比三种方案 + +对于缺少经验的人来说,使用 PaaS 是最简单的,几乎去掉了维护一个网站所需要的所有运维技能,只需要关注写代码。不过,似乎大部分 PaaS 都只支持从 GitHub 和 GitLab 和拉取代码,或者自己手动上传代码,不支持和自托管的 Gitea 或者 Forgejo 实例集成。个人感觉,==使用 PaaS 就像是在和恶魔交易,出卖自己的灵魂以换取便捷,代价是会被科技公司锁死在他们的平台上==。 + +GitHub Actions 类的自动化工作流,想必是有用武之地的,但我认为并不适合用来部署网站。如果只是运行自动化测试或拉取数据这种操作,把工作流脚本和代码放在一个仓库里大概是合适的。如果某些操作需要大量的依赖项才能运行,那么自动化工作流的效率就会因为需要安装大量依赖而被拉低。 + +目前实践下来,个人认为最优雅的方案就是在服务器上直接构建,通过 Webhook 触发,这样就省去了部署的步骤。不过,如果没有一台 Web 服务器,也就用不了这个方法了。 + +印象中还有人会在本地构建,将构建产物使用 `rclone` 同步到储存桶,或者使用 `rsync` 同步到服务器上,我没有实践过这种做法,就不评价了。 + +[^1]: 其实我更喜欢使用 `pnpm`,但如果要在自动化工作流里使用,还要额外安装,所以这里就直接用 `npm` 了。 \ No newline at end of file diff --git a/content/article/entitlement-is-sickness.md b/content/article/entitlement-is-sickness.md new file mode 100644 index 00000000..c011b6a3 --- /dev/null +++ b/content/article/entitlement-is-sickness.md @@ -0,0 +1,50 @@ ++++ +title = "鹰抬头门综合征" +slug = "entitlement-is-sickness" +categories = "人类恶疾" +date = 2026-01-02T14:48:57 +draft = true +toc = true +url = "/essays/entitlement-is-sickness/" + ++++ + +今天要谈的是 Entitlement Mentality,中文兴许可以译作「特权心态」,但总觉得词不达意,所以造了一个更不达意的音译词作为标题,还请读者见谅。这种心态我在包括我自己在内的许多人身上都有见到,简直像是恶疾缠身一样难以摆脱。本博客的宗旨是以人为鉴,以及毫不留情地分析和辱骂,所以我们直接来看案例吧。 + +--- + +我要举例的这个人,我一时找不到合适的词来称呼它,我想用「朋友」这个词,但我并不觉得他是我的朋友,但不幸的是他目前还无法远离我的生活,每天抬头不见低头见,我只能尽最大努力不去理他。真的很奇怪,人们把一起工作的人称作「同事」,一起学习的人称作「同学」,大概是因为这种关系并不总是和友谊绑定起来,那住在一间房子里的人就一定是了吗?室友不应该叫作「同室」吗?我跑题了。总而言之,我接下来会把这个人称作同室。 + +同室和我在刚进入大学没多久就认识了,我对他的第一印象就很差,说不上来为什么,但就是不喜欢他这个人。我以前把他描述为「他身上有种混沌的气息」,现在依然觉得不假。然而,他又是一个大部分时候都比较好相处的人,我觉得自己的情绪不太理性,便还是继续和他来往,甚至在不久前合租住在了一起。 + +如果你有关注我的 Telegram 频道,那你可能读过我被气到发长篇大论批评他的推文。我在写这篇文章的当下,还能听到他在外面走动的声音,听到他说话我都感到想吐——是的,就是彻头彻尾的厌恶。等我发现我对他的厌恶的确有来头的时候,已经太晚了(也算是教会了我要相信自己的直觉吧)。 + +普鲁塔克在《[如何从敌人身上获益](/library/2025/如何从敌人身上获益)》告诫读者,发现敌人的缺陷时要审视自己,看看自己身上有没有相同的弱点。在这么做之前,我应该先分析一下他这令人讨厌的缺陷究竟是什么。 + +## 久病成庸医 + +在我和同室搬到一起之前,他偶尔会到我的宿舍来窜门,聊天之余我会用塔罗牌帮他占卜感情状况。除了书桌椅之外,我以前的宿舍里还有一把躺椅,他来的时候就坐在那把躺椅上。某天给他解牌的时候,我看他躺在椅子上的画面,想起了一些动画和 Meme 里有关心理咨询的刻画:来访者躺在咨询室的沙发上望着天花板跟咨询师描述自己的问题。于是我随口说了一句:「这好像心理咨询」。他的回应是:「哎。难道我不应该才是心理医生吗?」 + +他之所以这么说,原因是他患有双相情感障碍,过去有不少心理咨询和精神科治疗的经验,所以就理所当然地把自己当成心理问题的专家了。你可能觉得这没什么,那就接着往下读吧。 + +某天他告诉我他的双相治好了,药都停了。在那之后,我渐渐发现他对「精神病」这个标签的态度变得非常微妙。 + +我在教培机构做兼职的时候,遇到了一个患有抑郁症的学生,他是个很有礼貌的学生,会弹钢琴也会弹吉他;我在一些网络社区冲浪的时候,也遇到了患有心理问题的社区成员,他会画画还会做饭,甚至有厨师证。我想着是因为抑郁症患者的内心世界都很丰富。跟同室聊天的时候我跟他分享了这些案例,我用打趣的口吻说到「你看我们抑郁症都这样多才多艺啊!」,他听完却表现得很**警惕**,问我「我们」是指谁。他的意思是不希望这个「我们」把他包含在内。 + +后来有一次他主动找我闲聊,他说:「我以前很喜欢跟精神病谈恋爱,因为这样能让自己感到很正常吧。」我记不清具体的词句了,但我记得他还说了诸如「能觉得自己有能力照顾别人」之类的话。 + +他跟所谓的「精神病恋人」的相处方式是什么样的呢?我这里要借用[莫比乌斯](https://onojyun.com/)的一句话:贱人总是成对出现。事实上,他面对亲密关系也远不如他自以为的那样健康和*正常*。大概一年前,他还在和一个女性交往的时候,他跟我表示自己想要分手。有一天晚上甚至跟我打电话,说他马上要去见他的女朋友了,但他只觉得想逃,我的回应是,你不想去那就不要去,现在立马转身就走,然后再把话说清楚。他在电话那头还是纠结,拉扯了好久,我也重复了好几遍我的建议,他还是去了。在那之后,他说「我下个月就要分手」,下个月到了,他没分。这样的戏码又上演了几个月,他甚至给自己设置截止时间,说要在几月几号的时候提分手。最后,他分手的方式是趁暑假的时候,他女朋友还没回来,把家里的东西都收走,然后给她留了言就断了联系——嗯,之后他就开始和我合租了…… + +问题的关键在于,他不敢和真实的人有真实的接触。他的情感矛盾从没有直接和他的女朋友开口讲过,反倒是时常找我抱怨。我有好几次建议或询问他有没有跟对方讲过这些不愉快,他都一直在讲对方是一个多蛮不讲理的人——咄咄逼人和不敢直面冲突的懦夫,确实挺适合凑一对儿的。回到「他不敢和真实的人有真实的接触」这句话,这不仅仅适用于亲密关系,和任何人都是这样。我们只要有一些观点上的摩擦,他就会选择傻笑、转身离开,完全忽略掉还在讲话的我,哪怕我根本没有生气。这种爱逃避问题、不敢直面冲突的性格特质,或许可以从原生家庭角度来分析,但是,这不正是应该由他自己去克服和治疗的吗?他这个自封的「心理医生」,不应该清楚这一点吗? + +如果你在读并且想要反驳的话:心理医生,你为什么要掉进自证陷阱? + +## 浅尝即止的快餐式傲慢 + +某天我跟同室分享一个有关 MBTI 的视频,他笑着跟我说:我已经脱离「咪咪」圈很久了。我过了一会儿才反应过来,他说的「咪咪」是英语单词 Meme(迷因)。 + +所谓的「很久」究竟是多久呢?这个模糊的用于表示时间长短的词给了许多人装作经验丰富的空间。他某天跟我说,要达到健美的身材至少要练一年。我之前开始练上肢的时候发现自己左右两边的肌肉大小不一样,求助过一个身材很好的前同事,他说这种不平衡在坚持健身的前两年会很明显。所以,我听到同室说「一年才能达到健美」的时候,我回复说「一年还挺短」。他觉得惊讶:「你觉得一年很短吗?我觉得挺长了」。 + +也就是说,这个人从开始健身到对话的那个当下,是连一年的经验都没有的。然而我已经听过不知道多少遍他在有关健身知识方面的说教了(他自己大概不觉得是说教)。我核心力量还比较弱的那段时间,在瑜伽垫上训练的时候经常疼到叫出声来,有一次我练得快喘不过气,他却在我还在运动的时候问我「做有氧的时候叫出来不会漏气吗?」——健身专家,你为什么分不清力量训练和有氧运动? + +w \ No newline at end of file diff --git a/content/article/everything-in-plain-text.md b/content/article/everything-in-plain-text.md new file mode 100644 index 00000000..6f980bb4 --- /dev/null +++ b/content/article/everything-in-plain-text.md @@ -0,0 +1,376 @@ ++++ +title = "关于一切的纯文本解决方案指南" +tags = [ "Geek", "编程", "效率",] +categories = "生产力报告" +date = 2025-12-18T17:38:00 +draft = false +toc = true +slug = "everything-in-plain-text" +url = "/essays/everything-in-plain-text/" + ++++ + +我极度厌恶拖拽式的图形界面,一方面是因为我最常使用的光标输入设备是 MacBook 自带的触控板,而众所周知用触控板拖拽简直是世界上最反人类的操作;另一方面,对于不少操作,图形界面都是不必要且更消耗资源的。开发者要构建图形界面,需要花更多的时间分析、设计和编码;电脑要运行图形界面,需要占用更多的系统资源;磁盘上存储图形数据,占用的空间也更高。诚然,图形界面的优势是简单直观、使用门槛低,但如果你有一个纯文本编辑器、习惯或愿意尝试使用命令行、乐意探索新技术,那么,我认为你至少应该尝试用纯文本的解决方案,替代原有的图形界面解决方案。 + +本文整理了几种在我看来使用纯文本解决要比使用图形界面解决来得更方便、更高效的问题场景,并给出了用到的相关软件,供读者参考。 + +## 绘图 + +作为软件工程的学生,画各种流程图、活动图、时序图和用例图应该是家常便饭。在软件工程里,表达需求的方式有很多种:自然语言描述、伪代码描述,还有图表。其中,图表自然是最清晰直观的,是必要的沟通工具。 + +在软件工程领域,各种类型的图表都有相应的规范。最常见的规范就是 UML,全称 Unified Modeling Language(统一建模语言),它提供了用图形描述软件系统架构、行为和需求的标准。 + +相关的绘图工具有很多,这里不谈国内外的各种 SaaS 软件[^1],笔者在以前最长使用的是开源免费的 [draw.io](https://draw.io/),基于 Web。使用这类基于图形界面的软件绘图的基本流程是:在左侧长长的列表中找到你需要的图形,然后把它拖拽到中间,点击它,把手指的位置从鼠标移动的键盘上,然后输入文本,然后把手指的位置从键盘移动到鼠标上,拖拽另一个图形到中间…… 在之后,你还要手动调整这些图形是否对齐、间距是否合适。 + +在这个过程中,有不少时间都浪费在了调整图形上,而不是用在「传达信息」上。而且,可供选择的图形种类很多,用户完全有可能用错图形,画出不符合 UML 规范的图。 + +有一段时间我会用自然语言描述需求,然后用 LLM 生成 SVG 代码来画图,但 LLM 的空间想象能力为 0,画出来的图歪七扭八,根本没法用。后来我发现,基于纯文本的画图解决方案其实不少。 + +### Mermaid + +你可以把 [Mermaid](https://mermaid.js.org/) 想象成用来画图的 Markdown。要画一个简单的流程图(Flowchart),你只需要这样写: + +```mermaid +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` + +Mermaid 的优势是,它和 Markdown 的生态系统兼容性很好,很多 Markdown 编辑器和渲染工具,都能够渲染嵌入在代码块里的 Mermaid 图形,你只需要把代码块的语言指定为 `mermaid`, 这个代码块就会被替换为图形。据我所知,Obsidian 是内置这个功能的,而 Hugo 的官方[文档](https://gohugo.io/content-management/diagrams/#mermaid-diagrams)里也提供了在 Hugo 中使用 Mermaid 的教程。 + +Mermaid 提供 [JavaScript 库](https://github.com/mermaid-js/mermaid)和[命令行工具](https://github.com/mermaid-js/mermaid-cli),可以轻易地在网站上使用、在基于 Web 的桌面端软件里使用,或者在本地用纯文本编写,再执行 `mmdc` 命令将文本转换为指定格式的图形。 + +不过,我并没有继续使用 Mermaid,因为它有一个非常明显的缺陷:Mermaid 并不支持完整的 UML 规范。尽管 Mermaid 支持很多类型的图形(甚至包括思维导图、看板、饼图和四象限图),但缺少对用例图、活动图等重要 UML 图的支持。 + +顺带一提,早在 2023 年七月,就有一个相关的 [Issue](https://github.com/mermaid-js/mermaid/issues/4628) 被提出,建议添加用例图,有超过 600 点赞,呼声不小。也有 [Pull Request](https://github.com/mermaid-js/mermaid/pull/6141) 被提出,没有被合并[^3],而且这个 PR 也没有完整实现规范的用例图,缺乏拓展、包含等关系的表示。Issue 的状态被标记为 Approved(通过),但用例图一直没有被添加到 Mermaid 中。Mermaid 上一次添加新的图表类型是在 [v11.0.0](https://github.com/mermaid-js/mermaid/releases/tag/v11.0.0) 版本[^2],一年前。毕竟是开源项目,缺乏人手添加新功能也是可以理解的,而且 Mermaid 的定位是创建图表和可视化内容的,并非是对 UML 的实现。 + +### Graphviz + +[Graphviz](https://graphviz.org/) 是上个世纪就出现的绘图软件,使用名为 DOT 的语言绘制节点、边、图、子图和组,支持命令行。Graphviz 的语法和 Mermaid 类似,但无需指定图表类型,因为 Graphviz 没有图表类型这个说法。个人感觉,Graphviz 中的 Graph 就是指数据结构中的图(graph),而不是图表(diagram)。 + +```graphviz +graph { + a -- b + a -- b + b -- a +} +``` + +Graphviz 是用 C 写的,速度应该会比用 TypeScript 编写的 Mermaid 要更快,但不适合集成在 Web 应用中。如果需要表示数据结构,Graphviz 大概会更合适。 + +### PlantUML + +[PlantUML](https://plantuml.com/) 基本上就是对 UML 的实现,支持时序图、用例图、类图、对象图、活动图等等。如果要画符合规范的 UML 图,PlantUML 几乎是最好的选择。除此之外,PlantUML 还支持不少非 UML 图,比如项目管理相关的甘特图和 WBS[^4] 图,还有数据库相关的 E-R 图[^5]。 + +PlantUML 的语法会稍微繁杂一点,~~原因大概是 PlantUML 是用 Java 写的,所以继承了编程语言的啰嗦特性~~,但整体上还算简单。以下是一个时序图的例子: + +```plantuml +@startuml +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: Another authentication Response +@enduml +``` + +*Bob 和 Alice 简直是软件领域的李华。* + +要使用 PlantUML,可以使用官方提供的[在线编辑器](https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000),也可以[下载](https://plantuml.com/download)到自己的电脑上,然后运行 JAR 文件——是的,你需要安装 Java…… + +```sh +java -jar plantuml.jar input.txt +``` + +我的建议是在 `.zshrc`(或者其他终端的配置文件里)给这个命令设置一个别名,这样就不需要每次都找到 JAR 文件在哪了。 + +PlantUML 也有相关的集成插件,可以在*万恶的* IntelliJ IDEA、VS Code 等编辑器中使用,也可以用在支持拓展语法的 Markdown 里。我自己最常用的场景是用 Pandoc 输入 Markdown 生成 PDF,可以使用这个 [pandoc-plantuml-filter](https://github.com/timofurrer/pandoc-plantuml-filter) 让 Pandoc 渲染通过代码块嵌入在 Markdown 文件中的 PlantUML 图。 + +## 富文本编辑 + +Word 简直是世界上最反人类的文本编辑器,还有与之相关的 Pages[^6] 和国内的 WPS——明明论文格式和各种文档都有固定的格式要求,我为什么会需要每写一篇文档都要手动调整格式,在各个菜单栏里点来点去?就算用格式刷我也觉得很难受! + +### LaTeX + +目前最成熟的文档标记语言应该是 [LaTeX](https://www.latex-project.org/),这是一个免费软件。以下是 LaTeX 官网上引言的片段: + +> LaTeX 不是一个文本处理器!相反,LaTeX 鼓励作者们不要太担心文档的外观,而是专注在编写正确的内容上。举个例子,考虑这篇文档: +> +> ```text +> Cartesian closed categories and the price of eggs +> Jane Doe +> September 1994 +> +> Hello world! +> ``` +> +> 要在大部分排字或文本处理系统里产出这个文本,作者不得不决定使用什么排版,所以要选择(比如说)18 pt 大小的 Times Roman 字体用在标题上,12 pt 大小的 Times Italic 字体用在名字上,等等。这会导致两个结果:作者把时间浪费在了设计上;还有很多设计得不好的文档! + +
+ 原文 + +> LaTeX is not a word processor! Instead, LaTeX encourages authors not to worry too much about the appearance of their documents but to concentrate on getting the right content. For example, consider this document: +> +> ```text +> Cartesian closed categories and the price of eggs +> Jane Doe +> September 1994 +> +> Hello world! +> ``` +> +> To produce this in most typesetting or word-processing systems, the author would have to decide what layout to use, so would select (say) 18pt Times Roman for the title, 12pt Times Italic for the name, and so on. This has two results: authors wasting their time with designs; and a lot of badly designed documents! + +
+ +使用 LaTeX 的话,就用纯文本这样写就好了。 + +```latex +\documentclass{article} +\title{Cartesian closed categories and the price of eggs} +\author{Jane Doe} +\date{September 1994} +\begin{document} + \maketitle + Hello world! +\end{document} +``` + +不过,我并没有高强度的写论文需求,所以接触 LaTeX 比较少,用的比较多的场景应该是在 Markdown 中嵌入公式,许多 Markdown 编辑器都支持用 `$$` 包裹 LaTeX 块以渲染数学公式。以下是一个二分类问题的对数损失函数,用做示例。 + +```latex +$$ +\mathcal{L}(\theta) += -\sum_{i=1}^{n} \left[ +y_i \log f_\theta(x_i) ++ (1 - y_i)\log\bigl(1 - f_\theta(x_i)\bigr) +\right] +$$ +``` + +![](https://r2.eltr.ac/uPic/2025/12/1giHuK.png) + +总而言之,LaTeX 是一个功能强大的文档标记语言,有了它就可以把注意力放在编写内容上,而无需过多关注页面排版。不过,也有人认为 LaTeX 的语法太啰嗦,所以会寻求其他的解决方案。 + +### Typst + +你可以把 Typst 理解为一个更像 Markdown 的 LaTeX,它的功能和 LaTeX 一样强大,却有着 Markdown 一样简洁的语法。 + +![](https://r2.eltr.ac/uPic/2025/12/gHo5ze.png) + +Typst 支持各种类型的可视化、图表、数学公式、代码高亮等,还可以用来做幻灯片。Typst 本身是开源免费的,有提供云储存和同步的增值服务,可以订阅支持。不过,我没有使用过 Typst,所以就不展开了,我认为有较专业的论文写作需求的,可以尝试 Typst。 + +### Markdown 和 Pandoc + +Markdown 最常用的使用场景是被渲染为 HTML,用在博客平台、论坛和一些即时通讯软件里(据我所知,Discord 就支持 Markdown 语法)。Markdown 的最大特点是可读性,即便没有被渲染,阅读纯文本的 Markdown 文档也没有任何问题。 + +尽管 Markdown 本身的语法比较局限,缺乏 LaTeX 和 Typst 的排版能力,但借助一些拓展语法和外部工具,就能让 Markdown 变得几乎万能。 + +本文要介绍的是一个非常强大的命令行工具——[Pandoc](https://pandoc.org/),他几乎可以把任何文档格式转换为另一种文档格式(官网列出了详细的支持列表),它可以在 Markdown、Emacs Org-Mode、AsciiDoc、Typst、LaTeX、Microsoft Word 等格式之间相互转换,还可以把上述格式轻松转换为 PDF。如果有不支持的小众格式,还可以自己用 Lua 语言编写 Reader 和 Writer。 + +有了 Pandoc,你就可以安心地用 Markdown 编写文档,写完之后再转换为需要的格式,比如 Word 和 PDF。 + +你还可以编写 Filter 来拓展 Pandoc 的功能。Pandoc 转换文档的过程是这样的:使用相应的 Reader 把以原始格式编写的文档读取为 AST(抽象语法树,一个中间层);再由 Writer 把 AST 写为用户指定的文档格式。编写自定义的 Reader 和 Writer 可以让 Pandoc 读取或写出更多的文档格式,编写 Filter 可以改变中间的抽象语法树。以下是 Pandoc 从输入到输出的过程: + +```text +INPUT --reader--> AST --filter--> AST --writer--> OUTPUT +``` + +举个例子,如果你想要把 Markdown 文档里的二级标题全部替换为斜体正文内容,这就涉及到了更改中间层 AST,因为 `## 二级标题` 被 Reader 读取时,依然是二级标题,如果 AST 没有改变,被 Writer 写出的时候就转换为了另一个格式的二级标题(比如 HTML 的 `

二级标题

`)。如果要从二级标题改为斜体正文内容,就要在内容被 Writer 写出之前改变 AST 的内容。 + +记得前文提到的 PlantUML 吗?GitHub 上有一个现成的 [pandoc-plantuml-filter](https://github.com/timofurrer/pandoc-plantuml-filter),他会把编程语言被标记为 `plantuml` 的代码块,用 PlantUML 渲染为对应的 UML 图——Reader 读取到了 `plantuml` 的代码块;Filter 把抽象语法树中的代码块变成了图片;Writer 把图片写入了输出文件。 + +配置好了对应的 Filter,就可以直接在 Markdown 文件里这样嵌入 UML 图: + +~~~ +```plantuml +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: Another authentication Response +``` +~~~ + +将 PDF 引擎设置为 `xelatex`,Pandoc 也能将被标记为 LaTeX 的代码块渲染为嵌入式的 LaTeX 文档,可以用这个特性来实现多图排版。 + +~~~ +```{=latex} +\begin{figure}[H] +\centering +\begin{subfigure}[b]{0.3\textwidth} + \centering + \includegraphics[width=\textwidth]{img/1.jpeg} + \caption{图 1} + \label{fig:img1} +\end{subfigure}% +\hfill +\begin{subfigure}[b]{0.3\textwidth} + \centering + \includegraphics[width=\textwidth]{img/2.jpeg} + \caption{图 2} + \label{fig:img2} +\end{subfigure}% +\hfill +\begin{subfigure}[b]{0.3\textwidth} + \centering + \includegraphics[width=\textwidth]{img/3.jpeg} + \caption{图 3} + \label{fig:img3} +\end{subfigure} +\caption{三张图} +\end{figure} +``` +~~~ + +有了上述工具,你就能以一种**工程化**的方式编写文档。我的建议是,把图片、参考资料、Markdown 源文件和其他资源放在同一个目录下,然后在这个目录下再创建一个 `pandoc.sh`,示例内容如下: + +```sh +#!/bin/bash + +pandoc "input.md" \ + --from=markdown+yaml_metadata_block \ + --pdf-engine=xelatex \ + --filter=pandoc-plantuml \ + -V geometry:margin=2cm \ + -V fontsize=12pt \ + -V mainfont="Songti SC" \ + -V CJKmainfont="Songti SC" \ + -o output.pdf +``` + +编写文档的过程中可能需要多次运行 Pandoc 来测试结果,或者在更新后生成更新版本的 PDF 文件,把命令放在 Shell 文件里更方便运行。这些设置项也可以放在 Markdown 文件的 frontmatter 里,具体放在哪里就看自己的喜好了。 + +```markdown +--- +title: 文档标题 +subtitle: 副标题 +author: Eltrac +date: "2025-12-13" +geometry: margin=2cm +fontsize: 12pt +mainfont: "Songti SC" +CJKmainfont: "Songti SC" +header-includes: + - \usepackage{xeCJK} + - \setCJKmainfont{Songti SC} + - \setCJKfamilyfont{hei}{Heiti SC} + - ... +--- +``` + +Pandoc 还可以一次性接收多个 Markdown 文件作为参数,文档也可以用模块化的方式编写。 + +```sh +pandoc intro.md chapter1.md chapter2.md appendix.md \ + -o output.pdf +``` + +如此一来,你就可以像开发软件系统一样编写文档,维护一个这样的目录: + +```text +document/ +├── intro.md +├── chapter1.md +├── chapter2.md +├── ... +├── appendix.md +├── pandoc.sh <-- 编译时运行 +├── img/ +│ ├── figure1.png +│ └── ... +└── output.pdf <-- 编译结果 +``` + +把文档发送给别人的时候,提交 `output.pdf` 就好了。 + +### Quarto + +[Quarto](https://github.com/quarto-dev/quarto-cli) 是一个基于 Pandoc 的命令行工具,可以用 Markdown 编写静态内容,也可以用 Python、R 语言、Julia 和 Observable 等技术生成动态内容,可以生成各种格式的博客文章、网站、幻灯片,以及 HTML、PDF、Word 和 ePub 等格式的电子书。 + +如果有更专业的写作和发布需求,比起用 Pandoc 自己搭框架,Quarto 可能是更成熟的选择。不过我没有用过这个工具,不清楚体验如何。 + +## 制作幻灯片 + +制作幻灯片(或者说演示文稿、PPT)的纯文本解决方案已经有很多,我比较熟悉的是 [sli.dev](https://sli.dev/),可以用 Markdown 编写幻灯片。用纯文本做幻灯片的好处与编写文档类似,可以更专注内容而不是纠结格式问题。此外,Slidev 还提供内置的代码高亮,可以编写 Vue 组件放在幻灯片里,对开发者非常友好。我能想到的使用场景是,自己用 Vue 做了一个可运行的原型组件,比起截图,嵌入可交互的组件会更有表现力。 + +Slidev 本质上是提供了一种新的幻灯片形式,虽然可以导出为 PPT 和 PPTX 格式(甚至可以导出为单页应用),但最佳的效果还是在本地运行一个 Web 服务器做演示。所以,在需要提交 PPT 文件或者必须把 PPT 拷贝到其他设备里做演示的场景下,Slidev 可能没有那么好用。 + +此外,Obsidian 也自带幻灯片插件。被 Markdown 的水平分割线 `---` 分开的内容就会在幻灯片里被分成两页,没有拓展语法,可自定义的空间也比较小。如果能接受幻灯片里只有基础的文字和图片(甚至没有动画)的话,也不失为一种选择。不过 Obsidian 是不能导出 PPT 文件的。 + +![](https://r2.eltr.ac/uPic/2025/12/glcTGC.png "Obsidian 的核心插件设置项,其中有一个 Slides 插件") + +我自己演讲的时候,比较依赖演示文稿的动画和稍微复杂一些的多栏排版,所以较少使用上述的纯文本解决方案。兴许以后可以尝试先用 Slidev 做出可用的原型,之后再使用 PowerPoint 或者 Keynote 添加动画。 + +--- + +## 为什么用纯文本? + +### 可以使用 Git 做版本管理 + +如果一篇文档的编写周期很长,或者说需要多人协同编写,而参与者又都是会使用 Git 的开发者的话,使用纯文本的编写方案,就可以利用 Git 的版本管理能力管理文档的历史版本,上传到远程仓库后也就自带了多人协同能力。比起价格昂贵的多人办公 SaaS 软件,让本来就有 Git 使用经验的开发者使用自己习惯的编辑器协同编写文档,难道不是更高校更具性价比的选择吗? + +任何用纯文本编写和储存的内容,都可以用 Git 管理。《[Just use cURL](https://justuse.org/curl/)》这篇文章表达了对 Postman 的鄙夷,作者认为把 cURL 命令放在 `.sh` 脚本文件里,就能够代替 Postman 的云端同步和团队协作功能。 + +> **Q:那团队协作怎么办?** +> +> 这是个文本文件。把放进 Git 里。你知道吗,那就是那个你本来就应该在用的东西?现在你的 HTTP 请求有了版本管理、代码审查和差异对比。免费的。真是革命性的改变。 + +
+ 原文 + +> **Q: What about team collaboration?** +> +> A: It's a text file. Put it in Git. You know, that thing you should be using anyway? Now your requests have version control, code review, and diffs. For free. Revolutionary, I know. + +
+ +如果你不喜欢 Git,那就去用 [Jujutsu](https://github.com/jj-vcs/jj),或者别的什么你喜欢的版本管理工具。 + +### 拥有 100% 的数据掌控权 + +纯文本是开放的文件格式,任何设备都能读取纯文本格式。你的数据不会被强制储存在云端,不会有科技大厂分析或出售你的数据,你想把文件放在哪就放在哪。 + +### 文件体积小 + +PDF 文件和 PPT 文件的磁盘占用是 MB 级别的,简单的 PNG 图片往往有几百 KB,Word 文件的体积要小一些,但也没必要那么大。如果以上内容全部都用纯文本表示,只在必要时渲染成需要的格式,那么占用的磁盘空间将会非常小。如果和你协作的人也使用相同的技术将纯文本转换为 PDF 文稿或其他格式的文件,你们只需要通过网络传输 KB 级别的数据,文件只会在本地膨胀到 MB 级别,而且在工作完成之后,完全可以只保留原本的纯文本文件,删除结果文件。 + +这相当于下载软件时只拉取源代码和 Makefile(或者 Homebrew Formula),软件本体在本地编译,是很高效的选择。我注意到有不少人的 U 盘或移动硬盘里装着爆满的 Office 文件,如果全都换成纯文本,PPTX、DOCX、PDF 等文件在用过之后就直接删除,需要的时候再从纯文本中编译,那储存的成本将会降到非常低。 + +### 操作方便 + +精细复杂的图形可能没办法用纯文本解决(不然就跟前端工程师调试 CSS 一样难受了),但我相信日常工作中的不少操作都可以用纯文本简化。编写文本的过程中,手指完全不需要离开键盘操作鼠标,这对熟练使用键盘的人来说无疑提升了效率——如果你只需要敲五次键盘,打出 `A-->B` 这一行代码,为什么要在冗长的图形选择菜单里翻找自己需要的图形,然后拖拽到中间,然后把手指放到鼠标上点击图形,然后把手指放回键盘按下 `A`,然后…… 你应该明白我的意思了。 + +## 除了绘图、文稿和幻灯片,余下的一切 + +不要忘了,除了 Markdown,JSON、YAML 和 TOML 也都是开放的文本格式,这些格式能够表示几乎所有结构化的数据,只要有能够读取这些数据的软件,理论上,你可以用文本格式编辑任何东西、做任何操作,比如管理 DNS 记录。 + +你可以参考 [Sukka 的实践](https://blog.skk.moe/post/dns-as-code-via-dnscontrol/),他使用 DNSControl 和 GitHub Actions 实现了用配置文件管理 DNS 记录的工作流,完全抛弃了各个服务商的用户体验参差不齐的 DNS 管理面板。以下 + +```javascript +D( + 'skk.moe', REG_NONE, DnsProvider(DSP_VERCEL), + DefaultTTL(300), + + ALIAS('@', 'skk.moe.cdn.cloudflare.net.', TTL(300)), + ALIAS('www', 'www.skk.moe.cdn.cloudflare.net.', TTL(300)), +); +``` + +*不过,把 JavaScript 代码说成是纯文本好像有点牵强呢……* + +我在文章最后想要抛砖引玉一下:如果你遇到了一个比较复杂的需求,比起构建图形界面,先不妨思考一下是否有必要。如果你的目标用户都是熟练编写代码的黑客,纯文本、Markdown、JSON 甚至 JavaScript 和 Lua 等脚本语言,是比图形界面更好的选择。 + +[^1]: SaaS:Software as a Service(软件即服务),可以简单理解为商业软件,一般以订阅制为商业模式。 + +[^2]: 根据更新日志("feat: Add packet diagram by @sidharthv96"),这个版本新增了报文图(Packet Diagram),用于表示计算机网络中报文或者说数据包的结构。 + +[^3]: 没有合并的原因是分支有冲突,而且 Pull Request 提出的时候,Mermaid 正好在把解析器从 jison 迁移到 langium,所以贡献者需要把原先写好的解析器迁移,额外的工作量可能劝退了他,总之这个 Pull Request 一年内都没了动静。 + +[^4]: WBS:Work Breakdown Structure(工作分解结构) + +[^5]: E-R:Entity-Relationship(实体-关系) + +[^6]: Pages 是苹果提供的 Office 软件,对标 Microsoft Word。 \ No newline at end of file diff --git a/content/article/exhausted-perfectionist.md b/content/article/exhausted-perfectionist.md new file mode 100644 index 00000000..bb210dd6 --- /dev/null +++ b/content/article/exhausted-perfectionist.md @@ -0,0 +1,54 @@ ++++ +title = "这个世界会累死完美主义者吗?" +tags = [ "职业", "大学时代",] +date = 2025-12-18T00:14:00 +draft = false +slug = "exhausted-perfectionist" +categories = "乱章" +aliases = [ "/exhausted-perfectionist",] +toot = "https://akk.eltr.ac/objects/1b6be0e8-807b-4805-b669-b99166145e73" +url = "/posts/exhausted-perfectionist/" + ++++ + +上个月和朋友去大坪玩,在路上聊到我的 MBTI 类型,得知我是 INFP 之后,朋友感叹:“感觉你趋近于完美了。”我问为什么,她说大概是因为我既有 P 人的随性,又有 J 人的守时。说起来,和朋友聚会时,我几乎总是第一个到。很多时候,为了不让朋友感到有压力,我会装作自己也刚刚到,或者在约定地点附近闲逛,故意拖延一会儿再出现。 + +我并非是真的守时,而是觉得不应该打破和他人的约定,而这种想法,其实是因为担心这么做了会让别人觉得不舒服。另一个原因是,我认为在约定时间前五分钟到达是约定俗成的,没有卡点到或迟到这个选项。换句话说,「提前到」是我的下限,我从没觉得晚点到也是可以接受的。 + +不知道是从什么时候开始,我发现自己为各种事情设置的「下限」,都普遍比别人高。室友直接用剪刀把没洗过的西兰花剪进锅里,和土豆、番茄、意大利面一起煮,加了不知道多少的生抽和蚝油之后还要大火收汁,目睹了这一切的我竟然感到愤怒,我想要大吼:“西兰花只用水煮两分钟!”室友对做饭的下限是能吃就行,而且越快越好,但我绝对不能忍受把一锅毫无色香味的菜端上餐桌,更不能忍受这种不尊重食物的行为。 + +我把这种下限当作对生活的积极态度和做人的原则,不过,在忙得抽不开身的时候,我才发现这有可能是一种缺陷。 + +我刚结束软件需求工程这门课的期末项目答辩,第二天,我睡到十点才醒,一共睡了十个小时——我真的太累了。截止日期的前几天,我一直在不断修改要交上去的软件需求规格说明书,以至于在我的 Wakatime[^1] 统计里,编写 Markdown[^2] 的用时以接近 60% 的占比,远超 Vue.js 和 Go 语言这两个我最常用的技术。等我意识到自己还没开始做 PPT 的时候,我所剩的时间已经不多了,而且我已经感到非常疲惫。于是我把文档发给了 Kimi AI,让它根据文档内容生成 PPT,从头到尾改了一遍自动生成的大纲,得到的结果还是不尽人意,必须动手大改。凌晨,我在手帐本上记下还需要修改的内容,准备明天再继续,可大脑仍然无法停止运转,硬生生把刚刚才写在待办清单上的事项做完了——我的副交感神经系统大概是坏掉了。讽刺的是,我的项目选题是一个帮助用户解读健康数据以调整作息和提升睡眠质量的软件系统。 + +答辩当天,我一边听老师对其他组的点评和提问,一边抱着电脑在台下修改自己的 PPT,容不下一点疏漏。万幸,我作为助教老师的一年的工作经验让我面对讲台不至于太紧张,再加上 PPT 的逻辑捋得很清晰,在脑子里过了好几遍。所以,即便没有提前排练过,讲得也还算流畅。最后,老师问我的第一个问题是:“你想把这个做出来吗?你有没有考虑过拿这个去参赛?” + +哈,第一个问题我就差点没回答上来。我着实感到惊喜,尽管这位老师本身就不严厉,但她在表达赞许和提供指导时的措辞是完全不同的。在整个提问过程中,她给的更多是后续的开发建议,还问了问我自己的想法,没有挑我的毛病。下台的时候,我回忆起刚才站在台上时捕捉到但没来得及反应的一些零散信息,我注意到有不少同学也有抬头在听。离开教室的时候,我收到一个同学的消息,问我能不能把我的答辩 PPT 发给他参考。 + +这些事情发生之后,我的确感到很高兴。不过,在我紧绷的神经终于放松下来过后,我却真实地感受到了过劳带来的无力感。我没有办法集中注意力读书、写代码,我在互联网上漫无目的地冲浪,陷入信息流当中,而这让我更累,更没有力气摆脱这种状态。如果我没有在那天晚上关掉第二天的闹钟,让自己好好睡一觉,我大概没有力气写这篇文章,也没有力气捡起我在高度紧张状态下丢掉的运动计划,我会苛责自己没有好好生活。 + +我并不是在力争上游,我只是没办法不负责任地把一坨让人没法看的东西交上去,而对我而言,「能看」的标准和下限很高,尽管我并不真的觉得它很高。 + +我回忆起半年前的项目实训,我被强制要求组队,几乎不和班里人社交的我慌不择路地和五个人组了队,他们让我做了组长。我至今还记得很清楚,当时的我在 QQ 群里把安装 Git 和配置 IDEA 的步骤一张一张地截图发在群里,在完成我自己的任务之外,还要去关心其他人能不能正常拉取和推送到远程仓库。有人在群里反馈了一个他修不好的 bug,我把他的代码拉取下来,打开浏览器控制台,发现问题再简单不过了,一个函数引用没有被定义——他的 AI 在写代码的时候删掉了一个原有的函数。他连最基本的开发者工具都不会用,不过也不能怪他,教前端的老师也只会死盯着源代码看,用肉眼找问题。 + +那个时候,我最大的感受是,整个组里好像就只有我一个人在乎我们要做出来的东西是不是一坨垃圾。这种孤立无援感依旧存在,所以需求工程这门课的项目我是一个人做的,但其他课的作业都有人数要求,我几乎无一例外地自动成为了组长,因为我是一群人里最在乎最终成果能不能达到「下限」的人。 + +接下来还有三门需要提交完整可运行系统的课,以及两门难度不小的理论课,再这样下去,我大概真的会过劳倒下的。 + +如果你问我为什么把下限设得这么高,我大概能围绕原生家庭、中小学经历和童年创伤扯两三千字,但这并不能解决问题。其实,我更好奇的是,为什么其他人可以这样不在乎,他们究竟是怎么做到心安理得地允许事情烂下去的?我的想法是,长期在社交媒体上吸收各种网友的同质化的观点,和身边人说着完全相同语言的很大一部分人,似乎早就已经把摆烂和蔑视权威刻在了骨子里。就算没有,他们也会因为其他人表现得不在乎而跟着伪装自己不在乎,即便所谓的其他人其实也是在装作不在乎——这大概就跟一些直男喜欢装作自己情感经历丰富一样,对他们而言是很酷的事情,甚至是合群的必要标签。 + +几天前听过的一期播客标题叫做《这个世界会惩罚每一个认真的人》。我想,施加这个惩罚的并不是抽象的世界,而是那些不认真的人——把责任和劳动丢给别人的,不正是他们的不在乎吗?不过,这好像也是我自己的错,如果我的标准和其他人一样,兴许就不会有这些痛苦了。 + +再说回我自己,我本来觉得我之所以对需求工程的期末答辩如此上心,是因为我尊重教授这门课的老师。对于那些在课堂上讲自己刚刚在短视频上看到的新闻、初始化项目之后的第一件事情是教学生移除 Git、虽然没有读 PPT 但对着 PPT 内容信口开河的那些老师[^3],我大概不会这般用心。我想我错了,我甚至会在做一门后端相关课程的课程项目时,在前端仔细调整每个元素的边距。==我在乎的并不是任何权威、任何人的意见,我只是不能忍受,一个丑陋、残缺、不入流的东西,上面写着我的名字——这大概是种病吧。== + +人生是不是一个不断降低预期的过程呢?从幻想,到梦想,到理想,再到认命,究竟要经历多少次失望,要承受多少劳苦?我想起去年年底,自己为了出国留学翻遍了欧洲各个学校的官网,信息多到我感觉自己快要溺死在互联网的北冰洋里;到了今年年初,我却等到一场和父亲的尴尬的谈话(说起谈话,其实是单方面的说教),他反复跟我强调国内的好,在往后的我为数不多的回家的期间,他也不断向我提及「中国就是最好的」,仿佛我这个终于在压抑的国内高校环境里找到一线生机的年轻人,犯了一个可怕的政治错误。我暗暗下定决心要在自己赚够钱之后,为自己支付留学的费用,可我要怎么拿到这笔「Fuck you money」,我究竟应该从事什么岗位、做什么事情,我几乎没有头绪。如果完成学校作业都会让我被完美主义的幽灵附身,神经紧绷,失去对生活的感知,没办法静下心来写一个字,我真的能忍受朝九晚五的职场生活吗? + +《大楼里只有谋杀》第三季,Ben 对同样对未来感到迷茫的 Mabel 说:那些老早就想明白自己人生规划的人都很无聊,像我们这样大器晚成的人,才是能真正改变世界的。这句话兴许给我带来的一些慰藉,但我依然掏心挠肺地想要搞明白——你们究竟是怎么忍受不知道该干什么,感觉一切都会失去控制的不踏实的感觉的! + +我不知道我的人生需要什么,但还好我知道,现在的我,需要睡眠。 + +[^1]: Wakatime 是一个为开发者设计的时间统计插件,支持多种编辑器。 + +[^2]: 我使用 Markdown 和嵌入式的 LaTeX 编写文档,随后再使用 Pandoc 转换为 PDF,使用的编辑器是我常用的 Zed,所以会出现在 Wakatime 的统计里。其实还有一段时间使用的是 Typora,所以实际用时比统计到的 60% 还要多。 + +[^3]: 一个教软件项目管理的老师,在解释一个经济学概念的时候,仅仅是凭借她对术语字面含义的理解在阐述而已,举了一些不恰当的例子。我读过曼昆的《经济学原理》的前几章,那是一个很基本的经济学概念;其他没有这些知识储备的学生,难道不会被她的这种不负责给误导吗? \ No newline at end of file diff --git a/content/article/git-with-trolley.md b/content/article/git-with-trolley.md new file mode 100644 index 00000000..740ef436 --- /dev/null +++ b/content/article/git-with-trolley.md @@ -0,0 +1,119 @@ ++++ +title = "如何用电车难题理解 Git" +slug = "git-with-trolley" +tags = [ "编程", "哲学", "小品",] +categories = "软件杂谈" +date = 2026-02-10T23:53:53 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/b35d9769-109a-4e4f-9d12-713eafe97038" +url = "/essays/git-with-trolley/" + ++++ + +你是一个疯狂的哲学家,你意识到反思、设想和解构已经无法满足你对人类道德的求知欲了,于是你决定开始实验。就这样,你找到了一些铁轨、一辆火车、一根拉杆和一些必要的机关,哦对,还有绳子,现在就差受害者了。 + +## 挑选受害者 + +你可不想过于随意地进行这场伟大的实验,有幸参与实验的人也是需要层层筛选的。总而言之,你找到了一群愿意或不愿意的受试者,让我们把他们称作 A 组。尽管你在选取受试者时也是带有目的的,但在正式开始实验之前,理应再做一次筛选。于是,你把 A 组中的一部分人绑上了铁轨,让另一部分人直接离开了,我们把这一部分有幸被绑上铁轨的人称作 B 组。 + +读者可能猜到了,一开始进入这场思想实验的 A 组就是 Git 的工作目录(work tree),B 组自然代表从工作目录中挑选出来的布置区(staging area),那些被哲学家打发走的人就是被丢弃(discard)或者说复原(restore)的工作。当然,挑选到布置区的人们也并非是直接为伟大的哲学事业做出了贡献,哲学家还需要规划思考一下,应该让火车怎样碾过他们,最好是要绘制一个路线图,这一步相当于是承认(commit)了这些人有真正参与到这场实验的资格,当然,哲学家也因此犯下(commit)了杀人罪。 + +简单来说,哲学家在这里做了三次选择: + +1. 在近乎无限的茫茫人海中,把受试者带到工作区域来; +2. 在工作区域中,挑选一部分人进入布置区,另一部分人留在工作区稍作等候,或者直接打发走; +3. 如果不需要对布置区里的人选进行调整了,就可以决定火车压过的路线了! + +当哲学家命令火车向前行驶,压过铁轨(staging area)上被绑好的人们之后,我们可以说:他提交(commit)了他的工作。 + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/work-concepts.png) +{.dark:invert} + +显然,在这篇文章中,我们把对代码的改动抽象为「工作」,而在电车难题的比喻中,我们用人来代指「工作」。 + +嗯,让我们来看看我能用这个*不太道德的*比喻扯多久吧。 + +## 无人生还 + +现在,哲学家已经把一些人绑在铁轨上了,距离电车压向他们已经不远了!从某种意义上来讲,他们是薛定谔的猫,几乎是已经死了,但又还没有死。无论怎么样,他们都可以被当作 Git 历史的一部分了。 + +如果你数学比较好的话,你可以把电车和这些人的距离理解为「无穷小」,而不是 0 或者负数。哲学家好像和上帝关系很好,或者如果你不信神的话,也可以说哲学家和疯狂科学家关系很好,他从隔壁爱因斯坦那里学会了和时间作对,于是成为了四维生物,能够在时间维度上行走。总之,哲学家可以在电车真的压向这些人之前做任何操作,甚至救下他们,但对这些凡人自己来说,他们已经必死无疑了。 + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/git-history.PNG) +{.dark:invert} + +这个时候,哲学家突然想再挑一些人上来。可是,就像我们说的,电车正在无限逼近,把人直接往铁轨后面叠加固然没问题,但属实缺乏一些工程美感(是的,哲学家也是思想的工程师!)。主要的原因是,哲学家自己其实也不太确定要不要真的把某些人纳入这场伟大的实验中,这可怎么办呢? + +答案就是:分支! + +我们假设,哲学家本来想要把奴隶主全都碾死,可转念一想,又觉得应该把所有的资本家也都放在铁轨上,但是他并不确定,可以确定的是,他想要奴隶主死,至于资本家,还要再斟酌斟酌。 + +于是他把奴隶主放在最主要的,车子一定会碾过的轨道上——我们把这条轨道称作主分支(master[^1])。至于那些资本家,先放在另一条轨道上,我们给这条分支随便起一个名字,比如 foo,原因是这些资本家挺蠢的(fool[^2]),但又有些实力,只能算四分之三的蠢吧。 + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/git-branch.png) +{.dark:invert} + +于是现在有了两条轨道,电车有两条行驶路径,哎呀呀,真是难选择啊。到底应该让车子往哪边开呢? + +如果哲学家决定不让资本家献身了,那他可以把 `foo` 分支删掉,或者就放在那不管。反正,只要他不拉动拉杆,电车就只会碾过主分支上的奴隶主们。 + +如果哲学家下定决心,觉得资本家也该死,那么他有两个选择,第一个是—— + +### *合并!(merge)* + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/git-merge.PNG) +{.dark:invert} + +需要注意的是,如果仅仅是把 `foo` 分支和主分支接轨,那是无法做到「无人生还」的。我们可以看到,轨道是在第 4 号奴隶主产生分支的,而在那之后,主分支上还相继出现了 5 号和 6 号奴隶主。如果让电车从分叉处驶入 `foo`,又在之后回到主分支,那分叉口之后才出现的 5 号和 6 号不就幸免于难了吗! + +所以,我们要把 5 号和 6 号奴隶主移动到第二个分叉口,也就是电车回到主分支后会到达的地方。这样就能保证合并之后,不会有一个人被落下。 + +“可是,”你可能会说,“这样不是太费铁轨了吗?而且好复杂。”没关系,我们还有第二个选择—— + +### *重整!(rebase)* + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/git-rebase.png) +{.dark:invert} + +对嘛,大家都躺成一排,这样就方便了。 + +## 哲学家的时间旅行魔法 + +在此之前,我们一直使用数字对受试者进行编号,这很直观,可是真正的哲学家却不会这样做。实际上,哲学家使用一种凡人们读不懂的语言为每个人起名,这种语言由数字和字母组成,十分神秘,它长这个样子:`9a0f7b785e`。 + +这种编号是怎么构建出来的呢?很简单,只需要对比这位受试者相比上一位受试者有何不同,并从特征中提取摘要,再进行哈希运算即可得到。 + +不过,即使是哲学家也记不住那么多人名,因此,哲学家规定,在某个时刻下,最后一个会被电车碾压的人为人群之首,记为 `HEAD`。不难理解,`HEAD` 也就是哲学家最近挑选的、最新鲜的工作成果。不过,这其实还要更复杂一些。 + +我们知道,哲学家是四维生物,可以在时间上行走,他可以查看(checkout)任意一个时间点下轨道的状态,以一种凡人没法做到的方式回顾历史。对于哲学家来说,`HEAD` 是他当前查看的那一个工作,也是他开始工作的地方——如果哲学家要添加新鲜的人类样本,或者创建分支,那就是从 `HEAD` 开始的。 + +我们不是知道哲学家可以给铁轨创建分支吗?一般来说,`HEAD` 就是就是当前分支下最新的那一条工作。如果哲学家念出咒语 `git checkout foo`,它就会来到 `foo` 分支,准确来说是 `foo` 分支下最新的那条工作;要回到主分支,只需要念出咒语 `git checkout master`。由此可以发现,轨道的分支实际上就是指向当前分支最新改动的一个指针。 + +哲学家还会使用一种特殊的相对记名法,他使用 `HEAD^` 表示 `HEAD` 的前一条,使用 `HEAD~n` 表示 `HEAD` 前面的第 n 条。这样一来,时间旅行就很方便了,喊出咒语 `git checkout HEAD^` 就能查看当前头部的前一条,也就是把最近这一个人放上铁轨之前的状态。 + +我之前说过,哲学家和上帝或者说科学家的关系很好,他有手段改变历史。这种手段也不难实施,只需要谨慎即可,我现在就传授给你,你只需要喊出咒语 `git reset --hard HEAD^`,就能把时间拨回上一次改动之前。同一系列的咒语还有 `--soft` 和 `--mixed` 等等,但还要等到你更成熟之后,才能施展此法。 + +## 严格筛选 + +哲学家对待他的作品有着近乎偏执的追求,他会像果农挑选樱桃一样挑选受试者。前文提到,哲学家可能还在纠结要不要碾死资本家,他可能发现,这些资本家其中的一些拖欠工资,而另一些则没有。显然,拖欠工资的资本家是一定要死的,但另一部分还需要再作考虑。 + +此时,哲学家显然不能把整个 `foo` 分支直接合并到主分支,他需要挑选其中的一些人,并把他们放在 `HEAD` 后面。这个过程就叫作 `cherry-pick`。 + +![](https://r2.eltr.ac/geedeapro/essays/git-with-trolley/git-cherry-pick.png) +{.dark:invert} + +## 现在,休息吧! + +哲学家累了,挑选总是很累的。没关系,我们可以随时退出,之后再继续工作!不过,哲学家需要提醒你的是,千万不要把未经深思熟虑后选择的人合并到主分支,然后就回家睡觉了。一般来说,我们把主分支视作已经确定了的工作,那些没有确定的,就先放在另一个分支上吧,*反正也跑不了*。 + +一个原则是,一旦有新的想法,就要先创建新分支,然后在分支上添加新人,等工作完成并且确定之后再合并或重整。如你所见,合并和重整并不困难,只需要咒语 `git merge` 或者 `git rebase` 就可以了。如果你正在发展一个想法,但是突然需要回到主分支或者另一个分支进行别的工作,也可以用之前学会的 `git checkout` 咒语进行时间旅行,在时间中移动也是很简单的。 + +不简单的是改写历史,所以,千万不要把没确定的东西合并到主分支! + +在你走之前,还有一些注意事项:如果读完此文发现自己既没有理解电车难题,也没有理解 Git,属于正常现象,前者请求助于道德哲学相关内容,后者可以参考 [Learn Git Branching](https://learngitbranching.js.org/) 这个网站。 + +好了,去睡吧。放心,哲学家是不会偷偷把睡着的人绑在铁轨上的。 + +[^1]: Pun intended. +[^2]: 严肃地讲,这并不是 `foo` 这个词的词源。真正的词源可以参考 [RFC 3092](https://datatracker.ietf.org/doc/html/rfc3092)。 \ No newline at end of file diff --git a/content/article/go-philosophy.md b/content/article/go-philosophy.md new file mode 100644 index 00000000..fae7ec37 --- /dev/null +++ b/content/article/go-philosophy.md @@ -0,0 +1,699 @@ ++++ +title = "Go 语言的编程哲学" +tags = [ "编程", "计算机", "设计",] +date = 2025-11-25T23:49:00 +draft = false +toc = true +aliases = [ "/posts/go-philosophy",] +categories = "代码炼金术" +url = "/essays/go-philosophy/" + ++++ + +从这个月 10 号,水逆期开始,我就开始减少出门,宅在家里读一读书,捡一捡法语学习,看看音乐剧,还找了些新东西来学,Go 语言就是其中一个。一开始只是抱着好奇心探索,并没有什么功利心,不过越学越发觉,Go 真的很适合用来写高并发高性能的 Web 应用(而且越学越讨厌 Java),也完全能胜任系统开发,就业岗位貌似不少,竞争也相对更小。更重要的是,我非常喜欢这种「观点鲜明」的编程语言,我想我会一直用下去的。 + +学任何一门编程语言我都更喜欢「不自量力」地直接上手写代码,一边写一边学基础语法,遇到不知道怎么实现的需求再查阅文档。不过,学 Go 的一开始我发现了 [Go Proverbs](https://go-proverbs.github.io/) 这个网站,便在实战之外还花了不少时间研读这里的「名言警句」。这些 Go 语言编程相关的谚语大多来自 Rob Pike 在 2015 年的[一场演讲](https://www.youtube.com/watch?v=PAAkCSZUG1c),每一条都很有启发性,这篇文章就来逐条阐述我对它们的理解,其中有不少也可以用在 Go 语言以外的编程中,希望能引发读者的一些思考。 + +## Don't communicate by sharing memory, share memory by communicating. + +这句话直接翻译过来是:不要用共享内存的方式通信,要用通信的方式共享内存。 + +这需要一些上下文来理解。Go 是一门可以通过非常优雅的方式实现并发的编程语言,异步编程若是要在多个线程之间同步信息,往往需要加锁,这是为了避免线程同时操作内存,导致冲突、数据准确性(integrity)被破坏等无法预测的问题。加锁一般指的是互斥锁(mutual exclusion object,简写作 `mutex`),线程操作数据时需要先获取对应的锁,如果锁被其他线程持有,则需要等待,获取到锁的线程才能执行操作,这保证数据操作是互斥的。 + +加锁是异步编程中的常见做法[^1],但「锁是痛苦的」,不仅要创建锁、管理锁,还要想办法避免死锁等运行时错误,这类错误没法被编译器察觉,程序员排查起来很困难。所以,为了保证程序的健壮性和可读性,应当避免使用锁。线程之间之所以要用锁来实现互斥,是因为共享了同一块内存区域,而共享内存是为了传递数据,也就是这句话的前半句「communicate by sharing memory」。共享了内存就必须加锁,不然就会出现问题,而锁又会带来更多难题。 + +Go 语言鼓励的「share memory by communicating」,要用到 Go 语言的一个特性—— `channel`。你可以把 `channel` 理解为在不同线程之间传递数据的「通道」。以下是一个整数类型的 `channel` 例子。 + +```go +intChan := make(chan int) + +// 线程 A 传入一个数据 +intChan <- 10 + +// 线程 B 取出这个数据 +someVar := <- intChan +``` + +严格来说,这两个线程仍然共享了 `intChan` 这个 `channel` 类型的变量,但整体上,这种写法避免了直接读写被储存在内存中的数据。在线程 A 没有传入数据时,线程 B 执行到 `<- intChan` 这一行就会自动阻塞,直到取到 `channel` 中的数据。在 `channel` 的**抽象**下,线程不再操作一块无人管理的,需要线程自觉加锁、等待用锁的数据区域,而是相互之间直接传递数据——这就是「share memory by communicating」。 + +Go 语言实现并发的方式非常优雅,而 `channel` 的存在又简化了线程之间共享数据的方式,这使得用 Go 编写并发程序的体验非常舒服,这一点在接下来还会看到。 + +## Concurrency is not parallelism. + +这句话直接翻译过来是:并发不是并行。 + +这其实是计算机科学的基础知识,并发(concurrency)和并行(parallelism)本来就不是一回事。一般来说,并发指的是程序在处理器上交替执行,在单核处理器上,一个进程完全占用 CPU 资源,完成计算或者用完时间片之后,其运行所需的上下文会被保存,然后 CPU 进行上下文切换(context switch),换上下一个要执行的进程的上下文,然后运行下一个进程。每个进程执行时都完全占用一个处理器内核,时间到了之后就让下一个进程执行,只不过进程在 CPU 上切换的速度非常快,宏观上让人感觉是在同步执行。并行指的是真正的同步执行,在多核处理器上,不同的进程在不同的处理器内核上执行,而不需要交替执行。 + +Go 语言是跨平台的,不需要考虑硬件底层,也就是说,编程语言不关心执行程序的计算机究竟有多少个处理器核心。Go 语言强调并发并非并行的原因是,Go 把并发当作一种「编程结构」,即组织程序的方式。程序员在进行多线程编程时,应该聚焦于程序结构而非硬件底层,如果关注程序结构,就能写出更清晰、可读、可维护的多线程程序代码;而且,也不能理所应当地认为自己用了并发的结构,程序就一定是并行的。 + +Go 语言里实现并发非常简单,假设我们有一个 `FetchData()` 函数,而这个函数需要进行大量 IO 操作或者需要发送 HTTP 请求,如果同步执行会长时间阻塞主线程,要把这个函数变成并发的,只需要在调用函数时,在前面加一个关键词 `go`。这有点像 JavaScript 里的 `async`,但并不相同。 + +```go +go FetchData() // 这样就创建了一个线程执行 FetchData() +``` + +在 Go 语言里,一个线程被称作 `goroutine`,和 Java 中 `Thread` 的显著区别是:`Thread` 是一个类,需要创建和管理对象;`goroutine` 是一种**控制结构**,直接写就好了。另一个很重要的区别是,Java 线程占用的内存是 MB 级别的,而一个最基本的 `goroutine` 大小只有 2 KB。简单来说,`goroutine` 用起来很简单,创建的成本也很低。 + +很重要的一个点是,将并发作为一种控制结构也让代码变得更可读了,比如上面那一行代码,就可以很有喜感地读成:*Go! Fetch data!* + +以下是一个 `goroutine` 配合 `channel` 的并发示例,代码来自我的项目 [wthis](https://github.com/BigCoke233/wthis): + +```go +fmlChan := make(chan *FormulaInfo) +caskChan := make(chan *CaskInfo) +rvsChan := make(chan []string) +// start 2 goroutines, fetching formula/cask info and uses +go func() { + formula, cask := GetBrewInfo(pkgName) + fmlChan <- formula + caskChan <- cask +}() +go func() { + rvsChan <- GetBrewUses(pkgName) +}() +stat = NewStatistics(<-fmlChan, <-caskChan, pkgName, <-rvsChan) +``` + +总结一下,关注程序结构,写出更清晰的代码,在逻辑结构上让代码异步执行,这是并发;至于并行,那与硬件底层和操作系统有关,不能认为按并发结构编写的代码就一定是并行的。 + +## Channels orchestrate; mutexes serialize. + +这句话直接翻译过来是:Channels 编排;互斥锁串行。 + +尽管 Go 提供了在大部分时候都更好用的 `channel`,也更鼓励使用 `channel`,但互斥锁并不是被禁止的,也没有从这门语言里消失,因为有些时候必须要用到锁。这句话简单回答了「什么时候该用 channel?」「什么时候该用锁?」这两个问题,也能帮助 Go 程序员更好地理解 `channel` 的用途。 + +编排这个词很有意思,它的原文是 orchestration,又名 choreography,意思分别是「编配管弦乐曲」和「编舞」。如果你理解概念,就会觉得这个描述非常生动形象。这个词在不同的语境下的意思有一些区别,但一般指代一种自动化的工作流,可以统一调度、掌控多个作业,高效处理大量用户请求,或者让多个程序之间相互协作等等。在管弦乐(orchestration)中,各个演奏者各司其职,但由指挥家统一主导;在舞蹈(choreography)中,舞者之间需要相互沟通,分工协作。这引申到编程中,对应了不同的编程结构,下面用简单的例子来解释。 + +假设有一项操作需要大量计算,这些计算被分散开,启动多个 `goroutines` 执行,最后由主线程将计算的结果整合起来,Go 语言代码可以这样写: + +```go +// 有 100 项作业需要执行,相应地有 100 项结果需要接收 +// 分别创建 channel +jobs := make(chan int, 100) +results := make(chan int, 100) + +// 启动 10 个 Worker 执行这些作业 +for w := range 10 { + go Worker(w, jobs, results) +} + +// 传入 100 个作业给 jobs channel +// worker 接收到之后就会执行 +// 执行完一个作业之后会继续接收 jobs channel 里的剩余作业 +for j := range 100 { + jobs <- j +} +close(jobs) + +// 收集 100 个作业结果 +for _ := range 100 { + doSomethingWith(<- results) +} +``` + +这是一个典型的 Worker Pool。这个例子中,主线程就是指挥,而 Workers 就是乐队成员,整体上,这就是一种编排(orchestration)。 + +假设有三个作业(A、B、C),C 作业依赖 A 和 B 的结果,而 B 依赖 A 的结果,要让这三个作业相互配合完成工作,可以这样写: + +```go +a := make(chan int) +b := make(chan int) +c := make(chan int) + +// A +go func() { + result := doSomething() + a <- result +}() + +// B +go func() { + result := doSomething(<-a) + b <- result +}() + +// C +go func() { + result := doSomething(<-a, <-b) + c <- result +}() +``` + +三个作业各司其职,使用 `channel` 相互通信完成了工作,A、B 和 C 都可以被视作相互配合的舞者,这也是一种编排(choreography)。 + +Go 语言还提供 `select` 控制结构,用于监听和操作 `channel`。在线程等待多个操作返回结果的时候,可以使用 `select`,数据先从哪个管道过来,就先处理哪一个。 + +```go +// 例子来源:https://gobyexample.com/select +c1 := make(chan string) +c2 := make(chan string) + +go func() { + time.Sleep(1 * time.Second) + c1 <- "one" +}() +go func() { + time.Sleep(2 * time.Second) + c2 <- "two" +}() + +for range 2 { + select { + case msg1 := <-c1: + fmt.Println("received", msg1) + case msg2 := <-c2: + fmt.Println("received", msg2) + } +} +``` + +`select` 和 `channel` 为 Go 语言提供了十分强大的编排能力,允许程序员在大多数情况下高效处理业务,而不是机械地等待上一个操作完成再做下一个。当然,严格的串行也是存在的,通常是为了保证某一操作的**原子性**(Atomic),即不可被打断性,这个时候就要用到锁。 + +在 Go 中使用锁需要用到标准库 `sync`,一个常见的做法是把 `sync.Mutex` 放到使用它的结构体中。以下例子实现了一个计数器容器,一个 `Container` 中有多个计数器(`counter`),`inc`(自增)方法用于自增指定计数器。默认情况下 `++` 是一个非原子(non-atomic)操作,如果多个 `goroutine` 都在对同一个计数器自增,极有可能会相互影响——例如,A 读取到计数器的值是 5,自增后写回 6;B 在 A 写回之前也读取了计数器,值也是 5,也写回 6,这就覆盖了 A 的操作;两次自增的结果本应该是 7,但由于操作的非原子性,变成了错误的 6。 + +为了保证自增操作的原子性,可以在自增时加锁,不允许其他 `goroutine` 读写。 + +```go +// 例子来源:https://gobyexample.com/mutexes +type Container struct { + mu sync.Mutex + counters map[string]int +} + +func (c *Container) inc(name string) { + c.mu.Lock() + defer c.mu.Unlock() + c.counters[name]++ +} +// ... +``` + +注意 `defer c.mu.Unlock()` 这一行代码。`defer` 关键词表示这行代码会在其周边代码执行完毕之后被执行,用在 `Unlock()` 和 `Close()` 这样的操作前面,就可以把它们紧挨着 `Lock()` 和 `Open()`,防止忘记关锁。`defer` 还会在程序 `panic`(遇到无法处理的错误)时执行,因此 `defer` 也经常被用来恢复错误。 + +以上操作也可以直接用 Go 标准库提供的原子计数器,不需要自己封装。 + +```go +var ops atomic.Uint64 +ops.Add(1) +``` + +总而言之,`channel` 用于高效、灵活地编排程序,而 `mutex`(互斥锁)用于安全、严格地保证串行。 + +## The bigger the interface, the weaker the abstraction. + +这句话直接翻译过来是:接口越大,抽象越弱。 + +熟悉面向对象编程的程序员应该不会对 `interface`(接口)感到陌生,它用于规定一个类应该实现什么方法,也让静态类型语言的类型系统变得更强大。例如,Java 中的 `List` 接口规定了列表应该实现 `add()` 等方法,同时也让底层实现不同的列表(`ArrayList`、`LinkedList`...)可以通用——如果一个方法要求传入一个 `List` 作为参数,无论传入 `ArrayList` 还是 `LinkedList` 都是可以接受的。 + +Go 语言鼓励程序员编写「小巧」的接口,就像这样: + +```go +type Writer interface { + Write() +} +``` + +只有一两个方法的接口看起来很没用,但语义非常明确:Writers write; Dancers dance; Eaters eat. 用 -er 后缀结尾的词命名接口几乎是 Go 语言的惯例。小巧的抽象是强大的,它能让程序员更灵活地使用 Go 语言的类型系统。 + +例如,这是一个日志接口: + +```go +type Logger interface { + Log() +} +``` + +在某个系统中,日志可能有三种输出方式:直接输出到终端、写入文件和发送 HTTP 请求给远程服务器。 + +```go +type StdoutLogger struct{} + +func (s StdoutLogger) Log(msg string) { + fmt.Println(msg) +} +``` + +```go +type FileLogger struct { + f *os.File +} + +func (fl FileLogger) Log(msg string) { + fmt.Fprintln(fl.f, msg) +} +``` + +```go +type HttpLogger struct { + endpoint string +} + +func (h HttpLogger) Log(msg string) { + http.Post(h.endpoint, "text/plain", strings.NewReader(msg)) +} +``` + +现在,我们正常编写业务逻辑,在处理某个数据的时候,突然有了记录日志的需求。由于我们定义了 `Logger` 接口,处理数据时不需要思考应该用哪种方式输出日志,只需要接收一个 `Logger`,直接 `Log()` 就好。调用这个函数时再传入具体的 `StdoutLogger` `FileLogger` 或者 `HttpLogger`。 + +```go +func Process(data string, logger Logger) { + logger.Log("processing: " + data) +} +``` + +短小的接口看起来没用,但接口完全可以像搭积木一样把方法堆叠起来,比如下面这个类型就既是 `Writer` 又是 `Closer` 还是 `Logger`。 + +```go +type FileWriter struct { + f *os.File +} + +func (*fw FileWriter) Write() { ... } +func (*fw FileWriter) Close() { ... } +func (*fw FileWriter) Log() { ... } +``` + +`interface` 实际上是对类型的「限制」,规定的方法越多,接口越大,要实现这个接口就越难,应用的场景也就越局限。Go 语言不是严格意义上的面向对象编程语言,它更关注**类型**,而短小的接口使得程序员可以更灵活地使用类型系统。 + +顺带一提,和面向对象编程语言不同,Go 语言不需要显式地指定实现哪些接口,只要包含了接口规定的方法的类型,都会被归为这个接口。 + +```java +// 在 Java 中实现接口 +class FileWriter implements Writer { + public void write() { ... } +} +``` + +```go +// 在 Go 中实现接口 +type FileWriter struct { ... } +func (*fw FileWriter) Write() { ... } +``` + +## Make the zero value useful. + +这句话直接翻译过来是:让零值变得有用。 + +Zero value 指的是变量被声明但尚未初始化(赋值),类型系统自动为变量填充的值。对字符串来说,这个值是 `""`,整数是 `0`,浮点数是 `0.0`,布尔值是 `false`,指针是 `nil`。结构体被声明时,其中的变量也会被填充零值。 + +Go 语言鼓励程序员好好利用这个零值,让类型即使没有初始化也能正常使用。标准库里有很多例子,前面提到的 `sync.Mutex` 就是一个。让我们回看这个例子: + +```go +// 例子来源:https://gobyexample.com/mutexes +type Container struct { + mu sync.Mutex + counters map[string]int +} + +func (c *Container) inc(name string) { + c.mu.Lock() + defer c.mu.Unlock() + c.counters[name]++ +} +// ... +``` + +显然,`inc()` 方法没有初始化 `c.mu` 这个 `sync.Mutex` 类型的变量,`c.mu` 里面装的是默认的零值,但零值仍然可以被正常使用。我觉得这句谚语更准确的说法应该是:Make the zero value us**able**. + +另一个例子是标准库里的 `bytes.Buffer`: + +```go +var b bytes.Buffer +b.Write([]buffer("Hello World")) +io.Copy(os.Stdout, &b) +``` + +字节缓冲区没有初始化,仅仅是声明过后就可以直接调用 `Write()` 方法使用。如果是在 Java 语言里,你大概需要 `new` 一个类的实例才行,或者用到别的构造方法,总之做不到声明即用。 + +Go 语言之所以强调「让零值可用」「声明即可用」,除了让代码更简单易读、编写程序更简单,另一个原因是在 Go 语言里,空指针(`nil`)可以用来调用未被初始化的类型的方法。假设你有一个名为 `Config` 的结构体类型,你为它编写了 `Path()` 方法,你声明一个 `Config` 之后并没有指定路径,甚至 `Config` 本身就是空的,`Path()` 也可以返回一个默认值。 + +```go +func (c *Config) Path() string { + if c == nil { + return DEFAULT_STRING + } + return filepath.Join(USER_HOME, c.Filename) +} +``` + +简单来说,如果你可以直接使用零值,就不要把事情搞得太复杂! + +## `interface{}` says nothing + +这句话直接翻译过来是:空接口说明不了任何东西。 + +这里说的并不是在编写接口时没有编写任何方法这种明显的错误,而是指在声明类型时使用 `interface{}`。前面提到,Go 并非是面向对象编程语言,`interface` 是为类型服务而非对象服务的;在 Go 里面,实现方法不需要显式声明,只需要实现规定的方法就好了——没有方法的空接口,自然能匹配任何类型。 + +`interface{}` 常常被用来接收不确定类型的值,很多时候这种操作是必要的,但 Rob Pike 指出,很多人滥用了空接口类型,他说: + +> You might as well write in Python. +> +> 你还不如去写 Python 呢。[^2] + +将代码保持在 Go 严格的类型系统中,有助于保持程序的安全性。除此之外,空接口最大的问题是「不够清晰」——清晰的代码可读性是 Go 语言的核心之一。使用空接口类型让函数的输入和行为都变得不可预测,代码更难阅读,而且更难发现 Bug。 + +在 Rob Pike 这场演讲的几年之后,Go 发布了 1.18 版本,其中添加了 `any` 类型,是 `interface{}` 的别名。添加这个别名的主要原因是让代码变得更可读,人们看到 `any` 就会知道在这里传入任何类型的值都可以,而不熟悉 Go 的人看到 `interface{}` 可能会觉得困惑。即使是 `any`,在使用前也要想清楚自己是不是真的没有办法预测数据类型,还是只是为了图省事而牺牲了安全性和可读性。 + +合理使用 `any` / `interface{}` 的例子是标准库里的 `fmt.Println()` 方法,程序员的确无法预知要打印的是字符串、数字还是别的什么类型。 + +总之,这条谚语让程序员严格遵守 Go 的类型系统。 + +## Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. + +这句话直接翻译过来是:gofmt 的样式不是任何人的最爱,但 gofmt 是所有人的最爱。 + +`gofmt`(或者 `go fmt`)是 Go 语言提供的命令行工具,用于格式化 Go 源代码。写完 Go 语言代码之后在项目根目录执行 `gofmt -s -w .` 就可以一键格式化代码。`gofmt` 的样式是统一的,没有自定义的空间,这看起来死板,让程序员不能用自己喜欢的风格格式化代码,但好处在于,有一个官方的格式意味着团队之间无需对代码风格做出讨论和决策,也不需要像 JavaScript 开发者一样纠结用 ESLint 还是 Prettier 等第三方代码格式化工具——用官方的 `gofmt` 就好了!这样一来,开发者就可以把心思放在更重要的事情上。 + +总而言之,不要纠结这个地方要不要用 Tab、那个地方要不要换行了,你的开发环境里已经有 `gofmt` 了。 + +## A little copying is better than a little dependency. + +这句话直接翻译过来是:一点点复制比一点点依赖更好。 + +大部分程序员都在强调代码复用性(reusability),排斥重复造轮子,追捧 DRY(Don't Repeat Yourself)的理念,这导致许多程序员在编写简单的需求时也会使用大量的第三方依赖库,即使他们只调用其中的一两个方法,即使自己完全可以封装一个三五行代码的函数来实现相同的需求。 + +Rob Pike 强调:要保持一个小巧干净的依赖树。维护依赖是痛苦的,因为依赖是**动态**的,如果依赖库有更新、出了问题,使用了这个依赖库的代码往往也需要跟进。这个教训,已经被 JavaScript 程序员吃尽了,JavaScript 庞大的生态意味着几乎没有一个 JavaScript 项目不大量使用依赖库,而一个 JavaScript 项目要是有几个月的时间没有更新,代码很可能就过时甚至用不了了。 + +所以: + +1. 在大多数情况下都尽量依赖标准库; +2. 需要更复杂的工具时,优先考虑封装在自己的代码库里; +3. 如果几行代码就能解决,就不要引入依赖; +4. 如果考虑周全,得出结论认为一定要使用第三方库,这时候才引入依赖。 + +总而言之,**头脑清晰**的「C-V 工程师」比喜欢尝试各种库的「时髦工程师」写出来的代码更稳定! + +## Syscall must always be guarded with build tags. + +这句话直接翻译过来是:Syscall 必须总是被构建标签守护。 + +`syscall` 即系统调用,允许程序从用户态访问内核态,像操作系统发出请求,完成需要系统级权限的操作。系统调用很强大,很多情况下也是必要的,尤其是在系统级开发下几乎必不可少,但系统调用的问题是:它不跨平台。 + +Windows、macOS 以及各种千奇百怪的 Linux 发行版,各自的 `syscall` 都有很大差异,几乎不能写出通用的代码。要保证全平台通用,就应该用 `os` 库;但如果必须用 `syscall`,就要用 Go 编译器的「构建标签」(build tags)。 + +构建标签实际上就是写在文件开头的一行注释: + +```go +// go:build linux +``` + +上面这行代码给整个文件添加了 `linux` 的构建标签,表示只有在 Linux 操作系统下才编译这个文件。构建标签也可以有别的用处,比如软件有 Free 和 Pro 两个版本,Pro 版的功能就可以单独写在几个文件里,给这些文件加上 `pro` 的构建标签,然后在构建的时候这样编译: + +```shell +go build -tags pro +# 在编译时手动加上 pro 标签 +``` + +区分 `debug` 模式,区分生产环境和开发环境,也可以用到构建标签。 + +## Cgo must always be guarded with build tags. + +这句话直接翻译过来是:Cgo 必须总是被构建标签守护。 + +Cgo(读音类似 Seagull)指的是 Go 语言标准库里的 `C` 包,这个包提供的方法允许程序员在 Go 语言中调用 C 标准库,还可以在注释里写 C 代码并使用在 Go 代码中。 + +```go +// 例子来源:https://go.dev/wiki/cgo + +/* +##include +##include + +void myprint(char* s) { + printf("%s\n", s); +} +*/ +import "C" + +import "unsafe" + +func Example() { + cs := C.CString("Hello from stdio\n") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) +} +``` + +和 `syscall` 一样,操作系统提供的 C 标准库实际上并非完全相同,C 语言并不跨平台。如果要用 Cgo,就必须使用构建标签声明这段代码是为哪个平台编写的。 + +## Cgo is not Go + +这句话直接翻译过来是:Cgo 不是 Go。 + +这句话强调的是,Go 语言提供性能良好的垃圾回收机制、安全的类型系统、安全的操作内存的方式,编写纯粹的 Go 代码可以保证准确性、稳定性、安全性以及代码可读性。相反,C 语言本身并不是一门安全的语言,需要程序员手动 `free()` 释放内存,容易出现段错误等等。如果使用 Cgo,就会失去 Go 语言自带的各种安全机制,很容易出现难以排查的问题。 + +Rob Pike 建议,尽量避免使用 Cgo,你多半不需要用到它。 + +## With the unsafe package there are no guarantees. + +这句话直接翻译过来是:用了 `unsafe` 包就没有保障。 + +在前面使用 Cgo 的例子里,就已经演示过了 Go 标准库提供的 `unsafe` 包。它的功能很强大,能绕过类型系统直接访问内存、把指针当作整数来用…… 能力越大,责任也越大。和 Cgo 一样,使用 `unsafe` 就等于抛弃了 Go 提供的安全机制——跑出安全区的样子好像很酷,但你为什么不直接去写 C 呢?明明用 `unsafe` 还麻烦不少。 + +Rob Pike 建议避免使用 `unsafe`,至少使用之前要想想自己是否真的需要用到这么强大又危险的功能,用的时候也要做好可能出错的准备。 + +## Clear is better than clever. + +这句话直接翻译过来是:聪明比不过清晰。 + +这解释了 Go 语言为什么移除了三目表达式,原因就是它不够清晰。一般来说,三目表达式其实非常好用,在 C、Java 和 JavaScript 等热门语言中都存在。 + +```js +// ? 前面是一个布尔值或者布尔表达式 +// ? 后面是为 true 的结果 +// : 后面是为 false 的结果 +console.log(OK ? "It's okay" : "It's not okay") +``` + +这看起来还挺清晰的,但 Go 的设计者发现有不少人会用三目表达式来编写令人费解的控制结构。 + +```js +const someString = isAnimal + ? (isElephant ? "I'm an elephant" : "I'm just a dumb animal") + : (CheckIfItIsAPlant() + ? "I can't speak. I'm a plant" + : "Fuck, I'm not even a plant?") +``` + +三目表达式被滥用过后会大大降低代码可读性,Go 语言鼓励看起来很蠢,但清晰可读的写法。 + +```go +var someString string +if isAnimal { + if isElephant { + someString = "I'm an elephant" + } else { + someString = "I'm just a dumb animal" + } +} else { + if CheckIfItIsAPlant() { + someString = "I can't speak. I'm a plant" + } else { + someString = "Fuck, I'm not even a plant?" + } +} +``` + +还有那些过度复杂的条件表达式,看起来很聪明,但可读性非常差。 + +```go +// ❌ + +if thisVar <= thatVar || (isLikeThis && fetchStatus() != status.OK) { + return +} + +// ✅ + +if thisVar <= thatVar { + return +} + +statusOK := (fetchStatus() != status.OK) +if isLikeThis && !statusOK { + return +} +``` + +更直接、简单、清晰的代码不仅提高可读性,让维护代码变得更容易(这对自己和团队成员都是好事),也变相提高了代码稳定性,因为清晰的代码更容易排查问题。 + +执拗地写聪明但不清晰的代码有点像某种大男子主义的攀比心,像是「我昨天熬夜到凌晨四点把工作做完了!」,许多人都会为这种刻苦但实际上是耍帅的精神鼓掌,然而,人的认知能力在凌晨四点到六点比喝醉了酒还要差[^3],而且熬夜对身体的伤害不必多说。 + +## Reflection is never clear. + +这句话直接翻译过来是:反射永远不清晰。 + +反射(Reflection)是很多高级语言里都有的机制,用于在程序**运行时**检视和操作对象。有的信息在程序运行之前无法预知,要在程序中使用这些不可预知的值,就可以用到反射;比如前面提到的空接口,如果函数接收一个空接口类型(任意类型)的值,但需要根据值的类型执行操作,就可以利用反射来获取这个值的类型。 + +反射也带点 Meta(元)的意味,经常被称作 Metaprogramming(元编程),因为它可以被用来检视程序自身的结构,比如 Java 语言中就可以利用反射机制获取某个类的注解、构造函数、成员变量等等,并把它们当作普通的对象来使用。 + +在 Go 语言提供的 `reflect` 包里,大致有以下几种方法: + +```go +// 接收一个 interface{} 类型的值,即任意类型的值 +func doSomeReflection(i interface{}) { + // 获取 i 的类型 + // 一个定义在 main 包里、名为 User 的结构体会返回 main.User + t := reflect.TypeOf(i) + + // 获取 i 的底层类型 + // 同样一个名为 User 的结构体,会返回 struct + k := reflect.KindOf(i) + + // 获取 i 的值 + v := reflect.ValueOf(i) + // 如果要获取值的类型,就可以这样写 + vk := reflect.ValueOf(i).Kind() + + // 如果 i 是一个结构体,可以用这个方法获取它的字段数量 + nf := reflect.NumField(i) + + // Field() 方法用于获取字段,配合上面的方法可以遍历结构体 + for n := 0; n < numberOfFields; n++ { + // 这里会输出该字段的类型和值 + fmt.Printf("Type:%T, Value:%#v", value.Field(n), value.Field(n)) + // 这里输出的是该字段的底层类型 + fmt.Println("Kind is ", value.Field(i).Kind()) + } +} +``` + +至于 Rob Pike 为什么说「反射不够清晰」,我想读完上面的代码已经不言自明了,反射就是很难读。我认为最根本的原因是,在代码中引入反射,迫使程序员用另一个完全不同的视角(元视角)来审视代码,这种视角的转换是很困难的,而且往往要同时使用常规的编程逻辑和元编程逻辑才能读懂反射。 + +这并不是说反射不好,有的需求必须要用反射实现。只不过,清晰永远比聪明更好,如果有更清晰的、不涉及反射的方法,那就不要用反射。 + +## Errors are values. + +这句话直接翻译过来是:错误是值。 + +接下来我们正式进入到 Go 的错误处理哲学。Go 语言完全抛弃了传统的 `try ... catch` 结构,将错误简化为值,将错误处理从一种特殊的控制接口降级为简单的 `if ... else`。Go 还支持多函数返回值,也就是说,你可以将错误当成一个返回值返回给调用者,而不需要像 Java 一样抛出(throw)。 + +在 Go 的错误处理中,程序员最常写的就是这样一段代码: + +```go +result, err := GetSomeData() +if err != nil { + // 在这里处理错误 +} +``` + +如果是 Java 等依赖 `try ... catch` 进行错误(异常)处理的语言,你需要这样写。 + +```java +try { + // 其他相关的代码 + ResultType result = GetSomeData() + // 继续其他相关的代码 + // ... +} catch (IOException e) { + // 处理 IO 异常 +} catch (Exception e) { + // 处理其他类型的异常 +} +``` + +这意味着你需要把可能会抛出错误(异常)的代码提前包裹在 `try ... catch` 块中,而且你还创建一个新的作用域(scope),如果你在 `try ... catch` 里面获取了数据,就得直接在里面处理这个数据,或者在这个作用域外面先声明函数,再在里面使用。总之是有点麻烦的。更不用说,在 Java 里面你还需要考虑不同类型的异常,光是想到这些我都不想做错误处理了。 + +Go 语言将错误作为值,不仅让错误处理变得简单直观,减少了一种控制结构,还让程序变得更灵活——既然错误是值,那你就可以把错误储存起来,像普通的值一样直接写进日志里,放进一个 map 里,缓存起来,或者等完成一大批操作之后统一反馈给用户,甚至发送给你的妈妈看——最后一条是 Rob Pike 在演讲时开的玩笑。其他语言也可以做到,但在 Go 里面会更容易,更重要的是,你可以对错误进行编程,而不会被局限在 `try ... catch` 这一种控制结构里。 + +总之,错误在 Go 语言里是值,你可以用它干任何事情! + +## Don't just check errors, handle them gracefully. + +这句话直接翻译过来是:不要只是检查错误,要优雅地处理错误。 + +所谓的「gracefully」(优雅地)其实只是「intentionally」(有意识地),也就是不理所当然地使用一种错误处理方式,不理所当然地觉得「发生错误了,我直接输出错误信息就好了」,而应该思考:我应该不应该增加更多上下文信息?应该不应该保存这个错误,做完其他事情之后再打印出来? + +以下是写在[官方文档](https://go.dev/doc/effective_go#errors)里的,处理错误的例子: + +```go +for try := 0; try < 2; try++ { + file, err = os.Create(filename) + if err == nil { + return + } + if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOSPC { + deleteTempFiles() // Recover some space. + continue + } + return +} +``` + +`for` 循环的目的是尝试创建文件两次,如果第一次成功(`err == nil`),就 `return` 跳出循环,不执行第二次;如果第一次失败,那就对 `err` 进行类型断言(type assertion),判断这是不是一个 `PathError`,并进一步对错误进行检查,如果发现是空间不足导致的错误,就调用 `deleteTempFiles()` 函数删除临时文件恢复一些空间,然后 `continue` 进行下一次循环,再次尝试创建文件。 + +总而言之,不要把错误抛出来之后就真的抛之脑后了,想想自己能对这个错误做些什么! + +## Don't panic. + +这句话并不是 Rob Pike 在前文提及的演讲中发表的,而是写在 Go 官方文档里的[一句话](https://go.dev/wiki/CodeReviewComments#dont-panic),由于它和前面两小节讨论的错误处理相关,我就插到了这里。 + +直接翻译过来是:不要恐慌(panic)。这里的 `panic` 指的是 Go 语言中用于错误处理的一个函数,表示程序遇到了**意料之外**且无法处理的错误,必须结束程序。这句话很直接地告诉你:不要使用 `panic()` 函数。 + +文档很明确地告诉 Go 程序员,不要把 `panic()` 用来处理常规错误,任何能被预料的、有办法处理的(诊断原因并打印错误也是一种处理),都应该使用 `error` 类型的值,并将这个值作为函数的额外返回值返回给调用者,然后调用者再检查 `if err != nil` 来处理错误。原因在于,`panic()` 会直接结束程序,只有在程序真的完全没有办法继续执行,发生了无法预料的致命错误时,才应该使用 `panic()`。 + +即使是这样,`panic()` 也可以被恢复,即使程序被 `panic()` 停止,`defer` 的函数也会执行(前文有提及),程序员可以在 `defer` 函数中使用 `recover()` 函数恢复错误。以下是官方文档中的例子。 + +```go +func server(workChan <-chan *Work) { + for work := range workChan { + go safelyDo(work) + } +} + +func safelyDo(work *Work) { + defer func() { + if err := recover(); err != nil { + log.Println("work failed:", err) + } + }() + do(work) +} +``` + +简单来说,除非真的没办法处理,否则不要 `panic()`。 + +## Design the architecture, name the components, document the details. + +这句话直接翻译过来是:设计架构,命名组件,用文档展开细节。 + +比起编程语言的基础知识,这条更像是软件工程的经验之谈,Rob Pike 说这是在 Go 语言中设计大型软件系统的方式,不过这对任何语言来说似乎都大有裨益。这句话总结了系统设计的三步骤: + +1. 设计架构:宏观上,完成这个软件系统,我需要哪些组件(模块)? +2. 命名组件:给每个组件起个好名字,清晰的名字会让系统更容易被理解,最好是让人看到名字之后就立马能知道各个组件的职责。 +3. 用文档展开细节:就像命名变量和函数一样,清晰直观固然能提升可读性,但也免不了要写注释。一些名字说不清楚的细节,就在文档里写清楚。 + +## Documentation is for users. + +这句话直接翻译过来是:文档是给用户的。 + +> A lot of time when people write documentation, they say "this is what the function does", and they don't think about "what the function is for". +> +> 很多时候人们写文档,会写「这个函数会做这个事情」,而他们不会想「这个函数是拿来干嘛的」。 + +这条也更像是工程智慧,而非语言的基础知识。在我的理解力,「这个函数是拿来干嘛的」其实是提供了相关的上下文,即「为什么一开始要设计这个函数」「为什么用户会用到这个函数」。在上一小节的例子中,`safelyDo()` 函数封装了 `do()` 函数,用于恢复可能出现的 `panic`,如果只考虑「做什么」,文档就应该是这样: + +> `safelyDo()` 调用 `do()`,并恢复潜在的 `panic`。 + +但用户可能会感到困惑:我为什么会需要恢复潜在的 `panic`?不恢复会有什么问题吗?如果这样写,就会清晰不少: + +> 由于 `do()` 可能会触发不可恢复的 `panic` 错误,为了保证程序能继续执行,`safelyDo()` 会恢复错误并不中断程序。 + +--- + +## 我的想法 + +总结下来,我认为 Go 语言最鲜明的几条观点是: + +1. ==代码的可读性和可维护性比开发效率更重要。== 不要贪快写聪明的代码而忽略了其他人能不能读懂、几个月后的自己能不能读懂,不要因为自己的好恶影响了代码的风格,不要因为不愿意复制粘贴就引入动态的依赖,不要因为方便就滥用强大但不安全且不跨平台的 `syscall`、Cgo 或 `unsafe`,减少使用不清晰的反射。我认为这是**反技术债务**且**长期主义**的,这避免了给未来的自己和开发团队留下隐患、增加工作量。 +2. ==程序员必须要有清晰的头脑,而且不能把任何事情当成理所当然,要思考每一个决策。== 使用 `interface{}` 接收任意类型很好用,但自己真的无法确定参数的类型吗?直接打印错误看起来很常规,但自己有没有办法恢复错误,或者打印错误时能不能提供更清晰的上下文信息以供排查问题?我要实现的需求真的只能用危险的 `unsafe` 或 Cgo 实现吗,如果一定要脱离 Go 的安全区,我愿不愿意接受代码随时可能崩溃的代价?代码复用和不重复造轮子真的是任何时候都必须遵守的铁律吗,这个涉及第三方库的需求我真的不能自己写吗? +3. ==不要轻易离开 Go 的保护。== Go 有自带的垃圾回收机制、安全的内存访问和各种安全机制,使用 Cgo 和 `unsafe` 就失去了 Go 的保障。 +4. ==保持代码的灵活性。== 无论是小巧的、积木式的接口、「错误是值」的思想,还是保证零值可用的做法,在我看来都是为灵活性服务的。小接口让抽象更强大,类型系统更灵活;错误是值意味着可以对错误做任何对值能做的事情;零值可用意味着无论有没有初始化,无论变量是不是空的,方法都可以被正常地调用。 + +目前看来,Go 就是一门既安全又灵活,写代码既优雅又清晰,没有痛苦且观点鲜明的编程语言。Go 能用更少的代码写出更健壮的程序,很难令人不爱。 + +[^1]: C 语言里还有用信号量(Semaphore)实现互斥的方法,不过似乎已经没有什么人用了。 + +[^2]: 此处并非嘲讽 Python 语言和 Python 程序员,这么说是因为 Python 是一门非常灵活的**动态类型语言**。Rob Pike 的意思应该是:滥用 `interface{}` 就像是抛弃了类型系统,把 Go 当作动态类型语言来说,如果这么做的话,用真的动态类型语言会更好。 + +[^3]: 来源:《[绝佳时间](/library/2025/绝佳时间/)》 \ No newline at end of file diff --git a/content/article/he-is-not-your-soulmate.md b/content/article/he-is-not-your-soulmate.md new file mode 100644 index 00000000..64442dd1 --- /dev/null +++ b/content/article/he-is-not-your-soulmate.md @@ -0,0 +1,33 @@ ++++ +title = "He's Not Your Soulmate" +categories = "乱章" +tags = [ "M", "爱",] +date = 2025-11-13T23:25:00 +draft = false +toc = true +aliases = [ "/posts/he-is-not-your-soulmate",] +url = "/posts/he-is-not-your-soulmate/" + ++++ + +周一早上五点,我醒来,意识到自己好像梦到了[他](/tags/M/),梦里他看起来和我记忆中的模糊印象不太一样,好像更高更瘦。梦里他和一个女生在一起,而我目睹了我不应该看见的画面。我跌跌撞撞地跑进厕所,意识模糊,很快又回到了床上,试图继续那个梦境,我大概觉得自己需要也能够改变那个梦。 + +周二,我拿到了新的活页本,比我想象的要大一些,但装上自己选的内页,划分好分区之后,还是觉得很满意——之后就完全用这个本子规划和记录生活吧!我在纸上写字,试图填充自己,可当我把本子装进挎包,走出家门,站在无事可做的通勤路上,那个梦又来烦我了。我没有把它写下来,我总觉得我该记下这个梦的,但我没有这样做,可能我害怕向包括自己在内的任何人暴露那种可怕的感受。不过,总归是要面对的,它很快会再找上我。 + +周三,我确认自己完成了本子上所有的计划,也做完了第二天的规划,打算补上今天的拉伸之后就上床睡觉。我在卧室地毯上做蜥蜴式,头埋进手心,贴在了地上。地毯或许该洗了,我有些委屈。我想起室友说我把卧室布置得像是私人影院,于是我又想起了和那个人在私影看恐怖片的记忆。我感觉把自己压在地上的并不是我的肌肉力量,也不是重力,而是那个[在我脊髓间穿梭的恶魔](/posts/用文字埋葬自己/)——我知道了,我会好好处理自己的情绪的!只不过,要等到明天…… + +我夜不能寐,把记忆里他的形状拉到我的表意识,想象我靠在他的肩上,或者他偎在我的怀里,什么都好,我只是想要糟糕的感觉停下,可我做不到。半个小时后,我意识到自己没办法就这样睡去。我打开手机,去翻找半年前我和他的聊天记录。我记得他给我发过好几张照片,我想找到。我大概是疯了,但我早就习惯自己失去理智的样子了——这毕竟是深夜,月亮就是会让人发疯的。 + +我没有找到任何一张照片,但我没有忍住读了好多以前的消息,听了他发过来的语音,听他软软的声音。我在笑,我似乎很开心,为什么呢?搞懂原因或许不再重要了,因为我很快发现了沉浸在梦里的我没有发现,或者说刻意忘掉了的事实—— + +He's just being nice. + +我不清楚半年前、一年前的我有没有读出过他消息里的敷衍,因为他实在是把自己的不关心包装得太好了,如今的我,在产生了一些距离之后,才感受到那种防备。我也不清楚那时的我有没有因为他没回复消息而辗转反侧,因为事实是,他并不是每条消息都回,可我记得,我总是向别人说:「他会很认真地在我发的一长串消息里看我说了哪几件事情,然后引用每一条,一条一条地回复」。更重要的是,我不知道,未满二十岁的那个我,究竟有没有发现,这个人实际上并不像自己想象的那样,理解自己说的每一句话,而我自己也不总是和他说一样的语言——我究竟知不知道,他并不是那个我不需要多言就能被理解和接受的一个人? + +He's not your fucking soulmate. Wake up. + +我放下手机,躺下了。我的心不再惴惴不安,只是被一阵纯粹的失落占据。睡着之前,我还在想,刚才听到的声音,似乎也和我记忆里的不太一样。我的脑子不再有复杂的想法了,认清现实总是万灵药,只是治不好伤心而已。 + +周四,我继续生活,一边拉伸一边盘算着出门之前要完成哪个待办事项,结果我什么也没干,只是看完了 RSS 更新。我出门了,又走在神奇的通勤路上,一个声音出现后就没有停下,我也不希望它停下:He's not your soulmate. He's not your soulmate. He's not your soulmate. + +突然想听摇滚,在 Apple Music 上找到了 Green Day,播放了《American Idiot》这张专辑,让吉他声和鼓声在我的颅骨里回响。我听不到世界的声音了,但我还是能听到,有人在几乎没有间隙的摇滚乐里,一遍一遍地告诉我:**他不是你的灵魂伴侣**。 \ No newline at end of file diff --git a/content/article/home-sick.md b/content/article/home-sick.md new file mode 100644 index 00000000..f14e2faf --- /dev/null +++ b/content/article/home-sick.md @@ -0,0 +1,74 @@ ++++ +title = "我的乡愁" +tags = [ "生活", "原生家庭", "人物速写",] +categories = "乱章" +date = 2026-02-21T00:01:24+08:00 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/28849005-924e-4a14-ae4d-2d6cdddcb6d8" +endnotes = [ "这篇文章的标题本来是《我没有故乡》,Slug 是 `forever-homeless`,不过,我想把这个标题留到以后用。",] +url = "/posts/home-sick/" + ++++ + +现在是凌晨 00:55,我还在书房坐着,因为我的门外有一个说话令人讨厌的可悲的小男人跟我爸聊了几个小时,而我一点也不想出去跟他们撞见。 + +我在校外租房,虽然还没到一年,但已经在住处建立起了生活秩序。因此,回家之前我一直拖延,终于要开始收拾行李时,我似乎出现了躯体化的反应,脖子酸痛,而且头昏脑胀。我在自己的床上躺了好一会儿,才平复心情。走之前,我还对家里的绿植念念不忘。虽然是水培植物,但一个月不换水,真的没问题吗? + +如今每次回家,我爸都会想方设法在餐桌上提起我的不念家,这次在我姑姑家,问我表哥,现在回家的时候还会不会有激动的感觉,我表哥说可能有点吧,我爸说,我已经没有了。也不知道是不是圆滑,我表哥说我爸应该感到高兴,因为成功、理性的人就是这样的,不念家——总之我说不出这种话来。我已经接受,这些已经活到四十多岁,还没有受过多少教育的人,本身就不会反思,跟他们讲道理是徒劳无功的,所以,我当然不会冒着起冲突的风险跟我爸解释我为什么不想回家,也没那个必要。 + +毫无预兆,今晚家里来了十多号人,从六点开始我就听到噪音,下楼之后全是不熟悉的面孔和目光,在自己家里走起路来,还真是不自在。我拿完我要的的东西,逃命回到书房,盘算着要找什么理由溜出去。西西弗的储值卡里正好还有一百多块钱,去那边喝杯饮料,坐一坐。不过,我要怎么在众目睽睽之下把电脑或者书带出门呢,真是难办。 + +最终还是留下来吃饭了,支撑我到最后的是豌豆苗、豆芽和娃娃菜,不然我早走了。*素菜请先上桌,谢谢。* + +不想引起注意,于是空手出门了,当然带了耳机,一边听歌一边走出小区,走进商圈,在人群里穿梭的时候,我才觉得自己是自由的。我没有目的地,就一直往前走,想着再过一两个小时,家里的人就应该走了。走到一个路口,突然认出了去母校的路,于是就去我的高中故地重游了。不过,我只是在看路边的招牌,看看那些熟悉的店铺是不是还在。看到一家支撑我度过无数个午后的奶茶店和我很爱吃的芝士焗饭还在,心满意足,只不过之前常和朋友去吃的一家鸡公煲不见了,校门口的一家杂货店变成了装修大气的古茗。而我,竟然没有一点怀旧的伤感。 + +唔,要不是不想破坏吃了很多绿叶菜肚子里很舒服的感觉,我就去买以前爱喝的奶茶了。或许我真是我表哥说的理性的人吧,这种时候,怀旧并不会战胜我对健康的追求。 + +走回家的时候,听了一期播客,盘算着能不能卡好时间,在播客结束的时间刚好到家。不过没成,离小区还有段距离的时候,巴赫的音乐响起,我直接摘下了耳机。就这样听着城市的声音也挺好的。由于我一年回来不了几次,没有录入小区的人脸门禁,要请保安开门。值班的是我不认识的保安,他问我住哪栋,我迟疑了,思考片刻还给出了错误的答案,不过好在我说的那栋楼也是存在的,没被当成坏人。 + +到家了,客厅灯光昏暗,我舒了一口气,可随即听到楼上传来男人的声音,我的心又死了。我散步了一个半小时,这个可悲的小男人还在我家里。事实是,三四个小时后,他还在我的房间外面跟我爸说话。 + +让我来列举一下他一直重复的几句话:「所以我这人生啊,过得还是很好的」「你懂没得?」「谁都比不过我,我谁都不怕」「他不行,他只能排老二」「你懂没得?」「你那个时候小,你不晓得」…… + +> 听到门外某个老男人在讲「我的人生为什么没有走到顶峰」,说自己从小就聪明、家里的男性长辈都喜欢他,说自己本来成为亿万富翁都有可能。后面叽里咕噜说了一大堆我没听清,最后得出的结论是: +> +> 「所以我这一生啊,都败在我的舅妈」 +> +> 我很不道德地在书房里笑出了声,哎哟,这种场面怎么没有早点端上来啊,听老男人追忆人生我能笑好久,早知道能看到这种戏码就不出门溜达了。 +> +> 他还把那句话重复了好几遍,后面还听到几句反复出现的话:「我在部队的时候」「我这辈子就是受到了奸人陷害」「所以我不恨我的舅舅,我就恨我的舅妈」 +> +> Ah, pathetic little old man always cheers me up. + +{{< right "——[我的联邦宇宙账号](https://akk.eltr.ac/objects/07877248-25d5-45f3-9c62-5c7697ce60cc)" >}} + +本来觉得这个小男人说的话很有观赏性,给我带来的愉悦能比过不少中文播客,不过我很快就听到了别的一些东西。 + +> 吃瓜吃到一半听到自己的名字,这小男人倒是很会控制语气语调,在大喊「我这辈子就是被我舅妈害了」这个时候字正腔圆,其他时候低声细气的,没听清说了什么。好像是在我说我这个年纪什么都不懂,叫我干什么就干什么,越来越好笑了。 +> +> 有的男人真的很喜欢把善良当作弱小呢。 + +{{< right "——[我的联邦宇宙账号](https://akk.eltr.ac/objects/705c4c8d-73fa-452a-939c-2aa076d20c99)" >}} + +随后这个可悲的小男人还说了不少有趣的话,比如他谈起他的佣人(我想,如果世道允许,他一定会使用「奴隶」这个词),说他过得跟古时候的老爷一样,叫他们打饭就去打饭。他的说话方式真值得品味,因为他在使用「老爷」这个词之前,加了一句「说得不好听点」,但是真说出口的时候,还觉得很得意。 + +他还谈起我的爷爷。 + +> 很有意思,他们开始讨论今天晚上我爷爷在餐桌上说的话。我爸在想办法给我爷爷找补,说他确实不会说话,而这个男人把这个当作某种机会,说「这是因为我舅舅(也就是我爷爷)跟我关系好,不介意这些」。 +> +> 我爷爷说那句话的时候我在场,大概是有些阴阳怪气地嘲讽了他,说他对自己的前妻不好。我能感到我的爷爷不太喜欢他,只不过用开玩笑的方式给他留了些体面。这个男人当时一直在委婉地表达我爷爷「胳膊肘往外拐」「帮外人说话」,而其他人还在讲所谓的兄弟情义,说「我们兄弟娶谁就认谁」。这个男人给我的印象就是自以为圆滑,立很多规矩,脑子里想了很多没用的东西,一直在想怎么让自己看起来[屌更大](/essays/不脱裤子如何证明自己屌更大/)一点(刚才跟我爸讲话的时候,一直在说「你晓不晓得?」,因为他似乎把我爸当成比他小、需要他教育的弟弟),就是不肯坦诚相待。 +> +> 对我爷爷感受到了前所未有的敬佩,就是在这种时刻。 + +{{< right "——[我的联邦宇宙账号](https://akk.eltr.ac/objects/7a7bb341-0a45-48c0-af49-d6603aee19cc)" >}} + +想起我的爷爷,我记得小时候和他睡一张床,他很喜欢我,孩童时期的我也经常围着他转。长大过后就渐渐不亲近了,他也对我的某些行为有些意见,不过他总是在大部分时候保持沉默,很少干涉我。 + +就是从这个时候开始,我对门外那个可悲的小男人的态度,从嘲弄变成了厌恶。 + +他的妻子给他打了两次电话,叫他回家,通话时我爸在旁边,她也就没把话说重让自己丈夫在兄弟面前难堪。如果我的想象力再发散一点,我可能不会把他妻子的好态度解读为圆滑,而是恐惧,那个男人的说话方式完全就像是个家暴男。这个男人,几个小时前在餐桌上谈起自己的前妻,说她割腕流了好多血,把那段经历当作故事来讲,我不觉得他对这任妻子会有多好。 + +我想我讨厌回家的根本原因,是不想和这类人扯上关系。在这座发展落后、官员贪污的小城市里,人们的心胸狭隘、目光短浅,是可以被理解的。他们话里话外说的都是他们小圈子里的人,谈的是过去乡镇上的事,他们能看到的世界,也就仅限于此了(虽然,出于某种莫名其妙的自信,他们觉得自己很擅长讲解国家政治话题)。我不批评他,但我厌恶他。 + +这就是我的乡愁——回到家乡时,不可避免感到的忧愁。 \ No newline at end of file diff --git a/content/article/in-the-mirror-i-get-weak.md b/content/article/in-the-mirror-i-get-weak.md new file mode 100644 index 00000000..6a87e78e --- /dev/null +++ b/content/article/in-the-mirror-i-get-weak.md @@ -0,0 +1,45 @@ ++++ +title = "In the Mirror I Get Weak" +categories = "乱章" +tags = [ "R", "爱",] +date = 2025-03-22T01:12:15 +draft = false +toc = true +aliases = [ "/posts/in-the-mirror-i-get-weak",] +url = "/posts/in-the-mirror-i-get-weak/" + ++++ + +记不清是从什么时候开始,每隔一段时间都会给自己占感情运,然后默默忍受桌上摊开的卡牌凝视自己的目光,最后把它们收起来,洗匀,不做任何记录。 + + + +上一次爱上直男的时候,我抽到一张魔术师和一张女祭司,另外一张牌是什么我已经忘记了。事后想到,魔术师大概是他的自我,在我眼里明显越界的行为,在他眼里只是正常的互动;又或许像我朋友说的,我没有隐瞒自己的性取向,他兴许只是享受向男人也散发性魅力的爽感,或者只是享受被人喜欢的感觉。 + +至于女祭司,大概也能对应到我自己,像是一本合上的书,纵使心底波涛汹涌,表面上也一定面不改色。除了那封四千字的情书,我没跟他谈起过我的感受。就连被他骂过之后的那天晚上,我的朋友也只能面对要她陪着却一言不发的我。 + +爱上直男或许不是最操蛋的,另一种让我至今无法释怀的情感经历,是一位原本自称双性恋和「不确定自己取向」的男生,在拒绝我着急的表白之后,突然改口说自己是直男。我不觉得我能再遇到一位与我这样契合的灵魂,我大概永远也想不明白,那天我向他抱怨找不到男人之后,他对我说的「兴许是有人暗恋你但不敢说」到底是什么意思。 + +最近,如卡牌预言那般地,我又陷入了一种怪异、不可言状,但难以称得上愉快的感情境地里。 + +作为朋友与他交往,大概已有一年,不知从何时起,我看出他在我面前的扭捏作态,以及背后所蕴含的意义。只是我不知道作何反应,他也不做出直接的行动,我不想落得曾经的尴尬境地,一直不知如何是好。这种暧昧不清,在这个春天愈演愈烈,不自觉的身体接触、眼神间的躲闪和言辞中的拉扯,都是赤裸裸的信号,但就在刚才,当我在没有路灯的道旁树下听他的高谈阔论时,一种由矛盾滋生的忧伤又向我袭来。 + +中学时代,我明知会失败,却还是硬着头皮去表了白,因为我实在等了太久,我想要一个结果。我记不清当时那个小胖子心里在想些什么了,但我知道,我就是奔着 1% 的希望和 99% 的破碎而去的。 + +前些日子,那种赴死般的行动欲望,变成了切实的希望,我清楚地记得,我当时这样告诉自己:他一定知道我想说什么,他一定会同意的,他为什么不会呢?而我要面对的,却是血一般酸甜的痛楚和残忍,无论是谩骂还是无休止的愧疚,说我牛逼也好,自顾自地道歉也罢,我都无法面对午夜月亮升起时,镜子里的自己。 + +现如今,又是另一番景象——我知道我一定会成功的,这还不是幼稚的幻想,种种证据都表明,我离那种我从未拥有过的东西,只有一步之遥,可我却不敢伸手,因为我又不知道,我即将面对的是什么了。 + +我不会否认身材健壮的男性对我的吸引力,我也不会否认我没对他的身体起过哪怕一些不干净的想法,我也当然会承认,当他把头或身体靠在我的臂膀上时,我会觉得他有些可爱。可和他的交流越是深入,我就越是发现,自己陷入了一个十分俗套的困境当中。 + +除了对苹果产品的赞誉和我学识中与他的专业屈指可数的交集,我们几乎没什么可聊。我们的音乐品味相差甚远,生活习惯上,除了夜里能一起约着跑步,也很难谈得上相似。我想,如果我跟他说话时多几分锋芒和直言不讳,我大概会和这位优秀共青团员起一些意见上的冲突。他把自己看了几年的游戏直播拿给我看,可我看不到他眼里的快乐,只看到令人眼花缭乱的攻击特效和短视频配乐。尽管傲慢无礼,但我看到的是优美的形体和无趣的灵魂。 + +我理解不了上天的安排,我与他的生日只相差三日;在没有提前相约的情况下,我们都选了同一门课,每周都在固定的时间和地点相见;他与人交谈时的那般小心翼翼,又让我想起以前的自己。不过,我似乎早已不相信缘分了,那位和我有着相同音乐、小说和电影品味,还研读《塔罗葵花宝典》的,不也早就在愧疚和恐惧中逃走了? + +当我这个感情白痴从幻想中抽离出来之后,又难免思考:我要找的是能与我攀谈到天明的灵魂,还是听不懂我说话、在我腿上安然睡去的小狗呢?话说回来,我似乎从来没去找过,我只是理所当然地等待。 + +水逆时感到脑子转不动,顾不了计划,只想切切实实地生活着,于是一边希望拥有一间自己的房间,一边重新排列起桌上的物件。我把一面镜子摆在了屏幕旁边,我有时用它整理发型,有时隔着镜片上的污垢看着自己,感受自己眼睛里的弱小。 + +{{< right "记于 3 月 22 日凌晨" >}} + +{{< right "*标题取自 Lady Gaga 歌词《Don't Call Tonight》*" >}} \ No newline at end of file diff --git a/content/article/jack-in-fitness.md b/content/article/jack-in-fitness.md new file mode 100644 index 00000000..0512cc06 --- /dev/null +++ b/content/article/jack-in-fitness.md @@ -0,0 +1,109 @@ ++++ +title = "Jack,你也健身吗?" +subtitle = "俚语常客勇闯健身房" +slug = "jack-in-fitness" +tags = [ "词源学", "语言",] +categories = "猫头鹰化石" +date = 2026-02-27T00:34:35 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/e6c8af69-7989-482a-98a3-05d9376b269e" +url = "/essays/jack-in-fitness/" + ++++ + +某种程度,英语里的 Jack 是很传奇的人名,它无处不在。 + +Jack 是不会说英语的中国人也耳熟能详的英文人名。著名俚语词典 [Urban Dictionary](https://www.urbandictionary.com/) 上有 864 页与 Jack 有关的词典(虽然这个网站也以胡说八道的词条居多著称)。令人费解的是,很多工具也以 Jack 命名。如果在公路旁边看到有人举着牌子,牌子上写着「Need a Jack!」,这并不是在说「需要一个男人」,而是说「需要一个千斤顶」;建筑工人用来在地上打孔的冲击锤,叫作 Jackhammer;一种用来脱靴子的工具叫作 Boot jack(反过来,Jackboot 是一种军靴)。 + +更怪的是,Jack 还和「偷窃」有关系:Hijack(劫持)、Carjack(偷车)和 Skyjack(劫机),Jack 本身作为动词就是「偷」的意思。想必不用我说,一些读者也知道 Jack off 是「手淫」的意思,与 Jerk off 同义。扑克牌里面的 J,也叫 Jack。除此之外,还有 Jack-o-Lantern(南瓜灯)、Jackpot(头等奖)、Lumberjack(伐木工)、Jackrabbit(野兔;兔属;甚至还有一个 Java 内容管理库叫作 Apache Jackrabbit)、Jackass(公驴,也用来骂人)、Jackdaw(寒鸦)、Blackjack(二十一点,一种纸牌游戏)、Applejack(一种苹果酒)。 + +Jack 的身影遍布这门语言的各个角落,不过今天的文章只会关注其中的一小部分,即健身房里的 Jack。看到 Jack 以各种工具名称出现之后,把它当作动词的用法突然就形象起来了,要么是把什么东西撬起来,要么是把什么东西冲破。带着这个印象,我们来看看以 Jack 命名的各种健身体式。 + +## 跳跃吧,杰克! + +开合跳的英文单词是 Jumping Jack,在英国叫作 Star Jump(星星跳,还挺形象的)。美国军队管开合跳叫 Side-straddle Hop,直译过来是「侧跨跳」,显然,这个名字更准确,中文里的「开合跳」也从另一个角度准确地描述了这个锻炼动作。如果你从没做过开合跳,可以参考下图。[^1] + +![](https://r2.eltr.ac/geedeapro/essays/jack-in-fitness/Jumpingjacks_wbs.gif "正在做开合跳的小人。") + +所以,明明有更准确的用词,为什么要用 Jack 这个毫不相关的人名呢?英语本身就是[语言界的最大缝合怪](/essays/为什么说英语是语言界的最大缝合怪/),再加上[英语的表意效率低下](/essays/语言表意效率差异导致的思维差异/),非常依赖言外之意和黑话,有了 Jumping Jack 这类简短的表达,没人会折磨自己的舌头去说 Side-straddle Hop 这类词的。 + +不过,为什么一定是 Jack?隔壁 John、Dick 和 Tony 不是也广为人知吗? + +有一种玩具叫作掷距骨[^2](Knucklebones),是一种古老的游戏,在许多文明里都能找到类似的变体,简单来说,是一种把小物件(例如骨头、石子)丢起来,然后抓住的反应力游戏。在比较现代的版本里,这种玩具用金属制成,长得很像三维的直角坐标轴。不过,如果不仔细看的话,这些小东西就很像把手脚都张开的小人,就有点像做开合跳时,手脚张开的样子。 + +![](https://r2.eltr.ac/geedeapro/essays/jack-in-fitness/500px-The_Childrens_Museum_of_Indianapolis_-_Jacks.jpg) + +这种用来抛的金属小玩具,名字叫作「Jack」。 + +所以,有没有可能是有人根据这个动作联想到了用来抛掷的这种 Jack,所以才想出了 Jumping Jack 这个名字呢? + +很遗憾,不是。根据[维基百科](https://en.wikipedia.org/wiki/Jumping_jack),开合跳据说是西点军校的一位军官发明的,他的名字叫作 John Joseph Pershing,他还有一个昵称,叫作「Black Jack」。他作为西点军校指导员的时候,由于非常严格且死板,学员们很不喜欢他。由于他在美国第 10 骑兵团服役过,而这个兵团一开始是作为隔离的黑人单位组建的[^3],所以学员们给他起外号叫作「Nigger Jack」,后来,这个称呼被弱化成了「Black Jack」[^4],因为 Nigger 是对黑人的歧视性用语。 + +所以,因为发明这个运动的军官外号里有 Jack 一词,开合跳也就被称作 Jumping Jack 了? + +很遗憾,不是。至少,根据维基百科的说法,Jumping Jack 取自一种玩具的名字(是的,还是玩具)。这种玩具的名字就叫作 [Jumping Jack](https://en.wikipedia.org/wiki/Jumping_jack_(toy)),在前几个世纪流行于英国、法国和德国等欧洲国家,是一种用木头制成的、有关节的小人。只要拉动小人身体下面的一根线,它的四肢就会动起来,就像是在做开合跳。 + +Jumping Jack 还有多种变体:Power Jack 要在跳出去的时候做深蹲动作;Squat Jack 则是要在开和合的过程中一直保持半蹲姿态;Half Jack 是幅度更小的开合跳;[^5]Alternating Jack 或者 Scissor Jack 是在保持开合跳手臂动作不变的情况下,左右脚前后交替跳跃。总之,在健身领域,Jack 差不多已经是开合跳的代名词了,各种类型的开合跳都有 Jack 的名字。 + +## 亮剑吧,杰克! + +Jackknife 是一种核心训练动作,躺在地上,把手臂和腿伸直,往上举,向身体中间靠拢,直到四肢并拢。如果核心力量较弱,身体条件不允许,一些 Jackknife 的变体并不要求手和脚一定要靠拢,只需要核心发力,将四肢支撑住就好。 + +![](https://r2.eltr.ac/geedeapro/essays/jack-in-fitness/Scyzoryki.gif "图源:[Jackknife (exercise) - Wikipedia](https://en.wikipedia.org/wiki/Jackknife_(exercise))") + +不同于 Jumping Jack,Jackknife 的词源很明确,这个词的本意是「折叠刀」。如果把人的核心想象成转轴,上半身想象成刀刃,下半身想象成刀柄,把手脚在空中并拢的动作,就像是把折叠刀折起来的动作。 + +所以,真正的问题是:折叠刀为什么叫 Jackknife? + +*没人知道。* + +我翻遍了维基百科、Wiktionary 和 Etymonline,都没有给出确切的词源描述。不过,我倒是误打误撞地在一个讨论刀的论坛[^7]上找到了[相关的讨论](https://www.bladeforums.com/threads/technically-what-is-a-jack.1092445/)。2013 年,有个叫作 Jack Black[^6] 的网友引用了某个如今打开已经是 404 的网页: + +> Jackleg is a U.S. southern slang adjective meaning unskilled or unqualified. The term almost certainly comes from jackleg knife (jackknife) and was probably originally used as jackleg carpenter, a carpenter with only the most basic set of tools. +> +> Jackleg 是美国南方俚语,意思是「未受训练的」或「不合格的」。这个词几乎可以肯定源自 Jackleg Knife(Jackknife),有可能最初被用在「只有一把折叠刀的木匠」(jackleg carpenter)这个词上,指代只有最基础的工具的木匠。 + +所以,Jackknife 最初应该是 Jackleg。[Etymonline](https://www.etymonline.com/word/jack-knife) 也在 Jack-knife 相关页面中提到了 Jackleg 这个词,里面提到苏格兰方言里有 *jockteleg* 这个词,也是一种折叠刀,但词源不明。 + +折叠刀不仅衍生出了一种锻炼的名字,还衍生出了别的含义。作为动词,Jackknife 表示把东西从中间折叠起来(~~我真服了,你们就不能老老实实用 Fold 这个单词吗?~~)。Jackknife 还是一种跳水动作,和核心训练动作很像,也要把手臂靠近腿部,将身体折叠起来。 + +Jackknife 还是一种口语表达:如果一辆卡车发生意外,车头朝向一个方向,而车厢朝向另一个方向,两者形成的角度过小,就像是折叠起来了,这种事故就被称作 Jackknife,这个意思也可以做动词。 + +> Before I knew what was happening, I'd jack-knifed the truck. +> +> 我还没意识到发生了什么,我已经把卡车撞成折叠刀了。 + +不过,我还是不知道折叠刀和 Jack 到底有什么关系! + +## 波巴和奇奇,杰克向你问好! + +有一类难以解释的语言现象叫作 [Bouba/Kiki 效应](https://en.wikipedia.org/wiki/Bouba/kiki_effect)。观察下面两个图形,凭借直觉选择,你觉得它们哪个叫 Bouba,哪个叫 Kiki? + +![](https://r2.eltr.ac/geedeapro/essays/jack-in-fitness/Booba-Kiki.svg.png "~~我觉得他们都叫 Claude~~") + +全世界的人类都有着相同的倾向,大部分人都会觉得那个圆圆的图形叫 Bouba,而尖尖的图形是 Kiki,人们会把声音和图形联系起来。神奇的是,最近[新发表的一篇研究](https://www.scientificamerican.com/article/baby-chicks-pass-the-bouba-kiki-test-challenging-a-theory-of-language/)发现,雏鸡也存在 Bouba/Kiki 效应,小鸡崽在听到 Bouba 的声音是会自发选择圆润的图形,听到 Kiki 时会选择带尖角的图形。 + +我在猜测,人们之所以把没有实义的人名 Jack 用在这么多地方,也可能是因为 Bouba/Kiki 效应。至少对我而言,Jack 这个词的发音很容易联想到插、打、锤、砸等动作,比如把长条状的工具插进汽车车窗里,借此把锁撬开偷车的动作(联系到「偷窃」的意思),或者把铁条插进脚和靴子的缝隙里,借此拉开距离,方便把脚从靴子里拿出来(联系到 Boot jack 这个词)。 + +我在做卷腹的时候,也能感觉到自己不是在轻轻地卷,而是在「Crunch it!」,Crunch 这个单词的发音也带有一些微妙的力量感。这种感觉很难描述清楚,就像很难用语言和逻辑解释为什么圆圆的图形叫 Bouba 而不应该叫 Kiki 一样。 + +不过,Jackrabbit、Jackass 和 Jackdaw 的用法,应该是把 Jack 这十分常见的男子名当作「雄性」的代名词了,用来表示公的动物,与上述语言现象无关。 + +--- + +就到这里吧,在电脑面前翻各种网页,坐了一两个小时,还吃了夜宵,现在要站起来做几个开合跳才行。 + +[^1]: 真的很难忍住不在这里放一张「Happy~ Happy~ Happy~」的 GIF 图。 + +[^2]: 我印象很深刻,因为《咩咩启示录》这部我很喜欢的肉鸽游戏里就有「掷距骨」小游戏,虽然和现实中的掷距骨有很大不同。现实中的掷距骨参见:[Knucklebones - Wikipedia](https://en.wikipedia.org/wiki/Knucklebones) + +[^3]: 参见:[10th Cavalry Regiment (United States) - Wikipedia](https://en.wikipedia.org/wiki/10th_Cavalry_Regiment_(United_States)) + +[^4]: 参见:[John J. Pershing](https://en.wikipedia.org/wiki/John_J._Pershing#West_Point_instructor) + +[^5]: 参见:[Jumping Jacks - Wikipedia](https://en.wikipedia.org/wiki/Jumping_jack) + +[^6]: *这名字…… 你该不会是黑杰克军官转世吧?* + +[^7]: 叫作 [Blade Forums](https://www.bladeforums.com/),很神奇,互联网上居然存在这么小众的论坛。 \ No newline at end of file diff --git a/content/article/lets-make-friday-cryday.md b/content/article/lets-make-friday-cryday.md new file mode 100644 index 00000000..57f4a766 --- /dev/null +++ b/content/article/lets-make-friday-cryday.md @@ -0,0 +1,33 @@ ++++ +title = "Let's Make Friday Cry-Day" +date = 2025-10-31T23:16:00 +draft = false +toc = false +tags = [ "M", "爱", "生活",] +categories = "乱章" +aliases = [ "/posts/lets-make-friday-cryday",] +url = "/posts/lets-make-friday-cryday/" + ++++ + +十月的最后一天,我的好运还是没有来。早上九点,[KeyDay](https://apps.apple.com/us/app/keydays-minimal-day-counter/id6450872567) 给我发来消息:「谢天谢地,又到周五啦!」。中午一点,我隔着窗帘给室友竖中指。下午三点,我一边读加缪的文字一边忍受老师声带发出的响动,在心里嘲弄这个教软件的老师居然如此自以为是地讲解她并不理解的经济学概念。下午五点半,我蜷缩在被窝里自说自话,没有办法忍住哭泣。 + +哭过之后我仍然感觉疯疯的,抱着玩偶和它分享着闲言碎语,仿佛我们心有灵犀。我的嘴里一直蹦出「Yeah, totally.」「That's so true.」「He thinks too much of himself.」这样的话,想象有另一个灵魂刚才分享了我十分认同的见解。被理解的感觉让我好起来了,哪怕只是我自己理解自己。 + +回家路上看到班上的一对情侣和我同路,路过电影院之后便消失不见。几周前在同一个路口,我突然想要看电影,只可惜世界承受不了我的随性,软件上尽是些无聊的片子。这次我听从直觉,买了晚上八点的票,去看我在猫眼上发现的第一部电影。我取完快递,收拾好房间,关掉灯,在床上计算好时间——我要八点去看电影,那我就要七点半出门,那我应该在七点吃完饭,这意味着我最迟六点半就要开始做饭,现在是五点半,我还可以再哭一个小时——INFP 在焦虑的时候,是不是都会变成 ESTJ 呢? + +六点半到了,我打开冰箱,把豆腐和猪肉拿出来又放回去,突然丧失了所有动力。我拿出了昨晚做好的燕麦酸奶杯,准备在外卖送达之前先垫垫肚子。酸奶是无糖的,燕麦是老式的,蓝莓是速冻的,好在口感弥补了一切,让我没在吃到鸡公煲之前再次情绪崩溃。 + +七点半,我出门了。我现在正在努力回想自己出门之前有没有给室友竖中指,但我想没有,我根本没心思理他。不过,我记得我把门关得很响,还挺小孩子气的。 + +七点五十,我路过之前工作的教培机构,和电影院在同一个商场,里面很热闹。我进了影院,拿到了爆米花,吃下了这个月的第二份精制糖类——奇怪,明明没有很想吃,但电影似乎就应该配上爆米花,我的大脑也被消费主义入侵了吧!我在等候厅找了个没人的位置坐下,看到了 [M](/tags/m/) 回复我的消息——哦对,我五点的时候跟他发过消息来着,我是为了那件事哭吗?我没回复,毕竟那只是毫无延伸可能性的轻浮的分享罢了。 + +临近八点,我坐下了,旁边是一对情侣,身边也有男男女女走来走去。我意识到自己在周五晚上犯了一个严重的错误——没有买到一张旁边没人的电影票。旁边的情侣往左边挪了一个位置,他们人真好,祝他们永远在一起。不过很快他们旁边也来了一对,又坐回来了。 + +电影开始了,我一边计算着自己要隔多长时间吃一次爆米花,才能在这一百零四分钟里均衡地吃完这一桶而不至于在后半场无爆米花可吃,一边在前半场默默嫌弃这部电影情节的老套——千金回家跟后妈争遗产,后妈和另一个男人搞上了,女儿不喜欢后妈,亲妈得了精神病,女儿和家里的司机相爱了。人物形象别太好猜。与此同时,我还忍受着人群对一些平平无奇的动静发出大惊小怪的声响。我的一个人格鄙视他们竟然连这样的场面都会被吓到,另一个人格又批评自己成为了自己讨厌的那类人,第三个人格哀叹:行,你俩吵吧,我不陪了。说是解离症大概言过其实了,电影我看得很认真,后半部分的情节一转再转很快把我拉回了现实,意外地还不错。 + +看完电影我心情很好,就想去楼下打声招呼。以前的上司见到我很惊喜(说实话,把她称作上司感觉怪怪的,毕竟我作为一个兼职的学生,她其实更像老师),还有很多认识我的学生、以前的同事也来跟我打招呼。她说明天晚上有一个万圣节活动,邀请我参加,还反复跟我提起他们现在有多少个班,有多需要助教老师。我说我会考虑的,实际上,我确实有点想回去了。说来好笑,这个月初我还回了 [Backrooms 社区](https://backrooms-wiki-cn.wikidot.com/),许多人见到失踪人口突然出现也很惊讶。两次都有人问我还认不认识他是谁,很像小时候过年回老家见到的亲戚,不过见到他们要开心很多。可能我在所有人面前都是一个有些孤僻的小孩子吧。我明天晚上打算去看看了,十一月大概会好起来的。 + +接近十点,我回到家,发现室友不在,于是这一天变得更值得高兴了。耳机里还放着 Chris James 的歌,我在客厅里放肆地跳舞,从厨房一路跳到书房,生活大概不会比此时此刻更美好了。 + +或许周五就应该多哭一哭。 \ No newline at end of file diff --git "a/content/article/libra-js-\345\274\200\345\217\221\346\227\245\345\277\227.md" "b/content/article/libra-js-\345\274\200\345\217\221\346\227\245\345\277\227.md" new file mode 100644 index 00000000..2c39d58b --- /dev/null +++ "b/content/article/libra-js-\345\274\200\345\217\221\346\227\245\345\277\227.md" @@ -0,0 +1,307 @@ ++++ +title = "Libra.js 开发日志" +tags = [ "Web",] +date = 2025-09-23T22:22:00 +draft = false +toc = true +aliases = [ "/posts/libra-js-开发日志",] +categories = "代码炼金术" +url = "/essays/libra-js-开发日志/" + ++++ + +博客从去年十二月开始就一直在用 [Fancybox](https://fancyapps.com/fancybox/) 作为博客的图片灯箱插件,之前还在用 Typecho 搭建博客的时候就在用这个库。所谓灯箱,其实就是点击图片之后将图片放大并居中显示,就像现实世界中的广告灯牌一样。不过我其实一直很想要把 Fancybox 换掉,因为它太臃肿了,包含了很多我不需要的功能(比如 1:1 放大、镜像翻转、前后切换等等),体积接近 100 KB;不仅如此,Fancybox 实际上是一个商业库,并不是免费开源的。出于这些原因,我决定自己从零开始做一个灯箱插件。 + +## 原则和技术选型 + +我希望项目能做到足够「轻」,一方面是打包后要足够小,另一方面是运行时不需要消耗太多资源。权衡之后,还有一个点就是必要的配置项足够少,最好能做到零配置起步。我决定用原生 JavaScript 编写,毕竟需求没有很复杂。由于需求本身足够简单,除了开发时会用到的一些依赖,打包后的库不应该包含或依赖于任何第三方库,这也能避免不必要的维护工作。此外,目前我能找到的灯箱插件大多都包含了多图排版功能或者额外的图片缩放操作,我希望这个库能够专注于需求本身,只要把图片放大就好了。 + +轻量、原生、专一,~~非常适合用作软件的宣传噱头的~~三个基调就这么定好了! + +## 模块设计 + +需求只有一个,点击图片后播放动画并放大以供查看,再明确不过了,完全可以跳过需求分析的步骤,直接开始设计。 + +由于点击图片之后需要播放动画——原图片从原位置、原大小逐渐过渡到屏幕正中间、放大显示的状态——而图片 `` 本身是一个行内元素或块元素,要让其「飞离」容器会有些困难,所以我的想法是构造一个**影子元素**(Shadow),通过绝对定位覆盖在图片上方,由于影子元素是绝对定位的,要放大和位移就很方便了。 + +除了放在正中央的图片,要组成灯箱,往往还需要**遮罩**(Overlay)。遮罩平时隐藏,打开图片灯箱之后显示在其他元素和影子图片之间,这样在视觉上,打开灯箱之后用户就只能看到放大的图片,可以起到突出强调的作用。 + +不需要其他花里胡哨的功能的话,**灯箱**(LightBox)就可以理解为「影子 + 遮罩」。影子的生命周期(创建和销毁)由自己管理,遮罩也用一个单独的模块管理,灯箱负责调用这两个模块,控制灯箱的开启和关闭,也负责把对应的图片信息传递给它们。 + +在之后的开发过程中,我发现影子模块的代码有些复杂,因为播放动画的逻辑也写在里面了,于是把动画相关的代码分离了出来,单独作为**动画**(Animation)模块。 + +于是四个模块的分工就很明确了: + +- Shadow:管理影子元素的生命周期;获取图片的位置和尺寸信息。 +- Overlay:创建、打开和关闭遮罩。 +- LightBox:初始化监听器;调用 Shadow 和 Overlay 两个模块来打开灯箱。[^1] +- Animation:计算动画的起始和结束状态,并应用相关属性。 + +## 定位图片时踩的坑 + +一开始我在一个小时内就实现了需求,在后续测试中却发现了明显的问题。我在测试页面里能够正常开关灯箱,图片也能被放到正确的位置,但在我的博客上应用插件时却发现动画的起始位置完全不对,图片不是从原始位置放大的,而是从页面最下方瞬间飞上来的,而且飞上来之后的位置也有偏移。 + +### 初始状态的获取逻辑 + +发现原因在于定位时使用的属性不对,我是这样获取图片的初始位置的: + +```js +// shadow 是根据图片创建的影子图片 +// image 是原图 +shadow.style.top = image.offsetTop; +shadow.style.left = image.offsetLeft; +``` + +一般情况下,`offsetTop` 和 `offsetLeft` 会返回元素相对于 `` 的位置,`offsetTop` 是元素顶部距离 `` 顶部的距离,`offsetLeft` 同理;可以理解为以整个页面的左上角为原点建立了一个坐标轴,只不过 Y 轴的正方向是向下的。 + +![](https://r2.eltr.ac/uPic/2025/09/lovecoordsystem.png "图片来自 [LÖVE 引擎的官方文档](https://www.love2d.org/wiki/love.graphics),由于这个图形系统和这里的例子很相似就拿过来做演示了;其中 x 可以理解为 left,而 y 是 top。") +{.dark:invert} + +然而,这并不是 ` offset ` 系列属性的用途,实际上,它们返回的是相对于最近的**定位祖先元素**(positioned ancestor element)的距离。[^2]其中,祖先元素是 DOM 树上比自己更高层且自身属于其枝干的节点,也就是父元素的父元素…… 定位(positioned)指的是 CSS ` position ` 属性不为 ` static `,受 ` top ` ` left ` ` bottom ` ` right ` 等属性影响。如果没有这样的祖先元素,就会选择 `` 作为参考对象。 + +问题就出在这里,如果图片位于一个定位元素(positioned element)中,那定位就不是相对于 `` 的;然而,影子元素的定位方式是 `position: absolute`,它在被创建时是插入到 `` 的末尾的,也就是说,影子元素是相对于 `` 进行定位的。由于计算得出的位置和实际应用的位置,两者的参考系不同,最终定位的结果自然是错位的。知道原因之后,解决方案就很简单了,只要获取原图相对于 `` 的位置信息就好。 + +在 MDN 上查阅之后,我找到了 `getBoundingClientRect()` 这个方法,用于获取一个矩形对象,这个矩形的位置信息是相对于**视口**的,也就是浏览器窗口中显示页面的区域。矩形的 `top` 属性就是这个元素相对视口顶部的距离,如果加上页面滚动的距离,就能得到这个元素相对于 `` 顶部的距离;`left` 属性也是同理。 + +```js +const rect = image.getBoundingClientRect(); +this.originalPosition = { + top: rect.top + window.scrollY, + left: rect.left + window.scrollX, + width: rect.width, // 宽高的获取没什么要绕弯子的 + height: rect.height // 这里就不追述了 +}; +``` + +这样获取的值就可以直接用来定位影子元素了,只要宽高也是一样的,就能遮盖住原图片。 + +![](https://r2.eltr.ac/picgo2025/IMG_0395.jpg "为了方便你理解,我在画了一个示意图。") +{.dark:invert} + +### 结束状态的计算方式 + +灯箱打开动画的结束状态就是灯箱放大后的位置和大小,这部分的需求是这样的: + +1. 图片应该尽量展开到原始尺寸,但不应该放大超过原始尺寸导致模糊; +2. 放大后图片的长宽不应该超过视口大小,也就是不应该出现放大后图片显示不全的情况; +3. 放大后图片的位置应该居中于视口正中央; +4. 出于美观考虑,应该给放大后的图片设置一个边距,在四周留出一定的空白。 + +图片的大小应该是窗口大小和图片自然情况下的大小共同决定的,也就是以下四个变量。 + +```js +const nw = element.naturalWidth; // 图片自然宽度 +const nh = element.naturalHeight; // 图片自然高度 +const ww = window.innerWidth; // 窗口内部宽度(视口宽度) +const wh = window.innerHeight; // 窗口内部高度(视口高度) +``` + +这里的逻辑其实很简单,如果优先计算宽度的话,选取图片宽度和视口宽度当中**最小**的一个就能保证图片不超过视口。不过要注意的是,并不能直接用相同的方法去获取结束状态的宽度,因为这可能会导致图片的比例变化,所以要先算出原始图片的长宽比例,然后通过比例计算出高度。 + +```js +const ratio = nw / nh; +finals.width = (nw > ww) ? ww : nw; // or `Math.min(nw, ww)` +finals.height = (nw > ww) ? ww / ratio : nh; +``` + +不过,通过比例计算出来的高度完全有可能超出视口高度,所以要再进行一次判断。 + +```js +if (finals.height > wh) { + finals.height = wh; + finals.width = wh * ratio; +} +``` + +这样就基本上没问题了。尺寸确定之后,才能计算最终的位置。 + +已知矩形的长宽,也知道视口的长宽,要算出让矩形居中的坐标位置就很容易了,只要把视口的长度减去矩形的长度再除以二就好,宽度也同理。这个操作应该还挺经典的,我记得我在学 Java Swing[^3] 的时候为了把窗口居中就经常做这样的计算。由于影子图片的定位是基于 `` 的,所以还要像刚才那样加上滚动的距离。 + +```js +finals.top = (wh - finals.height) / 2 + window.scrollY; +finals.left = (ww - finals.width) / 2 + window.scrollX; +``` + +这样就得到了放大尺寸合适、位置居中的图片状态。 + +还要添加边距,我本来以为要修改宽高的计算公式,后来发现,其实只要在**逻辑上**缩小视口大小、再偏移坐标位置就好了,简单来说就是这样: + +```js +// margin 是边距 +const ww = window.innerWidth - 2*margin; +const wh = window.innerHeight - 2*margin; + +finals.top = (wh - finals.height) / 2 + window.scrollY + margin; +finals.left = (ww - finals.width) / 2 + window.scrollX + margin; + +// 其他全都保持不变 +``` + +## 绘制动画时踩的坑 + +前面已经获取了影子元素的初始状态和结束状态,也就确定了动画的开始帧和结束帧,现在要做的就是把影子元素平滑地移动并放大到结束状态,补全中间的关键帧。 + +我能想到的最直接的办法就是通过 `setInterval()` 每隔一段时间更新一次影子元素的 `top` `left` `width` 和 `height` 属性,只要设置适当的步数(帧数)和持续时间,应该就能达到比较平滑的效果。然而,无论我怎么调整参数,动画效果都非常不如意。最主要的问题是太慢了,没有人愿意盯着一个图片动那么久。 + +我一开始仍然觉得是参数设置的问题,于是把代码发给 ChatGPT 修改,好在 ChatGPT 没有盲目听从我的指令,而是建议我使用 `requestAnimationFrame()` 这个方法,这个方法会请求浏览器在下一次**重绘**(repaint)时执行传入的用户回调函数。这有点像 LÖVE 引擎里的 `love.draw()` 方法,但又不完全一样,因为 `requestAnimationFrame()` 只会执行一次,所以要在传入的回调函数里再次执行 `requestAnimationFrame()`,直到动画完成之后再停下来,也就是要用到递归。 + +```js +animate(startingState, finalState) { + // 初始化步数,即从开始到结束一共绘制几帧 + const steps = 20; + let step = 0; + + // 每一帧会执行的回调函数 + const frame = () => { + // 通过当前步数和总步数计算进度 + const progress = step / steps; + + // 根据进度计算出当前的位置和尺寸 + const currentTop = startingState.top + (finalState.top - startingState.top) * progress; + const currentLeft = startingState.left + (finalState.left - startingState.left) * progress; + const currentWidth = startingState.width + (finalState.width - startingState.width) * progress; + const currentHeight = startingState.height + (finalState.height - startingState.height) * progress; + + // 更新影子元素的样式 + this.element.style.top = `${currentTop}px`; + this.element.style.left = `${currentLeft}px`; + this.element.style.width = `${currentWidth}px`; + this.element.style.height = `${currentHeight}px`; + + step++; // 自增步数 + + // 步数未到,则继续绘制下一帧 + if (step < steps) { + requestAnimationFrame(frame); + } + }; + + // 开始第一帧 + requestAnimationFrame(frame); + } +``` + +[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame) 是这样描述这个方法的: + +> The frequency of calls to the callback function will generally match the display refresh rate. The most common refresh rate is 60hz, (60 cycles/frames per second), though 75hz, 120hz, and 144hz are also widely used. +> +> 调用回调函数的频率一般会和显示器的刷新率匹配。最常见的刷新率是 60 赫兹(每秒 60 个循环/帧),不过 75 赫兹、120 赫兹和 144 赫兹也被广泛使用。 + +我不确定描述是否属实,因为测试时动画偶尔会掉帧,往往是在第一次执行动画时,这有可能是浏览器或者操作系统为了平衡性能和管理系统资源导致的偶发性问题吧,不过我只是在画 2D 图像啊…… 如果图片要移动的距离比较长,也容易出现卡顿或者闪现,这是因为动画的帧数是写死的,太长的话,每帧之间的差异也就会大一些。总之,使用 `requestAnimationFrame` 的方法不太美妙。 + +最后我选择参考 Fancybox 的实现方式,这才发现 Fancybox 的 GitHub 仓库里居然只有一个打包好、压缩过的 JavaScript 文件——原来你不是开源的啊!无妨,用浏览器检查元素也能看到 Fancybox 是怎么实现缩放动画的。观察之后,我发现 Fancybox 并没有逐帧更新元素,而是只更新了一次元素的 `transform` 属性,更改的值是我从没见过的 `matrix()`。 + +查阅之后才发现 `matrix()` 是用于表示 2D 变换的 CSS 函数,实际上它表示了**齐次坐标**(Homogeneous coordinates)的变化,按照 MDN 的说法,是**齐次二维变换矩阵**(homogeneous 2D transformation matrix)。说人话的话,可以把它理解为以下几个 2D 变换的缩略写法:缩放(scale)、歪斜(skew)和位移(translate)。 + +简单来说: + +```css +transform: matrix(a, b, c, d, e, f); +/* 等价于 */ +transform: scaleX(a) skewY(b) skewX(c) scaleY(d) translateX(e) translateY(f); +``` + +*好险,差点就要被线性代数吓死了。* 😰 + +所以 Fancybox 的做法是,计算要将图片放大并居中到对应状态,所需要对图片做出的 2D 变换,也就是不直接改变元素的坐标和宽高,而是对图片进行位移和缩放。这样做的好处是可以不用 JavaScript 处理动画,利用 CSS 自带的过渡(`transition`)实现简单且丝滑的动画。 + +这听起来不难,不过当时的我已经精疲力尽,便把这个发现告诉了 ChatGPT,让它帮我写。事实证明,大语言模型没有任何平面想象能力,因为他最终给出的结果简直惨不忍睹,图片都不知道飞到哪里去了。 + +_*闭眼捏鼻 *吸气 *呼气……_ + +得,还是自己来吧。 + +我调试了半天都还是没办法把图片变换到正确的位置上,后来发现一个很关键的问题。在此之前,图片的位置一直是根据元素左上角的坐标点确定的,如果你没理解,可以回看这一张图。 + +![](https://r2.eltr.ac/uPic/2025/09/lovecoordsystem.png "注意看小猪图片的坐标,是左上角的点的坐标。") +{.dark:invert} + +然而,`transform` 对元素进行缩放时,是从中心点进行缩放的。根据中心点放大或缩小之后,图片左上角的位置会向左、向上偏移;实际上,除了中心点以外的其他点的位置都会移动。所以,要计算图片变换到最终位置需要在 X 和 Y 轴上位移多长的距离,要先找到图片始末状态的中心点,这是唯一一个不会在缩放之后偏移从而造成计算误差的点。 + +先计算出开始状态和结束状态下,中心点的 X、Y 坐标。 + +```js +const startCenterX = starts.left + starts.width / 2; +const startCenterY = starts.top + starts.height / 2; +const finalCenterX = finals.left + finals.width / 2; +const finalCenterY = finals.top + finals.height / 2; +``` + +然后计算两个中心点的差值就能得到位移的距离。 + +```js +const translateX = finalCenterX - startCenterX; +const translateY = finalCenterY - startCenterY; +``` + +至于缩放的倍数,就非常简单了。 + +```js +const scaleX = finals.width / starts.width; +const scaleY = finals.height / starts.height; +``` + +计算完变换矩阵之后就可以把这些属性应用到元素上了,然后借助 CSS 自带的 `transition` 就能看到图片放大和缩小的动画了。 + +```js +// 放大、居中的变换 +element.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${translateX}, ${translateY})`; + +// 缩小、复位的变换 +element.style.transform = `matrix(1, 0, 0, 1, 0, 0)`; +``` + +## JavaScript 设置样式时踩的坑 + +以上一切问题都排查完毕之后,图片灯箱居然还是没有办法在博客上正常工作!明明在测试页面中就好好的!我百思不得其解,通过检查元素才发现,博客上的影子元素根本没有被应用 `top` `left` `width` 和 `height` 属性,也就是说一开始影子元素就没有遮在原图片的上方,初始位置一直在页面末尾,灯箱一直是从最底下飞上来,又从正中间飞下去…… + +可是为什么测试页面里就是正常的啊! + +为了自己的头发,我把自己观察到的问题和可能的原因连同代码一起发给了 ChatGPT,结果对方表示: + +> 你没写单位。 + +*啊…… 果然难改的 Bug 都是这种原因吗……* + +因为 JavaScript 通过操作元素 `style` 属性修改样式的方式,实际上是修改了元素的行内属性,而 HTML 属性只有字符串类型,没有整数和浮点数,所以我直接把计算得到的数字赋值给 `style.top` 等属性的方式不总是能奏效。JavaScript 作为一门弱类型语言,不总是能够正确地把数字转换为字符串,所以要加上单位,因为单位是字符串,一个数字加上字符串的操作就能让 JavaScript 明白我希望得到字符串的结果。 + +```js +positionShadow() { + this.element.style.top = this.originalPosition.top + 'px'; + this.element.style.left = this.originalPosition.left + 'px'; + this.element.style.width = this.originalPosition.width + 'px'; + this.element.style.height = this.originalPosition.height + 'px'; +} +``` + +JavaScript 真的是一坨混沌的产物! + +![](https://r2.eltr.ac/uPic/2025/09/programming-people-javascript.png "图片来自:[leftoversalad.com/c/015\_programmingpeople/](https://leftoversalad.com/c/015_programmingpeople/)") + +## 喜闻乐见的命名环节 + +用 Parcel 打包,最终得到了一个不到 4 KB 的 JavaScript 文件,包的大小我很满意。 + +![](https://r2.eltr.ac/uPic/2025/09/qP5PmF.jpg) + +由于是灯箱(LightBox)插件,又注重轻量,所以名字也简短一点比较好,我取了 Light 和 Box 两个词的前两个字母,取名叫 Libo。后来又觉得这个名字看着不太顺眼,读着也没有很上口,就改了。因为 Libo 读起来很像 Libra(天秤座),干脆就改成了这个好听又好记的名字。 + +现在有点想凑齐十二星座了…… + +--- + +## 最后 + +你可以在 GitHub 上查看 Libra.js:[BigCoke233/libra](https://github.com/BigCoke233/libra) + +之前用 LÖVE 引擎开发 2D 游戏的经验居然也在 Web 前端开发这一领域给了我帮助,果然天下没有白干的活,以往的经历会绕着弯子来帮助现在的自己。 + +嗯?你问我什么时候开发下一个游戏?呃…… _*擦汗_ 要不我们还是下次再聊? + +_*转身逃跑_ + +[^1]: 其实 LightBox 模块还能拆开来,初始化监听器和开关灯箱明显是两个职责,但我担心分出多个模块会让结构变得复杂。 + +[^2]: 参见:"The offsetTop read-only property of the HTMLElement interface returns the distance from the outer border of the current element (including its margin) to the top padding edge of the offsetParent, the closest positioned ancestor element." —— [HTMLElement: offsetTop property - Web APIs \| MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop#:~:text=The%20offsetTop%20read%2Donly%20property%20of%20the%20HTMLElement%20interface%20returns%20the%20distance%20from%20the%20outer%20border%20of%20the%20current%20element%20(including%20its%20margin)%20to%20the%20top%20padding%20edge%20of%20the%20offsetParent%2C%20the%20closest%20positioned%20ancestor%20element.) + +[^3]: 一个很老旧的 Java 图形库。 \ No newline at end of file diff --git a/content/article/lost-in-gui.md b/content/article/lost-in-gui.md new file mode 100644 index 00000000..0eda6109 --- /dev/null +++ b/content/article/lost-in-gui.md @@ -0,0 +1,119 @@ ++++ +title = "迷失于图形界面" +subtitle = "Not to be fooled by magic." +slug = "lost-in-gui" +tags = [ "认知", "软件",] +categories = "软件杂谈" +date = 2026-03-07T19:41:05 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/f188c4b3-6897-4de9-b551-5326927d339e" +url = "/essays/lost-in-gui/" + ++++ + +学校开设了 Python 课程,课程还涉及人工智能相关的内容,但也有相当一部分内容是 Python 程序设计基础。自然地,第一堂课的内容是配置开发环境,*自然地*,配置开发环境的内容就是*安装 PyCharm*,并在 PyCharm 的图形界面里找到对应的面板安装要用的依赖项。 + +一般来说,只要老师没有妨碍我愉快地用我爱用的编辑器(Neovim)写代码,我是不会说什么的。只不过,这位老师之前也教过我数据库的课程,他对于开发工具的态度在我看来非常典型,所以值得一谈。 + +## 不解之词 + +老师在演示如何用 PyCharm 安装依赖时说了这样一句话: + +> “我看有的人用写代码的方式就能把依赖安装上了,那样好像是会快很多,有些人就是能找到捷径啊!” + +尽管我对 Python 生态不熟悉,但根据他的描述,我大概明白他说的是类似 Node.js 的 `package.json`、Go 语言的 `go.mod` 和 Maven 的 `pom.xml` 之类的东西。在项目根目录的一个文件声明项目所需的依赖之后,执行安装命令,就能在当前项目下安装所需的依赖。这实际上是相当常见的实践,有正经工程应用的编程语言都有类似的东西。 + +在讲授数据库原理及其应用这门课的时候,他要求我们安装的是 [Navicat](https://www.navicat.com/),一个管理数据库的图形界面工具。我不想用闭源的商业软件(而且我当时的操作系统是 Arch Linux,似乎也没有在 AUR 上找到包),所以选择了 [DBeaver](https://dbeaver.io/)。我记得很清楚,我除了在需要提交作业截图时使用了这个软件,其他时候都是用 [MariaDB](https://mariadb.org/) 自带的命令行工具,手打 `SELECT` 和 `INSERT INTO` 等语句,因为我真的不想在层层叠叠的图形界面里找我想要的功能。 + +我记得有一次交作业我实在不想打开 DBeaver,于是提交了终端截图,结果下一次上课的时候就听到他这样说: + +> “有的同学直接输入 SQL 语句,都不嫌麻烦的吗?临时输入一两句还好,要输的东西多的时候,就直接在软件的表格里编辑数据表就好了啊。” + +~~那这和用 Excel 有什么区别!~~ + +到目前为止,这还只是操作习惯的差异,不足为奇。*所以,老师是一个喜欢操作图形界面的人,这不代表他是个差劲的程序员,程序员的能力不体现在工具的选择上,不熟悉命令行工具又怎么了?用 Neovim 和 Emacs 就比用 VS Code 更高尚?用 Postman 就比用 `curl` 更愚蠢?用集成开发环境也不代表无能啊。* + +> “大家用 `pip` 安装依赖的时候注意一下啊。”老师好像是突然想起了以往的经历,在讲课时突然插入了这样一句话,“用 `pip` 安装的第三方库和你的 PyCharm 里的第三方库可能不会互通,就是说你用 `pip` 安装了第三方库之后,在 PyCharm 里可能用不了,要在 PyCharm 的图形界面里安装依赖。” + +我没学过 Python,但确实用 Python 写过不少脚本来帮我自动化处理某些操作,比如批量修改博客的 Markdown 文件格式、替换文本之类的,我也的确遇到过没办法正常加载依赖的问题。当时我只能改变实现方式,避免调用第三方库,一直没明白原因。这么说,我的问题就要从老师那里得到解答了? + +没有,他直接往后讲了,什么也没说。他自己大概也不明白为什么 `pip` 安装的依赖会没办法在 PyCharm 里使用。 + +求助*熟练操作蟒蛇*的[狐狸](https://blog.southfox.me/)之后得知,这是 Python 的[虚拟环境](https://docs.python.org/3.14/library/venv.html)导致的,即 `venv`。虚拟环境会将软件包与全局环境的软件包隔离开来,只有在环境内显式声明的软件包才可用。`pip` 默认把软件包安装到全局环境中,而 PyCharm 会帮忙管理虚拟环境,两者不在同一个环境里操作软件包,所以没办法直接互通。 + +这就解释清楚了,所以我只需要执行 `source` 命令进入虚拟环境,然后在虚拟环境里管理依赖和运行 Python 程序就可以了;如果安装了 uv,使用 `uv run` ,可以直接在项目的环境里执行命令。[^1] + +不过,老师看起来教授 Python 也有几年了,为什么会不清楚这个基础概念呢?难道是我误解了老师的…… + +*好了,是时候放下我对教师的假惺惺的尊敬了。* + +## 图形界面的魔法 + +图形界面的优点在于,它屏蔽了很多细节,避免直接和复杂的配置文件和基础工具打交道。这无可厚非,软件设计的一大原则就是「信息屏蔽」,让用户关注更重要的事情。可是,对于程序员来说,这些细节真的应该被屏蔽吗?一个好的程序员不应该了解自己所使用的开发工具是如何运作的吗? + +我在英文博客上写过一篇《[Java Development with True IDEA](/en/posts/java-dev-with-true-idea/)》,强烈抨击了 IntelliJ IDEA 单边主义,[^5]并把软件开发所需要的 IDEA 重新定义为 Instant(快速)、Deliberate(审慎)、Elegant(优雅)和 Attentive(专心)。 + +我当时连续使用 IDEA 将近一年的时间,原因在于:没了 IDEA 我就不知道怎么开发 Java 项目了。之所以会这样,是因为 IDEA 给我屏蔽的信息太多了。不操心底层真正发生了什么的后果是,我根本不知道底下发生了什么。当我按下 IDEA 的「运行」按钮时,究竟有什么命令被执行了?我不清楚,以前的我也不关心,我只知道「这个按钮能让我的代码跑起来」,就像魔法一样。 + +可是,要是有一天魔法失效了呢?当我按下「运行」的时候程序没有被执行,当我按下「同步」按钮的时候依赖没有被同步(IDEA 的设计非常奇怪,有时候「同步」按钮根本不会显示,我必须在一个下拉框里找到某个菜单项才能正常同步依赖),当我的程序没有被正常编译,而我在密密麻麻的界面里找不到相关的配置项时,我要怎么办? + +要找到图形界面里的某项配置可真不简单。 + +首先,我很难用语言描述清楚我要找的是什么,如果描述不清楚,又怎么在搜索引擎里搜索教程呢?其次,就算找到了我要的东西,有人告诉我这个东西要在 `Project Strucutre -> Libraries -> More` 里面找到,我也要在硕大的图形界面里搜寻这些文字的位置。再次,就算有截图指引,我也有可能因为版本差异而没有办法在图中所示的地方找到我需要的东西。 + +有人可能会因为熟悉图形界面迷宫而感到自豪吧。我记得我在各种按钮、菜单、面板和输入框之间穿梭,只为了调整项目的编译方式时,有一个不熟悉计算机的朋友突然凑过来看我在做什么,发出了「好厉害」的感叹。可是,究竟为什么要学习一套可有可无的、建立在基础工具之上的抽象,而不去直接使用基础工具呢? + +这就好比用 React 开发一个只有一页的网站,而这一页的内容只是几句话和几个链接——*那你为什么不能直接写 HTML,而要去操作虚拟 DOM 呢?这层多余的抽象究竟给你带来了什么价值?* + +我为什么要学习 Postman 的图形界面,等待它花几秒钟的时间启动一个 Chromium 实例渲染一个网页,学习和记忆 URL 输入框 和 HTTP 请求方法的选择框的位置,只为了发一个简单的 HTTP 请求?我为什么不能直接使用 `curl`?如果我只会用 Postman,我就不知道要怎么在其他的地方发送 HTTP 请求了,而 `curl` 却被安装在几乎任何一台计算机上,是很多软件的基础工具,无论是日常测试、运维还是开发工作,都能用到。我调试自己写的 API 会用 `curl`,我测试部署的服务有没有真的跑起来会 `curl localhost:`,像 [Hurl](https://hurl.dev/) 这类与 HTTP 请求相关的软件也是在 `curl` 的基础上开发的。 + +显然,无论选用抽象层次很高的图形界面软件,还是最基础的命令行工具,都有学习的成本。那为什么要学习一套将你与底层隔离开来的抽象,而不是直接学习更接近底层的工具呢? + +我承认抽象有存在的价值,但我反对过度且不必要的抽象。 + +## 专业与门槛 + +可能有些幼稚,但我又要举一个大学老师的例子了。不过这个老师本身就很讨人厌,说话爹味很重而且粗俗,还觉得自己和蔼可亲,他项目组里的学生能跑的都跑了。他身上有一个很多爹味浓重的人都有的典型特质:热衷于做「守门人」,强调门槛与专业性,踩在门槛上拉开自己与他人的距离。 + +他也喜欢使用图形界面,但原因,在我看来,并非是权衡利弊之后的选择,而是对门槛的维护。在我看来,如果你不想接触基础工具,只想要优化开发体验,那么选择简洁直观的图形界面工具也无可厚非,只要这是你自己选的。 + +设计软件架构常用 UML,即统一建模语言,UML 有各种不同类型的图表,用来表达架构、活动、操作的时间顺序、涉及的模块和对象等等,总之是便于沟通的标准化工具。既然目的是「沟通」,那么只要能准确表达,能让他人理解,就达到了目的。简单来说,只要图画得清晰,没有错误和歧义,能够高效沟通,就是好图。 + +但是这位老师显然不这么认为。 + +> “有的同学用 Visio 画图,这样不好,我们作为软件工程的学生,要使用**专业**的 UML 绘图工具。你作为**专业**的软件工程学生,连**专业**的画图工具都不会用,怎么行!?”,老师神情严肃地讲道,“我在群里发了两个软件,第一个软件我们把他叫作 EA[^3],这个软件是商用的,你也可以用第二个开源的 StarUML。[^4]” + +Visio(以及开源的 draw.io)不被他视作**专业**的 UML 图绘制工具,并不是说架构师没办法用它们画好图,而是因为它们缺乏与 UML 相关的抽象。这位老师强调,Visio 是矢量图绘制工具,而不是**专业**的 UML 图绘制工具。这两类工具的区别就在于抽象层次的高低。 + +之所以这么说,是因为,UML 图明显就是图片的一种,一般也是作为矢量图来绘制的。能绘制矢量图的工具当然也能绘制 UML 图,说白了,UML 图里最常见的元素就是方框、圆圈、直线、箭头、小人和文字,连 PowerPoint 都能画这种图。只要使用了正确的建模语言和规范,保证图片清晰易懂,就是好的 UML 图。 + +前文提及的 EA 和 StarUML 等软件,当然也是能画方框、圆圈和小人的,只不过它们只能用这些元素来画 UML 图。使用这种工具绘制 UML 图是自然的,哪怕对建模语言本身不熟悉的人,也不容易画出错误的图。 + +通俗地来讲,这两类软件的区别,就是化学原料和包装好的清洁剂的区别。这位老师觉得:使用一水柠檬酸溶液来清除水垢是不专业的,应该使用包装上写明了「水垢清洁剂」的清洁产品,才**显得专业**。 + +## 破除魔法 + +让我总结一下目前为止我的观点。 + +长期依赖于高度抽象的图形界面工具,尤其是在一开始就没有了解过低层次抽象的前提下,会让人忽略最基础的知识。这是个人层面的问题。社会层面上,会创造出本不应该存在的门槛和鄙视链,仿佛使用高度抽象的软件系统就更专业。 + +这种心态不罕见,我相信:如果让所有的 Java 开发者停止使用 IDEA,有相当一部分人会不知道如何启动 Spring Boot 项目(答案:用 `mvn spring-boot:run`);如果你告诉别人你用 GIMP 编辑图片而不是 PhotoShop,有相当一部分人会认为你不够专业。 + +这么说来,因为普遍认为前端技术很简单,所以常常被鄙视的前端开发者,实际上大多都脱离了这种窘境,因为前端开发的必要工具之一就是 `npm` 或者其他相关的命令行工具,我很少看到有人用 JetBrains 的 WebStorm,通过操作图形界面管理依赖项。当然,前端开发也有自己的问题。 + +使用 LLM 开发也是,许多人宁愿用高度抽象的自然语言描述需求,也不愿意手写代码,就算在遇到 Bug 时跟 Agent 发疯也不愿意停下。[^2]如果他们愿意去看看真实的代码,接触被抽象掩盖的东西,他们就不会如此狼狈。我想这背后也是相似的心态在作祟,而且「程序员应该跟上潮流用 LLM 写代码,手写代码是落后的」这种思想,似乎也有愈演愈烈的苗头。这种潮流,何尝不是痴迷于高度抽象的软件,所造就的门槛? + +最后,我想说的是,不要怕麻烦,接触低层次的抽象并不可怕,反而能帮助自己建立起对软件的清晰认知,而清晰是非常宝贵的。就像学习 C 语言有助于程序员理解内存、指针和数据结构等基础概念,就算不用 C 做开发,有了这些理解,也更容易写出高性能、速度快的软件。 + +从长期来看,对软件的清晰认知,要胜过生产力和专业的外表,而扒开抽象的外壳向内看,是培养这种认知的关键步骤。 + +[^1]: 参见:[Running commands in projects | uv](https://docs.astral.sh/uv/concepts/projects/run/) + +[^2]: 顺带一提,我甚至见过有 Java 开发者非常认真地讨论,要不要双开 Cursor 和 IDEA 做开发,因为他们觉得需要用 AI 编程,而离开了 IDEA 做 Java 开发又很麻烦。 + +[^3]: 全称是 Enterprise Architect,中文意思是「企业架构师」。英文里的 Enterprise 除了指代企业和创业,也和企业家精神和专业性有关联,所以也可以理解为「专业架构师」。 + +[^4]: 我了解之后发现,StarUML 也是专卖软件(Proprietary software),最初以 GNU GPL 协议发布了开源版本,但开源版本在 2010 年就停止维护了。当然,就算它是自由软件,我也不想用,原因在于它是 GUI 软件,很重,另一个很关键的的原因是,*它是用 Electron 和 Java 写的*。 + +[^5]: IntelliJ IDEA 是 JetBrains 开发的,专注于 Java 和 Kotlin 开发的集成开发环境。一般来说,学校里教 Java,要么会要求学生安装 Eclipse,要么就是 IDEA。IDEA 是最常见的,人们几乎不会思考开发 Java 软件的其他方式。 \ No newline at end of file diff --git a/content/article/love-lost-in-xmas-eve.md b/content/article/love-lost-in-xmas-eve.md new file mode 100644 index 00000000..553879ea --- /dev/null +++ b/content/article/love-lost-in-xmas-eve.md @@ -0,0 +1,49 @@ ++++ +title = "撞到人要说对不起" +subtitle = "关于我在平安夜错过了自己的爱人这档子事" +tags = [ "自我", "孤独",] +date = 2025-12-25T01:39:00 +draft = false +toc = false +slug = "love-lost-in-xmas-eve" +categories = "乱章" +aliases = [ "/posts/撞到人要说对不起/",] +url = "/posts/love-lost-in-xmas-eve/" + ++++ + +我早早地订好了《Wicked: For Good》的电影票,平安夜的晚上是在电影院度过的。大概是因为音乐剧在国内水土不服,重庆人更是不爱看,所以本地影院的排场少得可怜。沙坪坝除了有一家影院提前开始售票,其他影院都是在开播的前一天才有票买,这也导致我去看的那场几乎坐满了人。 + +《Wicked》第一部电影,我是在去年的一个周四去的,那个时候电影已经开播了一段时间,整个影厅里只有我一个人,算是享受了包场。这次的感觉很不一样,前后左右都是人,不过,除了个别不知道是高中生还是大学生看到一丁点尺度极低的床戏就开始大笑之外,体验也不算差。 + +夏天刚结束的时候,我在好几次占卜中都得到了积极的预兆,大概会在十二月底到 2026 年初的时间遇见新恋情(其实更准确的说法是第一段恋情)。我虽然不是宿命论者,但我相信吸引力法则和心理暗示的力量——只要我怀着这样的期待和相信,这件事情发生的概率就只会增加而不会减少。我在这周安排了两次出行,其中一次是周六要去南岸区看音乐剧《雨中曲》,另外就是这一次。不喜欢去太吵闹太外放的社交场合,影院、剧院、书店和咖啡厅,是为数不多我能遇到陌生人的地方了,尽管这也意味着我和他们很有可能不会说上一句话。 + +这个周三给我的感觉很奇妙,一天都不想接收太多信息。这天一共走了一万八千多步,一般都会在路上听歌或者听播客的我,意外地对耳机感到些许厌烦。距离家三十分钟步行路程的影院,来回我都是走路,在路上只和自己的思绪作伴——我很喜欢散步的感觉,要是城市里没有电瓶车在人行道上狂奔就好了。 + +或许是没从虚拟世界里接收什么信息,心事也都在过去的几天里想遍了,脑子突然有了空闲的线程处理我身边的信息:早上刚走出电梯,看到地上有滩红色液体,脑子里本来已经开始想象邻里纠纷和动物虐待,并为人类感到高兴对猫猫狗狗感到痛心了,结果走出门发现另一滩相同的液体上有一颗烂掉的杨梅(好失望……?);远远地在学校的绿化带上看到一片颜色奇特的落叶,还没来得及感到惊奇,就发现那是某个没素质的人丢的火腿肠包装纸;影片快开始时,从前面匆匆跑进来三个人,身材中等,样貌打扮像是中学生,我疑惑「你们八点就放学了吗?」;在位置上坐下后,右下方突然有一个十岁出头的小男孩站起来(他的监护人在哪?);右边两个女生在放映之前一直在大声聊八卦,内容我忘记了,我没有很介意,但她们的声量和谈话方式的确是有点招人厌烦的类型,坐在我左边的男生似乎有些不满…… 唔,不知怎么地,接下来我的注意力就全放在坐在我左边的这个男生身上了。 + +我进场的时候,他已经坐在那了。因为觉得在没有交谈的情况下直视陌生人的脸不太礼貌,再加上灯光昏暗,我没有看清他长什么样子。他坐在 1 号座,我是旁边的 2 号座,右边的两个女生也已经坐在那了,所以我刚好进去填补了那个空位。大概是因为他有一种我难以描述的不好接近的气质,我坐下的时候,身体下意识地往远离他的方向倾斜,也导致我刚开始一直坐得不太舒服。这种气质,可能只有同类人才能如此清晰地察觉到,因为之前有人也说过我有「生人勿近」的气场,其他人要么是在跟我聊过一两句后发现我其实很好说话,要么就是因为这种气场一开始就没有跟我靠得很近,但不会细想这种印象的来源。总之,「坐在旁边的是一个很内敛的男生」,这个印象就这么产生了。 + +众所周知,INFP 的大脑结构很神奇,语言中枢并不会在他们开口讲话的时候被激活,这块大脑区域主要被用在以下场合:为未来即将发生的对话做预演、在脑子里回放以前进行过的对话并重新组织之前没说好的话,以及想象自己正在进行一场实际上根本不会发生的对话,对话的参与者与自己甚至根本不会相遇,再甚者,这个参与者根本不存在于现实当中。[^1] + +不过事实就是,我的确花了不少的时间想象,我会和坐在左边的这位和我一样在平安夜一个人出门看电影的男生,发生什么样的对话。我想他大概也暗暗地对这件屋子里其他所有的人感到厌烦,于是我跟他分析起右边两个讲八卦的女生的人物性格;他在看手机,是在和朋友聊天吧,我猜他也有大把大把的在网上认识的有趣的朋友;我猜他一定有着古怪的幽默感,所以我开始想象他笑的时候眯眼睛,盯着我看,尽管我从没看见过他的脸。 + +这些猜测,都是一些微小的、一般人不会注意到的细节,被我捕捉到之后,通过直觉自动生成的联想,而我已经忘记那些一开始让我产生这些印象的事实是什么了。 + +电影进行到奥兹国人民举着火把离开翡翠城,踏上黄砖路要去杀死西方坏女巫的桥段,此时北方好女巫 Glinda 心情十分复杂,看着队伍离去之后关上了窗户,窗户关上之后人群的吵闹声就几乎听不见了,而背景音乐并没有开始播放——本来是情感丰沛的一幕,而我脑子里蹦出来的第一个想法是「这窗户隔音真好!」我觉得我应该在电影院里保持安静,所以我又开始和脑海里的人对话。我在想,如果我把这句不合时宜的话说出来,他一定会笑的,虽然,我根本就不认识他! + +我很难描述清楚这种感觉。为什么会对一个从没跟我说过一句话的人如此关注呢?他坐在 1 号座,要给好多过路的观众让位。我看见他好几次挪开腿让人通行,竟从他的肢体动作里读出一丝厌烦、无奈和小心翼翼。不过,我的理智告诉我,他可能有也很有可能没有这些感受,我只不过是在投射我自己的想法而已。 + +他似乎把自己的包规规矩矩地放在胸前,又时不时在里面翻找些什么东西。他偶尔会调整自己的坐姿,但大部分时候好像是缩在椅子里的,是太拥挤的空间也让他觉得不舒服吗?他会是个高中生吗,我会不会像我那个令人讨厌的室友一样喜欢上一个高三学生?不,我对他绝对是说不上喜欢的,只是令人费解地对他感到好奇。他掏出了手机,屏幕上显示的像是课表的界面,那他一定是个大学生了。课表好像很满,他会是大一新生吗?他会不会也有着那种愤世嫉俗却不真正理解社会运作方式的思维特质?不清楚具体的原因,我似乎一直很害怕自己的这部分特质,这或许在以前的我身上会明显很多。我会真的和他说上话吗?如果的会的话,应该是什么契机?他会讨厌我和他搭话吗?我会有这样的担忧,大概是因为我本身就讨厌莫名其妙找我搭话的人。 + +原来,我对素未谋面的人也会产生「他懂我」的错觉,~~真的是顶级恋爱脑了~~。不过,事实是,我只是在脑子里和另一部分的自己玩耍而已。 + +他穿了一件白色的内搭,似乎是毛衣,也可能是卫衣。电影进行到尾声时,他穿上了一件黑色的外套。散场灯亮起,我才看清楚他的裤子是咖啡色的。电影的演职人员表刚开始播放,他就迫不及待地起身走了出去。没过多久,我也站了起来,走出六号影厅,我往左转弯,才在走廊尽头看见他的背影。我没有刻意加快步伐,但走得也不慢。等我走出电影院,我已经找不到他了。我还是没有看清楚他究竟长什么样。 + +为什么我会感觉像是错过了命中注定的人一样?真是奇怪。[^2]如果我未来的爱人性格和我一样,两个不爱跟陌生人说话的内向者,究竟是怎么相遇的呢? + +如果我三生有幸,能让未来的文学学者来研究我写的这篇文章,他们大概会分析:作者借文中人物之口(或者「之躯体」?)表达了他对人群的厌烦、对自己的厌烦以及一种在全文中占据主导地位的情感——孤独。 + +[^1]: 以上全是胡说八道。 + +[^2]: 如果你在好奇这篇文章的题目为什么叫「撞到人要说对不起」——这是《爱人错过》的歌词。 \ No newline at end of file diff --git a/content/article/no-sugar-in-my-coffee.md b/content/article/no-sugar-in-my-coffee.md new file mode 100644 index 00000000..91f20f29 --- /dev/null +++ b/content/article/no-sugar-in-my-coffee.md @@ -0,0 +1,71 @@ ++++ +title = "你凭什么往我的咖啡里加糖?" +tags = [ "心理学", "人际交往", "写作", "咖啡",] +date = 2025-07-03T21:03:00 +draft = false +toc = true +slug = "no-sugar-in-my-coffee" +aliases = [ "/posts/no-sugar-in-my-coffee",] +url = "/essays/no-sugar-in-my-coffee/" + ++++ + +我一直在用「[喝水羊驼](https://apps.apple.com/cn/app/%E5%96%9D%E6%B0%B4%E7%BE%8A%E9%A9%BC-%E5%96%9D%E6%B0%B4%E6%97%B6%E9%97%B4-%E5%96%9D%E6%B0%B4%E6%8F%90%E9%86%92-%E7%BE%8A%E9%A9%BC-waterllama/id1454778585)」这个 App 记录每日饮水量,除了根据体重、性别、运动量和天气推荐每日饮水目标,这个 App 还设置了各种挑战。其中有一个叫做「积极瘦身的树獭」,目标是挑战 10 天只喝白水或气泡水来补充水分,目的是远离糖分和不健康的饮料。我一直不能接受这个挑战,因为它把咖啡也排除在外了。前几天仔细读了读这个挑战的介绍,发现他鼓励用户挑战不喝咖啡的理由居然是: + +> 不要喝茶或咖啡,因为不往里加点甜味会很难喝。 + +我回去看了看英文原文,对应的句子是「because it's hard not to have it sweet」。翻译显然错了,译文意外地没那么令人恼火。说「茶和咖啡不加甜味很难喝」最多会让我翻个白眼评价软件开发者「没品」,但是说「不喝甜的茶喝咖啡很难」,会让我觉得开发者预设了用户都没品,只喝得下加了糖的茶和咖啡。这就很冒犯人了。 + +我乳糖不耐受,再加上对咖啡原本味道的偏好,所以不喝奶咖,在一般不卖手冲的咖啡店里都会点美式。如果一个店员在我点完美式之后问我要不要加糖,我对这家店的印象就会大打折扣——「原来你家用的豆子是不加糖就会难以下咽的水准吗?」。还好我不常去咖啡店。 + +叠个甲,我不是说喝茶和咖啡加糖就是没品,毕竟不同的人对饮品有不同的需求,有的只是为了放松或者获取咖啡因,而有的人会更偏好感受风味。我只是觉得那些认为「茶和咖啡只能加糖喝」的人没品而已[^1]。 + +按照本博客的尿性,这篇文章要谈的显然不是「咖啡该不该加糖」。 + +## 「为你好」为什么令人讨厌 + +因为我觉得咖啡很苦,而你应该不喜欢喝苦的,所以我就往你的咖啡里加了糖;因为我觉得爆米花就是要焦糖味、奶油味的才好吃,所以我给你的原味爆米花调了味;因为我觉得看完一整本书太累了,所以我就用 AI 总结好了发给你,这样你就不用看了,既然你都不看了,我就帮你把书放到多抓鱼上卖掉了…… 我记得高中时我家搬了新房,装修时没人问过我意见,我爸突然有一天带我去看房,走到我的房间时,他对我说「你看床是白色的,你喜欢白色」——我~~他妈~~不喜欢白色。到现在我也不喜欢那个房间的布局,我爸觉得把卧室装得像酒店房间很气派,我一直很苦恼床不能靠墙睡得不安稳。我爸给我买了一个黄色的印有龙图案的坐垫,觉得我肯定喜欢这种「当皇帝」的感觉,因为他就很喜欢,我每次回去都害怕有朋友来我家看到我坐在那种东西上面…… + +我知道我现在的语气很像是「得了便宜还卖乖」、对家人的好意斤斤计较,但好意也可能是压力,比如,对抑郁者患者频繁地表达关心、说话小心翼翼,反而会让对方觉得「自己成了负担」或者「别人都不把我当正常人看」,但这么做却能让自己觉得「啊,我帮助了需要的人,我真是个有美德的人!」或者「我已经表达了自己应有的关心了,现在我感觉安心多了」。==令人讨厌的「为你好」,本质上是对自己的满足而非对别人的奉献==。 + +「为你好」的第一重罪是**只看见了自己**。「好」的标准全由自己说了算,压根看不见或者拒绝接受别人的标准,还强迫别人接受自己的标准。因为自己觉得「加糖变好喝了」,所以认为这是「好」的行为,别人也理应接受这个标准,认为我往别人咖啡里加糖的行为应该被认作是「好」的。然而,对方可能正在减脂、控糖,或者正在间歇性禁食,非窗口期不能摄入热量;对方冲的也可能是一杯手冲咖啡,往里面加糖就完全毁掉了这杯咖啡的风味体验。从对方的视角看,这完全就是搞破坏的行为。解决方法其实很简单,像咖啡店店员一样问一句「美式要加糖吗?」;或者干脆不管,因为别人喝什么咖啡本来就不关你事。 + +「为你好」的第二重罪是**情绪勒索**。抢占了「好」的解释权之后,自己就能以「我出了力」「这是我一片心意」为由要求褒奖。如果对方不能提供自己想要的情绪价值,产生了情绪落差,就要让对方也产生情绪落差,来让自己心里平衡,即通过指责、卖惨的方式来破坏对方的心情,把对方也拉下水。当事情发展到这个层面上,「为你好」的虚伪面孔就被揭开了,这类行为的目的明明是「为了自己感觉良好」。 + +如果真的为一个人好,就不该只看到自己做了什么,而是要看到别人要什么;不该因为自己做了事情而别人不领情就指责别人,指责的行为本身就说明了自己不是为他好,而是为了从奉献性行为中获得认可,本质上是为了让自己感觉良好——换句话说,很「自恋」。 + +## 我喝什么咖啡不关你事 + +这里要引用阿德勒心理学里的「课题分离」概念。 + +> **课题分离**是阿德勒心理学中的一个概念,是阿德勒认为的、人际交往中应当遵守的法则。要区分一件事是谁的**课题**,可以思考「这件事情最终影响的是谁?」,例如孩子的学业情况最终影响的是孩子自己,而非父母,那么读书这件事情就是孩子自己的课题,父母原则上不应该干涉。 +> +> 在人际交往中,分清楚每件事情是谁的课题,并不干涉其他人的课题,就叫做**课题分离**。阿德勒认为人际交往中的一切问题都是由于干涉其他人的课题导致的。阿德勒认为「可以带马儿去河边,但不能强迫马喝水」。教育子女是父母的课题,学业是孩子的课题;提供物质基础和鼓励是父母的课题,这不一定要干涉孩子自己读书的课题。如果能在人际交往中做到课题分离,人与人之间的冲突就会大大减少。 +> +> Source: 《被讨厌的勇气》[日] 岸见一郎 + +真正的「为你好」应该是「带马儿去河边」,而不是「强迫马儿喝水」,因为马儿不一定渴,而且马儿渴不渴、渴了选择喝水还是不喝水,都不是自己的课题。马儿喝不喝水,最终的结果是由自己承担的。对方接不接受自己的好意,结果也由他自己承担。好意被接受后产生的正面情绪和被拒绝后产生的负面情绪,也是自己的课题,不该要求别人来解决自己的课题,也就是说不该要求别人照顾好自己的情绪。 + +我当然心领你想让我喝上更好喝的咖啡这个好意,但我想告诉你我现在正在喝的咖啡对我来说就已经非常好喝了,你加糖的行为只会让咖啡对我而言变得难喝,而且还会给我带来额外的热量负担。并且,==就像我不会因为自己喝了一杯不好喝的咖啡而责备你,你也不应该管我喝的咖啡究竟好不好喝==。 + +## 写作者、译者和他们的读者 + +在《[看动画片如何帮我提升译者素养?](/posts/看动画片如何帮我提升译者素养/)》这篇文章下,我和一位读者展开了讨论,谈到了译文要保留含义,还是保证功能的问题。对方认为在一些情景下,可以把 Google 翻译成「百度」,因为功能达到了,读者只需要知道「这是个搜索引擎」就可以了;如果大多数人都不知道「谷歌」是什么,那还要加上注释,读者的体验就会打折扣。 + +尽管我认可翻译就是要妥协的,但我始终无法接受「你只需要知道这是个搜索引擎就行了」这种翻译策略,这感觉就像是译者往我的咖啡里加糖了一样。 + +> 我不赞成把 Line 译成「微信」,就像我不赞成把 Wilde 译成「李白」一样。我知道这两个例子差别很大,一个是软件另一个是诗人,但的确符合「只需要知道这个东西起什么作用,而不需要知道这是是什么」的情景。如果剧中人物只是随口提了一句 Wilde,对理解剧情不重要,就可以把 Wilde 翻译成「李白」了吗?不,我之所以看美剧而没有在看其他文化产出的影视作品,就是想体会这一种文化,看看这个地方的这些人会说些什么话,而不是这个地方的人说的话**相当于**我们这边说的什么,不是这个地方的这些人用的软件**等同于**我们用的什么软件。 + +简单来说,我认为这种翻译策略预设了读者不愿意费心思了解另一种文化,做了「为你好」的工作。我的确见到很多汉化组把 PayPal 翻译成「支付宝」,或者把一些俏皮话不恰当地翻译成网络用语。这的确让读者、观众更容易理解了,但是,我到底在看什么?看的是英文的译文,还是这段英文相当于中文里的那句话?那我看的是中文还是英文,体会的是中国文化还是英文语境里的文化?[^2] + +话题一下扯得有点远,从人际交往扯到了翻译,那不妨再扯远一点。在写作的时候,该不该预设读者什么都不懂,然后把所有的概念都解释一遍?事实上,这就是一种写作的策略,一些人认为写作就应该尽量通俗、少用专业名词。一方面,从零构建概念是对自己知识储备和理解力的检验;另一方面,这种语言风格的确让作品能被更多的人读懂。 + +我们现在只是在从写作者的角度看问题,就像只从译者自己的角度看问题时,把本土化做得再极致一些,能让译文更好懂,能让自己觉得自己是「好的译者」。然而,从读者的角度看问题时,会发现一些读者并不喜欢读大白话,而且,过于通俗、过度简化的叙述方式,反而会妨碍读者精确地理解概念。我记得我在读《[算法之美](/library/2024/算法之美)》的时候,就批评作者把计算机算法写得太通俗,以至于我根本搞不清楚这个算法是如何运作的,只能建立感性的认知。 + +然而,《算法之美》的确是一本不错的书,因为它完成了自己给自己设下的任务——不是讲明白计算机算法,而是用计算机算法的思想指导生活。只是我作为一个读者比较刁钻,希望清楚、精确地理解罢了。 + +所以,写作者和译者应该给读者的咖啡里加糖吗?答案是,要看你的大部分读者喜不喜欢和加糖的咖啡。重点是「看见读者」「看见他人」,而不是沉浸在「我写得很通俗,我为读者着想了,我是个好作者」的自嗨情绪里无法自拔。 + +[^1]: 同样地,鄙视商业咖啡、速溶咖啡、茶包的行为其实也挺没品的,开开玩笑挺好玩,较真就挺没意思的。 + +[^2]: 这也是为什么我觉得,网易云音乐上那些把英文歌词翻译成古诗的行为令人作呕,画虎不成反类犬。 \ No newline at end of file diff --git a/content/article/on-wording.md b/content/article/on-wording.md new file mode 100644 index 00000000..0b5df172 --- /dev/null +++ b/content/article/on-wording.md @@ -0,0 +1,119 @@ ++++ +title = "论遣词造句" +slug = "on-wording" +tags = [ "语言", "写作",] +date = 2026-02-17T18:52:20 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/fb44f1b7-57e1-4600-b5f5-e88dd7022007" +url = "/essays/on-wording/" + ++++ + +语言被互联网文化变成了什么样子,在此不必赘述。要求普罗大众都精确用词、尊重文字,其实不太合适,因为即便言之凿凿,也避免不了说教味。本文并不是规范、要求或提倡,只是在规范我自己的文字表达,以及给出一个我眼中的好的遣词造句的标准。我也不纠结文风(相反我十分鄙夷「文采」这一说法),但我在意我写下的词句是否准确和得体,更重要地,能否使人读懂。 + +如果你也赞同我的观点,并打算和我以相似的态度规范自身,我会感到十分欢喜。即便观点不能做到完全契合,我也会将这种差异当作交流的机会。 + +## 个性和风格与用词有关系吗? + +首先要建立起的共识是,用词准确不代表写出呆板、千篇一律、毫无变化的文字。语言的多样性,想必不只是通过用词体现出来的,在用词之上,还有修辞。再深入一些,使用语言的目的是表达想法,而只要想法是多元的,语言也不会同质化得让人觉得无趣。反观,如果一切个性都必须通过哗众取宠的词汇体现出来,恰恰说明了这个人缺少有趣的灵魂。 + +我说的「哗众取宠」的词汇指什么呢?说实话,只需要到一个人员组成足够复杂的简中社交平台上看一看,就能找到大把大把的例子。对网络热词的鄙夷也是陈词滥调了,在此也不多提。其实,我并不反感黑话,前提是在小圈子里说给能听懂的人听,但是在人员复杂的公开平台上,让背景不同、兴趣不同、性格不同的人说同样的话,就显得有些可怕了。在我看来,人们在社交平台上使用此类词汇,一方面是下意识地谄媚,另一方面是为了感到安全。总想说点好玩的话来取悦一整个互联网(或者所有路过某个讨论区的人),想想就不太健康。为了保证失败的概率最低,人们使用大家都喜欢说、都「同意」使用的互联网黑话,牺牲个性和真实的思考,来获得表达的安全感。倘若仍然*不可避免*地失败了,就将对方定义为好事之徒,以便自洽。 + +我跑题了,本文要谈的并不是无法改变的有毒的互联网环境。我观察到,词汇的重复从大的社交平台一直蔓延到了小互联网、文字博客,甚至现实生活。那些愿意留在鱼龙混杂的社交平台上自取其辱的人我并不在乎,但这种风气以某种形式传染到了其他地方,就有点难以接受了。 + +回到这一小节的标题上来,个性和风格与用词当然是有关系的,但并不代表好好说话就会让自己失去个人风格。在我看来,大多数时候,写作者无需在意风格问题,也无需纠结某段文字是否足够「像自己」,借用 [Lawrence Block](https://lawrenceblock.com/) 的说法就是: + +> 形成个人风格的最佳手段是尽力自然而诚恳地写作。构成个人风格的不是刻意为之的文风,不是充满诗意的段落,也不是对文字结构的疯狂追求。写作者无需刻意为之,风格就会自然呈现。 + +{{< right "——《[小说的八百万种写法](/library/2025/小说的八百万种写法/)》" >}} + +因此,完全不必把互联网上乌烟瘴气的那一部分带到写作中来,更不应该带到现实中去。 + +尽管只要诚恳地写作,就无须在意风格问题。所谓的「诚恳」,除了坦诚地表达想法、适当地使用修辞,当然还包括准确地用词,因为诚恳的写作者当然希望读者能够读懂自己写的东西,若用词不精确,这个目的就难以达成。 + +## 什么是精确且诚恳的表达? + +不得不提的是,我观察到人们总是高估其他人和自己的相同点,以为用自己习惯的、见得比较多的表达,其他人就都能听懂。有个人曾经跟我聊天的时候,表达了他对我的不满,他觉得我在跟他抬杠,因为我一直在问他「这个词是什么意思?」,他觉得人人都应该理解这个意思,就算不知道,也能从字面意思上推断。天哪,我的严谨态度竟然变成了傲慢!我只是不想误解他,难道我要装作听懂了自己没听懂的东西,才算是尊重他吗?! + +我必须反驳这种观点,在面对不熟悉的概念时,仅仅从「字面意思上推断」是非常不负责任的行为,继而导致了不少词汇的误用。这种不负责任随处可见,人们不仅高估其他人与自己的共性,还高估自己的理解能力、高估自己的经验。我非常憎恶的是,人们觉得「XXX 是个伪命题」这一表达是正确的,并且广泛地接受了这个错误的用法,甚至在一些官方媒体上都能见到,因为他们从字面意义上推断「伪命题」的含义。查查字典吧!「命题」指的是能被判断真假的想法和论述,而「伪命题」就是假的命题。然而,人们却把「伪」理解成了「伪装」之类的意思,把「命题」模糊为「概念」的同义词,把「伪命题」当作「不存在的概念」「不应有的想法」甚至「骗人的说法」,继而有了「无糖饮料是个伪命题」这种被堂而皇之接受了的病句。 + +总而言之,要做到精确且诚恳,要避免两件事情:一,高估他人与自己的共性;二,高估自己的理解能力。 + +我更偏爱长文而非短文本,原因就在于,长文本可以在行文过程中逐渐建立起共识,如果有人一开始就不同意文中建立起的共识,那这位读者自然知道,后面的内容也不会让他感到满意。人们之所以容易在社交平台上爆发难以调和的争吵(而且很少能吵到点上),原因之一就是共识的缺乏,当然还有前提和论述的缺乏。社交平台适合记录和分享,不适合进行智识交流。依赖相互理解和清晰思考的智识交流需要建立共识。 + +撰写长文,建立共识的过程,就是认清自己与读者有相当多的差异的过程。正是因为有差异,才要在写作时把一切前提都交代清楚,把讨论的基础打好,以便促进理解。这个态度落实到遣词造句上,就是使用最基本的词句表达想法,遇到某些概念时,不吝啬笔墨解释概念。 + +遇到某些特定的概念和词汇,尤其是专有名词,应当查阅可靠的资料了解词汇的意思,而不是从字面意思上推断,然后就拿来用了。更不应该因为经常听到人们使用某个词,就假定这个词真的存在。比如,许多人都以为有「拉丁语系」这个词,事实并非如此,从严格的语言学分类来看,语系是相当大的分类,一般有「印欧语系」「汉藏语系」等,而印欧语系下,有「意大利语族」,这个语族的最大分支名为「罗曼语族」,罗曼指罗马(Roman),这个语族下都是由通俗拉丁语演变而来的语言。显然,「罗曼语族」才是正确的词,而「拉丁语系」则完全不存在。 + +有人可能会反驳:“我又不是语言学者,为什么要了解这么复杂的分类和术语?语言是用来交流的,只要对方能听懂就好了!”我会说:既然不是语言学者,也对语言学没有研究,那就不要乱用语言学的词汇,你完全可以不使用「语系」这个专有名词,直接说「由拉丁语演变过来的语言」,听话人反而更容易听懂。 + +高估自己的理解能力和经验,就会犯这样的错误。使用最基本的词汇,尽可能避免不熟悉的专有名词,才有助于相互理解。简洁不是简短,清晰比聪明更好![^1]这句编程领域的谚语,同样可以用在自然语言上。 + +## 避免欧化的中文 + +我不是在谈什么文化自信,我只相信:中文应该像中文。任何语言都是这样,这也是为什么充满了英语舶来词(还全是用片假名写就的,甚至不如直接写英文)的日语这么令人头大。中文欧化的说法几十年前就有,如今看来问题非但没有好转,反而变得更常见,这里主要分四点来谈。 + +### 1. 无处不在的量词和代词 + +英语里,单数不可数名词前必须有冠词是语法规定,所以 a、an、the 十分常见,指示代词 this 和 that 的出现频率比中文的「这个」「那个」更高。法语里,定冠词 le、la、les 用得也比英语里的 the 更多。在翻译的时候,难免译出很多「一个」「那个」「这种」,然而,很多时候这些词都是累赘,可以删去,不影响表达。 + +比如,「这是一种非常不负责任的行为」,完全可以写作「这是非常不负责任的行为」,除非是为了强调,也可以更进一步地写成「这非常不负责任」。 + +这个错误我经常犯,写着写着就出现好多量词,我也经常使用「这种」「这些」。可能是口癖,如非必要,量词和代词用多了非但不会让表达更精准,还会让句子显得冗杂,降低表意效率。西文里这么用没问题,是因为那些语言的冠词里基本上只有一个音节,而且是非常短的音节,说话时很容易和其他音素连接起来;书写时,由于只有两三个字母,单词之间还有空格,也很容易忽略。可中文就不一样了,上述量词和冠词几乎都是两个音节,而且汉语发音字正腔圆,很难忽视;汉字在书写和排印时,中间没有空格,也不容易跳过。 + +此外,除了表意效率低下,重复也是令人乏味的。如果非要用「这些」,为什么不可以换成「上述」「此类」和别的词呢? + +### 2. 抽象名词和欧化表达的泛滥 + +这个问题是否是欧洲语言的影响,貌似有争议,因为也有西方学者表示,滥用抽象名词的英文写法实际上是…… 中式英语。 + +关于这个问题,我不太能确定自己能否讲清楚。说到底,我的中文也算不上好,缺乏精炼有力的表达,甚至连白话都算不上。去读读鲁迅先生的文字,再随便找本译著进行对比,应该能发现明显的区别。不只是用词,遣词造句的结构都有质的差异。 + +既然我自己讲不清楚,读者读到这里多半也疲乏了,那么我就偷个懒,放两期我认为讲得不错的视频在这里。它们都出自「迷幻枸杞」这位视频博主,你可以在 Bilibili 上观看;如果你在乎隐私的话,可以使用 Invidious(YouTube 的第三方隐私前端)来观看,这里链接的是 [yewtu.be](),Invidious 的公共实例。 + +- 《真相大白:如何根治中式英语?》 [Bilibili](https://www.bilibili.com/video/BV16f4y1C71t) / [yewtu.be](https://yewtu.be/watch?v=FbV912WwLck) +- 《'英文没学好,中文却学坏了' :欧化汉语是什么》[Bilibili](https://www.bilibili.com/video/BV1S34y1D7hp) / [yewtu.be](https://yewtu.be/watch?v=WKZ-S4MtNBs) + +### 3. 多语言混杂 + +如果要证明自己的语言能力,比起在中文里插入英文,不如撰写全英文的文章,或者发表英文演讲。同理,写中文时就应该好好写中文。理想情况下,应该只同时使用一门语言。中夹英完全不利于促成相互理解,不会英语的中文使用者觉得疑惑,有素养的双语者觉得讨厌。总之是不恰当的做法。 + +比较难解决的问题是,如何处理那些难以翻译的英文单词,尤其是专有名词? + +这在软件领域尤为常见。从我有限的经验来看,我在撰写散文和人文社科相关的文章时,基本上能做到只用中文。然而,在撰写技术相关的文章时,我不得不在中文里夹杂英文,比如 JavaScript、Cloudflare、Docker 等等。很多软件、编程语言和技术,都没有广泛接受的中文名。此外,品牌和产品名也是如此,就算可以用「苹果耳机」代指 AirPods,两者给人的印象也是完全不同的。或许可以用苹果电脑代指 MacBook,但如果是更细分的产品线呢?MacBook Pro 难道要写成「苹果电脑专业版」吗?就算大众能接受,品牌方也是不会这样宣传的,中国的科技品牌都很少用中文给品牌和软件起名字。 + +把 Cloudflare 写成「火烧云」,把 ActivityPub 说成「活动酒馆」,把 Webmention 说成「万维网提及」,把 WordPress 说成「文字报社」,在社交时使用很有趣;如果受众是熟悉此类概念的读者,也是不错的幽默,算修辞;可其他时候使用就不合适了。首先,大部分人都不熟悉这些中文译名,让人疑惑。此外,这些名字都有歧义,使用原名才能准确表达,而这正是我们追求的精准用词。 + +所以,重点不是使用什么语言、要不要在文字里夹在另一门语言,而是要考虑怎样才能做到准确且诚恳。 + +### 4. 乱用音译 + +为什么要把 Cheese 译作「芝士」,是忘记有「奶酪」这个词了吗?真要追求高级感,为什么要用烂大街的英语?用法语吧,译成「弗洛麻吉」(fromage),前半部分像个奥地利心理学家的名字,后半部分像个日本动漫角色的名字,可谓是一举三得。 + +Cheese 就是「奶酪」,中文完全有能力不借用英语读音,直接用中文里的词表达 Cheese 的意思,不需要译成「芝士」或「起司」。中国有些地区惯用英语,使用音译词还能理解,但这种说法传播过来,就用欧化中文之嫌。 + +关于中文欧化的问题,还可以读读思果写的《[翻译研究](/library/2024/翻译研究/)》。尽管书本的主要内容是英译中的方法论(比如「Yes」在不同的语境下译成中文,有十多种译法),但也有不少关于「怎么写中文」的内容,毕竟翻译要求的是对两门语言的熟练掌握。 + +## 最后 + +日常表达里的累赘、不自然和堂而皇之犯下的错误,并不罕见。由于几乎人人都会使用语言,错误的语言用例被广泛传播开来也是正常的,没法避免。从词典和标准的修订也能看出知识分子对大众的妥协,比如「坐骑」中「骑」的读音就从 jì 改为了 qí[^2],大概是因为读错的人太多了。 + +互联网的不良用词习惯,大概也值得抨击,但总归没办法要求大众准确用词。最近在读塞涅卡的书信,其中有不少文本都与「哲学与大众的关系」有关,他的观点大概是:既不能与大众走得太远,什么都要反着来;也不能同流合污,面对大众的恶习,要退回到自身当中。 + +我在《[关于肥胖的杂谈](/essays/关于肥胖的杂谈/)》中写过,在公共层面,不对肥胖群体做出恶意的揣测和批评,在个人层面,追求健康的身体。这可以总结为「严于律己,宽于待人」。我想,遣词造句的自律也是如此。大众可以随意玩弄语言,但追求智慧的人对待语言应该有自己的看法。 + +我不是说我在文中提到的标准就是正确的,在我看来,重点在于「开始关注这个问题」,也就是对遣词造句有自己的思考,而不是使用他人都在使用的语言。 + +为此,我打算发起一个 [Slash Page](https://slashpages.net/)[^3],名为 `/glossary`(词汇表)——站长可以在这里写下对用词的思考,描述用语习惯,列出常用词或自己生造的概念,比如「我不喜欢用 AI 这个指代广泛的名词,更喜欢用 LLM(大语言模型)和文生图模型等精确的分类」。撰写这个页面能帮助自己审视语言使用习惯,也能让其他人看到自己的思考。 + +本站的 `/glossary` 页面将会在未来几天发布。如果你喜欢这个概念,也欢迎给你自己的网站添加,写完之后记得告诉我! + +就这样,回见! + +[^1]: 「清晰比聪明更好」的原文是「Clear is better than clever」。这是 Go 语言创始人之一 Rob Pike 的名言之一,也是 Go 语言的设计哲学。 + + +[^2]: 1985 年颁布的《[普通话异读词审音表](https://zh.wikisource.org/wiki/%E6%99%AE%E9%80%9A%E8%AF%9D%E5%BC%82%E8%AF%BB%E8%AF%8D%E5%AE%A1%E9%9F%B3%E8%A1%A8)》规定「骑」字统读为 qí,不再是多音字。不过,台湾和马来西亚貌似还保留了 zuò jì(坐骑)的读法,我用 RIME 输入法也能用 `zoji` 打出这个词。顺带一提,我之前以为「说服」的正统读音应该是 shuì fú,也经历了修订,查阅后发现并非如此,这个词在中国大陆一直读 shuō fú。 + +[^3]: Slash Page 指类似于 `/about` 和 `/now` 的网站页面,位于网站根目录,是个人化的、有特殊意义和用途的页面。 \ No newline at end of file diff --git a/content/article/perfect-day.md b/content/article/perfect-day.md new file mode 100644 index 00000000..b3910be6 --- /dev/null +++ b/content/article/perfect-day.md @@ -0,0 +1,74 @@ ++++ +title = "理想的日常" +slug = "perfect-day" +tags = [ "生活", "健康",] +categories = "乱章" +date = 2026-03-03T07:59:40 +draft = false +toc = true +toot = "https://akk.eltr.ac/objects/6ef07cec-d545-4b59-ab64-6d4dcfaa6ede" +url = "/posts/perfect-day/" + ++++ + +这是我的「[BlogBlog 同乐会 - 2026 年 3 月](https://blogblog.club/party/)」的投稿文章。本月主题是「[理想的日常](https://alexhsu.com/perfect-days)」,由 [Alex Hsu](https://alexhsu.com/) 主持。如果你有自己的博客,欢迎一起来参加! + +--- + +重庆已经到了不需要穿厚外套出门的时候了,总觉得今年的春天来得比以往早。我昨晚三点以后才睡着,今早八点就被阳光叫醒,油腻和不适的感觉裹缠着我的身体。从自己租的房子回到老家之后,生活秩序被打乱,也没有躺在熟悉的床上,总是不能安稳睡去。我记得一个月前收拾行李的时候,恨不得把整个家都搬回去,担心离开之后,住处没有好用的清洁剂、没有好写的笔,担心家里的盆栽会枯萎。 + +寒暑假我都会找点事情做,以便留在学校,因为生活方式的转变是痛苦的,一周还好,如果是一个月,我甚至会说是不人道的。一两个月的时间不长也不短,不够我建立起新的生活秩序(比如,不值得我为此把老家里所有我看不惯的堆满杂物的角落收拾干净),却又超出了我对生活失序的忍受范围。此外,我极度厌恶被他人审视的生活,我还不需要一个做不到忌嘴的糖尿病患者每天都提醒我不要喝冷水——实际上,除非是锻炼后立刻喝冰水,冷水并不会影响健康,喝太热的水反而会损伤食道黏膜。 + +说实话,我觉得固执的老人更像大语言模型,他们局限的生活经验就是语料库,未受教育且倔强难改的思维方式就是模型算法,而他们输出的内容,就算毫无道理,语气也带着他们本不该有的自信。要是我以后变成了一个只说不会做,因为自己生活空虚所以只会窥探别人的生活并且指指点点的老头儿,我希望有人能就地处决我,我该死。处决的光荣执行者,将会是为全人类做出贡献,让世界变得更美好的英雄。 + +好了,牢骚发完了,不依不孝的话也说了。现在,还留在这里的读者们,请允许我为你讲述我理想中的日常。 + +--- + +曾经和现实中认识的人聊天,谈到过「理想的一天是如何度过的?」这个问题,我忘记当时的回答了,唯一还能回忆起的细节是起床的时间。我说,我会在早上八点半起床,当时有人问我为什么不是十点,或者十二点。 + +我说,早晨很安静。 + +记不清从何时起,我不再喜欢睡懒觉,折磨我的生物钟并不令人愉悦。换成现在的我,大概会选择早上七点起床,甚至更早。晚起意味着白天的时间被缩短了,而我并不喜欢晚上我熬夜时的样子。据我所知,那个时候的我根本不会按照计划行事,状态也很差[^1],除非是为了自己有热情的项目赶工,而我们都知道,程序员是不该在晚上把代码提交之后就回去睡大觉的(这句话是 [Paul Graham](/library/2025/黑客与画家/) 说的)。考虑自己的健康和项目的安全,在意志力最薄弱的深夜抵抗继续编码的诱惑,就尤为重要——就算大半夜做完了,也不该提交工作,那还不如第二天早点起来做呢。 + +因为这一两年几乎没有断掉写日记的习惯,有记录自己身体和头脑的感受,也就逐渐在记录中发现,睡眠真的是生活质量的基石。一旦睡不好,我就容易暴饮暴食,运动表现也会明显变差,读书、写作和写代码虽然能够照常继续,但注意力很容易被其他信息夺走。我想,这是因为睡眠影响了认知活动吧。我相信良好的生活应该由七部分组成。 + +![](https://r2.eltr.ac/geedeapro/posts/perfect-day/good-life-pyramid.jpeg "我的良好生活金字塔,记录在我随身的 M5 活页本里") + +良好的睡眠、良好的饮食、规律的运动、大量和广泛的阅读、创造力、安心的关系和平和的心。这七个组成部分自底向上支撑着彼此,在我看来,要是没睡好,就会忍不住食欲、容易感到疲劳,上面的六项也都会垮台。过往的减肥经历告诉我,对健康的体魄而言,吃比动更重要,皮肤问题和情绪问题甚至也可以通过好好吃饭来解决,只不过现代人很少有能够好好吃饭的。规律的运动,指的是提升心肺能力的有氧运动、提升肌肉力量的抗阻力训练,以及提升柔韧性的静态和动态拉伸——只跑步或者只去健身房撸铁,是臃肿且不平衡的,尤其是不应该忽略拉伸,柔韧性是身体最好的盔甲。 + +身体之上,才是头脑。这点我和[塞涅卡](/library/2026/how-to-find-peace/)的观点完全相反,我和他另一个相悖的观点是,他认为阅读应该忠诚于一个作者,而不是走马观花地什么都读,可我认为阅读应该广泛,尽可能了解不同的人对不同事物的不同看法,尤其是那些与我观点不合的人。不过,在我眼中,高质量的阅读应该是基于长文本的,文章或是书籍,短文本和微博客只起到记录、分享和社交的用途。阅读(还要加上「体验」)是对创作者的滋养,是灵感来源,所以创造力要置于其上。对我而言,写作和创造软件,都是创造力发挥作用的领域。 + +头脑之上,又是心灵。上面的图片展示的是我随身携带的「良好生活金字塔」,我还在书房的墙上贴了一个更详细的版本,金字塔的每一层都有更详细的划分,不过,「安心的关系」和「平和的心」这两层是空白的,因为我从未体验过这两者中的任何一个,它们是我无法想象的世界。 + +之所以在开始描写我理想中的日常之前,扯了一大堆没人爱听的理论,是因为我觉得有必要让读者知道我对良好生活的标准是怎样的,目的是建立起共识,以免后文显得突兀。*我要是让读者毫无准备地了解到我每天都会把自己的身体掰来掰去,把脚放到头后面去,我认为是会令人感到措手不及的。* + +--- + +回到我的想象。现在是早上七点,日光透过窗户打在我的脸上,不早不晚,正好我把从一个睡眠周期刚结束时叫醒,此时我的头脑很清醒,完全没有起床困难症。我换好衣服,到吧台给自己倒了一杯热水,喝完之后又倒了一杯,很快我的肠道也开始工作,没过多久就进了厕所,并且在两分钟内走了出来,现在身体很轻盈。我洗完手,开始给自己冲咖啡。理想情况下,我是不需要咖啡因来提神的,但至少对现在我的来说,给自己冲咖啡这个动作是我生活的支点。我总觉得,早上要喝的应该是中度或深度烘焙的咖啡,没有太多需要我细细品味、扰乱思绪的风味。 + +此时我应该能够忍住查看社交媒体和电子邮件的欲望,开始对照前一天晚上列好的待办清单工作。从七点半或八点开始,直到早上十一点左右,我应该就完成今天需要做的所有事情了。据说对于脑力工作者而言,早晨是效率最高的时间段,我自己的感受也的确如此。如果能在头脑最清醒的早晨不受打扰地完成所有工作,剩下的时间就可以留给兴趣爱好、朋友和恋人了(是的,既然是理想的日常,那我应该有一个恋人),并且不会在这些时间里受工作打扰,把生活的秩序搅得一团乱。 + +十一点半左右,我应该出门赴约中午的饭局。我理想中的内层交际圈,或者说最亲密的那些朋友,他们的数量加上我应该是四人。在四个人的局里,不需要有人一直说话带动气氛,也很少出现其他人话太多导致某一个人插不上话的情况,最安静的人也能在这样的场里待得很舒服,前提是四个人中没有话痨。此外,有很多我喜欢的桌游,玩家数量上限是四人。唔,如果要谈理想的话,这四个人之中,有一个应该是我的男友,不过,我真的很难想象他是什么样子呢。 + +在某些日子里我可能会和朋友们去桌游店一直玩到晚上,甚至一起在店里点外卖吃饭。桌游比起电子游戏,给我带来的互动感会更强,但也不至于像其他聚会游戏那样过于亲密。不过,在这个理想的一天中,滥用时间是不明智的。吃完午饭后,我就应该和朋友们分开,回到家里给自己冲当天的第二杯,也是最后一杯咖啡。午后的咖啡应该是浅度烘焙的,日晒处理法,有浓烈的水果或花香,在降温后有持续的茶感,可以品味好久。 + +口腔中还有咖啡的回甘,我开始查看联邦宇宙和 RSS 更新,照顾我的另一个交际圈,看看离我很远的其他地方发生了什么事情。然后是查看电子邮件和即时通讯软件的消息,这个时候我应该收到一些我关注的产品和游戏的新闻报、一些读者的留言、一些求助或询问、联系紧密的网友的消息,这些消息加起来应该不会给我造成太大的负担,不会让我产生推迟到第二天再处理的倦怠感。这些与真实的人的连接应当是令人愉悦的。最后,我会选择一些内容,放到下一期的周刊里。 + +当我从网络中抽身后,时间应该是下午四点半左右,此时我在电视机前铺好了瑜伽垫,开始当天的锻炼。在这个理想的一天中,我的训练计划应该恰好没有排到力量训练,而是比较轻松的有氧(虽然做 HIIT 也不算轻松,但会让人觉得快乐),结束后略作休息,就开始十五分钟的拉伸,拉伸完毕后是洗澡,此时我的身体应该像刚出生的婴儿一样舒适。梳洗好自己过后,时间是五点半左右,应该开始准备晚餐了。 + +同样地,在别的日子里,我可能会从零开始买原料,做好几道工艺繁琐的菜,但在这个理想的一天里,冰箱里应该有一些容易处理的食材,或者其他人给我送来的,亦或是我自己提前做好的餐食,稍加处理之后,应该就能在六点左右摆上足够丰盛的晚餐。用餐时,我会和男友一起看《老友记》或者《瑞克与莫蒂》——是的,在理想的日子里,新片子是不被允许的。 + +晚餐后很适合散步消食,两个人要是能在江边或者海边漫游,应该会很浪漫。我有时会觉得,走出家门散步才是真正的旅行,因为没有行囊,甚至连手机都可以不带,身上没有任何负担,心灵上没有任何束缚,两个人之间也没有任何枷锁,只是在呼吸着、行走着、生活着。漫步也是思考和交谈的绝佳时间,可以消化和整理当天发生的事情,兴许是在餐桌上朋友的小动作,或者是互联网上的见闻。一个人思考可以整合认知,两个人交谈,则可以提供情绪支持,总之是很健康的处理信息的方式。此时路边应该会有跑步的人路过,如果是长相不错的男性,我和男友会有些不道德地一起欣赏,至少在我的想象里,这是作为同性恋者的好处之一。 + +回到家时大概接近八点了,这个时候我会回到书房里读书,兴许是一本觉得不错,便继续往下读的新书,或者是一本觉得很棒,所以捡起来重读的旧书,又或者,是一本初见便爱上的书,一边读一边想象自己几年后再次打开这本书重读时的感受,这本书的名字或许是《不可承受的生命之轻》。或许,在那个理想的日子里,我会庆幸自己早已体会过了生命中的轻与重、灵与肉,不会陷入托马斯、特蕾莎和萨比娜的苦痛。矛盾的是,在我的想象里,那时的我依旧年轻。 + +放下书本后,我会开始写作,但愿博客的名字还叫「极客死亡计划」,也但愿我能在上床之前发布文章,因为我不喜欢把草稿晾在 Git 仓库里的感觉。兴许这是一篇前几天写完了一半的草稿,又或许我写得十分顺畅,不需要做太多考究也不需要斟酌,只需要倾泻所思。合上电脑后,我会开始写日记,并依照周计划,写下第二天的待办清单。此时的时间应该是十一点,我钻进了被窝,依偎在爱人的怀抱里睡去。 + +只可惜,时间好像有些不够用呢。读书与写作这两件事情,对我来说是没办法在一两个小时内完成的。如果我没办法在不压缩睡眠的情况下做完我想做的事情,这又怎么能叫作「完美的一天」呢?我不禁思考,这样理想的日常,真的存在吗? + +不过理想就是因为不能存在于现实中,才有美感吧。 + +是时候回到现实中的生活了。 + +[^1]: 事实:凌晨四点时大脑的状态比喝醉了酒还要差。 \ No newline at end of file diff --git a/content/article/prejudice-of-college-education.md b/content/article/prejudice-of-college-education.md new file mode 100644 index 00000000..e8281d73 --- /dev/null +++ b/content/article/prejudice-of-college-education.md @@ -0,0 +1,141 @@ ++++ +title = "教师的傲慢 II" +tags = [ "教育",] +categories = "人类观察日志" +date = 2025-12-25T14:47:00 +draft = false +toc = true +slug = "prejudice-of-college-education" +aliases = [ "/essays/教师的傲慢-ii/",] +url = "/essays/prejudice-of-college-education/" + ++++ + +我在大学的前两年都是个很守纪律的学生,从来没有逃过课。一方面,我不想因为违纪给我带来不必要的麻烦,消耗心力;另一方面,自己毕竟还是学生,在脱离这个身份之前,课还是要上的,而且,大部分的课程其实还没有到难以忍受的地步。 + +不过例外总是有的。 + +## 在老旧的技术栈里坐井观天 + +专业开设了两门和前端开发相关的课程,一门叫做「Web 前端开发」,授课内容就是 HTML 和 CSS,和 JavaScript 相关的内容很少;另一门叫做「JavaScript 框架和 SPA 技术」,授课内容是 Vue 3 和相关的技术栈(谢天谢地你讲的不是 React)。前者我在初中买过一本书自学过,那本书所属的系列还有一本 JavaScript 和 jQuery 的教程,我也买来读过[^1];后者我在大学期间自学过,不过,就算没有学过 Vue,我对 React 相关的技术栈也比较熟悉。在我的整个高中生活里,我的周末和夜晚几乎都用来折腾各种前端框架了。 + +这两门课都是同一个老师教的,学校里显然没有别的会前端的老师了。像其他*目光短浅*的开发者一样,我所在的环境里几乎没有人重视前端开发,从学生到老师都是如此。课程的内容不是最大的问题(虽然问题也不小),最大的问题是授课的老师对他理应掌握的知识所展现出的*惊人的*匮乏。我从没见过他打开浏览器的开发者工具(也就是按下 Ctrl/Command + Shift + I 或者右键菜单的「审查元素」会打开的面板),他排查问题的方式是用肉眼盯着源代码看,而且是通过右键菜单点开「查看源代码」来排查的——当课程内容转向 Vue,浏览器里的源代码视图只会显示页面基本框架和用于加载 Vue 的 JavaScript 脚本,他也就没办法在浏览器里排查问题了,就只会盯着 VS Code 的界面看,还要学生来提醒他哪里写错了。[^2] + +作为开发者,这位老师对命令行工具的使用也不熟悉得令人发指。一般而言,创建一个基于 Vue 的前端项目框架,开发者会使用 `bun create vue`[^3] 这样的命令,拉取到相关的软件包之后,就会出现交互式的终端界面用于配置开发环境。这位老师的「不熟练」体现在两点,当然还有其他尚未发现的。 + +第一,他教学生不要使用 PowerShell,要使用 `cmd`,还教学生如何在 VS Code 中把终端切换为 `cmd`。即便我是 macOS 用户,我也知道,要运行 Node.js 相关的技术栈,`cmd` 这种老古董是不如 PowerShell 好使的。他这样教学生的理由是(以下是他的原话):「使用 PowerShell 呢,路径会有一些问题」我不知道他说的是什么路径问题,但我肯定那是他自己的无知导致的。 + +第二,我已经记不清楚他有几次课在课上这样讲到:「首先呢,我们要把 Vue 项目里的示例代码都清除掉。把 `