.

Posted 牧羊龟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.相关的知识,希望对你有一定的参考价值。

在Haskell中,用 . 函数来完成函数的组合,其定义如下

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \\ x -> f (g x)
  • f必须有一个与g的结果类型相同的值作为参数

函数组合的用途之一是动态地创建函数,并将其传递给其他函数。
当然,也可以使用Lambdas,但很多时候函数的组合更清晰、更简洁,如下

map (\\ x negate (abs x)) [5, -3, -6.7, -3.2, -19.24]
map (negate.abs) [5, -3, -6.7, -3.2, -19.24]

函数的组合是向右结合的,所以可以同时组合几个函数。 f (g (z x))等价于(f.g.z) x,如下

map (\\ xs -> negate (sum (tail xs))) [[1..5], [3..6], [1..7]]
map (negate . sum . tail) [[1..5], [3..6], [1..7]]

带有多个参数的函数,想使用函数组合,必须使用curry,让每个函数接受一个参数,如下

sum (replicate 5 (max 6.7 8.9))
(sum . replicate 5 . max 6.7) 8.9
sum. replicate 5 . max 6.7 $ 8.9

如果想要使用函数组合重写一个包含大量圆括号的表达式,可以先将最内层函数的最后一个形参放在$之后,然后开始组合所有其他函数
如下

replicate 100 (product (map (* 3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
replicate 100 . product . map (* 3) . zipWith max [1,2,3,4,5] $ [4,5,6,7,8]

有时函数的组合更容易阅读,有时函数的组合不容易阅读
追求短代码可以使用函数的组合,想提升阅读性可以使用let in表达式,如下

oddSquareSum = sum (takeWhile (< 10000) (filter odd (map (^ 2) [1..])))

oddSquareSum = sum . takeWhile (< 10000) . filter odd . map (^ 2) $ [1..]

oddSquareSum = 
  let oddSquares = filter odd $ map (^ 2) [1..]
      belowLimit = takeWhile (< 10000) oddSquares
  in sum belowLimit

学习Slim Framework for PHP v3 ( 二)

  昨天说到能够成功将本地的URL通过在index.php 中添加get(pattern,clouser)路由到指定的处理类中,处理后(这里指存入数据库中),然后返回response在浏览器中显示。

  昨天最后留的问题是:能不能在App的container中添加自己的key呢,今天还没有解决。

  今天做的工作是:添加一个middleware,在处理完成后记录日志。

  Slim3.0不再像Slim2那样在每个Middleware都添加Application,所以在Middleware中获取App的数据有困难,同时向container中加入key的难题也没有解决呢。所以我的思路是这样:

  1.APP class 只用来添加middleware、启动router;

  2.将router注册为相关业务处理的Moduel;

  3.Moduel中含有实现日志记录的类;

  4.在Middleware中指定所对应的类。

  

  其实我还有一个疑问即middleware的__invoke()方法是何时执行的。追踪代码,发现在添加middleware时有这样一段代码如下:

protected function addMiddleware(callable $callable)
    {
        echo ‘add middle ware‘;

        if ($this->middlewareLock) {
            throw new RuntimeException(‘Middleware can’t be added once the stack is dequeuing‘);
        }

        if (is_null($this->stack)) {
            $this->seedMiddlewareStack();
        }


        $next = $this->stack->top();
        $this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) {
            $result = call_user_func($callable, $req, $res, $next);
            if ($result instanceof ResponseInterface === false) {
                throw new UnexpectedValueException(
                    ‘Middleware must return instance of \Psr\Http\Message\ResponseInterface‘
                );
            }

            return $result;
        };

        return $this;
    }

   这段代码中重要的是这两句:

      $next = $this->stack->top();

      $this->stack[] = function();
   这个stack[]即添加到middleware stack中,但是这个function ()是个重要的东西,也就是所谓的依赖注入。有趣在什么地方的呢,就是现在整个函数是不执行的,如果要执行的就是执行了middleware的__invoke()方法。而什么时候执行呢,逻辑上说就是到当前middleware顺序的时候进行执行,在代码上既 app->run()中调用。它调用的是middle stack 的top元素,有代码为证:

public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res)
    {
        if (is_null($this->stack)) {
            $this->seedMiddlewareStack();
        }
        /** @var callable $start */
        $start = $this->stack->top();
        $this->middlewareLock = true;
        $resp = $start($req, $res);
        $this->middlewareLock = false;
        return $resp;
    }

  在 $start($req,$res)的时候,那个匿名函数function就会执行,自定义middleware的__invoke()就被执行了。

  这里应该是依赖注入的概念,现在还不是很明白,后面需要好好学习下。

  这算对源码的一些理解。

  根据上面4个方面的思路,设计中有的两点是:

    1.以Module为主体,将Log、DB等需要的lib加入到module中;
        2.在Midllerware中设定Module,调用Module的方法如写日志.
   在Module 中加入Log,DB是好用的,但是在Middleware中加入Module不可以用,原因在于Middleware先于module注册,注册时关联的module是NULL的,在后面执行的时候就找不到module,各种方法不存在的错误。
$app->add(Example\MiddleWare\MyMiddleware::instance());

$app->post(‘/homepage‘, function ($request, $response, $args) use ($app) {
    Example\Module\Replace::instance($request,$response)->excute();
    return $response;
});

  既然这样的话,那就先让Module存在即实例化module;然后在注册middleware的时候指定module,这样不会报错,对Module 和Middleware 修改代码如下:

/***
* Module
**/
public function init($request,$response){
    $this->request = $request;
    $this->response = $response;
    $this->excute();
}
public abstract  function excute();
/**
* Middleware
*/
    self::$middleWare = is_null(self::$middleWare)?new MyMiddleware($module):self::$middleWare;
    return self::$middleWare;
}

public function __construct($module){
    $this->module = $module;

}

   然后在index.php中,添加middleware和router,代码如下:

$repModule = Example\Module\Replace::instance();
$app->add(Example\MiddleWare\MyMiddleware::instance($repModule));

$app->post(‘/homepage‘, function ($request, $response, $args) use ($repModule) {
    $repModule->init($request,$response);
    return $response;
});

  这样,在Middleware中完成LogWrite的功能就算实现了,但是问题来了,这里过早的指定了Module和Middleware,如果在注册其他router时不能动态的更改Module。这样不算好!

  有没有其他更好的方法呢,框架里很多匿名函数(Clouser)。是不是能有Clouser的办法解决呢?

  Module在Middleware中动态指定的问题需要解决。或者能用App做些什么,暂时没思路。

 
  

 

以上是关于.的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别