Skip to content

Commit

Permalink
Merge pull request #227 from final-hill:feature-iff-225
Browse files Browse the repository at this point in the history
Implemented `iff` function
  • Loading branch information
mlhaufe authored Nov 21, 2021
2 parents 79131b7 + 3364492 commit 8c2c696
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v0.22.0

* Added `implies` function
* Added `iff` function
* Added topic tags to github repo
* Updated `package.json` keywords

Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [Checked Mode](#checked-mode)
- [Assertions](#assertions)
- [Implies](#implies)
- [Iff](#iff)
- [Overrides](#overrides)
- [Encapsulation](#encapsulation)
- [Invariants](#invariants)
Expand Down Expand Up @@ -272,6 +273,31 @@ implies(

This is logically equivalent to: `!p || q`

## Iff

When defining predicates it is a common use case to encode [if and only if](https://en.wikipedia.org/wiki/Logical_biconditional).
Also referred to as a biconditional.

The truth table is as follows:

| *p* | *q* | *p* ↔ *q* |
|-----|-----|----------------|
| T | T | T |
| T | F | F |
| F | T | F |
| F | F | T |

An example of usage is the encoding of `You can ride the train if and only if you have a ticket`:

```ts
iff(
person.hasTicket,
person.ridesTrain
)
```

This is logically equivalent to: `implies(p,q) && implies(q,p)`

## Overrides

Class features implemented in a base class can be overridden in a subclass. The
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@
},
"keywords": [
"assertion",
"biconditional",
"behavioral-subtyping",
"code-contracts",
"decorators",
"demands",
"design-by-contract",
"encapsulation",
"exception-handling",
"if-and-only-if",
"invariant",
"liskov-substitution-principle",
"LSP",
Expand Down
24 changes: 24 additions & 0 deletions src/iff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*!
* @license
* Copyright (C) 2021 Final Hill LLC
* SPDX-License-Identifier: AGPL-3.0-only
* @see <https://spdx.org/licenses/AGPL-3.0-only.html>
*/

/**
* Biconditional.
* p ↔ q.
* "P if and only if Q".
* An example of usage is the encoding of "You can ride the train if and only if you have a ticket"
* This is logically equivalent to: implies(p,q) && implies(q,p)
*
* @example
* iff(person.hasTicket, person.ridesTrain)
*
* @param {boolean} p - The antecedent
* @param {boolean} q - The consequent
* @returns {boolean} - The result
*/
export default function iff(p: boolean, q: boolean): boolean {
return (p && q) || (!p && !q);
}
25 changes: 25 additions & 0 deletions src/tests/iff.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*!
* @license
* Copyright (C) 2021 Final Hill LLC
* SPDX-License-Identifier: AGPL-3.0-only
* @see <https://spdx.org/licenses/AGPL-3.0-only.html>
*/
import iff from '../iff';

// https://github.com/final-hill/decorator-contracts/issues/225
describe('Biconditional tests', () => {
test('Truth Table', () => {
/*
p q p ↔ q
---------------
T T T
T F F
F T F
F F T
*/
expect(iff(true,true)).toBe(true);
expect(iff(true,false)).toBe(false);
expect(iff(false,true)).toBe(false);
expect(iff(false,false)).toBe(true);
});
});

0 comments on commit 8c2c696

Please sign in to comment.