0% found this document useful (0 votes)
158 views4 pages

Building Your Own Function Objects: Scala in Action

The document discusses function objects in Scala. It explains that a function object is an object that can be used as a function. It provides an example of creating a function object that wraps the foldLeft method. It also explains that to treat an object as a function object, it needs an apply method. Function objects allow code to be written more concisely and functions to be passed as parameters.

Uploaded by

Zoltán Miszti
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
158 views4 pages

Building Your Own Function Objects: Scala in Action

The document discusses function objects in Scala. It explains that a function object is an object that can be used as a function. It provides an example of creating a function object that wraps the foldLeft method. It also explains that to treat an object as a function object, it needs an apply method. Function objects allow code to be written more concisely and functions to be passed as parameters.

Uploaded by

Zoltán Miszti
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Building your own function objects

An article from

Scala in Action
EARLY ACCESS EDITION

Nilanjan Raychaudhuri MEAP Release: March 2010 Softbound print: Spring 2011 | 525 pages ISBN: 9781935182757

This article is taken from the book Scala in Action. The author explains using objects as functions. Tweet this button! (instructions here)

Get 35% off any version of Scala in Action with the checkout code fcc35. Offer is only valid through www.manning.com.
A function object is an object that you can use as a function. That doesnt help you much, so why dont I show you an example? Here, we create a function object that wraps a foldLeft method: object foldl { def apply[A, B](xs: Traversable[A], defaultValue: B)(op: (B, A) => B) = (defaultValue /: xs)(op) } Now we can use our foldl function object like any function: scala> foldl(List("1", "2", "3"), "0") { _ + _ } res0: java.lang.String = 0123 scala> foldl(IndexedSeq("1", "2", "3"), "0") { _ + _ } res24: java.lang.String = 0123 scala> foldl(Set("1", "2", "3"), "0") { _ + _ } res25: java.lang.String = 0123 To treat an object as a function object, all you have to do is declare an apply method. In Scala,

<object>(<arguments>) is syntactic sugar for <object>.apply(<arguments>). Now, because we defined the first parameter as Traversable, we can pass IndexedSeq, Set, or any type of collection to our function. The expression (defaultValue /: xs)(op) might look a little cryptic, but the idea isnt to confuse you but to demonstrate the alternative syntax for foldLeft, /:. When an operator ends with :, then the rightassociativity kicks in.

For Source Code, Sample Chapters, the Author Forum and other resources, go to http://www.manning.com/raychaudhuri

When declaring function objects, its a good idea to extend one of the Function traits defined in the Scala library. In Scala, the Functon1 trait is declared as follows: trait Function1[-T1, +R] extends AnyRef { def apply(v: T1): R } Here, 1 stands for function with one parameter. Similarly, Scala defines a function trait for two or more parameters. In the following example, were building an increment function that takes an integer parameter and increments its value with 1: object ++ extends Function1[Int, Int]{ def apply(p: Int): Int = p + 1 } The shorthand and equivalent implementation of this function would be: val ++ = (x: Int) => x + 1 Theres one more way we could define our function object, and thats using the alternative notation of function

=>:

object ++ extends (Int => Int) { def apply(p: Int): Int = p + 1 }

In the last case, were using the shorthand notation of Function1, Int => Int. Weve used similar syntactic notation when declaring function parameters. In Scala, theres always another way to define a construct, and its up to you to decide which one you like the most. We can now pass the function objects that we created as parameters to other functions. Here, were invoking our map function with our new ++ function: scala> map(List(10, 20, 30), ++) res1: List[Int] = List(11, 21, 31) This is the same as invoking with an anonymous function: scala> map(List(10, 20, 30), (x: Int) => x + 1) res2: List[Int] = List(11, 21, 31) Its also the same as passing the Function trait: scala> map(List(10, 20, 30), new Function1[Int, Int] { def apply(p: Int) = p + 1 }) res3: List[Int] = List(11, 21, 31) One drawback of using the Function trait is that youre restricted to only one apply method. When passing an existing function (not a function object) as a parameter, Scala creates a new anonymous function object with an

apply method, which invokes the original function. This is called eta-expansion. One interesting subtrait of the Function1[-P, +R] trait is PartialFunction, which allows you to define a function thats not defined for all P and allows you compose with other functions.

Function1 is also defined as Function


Because the Function1 trait is used so often, Scala defines a type alias called Function. You wont find any reference of this trait in scaladoc because this type alias is defined inside the Predef class as follows:

type Function[-A, +B] = Function1[A, B] type is a keyword in Scala, and its used to type variables. Its similar to typedef in C.
Another helpful use of type variables is as a representation of a complicated type.

type MILS = Map[Int, List[String]] val mapping: MILS = Map( 1 -> List("one", "uno"), 2 -> List("two", "dos"))

For Source Code, Sample Chapters, the Author Forum and other resources, go to http://www.manning.com/raychaudhuri

Why is the function1 trait contravariant for parameter and covariant for return type?
If youre interested in why its both covariant and contravariant at the same time, please read on. To answer the question, lets consider what would happen when its opposite; for instance, covariant for parameter and contravariant for return value. Now imagine we have a covariant parameter, as in the following example: val addOne: Any => Int = { x: Int => x + 1 } Because Int is subtype of scala.Any, the covariant parameter should allow the preceding code to compile. But, the loophole in this code is that we can now invoke addOne with any type of parameter as long as its a subtype of

scala.Any. This could cause all sorts of problems for a function that expects only Int. Scala, being a type-safe
language, doesnt allow you to do that. The only other option we have is to declare the parameter type as invariant, but that would make the Function1 trait inflexible. Now if we make the return type a contravariant, then we could declare a method like the following: val asString: Int => Int = { x: Int => (x.toString: Any) } This code should also be valid because Any is a super type of Int, and a contravariant allows us to go from a narrower type to a more generic type. The following piece of code should also be valid, right? asString(10) + 20 But we end up adding 20 to a string value, and that could be problematic. Scalas strong type system implementation stops you from making this kind of mistake when dealing with parameter types and return types. To have a flexible and type-safe Function1 trait, the only possible implementation would be to have the parameter contravariant and the return type covariant.

Summary
The knowledge of type parameterization helps us in exploring type-variance concepts and the type-safety features of Scala. Its important to understand this concept for building generic, type-safe, reusable components in Scala. We explored the usage and importance of higher-order functions such as map and how they help the Scala library, especially the collection library, provide rich, useful APIs. Using higher-order functions, you can easily encapsulate common programming idioms.

For Source Code, Sample Chapters, the Author Forum and other resources, go to http://www.manning.com/raychaudhuri

Here are some other Manning titles you might be interested in:

Lift in Action
EARLY ACCESS EDITION

Timothy Perrett MEAP Release: April 2010 Softbound print: February 2011 | 450 pages ISBN: 9781935182801

AspectJ in Action, Second Edition


IN PRINT

Ramnivas Laddad MEAP Release: October 2009 September 2009 | 568 pages ISBN: 1933988053

DSLs in Action
EARLY ACCESS EDITION

Debasish Ghosh MEAP Began: October 2009 Softbound print: December 2010 (est.) | 375 pages ISBN: 9781935182450

For Source Code, Sample Chapters, the Author Forum and other resources, go to http://www.manning.com/raychaudhuri

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy