Skip to content
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

Merged
merged 11 commits into from Mar 31, 2021

Conversation

prognant
Copy link
Contributor

@prognant prognant commented Mar 16, 2021

Closes #6732

Introduce a set of helper functions to test the type of a VRL var:

is_string("foobar") returns true

is_string(1515) returns false

is_integer(11) returns true

and so on for the supported types.

Signed-off-by: prognant pierre.rognant@datadoghq.com

@prognant prognant force-pushed the prognant/add_is_TYPE_functions_to_VRL branch from 59b0ad2 to fc42d19 Compare March 16, 2021 11:35
}
}

/*#[cfg(test)]
Copy link
Member

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

@prognant prognant marked this pull request as ready for review March 19, 2021 14:45
@prognant prognant requested review from a team and pablosichert and removed request for a team March 19, 2021 14:45
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
@prognant prognant force-pushed the prognant/add_is_TYPE_functions_to_VRL branch from f3debf4 to bf9f784 Compare March 19, 2021 16:56
Copy link
Contributor

@JeanMertz JeanMertz left a 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:

#5261

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.

@prognant
Copy link
Contributor Author

prognant commented Mar 22, 2021

@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 is_<type> functions are a better option as of today. And ultimately after having a type-level scoping, we could then implement a proper type_of function that could properly type-feed a conditional block.

I will rework the PR accordingly.

Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
@prognant prognant changed the title enhancement(remap): introduce type_of helper function enhancement(remap): introduce is_TYPE helper functions Mar 26, 2021
match v {
Value::Array(_) => Ok(value!(true)),
_ => Ok(value!(false)),
}
Copy link
Contributor

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(_))))

Copy link
Contributor

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)

@StephenWakely
Copy link
Contributor

I think it would be worth adding an is_null function as well. Currently we have is_nullish, but that does a bit more than a simple is_null would do. eg.. is_nullish("") == true but is_null("") == false.

@prognant
Copy link
Contributor Author

I think it would be worth adding an is_null function as well. Currently we have is_nullish, but that does a bit more than a simple is_null would do. eg.. is_nullish("") == true but is_null("") == false.

Thanks for the review !
I was thinking that some_val == null could be used for null type assertion (but I'm not 100% sure it would work) anyway for consistency purpose I agreee that having an is_null function make sense. I will add it.

@StephenWakely
Copy link
Contributor

I was thinking that some_val == null

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.

Copy link
Contributor

@JeanMertz JeanMertz left a 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.

docs/reference/remap/functions/is_timestamp.cue Outdated Show resolved Hide resolved
match v {
Value::Array(_) => Ok(value!(true)),
_ => Ok(value!(false)),
}
Copy link
Contributor

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>
Copy link
Member

@jszwedko jszwedko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prognant
Copy link
Contributor Author

Sure will do.

Signed-off-by: prognant <pierre.rognant@datadoghq.com>
@prognant prognant force-pushed the prognant/add_is_TYPE_functions_to_VRL branch from 07c64e5 to c69b216 Compare March 30, 2021 15:05
Signed-off-by: prognant <pierre.rognant@datadoghq.com>
Copy link
Member

@jszwedko jszwedko left a 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>
@prognant prognant merged commit b7d7c4a into master Mar 31, 2021
@prognant prognant deleted the prognant/add_is_TYPE_functions_to_VRL branch March 31, 2021 12:58
Copy link
Contributor

@pablosichert pablosichert left a 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"#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: #"The value to check"#
description: "The value to check."

Comment on lines +21 to +22
#"Returns `true` if `value` is an array."#,
#"Returns `false` if `value` is anything else."#,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#"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"#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: #"The value to check"#
description: "The value to check."

Comment on lines +21 to +22
#"Returns `true` if `value` is a boolean."#,
#"Returns `false` if `value` is anything else."#,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#"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"#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: #"The value to check"#
description: "The value to check."

Comment on lines +21 to +22
#"Returns `true` if `value` is a regex."#,
#"Returns `false` if `value` is anything else."#,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#"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"#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: #"The value to check"#
description: "The value to check."

Comment on lines +21 to +22
#"Returns `true` if `value` is a string."#,
#"Returns `false` if `value` is anything else."#,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#"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"#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: #"The value to check"#
description: "The value to check."

Comment on lines +21 to +22
#"Returns `true` if `value` is a timestamp."#,
#"Returns `false` if `value` is anything else."#,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#"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.",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add is_TYPE functions to vrl
5 participants