You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pharo/Smalltalk中带块参数键值消息及Promise类then:catch:实现问询

Implementing a Custom Promise Class with then:catch: in Pharo/Smalltalk

Let's walk through building this custom Promise implementation that accepts blocks as arguments via the then:catch: message. We'll cover everything from defining the class to testing your example code.

Step 1: Define the Promise Class

First, create a new class in the Pharo System Browser with the two mutually exclusive instance variables we need—only one will hold a value at any given time:

Object subclass: #Promise
	instanceVariableNames: 'promiseValue promiseError'
	classVariableNames: ''
	package: 'Your-Custom-Package'

Step 2: Add the promiseValue Method to BlockClosure

We need to extend BlockClosure so any block can spawn a Promise instance when sending the promiseValue message. This method runs the block, captures its result (or any thrown exception), and sets the appropriate Promise instance variable:

BlockClosure >> promiseValue
	| promise |
	promise := Promise new.
	[ promise promiseValue: self value ]
		on: Exception
		do: [ :ex | promise promiseError: ex ].
	^ promise

We also need setter methods for the Promise's instance variables to enforce mutual exclusivity:

Promise >> promiseValue: anObject
	promiseValue := anObject.
	"Clear error to maintain mutual exclusivity"
	promiseError := nil

Promise >> promiseError: anException
	promiseError := anException.
	"Clear value to maintain mutual exclusivity"
	promiseValue := nil

Step 3: Implement the then:catch: Method

This is the core method that handles success and failure blocks. It checks which instance variable is populated and executes the corresponding block:

Promise >> then: successBlock catch: failureBlock
	promiseValue ifNotNil: [ ^ successBlock value: promiseValue ].
	promiseError ifNotNil: [ ^ failureBlock value: promiseError ].
	"Optional: Handle pending state if you plan to support async execution later"
	^ self error: 'Promise is in pending state'

Step 4: Test Your Example Code

Now let's run the example you provided to verify it works:

promiseObject := [10/0] promiseValue.
promiseObject then: [:result | Transcript crShow: result] catch: [:failure | Transcript crShow: failure]

When you execute this, the block [10/0] will throw a ZeroDivide exception. The Promise will catch this exception, set promiseError, and the catch: block will print the exception details to the Transcript.

Key Details to Note

  • Mutual Exclusivity: Our setter methods ensure that setting either promiseValue or promiseError clears the other—this enforces the "only one initialized at a time" rule.
  • Error Handling: The promiseValue method wraps the block execution in an exception handler to catch any errors that occur.
  • Pending State: The current implementation throws an error for uninitialized (pending) promises. You could extend this later to support asynchronous operations by storing blocks to execute once the promise resolves.

内容的提问来源于stack exchange,提问作者Gakuo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:14:31