美国《读者文摘》评出最容易拼错的英语单词(二)
你还在纠结有些单词难记吗?这些单词会让你更加头疼!但它们毕竟只是少数。这些连英语国家人士都犯怵的词汇,我们就没有必要为记住它们一筹莫展而汗颜!找到规律,就是找到自信。
《读者文摘》(Reader's Digest),美国杂志,在全球多个国家和地区都有发行。1922年创刊,月刊。是一本能引起大众广泛兴趣的内容丰富的家庭杂志。它所涉及的故事文章涵盖了健康、生态、政府、国际事务、体育、旅游、科学、商业、教育以及幽默笑话等多个领域。该杂志列举了15个让英语国家人士“头疼”的词汇,我们试着记住它们!
8.Conscientious 英 [ˌkɒnʃiˈenʃəs] 美 [ˌkɑːnʃiˈenʃəs] adj. 勤勉认真的;一丝不苟的
“Conscious” and “conscience” are tricky enough to spell. Take the first eight letters of “conscience,” pronounce them differently, and add another “sh” sound created by different letters, and you’ve got a doozy of a word for “moral and principled.” For a real test of your spelling skills, see if you can pass this quiz of 4th-grade spelling words.
“Conscious ”和“conscience ”很难拼写。拿“conscience ”的前八个字母来说,用不同的发音,再加上另一个由不同字母组成的“sh”音,你就得到了一个“moral and principled ”的单词。要想真正测试你的拼写能力,看看你是否能通过这个四年级拼写单词的测试。
9.Wednesday 英 [ˈwenzdeɪ] 美 [ˈwenzdeɪ] n. 星期三
Native English spellers have gotten used to the spelling of “Wednesday,” but that doesn’t mean it isn’t still very, very strange when you think about it. What is that first “d” doing there?! Well, many English names for weekdays come from the names of old Germanic deities. Wednesday was named after the Norse god Woden, better known, at least to comic book fans, as Odin. (We have his hammer-wielding son Thor to thank for Thursday!) “Wednesday” comes from the Old English “Wōdnesdæg,” or “Woden’s Day.”
英语母语的拼写者已经习惯了“Wednesday ”的拼写,但这并不意味着当你想到它时,它仍然不是很奇怪。第一个“d”在那里干什么?!好吧,许多平日的英文名字都来自于古日耳曼神的名字。星期三以挪威神沃登的名字命名,至少在漫画迷中更为人所知的是奥丁。(星期四我们要感谢他挥舞着锤子的儿子托尔!)“星期三”来自古英语“Wōdnesdæg”或“Woden's Day”
10.Acquiesce 英 [ˌækwiˈes] 美 [ˌækwiˈes] v. 默许;默许, 勉强同意;勉强
This is simply a word where if you know it, you know it. Looking quickly at this word, which means “comply or agree without question,” you might not think that that first “c” needs to be there; it isn’t in words like “aquatic” or “aquiver.” You may also be tempted to throw a double “s” on the end in lieu of the “sc,” or just write the “s” with no “c.”
这是一个简单的词,如果你知道它,你就算认得它吧。快看这个词,意思是“毫无疑问地服从或同意(comply or agree without question )”,你可能不认为第一个“c”需要在那里;它不是像“水产(aquatic )”或“阿基弗(aquiver )”这样的词。你也可能会被诱惑在最后扔一个双“s”来代替“sc”,或者只写“s”而不写“c”。
11.Bologna 英 [bəˈləʊnjə] 美 [bəˈloʊnjə] 波隆納;博洛尼亚;波洛尼亚;波隆那;博罗尼亚
There’s a reason many meat packages spell it “baloney.” The word “bologna” derives from Bologna, Italy, since a similar (but fancier) type of sausage comes from that city. If you want to mimic this fanciness, that “-gn” at the end should be pronounced with a “yuh” sound. But the Americanized, more phonetic spelling seems to better suit thin slabs of Oscar Mayer. All of these hard words to spell are nothing compared to these insanely tough words that won the National Spelling Bee.
有一个原因,许多肉类包装拼写为“baloney ”,“bologna ”一词源于意大利博洛尼亚,因为一种类似(但更奇特)的Bologna 那个城市。如果你想模仿这种幻想,结尾的“-gn”应该发音为“yuh”。但是,美国化的、更符合语音的拼写似乎更适合奥斯卡·梅耶尔。所有这些难拼的单词都比不上那些赢得全国拼字比赛的疯狂难拼的单词。
12.Fuchsia 英 [ˈfjuːʃə] 美 [ˈfjuːʃə] n. 紫红色;倒挂金钟;紫红;倒挂金钟属;紫紅色
Both the pairs of letters “sc” and “sh” have been known to make the sound that starts the second syllable of “fuchsia.” But, unfortunately for anyone who likes writing about colors or plants, “fuchsia” uses neither of those pairings, instead taking all the necessary letters and jumbling them up. The plant, whose flowers give the name to the color, was named after esteemed German botanist Leonhard Fuchs.
众所周知,两对字母“sc”和“sh”的发音都以“fuchsia”的第二个音节开头。但是,不幸的是,对于任何喜欢写颜色或植物的人来说,“fuchsia”都不使用这两个字母对,而是把所有必需的字母都拿出来混淆起来。这种植物的花以这种颜色命名,是以德高望重的德国植物学家莱昂哈德·富克斯( Leonhard Fuchs )命名的。
13.Nauseous 英 [ˈnɔːziəs] 美 [ˈnɔːʃəs] adj. 令人作呕的;恶心的;令人恶心的
There sure are a lot of vowels in “nauseous,” and it can be tricky to remember what order they go in. Even if you’ve got them straight, you may still second-guess yourself about the consonants, too. The “sh” sound makes it sound like there should be a “c” in there somewhere, like in “conscious.” And, as if the spelling confusion weren’t enough, you’ve probably been using the word “nauseous” wrong too, but that’s a whole ‘nother story.
“nauseus”中肯定有很多元音,记住它们的顺序可能很难。即使你把辅音弄明白了,你也可能会对辅音进行二次猜测。“sh”音听起来好像应该有一个“c”在某个地方,就像在“conscious”中一样。而且,似乎拼写混乱还不够,你可能也用错了“nauseous”这个词,但那是另一个完整的故事。
14.Orangutan 英 [ˈɔːrəŋˈuːtæn] 美 [ɔˈræŋətæn] 猩猩;红毛猩猩;小猩猩
These poor Bornean primates are the subject of much linguistic confusion. According to Merriam-Webster, their name is the amalgamation of two words in the Malay pidgin language: “orang” for “man” and “hutan” for “forest.” But many people prefer pronouncing an anglicized version that adds another “g” to the end, making the word perplexing for spellers. As if that weren’t confusing enough, some variations on the spelling hyphenate the word and/or add an “o” before the “u,” creating “orang-outan.”
这些可怜的博尔纳灵长类动物是语言混乱的对象。根据《韦氏大词典》的说法,他们的名字是马来洋泾浜语中两个词的混合体:“orang ”代表“人”,而“hutan ”代表“森林”。但许多人更喜欢用英语发音,在结尾处加上另一个“g”,这让拼写者感到困惑。似乎这还不够混乱,拼写上的一些变体在“u”之前用连字符连接单词和/或添加“o”,创建“orang outan”
15.Paraphernalia 英 [ˌpærəfəˈneɪliə] 美 [ˌpærəfərˈneɪliə] n.随身用品;政治花瓶
Instead of adding a letter like in the case of “orangutan,” people pronouncing this already-tricky word tend to skip over the second “r” altogether. This mouthful actually comes from a nearly identical Latin word, paraphernālia, which referred to the belongings or property of a bride-to-be, similar to a dowry. Needless to say, this word has modernized, as now it can describe everything from ski gear to musical amplifiers to cell phone chargers. Next, ease your word-cluttered mind with these simple spelling rules to remember commonly misspelled words.
在“orangutan ”这个词中,人们不会像“orangutan ”那样加上一个字母,而是会把第二个“r”完全跳过。这一口实际上来自一个几乎相同的拉丁语单词paraphernālia,它指的是准新娘的财产或财产,类似于嫁妆。不用说,这个词已经现代化了,因为现在它可以描述从滑雪用具到音乐放大器到手机充电器的一切。下一步,用这些简单的拼写规则来缓解你的单词混乱的头脑,以记住常见的拼写错误的单词。
“告别 8 万行 C++ 代码,我用 4 千行 C 代码就搞定了!”
摘要:这一次,Zig 要彻底告别 C++ 了。
链接:https://ziglang.org/news/goodbye-cpp/
声明:本文为 CSDN 翻译,未经允许禁止转载。
作者 | Andrew Kelley 译者 | 弯月 责编 | 郑丽媛出品 | CSDN(ID:CSDNnews)在此次变更之前,Zig 代码库由两个编译器组成:
旧编译器:总共包含 8 万行 C++ 代码,加上新编译器共享 Zig 代码。
新编译器:总共包含 25 万行 Zig 代码。
新编译器的速度更快,使用的内存更少,并得到了积极的维护和增强。同时,没有人想碰旧编译器,但是通过源代码构建新编译器时需要用到旧编译器。
这意味着,新的 Zig 语言特性必须实现两次:在新代码库中实现一次,然后在旧代码库中再实现一次——这是一个巨大的痛点,尤其这两个编译器的设计早已大相径庭。
此外,用 C++ 实现的 Zig 最初使用的策略与 D 编译器相同:在进程退出之前不释放任何内存。但随着编译时执行代码成为该语言的标志性功能之一,加之使用同一个编译单元来处理一切,项目的规模越来越大,这个设计决策就有点不合时宜了。
解决方案
这个问题很有趣,有很多解决方案,但每一种都有一定的弊端。在搞清楚问题之后,我们就各种可能性展开了快速的头脑风暴会议,每个提议都有自己的优缺点。
放弃自我编译
Odin 就采用了这种方法。
这个方法可以解决整个问题,但缺点是我们必须放弃 Zig,转而使用 C。我不同意,因为 Zig 带来的改进太诱人了,我不想放弃:例如,我们使用的一些面向数据的设计技术无法通过 C/C++ 实现。
使用旧版本的编译器
这是 Rust 和许多其他语言采用的方法。
这种方法的一大缺点是,根据源代码构建任何提交都需要经过复杂的操作。例如,假设你尝试执行 git bisect,有时 git 会检出一个旧版本的提交,但脚本无法利用这些源代码构建,因为构建编译器的二进制文件不是正确版本。当然,这个问题并不是无法解决,但势必会给开发人员带来许多不必要的麻烦。
此外,构建编译器也会受到目标平台上已有二进制文件的限制。例如,假设没有 riscv64 版的编译器,就无法在 riscv64 硬件上利用源代码构建。
因此关键问题在于,这种方法无法充分支持能够在任何系统上构建任何提交的需求。
将编译器编译成 C 代码
这是 Nim 采用的方法。
与前面的策略相比,这种方法的好处是可以将生成的 C 代码提交至源代码控制,比较方便,但如果这些 C 代码只能用于特定平台,实际效果也是一样的。
我不太清楚怎样才能生成不依赖于平台的 C 代码(像 Nim 那样),但我看到他们的描述中说:“支持的 CPU/OS 组合比旧的 csources 代码库更多”。这意味着,尽管他们的代码可以在许多 CPU/OS 的组合上编译,但这并不一定表示这些 C 代码具有可移植性。此外,这些代码与主编译器分别保存在不同的代码库中,所以并不能解决前一种策略遇到的问题。
我探索了这种可能性,发现生成的 C 代码不仅只能用于特定平台,而且代码量非常大。我们的编译器会生成一个 80 MiB 的 C 文件。虽然我们可以通过 C 后端增强来改进,但与其接受如此大规模的扩张,还不如直接将二进制文件提交到 Git 代码库。
将编译器编译成 C 代码,之后直接维护 C 代码
这种方法我从多年前就想试试,最近终于开始研究了一下。很明显的一大缺点是,清理自动生成的 C 代码非常困难,而且依然需要维护两种编译器实现,容易打击贡献者的积极性——谁会愿意用 Zig 和 C 重复两次相同的工作?
将编译器编译成简单的虚拟机
有一次,在讨论编译器自举时,Drew DeVault 提到了 OCaml 的策略。于是我有了一个想法:可以建立一个自举专用的后端。
不过我认为 Zig 和 OCaml 之间还有一些差异。Zig 只有一个虚拟机平台,它是跨平台的,可以通过 LLVM 进行优化——这就是 WebAssembly,使用 WASI 作为操作系统抽象层。
探索思路
主要思路是,利用一个非常小的 wasm 二进制作为 stage1 内核,提交到源代码控制,这样就可以用它来编译源代码中的任何提交。我们提供了一个 C 编写的 WASI 解释器,然后用它将 Zig 编译器代码编译成 C 代码。之后用系统的 C 编译器对 C 代码进行编译和连接,生成 stage2 二进制文件。接着,stage2 二进制文件就可以通过反复的 zip build 从源代码进行构建。
wasm 二进制文件是通过 zig build update-zig1 生成的,后者使用了 LLVM 后端来生成一个针对 wasm32-wasi 平台、generic+bulk_memory CPU 的 ReleaseSmall 二进制文件。该二进制文件中 C 之外的所有后端都是禁用的,这样产生的文件仅有 2.6MiB。然后再通过 wasm-opt -Oz --enable-bulk-memory 进行优化,压缩到 2.4MiB。最后,用 zstd 进一步压缩至 637KB。其中还包括了 zstd 解码器(用 C 实现),但这是值得的,因为 zstd 的实现基本不会改变,而且它每次都能给 wasm 二进制文件节省下 1.8MiB。
因此,我们用 4 千行可移植的 C 代码替换了原本 8 万行的 C++ 代码。这些代码仅使用了标准 libc 函数,且不依赖于任何 POSIX 的头文件,也不依赖于 windows.h。操作系统互操作层完全抽象到了几个 WASI 函数中,由 WASI 解释器负责实现:
(import "wasi_snapshot_preview1" "args_sizes_get" (func (;0;) (type 3)))(import "wasi_snapshot_preview1" "args_get" (func (;1;) (type 3)))(import "wasi_snapshot_preview1" "fd_prestat_get" (func (;2;) (type 3)))(import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func (;3;) (type 6)))(import "wasi_snapshot_preview1" "proc_exit" (func (;4;) (type 11)))(import "wasi_snapshot_preview1" "fd_close" (func (;5;) (type 8)))(import "wasi_snapshot_preview1" "path_create_directory" (func (;6;) (type 6)))(import "wasi_snapshot_preview1" "fd_read" (func (;7;) (type 5)))(import "wasi_snapshot_preview1" "fd_filestat_get" (func (;8;) (type 3)))(import "wasi_snapshot_preview1" "path_rename" (func (;9;) (type 9)))(import "wasi_snapshot_preview1" "fd_filestat_set_size" (func (;10;) (type 36)))(import "wasi_snapshot_preview1" "fd_pwrite" (func (;11;) (type 28)))(import "wasi_snapshot_preview1" "random_get" (func (;12;) (type 3)))(import "wasi_snapshot_preview1" "fd_filestat_set_times" (func (;13;) (type 51)))(import "wasi_snapshot_preview1" "path_filestat_get" (func (;14;) (type 12)))(import "wasi_snapshot_preview1" "fd_fdstat_get" (func (;15;) (type 3)))(import "wasi_snapshot_preview1" "fd_readdir" (func (;16;) (type 28)))(import "wasi_snapshot_preview1" "fd_write" (func (;17;) (type 5)))(import "wasi_snapshot_preview1" "path_open" (func (;18;) (type 52)))(import "wasi_snapshot_preview1" "clock_time_get" (func (;19;) (type 53)))(import "wasi_snapshot_preview1" "path_remove_directory" (func (;20;) (type 6)))(import "wasi_snapshot_preview1" "path_unlink_file" (func (;21;) (type 6)))(import "wasi_snapshot_preview1" "fd_pread" (func (;22;) (type 28)))
为了让 Zig 编译器把自己编译成 C,只需要使用这些系统调用。
Jacob Young和我一起,在andrewrk/zig-wasi的基础上完成了这个 WebAssembly/WASI 解释器。我用 Zig 建立了初版,借助 Zig 丰富的标准库和安全机制探索了这个思路。这个解释器不会提前解码 wasm 模块,而是直接使用文件偏移量作为程序计数器。虽然它能正常工作,但太慢了,对编译器进行解释执行需要好几个小时,而用原生机器码只需大约 5 秒钟。
因此,Jacob 改善了该项目,引入了另一个指令集和更多的优化,还有一些其他技巧,将性能提升到了可接受的程度。同时,我将 Zig 代码转成了纯 C。
我们一起努力了大约两个星期,互相将对方的代码合并到自己的分支中,交流心得、分享成功的喜悦。我非常感谢 Jacob 在这个项目上的努力,特别是他一丝不苟地改进 Zig 的 C 后端,才让这个项目得以成功。
在概念得到证实后,Jacob 意识到,将 WebAssembly 转成 C,要比直接解释执行更快。这实际上就是 JIT 编译,但更大的好消息是,我们的自举工具实际上是系统的 C 编译器。
WebAssembly Binary Toolkit 项目里有一个 wasm2c 工具,但我们并没有移植或分叉——Jacob 从零开始创建了一个 wasm2c 的实现。这个实现没有考虑通用性,只包含了在编译器编译自己时需要调用的系统调用。
所以,这个版本的 wasm2c 只有 4 千行代码,也不依赖 C++,采用了更简洁的方式,没有实现任何沙盒、安全特性等。
新的构建过程
下面是新的构建过程:
Building CXX object CMakeFiles/zigcpp.dir/src/zig_llvm.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/zig_llvm-ar.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/zig_clang.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/zig_clang_driver.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/zig_clang_cc1_main.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/zig_clang_cc1as_main.cpp.oBuilding CXX object CMakeFiles/zigcpp.dir/src/windows_sdk.cpp.oLinking CXX static library zigcpp/libzigcpp.aBuilt target zigcppBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/wasm2c.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/decompress/huf_decompress.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/decompress/zstd_ddict.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/decompress/zstd_decompress.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/decompress/zstd_decompress_block.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/entropy_common.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/error_private.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/fse_decompress.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/pool.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/xxhash.c.oBuilding C object CMakeFiles/zig-wasm2c.dir/stage1/zstd/lib/common/zstd_common.c.oLinking C executable zig-wasm2cBuilt target zig-wasm2cConverting ../stage1/zig1.wasm.zst to zig1.cBuilding C object CMakeFiles/zig1.dir/zig1.c.oBuilding C object CMakeFiles/zig1.dir/stage1/wasi.c.oLinking C executable zig1Built target zig1Running zig1.wasm to produce zig2.cRunning zig1.wasm to produce compiler_rt.cBuilding C object CMakeFiles/zig2.dir/zig2.c.oBuilding C object CMakeFiles/zig2.dir/compiler_rt.c.oLinking CXX executable zig2Built target zig2Building stage3
总结:
使用系统 C 编译器编译 zig-wasm2.c;
使用 zig-wasm2.c 将 zig1.wasm.zst 转换成 zig1.c;
使用系统 C 编译器编译 zig1.c;
a.注意 zig1 只启用了 C 后端。
使用 zig1 将 Zig 编译器编译成 zig2.c;
使用系统 C 编译器编译 zig2.c;
a.这个编译器的逻辑是正确的,但它的机器码是由系统 C 编译器优化的,而不是它自己优化的。所以我们继续进行第六步,得到一个自我编译后的性能特性。
zig2 build(使用旧版本 Zig 编译 Zig 的标准构建流程);
如果用最后一步产生的结果再次编译 Zig,会得到同样的字节码。也就是说,zig3、zig4 是完全相同的。所以整个过程结束,最后得到的二进制文件可以去掉后缀,直接命名为 zig。
wasm 二进制的更新仅限于有重大更新,或新功能影响到编译器构建自身的时候。例如,编译器中的 bug 修复不会影响编译器编译自身,因此可以忽略。但如果 Zig 编译自身时必须修复该 bug,那么就需要更新 wasm 二进制。与之相似,当语言改变、编译器需要使用新功能来编译自身时,就要更新 wasm 二进制文件。
更新stage1/zig1.wasm.zst的方法如下:
zig build update-zig1
性能
我收集了两个性能数据:
数据#1:使用make -j8 install 从源代码编译,配置为-DCMAKE_BUILD_TYPE=Debug:
old: 8m12s with 11.3 GiB peak RSSnew: 9m59s with 3.8 GiB peak RSS
数据#2:使用ninja install从源代码编译,配置为-DCMAKE_BUILD_TYPE=Release:
old: 13m20s with 10.3 GiB peak RSSnew: 10m53s with 3.2 GiB peak RSS
其中最关键的是构建时内存的需求量。一个只有 4~8GiB 的 RAM 能否编译 Zig 是非常重要的,这决定了是否可以用 GitHub 认证的 Action。
未来的计划
有一点我要承认,尽管此次改动大获全胜,但还是有一个地方退步了,即能否在固定次数内实现 Zig 的自举。
在这之前,从源代码开始的构建过程没有涉及任何二进制块,除了系统的 C/C++ 编译器之外。但此次改动之后,它使用了 WebAssembly 的二进制,这并不是源代码,而是一个构建结果,有些人可能非常看重这一点。
这是需要付出的代价,但我认为这些代价是值得的。考虑到官方语言规格以及 Zig 越来越受欢迎的现状,我们会看到更多的第三方项目开始用 C 来实现 Zig。
我愿把此次改动之前的版本标记为 1.0,且此次改动也并不在 Zig 软件基金会的计划内。当然,事情可能会改变,这只是目前的计划。
此外,此次改动还去掉了 -fstage1 标志,这个标志可以让 Zig 用户选择旧版本编译器来代替新版本——这是使用异步函数的唯一方法,而异步函数功能在新的编译器中还没有实现。
我建议需要使用 -fstage1 标志的用户继续使用 0.10.0,当 0.10.1 发布后进行升级,最终升级到 0.11.0,该版本将会支持异步函数。注意 Zig 采用语义版本号,因此本文中所说的一切都不会进入 0.10.1 发布,。0.10.1 只会包含 master 分支上的 bug 修复。
语言的发展
从更积极的方面来看,此次改动意味着所有计划中的语言改动都可以更快地进行。当我们脱离了旧代码的束缚,Zig 0.11.0 的发布迭代会更快。
有了这个改动,我们就可以像试用标准库那样,立即试用语言上的新改动。
在这个改动合并到主分支时,标签“stage1”下已经有 650 个问题,而这些问题所针对的代码都可以删掉了!所以,理论上我们可以立即关闭这些问题,不过我要求关闭这些问题时必须编写相应的测试用例,或者证明相应的部分已经有测试覆盖了。也许这需要付出更多的努力,但这正是我们当前的工作。
相关问答
求助啊, odin 刷机卡在 nand write start,怎么办?1.手机进入应用程序--开发--打开USB调试。2.下载线刷rom包。3.下载刷机工具包odin后解压。4.关机,然后同时按住下音量下键+HOME键+电源键,等待3秒,出现...
I9100刷机失败 Odin 显示如下 在线急等-ZOL问答<0>Odinv.3engine(ID:3)..<0>Fileanalysis..<0>SetupConnection..<0>I...
三星9300系统固件升级后需要输入SIM卡网络解锁PIN码,我就准...<007>Odinv.3engine(ID:7)..
在菜单中选择“WriteImage”选项,并使用滚动键滚动至左侧找到“InstallfromADB”选项。确认所有设置无误后点击“StartWriting”开始卡刷过程。需要注意的...