The Artima Developer Community
Sponsored Link

Programming in Scala Forum
In search of deeper understanding of higher-function

2 replies on 1 page. Most recent reply: Dec 22, 2014 10:26 PM by Tris Nefzger

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 2 replies on 1 page
Bart Jenkins

Posts: 1
Nickname: bauhaus9
Registered: Jul, 2013

In search of deeper understanding of higher-function Posted: Apr 18, 2014 10:55 AM
Reply to this message Reply
Advertisement
Section 9.4 - Control Abstraction chapter (page 216 in my pdf) there is an example using a java PrintWriter. Specifically:

def withPrintWriter(file: File, op: PrintWriter => Unit) {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}

Given such a method, you can use it like this:

withPrintWriter(
new File("date.txt"),
writer => writer.println(new java.util.Date)
)

(Q) How does Scala KNOW that "writer" in the statement "writer => writer.println(new java.util.Date)" is a java.io.PrintWriter? The only way I see it is through inference based on the function definition in "withPrintWriter()", right? Or there another way I should be understanding this?

I've been reading an excellent blog from http://danielwestheide.com (The Neophyte's Guide to Scala), specifically part 10 on higher order functions (http://danielwestheide.com/blog/2013/01/23/the-neophytes-guide-to-scala-part-10-staying-dry-with-higher-order-functions.html) and am trying to wrap my head around ├╝ber concise notation like:

val sentByOneOf: Set[String] => EmailFilter = senders => email => senders.contains(email.sender)

(given: type EmailFilter = Email => Boolean)

As I understand this statement, this "sentByOneOf" val is a function type that takes a Set[String] and returns an EmailFilter (itself a function that takes an Email class and returns a Boolean) and this val is defined by logic that takes a "senders" val and returns a function that itself takes an "email" val that returns a Boolean result of evaluating the predicate "senders.contains(email.sender)". Right?

So, "senders" and "email" are "on-the-fly" vals? And the big question is how does Scala KNOW their types? I'm guessing again it is by inference to the functions to which they will be applied, yes?

Again, if someone has a different way of interpreting complex (complex to me) statements, I'd appreciate it. I'm still amazed at how much power we can get from such concise code.


Tris Nefzger

Posts: 6
Nickname: alacer
Registered: Dec, 2014

Re: In search of deeper understanding of higher-function Posted: Dec 21, 2014 7:14 PM
Reply to this message Reply
To answer your question: (Q) How does Scala KNOW that "writer" in the statement "writer => writer.println(new java.util.Date)" is a java.io.PrintWriter?

Looking in the definition of withPrintWriter as you gave it:
def withPrintWriter(file: File, op: PrintWriter => Unit) {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}

In this definition op is defined as a function taking a PrintWriter argument and yielding Unit.

Not shown in the book but in the source for this example is that the definition of withPrintWriter is encapsulated in an Object preceeding which is "import java.io._".

Now, since PrintWriter is preceeded with new in withPrintWriter it must be a class, but there is no such class shown in the Scala API documentation. Also in REPL running "var a = new PrintWriter() returns "error: not found: type PrintWriter". However afer running "import java.io._" it finds the class and gives its full path in an error about overloading its method constructor:

scala> import java.io._
import java.io._

scala> var c = new PrintWriter()
<console>:10: error: overloaded method constructor PrintWriter with alternatives:
(x$1: java.io.File,x$2: String)java.io.PrintWriter <and>
(x$1: java.io.File)java.io.PrintWriter <and>
(x$1: String,x$2: String)java.io.PrintWriter <and>
(x$1: String)java.io.PrintWriter <and>
(x$1: java.io.OutputStream,x$2: Boolean)java.io.PrintWriter <and>
(x$1: java.io.OutputStream)java.io.PrintWriter <and>
(x$1: java.io.Writer,x$2: Boolean)java.io.PrintWriter <and>
(x$1: java.io.Writer)java.io.PrintWriter
cannot be applied to ()
var c = new PrintWriter()

The Java API documentation for java.io.PrintWriter is at http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html and its shows the form of one of its constructors is "PrintWriter(File file)". Clicking on the "File" link in this goes to the java.io.file documentation which shoes the form of one of its constructors is "File(String pathname)". Based on this, a reattempt to instantiate PrintWriter with 'var a = new PrintWriter(new File("C:\\test.txt"))' succeeded in REPL.

By this means the PrintWriter argument of op()refers to java.io.PrintWriter.

Tris Nefzger

Posts: 6
Nickname: alacer
Registered: Dec, 2014

Re: In search of deeper understanding of higher-function Posted: Dec 22, 2014 10:26 PM
Reply to this message Reply
Regarding Daniel Westheide's blog part 10, it is is given:
case class Email(
subject: String,
text: String,
sender: String,
recipient: String

type EmailFilter = Email => Boolean

val sentByOneOf: Set[String] => EmailFilter = senders => mail => senders.contains(email.sender)
By correspondence of left and right sides of the definition of sentByOneOf, its Set[String] arg is senders, while by the definition of EmailBuilder, EmailBuilder corresponds to email => senders.contains(email.sender)

REPL shows the form of sentByOne Of is:
Set[String] => (Email => Boolean) = <function1>
It is a higher-order function because it returns a function.

Understanding all this is best achieved by using it. For example, given:
val e1 = Email("hello1","text1","sender1","recipient1")
val e2 = Email("hello2","text2","sender2","recipient2")
val e3 = Email("hello3","text3","sender3","recipient3")
val e4 = Email("hello4","text4","sender4","recipient4")
val s = SetFilt("sender1","sender2","sender3")
val efilterA = sentByOneOf(s)
then
efilterA(e1) // returns true
efilterA(e2) // returns true
efilterA(e3) // returns true
efilterA(e4) // returns false

At a higher level of processing a mail filtering system would consist of a number of mail filters such as sentByOneOf() configured for particular groups of senders or recipients, etc.,
and which would filter streams of incoming and possibly outgoing email messages. Examples of mail filtering systems for unix/linux are MailFilter and procmail.

Flat View: This topic has 2 replies on 1 page
Topic: (0).to(2) vs 0.to(2) Previous Topic   Next Topic Topic: Unable to Run Scala code on pg104 in the e-book edition


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2015 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us