Skip to content

Instantly share code, notes, and snippets.

@ricardclau
Created April 22, 2015 14:28
Show Gist options
  • Save ricardclau/93a45952bb423046b06b to your computer and use it in GitHub Desktop.
Save ricardclau/93a45952bb423046b06b to your computer and use it in GitHub Desktop.
package calculator
sealed abstract class Expr
final case class Literal(v: Double) extends Expr
final case class Ref(name: String) extends Expr
final case class Plus(a: Expr, b: Expr) extends Expr
final case class Minus(a: Expr, b: Expr) extends Expr
final case class Times(a: Expr, b: Expr) extends Expr
final case class Divide(a: Expr, b: Expr) extends Expr
object Calculator {
def computeValues(
namedExpressions: Map[String, Signal[Expr]]): Map[String, Signal[Double]] = {
var values = Map[String, Signal[Double]]()
for ( (str, sign) <- namedExpressions ) {
values += (str -> Signal(eval(sign(), namedExpressions)) )
}
values
}
def eval(expr: Expr, references: Map[String, Signal[Expr]]): Double = {
expr match {
case Literal(a) => a
case Plus(a, b) => eval(a, references) + eval(b, references)
case Minus(a, b) => eval(a, references) - eval(b, references)
case Times(a, b) => eval(a, references) * eval(b, references)
case Divide(a, b) => eval(a, references) / eval(b, references)
case Ref(name) => {
eval(getReferenceExpr(name, references), references - (name))
}
}
}
/** Get the Expr for a referenced variables.
* If the variable is not known, returns a literal NaN.
*/
private def getReferenceExpr(name: String,
references: Map[String, Signal[Expr]]) = {
references.get(name).fold[Expr] {
Literal(Double.NaN)
} { exprSignal =>
exprSignal()
}
}
}
package calculator
object Polynomial {
def computeDelta(a: Signal[Double], b: Signal[Double],
c: Signal[Double]): Signal[Double] = {
Signal(b() * b() - 4 * a() * c())
}
def computeSolutions(a: Signal[Double], b: Signal[Double],
c: Signal[Double], delta: Signal[Double]): Signal[Set[Double]] = {
val delta = computeDelta(a, b, c)
Signal[Set[Double]] (
if (delta() < 0) Set[Double]()
else {
var s = Set[Double]()
s = s + (-b() + Math.sqrt(delta())) / ( 2 * a() )
s + (-b() - Math.sqrt(delta())) / ( 2 * a() )
}
)
}
}
package calculator
object TweetLength {
final val MaxTweetLength = 140
def tweetRemainingCharsCount(tweetText: Signal[String]): Signal[Int] = {
Signal(MaxTweetLength - tweetLength(tweetText()))
}
def colorForRemainingCharsCount(remainingCharsCount: Signal[Int]): Signal[String] = {
Signal[String] (
remainingCharsCount() match {
case x if x >= 15 => "green"
case x if x >= 0 && x < 15 => "orange"
case _ => "red"
}
)
}
/** Computes the length of a tweet, given its text string.
* This is not equivalent to text.length, as tweet lengths count the number
* of Unicode *code points* in the string.
* Note that this is still a simplified view of the reality. Full details
* can be found at
* https://dev.twitter.com/overview/api/counting-characters
*/
private def tweetLength(text: String): Int = {
/* This should be simply text.codePointCount(0, text.length), but it
* is not implemented in Scala.js 0.6.2.
*/
if (text.isEmpty) 0
else {
text.length - text.init.zip(text.tail).count(
(Character.isSurrogatePair _).tupled)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment