【问题标题】:Comparing Blocks in Squeak Smalltalk比较 Squeak Smalltalk 中的块
【发布时间】:2016-06-15 20:40:39
【问题描述】:

我在squeak编程,需要比较两个代码块如下:(toRunBlock是一个实例变量)

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

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

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

但是那个检查总是给出错误的,我找不到检查它们是否相等的方法。有人可以帮我解决这个问题吗?

【问题讨论】:

  • 为什么需要比较两个块?这不是建模问题吗?

标签: smalltalk squeak


【解决方案1】:

正如@LeandroCaniglia 指出的那样,您不必比较块。这里有两种方法可以在不比较块的情况下解决您的问题:

  1. 将变量初始化为nil。在你的访问器方法中你懒惰地初始化它:

    toRunBlock
        ^ toRunBlock ifNil: [ [] ]
    

    现在,当您查看变量 toRunBlock 时,它将是 nil,除非已发送 #toRunBlock 或通过其他方式设置了块。

    您的代码将变为:

    toRunBlock ifNil: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    
  2. 通过设置您可以检查的实例变量来使用附加状态。例如,这可能是您的 setter 方法:

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

    要检查你可以使用这样的方法:

    hasToRunBlockBeenSet
        ^ hasToRunBlockBeenSet ifNil: [ false ]
    

    您的代码将变为:

    self hasToRunBlockBeenSet ifTrue: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    

第二种方法可以说更可靠。

【讨论】:

    【解决方案2】:

    没有为 BlockClosures 定义相等,除了引用相等。尽管两个块的行为可能相同,但它们仍然不同,因为它们是闭包,而不仅仅是代码的 sn-ps。每个块都有对其创建所在的上下文(方法激活或另一个块)的引用,因此您的两个 [nil]s 至少在这方面会有所不同。

    您只能通过将之前的内容存储在其他地方来检查该块是否仍然相同。假设 [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 是否发生了变化,您也可以将之前的值存储在一个额外的实例变量中。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多