//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) }