Разъяснение того, как эта функция возвращает значения и использует частичные функции - PullRequest
0 голосов
/ 11 марта 2020

Я запутываюсь, когда вижу функцию, которая выглядит следующим образом:

def site(req: RequestHeader, emit: ClientEmit) = WebSocket(req) { sri => user =>

Источник: здесь

Я хочу воссоздать очень простую функцию, которая следует та же самая схема, чтобы укрепить мое понимание того, что здесь происходит.

Функция вызывает WebSocket, а затем, кажется, передает другой вызов функции в теле внешнего узла функции.

Где sri и user взялись? Они не входят в сферу?

1 Ответ

3 голосов
/ 12 марта 2020

Блок WebSocket(req) { sri => user => в вашем примере это просто вызов метода WebSocket. Ваш блок эквивалентен:

def site(req: RequestHeader, emit: ClientEmit): Response = {
  return WebSocket(req)(
    new Function1[Sri, Function1[Option[User], Response]]() {
      override def apply(sri: Sri): Function1[Option[User], Response] =
        new Function1[Option[User], Response]() {
          override def apply(user: Option[User]): Response = ??? 
      }
    }
  )
}

, вызывающему здесь метод WebSocket sri => user => *do something* and return Response - это синтаксис c сахара для двух объектов Function1 с созданными на самом деле методами применения. Краткое примечание - это два лямбда-выражения. Просто прочитайте немного больше о выражениях и лямбда-выражениях. Если функция содержит только одно выражение, пышные скобки не требуются, и вы можете написать только один вызов метода WebSocket и передать ему лямбда-выражение как функцию из 1 аргумента, который создает функцию из 1 аргумента, который создает объект Response.

взгляните на WebSocket метод:

private def WebSocket(req: RequestHeader)(f: Sri => Option[User] => Response): Response =
  CSRF.check(req) {
    ValidSri(req) { sri => auth(req) flatMap f(sri) }
  }

Я написал здесь его расширенную версию:

private def WebSocket(req: RequestHeader)(f: Sri => Option[User] => Response): Response =
  CSRF.check(req) {
    new Function0[Response] {
      ValidSri(req) {
        new Function1[Sri, Response]() {
          sri: Sri =>
          val futureOptionUser: Future[Option[User]] = auth.apply(req)
          futureOptionUser.flatMap {
            optionUser: Option[User] =>
              val fAppliedToSri: Function1[Option[User], Response] = f.apply(sri)
              val response: Response = fAppliedToSri.apply(optionUser)
              return response
          }
        }
      }
    }
  }

в flatMap метод состав функции происходит, и это не аналогично функции 2 аргументов, но в данном случае это эквивалентно. Композиция функций более гибкая, чем функция из двух аргументов, вы можете оценить их не в один и тот же момент. Если вы хотите узнать больше о преобразовании между функцией 2 аргумента и 2 функцией 1 аргумента композиции, прочитайте о Curring .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...