Given something like:
#props.field1.field2.field3
I want to test if field3 exists. So:
#props.field1.field2.field3?
But. If field2 does not exist on field1 then then above line produces an error.
But I want to avoid a bunch of nested tests:
if #props.field1
if #props.field2
if #props.field3
//do something
Is this possible?
From the fine manual:
The Existential Operator
[...]
The accessor variant of the existential operator ?. can be used to soak up null references in a chain of properties. Use it instead of the dot accessor . in cases where the base value may be null or undefined. If all of the properties exist then you'll get the expected result, if the chain is broken, undefined is returned instead of the TypeError that would be raised otherwise.
So you could say:
#props?.field1?.field2?.field3?
to ignore missing properties all the way down.
if #props.field1 && #props.field2 && #props.field3
If one of the properties does not exists the compiler will not test any of the following
Actually
if #props.field3 should do the job
Related
I am new to Drools, we are trying to create basic validation rules like a NULL check, etc. using the Drools n Scala framework.
I have a source file which has 200 attributes, need to apply NULL-check rule on all these attributes,
is there any easy way to do this? or do I need to create 200 rules for each attribute?
Thanks in advance.
Assuming you have a POJO ("plain old java object", getters/setters and some private variables to hold values) or modern java Records (effectively the same thing), then the answer is no: you need separate rules. For this scenario, the only way to check that field "name" is null is to actually assert against that field like this:
rule "example - name is null"
when
ExampleObject( name == null )
then
System.out.println("Name is null.");
end
However there exist other data structures -- for example, Map and its sibling types -- where you can reference the fields by name. In this case you could theoretically iterate through all of the field names and find the one whose value is empty.
So, for example, Map has a keySet() method which returns a set of fields -- you could iterate through this keyset and for each key check that there is a non-null value present in the map.
rule "example with map"
when
$map: Map()
$keys: Set() from $map.keySet()
$key: String() from $keys
String( this == null ) from $map.get($key)
// or this might work, not sure if the "this" keyword allows this syntax:
// Map( this[$key] == null ) from $map
then
System.out.println($key + " is missing/null");
end
This would require converting your Java object into a Map before passing into the rules.
However I DO NOT RECOMMEND this approach. Maps are extremely un-performant in rules because of how they serialize/deserialize. You will use a ton of unnecessary heap when firing them. If you look at how a HashMap serializes, for example, by peeking at its source code you'll see that it actually contains a bunch of "child" data structures like entryset and keyset and things like that. When using "new", those child structures are only initialized if and when you need them; but when serializing/deserializing, they're created immediately even if you don't need them.
Another solution would be to use Java reflection to get the list of declared field names, and then iterate through those names using reflection to get the value out for that field. In your place I'd do this in Java (reflection is problematic enough without trying to do it in Drools) and then if necessary invoke such a utility function from Drools.
When I do app.getArgument("ARGUMENT_NAME") it returns the reference value for synonym. How do I determine the requested synonym rather than the reference value?
If you look at the JSON, this used to be available in the "result"."parameters"."name.original" field, but that seems to have changed at some point.
Now you can find it in the parameters for any of the contexts. So if you are using JavaScript and have the JSON in a variable named "body" and the argument name in a variable named "name", you can probably evaluate something like
body.result.contexts[0].parameters[`${name}.original`]
to get the value you want.
If you define a DSL file with some lines, and one of them uses a variable, you cannot use it twice in a rule because you will get a duplicate variable error.
What's the best way to avoid this? Ideally I would like to avoid to create two copies of the DSL line to just change the variable name.
ie, the DSL line:
[when][]For all qualifications of type Higher=$highers: Higher()
this cannot be used twice in the same rule or we get a duplicate $highers variable.
You can synthesize the name of a binding variable like any other chunk of text:
[when][]there is a qualification of type {qualification}=
${qualification}: {qualification}()
But it's going to be tricky because you'll have to make references to this variable variable variable, too:
[then] print {qualification}=System.out.println( ${qualification} );
instead of the straightforward
[then] print qualification=System.out.println( $qualification );
A lurking danger is that the amount of text that remains as a "landmark" around the macro variables is reduced which may result in multiple matches.
I know I've beem askimg alot, I am learning daly!
The offending expression is:
=IIf(Parameters!ResponseRange.Value = 3, Nothing,
IIf(Parameters!ResponseRange.Value is Nothing, Nothing,
Parameters!ResponseRange.Value))
It's spec. because of this part - Parameters!ResponseRange.Value is Nothing, Nothing,
As for the Parameters, here's a screenshot of how they look - the Parameter is a "Text" data type:
The order of the IIf() checks in that expression are odd; generally you want to handle the "success" or the non-null cases first. Also, you can combine the two checks into one IIf():
=IIf(Not IsNothing(Parameters!ResponseRange.Value) AndAlso
Parameters!ResponseRange.Value <> 3, Parameters!ResponseRange.Value, Nothing)
Note that I substituted the IsNothing() function for the Is Nothing expression. Other than that, the expression itself is valid. What is the data type for the ResponseRange parameter? I'm deducing that it is an Integer via the comparison to 3. Do you have it marked that it can be null? Primitive data types like Integer can't be set to Nothing like you're attempting if you haven't made them nullable.
You may need to set a default value of 0 or -1 instead of Nothing and handle that subsequently in your query.
How do I test and see if a variable is set in Scala. In PHP you would use isset()
I am looking for a way to see if a key is set in an array.
First, Array in Scala does not have keys. They have indices, and all indices have values in them. See the edit below about how those values might be initialized, though.
You probably mean Map, which has keys. You can check whether a key is present (and, therefore, a value) by using isDefinedAt or contains:
map isDefinedAt key
map contains key
There's no practical difference between the two. Now, you see in the edit that Scala favors the use of Option, and there's just such a method when dealing with maps. If you do this:
map get key
You'll receive an Option back, which will be None if the key (and, therefore, the value) is not present.
EDIT
This is the original answer. I've noticed now that the question is not exactly about this.
As a practical matter, all fields on the JVM are pre-initialized by the JVM itself, which zeroes it. In practice, all reference fields end up pointing to null, booleans are initialized with false and all other primitives are initialized with their version of zero.
There's no such thing in Scala as an "undefined" field -- you cannot even write such a thing. You can write var x: Type = _, but that simply results in the JVM initialization value. You can use null to stand for uninitialized where it makes sense, but idiomatic Scala code tries to avoid doing so.
The usual way of indicating the possibility that a value is not present is using Option. If you have a value, then you get Some(value). If you don't, you get None. See other Stack Overflow questions about various ways of using Option, since you don't use it like variable.isDefined in idiomatic code either (though that works).
Finally, note that idiomatic Scala code don't use var much, preferring val. That means you won't set things, but, instead, produce a new copy of the thing with that value set to something else.
PHP and Scala are so different that there is no direct equivalent. First of all Scala promotes immutable variables (final in Java world) so typically we strive for variables that are always set.
You can check for null:
var person: Person = null
//...
if(person == null) {//not set
//...
}
person = new Person()
if(person == null) {//set
//...
}
But it is a poor practice. The most idiomatic way would be to use Option:
var person: Option[Person] = None
//...
if(person.isDefined) {//not set
//...
}
person = Some(new Person())
if(person.isDefined) {//set
//...
}
Again, using isDefined isn't the most idiomatic ways. Consider map and pattern matching.