Mccranky's Blog

Turn On, Boot Up, Jack In

作为留美研究生,我的课余时间大多耗在了攀岩俱乐部里。在岩壁下给双手打着镁粉,与新结识的同好交流攀登路线时,总会遇到那个无可回避的问题:“Where are you from?”

每当这时,我都会不假思索地回答:“Shanghai.”

这并非单纯的地理定标,而更像是一种精心算计过的、带点无奈的文化防御。在这个简短的回答背后,藏着一句没有说出口的潜台词:请将我视作一个拥有契约精神、懂得边界感的现代人,而不是那个庞大、喧哗且面目模糊的集体中的一员。

如果碰巧,你能用毫无口音的英语与对方交谈,你能明显察觉到对方眼底那层天然戒备的消融。然而,这种消融带给我的,往往不是庆幸,而是一丝深沉的悲哀。因为这种对“无口音”和“得体”的执念,本质上是一种近乎绝望的伪装。我们在试图用力擦洗掉一种不属于自己的集体底色。

这总让我联想起《人间失格》英文版译者在附文里写下的那种困境。明治以来的日本拼命想要“脱亚入欧”,渴望被当作现代文明的一部分,但无论怎么模仿,西方审视他们的目光里,依然死死贴着“亚洲”的标签。 今天的我们,同样身处这种巨大的身份错位中。我们认同普世的秩序,欣赏发达社会的整洁与体面,试图在精神上完成一次个体的突围。但现实是,无论你多么努力地展示文明的素养,只要身处国际社会的宏大语境下,你依然要为某些你不认同的粗鄙和战狼式的傲慢买单。

而更残忍的撕裂,发生在转身面对故土的时刻。

这几年的周遭,正被一种粗糙的仇恨教育和排外情绪所笼罩。当你试图保持常识的清醒,拒绝去盲目仇恨那些你明明觉得值得学习的社会时,你便成了同胞嘴里的“精外”与“汉奸”。这是一种极其荒谬的倒错:你仅仅是因为向往更文明的生活方式,就被粗暴地开除了爱国的资格。 在国际上,你因为无法选择的出身而被防备;在故土上,你又因为自己选择的清醒而被排斥。这成了我们这一代人最尴尬的处境。

最终,我们既无法彻底融入彼岸的认同,也再难附和此岸的狂热。那些识时务的年轻人,渐渐变成了游荡在两种叙事夹缝里的“精神侨民”。我们别无他法,只能在心里牢牢守住那座名叫“文明”的孤岛,在看透了周遭的藩篱之后,孤独、但必须体面地活着。

出生在上海,五岁前长在海门的三厂镇,这是我认知的起点。后来跨过大洋,吹过科罗拉多的风,走过纽约和波士顿的街头。年少的眼睛看世界,大多是走马观花,直到高一那年去了新加坡。

五天不长,却让我凭空生出一种置身佛罗里达的错觉。明明也是黄种人熙攘的亚洲,骨子里透出的却是一种被精心打理过的现代秩序。它比美国安全,更比此时的故土干净。那种干净,不仅是街道上没有随处可见的痰迹,更是一种没有暴戾之气的社会底色。

真正让我在异乡品尝到“故乡感”的,是大四毕业旅行时的日本关西。大阪的临海气息与市井烟火,像极了剥离掉浮躁和傲慢后的上海;京都连绵的群山,满是浙江丘陵的轮廓;而当我坐在开往奈良的电车上,看着窗外富饶的田地、泾渭分明的小路和疏落的村镇时,我脑海里浮现的,竟是海门的影子。

只是,奈良比海门更干净,也更体面。

这种体面,像一面澄澈的镜子,照出了我们狂飙突进背后的狼藉。这几十年,我们造了最密的高铁和最高的大楼,却在“效率至上”的狂热里,默许了道德教育的长期缺席。在许多地方,素质成了丛林法则里最无用的东西,传统的温良恭俭让,被视作软弱的代名词。制度上的某些根本性缺陷,让人们在内卷中相互消耗,急功近利填满了社会的缝隙。我们拥有了庞大的躯体,灵魂却依然在泥沼里打转。

但我依然对这片土地抱有渴望。我不去幻想某种宏大叙事下的全面腾飞,我只看我生活过的地方。

长三角本就有足够的底蕴。如果未来的二十年,我们能从一味追求做大的狂热中冷静下来,去缝补那些制度的漏洞,去重新拾起对人的教化,去巩固一个现代公民应有的底线素养,一切并非不可挽回。

到那时,海门完全可以成为下一个奈良,上海也理应拥有大阪那般的从容。差距依然横亘,痼疾绝非朝夕可改。但在那趟开往奈良的列车上,我确乎看清了故乡脱胎换骨后,原本可以拥有的模样。

5岁前我在海门,和外公外婆一起生活,6岁回到上海。如今,海门话对我而言,变成了一截隐隐作痛的幻肢。我能听懂,口腔肌肉甚至还记得发音的位置,但每当试图开口,意识却怎么也拨不通那串输出的号码。这在语言学上叫“被动双语”,但在我心里,这叫剥夺。

作为00后,我们这代人的普通话标准得毫无破绽,这是宏大叙事的一场全胜。从小,校园里的方言是被隐秘地“污名化”的。我至今记得,小学老师平时讲着标准的普通话,只有在勃然大怒、甚至体罚学生时,才会飙出上海话。在这种潜移默化的心理规训下,方言与“粗鄙、失控”画上了等号,我们在潜意识里,自动完成了对家乡话的抵触与阉割。

这种母语的断裂绝非偶然。语言从来不仅是沟通的工具,它是凝结同乡认同的粘合剂,是一道抵御权力渗透的文化护城河。当方言被强制从校园和家庭的堡垒中驱逐,一种基于地域的民间凝聚力便随之瓦解。推普的推土机铲平了语言的沟壑,也顺手将复杂的社会结构,碾压成了便于管理的、平庸的原子化沙盘。失去了共同的乡音,我们就成了流水线上规格统一、却不知来处的产品。

极具讽刺意味的是,我是通过学习英语,才真正读懂了母语消亡的悲剧。外语的介入重塑了我的思维方式,让我恍然大悟:语言中那些感性的“nuance”(细微差别),是无论多么精准的翻译都无法替代的。普通话像一台轰鸣的工业烘干机,抽干了方言里湿润、暧昧且鲜活的市井温度。那些只属于海门江风或上海弄堂的情感密码,一旦失去时间的积累,就会变成永远无法破译的死语。

我时常感到愤怒,这种愤怒是对文化根脉被强行折断的本能痛感。但愤怒,也是觉醒的开始。我庆幸我的口腔肌肉还保留着那一点微弱的发音本能。在一个高度标准化的时代,拒绝遗忘,本身就是一种微小而坚韧的反抗。

我的方言还在那里。那不仅是乡音,那是我的灵魂指纹,是我绝不交出的最后一块主权。

近来,关于天朝二三线城市年轻人的讨论颇多。从表面上看,他们是不再困于温饱的一代,享受着比乡村更好的物质条件,每天在互联网和流媒体的碎片信息中浸泡。但令人困惑的是,这种物质的改善与技术的普及,并没有带来精神世界的开放。相反,在一个缺乏真实国际视野的半封闭生态里,滋生出了一种极其吊诡的群体性格——既盲目自大,又在道德上极度“双标”。

如果你用现代文明的常识去审视,这种现象其实并不突兀,它恰恰是天朝这几十年来社会工程结出的必然之果。互联网在这里并没有成为接轨世界的桥梁,反而成了算法圈养和宏大叙事洗脑的围栏。在这个信息茧房里,缺乏跨文化现实碰撞的年轻人,很容易把无知当个性,习惯于站在道德制高点上去审视他人,却对自身的行为毫无底线。这种“严以待人、宽以律己”的狂欢,本质上是传统熟人社会解体后,现代公民责任未能建立而留下的道德真空。

更有意思的是,抛开当下经济下行的现实压力不谈,这代人对结婚生子表现出了前所未有的排斥。他们热衷于当下的“快活”,对所谓延续家族和抚养后代的使命感嗤之以鼻。

这其实是一场历史的宿命。正如我们常看到的,天朝有着极强的“控制能力”,却极度缺乏现代意义上的“治理能力”。为了建立这种自上而下的绝对控制,官府自建政以来,通过连番的政治运动,系统性地摧毁了以家族、乡绅和儒家伦理为基础的传统民间自治结构。那些曾经维系中国人精神内核的“传统美德”,早就在权力的碾盘下化为齑粉。

紧接着,长达三十多年的计划生育政策,又从微观上彻底重塑了家庭。一个从小被视为绝对中心、习惯了单向索取的“原子化”个体,怎么可能在成年后,突然生出牺牲自我、去承担繁衍责任的使命感?

所以,当我们看到这些以自我为中心、拒绝生育、精神世界高度封闭的年轻人时,不能仅仅归咎于个人的自私。这是制度与国民互为因果的绝佳样本。他们失去了传统宗族社会的敬畏心,又被阻挡在现代公民文明的门外;他们被剥夺了历史的厚重感,最终只能在消费主义的奶嘴中寻找虚无的寄托。

这一切,或许正是那个反常识的体制,在狂飙突进几十年后,不得不面对的社会残局。

Every day, the human brain is tasked with processing a massive, chaotic influx of social data. To navigate this overwhelming reality, the mind must inherently act as a predictive algorithm. However, just as in machine learning, the algorithms we choose to run in our social interactions dictate the accuracy—and the morality—of our worldview. When we examine the phenomenon of stereotyping through the lens of computer science, it becomes clear that prejudice is not merely a moral failing; it is a symptom of cognitive underfitting.

At its core, a stereotype is a “low-compute” heuristic. It operates much like a Naive Bayes classifier. Because the human brain has limited processing power, it relies on heuristics as slacks to make constant-time, O(1) judgments. By compressing a complex human being into a few highly weighted, discrete features (such as age, gender, dress code, or subculture), the brain establishes a binary baseline. For everyday survival or minimal social navigation, this low-resolution model “gets the job done.” It draws a massive, straight line through a wildly scattered dataset, purposefully ignoring the outliers to save mental CPU.

But saving compute comes at a severe cost. When a model is aggressively regularized to ignore complexity, it underfits the data, leading to a high rate of false positives and false negatives. In social dynamics, we call this misclassification prejudice. By leaning on these generic, binary parameters, we dull our moral compass. We ignore the very real “cost function” of our errors—the human damage done when we strip an individual of their nuance and force them into a static, pre-calculated bucket.

For those educated in logic and systems thinking, relying on such a crude baseline is computationally unacceptable. If stereotypes represent an underfitted linear model, the logical upgrade is to process social interactions much like a Support Vector Machine utilizing the Kernel Trick.

A naive classifier looks at a person in a two-dimensional feature space—perhaps judging them purely on appearance and accent—and clusters them with everyone else who shares those traits. But an SVM-style thinker projects that data into a much higher-dimensional space. By feeding the model dozens of continuous variables—intellectual curiosity, emotional intelligence, conflict resolution style, moral consistency—the “stereotype” dissolves. Two individuals who appear identical in a low-dimensional binary space are suddenly revealed to be miles apart in the high-dimensional space of their actual character.

Furthermore, an SVM handles non-linearity. It recognizes that human behavior rarely follows a straight line. A person can simultaneously hold seemingly contradictory traits, requiring a complex, dynamic decision boundary rather than a rigid binary box.

Ultimately, rejecting stereotypes is not just an exercise in social etiquette; it is a commitment to data fidelity. To rely on stereotypes is to accept an intellectually lazy algorithm. To understand people accurately requires us to willingly spend the “mental overhead” necessary to evaluate them as the high-dimensional, non-linear datasets they truly are. As logical thinkers, we must recognize that the real world is infinitely complex, and it is our moral and computational duty to scale our feature space to meet it.

The modern mantra championing the “freedom to do whatever one wants with their own body” is widely celebrated as the pinnacle of personal liberation. In reality, however, this phrase often functions as a deceptive shield. It acts as a socially acceptable cover for self-degeneracy, masking a lazy disregard for personal boundaries and self-esteem. By framing exploitative or self-destructive behaviors as “empowerment,” society ignores the severe psychological and moral costs of treating the self as a mere commodity. Nowhere is the discrepancy between the marketing of freedom and the mechanics of exploitation more glaring than in the Japanese entertainment and adult industries.

To understand this dynamic, one must look at how these industries are structured. The Japanese approach to the adult and idol industries is highly pragmatic. Rather than imposing outright bans—which historically only drive illicit activities into the dangerous hands of the black market—Japan opts for heavy regulation and containment. It is a cynical but effective system that acknowledges human impulses without necessarily celebrating them as moral goods. However, this hyper-regulated environment also perfects the machinery of human commodification, turning personal identity into a literal “meat market.”

This is most evident in the Japanese idol industry, which exposes the dark truth behind the illusion of bodily autonomy. Under the guise of pursuing their dreams, young entertainers essentially sell themselves into contractual slavery. The product they are selling is not merely music or acting, but availability and purity. To protect this product, talent agencies strip idols of their basic human rights, dictating what they wear, who they associate with, and expressly forbidding them from having romantic partners. When an idol is caught asserting their actual freedom—such as dating—they are forced to publicly apologize or “graduate” (a polite euphemism for being terminated). They are punished for damaging the merchandise.

