简体   繁体   English

比较Squeak Smalltalk中的块

[英]Comparing Blocks in Squeak Smalltalk

I am programming in squeak and need to compare two blocks of code as follows: (toRunBlock is an instance variable) 我正在编程吱吱声,需要比较两个代码块,如下所示:(toRunBlock是一个实例变量)

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

But at some point, I need to compare it to another block of code: 但在某些时候,我需要将它与另一个代码块进行比较:

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

But that check is always giving false, and I can't find a way to check if they're equal. 但是这个检查总是假的,我找不到办法检查它们是否相等。 Can someone help me out with this? 有人可以帮我解决这个问题吗?

As @LeandroCaniglia pointed out, you shouldn't have to compare blocks. 正如@LeandroCaniglia指出的那样,你不应该比较块。 Here are two ways to solve your problem without comparing blocks: 以下是两种在不比较块的情况下解决问题的方法:

  1. initialize the variable to nil . 将变量初始化为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. 现在,当您查看变量toRunBlock ,除非已发送#toRunBlock或通过其他方式设置了块,否则#toRunBlock nil

    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: 这可能是你的setter方法,例如:

     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" ]. 

The second method is arguably more reliable. 第二种方法可以说更可靠。

Equality is not defined for BlockClosures, except for reference equality. 除了引用相等性之外,BlockClosures没有定义平等。 Although two blocks might behave identically, they are still different because they are closures and not only snippets of code. 虽然两个块可能表现相同,但它们仍然不同,因为它们是闭包而不仅仅是代码片段。 Each block has a reference to the context (method activation or another block) where it was created in, so your two [nil] s would at least differ in this regard. 每个块都引用了创建它的上下文(方法激活或其他块),因此在这方面你的两个[nil]至少会有所不同。

You can only check if the block is still the same as earlier by storing somewhere else what it was earlier. 您只能通过存储其他地方之前的内容来检查该块是否仍然之前相同 Assuming that [nil] is some kind of default value in your case, you could store that [nil] block in another instance variable or a class pool variable (eg, defaultRunBlock) and compare toRunBlock (by reference) with that variable to check if toRunBlock has been changed. 假设[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: [ "..." ]

Or if you wanted to check if toRunBlock changed since the last time when that latter method was called, you could store the previous value in an additional instance variable as well. 或者,如果您想检查自上次调用后一个方法后是否更改了toRunBlock,您也可以将之前的值存储在另一个实例变量中。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM