Composition of Methods - Gnorion/BizVR GitHub Wiki
Composition of Methods Example
Sample Business Problem
Is the average weight of the five lowest income people over age 21 greater than 200lbs?
Approach 1 Applying Methods In Separate Steps
Apply the methods in separate steps, creating intermediate objects for each component of the problem
Expression | Description |
---|---|
C1 ={p in Persons where age>21} | unordered collection (bag) of persons each of which has age > 21 |
L1=C1.sortedBy(income) | creates a list sorted by age in ascending order |
L2=L1.first(5) | creates a list containing the first 5 persons in L1 |
N1=L2.weight.avg | sets N1 to the average weight of the 5 persons in L2 |
B1=N1>200 | B1 is true if avg weight>200, otherwise its false |
DISCUSSION POINT: Is this a copy of the data elements, or a list of pointers to the originals?
Approach 2
The same things can be done in a single expression by concatenating the methods and without the need for all the intermediate lists.
While this results in a more concise expression it can be a bit harder to comprehend.
B1={p in Persons where age>21}.sortedBy(income}.first(5).weight.avg>200
Because we are not creating lots of intermediate variables (C1,L1,L2):
- This has fewer side effects. No left over variables to cleanup.
- It also takes less memory, particularly if the collection is large
- It allows for more flexibility in the underlying implementation of the methods (instead of actually copying the data elements we could simply keep a reference to it. This is particularly useful if the data elements themselves might be large structures such as json objects. This way we only ever need to keep a single copy of the original data)
We can interpret the expression by reading from left to right:
- First a collection of Persons over 21 is created.
- Then the .sortedBy(income) method is applied to that collection to produce an ordered list (sequence)
- Then the .first(5) method is applied to that list to create a list of just five elements
- The the weight attribute of those five is processed by the .avg method to produce a single number as the result.
- This number is compared with 200 resulting in a boolean True or False
Approach 3
We can go one step further and define a composed method comprising a sequence or chain of methods, the output of one being the input to the next
define method {Persons}:avgWeightFivePoorest = sortedBy(income).first(5).weight.avg
Now we can say
B1={p in Persons where p.age>21}.avgWeightFivePoorest>200
Approach 4
We could also express it in two steps like this
C1 ={p in Persons where p.age>21}
B1=C1.avgWeightFivePoorest>200
This would be appropriate if the collection C1 was going to be processed by other functions or methods such as this
B2=C1.sortedBy(age).first(5).height.max>80
Is the maximum height of the five youngest persons over 21 greater than 80?B3=C1.sortedBy(age).last(5).forAll(gender='male')
Are the oldest five persons over 21 all male?B4=C1.select(gender='male',state='CA').size>50
Are there more than 50 male persons in CA over 21?