The Artima Developer Community
Sponsored Link

Agile Buzz Forum
Value of an Argument

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
James Robertson

Posts: 29924
Nickname: jarober61
Registered: Jun, 2003

David Buck, Smalltalker at large
Value of an Argument Posted: May 5, 2007 1:55 AM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by James Robertson.
Original Post: Value of an Argument
Feed Title: Travis Griggs - Blog
Feed URL: http://www.cincomsmalltalk.com/rssBlog/travis-rss.xml
Feed Description: This TAG Line is Extra
Latest Agile Buzz Posts
Latest Agile Buzz Posts by James Robertson
Latest Posts From Travis Griggs - Blog

Advertisement

Vassili Bykov has a habit of inspiring me. I'll let you decide if the inspiration is worthwhile. Within the last month, Vassili did a series of posts regarding (among other things), currying in Smalltalk. I got to thinking about this and how I might use it to simplify things. I hit upon something different. The opposite in some ways.

Evaluate the expression

base := BrowserEnvironment new.
((base referencesTo: #numArgs) & (base referencesTo: #value:value:))
	openEditor
What we see here is a common pattern. One that has showed up more and more as we have tried to make tools more and more dynamic. It is the pattern of having a block (function) which takes a predefined stack of arguments, but the arguments are optional. If the block takes no arguments, we just evaluate it. If it takes one argument, the API defines what the argument will be (often the reciever). If two, maybe a parameter as the second. You can see different variants by varying the number of #value: keywords in the query. It shows up lots in tools and in Widgetry.

It looks nearly the same every time. Something like:

drawAction numArgs == 1 ifTrue: [self drawAction value: aGraphicsContext].
drawAction numArgs == 2 ifTrue: [self drawAction value: aGraphicsContext value: pane]
Whether it's 2 options, 1, or maybe 3, it's always some sort of case statement. What if... we move this behavior to BlockClosure? Consider the following three BlockClosure methods.
cull: anObject
	^self numArgs = 1
		ifTrue: [self value: anObject]
		ifFalse: [self value]

cull: anObject cull: bObject
	^self numArgs = 2
		ifTrue: [self value: anObject value: bObject]
		ifFalse: [self cull: anObject]

cull: anObject cull: bObject cull: cObject
	^self numArgs = 3
		ifTrue: [self value: anObject value: bObject value: cObject]
		ifFalse: [self cull: anObject cull: bObject]
Basically the idea is that we make a recursive method family which throws arguments away til it gets down to the right size. Now that we've done this, we have a higher level pattern we can use in all these spots. Consider the implementation of the VisualWorks's Object>> ifNotNil:
ifNotNil: aBlock	
	^0 == aBlock numArgs
		ifTrue: [aBlock value]
		ifFalse: [aBlock value: self]
This can now be written simply as:
ifNotNil: aBlock	
	^aBlock cull: self
And all of the other similiar patterns in the system can be abstracted to follow the same pattern.

Some interesting things fall out of this. If we want, we could optimize these parallel to the value: primitives. If I recall correctly, VSE would have made the dispatch based on varying arg count easy, as it had separate subclasses for the 0,1, and 2 arg blocks. Or maybe it was another Smaltlalk.

Another interesting thing is the single problem that my much loved Symbol>>value: technique encounters becomes easier to solve. It would often be nice to do some ifNotNil: code as:

	^(self customer ifNotNil: #name) ifNotNil: #size
But it doesn't work because of the ambiguous meaning of argCount in that context. But we can implement cull: on Symbol the same as value: and suddenly it just magically polymorphically slots into place.

I had thought I would actually simplify AnnouncementDeliveryDestination to use cull:, but while it does the case statement like determination of what to do, it actually determines what to do up front at configuration time and those avoids redoing the computation each time. So I'm still pondering that one.

Michael and I batted many names around for such a behavior. maybe:maybe:maybe:. perhaps:perhaps:perhaps:. There were some others. In the end, credit for this one goes to Martin Kobetic. What would you call it? Terse wins.

Finally, you can find this code publised in the Open Repository as BlockCulling.

Read: Value of an Argument

Topic: When Cat Blogging Meets StarTrek Previous Topic   Next Topic Topic: carnival of the agilists, 3-may-07

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use