[F-Script-talk] FSBOOLEAN return values
Brought to you by:
pmougin
From: Alun ap R. <al...@ma...> - 2005-01-09 17:01:06
|
Hi, As this is my first post to this group I will say something about my background and what I am using F-Script for. I have been using F-Script for my latest project and am very impressed by it. I have been programming smalltalk since 1989 (and Macintoshes since 1986), and it is great to see these two things come together so well. I always thought it sad and ironic that the smalltalk group at Xerox PARC did so much to influence the design of the Mac, and yet we don't have a really good smalltalk implementation on it that I can use. We did have SmalltalkAgents, of which I was an early adopter and did some work on the text processing part of the frameworks, but that ceased. Then Digitalk was killed off, and IBM never released VisualAge for the Mac. Squeak is technically great, but I could never give apps with the weird interface to discriminating Mac users, and VisualWorks also looks quirky on the Mac. So grateful thanks to Philippe for giving us F-Script. I would like to get to the point of doing more of the app in F-Script, rather like I can with Python via the pyobjc bridge. I am using F-Script for a number of methods that would be time-consuming or tricky to write in Objective-C, and also for debugging (using the palettes to provide the menu with object inspector and interpreter). I plan also to provide some sort of plugin or scripting ability via F-Script. A great deficiency of gdb is that it is hard to look at variables, particularly arrays, which means you can't follow a trail of object references to get to something you want to examine, unlike the F-Script object inspector. Just out of interest, here are a couple of examples of how I am using it, the first couple of methods generate an array of values for displaying in a graph: /*! Returns an array of points (0=client, 1=developer) where x=trialGSR and y=abr. For efficiency (as this is likely to be called from a loop) does not set GSR back to the original project setting, as this would cause all figures to be recalculated twice each time through the loop */ - (NSArray *)abrForGSR:(float)trialGSR { [self setGrossSalesRevenues:trialGSR]; NSPoint clientPoint = NSMakePoint(trialGSR,[self clientABRValue]); NSPoint devPoint = NSMakePoint(trialGSR, [self developerABRValue]); return [NSArray arrayWithObjects:[NSValue valueWithPoint:clientPoint], [NSValue valueWithPoint:devPoint],nil]; } /*! Returns an array of NSPoints where x varies from -20% to +20% of current GSR and y is corresponding ABR. Resets GSR to the original value when it has finished. */ - (NSArray *)abrDisplayValues { if (!calculateDisplayValuesBlock) calculateDisplayValuesBlock = [[@"[:project | | gsr | gsr := project grossSalesRevenues. project abrForGSR: @ 41 iota + 80 / 100 * gsr ]" asBlock]retain]; float currentGSR = grossSalesRevenues; NSArray *ary = [calculateDisplayValuesBlock value:self]; [self setGrossSalesRevenues:currentGSR]; return ary; } The second example uses an interpreter to update values in bands when any of the previous band values have changed. There isn't anything that can realistically go wrong with these calculations, so I don't check return values: /*! Check the allocations. If they can be satisfied with within the new startValue, ask each to take what it wants and set depth and end value to match. If they cannot be satisfied, work out amounts to give them proportionally and set depth to startValue making endValue zero targetDepth should always be aligned with sum of allocation targets, so we can use that initially */ - (void)recalculateActualDepth { if (targetDepth <= startValue) { // Okay, give the allocations what they want, set target depth to their sum execResult = [interpreter execute:@"myBand allocations setBandActualAmount: myBand allocations bandTargetAmount"]; [self setActualDepth:targetDepth]; } else { // restrict allocation actual amount to proportion of amount available (startValue) execResult = [interpreter execute:@"myBand allocations setBandActualAmount: myBand allocations bandTargetAmount / (myBand allocations bandTargetAmount \\ #+) * myBand startValue"]; [self setActualDepth:startValue]; } } I show this code because Philippe suggested it would be interesting to see what different people are using F-Script for. Now to my problem. I have a class called Tender, which contains an array of Project proposals, one per Site. A Tender can have no more than one proposal per site, so I need to filter the sites shown in a popup menu when new proposals are created. Tenders also sum the values of their proposals for display in an outline view. eg - (float)grossSalesRevenues { if ([proposals count] > 0) return [[[@"[:proposals | proposals grossSalesRevenues \\ #+]" asBlock]value: proposals] floatValue]; else return 0.0; } grossSalesRevenues on a Project object is simply a float getter. This works fine, but the next does not: - (BOOL)hasProposalForSite:(Site *)s { return [[@"[:proposals :s| proposals site = s \\ #|]" asBlock] value: proposals value:s]; } Now if I open an interpreter and assign t to the tender containing this method and one proposal (for site s1), and I have two sites, s1 and s2, then t proposals site = s1 \ #| => true (correct) t proposals site = s2 \ #| => false (correct) but if I call the method above t hasProposalForSite: s1 => true (correct) t hasProposalForSite: s2 => true (wrong) It appears that the block returns a pointer, which is then always caste to YES. Unlike NSValue, I don't see a way of getting the plain C value of of this return value. |