search term:

sff4s: simple future facade for Scala

future ใฎๅฎŸ่ฃ…ใซใฏๆง˜ใ€…ใชใ‚‚ใฎใŒใ‚ใ‚‹ใ‘ใฉใ€ๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎไธญใซๅ…ฑ้€šใฎ่ฆช trait ใŒใ‚ใ‚Œใฐใ€็‰นๅฎšใฎใƒ—ใƒฉใƒƒใƒˆใƒ•ใ‚ฉใƒผใƒ ใ‚นใ‚ฟใƒƒใ‚ฏใซใ‚ณใƒผใƒ‰ใ‚’ไพๅญ˜ใ•ใ›ใšใซใ“ใฎๆฆ‚ๅฟตใ‚’่กจ็พใงใใ‚‹ใฎใซใจๆ€ใฃใฆใ„ใŸใ€‚ใใ†ๆ€ใ†ไบบใŒไป–ใซใ‚‚ใ„ใ‚‹ใ‹ใฏๅˆ†ใ‹ใ‚‰ใชใ„ใ‘ใฉใ€ใƒฉใ‚คใƒ–ใƒฉใƒชใฎไฝœ่€…ใชใ‚“ใ‹ใซใฏๅฝนใซ็ซ‹ใคใ‚“ใ˜ใ‚ƒใชใ„ใ‹ใชใ€‚ๅ–ใ‚Šๆ•ขใˆใšใ“ใ‚ŒใŒใ€sff4s ใ‚’ๆ›ธใ„ใŸๅ‹•ๆฉŸใ ใ€‚

future ใฃใฆไฝ•?

ๅคšๅˆ†ๅๅ‰ใใ‚‰ใ„ใฏ่žใ„ใŸใ“ใจใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ‘ใฉใ€ไธ€ๅฟœใŠใ•ใ‚‰ใ„ใ—ใ‚ˆใ†ใ€‚futureๅ€ค๏ผˆpromise ใจใ‚‚ๅ‘ผใฐใ‚Œใ‚‹๏ผ‰ใฏๆœชๅฎŒใฎ่จˆ็ฎ—ใ‚’่กจ็พใ™ใ‚‹ใ€‚

ใ“ใ‚ŒใŒใ‚ˆใไฝฟใ‚ใ‚Œใ‚‹่ชฌๆ˜Žใ ใ‘ใฉใ€ใใ‚Œใ ใ‘ใงใฏๅˆ†ใ‹ใ‚‰ใชใ„ใ€‚ใ“ใ“ใง่จ€ๅค–ใซๅซใพใ‚Œใฆใ„ใ‚‹ใฎใฏใ€ใใฎ่จˆ็ฎ—ใฏ่ฃใง่กŒใ‚ใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใ ใ€‚ใใ‚ŒใฏๅŒใ˜ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟๅ†…ใฎๅˆฅใฎใ‚นใƒฌใƒƒใƒ‰ใ‹ใ€ๅˆฅใฎใ‚ตใƒผใƒใฎไธญใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ—ใ€่กŒๅˆ—ๅพ…ใกใงใพใ ่จˆ็ฎ—ใฏๅง‹ใพใฃใฆใ•ใˆใ„ใชใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ใจใซใ‹ใใ€่จˆ็ฎ—ใฏ็พๅœจใฎๅˆถๅพกใƒ•ใƒญใƒผใฎๅค–ใง่กŒใ‚ใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใ ใ€‚

futureๅ€คใฎใ‚‚ใ†ไธ€ใคใฎๅด้ขใฏใ€ใใฎใ†ใกใซ่จˆ็ฎ—็ตๆžœใ‚’ๅพ—ใ‚‰ใ‚Œใ‚‹ใจใ„ใ†ใ“ใจใ ใ€‚Scala ใฎๅ ดๅˆใฏ def apply() ใ‚’ๅ‘ผใณๅ‡บใ™ใชใฉใฎๆ˜Ž็คบ็š„ใชใ‚นใƒ†ใƒƒใƒ—ใ‚’่ฆใ™ใ‚‹ใ€‚่จˆ็ฎ—ใŒๆœชๅฎŒใฎๅ ดๅˆใฏใ€ใƒ–ใƒญใƒƒใ‚ฏ(block)ใ™ใ‚‹ใ€‚ใคใพใ‚Šใ€่จˆ็ฎ—็ตๆžœใŒๅพ—ใ‚‰ใ‚Œใ‚‹ใพใงๅพ…ใŸใ•ใ‚Œใ‚‹๏ผˆใ‚‚ใ—ใใฏใ‚ฟใ‚คใƒ ใ‚ขใ‚ฆใƒˆใ™ใ‚‹๏ผ‰ใ€‚

