Sample run of chapter's interpreter examples
// In file extension-methods/singleSpace-1.scala def singleSpace(s: String): String = s.trim.split("\\s+").mkString(" ")
// In file extension-methods/singleSpace-1.scala singleSpace("A Tale\tof Two Cities") // "A Tale of Two Cities" singleSpace(" It was the\t\tbest\nof times. ") // "It was the best of times."
// In file extension-methods/singleSpace-1.scala val s = "One Fish, Two\tFish " val t = " One Fish, Two Fish" singleSpace(s) == singleSpace(t) // true
s.singleSpace == t.singleSpace // if only this were true
// In file extension-methods/singleSpace-extension.scala extension (s: String) def singleSpace: String = s.trim.split("\\s+").mkString(" ")
// In file extension-methods/singleSpace-extension.scala s.singleSpace == t.singleSpace // It's true!
// In file extension-methods/singleSpace-2.scala // With internal extension marker def singleSpace(s: String): String = s.trim.split("\\s+").mkString(" ")
scala> extension (s: String) | def singleSpace: String = | s.trim.split("\\s+").mkString(" ") def singleSpace(s: String): String
scala> s.singleSpace == t.singleSpace val res0: Boolean = true
// In file extension-methods/generic-extensions-test-1.scala List(1, 2, 3).head // 1 List.empty.head // throws NoSuchElementException
// In file extension-methods/generic-extensions-test-2.scala List(1, 2, 3).headOption // Some(1) List.empty.headOption // None
// In file extension-methods/generic-extensions-test-3.scala List(1, 2, 3).tail // List(2, 3) List.empty.tail // throws NoSuchElementException
// In file extension-methods/tailOption-extension.scala extension [T](xs: List[T]) def tailOption: Option[List[T]] = if xs.nonEmpty then Some(xs.tail) else None
// In file extension-methods/tailOption-extension.scala List(1, 2, 3).tailOption // Some(List(2, 3)) List.empty[Int].tailOption // None List("A", "B", "C").tailOption // Some(List(B, C)) List.empty[String].tailOption // None
// In file extension-methods/tailOption-extension.scala tailOption[Int](List(1, 2, 3)) // Some(List(2, 3))
// In file extension-methods/collective-extensions-1.scala Int.MaxValue // 2147483647 Int.MinValue // -2147483648
// In file extension-methods/collective-extensions-1.scala Int.MinValue.abs // -2147483648 (overflow)
// In file extension-methods/collective-extensions-1.scala extension (n: Int) def absOption: Option[Int] = if n != Int.MinValue then Some(n.abs) else None
// In file extension-methods/collective-extensions-1.scala 42.absOption // Some(42) -42.absOption // Some(42) Int.MaxValue.absOption // Some(2147483647) Int.MinValue.absOption // None
// In file extension-methods/collective-extensions-1.scala -Int.MinValue // -2147483648 (overflow)
// In file extension-methods/int-negateOption.scala extension (n: Int) def absOption: Option[Int] = if n != Int.MinValue then Some(n.abs) else None def negateOption: Option[Int] = if n != Int.MinValue then Some(-n) else None
// In file extension-methods/int-negateOption.scala -42.negateOption // Some(42) 42.negateOption // Some(-42) Int.MaxValue.negateOption // Some(-2147483647) Int.MinValue.negateOption // None
// In file extension-methods/int-extension.scala extension (n: Int) def isMinValue: Boolean = n == Int.MinValue def absOption: Option[Int] = if !isMinValue then Some(n.abs) else None def negateOption: Option[Int] = if !isMinValue then Some(-n) else None
// All with internal extension markers def isMinValue(n: Int): Boolean = n == Int.MinValue def absOption(n: Int): Option[Int] = if !n.isMinValue then Some(n.abs) else None def negateOption(n: Int): Option[Int] = if !n.isMinValue then Some(-n) else None
// In file extension-methods/typeclass-test.scala Long.MinValue.abs // -9223372036854775808 (overflow) -Long.MinValue // -9223372036854775808 (overflow) Short.MinValue.abs // -32768 (overflow) -Short.MinValue // -32768 (overflow) Byte.MinValue.abs // -128 (overflow) -Byte.MinValue // -128 (overflow)
// In file extension-methods/TwosComplement.scala trait TwosComplement[N]: def equalsMinValue(n: N): Boolean def absOf(n: N): N def negationOf(n: N): N object TwosComplement: given tcOfByte: TwosComplement[Byte] with def equalsMinValue(n: Byte) = n == Byte.MinValue def absOf(n: Byte) = n.abs def negationOf(n: Byte) = (-n).toByte given tcOfShort: TwosComplement[Short] with def equalsMinValue(n: Short) = n == Short.MinValue def absOf(n: Short) = n.abs def negationOf(n: Short) = (-n).toShort given tcOfInt: TwosComplement[Int] with def equalsMinValue(n: Int) = n == Int.MinValue def absOf(n: Int) = n.abs def negationOf(n: Int) = -n given tcOfLong: TwosComplement[Long] with def equalsMinValue(n: Long) = n == Long.MinValue def absOf(n: Long) = n.abs def negationOf(n: Long) = -n
// In file extension-methods/TwosComplement-extension.scala extension [N](n: N)(using tc: TwosComplement[N]) def isMinValue: Boolean = tc.equalsMinValue(n) def absOption: Option[N] = if !isMinValue then Some(tc.absOf(n)) else None def negateOption: Option[N] = if !isMinValue then Some(tc.negationOf(n)) else None
// In file extension-methods/TwosComplement-extension.scala Byte.MaxValue.negateOption // Some(-127) Byte.MinValue.negateOption // None Long.MaxValue.negateOption // -9223372036854775807 Long.MinValue.negateOption // None
BigInt(42).negateOption 1 |BigInt(42).negateOption |^^^^^^^^^^^^^^^^^^^^^^^ |value negateOption is not a member of BigInt. |An extension method was tried, but could not be |fully constructed: | | negateOption[BigInt](BigInt.apply(42))( | /* missing */summon[TwosComplement[BigInt]] | )
// In file extension-methods/TwosComplementOps-extension.scala object TwosComplementOps: extension [N](n: N)(using tc: TwosComplement[N]) def isMinValue: Boolean = tc.equalsMinValue(n) def absOption: Option[N] = if !isMinValue then Some(tc.absOf(n)) else None def negateOption: Option[N] = if !isMinValue then Some(tc.negationOf(n)) else None
// In file extension-methods/TwosComplementOps-extension.scala import TwosComplementOps.*
// In file extension-methods/TwosComplementOps-extension.scala -42.absOption // Some(42)
// In file extension-methods/insert.scala def insert[T](x: T, xs: List[T])(using ord: Ord[T]): List[T] = if xs.isEmpty || ord.lteq(x, xs.head) then x :: xs else xs.head :: insert(x, xs.tail)
x <= xs.head // Ah, the clarity!
// In file extension-methods/insert2.scala // (Not yet the best design) object OrdOps: extension [T](lhs: T)(using ord: Ord[T]) def < (rhs: T): Boolean = ord.lt(lhs, rhs) def <= (rhs: T): Boolean = ord.lteq(lhs, rhs) def > (rhs: T): Boolean = ord.gt(lhs, rhs) def >= (rhs: T): Boolean = ord.gteq(lhs, rhs)
// In file extension-methods/insert2.scala def insert[T](x: T, xs: List[T])(using Ord[T]): List[T] = import OrdOps.* if xs.isEmpty || x <= xs.head then x :: xs else xs.head :: insert(x, xs.tail)
// In file extension-methods/insert3.scala trait Ord[T]: def compare(x: T, y: T): Int def lt(x: T, y: T): Boolean = compare(x, y) < 0 def lteq(x: T, y: T): Boolean = compare(x, y) <= 0 def gt(x: T, y: T): Boolean = compare(x, y) > 0 def gteq(x: T, y: T): Boolean = compare(x, y) >= 0 // (This is the best design) extension (lhs: T) def < (rhs: T): Boolean = lt(lhs, rhs) def <= (rhs: T): Boolean = lteq(lhs, rhs) def > (rhs: T): Boolean = gt(lhs, rhs) def >= (rhs: T): Boolean = gteq(lhs, rhs)
// In file extension-methods/insert3.scala def insert[T](x: T, xs: List[T])(using Ord[T]): List[T] = if xs.isEmpty || x <= xs.head then x :: xs else xs.head :: insert(x, xs.tail)
// In file extension-methods/Ord-internal-extension-markers.scala trait Ord[T]: def compare(x: T, y: T): Int def lt(x: T, y: T): Boolean = compare(x, y) < 0 def lteq(x: T, y: T): Boolean = compare(x, y) <= 0 def gt(x: T, y: T): Boolean = compare(x, y) > 0 def gteq(x: T, y: T): Boolean = compare(x, y) >= 0 // With internal extension markers: def < (lhs: T)(rhs: T): Boolean = lt(lhs, rhs) def <= (lhs: T)(rhs: T): Boolean = lteq(lhs, rhs) def > (lhs: T)(rhs: T): Boolean = gt(lhs, rhs) def >= (lhs: T)(rhs: T): Boolean = gteq(lhs, rhs)
// In file extension-methods/TwosComplementOps-absOption-test.scala import TwosComplementOps.absOption 88.absOption // Some(88)
For more information about Programming in Scala, Fifth Edition (the "Stairway Book"), please visit: http://www.artima.com/shop/programming_in_scala_5ed and: |
Copyright © 2007-2020 Artima, Inc. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. |