# Values, Types and Expressions — Scala

Source: https://www.geekswithgeeks.com/en/scala/f-basics

> Use val and var, type inference, strings and the expression-oriented style.

## Everything is an expression

Declare immutable values with **`val`** and mutable variables with **`var`**; idiomatic Scala uses `val` almost everywhere. The compiler **infers types** (`val count = 3` is an `Int`), but annotate public method signatures for clarity. Core types include `Int`, `Long`, `Double`, `Boolean`, `Char`, `String`, `BigDecimal` (use it for money) and `Unit` (like `void`, with the single value `()`). The type hierarchy has **`Any`** at the top, split into `AnyVal` (primitives) and `AnyRef` (objects), and **`Nothing`** at the bottom (the type of `throw` and of empty collections). **String interpolation** uses `s"Hi $name"`, `f"$price%.2f"` for formatting and `raw` for no escapes; triple quotes create multi-line strings. Crucially, **almost everything is an expression** that produces a value: `if`/`else`, `match`, blocks (the last expression is the result) and `try`. Methods are defined with `def`, and a method body can be a single expression: `def gst(amount: BigDecimal): BigDecimal = amount * 0.18`. `lazy val` defers evaluation until first use.

## Values, inference and expressions

if and blocks return values, and BigDecimal keeps money exact.

```scala
val name = "Asha"                   // String, inferred
var visits = 0                        // mutable: use sparingly
visits += 1

val price: BigDecimal = BigDecimal("49.50")
val qty = 3
val total = price * qty               // BigDecimal 148.50

val label = if total > 100 then "large" else "small"   // if is an expression

val discounted =
  val rate = BigDecimal("0.1")
  total - total * rate                 // a block's value is its last expression

def withGst(amount: BigDecimal, rate: BigDecimal = BigDecimal("0.18")): BigDecimal =
  (amount * (rate + 1)).setScale(2, BigDecimal.RoundingMode.HALF_UP)

println(s"Hello $name, visit number $visits")
println(s"Total with GST: ${withGst(total)}")      // already rounded to 2 places
println(7 / 2)                         // 3 (integer division)
println(7 / 2.0)                       // 3.5

lazy val config = loadConfig()         // evaluated on first access only
def loadConfig(): Map[String, String] = Map("env" -> "dev")
```

## Prefer val

Start every declaration with `val`. If you find yourself needing `var`, check whether a fold, a recursive function or a new immutable value would express the same logic more clearly.

**Quiz:** What does `val label = if total > 100 then "large" else "small"` show about Scala?

- [ ] if cannot return values
- [ ] val is mutable
- [x] if is an expression that produces a value
- [ ] Strings must be declared with var

*Answer:* if is an expression that produces a value. In Scala, if/else, match and blocks are expressions with results.
