LoginSignup
0
0

More than 1 year has passed since last update.

Ruby の Array.pack('p') で 'can't modify frozen String' が出たら、バージョンを上げるか、解凍が必要

Posted at

Ruby で pack をしたら、 can't modify frozen String が出たので、記録する。

[47] pry(main)> str = 'abc'
=> "abc"
[48] pry(main)> str.freeze
=> "abc"
[49] pry(main)> [str].pack('p*')
RuntimeError: can't modify frozen String
from (pry):48:in `pack'

pack は変更(modify)ではない、エラーが出るのが不思議だった。
そこで思いついたのは、「ポインタを渡すと、破壊できるから」という理由。

本当にそうなのかを調べようと思ったが、 2.6.3 まではエラーだが、 2.7.3 からはエラーにならなくなっていることに気づいた。

下記のコードを tmp.rb として保存し、手元にある version を切り替えながらテストした。

# tmp.rb
# frozen_string_literal: true

puts RUBY_VERSION

['abc'].pack('p*')
$ rbenv shell 2.3.3
$ ruby tmp.rb
2.3.3
tmp.rb:5:in `pack': can't modify frozen String (RuntimeError)
        from tmp.rb:5:in `<main>'
$ rbenv shell 2.5.0
$ ruby tmp.rb
2.5.0
Traceback (most recent call last):
        1: from tmp.rb:5:in `<main>'
tmp.rb:5:in `pack': can't modify frozen String (FrozenError)
$ rbenv shell 2.6.3
$ ruby tmp.rb
2.6.3
Traceback (most recent call last):
        1: from tmp.rb:5:in `<main>'
tmp.rb:5:in `pack': can't modify frozen String (FrozenError)
$ rbenv shell 2.7.3
$ ruby tmp.rb
2.7.3
$ rbenv shell 3.0.1
$ ruby tmp.rb
3.0.1

ポインタが関係なかったのは残念。
バージョンを上げれば解決する。

バージョンを上げずに対応する方法は、解凍すること。

[56] pry(main)> [str].map(&:+@).pack('p*')
=> "\xD8\xC6\b\x04\x00\x00\x00\x00"
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0