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
enhancement(remap): introduce is_TYPE
helper functions
#6775
Conversation
59b0ad2
to
fc42d19
Compare
lib/vrl/stdlib/src/type_of.rs
Outdated
} | ||
} | ||
|
||
/*#[cfg(test)] |
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 the unit tests should be runnable now as-of #6492
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
f3debf4
to
bf9f784
Compare
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 haven't looked at the implementation details yet, but before I do that, I wanted to note that a previous issue was filed to discuss this feature:
In it, @binarylogic also proposed a type
function similar to type_of
.
I raised a concern that this could become problematic in the future if we want to introduce type-level scoping.
For example, I envision us being able to do:
if is_string(.foo) {
// compiler knows `.foo` is a string, so this is OK
.foo = upcase(.foo)
}
For this to work, we'd need to add a feature to the compiler that allows functions to bubble up type information invariants about one or more of their arguments. In this case, the is_string
function would let the compiler know whether .foo
is a string, which can then be used within the if block
scope to allow functions to treat .foo
as if it were a string.
By having a type_of
function, this becomes more difficult and/or hacky to solve because it would no longer just be the function that can inform the compiler about the type, you'd also need to special-case the conditional that happens afterward (e.g. type_of(.foo) == "string")
.
So, my preference would be to add all missing is_*
functions, then more forward with the type-level scoping proposal, and after that make a proposal on how we could add type_of
.
@JeanMertz Thanks for the insights ! I read the discussion in #5261 and based on my somehow very low knowledge of VRL I concur with the conclusion that I will rework the PR accordingly. |
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
type_of
helper functionis_TYPE
helper functions
lib/vrl/stdlib/src/is_array.rs
Outdated
match v { | ||
Value::Array(_) => Ok(value!(true)), | ||
_ => Ok(value!(false)), | ||
} |
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 code is fine, but could be simplified using matches! to something like:
Ok(value!(matches!(v, Value::Array(_))))
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.
At that point, you might as well collapse it all together 😄
Value
has is_xxx()
already implemented, so you can do:
self.value.resolve(ctx).map(Value::is_array)
I think it would be worth adding an |
Thanks for the review ! |
Yes, of course, I hadn't thought of that. I think it might still come in handy for future work as Jean suggested earlier where we may then be able to derive typing information inside the if blocks. |
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.
LGTM! I added one comment, but I don't consider that a blocker.
I think it might still come in handy for future work as Jean suggested earlier where we may then be able to derive typing information inside the if blocks.
null
is a bit of a special case, since it's both a type and a value. If/when we add typed scopes, we'll have to support foo == null
regardless, otherwise it would be very weird for is_null(foo)
to work, but foo == null
not. I don't have a particular opinion on if we should support is_null
, it seems a bit pointless, but it does round up all the is_*
functions, which might be something we want to do.
lib/vrl/stdlib/src/is_array.rs
Outdated
match v { | ||
Value::Array(_) => Ok(value!(true)), | ||
_ => Ok(value!(false)), | ||
} |
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.
At that point, you might as well collapse it all together 😄
Value
has is_xxx()
already implemented, so you can do:
self.value.resolve(ctx).map(Value::is_array)
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
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 looks good to me! Could we add these to the benchmark suite too?
Sure will do. |
07c64e5
to
c69b216
Compare
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
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.
🎉
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
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.
Just some pedantic suggestions for the docs 😄
arguments: [ | ||
{ | ||
name: "value" | ||
description: #"The value to check"# |
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.
description: #"The value to check"# | |
description: "The value to check." |
#"Returns `true` if `value` is an array."#, | ||
#"Returns `false` if `value` is anything else."#, |
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.
#"Returns `true` if `value` is an array."#, | |
#"Returns `false` if `value` is anything else."#, | |
"Returns `true` if `value` is an array.", | |
"Returns `false` if `value` is anything else.", |
arguments: [ | ||
{ | ||
name: "value" | ||
description: #"The value to check"# |
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.
description: #"The value to check"# | |
description: "The value to check." |
#"Returns `true` if `value` is a boolean."#, | ||
#"Returns `false` if `value` is anything else."#, |
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.
#"Returns `true` if `value` is a boolean."#, | |
#"Returns `false` if `value` is anything else."#, | |
"Returns `true` if `value` is a boolean.", | |
"Returns `false` if `value` is anything else.", |
arguments: [ | ||
{ | ||
name: "value" | ||
description: #"The value to check"# |
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.
description: #"The value to check"# | |
description: "The value to check." |
#"Returns `true` if `value` is a regex."#, | ||
#"Returns `false` if `value` is anything else."#, |
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.
#"Returns `true` if `value` is a regex."#, | |
#"Returns `false` if `value` is anything else."#, | |
"Returns `true` if `value` is a regex.", | |
"Returns `false` if `value` is anything else.", |
arguments: [ | ||
{ | ||
name: "value" | ||
description: #"The value to check"# |
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.
description: #"The value to check"# | |
description: "The value to check." |
#"Returns `true` if `value` is a string."#, | ||
#"Returns `false` if `value` is anything else."#, |
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.
#"Returns `true` if `value` is a string."#, | |
#"Returns `false` if `value` is anything else."#, | |
"Returns `true` if `value` is a string.", | |
"Returns `false` if `value` is anything else.", |
arguments: [ | ||
{ | ||
name: "value" | ||
description: #"The value to check"# |
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.
description: #"The value to check"# | |
description: "The value to check." |
#"Returns `true` if `value` is a timestamp."#, | ||
#"Returns `false` if `value` is anything else."#, |
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.
#"Returns `true` if `value` is a timestamp."#, | |
#"Returns `false` if `value` is anything else."#, | |
"Returns `true` if `value` is a timestamp.", | |
"Returns `false` if `value` is anything else.", |
Closes #6732
Introduce a set of helper functions to test the type of a VRL var:
is_string("foobar")
returnstrue
is_string(1515)
returnsfalse
is_integer(11)
returnstrue
and so on for the supported types.
Signed-off-by: prognant pierre.rognant@datadoghq.com