«前の日(12-16) 最新 次の日(12-18)» 追記

いがいが日記


2004-12-17

_ 液晶ディスプレイ

先週ツクモへ行って展示品を見てたら欲しくなった。

面がツルツルしてるやつ。(?)

やっぱ絵が綺麗ですよね。

反射しやすくなるので光源が映ったりする弊害もあるけど、

自宅だったら気にならなそうだし。

使ってらっしゃる方いますか?

シールシートで貼るタイプもありますよね。

これはどうなんだろう。

でもでかいディスプレイも欲しいだよなー。

出張先でアップルシネマディスプレイ(旧型)を触ったのですが、

大きな画面を横に2つ開けるのはいいですね。

そしてお金は無い。(^^;)

そういえば、、、↓続く

_ 無機ELディスプレイ

今日の朝日新聞に無機ELディスプレイで参入するベンチャー会社の記事が。

37inchクラスは液晶とPDPの隙間なので勝負できるそうだ。

実物みてみないとなんとも言えないけどどんなもんなんだろ。

本日のツッコミ(全2件) [ツッコミを入れる]

_ kzy [今回買ってもらったLOOXの液晶ディスプレイがつるつるのやつなんですけど、蛍光灯の映り込みが結構気になります。 慣れ..]

_ いが [やっぱり気になるのですか。 私も展示品見てると気になるのですが、 お店は明るいからかなーとも思ってまして。 とりあえ..]


2005-12-17

_ 浜松オートレース廃止へ

ぐは。ショックだ。。。

オートレースは全国6場しかなく、

遠征という形で選手の交流もあるので1つが倒れると共倒れになる可能性が高い。

それにしても何十年も黒字で財政に貢献したのに、

廃止になるときは数年の赤字で決まってしまうのが残念。

しかも今年は構造改革で黒字の見通しなのに、

もう少し待って欲しいというのがファンの本音。

ただ、ギャンブルは嗜好だから、赤字になってまで続けるべきではないと思う。

今後の見通しが赤字という報告も客観的にみて支持できると思う。

ファン心理と客観性のどちらも分かるだけに切ないです。

多くのバイク工場を生み出した浜松だけになおさら残念です。

_ おいでよ どうぶつの森

最近、NINTENDO DS がおもしろそうだ。

私の周りでももってる人がたくさんいる。

XBOXやPSと違って、

グラフィックではなくアイデアで攻めているところが面白い。

「おいでよ どうぶつの森」はすれちがい通信ができるらしい。

現実世界で実際にすれちがった人とメッセージの交換ができる機能だ。

#「NINTENDOGS」でも同じ機能があったらしく、

#私は↑にはあんまり興味がないけどその機能だけは興味津々だった。

ゲームもネット対応で世界が爆発的に広まったけど、

現実世界でもコネクションができればネットとは異質の面白さがある。

何度かメッセージが交換されれば、

「電車でよくみかけるあの人」みたいな親近感があるだろうし。

おでかけもさらに楽しくなるよね。

買ってみて試してみたくなりました。

iPodにも同じ機能がついて、

他の人のiPodからあらかじめ設定したオススメ曲が聴けたりすると面白いよね。

ところで、DSのすれちがい通信って何でやってるのかな?

Bluetoothだと思うのだけど。。。

_ webで使えるExcel

web上でみんなで共有しながら使えるExcelページ無いかなー、

と探していたのですが、kzyさんに教えて頂きました。

NumSumというページです。無料で使えます。

簡単な計算もしてくれます。

Excelへ貼り付け、Excelから貼り付け(ImportDataから)もできるね。

デフォルトはみんなに公開だけど、

more properties からprivateに設定すると自分だけが閲覧可能です。

これは便利かも。

ちなみに、macではFirefoxで使えます。

Winでは、IEとかFIrefox。SafariやIE(mac)、OPERA(Win)はダメでした。

本日のツッコミ(全2件) [ツッコミを入れる]

_ sakurai [DSは、11bです。]

_ いが [マリオカートの対戦だと11bだと思うんですけど、 すれちがい通信の場合もそうなんでしょうか? 11bのサーバ・クライ..]


2021-12-17

_ Ruby3.0キーワード引数仕様変更に伴う書き換えをしたので調べたことのまとめ

