0

EDIT: I agree with the sentiment of the down vote, but disagreed with the solution. So I've corrected/broken the code in the question so it has the problem as explained. I've left the answer and my original comment to it. In my opinion, the "def vs val" on line 12 was the non-obvious problem to a beginner such as myself.

I have some Scala that I'm trying to write, but I can't get it to behave exactly the way I want.

What I want to do is call some function, this function should accept some configuration parameters and then configure another function and return that. The caller would then repeatedly use this returned function knowing that it was configured in a certain way. Repeated calls to the returned function should not cause the (expensive) configuration to be re-run.

For example;

1   private def send(host : String, port : Int)(msg : String) = {
2    // send msg to host:port
3  }
4 
5  def sendConfiguredFor(cfg : ConfigOptions) = {
6    // expensive function to figure out what host/port to use
7    val host = ...
8    val port = ...
9
10  send(host, port) _
11 }

The caller should then be able to;

12 def mySend = sendConfiguredFor(someCfg)
13 mySend("msg1")
14 mySend("msg2")

The above is an edited cut/paste from what I have so far. The problem with my implmentation is that every call to "mySend" re-runs the whole of "sendConfigurationFor", which is not what I want.

I'm sure I read a "Scala Puzzler" where this kind of beaviour was the unexpected (and therefore wrong) answer. Now I'm actually trying to use that same behaviour I'm unable to - and I can't find the puzzler either.

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
Tom
  • 313
  • 1
  • 4
  • 10
  • 2
    Downvote. Given that the code as shown doesn't exhibit the problem described, I'd suggest deleting the post - you've been helped, and it's a waste of time and confusing, until they see your comment on the answer, for anyone else to read. – Ed Staub Apr 23 '15 at 19:00

1 Answers1

2

First, it's not related to the PartialFunction - don't mess them with partially applied functions.

Second, it works as expected with val:

def send(host : String, port : Int)(msg : String) = {
  println("sending...")
}

def sendConfiguredFor(cfg : Any) = {

  val host = "localhost"
  val port = 8080

  println("configuring...") //will be called only once

  send(host, port) _
}

scala> val mySend = sendConfiguredFor(null)
configuring...
mySend: String => Unit = <function1>

scala> mySend("msg1")
sending...

scala> mySend("msg2")
sending...
dk14
  • 22,206
  • 4
  • 51
  • 88
  • You're right, what I posted in my original question does work as intended. It's a pity that it suffered from a cut-and-paste error. Specifically, my calling code actually had "def mySend = sendConfiguredFor(someCfg)" Subsequent calls to "mySend" were repeatedly calling the configure code. Changing "def" to "val", like you have, gives me the expected behaviour. Thanks for the help. – Tom Apr 23 '15 at 18:49