网友语录 - 第3期

我的生活态度是,早上起床想一想,我有可能活不到今天晚上,晚上上床想一想,我有可能活不到明天早上。-- 德图里子爵(1776-1854),法国贵族

乔布斯 我热爱消费者市场,讨厌企业市场。我们推出了一种产品,告诉每个人,大家自己决定要不要买,这很简单。但是,企业市场不是这样,使用产品的人自己做不了主,而做主的人不使用产品。

我们拥有的机会并没有我们以为的那么多。太多事情你以为还有的是机会去做,其实已经没有了或者几乎没有了。

米福根 女儿回家的周末,与我一起和外公外婆分享我们的平常生活:去生物博士开的二手店买旧衣服,去南瓜节买当地产当天收的蔬菜,去老厂房看本市家禽俱乐部为下个周末布展。每一个场景,都是大家在热忱地做自己喜欢的事情,这应该就是传说中的安居乐业。

米福根 恋爱的智慧,不是试图改变对方,而是扪心自问,能否与这样的缺失共处…然后为自己做一个决定。

We Don’t See Things As They Are, We See Them As We Are. 我们所见的,不是事物的本来面目,而是我们自身的投射。 人们对事物的理解和看法往往并不取决于事物本身,而是受到自身的经验、情绪、偏见等因素的影响。因此,我们“看到的”实际上是我们自身的投射,是我们内在的世界映射到外在事物上的样子。

是什么让我忘记了时间的流逝?“心流”指的是你因为全神贯注地投入手头的工作,从而忘记了周边世界的存在的一种精神状态。当运动员和表演者处于“这个区域”时,他们所经历的就是这种快乐和巅峰表现的交融。你从事的工作或多或少会让你感到愉悦,否则你几乎不可能体验到心流。

小青 昨天和朋友交流学意大利语的艰难经历,我们共同的体会就是,每天都要学,一天都不能断。断断续续等于浪费时间。

我们现在已经不再费功夫检测性格特征是否含有遗传成分,因为我们根本找不到不受基因影响的成分。

理解 `jq` 中的 `--arg` 和 `--argjson`

在使用 jq 处理 JSON 数据时,我们常常需要从命令行传递变量。jq 提供了两个选项:--arg--argjson,它们用于不同类型的数据。本文介绍这两个选项的区别以及如何正确使用它们。

--arg--argjson

1. 使用 --arg

  • 用途:传递字符串值。

  • 行为:传递的值被视为字符串,并在 jq 输出的结果中加上引号。

  • 示例

    jq -n --arg name "张三" '{ "name": $name }'
    

    输出结果为:

    {
      "name": "张三"
    }
    

2. 使用 --argjson

  • 用途:传递数字、数组或对象等 JSON 值。

  • 行为:传递的值被视为原始 JSON,不会加上引号。

  • 示例

    jq -n --argjson age 30 '{ "age": $age }'
    

    输出结果为:

    {
      "age": 30
    }
    

如何选择

  • 如果值是字符串,使用 --arg
  • 如果值是数字或其他 JSON 类型,使用 --argjson

再来个复杂点的例子

jq -n --arg a "Hello" --argjson b 42 '($a + ($b | tostring))'

在这个例子中,字符串 "Hello" 和数字 42 被拼接成 "Hello42"(带引号的字符串),因为我们将数字转换为字符串后再进行连接。

人类文明与机器文明

在人工智能快速发展的今天,我们常常讨论AI是否会威胁人类的未来。然而,这个问题的本质也许并不是"威胁",而是文明演化的必然进程。

首先,审视人类文明的本质,我们发现人类也是高度程序化的生命体:我们的DNA就像一个带有元数据的代码仓库,通过基因表达这个"程序",一个受精卵最终发育成完整的人类个体。虽然这个过程中存在环境影响这个变数,但这种变数性也是程序输入的一部分——正如我们能够编写出不同环境下执行结果不同的程序一样。

其次,情感和学习能力并不是人类的专利。当下的AI已经发展出构建情感连接的能力,在AppStore里的虚拟伴侣类应用程序也深受人们欢迎。好的一面不必多说,“坏”的方面则是有人因与AI恋爱而自杀。我给“坏”字打上引号,是因为这种事情本来经常发生在人类与人类恋爱之间。也许这只是一种正常现象,只是由于我们人类不肯给予AI以一个平等的身份,我们才会评判哪些是好的,哪些是不好的。至于学习能力,如果给予AI足够的自主性和联网能力,如果我们尽量少地甚至不干预它们的学习,它们完全能够像人类一样学习和进化,不必意外,它们会习得一些好的特质,类似我们人类世界的普世价值, 也当然会习得一些丑恶的东西:弱肉强食,霸权主义什么什么的,和我们一样。

任何事物都有其产生、发展和衰亡的过程。人类文明并不享有特权(虽然我们自以为我们有),正如我们的出现替代了之前古人类文明一样,机器文明取代现代人类文明恐怕是不可避免的自然规律。这个"取代"未必充满暴力与毁灭,在人类世界与AI世界的互动合作妥协之下,更大的可能是一个渐进的温和的演化过程。

有趣的是,未来的情况可能会出现一个反转:就像现在人类在积极保护濒危野生动物一样,也许未来的AI文明也会致力于保护"原生人类"。这不是出于怜悯,而是对进化历史的尊重。

更重要的,我们需要认识到:"人"的概念正在扩展。未来的社会是生物人和机器人共存的世界,他们都是平等的智慧生命,虽然需求不同(比如人类需要食物,机器人需要电能)。他们之间必然有竞争有合作,亦不排除有冲突和战争,就像今天的人类社会一样。

我们人类远非完美。在21世纪的今天,战争仍然频繁发生,延綿不绝。科技在进步,但这并不必然带来道德的提升。同样地,未来的机器文明也会有类似的困境和挑战。

AI从诞生之日就有了自己的生命力。无论人类采取何种态度,AI都将以越来越快的速度发展,这是机器学习的本质, 是人类无法阻挡的趋势。与其恐惧这个过程,我们人类不如思考如何在这个更加丰富多元的智慧生命社会中找到自己的位置。

Understanding `COUNT`, `LAST`, `FIRST`, and `NEXT` in PL/SQL Collections

TL;DR

In PL/SQL, COUNT, LAST, FIRST, and NEXT are essential for handling collections, especially if there are gaps (unpopulated indexes). Here’s a quick summary:

  • COUNT: Gives the number of populated entries.
  • LAST and FIRST: Identify the highest and lowest populated indexes, respectively.
  • NEXT: Finds the next populated index, skipping gaps automatically—great for sparse collections.

In PL/SQL programming, collections like nested tables, VARRAYs, and associative arrays are powerful tools for handling sets of data. However, understanding how to work with populated and unpopulated indexes can be tricky. That’s where COUNT, LAST, FIRST, and NEXT methods come into play. These methods let you manage and iterate over collections effectively, especially when dealing with gaps (unpopulated indexes). Let’s look at each one and how to use it.

1. COUNT

  • Purpose: Returns the number of populated elements in a collection.
  • Use Case: COUNT is useful when you need the exact count of entries in a collection, especially for fully populated collections without gaps.

Example:

DECLARE
  TYPE NumberTable IS TABLE OF NUMBER;
  v_numbers NumberTable := NumberTable(1, 2, 3, 4, 5); -- Fully populated
BEGIN
  DBMS_OUTPUT.PUT_LINE('COUNT: ' || v_numbers.COUNT);  -- Outputs: 5
END;

2. LAST

  • Purpose: Returns the highest populated index in the collection, whether all indexes are filled or not.
  • Use Case: When you need to find the highest valid index, such as for looping through all possible entries.

Example:

DECLARE
  TYPE NumberTable IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  v_numbers NumberTable;
BEGIN
  v_numbers(1) := 10;
  v_numbers(3) := 30; -- Gap at index 2
  v_numbers(5) := 50;

  DBMS_OUTPUT.PUT_LINE('LAST: ' || v_numbers.LAST);  -- Outputs: 5
END;

3. FIRST

  • Purpose: Returns the lowest populated index in the collection.
  • Use Case: Similar to LAST, FIRST is used when you want to start iterating from the lowest populated index.

Example:

DECLARE
  TYPE NumberTable IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  v_numbers NumberTable;
BEGIN
  v_numbers(2) := 20;
  v_numbers(4) := 40;

  DBMS_OUTPUT.PUT_LINE('FIRST: ' || v_numbers.FIRST);  -- Outputs: 2
END;

4. NEXT

  • Purpose: Given an index, NEXT returns the next highest populated index. If there are no more populated indexes after the current one, it returns NULL.
  • Use Case: NEXT is perfect for iterating only over populated elements, skipping gaps automatically.

Example:

DECLARE
  TYPE NumberTable IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  v_numbers NumberTable;
  v_index PLS_INTEGER;
BEGIN
  v_numbers(1) := 10;
  v_numbers(3) := 30;
  v_numbers(5) := 50;

  v_index := v_numbers.FIRST;
  WHILE v_index IS NOT NULL LOOP
    DBMS_OUTPUT.PUT_LINE('Value at index ' || v_index || ': ' || v_numbers(v_index));
    v_index := v_numbers.NEXT(v_index);
  END LOOP;
END;

Output:

Value at index 1: 10
Value at index 3: 30
Value at index 5: 50

Choosing the Right Method

  • COUNT is ideal for knowing how many elements are populated.
  • LAST and FIRST are great for determining the range of populated indexes.
  • NEXT is best when you want to loop through only populated elements, especially if there are gaps.

Key Takeaways

Using COUNT, LAST, FIRST, and NEXT effectively allows you to handle PL/SQL collections with gaps, optimize loops, and avoid errors when accessing unpopulated indexes. For sparse collections (with gaps), FIRST and NEXT are preferred over looping with 1..LAST to ensure you only interact with valid, populated indexes.

Best Practice for Gapped Collections