ๆœ€ๅˆใซ futureๅ€คใŒๅฎฃ่จ€ใ•ใ‚ŒใŸๆ™‚ใซใฏ่จˆ็ฎ—็ตๆžœใฏๆœ‰ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ—ใ€ใพใ ็„กใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ใ†ใพใใ„ใ‘ใฐใ€ใ‚ใ‚‹ๆ™‚็‚นใง็ตๆžœใŒๅˆฐ็€ใ—ใ€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๅ†…้ƒจๆง‹้€ ใŒๅค‰ๆ›ดใ•ใ‚Œใ‚‹ใ€‚ใ“ใ‚Œใ‚’ใ€futureๅ€คใ‚’ใ€Œ่งฃๆฑบใ€(resolve)ใ—ใŸใจใ„ใ†ใ€‚ๅ‹ๆ‰‹ใซ็Šถๆ…‹ใŒๅค‰ใ‚ใ‚‹ใ‚‚ใฎใจใ„ใ†ใฎใฏใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐใงใฏใ‚ใพใ‚Š่ฆ‹ใ‹ใ‘ใชใ„ใฎใงใ€ๅฐ‘ใ—ไธๆฐ—ๅ‘ณใงใฏใ‚ใ‚‹ใ€‚

ใ“ใ‚Œใพใงใงใ€ๆœ€ใ‚‚ๅ˜็ด”ใชๅฝขใฎ futureๅ€คใ‚’่จ˜่ฟฐใ—ใŸใ€‚ๅฎŸ้š›ใซๅฝนใซ็ซ‹ใคใซใฏไป–ใฎๆฉŸ่ƒฝใ‚‚ๅฟ…่ฆใ ใ‘ใฉใ€ใ“ใ‚Œใงใ‚‚ไฝฟใˆใชใ„ใ“ใจใฏใชใ„ใ€‚ใกใ‚‡ใฃใจไฝฟ็”จไพ‹ใ‚’ใฟใฆใฟใ‚ˆใ†:

val factory = sff4s.impl.ActorsFuture
val f = factory future {
  Thread.sleep(1000)
  1
}
f() // => ใ“ใ‚Œใฏ 1็ง’้–“ใƒ–ใƒญใƒƒใ‚ฏใ—ใŸๅพŒใง 1 ใ‚’่ฟ”ใ™

็ดฐใ‹ใ„ไบ‹ใฏๆฐ—ใซใ—ใชใ„ใงใ€ๆœ€ๅพŒใฎไธ€่กŒใฎๆŒฏใ‚‹่ˆžใ„ใ ใ‘่ฆ‹ใฆใปใ—ใ„ใ€‚ใ“ใฎใ‚ˆใ†ใซใ€่จˆ็ฎ—็ตๆžœใ‚’ๅ–ๅพ—ใ™ใ‚‹ใ“ใจใ‚’ใ€ๅผท่ฆ(forcing)ใ™ใ‚‹ใจใ‚‚ใ„ใ†ใ€‚ๆœ€ๅฐ้™ใฎ API ใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚‹ใ€‚

Future v0.1

abstract class Future[+A] {
  /** ่จˆ็ฎ—็ตๆžœใ‚’ๅผท่ฆใ—ใฆ็„กๆœŸ้™ใซใƒ–ใƒญใƒƒใ‚ฏใ™ใ‚‹ */
  def apply(): A
}

Scala ใ‹ใ‚‰ไฝฟ็”จๅฏ่ƒฝใช futureๅ€คใฎๅฎŸ่ฃ…ใซใฏใ„ใใคใ‹ใ‚ใ‚‹ใ‘ใฉใ€ใฉใ‚Œใ‚‚ไธ€ใ‹ใ‚‰ๆ›ธใ‹ใ‚Œใฆใ‚‹ใ€‚ไธŠใฎใ‚ˆใ†ใชๅ…ฑ้€šใช่ฆชใ‚ฏใƒฉใ‚นใŒใ‚ใ‚Œใฐใ€็‰นๅฎšใฎใƒฉใ‚คใƒ–ใƒฉใƒชใซไพๅญ˜ใ—ใชใ„ใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใใ“ใจใŒใงใใ‚‹ใ€‚

ใพใ ๆฅใชใ„?

