From: chang@alc.com (Sehyo Chang)
Subject: Re: triggers
Organization: Wizard's Castle
Date: Fri, 4 Sep 1992 20:25:14 GMT

In article <1992Sep4.101649.17897@informix.com> christb@infmuc (Christian Barmala) writes:
>I've heared, that Smalltalk provides 'Triggers'. That is, procedures, that
>are executed every time an Object changes its value, or reaches a certain
>value. Is that true? Is that even true for Smalltalk V?
>Thank you.

Smalltalk  doesn't have "triggers" as basic features, but you can implement it
easier than any other language maybe except CLOS.  The triggers
correspond to the the concept of 'daemon' and 'slot' in the AI based   
knowledge based system.  The trigger is also present in the language
called SELF and also in the some relational database such as SYBASE and ORACLE
and it is maybe part of upcoming SQL2(SQL3?)  standard.


Simple example of 'trigger' like object for a simple floating point
with upper and lowerlimit:

Object
    subclass: #TriggerObject
    instanceVariables:  'lowerLimit upperLimit value lowerLimitTrigger upperLimitTrigger'
    classVariables:  ''


!TriggerObject class methodsFor: 'instance creation'

new
	^ self new initialize


!TriggerObject methodsFor: 'initialize - release'
initialize
	self lowerLimit: 0.0
	self upperLimit: 100.0


!TriggerObject methodsFor: 'public - accessing'

lowerLimit: aFloatNumber

	lowerLimit := aFloatNumber


upperLimit: aFloatNumber

	upperLimit := aFloatNumber



lowerLimitTrigger: aBlock
	"assign block to evaluated later if lower limit condition test fails"

	lowerLimitTrigger := aBlock.

upperLimitTrigger: aBlock
	"assing bloc to evaluated later if upper limit condition test fail"
	upperLimitTrigger := aBlock.



!TriggerObject methodsFor: 'public - value'
value: aFloatNumber
	"accept value as float number, if number exceeds
	upper limit activate trigger for upper limit.
	if number is less than lower limit than trigger lower limit"

	aFloatNumber > self upperLimit
		ifTrue: [^ self triggerForUpper: aFloatNumber].

	aFloatNumber < self lowerLimit
		ifTrue: [^ self triggerForLower: aFloatNumber].

	value := aFloatNumber.


value
	"return value"

	^ value


!TriggerObject methodsFor: 'private - triggering"

triggerForUpper: aFloatNumber
	"trigger procedure for upper limit"

	
	^ upperLimitTrigger value: aFloatNumber


triggerForLower: aFloatNumber
	"trigger procedure for upper limit"

	^ lowerLimitTriger value: aFloatNumber





-----  Examples --------------------------

"simple of trigger that print out value to the transcript if 
value exceeds lower and upper limit
test

	| trigger |

	trigger := TriggerObject new.
	"assign 0 as lower limit"
	trigger lowerLimit: 0.0.

	"assign 100 as upper limit"
	trigger upperLimit: 100.0.

	"assign trigger for upper limit"
	trigger upperLimitTrigger: [:aValue | Transcript show: aValue printString ;cr].

	"assign trigger for lower limit. same thing"
	trigger lowerLimitTrigger: [:aValue | Transcript show: aValue printString ; cr].

	"simple test. assign value 5.0"
	trigger value: 5.0.

	"test to trigger lower limit"
	trigger value: -5.0.

	"test to trigger upper limit"
	trigger value: 2000.0.


Note that this example can also be duplicated by Exception Handling capability in
the ParcPlace Smalltalk or Servio Logic's Digitalk Window Interface.


"same example but using exception handling capability in Parc Place"


TriggerObject class methodsFor: 'signal initialization'

initialize
	"initialize out signal"

	TriggerUpperSignal := Signal genericSignal newSignal.
	TriggerLowerSignal := Signal genericSingal newSignal.


lowerSignal
	^ TriggerLowerSignal

upperSignal
	^ TriggerUpperSignal


"same methods as before to trigger upper and lower procedures"
TriggerObect methodsFor: 'public - value"


value: aValue

	aValue > self upperLimit ifTrue:
		[TriggerUpperSignal raise].

	aValue < self lowerLimit ifTrue:
		[TriggerLowerSignal raise].



---- example with signals -------------

test             

	| aTrigger |
	aTrigger := TriggerObject new.
	aTrigger upperLimit: 100.0 ; lowerLimit: 0.0.

	aTrigger lowerSignal

	 handle: [:ex | Transcript show: 'lower limit failed']

	 do: [aTrigger value: -10.0].



Trigger can also be implemented using dependencies, pluggble adaptors, etc...

Usage depends on types of applications and how to generalize these kind of triggers.


Good luck..



--------------
Sehyo Chang
Wizard's Castle
sehyo@netcom.com
Newsgroups: comp.lang.smalltalk