scalac -decompile foo.tasty
Tuple2
is a class, Tuple
is a trait
//
/* ... */
Apparently, explicit type annotations are discouraged??
https://docs.scala-lang.org/style/naming-conventions.html
@main
annotationString*
indicates variable number of String
arguments// Filename: hi.scala
def hi(args: String*): Unit =
@main println("Hello world!")
Compilation:
$ scalac --version
Scala compiler version 3.3.1 -- Copyright 2002-2023, LAMP/EPFL
# Generate class files
$ scalac hi.scala
$ ls
'hi$package$.class' 'hi$package.class' 'hi$package.tasty' hi.class hi.scala hi.tasty
# Run
$ scala hi
Hello world!
See:
case class
https://docs.scala-lang.org/tour/case-classes.html
Example from here:
case class Board(width: Int, height: Int) {
case class Coord(x: Int, y: Int) {
require(0 <= x && x <= width &&
0 <= y && y <= height)
}val occupied = scala.collection.mutable.Set[Coord]()
}
def eg(args: String*): Unit =
@main val b = Board(10, 20)
val c1 = b.Coord(3, 5)
occupied += c1 // Add new coordinate to set of occupied
b.// No error
val c2 = b.Coord(11, 20)
// Run-time error! Not compile-time... ??
Running this would give error:
$ scalac pathdeptype.scala; scala eg
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:324)
at Board$Coord.<init>(pathdeptype.scala:5)
at Board$Coord$.apply(pathdeptype.scala:3)
at pathdeptype$package$.eg(pathdeptype.scala:17)
at eg.main(pathdeptype.scala:11)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at dotty.tools.runner.RichClassLoader$.run$extension$$anonfun$1(ScalaClassLoader.scala:36)
at dotty.tools.runner.ScalaClassLoader$.asContext(ScalaClassLoader.scala:80)
at dotty.tools.runner.RichClassLoader$.dotty$tools$runner$RichClassLoader$$$asContext$extension(ScalaClassLoader.scala:18)
at dotty.tools.runner.RichClassLoader$.run$extension(ScalaClassLoader.scala:36)
at dotty.tools.runner.CommonRunner.run(ObjectRunner.scala:23)
at dotty.tools.runner.CommonRunner.run$(ObjectRunner.scala:13)
at dotty.tools.runner.ObjectRunner$.run(ObjectRunner.scala:48)
at dotty.tools.runner.CommonRunner.runAndCatch(ObjectRunner.scala:30)
at dotty.tools.runner.CommonRunner.runAndCatch$(ObjectRunner.scala:13)
at dotty.tools.runner.ObjectRunner$.runAndCatch(ObjectRunner.scala:48)
at dotty.tools.MainGenericRunner$.run$1(MainGenericRunner.scala:215)
at dotty.tools.MainGenericRunner$.process(MainGenericRunner.scala:270)
at dotty.tools.MainGenericRunner$.main(MainGenericRunner.scala:281)
at dotty.tools.MainGenericRunner.main(MainGenericRunner.scala)
Type of Coord
depends on the Board
instance which instantiated the Coord
.
ie, Coord
type depends on Board
value.
The name is 'path-dependent type' because type depends 'selector path' through objects. ʳ
See:
match
.. case
Example from here:
val suffix = (age % 100) match
case 11 | 12 | 13 => "th"
case _ => (age % 10) match
case 1 => "st"
case 2 => "nd"
case 3 => "rd"
case _ => "th"
require
, assert
, etcUseful to represent invariants that is difficult to represent using types.
require
: use to check if caller has adhered to require conditions
require
fails, pre-condition necessary to use a definition was not satisfiedassert
: can be used to assert something a function should be doing.
More: ensuring
, assume
, implicitly
See:
<static>
:
final
scala.util.CommandLineParser
??