Future v0.1 ใซๅฏพใ—ใฆๅ”ฏไธ€ใงใใ‚‹ไบ‹ใŒ่จˆ็ฎ—็ตๆžœใŒๆˆปใฃใฆใใ‚‹ใพใงใƒ–ใƒญใƒƒใ‚ฏใ—ใฆใ—ใพใ†ใฎใงใ€ใ‚ใพใ‚Šใซใ‚‚ไธไพฟใ ใ€‚ๅพ…ใคใ“ใจใ—ใ‹ใงใใชใ„ใ‹ใ‚‰ future ใ‚’ไฝฟใ‚ใชใ„ใปใ†ใŒใ„ใ„ใ€‚ใใฎใŸใ‚ใ€ๅ…จใฆใฎ futureๅ€คใŒๆไพ›ใ™ใ‚‹ใ‚‚ใ†ไธ€ใคใฎๆฉŸ่ƒฝใจใ—ใฆใ€่จˆ็ฎ—็ตๆžœใฎ็”จๆ„ใŒใงใใŸใ‹ใ‚’็ขบใ‹ใ‚ใ‚‹ใƒŽใƒณใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐ(non-blocking)ใชๆ–นๆณ•ใŒใ‚ใ‚‹ใ€‚ใ“ใ‚ŒใฏๅฎŸ่ฃ…ใซใ‚ˆใฃใฆ isDoneใ€isSetใ€isDefinedใ€isCompleted ใชใฉใจๅ‘ผใฐใ‚Œใฆใ„ใ‚‹ใŒใ€ๅ…จใฆๅŒใ˜ๆ„ๅ‘ณใ ใ€‚ไปŠใฎใจใ“ใ‚ใ€ๅƒ•ใฎๅฅฝใฟใจใ—ใฆใฏ def isDefined: Boolean ใŒใ„ใ„ใจๆ€ใ†ใ€‚future ใ‚’ๆฆ‚ๅฟต็š„ใซ Option ใฎๅค‰ๆ•ฐใจใ—ใฆ่€ƒใˆใ‚‹ใ“ใจใŒใงใใ‚‹ใ‹ใ‚‰ใ ใ€‚

Future v0.2

abstract class Future[+A] {
  def apply(): A
  
  /** ่จˆ็ฎ—็ตๆžœใŒ็”จๆ„ใงใใŸใ‹ใ‚’็ขบใ‹ใ‚ใ‚‹ */
  def isDefined: Boolean
}

ใ‚ฟใ‚คใƒ ใ‚ขใ‚ฆใƒˆ

ใ‚‚ใ†ไธ€ใคใฎใ‚ˆใใ‚ใ‚‹ๆฉŸ่ƒฝใจใ—ใฆใฏใ€ๆœ‰้™ใฎๆ™‚้–“ใ ใ‘ใƒ–ใƒญใƒƒใ‚ฏใ™ใ‚‹ใจใ„ใ†ใ‚‚ใฎใŒใ‚ใ‚‹ใ€‚ไพ‹ใˆใฐใ€ใ“ใ‚Œใฏใ€def apply(timeoutInMsec: Long) ใจๆ›ธใใ“ใจใŒใงใใ‚‹ใ€‚ๆŒ‡ๅฎšใ•ใ‚ŒใŸๆ™‚้–“ๅ†…ใซ่จˆ็ฎ—ใŒ่ฟ”ใฃใฆใ“ใชใ‘ใ‚Œใฐใ€TimeoutException ใŒๆŠ•ใ’ใ‚‰ใ‚Œใ‚‹ใ€‚

Future v0.3

abstract class Future[+A] {
  def apply(): A
  
  def apply(timeoutInMsec: Long): A
  
  def isDefined: Boolean
}

ใพใ ๆœ€ๅฐ้™ใจใ„ใ†ๆ„Ÿใ˜ใ ใ‘ใฉใ€ใ“ใฎ็Šถๆ…‹ใงไฝฟใ„ๅง‹ใ‚ใ‚‹ใ“ใจใŒใงใใ‚‹ใ€‚

ใ‚คใƒ™ใƒณใƒˆใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ

