SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|

2024-03-03(Sun) pack/unpackをどうにかする

  昨日、pack/unpackって記述方法としてはどうなのよ、と書いてから、なんだか考え始めてしまった。要するに、以下の書き方が全然ピンとこないのでちっとも覚えられない、って話である。

[65, 66, 67].pack('c*')
=> ABC
'ABC'.unpack('c*')
=> [65, 66, 67]

  じゃ、ピンとくる書き方ってなんだって考えたら、以下が思い浮かんだ。これは実際に動く。いわゆるprintfだよね。

'%c%c%c' % [65, 66, 67]
=> ABC

  「%」演算子を使っているのがミソだ。「文字列化する」「引数は配列」というイメージが自然に湧く。じゃ、逆に「配列化する」演算子はなんだ? 苦し紛れだが、こんなのはどうだ。こんな文法はないので動かないが。

'%c%c%c' << 'ABC' # 動きません
=> [65, 66, 67]

  これに近い記述方法で、実際に動かすことはできないか? って考えたら、思い浮かんでしまい、できてしまった。

:c_ << 'ABC'
=> [65, 66, 67]

  RubyのSymbolを悪用(?)して定義した。「<<」演算子を再定義している。「c*」とは書けないので「c_」で代用してみた。

class Symbol
    def <<(packed)
        packed.unpack(self.to_s.sub(/_$/, '*'))
    end
end

  これを使うと、BASE64のデコード処理を以下のように書ける。

:m_ << 'QUJDREU='
=> ["ABCDE"]

  そうなると、逆にエンコードする時はこう書きたい。そんな指示子はないので動かないが。

'%m' % ['ABCDE'] # 動きません
=> "QUJDREU=\n"

  んが、今度は逆に、Stringの「%」演算子を再定義してしまえばいい。指示子の指定が「%」だと既存の機能と衝突するので「:」を割り振ってみた。

class String
    alias :perc :%
    def %(arg)
        self =~ /^:(.+)/ ? arg.pack($1.sub(/_$/, '*')) : perc(arg)
    end
end

  これを使うと、BASE64のエンコード処理を以下のように書ける。

':m_' % ['ABCDE']
=> "QUJDREU=\n"

  そもそもBASE64の変換は「文字↔文字」だからピンときにくいだけのことかもしれない。無理にピンとこさせずとも、以下をメモっておけば十分か。

['ABCDE'].pack('m*')
=> "QUJDREU=\n"
'QUJDREU='.unpack('m*')[0]
=> "ABCDE"

  まぁ、単なるたわむれプログラミングだ。わはははははははは、たわむれは、おわりじゃ。