Contest: scala-lang.org frontpage code snippet

Hello,

I’m adding a Scastie embedding on the front page of scala-lang.org.

I would like to do a little contest to decide what would be the content of this snippet. The winner will receive a Scala contributor T-SHIRT.

Here are some guidelines:

  • The code snippet should be relatively small (18 lines of code or less).
  • It should show how awesome Scala is.
  • It must be understandable by someone with no prior Scala experience.

A consensus on this thread will decide the winner(s).

Good Luck!

Scala contributor T-SHIRT

5 Likes

Do I missed out the consensus poll on using scastie vs scalafiddle.io ?

1 Like

Couldn’t think of anything better, but this code snippet includes a tail-recursive method, named arguments, passing functions to other functions, some collection operations, and pattern matching. The basic stuff you use in every-day Scala. :slight_smile:

def binaryToDecimal(acc: Int = 0, list: List[Int]): Int = list match {
  case element :: remainder => binaryToDecimal(2 * acc + element, remainder)
  case Nil => acc
}

val data = List(1, 1, 0, 0, 0).permutations.toSet

println(s"Here are the first ${data.size} numbers " +
  "that contain exactly 2 ones in their binary representation:")

val result = data.map(digits => binaryToDecimal(list = digits)).toList.sorted

println(result.mkString(", "))
1 Like

A basic example, mostly showing off case classes. Should be easy to modify and play with.

case class Position(x: Int, y: Int)

val positiveXPositions = {
  val positions =
    Set(Position(3, 5), Position(100, 5), Position(-55, 10), Position(3, 5))

  positions.filter(pos => pos.x > 0)
}
println(s"Positions with positive x-coordinate: $positiveXPositions")

val position1 = Position(43, 5).copy(x = 40, y = 20)
println(s"A position: $position1")

val findResult = positiveXPositions.find(pos => pos.x < 0)
println(s"Found: ${findResult.getOrElse("No position")}")

val summedXs = positiveXPositions.map(pos => pos.x).sum
println(s"Summed x-coordinates: $summedXs")

I don’t think I will win, but if I do, please pass on the T-shirt to the second-place winner.

1 Like

i think we should first ask what users we want the snippet to “speak to” the most. Coming from Java? Javascript? Interested in seeing how the language compares apples-to-apples in a common programming task, or interested in seeing something interesting in Scala that doesn’t exist in other languages? Also, something fun (appeal more to younger crowd) or something more practical (appeal more to seasoned developers who want to know about getting things done)? Etc.

(I don’t mean that we should first answer this before even trying to come up with snippets, only that part of coming up with snippets is choosing between these kinds of tradeoffs and if any of them matter, perhaps they should be a factor.)

What some other languages do:

https://www.typescriptlang.org/: none
https://elixir-lang.org/: A bunch of different snippets showing different features. Snippet in first screenful is a 7-line actor send + receive
https://golang.org/: print Hello world on stdout
https://www.rust-lang.org: trivial pattern match that prints a greeting in 11 languages
https://www.ruby-lang.org: print Hello world via a bunch of OOP and other features
https://www.python.org/: carousel with a few snippets, showing off some basic constructs. Button to launch a blank REPL-terminal-in-the-browser
https://www.python.org/: another a feature-list-with-snippets, showcasing JS interop, lack of runtime errors with example super-friendly compiler error, a performance graph, and enforcement of semver
https://www.haskell.org/: What I think is a lazy infinite list of primes, plus a blank REPL-in-browser-with-built-in-tutorial-mode and some suggestions to try out
https://kotlinlang.org/: Hello world with explanations of the code. Other tabs have an OO version, an Android activity, and an example of the HTML builder

2 Likes

@andreaTP scastie is an effort of Scala Center (and the OP). Anyway I think scalafiddle only supports scala.js, no?

trait Entry { def display: String }

case class Person(first: String, last: String) extends Entry {
  def display = s"$first $last"
}

