-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from ba-st/dynamic_binding
Dynamic Bindings
- Loading branch information
Showing
111 changed files
with
999 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
## Bindings | ||
|
||
A binding is useful for describing situations when there's a need for a required value that can be missing at the beginning. As this is a required value, the contract is to ask for it, and in case it is still missing we will raise an exception. | ||
|
||
```smalltalk | ||
| definedBinding undefinedBinding | | ||
definedBinding := Binding to: 1. | ||
definedBinding content. "1" | ||
undefinedBinding := Binding undefinedExplainedBy: 'Please set the default count.'. | ||
undefinedBinding content "Raises and exception" | ||
``` | ||
|
||
## Optionals | ||
|
||
An optional is useful for describing situations when we have an object that can either be present or not. In some ways it's similar to the Maybe monad, but it does not pretend to be a monad. | ||
|
||
So let's say we have a user interface where we want to show the details of some file the user has to upload. At the beginning there is no file so we can start with an unused optional: | ||
|
||
```smalltalk | ||
fileOptional := Optional unused. | ||
``` | ||
|
||
and we can have the following rendering code: | ||
|
||
```smalltalk | ||
fileOptional withContentDo: [:file | self renderDetailsOf: file] | ||
``` | ||
|
||
The first time we render our page we don't have a file, and so we won't render anything. Now we can let the user upload a file and change the optional: | ||
|
||
```smalltalk | ||
fileOptional := Optional containing: self uploadFile | ||
``` | ||
|
||
and now the rendering code will take care of rendering the file details. | ||
|
||
This is the simplest use, now suppose we want to take some action in case the file is not yet uploaded. We can change the rendering code to: | ||
|
||
```smalltalk | ||
fileOptional | ||
withContentDo: [ :file | self renderDetailsOf: file ] | ||
ifUnused: [ self renderUploadInstructions ] | ||
``` | ||
|
||
### Combinations | ||
|
||
We can easily combine two optionals: | ||
|
||
```smalltalk | ||
fileOptional | ||
with: fileExtensionOptional | ||
return: [:fileName : fileExtension | | ||
'<1s>.<2s>' expandMacrosWith: fileName with: fileExtension ] | ||
``` | ||
This will produce a new optional that will have the concatenation as its content, or an unused one in case some part is missing. | ||
|
||
If we have a list of optionals it's possible to combine them to get a new optional as a result. So suppose we have a list of possible numbers and we want to get the sum only if all are available. We can do that by sending the following message: | ||
|
||
```smalltalk | ||
Optional | ||
withAll: numberOptionals | ||
return: [:addends | addends sum ] | ||
``` | ||
|
||
So we will get a new optional that contains the sum in case all the possible numbers are available, or an unused optional in case some number is not available. In that case we are performing the computation over a collection of the values. It can be expressed for each step, with an injection: | ||
|
||
```smalltalk | ||
Optional | ||
forEvery: numberOptionals | ||
injectInto: [:sum :addend | sum + addend ] | ||
``` |
8 changes: 0 additions & 8 deletions
8
...Buoy-Dynamic-Binding-Tests.package/BindingTest.class/instance/testBoundObjectWhenBound.st
This file was deleted.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
source/Buoy-Dynamic-Binding-Tests.package/BindingTest.class/instance/testTo.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
tests | ||
testTo | ||
|
||
| binding | | ||
|
||
binding := Binding to: 1. | ||
|
||
self assert: binding content equals: 1 |
12 changes: 0 additions & 12 deletions
12
source/Buoy-Dynamic-Binding-Tests.package/BindingTest.class/instance/testUnbound.st
This file was deleted.
Oops, something went wrong.
14 changes: 14 additions & 0 deletions
14
...Buoy-Dynamic-Binding-Tests.package/BindingTest.class/instance/testUndefinedExplainedBy.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
tests | ||
testUndefinedExplainedBy | ||
|
||
| binding explanation messageObtained | | ||
|
||
explanation := 'Parameter not yet configured'. | ||
binding := Binding undefinedExplainedBy: explanation. | ||
|
||
self | ||
should: [ binding content ] | ||
raise: AssertionFailed | ||
withExceptionDo: [ :error | messageObtained := error messageText ]. | ||
|
||
self assert: messageObtained equals: explanation |
16 changes: 16 additions & 0 deletions
16
...ic-Binding-Tests.package/BindingTest.class/instance/testUndefinedExplainedByAllRaising.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
tests | ||
testUndefinedExplainedByAllRaising | ||
|
||
| binding explanations messageObtained | | ||
|
||
explanations := {'Parameter not yet configured' . 'Parameter seems wrong'}. | ||
binding := Binding undefinedExplainedByAll: explanations raising: InstanceCreationFailed. | ||
|
||
self | ||
should: [ binding content ] | ||
raise: InstanceCreationFailed | ||
withExceptionDo: [ :error | messageObtained := error messageText ]. | ||
|
||
self | ||
assert: messageObtained | ||
equals: 'Parameter not yet configured. Parameter seems wrong' |
14 changes: 14 additions & 0 deletions
14
...namic-Binding-Tests.package/BindingTest.class/instance/testUndefinedExplainedByRaising.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
tests | ||
testUndefinedExplainedByRaising | ||
|
||
| binding explanation messageObtained | | ||
|
||
explanation := 'Parameter not yet configured'. | ||
binding := Binding undefinedExplainedBy: explanation raising: InstanceCreationFailed. | ||
|
||
self | ||
should: [ binding content ] | ||
raise: InstanceCreationFailed | ||
withExceptionDo: [ :error | messageObtained := error messageText ]. | ||
|
||
self assert: messageObtained equals: explanation |
6 changes: 4 additions & 2 deletions
6
source/Buoy-Dynamic-Binding-Tests.package/BindingTest.class/methodProperties.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
{ | ||
"instance" : { | ||
"testBoundObjectWhenBound" : "GabrielOmarCotelli 3/15/2017 15:35", | ||
"testUnbound" : "GabrielOmarCotelli 3/15/2017 15:35" | ||
"testUndefinedExplainedByAllRaising" : "MaximilianoTabacman 3/18/2017 16:32", | ||
"testUndefinedExplainedBy" : "MaximilianoTabacman 3/18/2017 16:28", | ||
"testUndefinedExplainedByRaising" : "MaximilianoTabacman 3/18/2017 16:30", | ||
"testTo" : "MaximilianoTabacman 3/18/2017 16:28" | ||
}, | ||
"class" : { } | ||
} |
1 change: 1 addition & 0 deletions
1
source/Buoy-Dynamic-Binding-Tests.package/OptionalTest.class/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
An OptionalTest is a test class for testing the behavior of Optional |
4 changes: 4 additions & 0 deletions
4
...y-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testPrintingUnusedOptional.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
tests-Printing | ||
testPrintingUnusedOptional | ||
|
||
self assert: (Optional unusedBecause: 'This feature is disabled.') printString equals: 'This feature is disabled.' |
4 changes: 4 additions & 0 deletions
4
...uoy-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testPrintingUsedOptional.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
tests-Printing | ||
testPrintingUsedOptional | ||
|
||
self assert: (Optional containing: 1) printString equals: '1' |
26 changes: 26 additions & 0 deletions
26
...-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testWhenAllUsedInInjectInto.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
tests-Combining | ||
testWhenAllUsedInInjectInto | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional | | ||
|
||
firstOptional := Optional containing: 1. | ||
secondOptional := Optional containing: 0. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
injectInto: [ :min :current | min min: current ]. | ||
|
||
combinedOptional withContentDo: [ :min | self assert: min equals: 0 ] ifUnused: [ self fail ]. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
injectInto: [ :sum :current | sum + current ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self assert: sum equals: 4 ] ifUnused: [ self fail ] |
8 changes: 8 additions & 0 deletions
8
...Binding-Tests.package/OptionalTest.class/instance/testWhenAllUsedInInjectIntoWhenEmpty.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
tests-Combining | ||
testWhenAllUsedInInjectIntoWhenEmpty | ||
|
||
| combinedOptional | | ||
|
||
combinedOptional := Optional whenAllUsedIn: #() injectInto: [ :min :current | self fail ]. | ||
|
||
self assert: (combinedOptional withContentDo: [ :x | self fail ] ifUnused: [ 0 ]) isZero |
17 changes: 17 additions & 0 deletions
17
...g-Tests.package/OptionalTest.class/instance/testWhenAllUsedInInjectIntoWhenFirstUnused.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
tests-Combining | ||
testWhenAllUsedInInjectIntoWhenFirstUnused | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional | | ||
|
||
firstOptional := Optional unused. | ||
secondOptional := Optional containing: 1. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
injectInto: [ :min :current | min min: current ]. | ||
|
||
self assert: (combinedOptional withContentDo: [ :min | self fail ] ifUnused: [ 0 ]) isZero |
17 changes: 17 additions & 0 deletions
17
...ng-Tests.package/OptionalTest.class/instance/testWhenAllUsedInInjectIntoWhenSomeUnused.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
tests-Combining | ||
testWhenAllUsedInInjectIntoWhenSomeUnused | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional | | ||
|
||
firstOptional := Optional containing: 1. | ||
secondOptional := Optional unused. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
injectInto: [ :min :current | min min: current ]. | ||
|
||
self assert: (combinedOptional withContentDo: [ :min | self fail ] ifUnused: [ 0 ]) isZero |
29 changes: 29 additions & 0 deletions
29
...Buoy-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testWhenAllUsedInReturn.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
tests-Combining | ||
testWhenAllUsedInReturn | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional result | | ||
|
||
firstOptional := Optional containing: 0. | ||
secondOptional := Optional containing: 2. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := firstOptional | ||
whenAllUsedIn: | ||
{secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
result := 0. | ||
combinedOptional withContentDo: [ :sum | result := sum ] ifUnused: [ self fail ]. | ||
self assert: result equals: 5. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
result := 0. | ||
combinedOptional withContentDo: [ :sum | result := sum ] ifUnused: [ self fail ]. | ||
self assert: result equals: 5 |
8 changes: 8 additions & 0 deletions
8
...mic-Binding-Tests.package/OptionalTest.class/instance/testWhenAllUsedInReturnWhenEmpty.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
tests-Combining | ||
testWhenAllUsedInReturnWhenEmpty | ||
|
||
| combinedOptional | | ||
|
||
combinedOptional := Optional whenAllUsedIn: #() return: [ :addends | addends sum ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self fail ] ifUnused: [ :explanations | self assert: explanations isEmpty ] |
25 changes: 25 additions & 0 deletions
25
...ing-Tests.package/OptionalTest.class/instance/testWhenAllUsedInReturnWhenFirstIsUnused.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
tests-Combining | ||
testWhenAllUsedInReturnWhenFirstIsUnused | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional | | ||
|
||
firstOptional := Optional unusedBecause: 'This is expected.'. | ||
secondOptional := Optional unusedBecause: 'This is also expected.'. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := firstOptional | ||
whenAllUsedIn: | ||
{secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self fail ] ifUnused: [ :explanations | self assert: explanations equals: #('This is expected.' 'This is also expected.') ]. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self fail ] ifUnused: [ :explanations | self assert: explanations equals: #('This is expected.' 'This is also expected.') ] |
25 changes: 25 additions & 0 deletions
25
...ing-Tests.package/OptionalTest.class/instance/testWhenAllUsedInReturnWhenSomeAreUnused.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
tests-Combining | ||
testWhenAllUsedInReturnWhenSomeAreUnused | ||
|
||
| firstOptional secondOptional thirdOptional combinedOptional | | ||
|
||
firstOptional := Optional containing: 0. | ||
secondOptional := Optional unused. | ||
thirdOptional := Optional containing: 3. | ||
|
||
combinedOptional := firstOptional | ||
whenAllUsedIn: | ||
{secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self fail ] ifUnused: [ :explanations | self assert: explanations isEmpty ]. | ||
|
||
combinedOptional := Optional | ||
whenAllUsedIn: | ||
{firstOptional. | ||
secondOptional. | ||
thirdOptional} | ||
return: [ :addends | addends sum ]. | ||
|
||
combinedOptional withContentDo: [ :sum | self fail ] ifUnused: [ :explanations | self assert: explanations isEmpty ] |
13 changes: 13 additions & 0 deletions
13
source/Buoy-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testWithContentDo.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
tests-Accessing | ||
testWithContentDo | ||
|
||
| optional expectedContent content | | ||
|
||
expectedContent := 2. | ||
content := 1. | ||
|
||
optional := Optional containing: expectedContent. | ||
|
||
optional withContentDo: [ :theContent | content := theContent ]. | ||
|
||
self assert: content equals: expectedContent |
12 changes: 12 additions & 0 deletions
12
...oy-Dynamic-Binding-Tests.package/OptionalTest.class/instance/testWithContentDoIfUnused.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
tests-Accessing | ||
testWithContentDoIfUnused | ||
|
||
| optional expectedContent content | | ||
|
||
expectedContent := 2. | ||
|
||
optional := Optional containing: expectedContent. | ||
|
||
content := optional withContentDo: [ :theContent | theContent ] ifUnused: [ self fail ]. | ||
|
||
self assert: content equals: expectedContent |
Oops, something went wrong.