Частичные функции и поведение Execute-Once в Scala

РЕДАКТИРОВАТЬ: я согласен с мнением отрицательного голоса, но не согласен с решением. Итак, я исправил/сломал код в вопросе, чтобы проблема была объяснена. Я оставил ответ и свой оригинальный комментарий к нему. На мой взгляд, «def vs val» в строке 12 была неочевидной проблемой для новичка, такого как я.

У меня есть Scala, который я пытаюсь написать, но не могу заставить его вести себя именно так, как я хочу.

Что я хочу сделать, так это вызвать какую-то функцию, эта функция должна принимать некоторые параметры конфигурации, а затем настраивать другую функцию и возвращать ее. Затем вызывающая сторона неоднократно использовала бы эту возвращаемую функцию, зная, что она настроена определенным образом. Повторные вызовы возвращаемой функции не должны приводить к повторному запуску (дорогостоящей) конфигурации.

Например;

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 }

Затем вызывающий абонент должен иметь возможность;

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

Вышеупомянутое является отредактированным вырезанием/вставкой из того, что у меня есть до сих пор. Проблема с моей реализацией заключается в том, что каждый вызов «mySend» повторно запускает весь «sendConfigurationFor», чего я не хочу.

Я уверен, что читал "Scala Puzzler", где такое поведение было неожиданным (и, следовательно, неправильным) ответом. Теперь я на самом деле пытаюсь использовать то же самое поведение, которое у меня не получается, и я также не могу найти загадку.


person Tom    schedule 23.04.2015    source источник
comment
Понизить. Учитывая, что показанный код не демонстрирует описанной проблемы, я бы предложил удалить сообщение - вам помогли, и это пустая трата времени и путаница, пока они не увидят ваш комментарий к ответу, для всех остальных читать.   -  person Ed Staub    schedule 23.04.2015


Ответы (1)


Во-первых, это не связано с PartialFunction. не путайте их с частично применяемыми функциями.

Во-вторых, он работает, как и ожидалось, с 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...
person dk14    schedule 23.04.2015
comment
Вы правы, то, что я разместил в своем первоначальном вопросе, работает так, как предполагалось. Жаль, что он пострадал от ошибки вырезания и вставки. В частности, мой вызывающий код на самом деле имел def mySend = sendConfiguredFor(someCfg) Последующие вызовы mySend неоднократно вызывали код конфигурации. Изменение def на val, как и у вас, дает мне ожидаемое поведение. Спасибо за помощь. - person Tom; 23.04.2015