This exploitative system is sustained by the pathetic delusion of the fandom. Through the purchase of merchandise and event tickets, fans are sold the grotesque fantasy that they have bought a claim over another human being’s life. Because they funded the idol’s career, fans feel entitled to the idol’s perpetual purity and isolation. It is a transactional, parasocial relationship born of profound overcompensation. The philosophical irony is stark: human beings barely have a claim over their own lives, subject as we all are to biology, aging, and societal pressures. Yet, the fan—often powerless in their own reality—attempts to play god over a curated celebrity, buying the illusion of control to mask their own loneliness.

Ultimately, the narrative that one can “do whatever they want with their body” serves as the perfect marketing hook for systemic exploitation. Young people are lured by the promise of agency and fame, only to realize they have signed away their right to authentic human connection. The uncomfortable truth is that true freedom requires self-respect and boundaries, not endless, reckless consumption. When intimacy, beauty, and identity are reduced to corporate inventory, the result is not liberation. It is a mutual degradation shared by the exploitative agency, the deluded consumer, and the commodified self.

Code snippet:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env -S bash

hello="hello:world:hello:world:hello"

IFS="lo:"

read -ra list <<<"$hello"

printf "%s*" "${list[*]}"
  1. Double quotes
  2. Bundling into an array
  3. Array expansion re-splitting

Double quotes

If $hello is wrapped with "", its literal value will be preserved. Without them, IFS characters will be displayed as blanks spots.

With Without
hello:world:hello:world:hello he(4 spaces)w r d he(4 spaces)w r d he

Bundling into an array

read -ra list cares not for whether the string is wrapped in quotes. It will split the string into an array regardless.

However, mind that the read command reads one line at a time. If the string is multiline, read will only read the first line.

Array expansion re-splitting

Both ${list[*]} and ${list[@]} are prone to re-splitting the array.

IFS \ printf "%s*" <..> ${list[*]} ${list[@]} "${list[*]}" "${list[@]}"
IFS="lo:" he****w*r*d*he****w*r*d*he** (1) (1) hellllwlrldlhellllwlrldlhell* (2) he****w*r*d*he****w*r*d*he*** (3)
IFS= he*w*r*d*he*w*r*d*he* (4) (4) (2) (3)
Observation
  • IFS="lo:"
    1. * acts like a delimiter, and fills the gap between each array element. Eg: hel * l * o. Only behaves like this when the last element contains a single delimiter, else the result is the same as (3).
    2. The first character of IFS, which happens to be l, serves as the delimiter for the array elements. The whole string is treated as one element, thus * is appended to the very end.
    3. * acts normally and is appended to each array element. Eg: hel * l * o *
  • IFS=: The effect this has on word splitting seems to be that it squeezes multiple blank arguments into one.

Converting characters to uppercase(/lowercase)

Take variable sayhi for example:

1
2
sayhi="hello there"
echo ${sayhi^^[eo]}

This method of converting lowercase letters to uppercase only works in Bash and will throw and “Bad substitution” error if you try it in Zsh.
Instead, you should use general replacement for this in Zsh:

1
echo ${sayhi//[eo]/[EO]}

Or, for a more Zsh native method, we can try out substitution flags, which comes in two formats:

1
2
3
echo ${sayhi:u}
# Or use it as a prefix:
echo ${(U):sayhi}

To delete a superuser in Django, you can use the Django shell to query and delete the user model instance. Here are the steps to delete a superuser using the Django shell:

  1. Open a terminal and navigate to the root directory of your Django project.

  2. Activate the virtual environment, if you are using one.

  3. Run the following command to open the Django shell: python manage.py shell.

  4. Import the User model by running the following command: from django.contrib.auth.models import User.

  5. Query the User model for the superuser you want to delete using the get() method. For example, if the username of the superuser you want to delete is “admin”, you would run: user = User.objects.get(username='admin').

  6. Call the delete() method on the user instance to delete the superuser. For example, you would run: user.delete().

  7. Exit the Django shell by typing exit() or pressing Ctrl+D.

After following these steps, the superuser will be deleted from the Django project.

It’s important to note that deleting a superuser will also delete all related data, such as blog posts or comments, if those models are related to the User model with a foreign key. If you want to preserve this data, you should first transfer ownership of the data to another user before deleting the superuser.

Another way to delete a superuser is to use the Django admin. To do this, log in as a superuser in the Django admin, navigate to the “Users” section, and click the “Delete” button next to the superuser you want to delete. Confirm the deletion in the next screen.

In summary, you can delete a superuser in Django by using the Django shell to query and delete the user model instance. Alternatively, you can use the Django admin to delete the superuser. Keep in mind that deleting a superuser will also delete any related data.

因为本人使用的操作系统是 OS X ,所以一下书写规范均符合 POSIX(Portable Open System Interface eXtended),Windows 用户请自行查阅资料。

path.basename(path[, suffix])

1
2
path.basename('/path/to/project/index.html', '.html')
// 'index'

path.delimiter

1
2
3
console.log(process.env.PATH)
// /opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/llvm/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin/:/Applications/Visual Studio Code.app/Contents/Resources/app/bin/:/Users/Mccranky/.gem/ruby/3.1.3/bin:/Users/Mccranky/.rubies/ruby-3.1.3/lib/ruby/gems/3.1.0/bin:/Users/Mccranky/.rubies/ruby-3.1.3/bin::/opt/local/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/mysql/support-files:/usr/local/mysql/bin:/etc/platform-tools:/usr/local/go/bin:/usr/local/MacGPG2/bin:/usr/local/share/dotnet:~/.dotnet/tools:/Library/Apple/usr/bin:/Users/Mccranky/.nami/bin:/Users/Mccranky/.spicetify
// undefined

输出第一行为环境变量。
输出第二行的undefined示意无返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
process.env.PATH.split(path.delimiter)
/*
[
'/opt/homebrew/opt/llvm/bin',
'/opt/homebrew/opt/llvm/bin',
'/Applications/Sublime Text.app/Contents/SharedSupport/bin/',
'/Applications/Visual Studio Code.app/Contents/Resources/app/bin/',
'/Users/Mccranky/.gem/ruby/3.1.3/bin',
'/Users/Mccranky/.rubies/ruby-3.1.3/lib/ruby/gems/3.1.0/bin',
'/Users/Mccranky/.rubies/ruby-3.1.3/bin',
'',
'/opt/local/bin',
'/opt/homebrew/bin',
'/opt/homebrew/sbin',
'/usr/local/bin',
'/usr/bin',
'/bin',
'/usr/sbin',
'/sbin',
'/usr/local/mysql/support-files',
'/usr/local/mysql/bin',
'/etc/platform-tools',
'/usr/local/go/bin',
'/usr/local/MacGPG2/bin',
'/usr/local/share/dotnet',
'~/.dotnet/tools',
'/Library/Apple/usr/bin',
'/Users/Mccranky/.nami/bin',
'/Users/Mccranky/.spicetify'
]
*/

path.delimiter: :

path.dirname

1
2
path.dirname('path/to/file.txt')
// 'path/to'

path.extname

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
path.extname('index.html')
// '.html'

path.extname('index.foo.md')
// '.md'

path.extname('index.')
// '.'

path.extname('index')
// ''

path.extname('.index')
// ''

path.extname('.index.md')
// '.md'

path.format(pathObject)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// `${dir}${path.sep}${base}`
path.format({
root: '/ignored',
dir: '/home/user/dir',
base: 'file.txt',
})
// '/home/user/dir/file.txt'

path.format({
root: '/',
base: 'file.txt',
ext: 'ignored',
})
// '/file.txt'

path.format({
root: '/',
name: 'file',
ext: '.txt',
})
// '/file.txt'

path.format({
root: '/',
name: 'file',
ext: 'txt',
})
// '/file.txt'

path.isAbsolute

1
2
3
4
path.isAbsolute('/foo/bar') // true
path.isAbsolute('/baz/..') // true
path.isAbsolute('qux/') // false
path.isAbsolute('.') // false

path.join([...paths])

1
2
3
4
5
path.join('')
// '.'

path.join('/', '/foo', 'bar', 'baz', '..')
// '/foo/bar'

path.normalize(path)

1
2
path.normalize('/foo/bar//baz/asdf/quux/..')
// Returns: '/foo/bar/baz/asdf'

path.parse(path)

1
2
3
4
5
6
7
8
9
10
path.parse('/home/user/dir/file.txt')
/*
{
root: '/',
dir: '/home/user/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
}
*/
1
2
3
4
5
6
┌─────────────────────┬────────────┐
│ dir │ base │
├──────┬ ├──────┬─────┤
│ root │ │ name │ ext │
" / home/user/dir / file .txt "
└──────┴──────────────┴──────┴─────┘

path.posix

只是输出一下path模组所有的方法。

path.relative(from, to)

1
2
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
// '../../impl/bbb'

path.resolve([...paths])

1
2
3
4
5
path.resolve('')
'/Users/Mccranky'

path.join('foo', 'bar', 'baz', '..')
// '/Users/Mccranky/foo/bar'

path.sep

path.sep: /

1
2
'foo/bar/baz'.split(path.sep)
// ['foo', 'bar', 'baz']
0%