Squeak Smalltalk中块的比较

4

我正在使用Squeak编程,需要比较两个代码块,如下所示:(toRunBlock是一个实例变量)

~~~Other code~~~
toRunBlock := [nil].
~~~Other code~~~

但是在某个时候,我需要将它与另一块代码进行比较:

(toRunBlock = [nil]) ifTrue: [
    "Run some code if toRunBlock hasn't been overwritten"
].

但是那个检查总是返回错误,我找不到一种方法来检查它们是否相等。有人能帮我解决吗?


4
为什么需要比较两个块?难道这不是一个建模问题吗? - Leandro Caniglia
2个回答

6

正如@LeandroCaniglia所指出的那样,您不必比较块。以下是两种解决问题的方法,而无需比较块:

  1. initialize the variable to nil. In your accessor method you initialize it lazily:

    toRunBlock
        ^ toRunBlock ifNil: [ [] ]
    

    Now, when you look at the variable toRunBlock it will be nil unless #toRunBlock has been sent or the block as been set by other means.

    Your code would become:

    toRunBlock ifNil: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    
  2. use additional state by setting an instance variable you can check. This could be your setter method for example:

    toRunBlock: aBlock
        toRunBlock := aBlock.
        hasToRunBlockBeenSet := true
    

    And to check you could use a method like this:

    hasToRunBlockBeenSet
        ^ hasToRunBlockBeenSet ifNil: [ false ]
    

    Your code would become:

    self hasToRunBlockBeenSet ifTrue: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    
第二种方法可以说更加可靠。

3
除了引用相等性外,BlockClosures并没有定义相等性。尽管两个块可能表现相同,但它们仍然不同,因为它们是闭包而不仅仅是代码片段。每个块都有一个对上下文(方法激活或另一个块)的引用,该上下文是创建该块的地方,因此您的两个[nil]至少在这方面不同。
您只能通过在其他地方存储先前的块来检查块是否仍与之前相同。假设[nil]在您的情况下是某种默认值,您可以将该[nil]块存储在另一个实例变量或类池变量(例如defaultRunBlock)中,并将toRunBlock(按引用)与该变量进行比较,以检查toRunBlock是否已更改。
Object subclass: #YourClass
    instanceVariableNames: 'toRunBlock defaultRunBlock' 
        "or as class variable:"
    classVariableNames: 'DefaultRunBlock'
    poolDictionaries: ''
    category: 'Kernel-Methods'

initialize
    defaultRunBlock := [nil]

otherCode
    toRunBlock := defaultRunBlock

whereYouCompareThem
    toRunBlock == defaultRunBlock ifTrue: [ "..." ]

如果您想检查自上次调用后toRunBlock是否发生了更改,您还可以将先前的值存储在额外的实例变量中。

注:该段内容为关于IT技术的讨论,建议根据具体上下文进行翻译。
whereYouCompareThem
    toRunBlock == previousRunBlock ifTrue: [ "..." ].
    previousRunBlock := toRunBlock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接