-
-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a parse function to the library #10
Conversation
index.js
Outdated
//. make their data types compatible with the algorithm. | ||
//. This package exports a function which derives a _type identifier_ from any | ||
//. JavaScript value, and a [specification][3] for customizing the type | ||
//. identifier of a value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence could be improved. As written This package exports applies to both clauses, but the package does not export a specification.
I suggest:
sanctuary-type-identifiers comprises:
- an npm and browser -compatible package for deriving the type identifier of a JavaScript value; and
- a specification which authors may follow to specify type identifiers for their types.
index.js
Outdated
return { | ||
type: type, | ||
parse: parse | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you agree with the way I exported it? Or would you rather see parse
be a property of type
, allowing this release to be MINOR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer type.parse
, though not for the reason given. I'd like to avoid type.type
. Do you agree that type
+ type.parse
is nicer, or are you opposed to exporting the functions in different ways?
I think the next release should be MAJOR to reflect the change to the specification, even though it is backwards compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. 6. Return the [`Object.prototype.toString`][2] representation of `x` | ||
//. without the leading `'[object '` and trailing `']'`. | ||
//. - the type identifier MUST be a string primitive and SHOULD have format: | ||
//. `'<namespace>/<name>[@<version>]'`, where: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence contains two colons. Let's remove the first one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. ### Compatibility | ||
//. - The `namespace` MUST consist of one or more characters, and SHOULD | ||
//. equal the npm package name which defines the type (including | ||
//. [scope][4] where appropriate); and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A type is defined by an npm package rather than by an npm package name. Let's replace the npm package name with the name of the npm package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. - every member of the type must have a `constructor` property pointing | ||
//. to an object known as the _type representative_; | ||
//. - the `version` MUST be a numeric value consisting of one or more | ||
//. digits, and it SHOULD represent the version of the type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Numeric value is redundant. Let's state that the version
MUST consist of one or more digits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. | ||
//. - the type representative's `@@type` property (the _type identifier_) | ||
//. must be a string primitive, ideally `'<npm-package-name>/<type-name>'`. | ||
//. - If the version is not given, it is assumed to be `0`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be _version_
to match _name_
and _namespace_
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
parsed[1] == null ? null : parsed[1], | ||
parsed[2], | ||
parsed[3] == null ? 0 : Number(parsed[3]) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find TypeIdentifier
to be an awkward function. I have thought of a way to remove it which may or may not be sensible. What do you think of the following?
var groups = RPARSE.exec(s);
return {
namespace: groups == null || groups[1] == null ? null : groups[1],
name: groups == null ? s : groups[2],
version: groups == null || groups[3] == null ? 0 : Number(groups[3])
};
I like the fact that default values (null
and 0
) are specified in one place rather than two. Also, the length of the longest line is 79 characters. ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡ - much nicer this way!
package.json
Outdated
@@ -12,6 +12,7 @@ | |||
}, | |||
"dependencies": {}, | |||
"devDependencies": { | |||
"doctest": "^0.12.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"0.12.x"
, please. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every time 😒
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
test/index.js
Outdated
eq(parse('package/Type@999'), TypeIdentifier('package', 'Type', 999)); | ||
eq(parse('package/Type@X'), TypeIdentifier('package', 'Type@X', 0)); | ||
eq(parse('package////@3@2@1@1'), TypeIdentifier('package///', '@3@2@1', 1)); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've done a nice job with these test cases. Each test case exists to test a specific pathway. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪
index.js
Outdated
//. 'Null' | ||
//. | ||
//. > type(true); | ||
//. 'Boolean' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like to omit trailing semicolons when writing doctests. Doctests are meant to resemble REPL interactions, after all. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. > function Identity(x) { this.value = x; } | ||
//. > Identity['@@type'] = 'my-package/Identity@1'; | ||
//. > type(new Identity(0)); | ||
//. 'my-package/Identity@1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of new
in the usage example bothers me. I'd prefer to make the set-up noisier to avoid it:
//. > function Identity(x) {
//. . if (!(this instanceof Identity)) return new Identity(x);
//. . this.value = x;
//. . }
//. . Identity['@@type'] = 'my-package/Identity@1';
//.
//. > type(Identity(42))
//. 'my-package/Identity@1'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know about the multiline syntax either. Nice. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. {namespace: null, name: 'nonsense!', version: 0} | ||
//. | ||
//. > function Identity(x) { this.value = x; } | ||
//. > Identity['@@type'] = 'my-package/Identity@1'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could remove these two lines as the definition from the first block of doctests should be in scope. I don't mind the repetition, but I want you to know that the repetition is not required in case you'd prefer to avoid it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. I was under the impression that each doctest runs in its own scope isolated scope which extends the scope in which the doctest was defined. I'll remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're interested in understanding the scoping, run this:
$ node_modules/.bin/doctest --module commonjs --prefix . --print -- index.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//# parse :: String -> { namespace :: Nullable String, name :: String, version :: Number } | ||
//. | ||
//. Takes any String and parses it according to the [specification][3], | ||
//. returning an object with a `namespace`, a `name` and a `version` field. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer this tweaked version:
- //. returning an object with a `namespace`, a `name` and a `version` field.
+ //. returning an object with `namespace`, `name`, and `version` fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. | ||
//# type :: Any -> String | ||
//. | ||
//. Takes any value and produces a String which represents its type. If the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer returns in place of produces. Also, I think string could be written in lower case in this context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And identifies instead of represents?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Identifies sounds good to me, yes. :)
index.js
Outdated
|
||
//. ### Usage | ||
//. | ||
//. `const {parse, type} = require('sanctuary-type-identifiers')` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be in a ```javascript
code block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think doctest went along and tried to execute it last time I tried, but that may have also had to do with my attempt to put the whole block in a quote-block (>
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, it's fine. It must've been the quote block. ⚡
index.js
Outdated
@@ -119,7 +103,46 @@ | |||
// $$type :: String | |||
var $$type = '@@type'; | |||
|
|||
// type :: Any -> String | |||
// RPARSE :: RegExp | |||
var RPARSE = /^([^]+)\/([^]+?)(?:@(\d+))?$/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still very much in favour of the version with comments I proposed in #8 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚡
index.js
Outdated
//. > type.parse(Identity['@@type']) | ||
//. {namespace: 'my-package', name: 'Identity', version: 1} | ||
//. ``` | ||
/* eslint-disable key-spacing */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are breaking the key-spacing
rule in most of the parse
function.
- We want to break the rule, because it looks nice in this case.
- Disabling the rule altogether would open the rest of the code up for this mistake.
- Putting the comments outside of the function was most aesthetically pleasing.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to break the rule, because it looks nice in this case.
I'd go further by claiming that in this case it makes the code easier to comprehend.
Disabling the rule altogether would open the rest of the code up for this mistake.
I like having strict rules as a starting point, but I'm happy to break the rules in some cases. The makefiles for the various Sanctuary projects disable several rules. Let's add --rule 'key-spacing: [off]'
to the makefile.
@@ -129,6 +160,38 @@ | |||
Object.prototype.toString.call(x).slice('[object '.length, -']'.length); | |||
} | |||
|
|||
//# type.parse :: String -> { namespace :: Nullable String, name :: String, version :: Number } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you also have documented this function as type.parse
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! 👍
index.js
Outdated
//. | ||
//. For example: | ||
//. | ||
//. ```javascript | ||
//. // Identity :: a -> Identity a | ||
//. function Identity(x) { | ||
//. if (!(this instanceof Identity)) return new Identity(x); | ||
//. if (!(this instanceof Identity)) return Identity(x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops.
index.js
Outdated
//. ### Usage | ||
//. | ||
//. ```javascript | ||
//. var type = require('sanctuary-type-identifiers')` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/`/;/
We could use const
here rather than var
, if you like. :)
index.js
Outdated
} | ||
/* eslint-enable key-spacing */ | ||
|
||
type.parse = parse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer type.parse = function parse(s) { ... };
.
This is looking very good, Aldwin. I particularly like the way you reorganized the doctests. :) |
index.js
Outdated
//. - the type representative must have a `@@type` property; and | ||
//. - If the type identifier does not conform to the format specified above, | ||
//. it is assumed that the entire string represents the _name_ of the type, | ||
//. and _namespace_ will be `null`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should make this change:
- and _namespace_ will be `null`
+ and _namespace_ and _versoin_ will be `null`
to make it clear that if @@type
is T@1
version will not be parsed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ _versoin_ will be `null`
Version will actually just be 0
, as implied by the statement below. Do you think it should be null
?
to make it clear that if
@@type
isT@1
version will not be parsed
That should be conveyed by the entire string represents the name of the type. Do you think it's unclear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... Do you think it should be null?
My mistake, it should be:
+ and _versoin_ will be `0`
... Do you think it's unclear?
It was a bit unclear for me, as it states "and namespace will be null
", but says nothing about version
.
index.js
Outdated
//. - If the type identifier does not conform to the format specified above, | ||
//. it is assumed that the entire string represents the _name_ of the type. | ||
//. _namespace_ will be `null` and _version_ will be `0` in accordance with | ||
//. the following statement: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this, @safareli? Do you approve of this change @davidchambers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it, though I would drop in accordance with the following statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it too. +1 for dropping "in accordance with the following statement"
index.js
Outdated
//. - every member of the type must have a `constructor` property pointing | ||
//. to an object known as the _type representative_; | ||
//. - the `version` MUST consist of one or more digits, and it SHOULD | ||
//. represent the version of the type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second clause of each of the sibling points begins and SHOULD rather than and it SHOULD. Let's remove it.
I have one remaining concern, of a typographical nature. ;) There are several consistent approaches to formatting lists. Sentence fragments:
Complete sentence:
Multiple stand-alone points:
Currently we have this:
We're mixing styles. Also, it seems to me that the last two points don't belong in the list since they are not compatibility requirements. I suggest this structure:
Also, is there a reason to use |
In the instances where
|
I thought this might be the case. You don't do things arbitrarily. :)
I like this option. Additionally, let's drop the definite article: |
I pushed one (last!) commit to your branch, Aldwin. Please confirm that you're happy with the changes, then squash your commits. You may also like to view the rendered proof. |
04647c9
to
491fdb2
Compare
Squashed and happy! |
491fdb2
to
924bf05
Compare
This commit adjusts the specification to allow for the inclusion of a version number in the type identifier. It also adds a utility function to the library which takes a string and parses it as a type identifier to separate the different parts. This function is exposed as `type.parse`. Furthermore, because this change asked for a more extensive API documentation, the commit adds validation of the documentation by doctest. Closes #4 Closes #8 (supersedes)
924bf05
to
a91f7fe
Compare
🎉 |
I decided to make a new pull-request, as this is a somewhat different solution to the one originally proposed in #8. This keeps the conversation-log clean.
Closes #4
Closes #8 (supersedes)