//why monads tutorial
class CompanyInfo { /* important shit here */ }
def getCompanyInfoFromDB(user: User, companyname: String) = ??? //prototype method
//java style classes
class Company { var name: String }
class User { var company: Company }
class Session { var user: User }
def getCompanyInfo(session: Session, newname: String): CompanyInfo {
//BIG FAT RACE CONDITION, POSSIBLE NPE. NOT THREAD SAFE
if (session.user != null && session.user.company != null)
return getCompanyInfoFromDB(session.user, session.user.company.name)
else
return null
}
//Functional (mutable) style
class Company { var name: Option[String] }
class User { var company: Option[Company] }
class Session { var user: Option[User] }
def getCompanyInfoDesugared(session: Session, newname: String): Option[CompanyInfo] {
//what is really happening:
return session.user.flatMap(user =>
user.company.flatMap(company =>
company.name.map(compname =>
getCompanyInfoFromDB(user, compname)
)
)
)
}
//Equivalent to above code, just using scala's monad syntax
def getCompanyInfoMonadic(session: Session, newname: String): Option[CompanyInfo] {
//MONADIC STYLE BECAUSE OPTION IS A MONAD!!!
return for {
user <- session.user
company<- user.company //if any of these are None, we terminate and return None
name<- company.name
//we could keep going deeper, doesn't matter no nesting syntax!
} yield
getCompanyInfoFromDB(user, name)
}