对每个满足的条件执行块,否则执行其他块

时间:2015-10-19 22:47:34

标签: iteration enumeration smalltalk pharo

想象一下,您必须选择一些值,并且对于每个值,您必须评估一个块。另一方面,如果没有满足条件的值,则必须评估另一个块。

示例: 考虑下一个方法签名:

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock

此方法应使用aBlock的每个正元素评估一个块aCollection,但如果没有这样的元素,请评估defaultBlock。请注意,实际上该方法可能会计算出比正数更复杂的东西,而不是aCollection,可能会有更复杂的对象。

4 个答案:

答案 0 :(得分:4)

第一个替代方案的更紧凑版本是以下内容,它不会实例化新的闭包,只使用作为参数接收的闭包。

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock

    ^(aCollection select: [:each | each positive ]) 
         ifEmpty: defaultBlock
         ifNotEmpty: [ :collection | collection do: aBlock ]

答案 1 :(得分:1)

目前我看到两个解决方案:

<强> 1)

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock
  (aCollection select: #positive)
    ifEmpty: [ defaultBlock value ]
    ifNotEmpty: [ :collection |
      collection do: [ :el | aBlock cull: el ] ]

但是如果positive的计算成本很高,那么评估aBlock第一个遇到的元素会很好,因为那个通过aBlock的人将能够做出任何反应。想要的方式。

<强> 2)

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock
  | encountered |
  encountered := false.
  aCollection do: [ :el |
    el positive ifTrue: [
      encountered := true.
      aBlock cull: el ] ].

  encountered ifFalse: [
    defaultBlock value ]

但我不喜欢额外遇到的变量,它会降低代码的功能。

答案 2 :(得分:1)

进一步采用Uko的解决方案:

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock
    ^ (aCollection
          select: #positive
          thenCollect: aBlock
      ) ifEmpty: defaultBlock

答案 3 :(得分:0)

一种非常好的功能方式适用于 SequenceableCollection

forPositivesOf: aCollection do: aBlock otherwise: defaultBlock
  (aCollection
    select: #positive
    thenCollect: [ :el | aBlock cull: el ]) ifEmpty: [ defaultBlock value ]