Skip to content

Instantly share code, notes, and snippets.

@edwardGunawan
edwardGunawan / fetchApi2WithCats.scala
Created December 1, 2021 06:28
Why Do Functional Programmers Prefer For-Comprehension Over Imperative Code Block
import cats.data._
type FutureOption[A] = OptionT[Future, A]
type FutureOptionEither[A] = EitherT[FutureOption, Throwable, A]
def computeApi = {
val futureEitherOption = for {
someValue <- FutureOptionEither(fetchAp2(1))
someOtherValue <- FutureOptionEither(fetchApi3(someValue))
} yield ()
@edwardGunawan
edwardGunawan / computeSequentiallyWithFor.scala
Created December 1, 2021 06:27
Why Do Functional Programmers Prefer For-Comprehension Over Imperative Code Block
def computeSequentially = for {
api1 <- Future { ... }
api2 <- Future { ... }
api3 <- Future { ... }
} yield( /* do something */ )
@edwardGunawan
edwardGunawan / computeSequentiallyWithoutFor.scala
Created December 1, 2021 06:26
Why Do Functional Programmers Prefer For-Comprehension Over Imperative Code Block
def computeSequentially = {
val api1Future = Future {...}
val api2Future = Future {...}
val api3Future = Future {...}
api1Future.flatMap {api1 =>
api2Future.flatMap { api2 =>
api3Future.map{api3 =>
//do something here
}
@edwardGunawan
edwardGunawan / fetchApi2.scala
Last active December 1, 2021 06:28
Why Do Functional Programmers Prefer For-Comprehension Over Imperative Code Block
def fetchAPi2(someValue: Int): Future[Option[Int]]
def fetchApi3(someOtherValue: Int): Either[Throwable, Result]
def computeApi = {
fetchApi2(1).flatMap{someValueMaybe =>
someValueMaybe.map{
fetchApi3(someOtherValue) match {
case Left(throwable) => ???
case Right(result) => ???
}
@edwardGunawan
edwardGunawan / getAPIWithInCache.scala
Created September 14, 2021 07:21
An Interview Question that Truly Tests your Experience as a Software Engineer
def getAPI[K,V](key:K): Future[V] = get(key).getOrElse{
for {
bool <- Future(compareAndSet(key, null, "in-progress"))
value <- fetchAPIA(key)
bool1 <- Future(compareAndSet(key, "in-progress", value))
} yield (value)
}
@edwardGunawan
edwardGunawan / getAPI.scala
Created September 14, 2021 07:21
An Interview Question that Truly Tests your Experience as a Software Engineer
def getAPI[K,V](key:K): Future[V] = get(key).getOrElse{
fetchAPIA(key).flatMap{value =>
Future(compareAndSet(key, null, value)).map{bool =>
getApi(key)
}
}
}
@edwardGunawan
edwardGunawan / fetchAPI.scala
Created September 14, 2021 07:20
An Interview Question that Truly Tests your Experience as a Software Engineer
// third party API
def fetchAPIA[K,V](key:K): Future[V]
def getAPI[K, V](key: K) : Future[V] = ???
@edwardGunawan
edwardGunawan / cache.scala
Created September 14, 2021 07:19
An Interview Question that Truly Tests your Experience as a Software Engineer
trait Cache[K, V] {
def get(key: K): Option[V]
def compareAndSet(key:Key, prevValue: V, currValue: V): Boolean
}
@edwardGunawan
edwardGunawan / InvoiceSchema.scala
Created August 26, 2021 07:36
How to Turn Your Domain Model into DynamoDB AttributeValue
Invoice(invoiceId: String, orderCode:String, metadata:Metadata, status: Status, isReceived: Received)
val invoiceSchema = Schema[Invoice].recordOf{field =>
(field("invoiceId", _.invoiceId),
field("orderCode", _.orderCode),
field("metadata", _.metadata)(metadataSchema),
field("status", _.status)(statusSchema),
field(isReceived, _.isReceived)(receivedSchema)
).map{(invoiceId:String, orderCode:String, metadata:Metadata, status: Status, isReceived:Received) =>
Invoice(invoiceId = invoiceId, orderCode = orderCode, metadata = metadata, status = status, isReceived = isReceived)
@edwardGunawan
edwardGunawan / UpdateSchema.scala
Created August 26, 2021 07:35
How to Turn Your Domain Model into DynamoDB AttributeValue
val updateSchema = Schema.oneOf[Update]{alt =>
val updateRefundSchema = Schema[UdpateRefund].record{field =>
(field.opt("additionalData", _.additionalData),
field.opt(status, _.status)).mapN{(additionalData: Option[String], status: Option[String]) => UpdateRefund(additionalData = additionalData, status = status)
}
}.tag("updateStatus")
val updateNewPurchaseSchema = Schema[UpdateNewPurchase].record{field =>
(field.opt("additionalData", _.additionalData)
field.opt("amount", _.amount)