def hello(e: Entry) = s"Hello, ${e.display}!"
def informal(e: Entry) = e match {
  case Person(first, _) => s"Hey there $first"
  case _                => "Um, wait, there's nobody here."
}
val entries = List(
  Person("John", "Grey"),
  Person("Jane", "White"),
  new Entry { def display = "Red Staircase" }
)

for { who <- entries; talk <- List(hello _, informal _) } println(talk(who))
1 Like

Well, I think that “Hello World” is kind of obligatory and later we can demonstrate other features. So here is my take:

object HelloWorld extends App {
  println("Hello World!")
}

case class Point(x: Int, y: Int) {
  override def toString: String = s"($x, $y)" // String interpolation
}

def double(p: Point): Point = {
  val (newX, newY) = (p.x * 2, p.y * 2)
  p.copy(x = newX, y = newY)
}

val points = List(Point(1, 1), Point(2, 2), Point(-3, 3), Point(4, 4))
points.filter(p => p.x > 0) // only points where x > 0
      .map(double)          // call the double function for every point
      .map(_.toString)      // map them to string representation
      .mkString(", ")       // join all the strings separating them by ","

I think that adding some comments would be good too. :slight_smile:

case class Location(latitude: Double, longitude: Double)

def printHemisphere(location: Location): Unit = {
  location match {
    case Location(0.0, _) => println("You're at the equator!")
    case Location(lat, _) if lat > 0 => println("You're in the northern hemisphere")
    case _ => println("You're in the southern hemisphere")
  }
}

def parseLocation(coordinates: String): Location = {
  coordinates split ',' map { _.toDouble } match {
    case Array(lat, long) => Location(latitude = lat, longitude = long)
    case _ => throw new IllegalArgumentException(s"Invalid coordinates: $coordinates")
  }
}

printHemisphere(parseLocation("46.5190557,6.5667576"))

scastie

I am aware that there is a small bug in parseLocation (if the coordinates end in a comma), but I felt clarity was more important than catching edge cases.

I think either a merge sort or a quick sort would look pretty cool.
(I only used an Int, because an (implicit ev: T => Ordered[T]) parameter isn’t very clear without the knowing how implicits work)

def merge(left: List[Int], right: List[Int]): List[Int] =
  if (left.isEmpty || right.isEmpty)
    left ::: right // ::: concatenates two lists
  else if (left.head > right.head)
    right.head :: merge(left, right.tail) // :: prepends an element to a list
  else
	left.head :: merge(left.tail, right)

def mergeSort(list: List[Int]): List[Int] = 
  list.length match {
    case 0 | 1 => list
    case length =>
      val (left, right) = list.splitAt(length / 2)
      merge(mergeSort(left), mergeSort(right))
  }

mergeSort(List(4, 2, 1, -3, -3, 0, 5, 9, -9))
mergeSort((19 to 0 by -2).toList)


def quickSort(list: List[Int]): List[Int] =
  list match {
    case Nil => Nil
    case x :: xs =>
      val (left, right) = xs.partition(_ < x)
      quickSort(left) ::: List(x) ::: quickSort(right)
	}

quickSort(List(4, 2, 1, -3, -3, 0, 5, 9, -9))
quickSort((19 to 0 by -2).toList)

The same in scastie

It should be very simple. Most of the cases user will just delete it. A user won’t be sitting and puzzling in existing code. A user shouldn’t think more than 5-10 second on a task that he doesn’t need.
So here are multiple simple tasks. A user can stop reading after each of them:

    val simple = 2 + 2
    
    val safe = Option(null)

    val clear = safe match {
      case None => "Hello, null!"
      case Some(_) => "Hello, value!"
    }

    case class User(name: String, age: Int, male: Boolean)
    val short = User("John", age = 33, male = true)

    type Line = List[String]
    val readable = List.empty[Line]

    def `🎲`() = Random.nextInt()
    val `💬` =
          if (`🎲` % 2 == 0) "👍"
    	  else "👎"
    val fun = s"😛: ${`💬`}"

