読者です 読者をやめる 読者になる 読者になる

( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

ScalaでRubyのObject#tapがぽぽぽぽ〜ん。っていうかいつでもmapしたい

scala

「まほうのこーどで♪ たのしい♪ れいがいが♪ ぬるぽぽ〜ん♪ 」


作ってみた。

// 入れ物はタッパーです。
trait Tapper[A] {
  val obj:A
  
  // RubyのObject#tap的な。引数fに自分自身を適用させて自身を返す。
  // 副作用専用メソッド。nullだったらなにもしなーい
  def tap(f:A => Unit):A = { Option(obj).foreach(f);obj }
   
  // 上記の、戻り値Option版。nullだったらNoneが返る
  def tapOption(f:A => Unit):Option[A] = { Option(obj).foreach(f);Option(obj) }
  
  // いつでもmapできたら便利よね?
  def map[B](f:A => B):Option[B] = Option(obj).map(f)
  
  // Option(obj)でもいいけど、何でもメソッドチェーンしたい病の人に
  def toOption:Option[A] = Option(obj)
}

// implict conversionで、タッパーに詰める
implicit def any2Tapper[A](a:A):Tapper[A] = new Tapper[A]{ val obj = a }


こういう風に使えば。nullとか気にしないでよくなるよねー。ぽぽぽぽ〜ん。まぁこの例のカレンダーだったらブロックに初期化処理を詰めてもいんだけどね。nullチェックとかウザいし。

scala> import java.util.Calendar
import java.util.Calendar

scala> val c1 = Calendar.getInstance.tap{ c =>
     |   c.add(1, Calendar.MONTH )
     |   c.add(1, Calendar.YEAR )
     | }
c1: java.util.Calendar = java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2014,MONTH=2,WEEK_OF_YEAR=12,WEEK_OF_MONTH=4,DAY_OF_MONTH=23,DAY_OF_YEAR=82,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=1,HOUR_OF_DAY=13,MINUTE=30,SECOND=19,MILLISECOND=552,ZONE_OFFSET=32400000,DST_OFFSET=0]

scala> (new java.text.SimpleDateFormat).map { fmt => fmt.format(c1.getTime) }
res0: Option[java.lang.String] = Some(14/03/23 13:30)

scala> val c2:Calendar = null
c2: java.util.Calendar = null

scala> val c3 = c2.tap{ c =>
     |   c.add(1, Calendar.MONTH )
     |   c.add(1, Calendar.YEAR )
     | }
c3: java.util.Calendar = null