Hos*_*ork 5 unicode rebol rebol3 rebol2 astral-plane
我知道你不能在Rebol 2中使用大于^(FF)的代码点在字符串中使用插入符号样式,因为它对Unicode没有任何了解.所以这不会产生任何好处,它看起来搞砸了:
print {Q: What does a Zen master's {Cow} Say? A: "^(03BC)"!}
Run Code Online (Sandbox Code Playgroud)
然而代码在Rebol 3中工作并打印出来:
Q: What does a Zen master's {Cow} Say? A: "?"!
Run Code Online (Sandbox Code Playgroud)
这很好,但是R3最大限度地发挥了它在U + FFFF中保持字符串的能力显然:
>> type? "^(FFFF)"
== string!
>> type? "^(010000)"
** Syntax error: invalid "string" -- {"^^(010000)"}
** Near: (line 1) type? "^(010000)"
Run Code Online (Sandbox Code Playgroud)
当Rebol 2遇到它不知道的代码点时,情况要好于Rebol 2的随机行为.但是,如果您知道如何进行自己的UTF-8编码(或通过从磁盘加载源代码获取字符串),Rebol中常常会有一种解决方法来存储字符串.你可以从个别角色组装它们.
所以U + 010000的UTF-8编码是#F0908080,你可以说:
workaround: rejoin [#"^(F0)" #"^(90)" #"^(80)" #"^(80)"]
Run Code Online (Sandbox Code Playgroud)
并且您将获得一个使用UTF-8编码的单个代码点的字符串,您可以在代码块中保存到磁盘并再次读回.R3中有类似的技巧吗?
是的,有一个技巧......这也是您应该在 R2 中使用的技巧。 不要使用字符串!使用二进制!如果你必须做这样的事情:
好的解决方法:#{F0908080}
它在 Rebol2 中可以工作,在 Rebol3 中也可以工作。您可以保存并加载它,而不需要任何有趣的事情。
事实上,如果你关心 Unicode,永远...如果你陷入 Rebol 2 而不是 3 ,请停止使用高于 ^(7F) 的代码点进行字符串处理。我们将通过查看这个可怕的解决方法来了解原因:
可怕的解决方法:重新加入 [#"^(F0)" #"^(90)" #"^(80)" #"^(80)"]
... “你会得到一个带有单个 UTF-8 代码点的字符串” ...
您唯一应该得到的是一个带有四个单独字符代码点的字符串,并且带有4 = length? terrible-workaround. Rebol2 因字符串而损坏!基本上和二进制没有什么区别!在引擎盖下。事实上,在 Rebol2 中,您可以来回为这两种类型设置别名,而无需进行复制,查找 AS-BINARY 和 AS-STRING。(这在 Rebol3 中是不可能的,因为它们确实有本质上的不同,所以不要执着于这个功能!)
看到这些字符串报告的长度为 4 有点具有欺骗性,并且如果转换它们,每个字符都会产生相同的值,这会让人产生一种虚假的安慰to integer!。因为如果你把它们写到某个文件或端口,并且需要对它们进行编码,你就会被咬。请注意 Rebol2 中的这一点:
>> to integer! #"^(80)"
== 128
>> to binary! #"^(80)"
== #{80}
Run Code Online (Sandbox Code Playgroud)
但在 R3 中,当需要二进制转换时,您可以使用 UTF-8 编码:
>> to integer! #"^(80)"
== 128
>> to binary! #"^(80)"
== #{C280}
Run Code Online (Sandbox Code Playgroud)
因此,当您看似正常工作的代码稍后执行不同的操作并最终以不同的方式进行序列化时,您将会感到惊讶。事实上,如果你想知道 R2 在这方面有多“混乱”,看看为什么你的“mu”有一个奇怪的符号。在 R2 中:
>> to binary! #"^(03BC)"
== #{BC}
Run Code Online (Sandbox Code Playgroud)
它只是把“03”扔掉了。:-/
因此,如果您出于某种原因需要使用 Unicode 字符串并且无法切换到 R3,请针对奶牛示例尝试如下操作:
mu-utf8: #{03BC}
utf8: rejoin [#{} {Q: What does a Zen master's {Cow} Say? A: "} mu-utf8 {"!}]
Run Code Online (Sandbox Code Playgroud)
这会给你一个二进制文件。仅将其转换为字符串以进行调试输出,并准备好看到乱码。但如果你被困在《Rebol2》中,这就是正确的做法。
重申一下答案:如果由于某种奇怪的原因需要在 Rebol3 中使用那些更高的代码点,这也是该怎么做:
utf8: rejoin [#{} {Q: What did the Mycenaean's {Cow} Say? A: "} #{010000} {"!}]
Run Code Online (Sandbox Code Playgroud)
我确信如果我知道线性 B 音节 B008 A是什么,那将是一个非常有趣的笑话。这让我想说,如果你正在做一些深奥的事情,你很可能只会引用几个代码点作为示例。您可以将大部分数据保存为字符串,直到您需要方便地将它们插入,并将结果保存在二进制系列中。
更新:如果遇到此问题,这里有一个实用函数,可用于暂时解决该问题:
safe-r2-char: charset [#"^(00)" - #"^(7F)"]
unsafe-r2-char: charset [#"^(80)" - #"^(FF)"]
hex-digit: charset [#"0" - #"9" #"A" - #"F" #"a" - #"f"]
r2-string-to-binary: func [
str [string!] /string /unescape /unsafe
/local result s e escape-rule unsafe-rule safe-rule rule
] [
result: copy either string [{}] [#{}]
escape-rule: [
"^^(" s: 2 hex-digit e: ")" (
append result debase/base copy/part s e 16
)
]
unsafe-rule: [
s: unsafe-r2-char (
append result to integer! first s
)
]
safe-rule: [
s: safe-r2-char (append result first s)
]
rule: compose/deep [
any [
(either unescape [[escape-rule |]] [])
safe-rule
(either unsafe [[| unsafe-rule]] [])
]
]
unless parse/all str rule [
print "Unsafe codepoints found in string! by r2-string-to-binary"
print "See http://stackoverflow.com/questions/15077974/"
print mold str
throw "Bad codepoint found by r2-string-to-binary"
]
result
]
Run Code Online (Sandbox Code Playgroud)
如果您使用它而不是to binary!转换,您将在 Rebol2 和 Rebol3 中获得一致的行为。terrible-workaround(它有效地实现了样式字符串的解决方案。)
| 归档时间: |
|
| 查看次数: |
717 次 |
| 最近记录: |