Proposal: Boolean.parseBoolean
Just to check my understanding, would
Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };
be a reasonable polyfill for your proposed function?
This would definitely be useful for parsing process.env.*
environment
variables in Node!
Ben
On Thu, Mar 16, 2017 at 2:03 PM, Ben Newman <benjamin at cs.stanford.edu>
wrote:
Just to check my understanding, would
Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };
be a reasonable polyfill for your proposed function?
Yep, this looks good.
Dmitry
On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu> wrote:
Just to check my understanding, would
Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };
be a reasonable polyfill for your proposed function?
Not quite -- that would throw for strings that are not valid JSON, e.g.:
Boolean.parseBoolean('{dddddd]');
It'd probably be more like:
Boolean.parseBoolean = function (val) {
if (val === 'false') return false;
return !!val;
};
在 2017/3/17 5:03, Ben Newman 写道:
Just to check my understanding, would
Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };
be a reasonable polyfill for your proposed function?
This implemention throws for invalid JSON syntax and is case-sensitive (Java's counterpart is case-insensitive). Is this better?
Boolean.parseBoolean = function (value) {
return !(!value || /^false$/i.test('' + value));
};
However I'm not sure this is widely useful. If the value is not from JSON, there are a lot of alternatives for 'true|false', e.g. 'yes|no', 'on|off', or 'T|F', and different rules for casing/empty value/invalid syntax. So it's better to do this in users' code.
The user's code…
Trying to parse "" will also throw with JSON; !!"false " is true; host objects (or whatever they're called now) such as document.all.
Unsubscribing. Not sure why I didn't earlier… I need to stay a code-free user. :-)
On Thu, Mar 16, 2017 at 7:04 PM, Karl Cheng <qantas94heavy at gmail.com> wrote:
On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu> wrote:
Just to check my understanding, would
Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };
be a reasonable polyfill for your proposed function?
Not quite -- that would throw for strings that are not valid JSON, e.g.:
Boolean.parseBoolean('{dddddd]');
It'd probably be more like:
Boolean.parseBoolean = function (val) { if (val === 'false') return false; return !!val; };
Looks good either (probably worth making case-insensitive).
Dmitry
What would be the result for Boolean.parseBoolean('undefined')
and
Boolean.parseBoolean('null')
?
On 03/16/2017 09:40 PM, Dmitry Soshnikov wrote:
On Thu, Mar 16, 2017 at 7:04 PM, Karl Cheng <qantas94heavy at gmail.com <mailto:qantas94heavy at gmail.com>> wrote:
On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu <mailto:benjamin at cs.stanford.edu>> wrote: > Just to check my understanding, would > > Boolean.parseBoolean = function (value) { > return !! (value && JSON.parse(String(value))); > }; > > be a reasonable polyfill for your proposed function? Not quite -- that would throw for strings that are not valid JSON, e.g.: ``` Boolean.parseBoolean('{dddddd]'); ``` It'd probably be more like: ``` Boolean.parseBoolean = function (val) { if (val === 'false') return false; return !!val; }; ```
Looks good either (probably worth making case-insensitive).
There are many, many reasonable choices for a function that maps a string to a boolean. Even more for a function that maps an arbitrary value to a boolean. The choice of the function is highly context dependent. That context includes language/locale/whatever the right l10n term is. It's true that JS could arbitrarily pick one, but then it would implicitly be favoring one context over another. And not even Node and the Web would completely agree on the most appropriate definition. It makes sense for JSON to pick a single function, because it's a specified interchange format.
-1 from me.
On Fri, Mar 17, 2017 at 7:42 AM Augusto Moura <augusto.borgesm at gmail.com>
wrote:
What would be the result for
Boolean.parseBoolean('undefined')
andBoolean.parseBoolean('null')
?
Perhaps this should be restricted to JSON-compatible "false" only. Other possible may include "", and "0". For stricter handling "null", "undefined", and similar strings may even throw as non-Boolean parseable.
Dmitry
On Thu, Mar 16, 2017 at 1:55 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:
Similar to
Number.parseInt
, theBoolean.parseBooelan
might be useful for "boolean strings" retrieved from some string-based storages, which do not support other types at serialization.Boolean.parseBoolean('true'); // true Boolean.parseBoolean('false'); // false
OK, here the actual proposed spec for it: gist.github.com/DmitrySoshnikov/5ee1a7d51d8dbe159ae917876b27f36a
I made it plain simple (anything which is not case-insensitive "true"
is
false
), and copy-pasted from Java.
Dmitry
Any reason for not just using Boolean.parse
? (Rather than repeating
Boolean
in the function name?)
-- T.J. Crowder
On Mon, Mar 20, 2017 at 11:57 AM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote:
Any reason for not just using
Boolean.parse
? (Rather than repeatingBoolean
in the function name?)
Just a copy-paste from Java, similarly was done with parseInt
taken from
Java. But just parse
probably would work too. For consistency and
predictability parseBoolean
is probably better now.
Dmitry
I'd say there's no clear model for consistenty, e.g. JSON.parse. One could
argue that the template is that anything which has only one way to parse is
to use parse
. Numbers have more than one way (parseInt
, parseFloat
)
One could argue that parse
makes more sense, as there is really just that one way to parse a bool.
Funny, I'd go the other way. We have parseInt
in part because we also
have parseFloat
. Date
has parse
(but it doesn't return a Date
,
sigh). JSON
has parse
.
For me, consistency with Java isn't important for this.
My $0.02 for what it's worth...
-- T.J. Crowder
As mentioned in the gist, and FWIW, -1 here.
/^true$/i.test(str)
works since ever for the specified use case
Boolean.parseBoolean(1)
that returns false
is a footgun.
Either we talk about a better definition of truthy-like values, or having a
public spec about just string type and true
as value looks like the
solution for 1% of use cases that's also already covered by JSON.parse
On Mon, Mar 20, 2017 at 12:09 PM, kdex <kdex at kdex.de> wrote:
One could argue that
parse
makes more sense, as there is really just that one way to parse a bool.
I agree, just parse
sounds good (similar to Date.parse
, and
JSON.parse
). Since in parseInt
, the Int
is a quantifier.
Dmitry
On Mon, Mar 20, 2017 at 12:12 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
As mentioned in the gist, and FWIW, -1 here.
/^true$/i.test(str)
works since ever for the specified use case
Boolean.parseBoolean(1)
that returnsfalse
is a footgun.Either we talk about a better definition of truthy-like values, or having a public spec about just string type and
true
as value looks like the solution for 1% of use cases that's also already covered byJSON.parse
Still, semantics matter :) With a JSON.parse
you may parse any JSON
value, and then will have to do extra checks. RegExp test is also less
semantic. Initially in the thread I considered truthy/falsey values, but
then reduced to strings only, and took Java's implementation, but this can
be discussed. The need for a semantic method from Boolean
still exists,
instead of using ad-hoc technics like JSON or regexp, which are just
implementation details for the semantic method.
Dmitry
I still think Boolean.parse
makes sense only if gives us something more
than JSON.parse
like /^true|yes|y|1$/i.test(value)
would do.
Otherwise I personally don't see any real-world use case for it, specially not those from bash or env variables.
I would add case insensitive "t", "y", "yes", 1, -1 as well
My suggestion for a polyfill.
if (!Boolean.parse) { Boolean.parse = function(input) { // return false if it is already falsy if (!input) return false;
var expr = String(input);
// return false if it's reasonably too long of a string
if (expr.length > 10) return false;
// test trimmed input against truthy values
return (/^(-?1|y|t|yes|true)$/).test(expr.trim().toLowerCase());
} }
-1/1 are common database boolean/bit fields y/yes also common inputs for truthiness t/true also common for truthiness
These account for pretty much every case of truthy stored values I've seen in the wild.
--- Dmitry, sorry, meant to reply-all the first time, also refactored the polyfill slightly to better account for potentially too long an input value.
On Mon, Mar 20, 2017 at 4:59 PM, Michael J. Ryan <tracker1 at gmail.com> wrote:
My suggestion for a polyfill.
if (!Boolean.parse) { Boolean.parse = function(input) { // return false if it is already falsy if (!input) return false;
var expr = String(input); // return false if it's reasonably too long of a string if (expr.length > 10) return false; // test trimmed input against truthy values return (/^(-?1|y|t|yes|true)$/).test(expr.trim().toLowerCase());
} }
-1/1 are common database boolean/bit fields y/yes also common inputs for truthiness t/true also common for truthiness
Yeah, these might be good in general, although I'd like to reduce the
proposal to minimum vital version, and JS related. The problem we are
trying to solve is to parse "false"
as false
. It's not possible with
Boolean('false')
today. And all the JSON.parse, and regexp manipulations
are too low-lever implementation details; users want good semantic library!
:)
So:
Boolean.parse('true'); // true
Boolean.parse('false'); // false
That's all we need for now, and already will be much better semantic alternative too all existing "non-semantic building material".
Dmitry
I slightly disagree... mainly in that as it stands, we have a fairly loose type coercion system that allows almost anything to be coerced into a boolean... in this case "parse" at least in my mind means that it should cover the most common use cases. I understand that Boolean("false") doesn't currently work this way, and why Date.parse doesn't give a date instance is a bit beyond me.
With my suggested polyfill your use case would work as expected... However, JS interacts with more than just serialized results from JS. It interacts with input from multiple systems, sources, users and good/bad the content of users. The type coercion as it exists for boolean is in order to provide for simplistic validation... why an empty string coerces false, for example. Much like we have defined "falsey" values in JS, I think that Boolean.parse should have common truthy values/strings that can predictably be converted as a true, where all else is false.
If all it does is:
input => String(input).toLowerCase() === 'true';
what is the point of extending Boolean?
On Tue, Mar 21, 2017 at 11:49 AM, Michael J. Ryan <tracker1 at gmail.com>
wrote:
I slightly disagree... mainly in that as it stands, we have a fairly loose type coercion system that allows almost anything to be coerced into a boolean... in this case "parse" at least in my mind means that it should cover the most common use cases. I understand that Boolean("false") doesn't currently work this way, and why Date.parse doesn't give a date instance is a bit beyond me.
With my suggested polyfill your use case would work as expected... However, JS interacts with more than just serialized results from JS. It interacts with input from multiple systems, sources, users and good/bad the content of users. The type coercion as it exists for boolean is in order to provide for simplistic validation... why an empty string coerces false, for example. Much like we have defined "falsey" values in JS, I think that Boolean.parse should have common truthy values/strings that can predictably be converted as a true, where all else is false.
If all it does is:
input => String(input).toLowerCase() === 'true';
what is the point of extending Boolean?
Yeah, all good points, but they open a door for more questions mentioned above (so many different formats, "yes", "1", "on", etc, and "why one, but not another?", and "why not i18n?").
So to reduce this, having a good MVP would be good. Then, if there is a need, it can be extended by adding.
The actual practical use-case I want to solve is:
-
Not to use "raw building material" (aka "syntactic garbage") to solve the issue. With this I mean using non-semantic techniques to achieve the goal, like RegExp testings, JSON.parsing, etc. This is also a building material: "String(input).toLowerCase() === 'true';", and users want nice semantic library.
-
To solve
Boolean('false')
issue. This is an actual use-case I had, when was asked why Boolean type coercion treats "false" as true, and there is no good answer other than -- "it's specified so". So to keep backward compats we need Boolean.parse(...) for this.
So the only question it needs to address whether we accept truthy/false values, or only strings.
Dmitry
The good answer is that Boolean(x)
is the same as ‼x
(which is a good
thing) - and the string "false" is truthy, since the only falsy string
value is the empty string.
Similar to
Number.parseInt
, theBoolean.parseBooelan
might be useful for "boolean strings" retrieved from some string-based storages, which do not support other types at serialization.This is to contrast current:
In JS people do today:
Other parsing results:
The API, and the results are from Java's corresponding
Boolean.parseBoolean
method: docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html#parseBoolean(java.lang.String) .Dmitry