-
Notifications
You must be signed in to change notification settings - Fork 0
Scala Basics
Pramode C E edited this page May 7, 2019
·
1 revision
Welcome to the learn-spinalhdl wiki!
We can directly define objects in Scala!
object Hello {
def main(args: Array[String]): Unit = {
println("Hello, world")
}
}
Scala is statically typed, but types are inferred in almost all contexts.
object Infer1 {
def main(args: Array[String]): Unit = {
// Explicit type specification
val x:Int = 20
// Scala will infer types. Type of "y"
// is Int.
val y = 10
}
}
object Def1 {
// A function with no arguments.
// Call like this: Def1.foo
def foo:String = "hello"
// A function with one arg
def sqr(x:Int):Int = x*x
def main(args: Array[String]): Unit = {
println(Def1.foo)
println(Def1.sqr(10))
}
}
object Unit1 {
def main(args: Array[String]): Unit = {
// println returns "nothing", and this "nothing"
// has type "Unit".
val x:Unit = println("world")
// Type of y is "Unit"; it is inferred
// by Scala.
val y = println("hello")
// The only object of type "Unit" is (), it
// is printed as () itself.
println(x)
println(y)
val z = ()
println(z)
}
}
import scala.language.postfixOps
object Operators1 {
def main(args: Array[String]): Unit = {
val msg = "Hello,world"
val newmsg = msg.toUpperCase
// Without the import, the next line will give
// a warning. This notation is not encouraged, but
// Spinal code seems to be using it liberally.
val newmsg2 = (msg toUpperCase)
println("newmsg = "+ newmsg)
println("newmsg2 = " + newmsg2)
}
}
// Infix operators
object Operators2 {
def main(args: Array[String]): Unit = {
println(1 + 2)
println(1.+(2))
val x = "abc def ijk".split(" ")
val y = "abc def ijk" split " "
for (item <- x) {
println(item)
}
for (item <- y) {
println(item)
}
}
}
object ValAndVar1 {
def main(args: Array[String]): Unit = {
val x = Array(1, 2, 3)
// Compile error. Can't rebind a val
x = Array(10, 20, 30)
}
}
object ValAndVar2 {
def main(args: Array[String]): Unit = {
var x = Array(1, 2, 3)
// No problem, can reassign to a var
x = Array(10, 20, 30)
println(x(0))
}
}
object ValAndVar3 {
def main(args: Array[String]): Unit = {
val x = Array(1, 2, 3)
// Even though we can't reassign to "x", we
// can change the object that "x" refers to
// because it is a mutable Scala object.
x(0) = 10
println(x(0))
}
}
object IfElse1 {
def main(args: Array[String]): Unit = {
val x = if (1 > 2) "hello" else "world"
println(x)
}
}
object Block {
def name: String = {
val title = "Dr."
val name = "Einstein"
title + " " + name
}
def main(args: Array[String]): Unit = {
println(Block.name)
}
}
class Student {
val firstName = "Foo"
val lastName = "Bar"
def name = firstName + " " + lastName
}
object Class1 {
def main(args: Array[String]):Unit = {
val s = new Student
println(s.name)
}
}
class Student(first: String, last: String) {
val firstName = first
val lastName = last
def name = firstName + " " + lastName
}
object Class2 {
def main(args: Array[String]):Unit = {
val s = new Student("Foo", "Bar")
println(s.name)
}
}
Note that we are now prefixing the constructor arguments with "val"; this automatically sets them up as fields of the created object thereby avoiding unnecessary boilerplate.
class Student(val firstName: String, val lastName: String) {
def name = firstName + " " + lastName
}
object Class3 {
def main(args: Array[String]):Unit = {
val s = new Student("Foo", "Bar")
println(s.name)
}
}
class Adder(amount: Int) {
def apply(n: Int):Int = amount + n
}
object Apply1 {
def main(args: Array[String]):Unit = {
val a = new Adder(10)
val b = a(1) // same as a.apply(1)
println(b)
}
}
You can avoid a lot of boilerplate using case classes.
// "val x" and "val y" is not required;
// "x" and "y" automatically become fields
// of the created object.
case class Foo(x: Int, y: Int) { }
object CaseClass1 {
def main(args: Array[String]):Unit = {
val f1 = new Foo(1, 2)
println(f1.x)
// For a case class, a companion object is automatically
// created.
val f2 = Foo(1, 2)
println(f2.x)
}
}
Pattern matching can be performed on case classes:
// "val x" and "val y" is not required;
// "x" and "y" automatically become fields
// of the created object.
case class Foo(x: Int, y: Int) { }
object CaseClass2 {
def check(f: Foo):String = {
f match {
case Foo(0, 0) => "Both x and y 0"
case Foo(0, y) => "x is zero, y may be non zero"
case Foo(-1, -1) => "x and y are -1"
case Foo(_, _) => "default case"
}
}
def main(args: Array[String]):Unit = {
val f1 = Foo(1, 2)
println(CaseClass2.check(f1))
val f2 = Foo(-1, -1)
println(CaseClass2.check(f2))
}
}
class Foo(var x: Int) {
def := (xx: Int) = {
x = xx
}
}
object OperatorFunctions {
def main(args: Array[String]):Unit = {
val f = new Foo(10)
f := 20
println(f.x)
}
}
object Lambda {
def main(args: Array[String]):Unit = {
val f = (x: Int, y: Int) => x + y
println(f(1,2))
}
}
object Map1 {
def main(args: Array[String]):Unit = {
val xs = List(1, 2, 3, 4)
println(xs.map((x: Int) => x + 1))
}
}
sealed trait Color {}
case object Red extends Color
case object Green extends Color
object Traits1 {
def main(args: Array[String]):Unit = {
val c1:Color = Red
val s = c1 match {
case Red => "red"
case Green => "green"
}
println(s)
}
}
sealed trait Option {}
case object None extends Option
final case class Some(x: Int) extends Option
object Traits2 {
def main(args: Array[String]):Unit = {
val o1:Option = Some(10)
val s = o1 match {
case Some(x) => "Some: " + x
case None => "None"
}
println(s)
}
}
Important: This gives a warning as we are not checking for all possible values of Color!
sealed trait Color {}
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Traits3 {
def main(args: Array[String]):Unit = {
val c1:Color = Red
val s = c1 match {
case Red => "red"
case Green => "green"
}
println(s)
}
}