ใ‚ฟใ‚คใƒ ใ‚ขใ‚ฆใƒˆใจใ„ใ†ใฎใฏๆ–นๆณ•ใจใ—ใฆๆ นๆœฌ็š„ใชๅ•้กŒใŒใ‚ใ‚‹ใ€‚่ฃใง่กŒใ‚ใ‚Œใฆใ„ใ‚‹ๆผ”็ฎ—ใŒ้•ทๆ™‚้–“ใซๆธกใฃใŸๅ ดๅˆใ€่จˆ็ฎ—็ตๆžœใ‚’ๅพ…ใคใŸใ‚ใซใ„ใใคใ‚‚ใฎใƒซใƒผใƒ—ใ‚’็ฎก็†ใ—ใชใใฆใฏใ„ใ‘ใชใ„ใจใ„ใ†ใ“ใจใ ใ€‚ใ‚ˆใ‚Šๅ˜็ด”ใชใฎใฏใ€ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใŸใ‚ใฎใ‚ฏใƒญใƒผใ‚ธใƒฃใ‚’ๆธกใ—ใฆใŠใ„ใฆใ€่จˆ็ฎ—็ตๆžœใฎ็”จๆ„ใŒใงใใŸๆ™‚็‚นใง futureๅ€คใซๅ‘ผใณๅ‡บใ—ใฆใ‚‚ใ‚‰ใ†ใจใ„ใ†ๆ–นๆณ•ใ ใ€‚ใ„ใ‚ˆใ„ใ‚ˆ่ฉฑใŒ้žๅŒๆœŸใซใชใฃใŸใใŸใ€‚twitter ใฎ future ใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ def onSuccess(f: A => Unit): Future[A] ใ‚’ๆŽก็”จใ—ใŸใ€‚ไฝฟ็”จไพ‹ใ‚’่ฆ‹ใฆใฟใ‚ˆใ†:

f onSuccess { value =>
  println(value) // => "1" ใจ่กจ็คบใ™ใ‚‹
}

ๅๅ‰ๆธกใ—(call-by-name)ใฎใŠ้™ฐใง Scala ใฏไธŠใฎใƒ–ใƒญใƒƒใ‚ฏใฎใ‚ณใƒผใƒ‰ใ‚’็›ดใกใซใฏๅฎŸ่กŒใ—ใชใ„ใ€‚ ใพใŸใ€futureๅ€คใซใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉใŒ่ฟฝๅŠ ใ•ใ‚Œใ‚‹ใ ใ‘ใงใ€่จˆ็ฎ—ๅ€คใใฎใ‚‚ใฎใฏๅค‰ใ‚ใ‚‰ใชใ„ใ“ใจใซๆณจๆ„ใ€‚

ใ‚จใƒฉใƒผๅ‡ฆ็†

ไธŠใฎใ‚คใƒ™ใƒณใƒˆใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใŒ onSuccess ใจๅไป˜ใ‘ใ‚‰ใ‚Œใ‚‹ใ“ใจใ‹ใ‚‰ใ€ๆฌกใฎ่ฉฑ้กŒใŒ่จˆ็ฎ—ใฎๅคฑๆ•—ใงใ‚ใ‚‹ใ“ใจใฏไบˆๆƒณใงใใŸใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ใใฎๅ‰ใซใ€ๆœ€ๅˆใฎ็ฏ€ใงใฎใƒใ‚คใƒณใƒˆใ‚’ๆ€ใ„ๅ‡บใ—ใฆใปใ—ใ„: ่จˆ็ฎ—ใฏใฉใ“ใ‹ๅˆฅใฎๆ‰€ใง่กŒใ‚ใ‚Œใ‚‹ใ€‚ไพ‹ใˆใฐใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใฎใ‚นใƒฌใƒƒใƒ‰ไธŠใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใจใ—ใฆใ€ไฝ•ใ‚‰ใ‹ใฎไพ‹ๅค–ใŒๆŠ•ใ’ใ‚‰ใ‚ŒใŸใจใ™ใ‚‹ใ€‚ใฉใ†ใ™ใ‚Œใฐใ„ใ„๏ผŸ็พๅœจใฎๅˆถๅพกใƒ•ใƒญใƒผไธญใซใ„ใใชใ‚Šไพ‹ๅค–ใ‚’ๆŠ•ใ’่พผใ‚€ในใใ ใ‚ใ†ใ‹ใ€‚ๅคšๅˆ†ใ€้•ใ†ใ€‚ๅ“ฒๅญฆๅ•็ญ”ใซใ€ใ€Œ่ชฐใ‚‚ใ„ใชใ„ๆฃฎใฎไธญใงๆœจใŒๅ€’ใ‚Œใ‚‹ใจใใ€้ŸณใŒใ™ใ‚‹ใ ใ‚ใ†ใ‹ใ€ใจใ„ใ†ใ‚‚ใฎใŒใ‚ใ‚‹ใŒใ€ใใ‚Œใซ่ฟ‘ใ„ใ‚‚ใฎใŒใ‚ใ‚‹ใ€‚ไฝ•ใŒ่ตทใ“ใ‚‹ใ‹ใจ่จ€ใ†ใจใ€ๅ…จใฆใฎไพ‹ๅค–ใฏๅ†…้ƒจ็Šถๆ…‹ๅ†…ใซๆ•ๆ‰ใ•ใ‚Œใฆใ€่จˆ็ฎ—ๅ€คใŒ apply() ใซใ‚ˆใฃใฆๅผท่ฆใ•ใ‚Œใ‚‹ๆ™‚ใซๅ†็พใ•ใ‚Œใ‚‹ใ€‚

