【问题标题】:Caching the result of all methods缓存所有方法的结果
【发布时间】:2016-02-04 09:10:26
【问题描述】:

我有一个类,它本质上是一些数据转换的方法集合。换句话说,我的文件中有一些数据,我使用一些不同的代码 sn-ps 将文本数据转换为我可以轻松查询的内容。

现在这些方法经常相互重用,并且随着核心数据的变化,出于速度原因,我想简单地缓存每个方法的结果。

我不想通过添加来更改每个方法:

^ methodsCache ifNil: [ methodsCache := "compute" ]

我想使用 Pharo 反射的强大功能来完成我的任务,而无需接触太多代码。

我的一个想法是,如果我可以在每个方法之前运行一些代码,我可以返回一个缓存值或继续执行该方法并缓存它的结果

【问题讨论】:

    标签: caching reflection smalltalk pharo


    【解决方案1】:

    您可以使用 Reflectivity 框架为您的方法添加前置和后置元链接。链接可以在透明执行之前检查缓存。

    link := MetaLink new
        metaObject: self;
        selector: #cachedExecute:;
        arguments: #(selector);
        control: #before.
    (MyClass>>#myMethodSelector) ast link: link.
    

    此代码将安装一个元链接,该链接将#cachedExecute: 发送到带有#myMethodSelector 参数的MyClass 对象。该链接安装在已编译方法的第一个 AST 节点上(同一个方法选择器,但可能在另一个方法上)。 #control: 消息确保链接将在 AST 节点执行之前执行。

    您当然可以安装多个相互影响的元链接。

    请注意,在上面的示例中,您不得#cachedExecute: 方法内再次发送相同的消息 (#myMethodSelector),因为您最终会陷入循环。

    更新 上面的代码实际上有一个错误(现已修复)。 #arguments: 消息采用符号列表定义通过 #selector: 指定的方法的参数。这些参数将从上下文中reified。要传递方法选择器,您使用#selector reification,方法上下文使用#context reification,方法参数#arguments。要查看可用的具体化,请查看 RFReification 的子类的类侧的 #key

    【讨论】:

    • 谢谢 Max,这是一个很好的例子。你知道我如何也可以重定向方法的参数吗?
    • 另一个问题是如何执行cachedExecute:?我可以调用我的方法的“干净”版本吗?我可以返回一些值而不是运行该方法的其余部分吗?
    • 您可以安装#after 链接,该链接在方法执行被缓存后 后在同一方法上安装#instead 链接。然后#instead 链接将返回缓存值(它替换了方法的整个 AST)。
    【解决方案2】:

    我的一个想法是定义

    doesNotUnderstand: aMessage
    
        aMessage selector beginsWith: 'cached' ifFalse: [ ^ super doesNotUnderstand: aMessage ].
    
        ^ cache at: aMessage selector ifAbsentPut: [ 
            self perform: aMessage selector allButFirst: 6 ]
    

    这样你唯一需要做的就是用self cachedmethodName(或self cachedMethodName但是你必须在doesNotUnderstand:中做额外的小写解决方法)替换所有发送的消息,如self methodName

    【讨论】:

      【解决方案3】:

      另一个众所周知的选择是替换你的新的并返回一个缓存代理,委托给实际的对象

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-20
        • 1970-01-01
        • 2022-01-25
        • 2017-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-17
        相关资源
        最近更新 更多