java - 如何使用 Monadic Bind 简化此 Apache Tomcat 代码?

标签 java haskell bind monads nested-if

commentator writes :

Some nice "greater-than sign" code in Tomcat. Needs a healthy dose of (>>=).

查看 the AuthenticatorBase.java class from Apache Tomcat 时:

/**
 * Enforce the security restrictions in the web application deployment
 * descriptor of our associated Context.
 *
 * @param request Request to be processed
 * @param response Response to be processed
 *
 * @exception IOException if an input/output error occurs
 * @exception ServletException if thrown by a processing element
 */
@Override
public void invoke(Request request, Response response)
    throws IOException, ServletException {

    if (log.isDebugEnabled())
        log.debug("Security checking request " +
            request.getMethod() + " " + request.getRequestURI());
    LoginConfig config = this.context.getLoginConfig();

    // Have we got a cached authenticated Principal to record?
    if (cache) {
        Principal principal = request.getUserPrincipal();
        if (principal == null) {
            Session session = request.getSessionInternal(false);
            if (session != null) {
                principal = session.getPrincipal();
                if (principal != null) {
                    if (log.isDebugEnabled())
                        log.debug("We have cached auth type " +
                            session.getAuthType() +
                            " for principal " +
                            session.getPrincipal());
                    request.setAuthType(session.getAuthType());
                    request.setUserPrincipal(principal);
                }
            }
        }
    }

我必须承认,我不知道如何应用它。我知道可能有一种方法可以将 if 树重构为单子(monad)绑定(bind),但我不知道该怎么做。

假设:

  • 这与语言无关,而是与逻辑构造有关。您可以用 Haskell、Scala 或 Clojure 来表示这个 if 树,它仍然表示相同的 if 逻辑。

我的问题是:如何使用 Monadic Bind 简化此 Apache Tomcat 代码?

最佳答案

好吧,这里你有副作用(request.set...),当你没有副作用时,bind 更有用。使用 ifPresent 就足够了:

Optional.ofNullable(principal).ifPresent(principal ->
  Optional.ofNullable(request.getSessionInternal(false)).ifPresent(session ->
    Optional.ofNullable(session.getPrincipal).ifPresent(principal -> {
      if (log.isDebugEnabled())
        log.debug(...);
      request.setAuthType(session.getAuthType());
      request.setUserPrincipal(principal);
    })));

这看起来可能不像是一场胜利;重复,但如果 request.getSessionInternalsession.getPrincipal 已返回,则不需要 Optional.ofNullable(...) Optional

您可以编写一个类似于 Optional.ofNullable(...).ifPresent 的方法:

public static <T> void ifNotNull(T value, Consumer<? super T> consumer) {
  if (value != null) { consumer.accept(value); }
}

ifNotNull(principal, principal ->
  ifNotNull(request.getSessionInternal(false), session ->
    ifNotNull(session.getPrincipal, principal -> {
      if (log.isDebugEnabled())
        log.debug(...);
      request.setAuthType(session.getAuthType());
      request.setUserPrincipal(principal);
    })));

(注意:不确定我是否准确记得 Java 语法,我已经有一段时间没有使用它了。)

关于java - 如何使用 Monadic Bind 简化此 Apache Tomcat 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34450149/

相关文章:

java - 在服务器端验证 token 时获得无效授权、格式错误的授权代码

haskell - GHC 明确强制要求

android - Android上的Haskell解释器?

Android - 多次绑定(bind)服务

Java 8 和文件处理 30 MB excel

java - Struts 1.x validate() 和validation.xml

java - .NET 相当于 Java 加密技术

Haskell:显示 Hlist 上所有 "showable"的元素

javascript - 在 Javascript 中绑定(bind)已绑定(bind)函数的更多参数

jquery - 如何使用 Jquery 删除 append 元素以及为什么 bind 或 live 会导致元素重复