ใ“ใฎๆฆ‚ๅฟตใฎใ€Scala ใงใฎๆ…ฃไพ‹็š„ใช่กจ็พใฏ Either ใ ใ€‚ใƒ‘ใƒฉใƒกใƒผใ‚ฟไป˜ใๅž‹ใฎ Future[A] ใฏใฉใฎใ‚ˆใ†ใชใ‚จใƒฉใƒผใŒๆฝœๅœจ็š„ใซๆŠ•ใ’ใ‚‰ใ‚Œใ‚‹ใ‹ใ‚’่กจใ•ใชใ„ใŸใ‚ใ€ๅƒ•ใฏ Either[Throwable, A] ใจใ—ใŸใ€‚

ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚จใƒฉใƒผๅ‡ฆ็†ใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใงใ‚ใ‚‹ def onFailure(rescueException: Throwable => Unit): Future[A] ใŒๅฏ่ƒฝใจใชใ‚‹ใ€‚ๅฎŸ่ฃ…ไธŠใฏใ€onSuccess ใ‚‚ onFailure ใ‚‚ใ‚ˆใ‚Šไธ€่ˆฌ็š„ใชใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใงใ‚ใ‚‹ def respond(k: Either[Throwable, A] => Unit): Future[A] ใฎ็‰นๆฎŠๅฝขใจใฟใชใ™ใ“ใจใŒใงใใ‚‹ใ€‚

ใ‚จใƒฉใƒผ็Šถๆ…‹ใŒ Either ใจใ—ใฆๆ•ๆ‰ใ•ใ‚Œใ‚‹ใŸใ‚ใ€ๅผท่ฆใฏ def get: Either[Throwable, A] ใจใ—ใฆๅฎŸ่ฃ…ใ•ใ‚Œใ€apply() ใฏใใ‚Œใ‚’ไปฅไธ‹ใฎใ‚ˆใ†ใซๅ‘ผใณๅ‡บใ™ใ“ใจใซใ—ใŸ:

def apply(): A = get.fold(throw _, x => x)

Future v0.4:

abstract class Future[+A] {
  def apply(): A = get.fold(throw _, x => x)
  def apply(timeoutInMsec: Long): A = get(timeoutInMsec).fold(throw _, x => x)
  
  def isDefined: Boolean
    
  /** forces calculation result */
  def get: Either[Throwable, A]
  def get(timeoutInMsec: Long): Either[Throwable, A]
  
  def value : Option[Either[Throwable, A]] =
    if (isDefined) Some(get)
    else None  
  
  /** ่จˆ็ฎ—็ตๆžœใฎ็”จๆ„ใงใใŸใ‚‰ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ๅ‘ผใณๅ‡บใ™ */
  def respond(k: Either[Throwable, A] => Unit): Future[A]  
  
  def onSuccess(f: A => Unit): Future[A] =
    respond {
      case Right(value) => f(value)
      case _ =>
    }
    
  def onFailure(rescueException: Throwable => Unit): Future[A] =
    respond {
      case Left(e) => rescueException(e)
      case _ =>
    }
}

ใ ใ‚“ใ ใ‚“่‰ฏใใชใฃใฆใใŸใ€‚ไบ‹ๅฎŸใ€ใ“ใ‚Œใ‚‰ใฎๆฉŸ่ƒฝใฏๆ—ขใซ java.util.concurrent.Future ใงๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ๅŸบๆœฌๆฉŸ่ƒฝใ‚’่ฟฝใ„่ถŠใ—ใฆใ„ใ‚‹ใŸใ‚ใ€็‹ฌ่‡ชใฎๅฎŸ่ฃ…ใ‚’ๆไพ›ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใฃใŸใ€‚

ใƒขใƒŠใƒ‰้€ฃ้Ž–

