5

Rebol 2 では、Unicode について何も知らないため、^(FF) より大きいコードポイントの文字列でキャレット スタイルのエスケープを使用できないことはわかっています。したがって、これは何も生成しません。めちゃくちゃに見えます。

print {Q: What does a Zen master's {Cow} Say?  A: "^(03BC)"!}

それでも、コードは Rebol 3 で機能し、次のように出力されます。

Q: What does a Zen master's {Cow} Say?  A: "μ"!

それは素晴らしいことですが、R3 は明らかに U+FFFF で文字列内の文字を保持する能力を最大限に発揮します。

>> type? "^(FFFF)"
== string!

>> type? "^(010000)"
** Syntax error: invalid "string" -- {"^^(010000)"}
** Near: (line 1) type? "^(010000)"

この状況は、Rebol 2 が知らなかったコードポイントに遭遇したときのランダムな動作よりもはるかに優れています。ただし、独自の UTF-8 エンコーディングを行う方法を知っている場合 (またはディスクからソース コードをロードして文字列を取得した場合) は、文字列を保存するための回避策が Rebol にありました。個々のキャラクターからそれらを組み立てることができます。

したがって、U+010000 の UTF-8 エンコーディングは #F0908080 であり、前に次のように言うことができます。

workaround: rejoin [#"^(F0)" #"^(90)" #"^(80)" #"^(80)"]

そして、UTF-8 を使用してエンコードされた単一のコードポイントを含む文字列を取得し、コード ブロックでディスクに保存して、再度読み込むことができます。R3に似たようなトリックはありますか?

4

2 に答える 2

4

文字列を使用した回避策があります。データ型も。その場合、UTF-8 は使用できませんが、次のように UTF-16 の回避策を使用できます。

utf-16: "^(d800)^(dc00)"

、UTF-16 サロゲート ペアを使用して ^(10000) コード ポイントをエンコードします。一般に、次の関数でエンコードを実行できます。

utf-16: func [
    code [integer!]
    /local low high
] [
    case [
        code < 0 [do make error! "invalid code"]
        code < 65536 [append copy "" to char! code]
        code < 1114112 [
            code: code - 65536
            low: code and 1023
            high: code - low / 1024
            append append copy "" to char! high + 55296 to char! low + 56320
        ]
        'else [do make error! "invalid code"]
    ]
]
于 2013-04-09T01:08:41.337 に答える
3

はい、トリックがあります...これは、R2でも使用する必要があるトリックです。 文字列を使用しないでください。バイナリを使用してください!このようなことをしなければならない場合:

適切な回避策: #{F0908080}

Rebol2 でも機能し、Rebol3 でも機能します。面白いビジネスなしで保存してロードできます。

実際、Unicodeに関心がある場合は、 3 ではなく Rebol 2 で立ち往生している場合は、^(7F) よりも高いコードポイントを使用する文字列処理を停止してください。そのひどい回避策を見ると、その理由がわかります。

ひどい回避策: rejoin [#"^(F0)" #"^(90)" #"^(80)" #"^(80)"]

... "そして、その単一の UTF-8 コードポイントを持つ文字列を取得します" ...

取得する必要があるのは、4 つの個別の文字コードポイントと4 = length? terrible-workaround. Rebol2は文字列で壊れています!基本的にバイナリと変わりません!フードの下。実際、Rebol2 では、AS-BINARY と AS-STRING を検索して、コピーを作成せずに 2 つの型を前後にエイリアスできます。(これは Rebol3 では不可能です。根本的に異なるため、機能に執着しないでください!)

これらの文字列が 4 の長さを報告するのを見るのはやや欺瞞的であり、変換すると各文字が同じ値を生成するという誤った安心感がありますto integer!。それらをどこかのファイルまたはポートに書き出すことがあり、それらをエンコードする必要がある場合、噛まれるからです. Rebol2 でこれに注意してください。

>> to integer! #"^(80)"
== 128

>> to binary! #"^(80)"
== #{80}

しかし、R3 では、バイナリ変換が必要な場合に UTF-8 エンコーディングが使用されます。

>> to integer! #"^(80)"
== 128

>> to binary! #"^(80)"
== #{C280}

そのため、一見動作しているように見えるコードが後で別のことを行い、別の方法でシリアル化することになると、驚くことでしょう。実際、この点で R2 がどのように「めちゃくちゃ」になっているのか知りたい場合は、「mu」に奇妙な記号が付けられた理由を調べてください。R2:

>> to binary! #"^(03BC)"
== #{BC}

「03」を捨てただけです。:-/

したがって、何らかの理由で Unicode 文字列を操作する必要があり、R3 に切り替えることができない場合は、牛の例で次のようなことを試してください。

mu-utf8: #{03BC}
utf8: rejoin [#{} {Q: What does a Zen master's {Cow} Say?  A: "} mu-utf8 {"!}]

これでバイナリが得られます。デバッグ出力用に文字列に変換するだけで、意味不明なものが表示される準備ができています。しかし、Rebol2 で行き詰まっている場合は、これを行うのが正しいことです。

そして、答えを繰り返します: Rebol3 でこれらのより高いコードポイントを使用する必要がある何らかの奇妙な理由で立ち往生した場合の対処方法でもあります。

utf8: rejoin [#{} {Q: What did the Mycenaean's {Cow} Say?  A: "} #{010000} {"!}]

LINEAR B SYLLABLE 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
]

変換の代わりにこれを使用するto binary!と、Rebol2 と Rebol3 の両方で一貫した動作が得られます。terrible-workaround(スタイル文字列のソリューションを効果的に実装します。)

于 2013-02-25T22:44:30.477 に答える