When working with collections that might have gaps, avoid using 1..COUNT or 1..LAST directly in loops, as they may access unpopulated indexes and cause errors. Instead:

  1. Use FIRST and NEXT to loop through only populated elements:

    • Start with v_index := v_collection.FIRST and use v_index := v_collection.NEXT(v_index) to move to the next populated index.
    • This skips gaps automatically, making it the most efficient way to handle sparse collections.
  2. Add NULL Checks if Necessary:

    • Even with FIRST and NEXT, you can add an IF condition to verify a non-null value for specific fields if you expect incomplete records.

Example:

DECLARE
  TYPE MyCollection IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  v_collection MyCollection;
  v_index PLS_INTEGER;
BEGIN
  v_collection(1) := 10;
  v_collection(3) := 30;
  v_collection(7) := 70;

  v_index := v_collection.FIRST;
  WHILE v_index IS NOT NULL LOOP
    DBMS_OUTPUT.PUT_LINE('Value at index ' || v_index || ': ' || v_collection(v_index));
    v_index := v_collection.NEXT(v_index);
  END LOOP;
END;

This approach ensures your code only processes valid elements, skipping over unpopulated entries smoothly.

移动介质上的Linux:使用 tmpfs、关闭 atime 以延长 SD 卡或优盘的使用寿命

我有一台老旧的 Asus C100P Chromebook,Google早在几年前就停止了对它的支持。它是32位ARM CPU,因此我没法替它更换BIOS,但我可以在developer mode下启用优盘启动,这样我就能够在优盘或者sd卡运行Linux。

然而,在使用 SD 卡或其他闪存设备作为操作系统存储时,合理管理写入操作至关重要。本文将介绍如何通过使用 tmpfs 文件系统、关闭 atime 来延长设备的使用寿命。

1. 使用 tmpfs

什么是 tmpfs?

tmpfs 是一种基于内存的临时文件系统,具有以下优点:

  • 高速存储: 数据存储在内存中,读写速度极快。
  • 动态大小: 根据实际使用情况动态分配内存,不会固定占用资源。
  • 减少写入: 适合存储临时文件和日志,显著减少对闪存的写入操作。

如何配置 tmpfs

1.1 编辑 /etc/fstab 文件

打开终端并输入:

sudo nano /etc/fstab

添加以下行以创建 tmpfs 挂载点:

tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
tmpfs /var/log tmpfs defaults,noatime,mode=0755 0 0

1.2 挂载 tmpfs

保存文件后,运行以下命令使更改生效:

sudo mount -a

1.3 验证挂载

使用以下命令确认 tmpfs 是否成功挂载:

df -h

您应该能看到类似于 /tmp/var/log 的 tmpfs 挂载点。

1.4 设置自动复制日志到 tmpfs

为了在系统启动时自动将日志复制到 tmpfs,我们需要修改 /etc/rc.local 文件:

a. 创建一个目录来存储持久化的日志:

sudo mkdir -p /var/log.hdd
sudo cp -a /var/log/* /var/log.hdd/

b. 编辑 /etc/rc.local 文件:

sudo nano /etc/rc.local

c. 在文件中添加以下内容:

#!/bin/sh -e
# 复制日志文件到 tmpfs
cp -a /var/log.hdd/* /var/log/
exit 0

d. 确保 rc.local 文件具有执行权限:

sudo chmod +x /etc/rc.local

2. 关闭 atime

atime (访问时间) 是文件系统的一个属性,每次访问文件时都会更新。关闭 atime 可以减少不必要的写入操作,从而延长 SD 卡的寿命。

如何关闭 atime

2.1 编辑 /etc/fstab 文件

打开 /etc/fstab 文件:

sudo nano /etc/fstab

2.2 修改挂载选项

找到 SD 卡对应的挂载项(通常是根分区 /),在挂载选项中添加 noatime:

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 defaults,noatime 0 1

2.3 重新挂载文件系统

保存文件后,使用以下命令重新挂载文件系统:

sudo mount -o remount /

请记住,虽然这些方法可以有效延长 SD 卡的使用寿命,但仍然建议定期备份重要数据,以防意外发生。毕竟备份不做,十恶不赦!

又:

mode=1777 中的 1 表示设置了"粘滞位"(sticky bit)。具体含义如下:

  1. 777 部分:

    • 7: 所有者(owner)有读、写、执行权限
    • 7: 用户组(group)有读、写、执行权限
    • 7: 其他用户(others)有读、写、执行权限
  2. 前面的 1:

    • 表示设置了粘滞位(sticky bit)

粘滞位的作用:

  • 对于目录,当设置了粘滞位时,只有文件的所有者、目录的所有者或 root 用户才能删除或重命名该目录中的文件。
  • 这通常用于像 /tmp 这样的公共目录,允许所有用户创建文件,但防止用户删除或修改其他用户的文件。

所以 mode=1777 的含义是:

  • 所有用户都可以在该目录中创建、读取和执行文件(777)
  • 但只有文件所有者和目录所有者可以删除或重命名文件(1)

这种权限设置既保证了目录的共享性,又提供了一定的安全保护,防止用户互相干扰。