ใ“ใ‚Œใง๏ผˆใ‚„ใฃใจ๏ผ‰ๅฎŸ้š›ใฎ future ใ‚’ไฝฟใฃใŸ่ฉฑใ‚’ใ™ใ‚‹ไธ‹ๅœฐใŒๆ•ดใฃใŸใ€‚ใ“ใ‚Œใพใงใฏใ€่จˆ็ฎ—็ตๆžœใ‚’ๅ–ใ‚Šๅ‡บใ™่ฉฑใฐใฃใ‹ใ‚Šใ‚’ใ—ใŸใใŸใŒใ€ใใ‚Œใฏๆœชๆฅๅ€คใจใ„ใ†ใ‚ˆใ‚Šใฏ็พๅœจๅ€คใ ใ€‚่จˆ็ฎ—ๅ€คใฎ็”จๆ„ใŒใงใใ‚‹ๅ‰ใซ futureๅ€คใ‚’็”จใ„ใฆๅˆฅใฎ futureๅ€คใ‚’่จˆ็ฎ—ใ™ใ‚‹ๆ–นใŒ้ข็™ฝใ„ใ“ใจใŒใงใใ‚‹ใ€‚ใ‚ใ‚‹็‰ฉใฎๅ€คใ‹ใ‚‰ๅˆฅใฎ็‰ฉใ‚’่จˆ็ฎ—ใ™ใ‚‹… ใƒขใƒŠใƒ‰ใ ใ‚ใ€ใ“ใ‚Œใฏใ€‚ไฝฟ็”จไพ‹ใซ้€ฒใ‚€!

val g = f map { _ + 1 }

ใ•ใฃใๆ‰“ใก่พผใ‚“ใ ใฐใฃใ‹ใ‚Šใ ใ‹ใ‚‰ f() ใŒใฉใ†่งฃๆฑบใ™ใ‚‹ใ‹ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใŒใ€็Ÿฅใ‚‰ใชใ„ใƒ•ใƒชใ‚’ใ—ใ‚ˆใ†ใ€‚ใคใพใ‚Šใ€ใ“ใ“ใซๆœช็Ÿฅใฎ Future[Int] ใŒใ‚ใ‚‹ใจใ™ใ‚‹ใ€‚ใใฎๅ€คใŒใชใ‚“ใงใ‚ใ‚ใ†ใจใ€1 ใ‚’ๅŠ ใˆใ‚‹ใ€‚ใ“ใ‚Œใฏใ€ใพใŸๅˆฅใฎๆœช็Ÿฅใฎ futureๅ€คใจใชใ‚‹ใ€‚ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใง f ใŒๅคฑๆ•—ใ—ใŸๅ ดๅˆใ€Option ใ‚’ map ใ™ใ‚‹ใจใใฎใ‚ˆใ†ใซใ€ๅ…จไฝ“ใŒๅคฑๆ•—ใ™ใ‚‹ใ€‚

ใ“ใ‚Œใ‚‰ใ‚’ for ๅผใ‹ใ‚‰ไฝฟใ†ใ“ใจใ‚‚ใงใใ‚‹:

val xFuture = factory future {1}
val yFuture = factory future {2}

for {
  x <- xFuture
  y <- yFuture
} {
  println(x + y) // => prints "3"
}

้•ทใใชใ‚‹ใฎใงใ€ใ“ใ‚Œใ‚‰ใฎใ‚ทใ‚ฐใƒใƒใƒฃใ ใ‘ใ‚’ๆ›ธใใ ใ™ใ€‚

  def foreach(f: A => Unit)
  def flatMap[B](f: A => Future[B]): Future[B]
  def map[B](f: A => B): Future[B]
  def filter(p: A => Boolean): Future[A]

select ใจ join

twitter ใฎ Future ใ‹ใ‚‰ใ‚‚ใ†ไบŒใค้ข็™ฝใ„ใƒกใ‚ฝใƒƒใƒ‰ select(other) ใจ join(other) ใ‚’่ฟฝๅŠ ใ—ใŸใ€‚ select (ๅˆฅๅ or) ใฏใ‚‚ใ†ไธ€ใคใฎ Future ใ‚’ๅผ•ๆ•ฐใซใจใ‚Šใ€ๆœ€ๅˆใซๆˆๅŠŸใ—ใŸใ‚‚ใฎใ‚’่ฟ”ใ™ใ€‚

ๅŒๆง˜ใซใ€join ใ‚‚ๅˆฅใฎ Future ใ‚’ๅผ•ๆ•ฐใซๅ–ใ‚Šใ€ไธ€ใคใฎ Future ใซ็ต„ใฟๅˆใ‚ใ›ใ‚‹ใ€‚

Future v0.5:

abstract class Future[+A] {
  def apply(): A = get.fold(throw _, x => x)
  def apply(timeoutInMsec: Long): A = get(timeoutInMsec).fold(throw _, x => x)
  def isDefined: Boolean
  def get: Either[Throwable, A]
  def get(timeoutInMsec: Long): Either[Throwable, A]
  def value : Option[Either[Throwable, A]] =
    if (isDefined) Some(get)
    else None  
  def respond(k: Either[Throwable, A] => Unit): Future[A]  
  def onSuccess(f: A => Unit): Future[A] =
    respond {
      case Right(value) => f(value)
      case _ =>
    }
  def onFailure(rescueException: Throwable => Unit): Future[A] =
    respond {
      case Left(e) => rescueException(e)
      case _ =>
    }
  
  def foreach(f: A => Unit)
  def flatMap[B](f: A => Future[B]): Future[B]
  def map[B](f: A => B): Future[B]
  def filter(p: A => Boolean): Future[A]
  
  def select[U >: A](other: Future[U]): Future[U]
  def or[U >: A](other: Future[U]): Future[U] = select(other)
  def join[B](other: Future[B]): Future[(A, B)] 
}

ใ“ใ‚Œใงไฝฟใ„ใ‚„ใ™ใ„ futureๅ€คใฎๆŠฝ่ฑกไฝ“ใŒใงใใ‚ใŒใฃใŸใ€‚

ๆถˆ่ฒป่€…ใจ็”Ÿ็”ฃ่€…

futureๅ€คใŒใฉใฎใ‚ˆใ†ใซใ—ใฆไฝœใ‚‰ใ‚Œใ‚‹ใ‹ใฎ่ฉฑใ‚’ใ™ใ‚‹ๅ‰ใซใ€ๅฐ‘ใ—ใใฎ่ƒŒๆ™ฏใซ้–ขใ™ใ‚‹่ฉฑใ‚’ใ™ใ‚‹ใ€‚ futureๅ€คใฏๆœชๅฎŒใฎ่จˆ็ฎ—ใ‚’่กจ็พใ™ใ‚‹ใ€‚ใ“ใฎ่จˆ็ฎ—ใฏๆœ€ๅˆใซใ‚ณใƒณใ‚ทใƒฅใƒผใƒž๏ผˆconsumerใ€ๆถˆ่ฒป่€…๏ผ‰ใซใ‚ˆใฃใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ•ใ‚Œใ€ใƒ—ใƒญใƒ‡ใƒฅใƒผใ‚ต๏ผˆproducerใ€็”Ÿ็”ฃ่€…๏ผ‰ใซใ‚ˆใฃใฆ่งฃๆฑบใ•ใ‚Œใ‚‹ใ€‚ๅˆฅใฎ่จ€ใ„ๆ–นใ‚’ใ™ใ‚‹ใจใ€ใ‚ณใƒณใ‚ทใƒฅใƒผใƒžใฎ่ฆ–็‚นใ‹ใ‚‰ใฏใ ใ„ใŸใ„ใฎ็‚นใซใŠใ„ใฆ read-only ใชๅ€คใ ใ‘ใฉใ€ใƒ—ใƒญใƒ‡ใƒฅใƒผใ‚ตๅดใ‹ใ‚‰ใฏๆ›ธใ่พผใฟๅฏ่ƒฝใชใƒ‡ใƒผใ‚ฟๆง‹้€ ใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใ„ใ†ใ“ใจใ ใ€‚ใ“ใ‚Œใพใงใซๅฎš็พฉใ—ใŸ Future ใฏๅ‰่€…ใ ใ€‚

ใ“ใ‚Œใฏ็•ฐใชใ‚‹ใ‚ทใ‚นใƒ†ใƒ ใฎ้•ใ„ใซใ‚ˆใ‚‹ใ€‚ๅคงใพใ‹ใซ่จ€ใ†ใจใ€java.util.concurrency.Futureใ€actors.Futureใ€akka.dispatch.Future ใฏใƒฆใƒผใ‚ถใŒๅง‹ๅ‹•ใ—ใŸ่จˆ็ฎ—ใ‚’ๅˆฅใฎ CPU ใ‚ณใ‚ขใ‹ๅˆฅใฎใƒžใ‚ทใƒณใซๅค–ๆณจใ™ใ‚‹ใฎใซไฝฟใ‚ใ‚Œใ‚‹ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚ทใ‚นใƒ†ใƒ ใงใฏ่งฃๆฑบใ‚นใƒ†ใƒƒใƒ—ใฏ API ใซใฏ้š ่”ฝใ•ใ‚ŒใฆใŠใ‚Šใ€ๅ†…้ƒจใง่‡ชๅ‹•็š„ใซ่กŒใ‚ใ‚Œใ‚‹ใ€‚

