object Functions extends App {
//
// Function Calls
//
// basic function call with a single param
println("foo")
// function call with a block param
println { "foo" }
// function call with a more complex block param
println {
val f = "f"
f + "oo"
}
// fully qualified function call
Predef.println("foo")
// infix function call
Predef println "foo"
// named param function call
println(x = "foo")
// optional parens for no-param function
// Note: println is overloaded taking either no params or a single param
println()
println
// identifier
`println`("foo")
//
// Function Definitions
//
// no params for a function def
def noParams = scala.util.Random.alphanumeric.take(8).mkString
println(noParams)
// parens for a no-param function def
def noParamsWithParens() = scala.util.Random.alphanumeric.take(8).mkString
println(noParamsWithParens)
// def with a return type
def noParamsWithParensAndReturnType(): String = scala.util.Random.alphanumeric.take(8).mkString
println(noParamsWithParensAndReturnType)
// single param def
def aSingleParamDef(s: String) = s.toUpperCase
println(aSingleParamDef("foo"))
// function body in a block
def aSingleParamDefBlock(s: String) = {
s.toUpperCase
}
println(aSingleParamDefBlock("foo"))
// function body in parens
def aSingleParamDefParens(s: String) = (
s.toUpperCase
)
println(aSingleParamDefParens("foo"))
// single param and return type
def aSingleParamDefWithReturnType(s: String): String = s.toUpperCase
println(aSingleParamDefWithReturnType("foo"))
// function val
val aSingleParamFunctionVal = (s: String) => s.toUpperCase
println(aSingleParamFunctionVal("foo"))
// function val with body in a block
val aSingleParamFunctionValBlock = {
(s: String) => s.toUpperCase
}
println(aSingleParamFunctionValBlock("foo"))
// two param def
def twoParamDef(s: String, i: Int): String = s.take(i)
println(twoParamDef("hello", 2))
// multiple parameter sets
def twoParamSetsDef(s: String)(i: Int): String = s.take(i)
println(twoParamSetsDef("hello")(2))
// partially applied function
val partiallyAppliedFunction = twoParamSetsDef("hello")(_)
println(partiallyAppliedFunction(3))
// partially applied function where the second parameter is applied
val anotherPartiallyAppliedFunction: (String => String) = twoParamSetsDef(_)(1)
println(anotherPartiallyAppliedFunction("foo"))
// polymorphic type parameter for a def
def typeParamDef[T](o: Option[T]): Boolean = o.isDefined
println(typeParamDef(Some("foo")))
println(typeParamDef[String](Some("foo")))
// create an instance of a single parameter function
val aFunction1 = new Function1[String, String] {
override def apply(s: String): String = s.toUpperCase
}
println(aFunction1("foo"))
// create an instance of a single parameter function but use parens after the type
val aFunction1WithParens = new Function1[String, String]() {
override def apply(s: String): String = s.toUpperCase
}
println(aFunction1WithParens("foo"))
// shorthand for creating a new single parameter function
val anotherFunction1 = new (String => String) {
override def apply(s: String): String = s.toUpperCase
}
println(anotherFunction1("foo"))
// single input parameters can optionally be wrapped in parens
val yetAnotherFunction1 = new ((String) => String) {
override def apply(s: String): String = s.toUpperCase
}
println(yetAnotherFunction1("foo"))
// shorthand for a single parameter function
val andAnotherFunction1 = (s: String) => s.toUpperCase
println(andAnotherFunction1("foo"))
// shorthand for a partial function val
val aPartialFunction: PartialFunction[String, String] = {
case s: String => s.toUpperCase
}
println(aPartialFunction("foo"))
// shorthand for a partial function def
def aPartialFunctionDef: PartialFunction[String, String] = {
case s: String => s.toUpperCase
}
println(aPartialFunctionDef("foo"))
// create a new instance of a partial function
val anotherPartialFunction = new PartialFunction[String, String] {
override def isDefinedAt(s: String): Boolean = true
override def apply(s: String): String = s.toUpperCase
}
println(anotherPartialFunction("foo"))
// an operator
def &%->(): String = "foo"
println(&%->())
// right-associative by putting a colon on the right side of the method name
class Foo {
def #:(s: String): String = s.reverse
}
val foo = new Foo
// normal operator call
println(foo.#:("asdf"))
// reverse infix call
println("asdf" #: foo)
// no equals necessary for functions that return Unit
def returnsUnit() {
println("bad form")
}
returnsUnit()
// call by name params are evaluated each time the are accessed
def callByName(byName: => String, byValue: String): Unit = {
println(byName, byValue)
println(byName, byValue)
}
callByName(scala.util.Random.alphanumeric.take(8).mkString, scala.util.Random.alphanumeric.take(8).mkString)
// default values
def defaultValues(s: String = "asdf") = s.toUpperCase
//
println(defaultValues("foo"))
// the parens are required
println(defaultValues())
//
// Higher-order Functions
//
// a function that takes a string and returns it in upper case
def toUpperCase(s: String): String = s.toUpperCase
// a higher-order function that takes a function, and calls it with the string "foo"
def aHigherOrderFunction(f: String => String): String = f("foo")
println(aHigherOrderFunction(toUpperCase))
// single input type parameters can optionally be wrapped with parens
def anotherHigherOrderFunction(f: (String) => String): String = f("foo")
println(anotherHigherOrderFunction(toUpperCase))
// multiple input type parameters must be wrapped with parens
def multipleInputParamHigherOrderFunction(f: (String, Int) => String): String = f("foo", 1)
// no input type parameters
// note: the call to f must use parens in this context
def noInputParamHigherOrderFunction(f: () => String): String = f()
// a higher-order function that returns a function
def returnsAHigherOrderFunction: (String => String) = toUpperCase
println(returnsAHigherOrderFunction("foo"))
// anonymous function where s is the string input parameter
println {
anotherHigherOrderFunction { s =>
s.toUpperCase
}
}
// anonymous function with input type specified
println {
anotherHigherOrderFunction { s: String =>
s.toUpperCase
}
}
// anonymous function with partial function from a case statement
println {
anotherHigherOrderFunction { case s: String =>
s.toUpperCase
}
}
// anonymous function with multiple params
println {
multipleInputParamHigherOrderFunction { (s, i) =>
s.take(i)
}
}
// anonymous function with multiple params via a case statement
println {
multipleInputParamHigherOrderFunction { case (s: String, i: Int) =>
s.take(i)
}
}
// shorthand anonymous function
println(anotherHigherOrderFunction(_.toUpperCase))
// polymorphic type param with a higher-order function
def aTypeParamedHigherOrderFunction[T](f: String => T) = f("foo")
println(aTypeParamedHigherOrderFunction(_.length))
println(aTypeParamedHigherOrderFunction[Int](_.length))
}
Created
November 10, 2018 13:51
-
-
Save rahulkumar-aws/266c0cbfc0bb72951aab99143f9c15a5 to your computer and use it in GitHub Desktop.
Main Repository : https://github.com/jamesward/let-me-count-the-ways-scala
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment