Sample run of chapter's interpreter examples
def isEMail(s: String): Boolean def domain(s: String): String def user(s: String): String
if (isEMail(s)) println(user(s) +" AT "+ domain(s) else println("not an email address")
EMail(user, domain)
// In file extractors/IsEmail.scala s match { case EMail(user, domain) => println(user +" AT "+ domain) case _ => println("not an email address") }
ss match { case EMail(u1, d1) :: EMail(u2, d2) :: _ if (u1 == u2) => ... ... }
// In file extractors/EMail.scala object EMail { // The injection method (optional) def apply(user: String, domain: String) = user +"@"+ domain // The extraction method (mandatory) def unapply(str: String): Option[(String, String)] = { val parts = str split "@" if (parts.length == 2) Some(parts(0), parts(1)) else None } }
object EMail extends (String, String) => String { ... }
unapply("John@epfl.ch") equals Some("John", "epfl.ch") unapply("John Doe") equals None
selectorString match { case EMail(user, domain) => ... }
EMail.unapply(selectorString)
val x: Any = ... x match { case EMail(user, domain) => ... }
// In file extractors/Misc.scala EMail.unapply(EMail.apply(user, domain))
Some(user, domain)
EMail.unapply(obj) match { case Some(u, d) => EMail.apply(u, d) }
// In file extractors/Twice.scala object Twice { def apply(s: String): String = s + s def unapply(s: String): Option[String] = { val length = s.length / 2 val half = s.substring(0, length) if (half == s.substring(length)) Some(half) else None } }
// In file extractors/UpperCase.scala object UpperCase { def unapply(s: String): Boolean = s.toUpperCase == s }
// In file extractors/Test2.scala def userTwiceUpper(s: String) = s match { case EMail(Twice(x @ UpperCase()), domain) => "match: "+ x +" in domain "+ domain case _ => "no match" }
scala> userTwiceUpper("DIDI@hotmail.com") res0: java.lang.String = match: DI in domain hotmail.com scala> userTwiceUpper("DIDO@hotmail.com") res1: java.lang.String = no match scala> userTwiceUpper("didi@hotmail.com") res2: java.lang.String = no match
// In file extractors/DomainTest.scala dom match { case Domain("org", "acm") => println("acm.org") case Domain("com", "sun", "java") => println("java.sun.com") case Domain("net", _*) => println("a .net domain") }
// In file extractors/Domain.scala object Domain { // The injection method (optional) def apply(parts: String*): String = parts.reverse.mkString(".") // The extraction method (mandatory) def unapplySeq(whole: String): Option[Seq[String]] = Some(whole.split("\\.").reverse) }
// In file extractors/DomainTest.scala def isTomInDotCom(s: String): Boolean = s match { case EMail("tom", Domain("com", _*)) => true case _ => false }
scala> isTomInDotCom("tom@sun.com") res3: Boolean = true scala> isTomInDotCom("peter@sun.com") res4: Boolean = false scala> isTomInDotCom("tom@acm.org") res5: Boolean = false
// In file extractors/ExpandedEMail.scala object ExpandedEMail { def unapplySeq(email: String) : Option[(String, Seq[String])] = { val parts = email split "@" if (parts.length == 2) Some(parts(0), parts(1).split("\\.").reverse) else None } }
scala> val s = "tom@support.epfl.ch" s: java.lang.String = tom@support.epfl.ch scala> val ExpandedEMail(name, topdom, subdoms @ _*) = s name: String = tom topdom: String = ch subdoms: Seq[String] = List(epfl, support)
List() List(x, y, _*) Array(x, 0, 0, _)
package scala object List { def apply[T](elems: T*) = elems.toList def unapplySeq[T](x: List[T]): Option[Seq[T]] = Some(x) ... }
List() List(1, 2, 3)
case C(...)
scala> import scala.util.matching.Regex
scala> val Decimal = new Regex("(-)?(\\d+)(\\.\\d*)?") Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
scala> val Decimal = new Regex("""(-)?(\d+)(\.\d*)?""") Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
scala> val Decimal = """(-)?(\d+)(\.\d*)?""".r Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
package scala.runtime import scala.util.matching.Regex class RichString(self: String) ... { ... def r = new Regex(self) }
scala> val Decimal = """(-)?(\d+)(\.\d*)?""".r Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)? scala> val input = "for -1.0 to 99 by 3" input: java.lang.String = for -1.0 to 99 by 3 scala> for (s <- Decimal findAllIn input) | println(s) -1.0 99 3 scala> Decimal findFirstIn input res1: Option[String] = Some(-1.0) scala> Decimal findPrefixOf input res2: Option[String] = None
scala> val Decimal(sign, integerpart, decimalpart) = "-1.23" sign: String = - integerpart: String = 1 decimalpart: String = .23
scala> val Decimal(sign, integerpart, decimalpart) = "1.0" sign: String = null integerpart: String = 1 decimalpart: String = .0
scala> for (Decimal(s, i, d) <- Decimal findAllIn input) | println("sign: "+ s +", integer: "+ | i +", decimal: "+ d) sign: -, integer: 1, decimal: .0 sign: null, integer: 99, decimal: null sign: null, integer: 3, decimal: null
For more information about Programming in Scala (the "Stairway Book"), please visit: http://www.artima.com/shop/programming_in_scala and: |
Copyright © 2007-2008 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. |