Or you can show random snippet every time :)
2 Likes

Yes, I know, but even if Scalafiddle supports only Scala.Js it is much master and has got some better bindings for rendering output (i.e. things like: http://www.lihaoyi.com/hands-on-scala-js/ ).
Moreover Scalafiddle is already used in Akka official documentation with success and I suspect that it is already enough battle tested in prod docs envs.
I was simply expecting to have a poll on community before going straight with one solution.
:slight_smile:

cc. @ochrons

1 Like

The Scala.js homepage already has a selection of snippets for users coming from JavaScript, ECMAScript 6 and Typescript, so I’m a little less concerned about them as a specific audience.

But it’s a good illustration of the point – it takes several common idioms from the JS world and shows how concise and clear they are in Scala. We might want to think about similar compare-and-contrasts with other languages.

How is that relevant? Scala is Scala, and IMO a JVM-dependent example is probably not the way to go for this. At a quick glance, all of the proposed suggestions so far are platform-independent.

I agree that, since scastie is from the SC, it’s likely going to get used here. But scalafiddle is blazingly fast compared to scastie (and arguably makes a better first impression), so it’s not a trivial decision…

The use of emoji looks really cool; I’m just concerned it will look really bad for people who don’t have a good emoji font.

1 Like

This solves the n-Queens puzzle in 1 line of code.

def nQueens(n: Int) = (0 until n).permutations filter {p =>   
  p.zipWithIndex.flatMap{case (c, d) => Seq(n + c + d, c - d)}.distinct.size == 2*n  
}

// Pretty print all 92 solutions for n=8
nQueens(8).zipWithIndex foreach {case (solution, num) => 
  println(s"Solution #${num + 1}:")
  val rows = solution.map(col => solution.indices.map(i => if (i == col) 'Q' else '-').mkString)
  rows foreach println
}

See: https://gist.github.com/pathikrit/6fa878fe87c6160a52c4c27dabbfa6df

This is a Sudoku solver in Scala: https://gist.github.com/pathikrit/a32e17832296befd6b94

val n = 9
val s = Math.sqrt(n).toInt
type Board = IndexedSeq[IndexedSeq[Int]]
 
def solve(board: Board, cell: Int = 0): Option[Board] = (cell%n, cell/n) match {
  case (r, `n`) => Some(board)
  case (r, c) if board(r)(c) > 0 => solve(board, cell + 1)
  case (r, c) =>
    def cells(i: Int) = Seq(board(r)(i), board(i)(c), board(s*(r/s) + i/s)(s*(c/s) + i%s))
    def guess(x: Int) = solve(board.updated(r, board(r).updated(c, x)), cell + 1)  
    val used = board.indices flatMap cells
    1 to n diff used collectFirst Function.unlift(guess)
}
 
//////////////////////////////////////////////////////////////////
import scala.collection.{IndexedSeq => $}
val board = $(                        //0s denote empty cells
  $(1, 0, 0, 0, 0, 7, 0, 9, 0),
  $(0, 3, 0, 0, 2, 0, 0, 0, 8),
  $(0, 0, 9, 6, 0, 0, 5, 0, 0),
  $(0, 0, 5, 3, 0, 0, 9, 0, 0),
  $(0, 1, 0, 0, 8, 0, 0, 0, 2),
  $(6, 0, 0, 0, 0, 4, 0, 0, 0),
  $(3, 0, 0, 0, 0, 0, 0, 1, 0),
  $(0, 4, 0, 0, 0, 0, 0, 0, 7),
  $(0, 0, 7, 0, 0, 0, 3, 0, 0)
)    
println(solve(board).get.map(_ mkString " ") mkString "\n")

Something short and sweet: https://gist.github.com/pathikrit/6d1917174e8278bada65

def isPalindrome[A](x: Vector[A]): Boolean = x match {
  case start +: middle :+ end => start == end && isPalindrome(middle)
  case _ => true
}

Finally, Peter Norvig’s spell checker in Scala https://gist.github.com/pathikrit/d5b26fe1c166a97e2162:

class AutoSuggest(corpus: String, alphabet: Seq[Char] = 'a' to 'z', depth: Int = 2) {
  val words = s"[${alphabet.head}-${alphabet.last}]+".r
    .findAllIn(corpus.toLowerCase).toSeq
    .groupBy(_.toSeq).mapValues(_.size)
    .par withDefaultValue 0

  def editDistance(a: Seq[Char], b: Seq[Char]) = {
    lazy val d: Stream[Stream[Int]] = Stream.tabulate(a.length + 1, b.length + 1) {
      case (i, j) if (i - j).abs > depth => Int.MaxValue
      case (i, 0) => i
      case (0, j) => j
      case (i, j) if a(i-1) == b(j-1) => d(i-1)(j-1)
      case (i, j) => 1 + (d(i)(j-1) min d(i-1)(j) min d(i-1)(j-1))
    }
    d(a.length)(b.length)
  }

  def apply(word: String) = words maxBy {case (i, frequency) => -editDistance(i, word) -> frequency}
}
// Demo:
object AutoSuggest extends App {
  val suggest = new AutoSuggest(io.Source.fromFile("big.txt").mkString)  // curl http://norvig.com/big.txt > big.txt
  Seq("speling", "korrecter", "corrected", "xyz") foreach {w => println(s"$w: ${suggest(w)}")}
}```
2 Likes

Most people with math background will appreciate complex numbers with natural math operators:

class Complex(re: Double, im: Double) {
  def +(other: Complex): Complex = new Complex(re + other.re, im + other.im)
  def *(other: Complex): Complex = new Complex(re*other.re - im*other.im, re*other.im + im*other.re)
  def abs: Double = Math.sqrt(re*re + im*im)
}

object Complex {
  val i: Complex = Complex(0.0, 1.0)
  implicit def realToComplex(re: Double): Complex = Complex(re, 0.0)
}

import Complex.{i, realToComplex}

val x = 1.0
val y = 2.0 + 4.0*i
val z = x + y
println(z.abs)
2 Likes

The code below tries to communicate the three most important Scala feature (we can add others, and probably improve the descriptions), that can be easily understood by programmers coming from procedural and object oriented languages.

By avoiding any complex logic or algorithm, the reader can focus on what the code means instead of what the code does, and of corse the Scala code is an actual example of the features that it tries to showcase.

The code also shows how non verbose the Scala syntax is, a class definition containing a class member, a constructor and a toString method can be written in one line.

trait Feature 

case class ObjectOriented(description: String) extends Feature
case class Functional(description: String) extends Feature
case class StaticallyTyped(description: String) extends Feature

val scalaFeatures = List(
    ObjectOriented("Define new types and behaviors using classes and traits,"),
    Functional("Define functions as values, pass them as higher-order functions or return them as curried functions"),
    StaticallyTyped("Programs are staticly checked for safe correct type usage at compile time")
)

scalaFeatures.foreach(println)
3 Likes

(This post reflects my own opinion, not the position of the Scala Center)

It’s not clear to me what is the question the community is supposed to answer.

If scalafiddle fits your need for Akka documentation, just go for it!

I don’t see a problem in having both Scastie and scalafiddle. They are different tools with different features and compromises. Both can be the best solution to choose according to the context.

1 Like

I totally agree with you!
But, at least personally, I see that scalafiddle perfectly fits the homepage :slight_smile: and that’s why I was asking!
Faster, intuitive, community driven, I feel it as a great example of what the Scala community is able to offer to newcomers.
But of course this is a totally personal opinion and that’s why I was expecting, before this one, a poll like: "scastie or scalafiddle or whatever for the homepage?"
I will love to have a community agreement also on that bit :slight_smile: instead of just the content, we are anyhow talking about a programming language and demonstrations of what it is capable are appreciated even from the presentation POV.
Again this is a totally personal opinion and I really appreciate the effort you(all) are putting on getting things done better!