igaigaです。この記事は Ruby Advent Calendar 2021 の17日目の記事です。昨日はフィヨルドブートキャンプでもお世話になっているyuuuさんの mruby-esp32-app-mirbをESP32で動かしてみた - panicの原因を見つけるまでの過程 でした。マイクロデバイスは胸が躍りますよね。

キーワード引数の仕様変更

Ruby2.7と3.0でキーワード引数の非互換を伴う仕様の整理が行われました。先日、Ruby2.6から2.7にバージョンアップすることがあり、この変更での書き換えを調べたのでまとめます。

また、本編とは直接関係ないですが、Ruby2.7.1から2.7.2へのバージョンアップでdeprecated カテゴリの警告はデフォルトで出力されなくなる変更が入ったので、Warningを出力するときは以下のようなオプションを指定します。 -W:deprecated の代わりに -W と書くとさらに広い範囲で全ての警告を表示します。

$ ruby -W:deprecated foo.rb
$ RUBYOPT='-W:deprecated' bin/rspec spec/foo_spec.rb

参考資料

以下の記事を参考にしました。特にmameさんの記事にたくさん助けられました。ありがとうございました。

概論(mameさんの記事より抜粋)

Ruby 3.0で、キーワード引数が通常の引数とは独立した引数になりました。これは非互換な変更になっています。

# キーワード引数を受け取るメソッド
def foo(key: 42)
end

foo(key: 42)      # OK: キーワード引数を渡している

opt = { key: 42 }
foo(opt)          # NG: 普通の引数を渡しているのでエラー(2.7では警告付きで動く)
foo(**opt)        # OK: ハッシュを明示的にキーワードに変換している

Ruby2.7までは普通の引数をキーワード引数に暗黙的に変換していましたが、3.0からはこの暗黙的変換を行わないようになりました。

ただし、キーワード引数から普通の引数への暗黙的変換は維持されています。削除するには互換性の影響が大きすぎるためだそうです。次のコードはRuby 3.0でも動作します。

# 普通のオプショナル引数を受け取るメソッド
def foo(opt = {})
end

foo(key: 42) # OK: キーワード引数が暗黙的に普通の引数に変換される

# # ↑は動きますが、今後は次のように書くのがおすすめです
# def foo(**opt)
# end

受け取った引数を別メソッドへ委譲するケースでのキーワード引数仕様変更

基本形

受け取った引数をそのまま全て別のメソッドの引数として渡すケースを考えます。Ruby2.7までは次のようなコードでした。

def foo(*args, &block)
  target(*args, &block)
end

Ruby3.0では次のようなコードになります。

def foo(*args, **kwargs, &block)
  target(*args, **kwargs, &block)
end

メソッド内で引数を変更しなければ、上記のコードと同じ動作を、以下のように委譲記法 ... で書けます。

def foo(...)
  target(...)
end
引数委譲記法 ... の拡張

引数委譲記法 ... では、先頭側の引数は変更できるようになっています。たとえば次のような書き方です。

def foo(arg1, ...) # 引数の先頭1つ目をarg1に入れ、残りは...で受け取る
  target(...) # 引数の先頭1つ目を抜いた残りを渡す
end

Ruby3.0で ... の先頭を取り除いたり、新しい値を追加できるようになりました。Ruby2.7へもバックポートされています。nagachikaさんありがとうございます。

Arguments forwarding (...) now supports leading arguments. Feature #16378

Ruby2.7での該当commit(動作確認して、Ruby2.7.3で入っていることを確認): https://github.com/ruby/ruby/commit/27fca66207f2c35f2f44f6a7cbbe6fd153546082

以下、mameさんのRuby3.0リリース時の記事より


https://techlife.cookpad.com/entry/2020/12/25/155741

キーワード引数の分離の悪影響の1つに、引数を委譲するのがめんどうになることがあります。そのため、Ruby 2.7では引数を委譲するための構文が導入されたのですが、引数を一切変更できないので使えるケースが限定されていました。

Ruby 3.0では、次のように、先頭の引数を取り除いたり、新しい値を追加したりすることが許されるようになりました。

def method_missing(meth, ...)
  send(:"do_#{meth}", ...)
end

先頭の引数以外はやはり変更できないのですが、これだけでも多くのケースが救われるという声が前述のヒアリングスレッドなどでも聞かれたため、導入されました。


実際に私の遭遇したケースでも先頭側の引数だけを取り除いて使いたいケースだったので、この機能で対応できました。

引数委譲記法 ... のサンプルコード

Ruby2.7.3, 3.0.3で実行して同様の結果で動作しました。 Ruby2.7.2ではエラー(syntax error, unexpected (... def foo(arg1, ...))になりました。

class Example
  def foo(arg1, ...) # 引数の先頭1つ目だけarg1に入れ、残りは...で受け取る
    p arg1 #=> :first
    bar(...) # 引数の先頭1つ目を抜いた残りを渡す
  end
  def bar(...)
    p(...) #=> "second", {:third=>3, :forth=>4}
  end
end

Example.new.foo(:first, "second", third: 3, forth: 4)

なお、上記のコードでの受け取り側引数arg1はarg1, arg2, arg3 と複数でも動作しました。

Ruby2.7 or Ruby3.0でのキーワード引数書き換え方法

https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/

"Handling argument delegation" を日本語訳したもの。

Ruby 2.6以前

Ruby 2では、*rest引数と&block引数を受け取り、その2つをターゲットメソッドに渡すことでデリゲーションメソッドを書くことができる。この動作では、位置引数(positional argument)とキーワード引数の自動変換により、キーワード引数も暗黙のうちに処理される。

def foo(*args, &block)
  target(*args, &block)
end
Ruby 3.0以降

キーワード引数を明示的に委譲する必要があります。

def foo(*args, **kwargs, &block)
  target(*args, **kwargs, &block)
end

また、Ruby 2.6 以前との互換性を必要とせず、引数を変更しない場合は、Ruby 2.7 で導入された新しいデリゲーション構文 (...) を使用することができます。

def foo(...)
  target(...)
end
Ruby 2.7

要約: Module#ruby2_keywords と delegate *args, &block を使えばいいのです。

ruby2_keywords def foo(*args, &block)
  target(*args, &block)
end

ruby2_keywordsはHashの最後の引数としてキーワード引数を受け取り、他のメソッドを呼び出す際にキーワード引数として渡します。

実際、Ruby 2.7 では多くの場合、この新しいスタイルのデリゲーションが可能です。しかし、既知のコーナーケースがあります。次のセクションを参照してください。

Ruby 2.6以前, 2.7, 3.0以降で動く書き方

要約: やっぱり Module#ruby2_keywords を使えばOK

ruby2_keywords def foo(*args, &block)
  target(*args, &block)
end

残念ながら、Ruby 2.6 以前のバージョンでは新しいデリゲーションスタイルを正しく扱えないため、古いスタイルのデリゲーション(つまり **kwargs がない)を使用する必要があります。これがキーワード引数分離の理由の一つです。詳細は最後のセクションで説明します。また、ruby2_keywordsを使うと、Ruby2.7や3.0でも古いスタイルのまま実行することができます。2.6以前ではruby2_keywordsは定義されていませんので、ruby2_keywords gemを使うか、自分で定義してください。

def ruby2_keywords(*)
end if RUBY_VERSION < "2.7"

もしあなたのコードがRuby 2.6以前で動作する必要がなければ、Ruby 2.7の新しいスタイルを試してみてもよいでしょう。ほとんどの場合、うまくいきます。しかし、以下のような不幸なコーナーケースがあることに注意してください。

def target(*args)
  p args
end

def foo(*args, **kwargs, &block)
  target(*args, **kwargs, &block)
end

foo({})       #=> Ruby 2.7: []   ({} is dropped)
foo({}, **{}) #=> Ruby 2.7: [{}] (You can pass {} by explicitly passing "no" keywords)

空のHash引数は自動的に変換されて**kwargsに吸収され、デリゲーションコールは空のキーワードHashを削除するので、targetに引数は渡されない。私たちが知る限り、これは唯一のコーナーケースです。

最後の行で述べたように、**{}を使うことでこの問題を回避することができます。

本当に移植性が心配なら、ruby2_keywords を使ってください。(Ruby 2.6以前では、キーワード引数には多くの問題があります。) ruby2_keywordsはRuby 2.6が終了した後、将来的に削除されるかもしれません。そのときは、キーワード引数を明示的に委譲することをお勧めします(上記のRuby 3のコードを参照)。


«前の日(12-16) 最新 次の日(12-18)» 追記