ไธ€ๆ–นใ€com.twitter.util.Future ใฏไธฆ่กŒ่จˆ็ฎ—ใฎๆฉŸๆง‹ใ‚’ๆไพ›ใ—ใชใ„ใŸใ‚ใ€ใ‚ณใƒณใ‚ทใƒฅใƒผใƒžใจใƒ—ใƒญใƒ‡ใƒฅใƒผใ‚ตใฎไธก่€…ใ‚’ๆผ”ใ˜ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ€‚้€†ใซ่จ€ใ†ใจใ€ใƒ—ใƒญใƒ‡ใƒฅใƒผใ‚ตๅดใ‚’ๅฅฝใใชใ‚ˆใ†ใซใ‚ณใƒณใƒˆใƒญใƒผใƒซใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ใจ่€ƒใˆใ‚‹ใ“ใจใ‚‚ใงใใ‚‹ใ€‚

็™บ้€ๅ“ก

sff4s ใฏไธŠ่จ˜ใฎๅ››ใคใฎ future ๅฎŸ่ฃ…ใซๅฏพใ™ใ‚‹ใƒ‡ใ‚ฃใ‚นใƒ‘ใƒƒใƒใƒฃ๏ผˆdispatcherใ€็™บ้€ๅ“ก๏ผ‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆไพ›ใ™ใ‚‹ใ€‚ใ“ใ‚Œใฏๅ†…้ƒจใ‚ทใ‚นใƒ†ใƒ ใซ่จˆ็ฎ—ใ‚’็™บ้€๏ผˆdispatch๏ผ‰ใ™ใ‚‹ future ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅฎš็พฉใ™ใ‚‹ใ€‚ๆœ€ๅˆใฎไฝฟ็”จไพ‹ใ‚’ใ‚‚ใ†ไธ€ๅบฆใฟใฆใฟใ‚ˆใ†:

val factory = sff4s.impl.ActorsFuture
val f = factory future {
  Thread.sleep(1000)
  1
}

ใ“ใ‚Œใฏๅ†…้ƒจใง scala.acotors.Futures ใฎ future ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ใซใ‚ˆใ‚Šใƒ–ใƒญใƒƒใ‚ฏใฎ่จˆ็ฎ—ใ‚’็™บ้€ใ—ใฆใ„ใ‚‹ใ€‚ ใ“ใ“ใงๆณจๆ„ใŒๅฟ…่ฆใชใฎใฏ sff4s.impl.TwitterUtilFuture ใฎ future ใƒกใ‚ฝใƒƒใƒ‰ใฏใ€ActorsFuture ใฎใ‚ˆใ†ใช้žๅŒๆœŸใชๆŒฏใ‚‹่ˆžใ„ใ‚’ๆœŸๅพ…ใ—ใฆใ„ใ‚‹ใจใ‚ฌใƒƒใ‚ซใƒชใ™ใ‚‹็ตๆžœใจใชใ‚‹ใจใ„ใ†ใ“ใจใ ใ€‚

ๆš—้ป™ใฎๅค‰ๆ›

ใƒ‡ใ‚ฃใ‚นใƒ‘ใƒƒใƒใƒฃใฏใ€ใƒใ‚คใƒ†ใ‚ฃใƒ–ใช futureๅ€คใ‹ใ‚‰ใƒฉใƒƒใƒ”ใƒณใ‚ฐใ•ใ‚ŒใŸใ‚‚ใฎใซๅค‰ใˆใ‚‹ๆš—้ป™ใฎๅค‰ๆ›๏ผˆimplicit converter๏ผ‰ใ‚‚ๅฎŸ่ฃ…ใ™ใ‚‹ใ€‚

import factory._
val native = scala.actors.Futures future {5}
val w: sff4s.Future[Int] = native
w() // => This blocks for the futures result (and eventually returns 5)

ๆ„Ÿๆƒณใจใ‹

sff4s ใฏใ“ใ“ๆ•ฐๆ—ฅใงๆ›ธใ„ใŸใ‚‚ใฎใชใฎใงใ€ไปŠๅพŒใƒใ‚ฐใƒ•ใ‚ฃใ‚ฏใ‚นใ‚„ๅค‰ๆ›ดใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ใ”ๆ„่ฆ‹ใ€ๆ„Ÿๆƒณใชใฉใ€ๅพ…ใฃใฆใพใ™ใ€‚