jsonnet
jsonnet copied to clipboard
Add std.parseFloat
I would like to suggest a feature to parse strings into float numbers. I haven't found std.parseFloat()
function in https://jsonnet.org/ref/stdlib.html. Since std.extVar
returns a string it's impossible to use float numbers as external variables.
In my case, it would be useful since I used jsonnet to describe experiments in AllenNLP framework as sometimes I pass hyperparameters like learning rate as an environmental variable. Although I could obviously pass them using a top-level function, some platforms like Polyaxon requires to pass them as environmental variables.
Since std.extVar returns a string it's impossible to use float numbers as external variables.
Not necessarily. You can do something like:
21x.jsonnet:
std.extVar('foo') * 21
Command to run (see that --ext-code
is used rather than --ext-var
):
jsonnet --ext-code foo=2 21x.jsonnet
That said, parseFloat would be a useful addition to stdlib.
Workaround: use std.parseJson
, which can also parse a float as a special case:
$ ./jsonnet -e 'std.parseJson("3.14")'
3.1400000000000001
Thank you for the workaround!
Workaround: use
std.parseJson
, which can also parse a float as a special case:
That's what we've done. It's not easy to discover that workaround the first time, but it does work well enough so far.
I need to be able to parse a float that isn't an external variable. Unfortunately, std.parseJson has a little problem:
% jsonnet -e 'std.parseJson("x3.1")'
Something went wrong during jsonnet_evaluate_snippet, please report this: [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'
The error is not ideal and should be fixed (it shouldn't just crash) and it should be fixed. That said, "x3.1" is not a valid float, so I don't see how std.parseFloat would help you here.
std.parseJson("1.0") is parsed as 1 (int) instead of 1.0 (float). Is there a workaround for this?
I was just fooling around to see what would happen. I'd have expected a failure, of course. What I actually want to do is to validate a string that contains a bunch of numbers. I think that failing on such an assertion is OK for many purposes, but if you want to check that a string encodes a number as a option, you're out of luck.
What I'd really like to see is support for regexp matching.
@eladsegal
std.parseJson("1.0") is parsed as 1 (int) instead of 1.0 (float).
There's no separate int type in Jsonnet. A floating point number 1.0
is printed out as 1
. (That's the same behavior as in JS).
@sbarzowski Oh, I see. Python's json library does make the distinction, so I hoped the same from jsonnet's python bindings. Thanks!
@glenntrewitt
Weel parseFloat wouldn't help you. It would still error out.
Regexp support may come in the future. In the meantime you can validate "manually" which shouldn't be too hard in this case.
You can try a library I wrote: https://github.com/sbarzowski/jsonnet-parser-combinators. It can actually do more than regexp, but it's very slow.
Just playing around with this before reading about the std.parseJson
workaround and came up with this naive implementation:
{
parseFloat(str)::
local decimalPoint = std.find('.', std.reverse(std.stringChars(str)));
assert std.length(decimalPoint) <= 1 : 'Not a float, str has too many decimal points';
local strWithoutDecimalPoint = std.strReplace(str, '.', '');
std.parseInt(strWithoutDecimalPoint) / std.pow(10, decimalPoint[0]),
}