Intershop: checking for not null in .isml template - intershop

I'm not finding a function to test for the existence of a value in the ISML template code. There's 'isDefined' but not 'isNull'.
isDefined returns true on null values:
<isset name="woot" value="" scope="request">
<isif condition="#isDefined(woot)#">
<h1>woot</h1>
</isif>
For now I'm using:
<isif condition="#woot EQ null#">
or
<isif condition="#woot EQ ''#">
I don't know if this will work for Boolean values.

isDefined is how you would check for a null value. In AbstractTemplate you have the method isDefined(Object anObject) that is called. Checkout the compiled jsp and java versions of your isml template.
In AbstractTemplate
public Boolean isDefined(Object anObject){
...
return anObject != null ? Boolean.TRUE : Boolean.FALSE;
}
The code in your example is a bit misleading, it doesn't actually test for a null reference. Bear with me.
First statement :
<isset name="woot" value="" scope="request">
Compiles to :
Object temp_obj = ("");
getPipelineDictionary().put("woot", temp_obj);
This just sets the woot variable to an empty string. If you add the following scriptlet to your isml you will see that it really isn't a null.
Disclaimer: don't use scriptlets in production code, this is only for demonstrating a point
<%
Object woot = getPipelineDictionary().get("woot");
out.print(woot == null); //print false
%>
Second line:
<isif condition="#isDefined(woot)#">
Evaluates if the variable exist and it does. It has an empty string as a value, not null like you might think.
So what happens here then?
<isif condition="#woot EQ null#">
Looking at the compiled version:
context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue(getObject("null"),null))
The context.getFormattedValue(getObject("null"),null) is the important bit here. It tries to retreive the variable called null, it doesnt exist so returns null. The getFormattedValue method then returns an empty string for the null argument (see TemplateExecutionConfig::getFormattedValue). The whole statement then evals to true. Not because woot is null, but because you are comparing it to a variable that doesnt exist, so you are inadvertently evaluating two empty strings. This behaviour is consistent with the EQ operator because it is use to compare strings.
You would get the same result if u would use this statement too.
<isif condition="#woot EQ iDontExistButImAlsoNotNull#"> //true
The third statement compares the woot variable to an empty string value, which returns true.
<isif condition="#woot EQ ''#">
Compiled version:
context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue("",null))
So the real problem is that woot doesn't have the literal value null. See the following code:
<isset name="foo" value="#IDontExitPrettySureAboutThat#" scope="request">
<%
Object foo = getPipelineDictionary().get("foo");
out.print("foo is null? ");
out.print(foo == null);
//prints : foo is null? true
%>
<isif condition="#isDefined(foo)#">
<h1>foo1</h1> //is never printed
</isif>
I'm abusing the fact that IDontExitPrettySureAboutThat doesn't exist to set a null value to foo. isDefined then starts to work like you would expect. That is until someone initializes my variable to something other than null.
I wouldn't advocate that you use this method, however. I think the best advice is not to use null to represent a missing value or invalid state.
This thread goes into some details on this topic.

Related

Weird behavior with Maps(A nullable expression can't be used as a condition)

Map<String,bool> map= { "key1":true, "key2":false };
/*
* Flags following compilation error:
* A nullable expression can't be used as a condition.
* Try checking that the value isn't 'null' before using it as a condition.
*/
if(map["key1"]) {
//do sth
}
/*So I try checking value isn't null as specified in error
*Still flags same compilation error
*/
if(map!=null && map["key1"]) {
//do sth
}
//This works
if(map["key1"] == true) {
//do sth
}
}
Based on the following snippet, may I know why both the 1st and 2nd if blocks fail but not the 3rd?
You misunderstood the error message.
A nullable expression can't be used as a condition.
means that you can't do:
bool? condition;
if (condition) {
...
}
Map<K, V>'s operator[] returns a V?. It returns a nullable type as a way of indicating failure when the key isn't found, and you need to check that the returned value isn't null, not that map itself is not null. For example:
if (map["key"] ?? false) {
...
}
Your third approach (which checks == true) works because it will perform a null == true equality check if the lookup returns null. However, you should prefer using ?? false since it conveys the intent better, and equality checks against true or false are usually a code smell.
The [] operator on Map can return null which makes it nullable which is explained in details here: https://dart.dev/null-safety/understanding-null-safety#the-map-index-operator-is-nullable
So your first example is invalid since null is not a bool. So you cannot directly use the value from the [] operator for a Map.
Your second example is invalid for the same reason since map["key1"] is bool?.
Third example works since null == true is always false. So it is fully valid to make a comparison which involves something which can be null.

Cannot call `JSON.parse` with `localStorage.getItem(...)`

Just added Flow types to a project I'm working on and progressively adding types until I got to this error:
Cannot call JSON.parse with localStorage.getItem(...) bound to text because null or undefined [1] is incompatible with
string [2]
This comes from a expression:
const myVar = JSON.parse(localStorage.getItem('itemName'))
I understand why I get this error (except maybe the "bound to text" part), but couldn't find a way around it. I'd appreciate any help here!
So, the function localStorage.getItem can return null values and flow wants you to tackle them before parsing it. As JSON.parse only takes a string, you can do the following:
localStorage.getItem("key") || '{}'
So, if it returns null. The empty object string is chosen, which JSON.parse can parse into an empty object.
Prefer using 'null' than '{}' as it parses to empty object
JSON.parse(localStorage.getItem("key") || 'null') // null
JSON.parse(localStorage.getItem("key") || '{}') // {} - empty object

What is the '<>' asp operator?

Simple question. I tried searching, by googling for less than and greater than signs doesn't return great results.
My guess is that <> is basically equivalent to not equals. So, the below expression would be false if x is null or an empty string, and true otherwise?
if x <> ""
This would also return True if a value is contained in the entity listed. This is commonly used to look for quesrystring or form elements that may or may not have been supplied:
If Request("someFieldName") <> "" Then
' Field was provided and has a value, so use the field value
Else
' Field was either empty or not provided, in which case use something else
End If
Hope this helps.
So, the below expression would be false if x is null or an empty string, and true otherwise?
Not exactly. There are few function to verify value:
IsNull(expression)
IsNull returns True if expression is Null, that is, it contains no
valid data; otherwise, IsNull returns False. If expression consists of
more than one variable, Null in any constituent variable causes True
to be returned for the entire expression.
The Null value indicates that the variable contains no valid data.
Null is not the same as Empty, which indicates that a variable has not
yet been initialized. It is also not the same as a zero-length string
(""), which is sometimes referred to as a null string.
IsEmpty(expression)
The expression argument can be any expression. However, because
IsEmpty is used to determine if individual variables are initialized,
the expression argument is most often a single variable name.
IsEmpty returns True if the variable is uninitialized, or is
explicitly set to Empty; otherwise, it returns False. False is always
returned if expression contains more than one variable.
Other good function
VarType(varname)
Returns a value indicating the subtype of a variable.
Use Windows Script 5.6 Documentation from http://www.microsoft.com/en-us/download/details.aspx?id=2764

How do I initialize a variable as null in R5RS?

While working on a project in Dr. Scheme, I initialized a variable as null as follows:
(define var null)
How can I do this in R5RS?
In Scheme, the conventional placeholder for "invalid" is #f, the false object. You can test for it using not.
(There is a null? procedure in Scheme that checks whether the object is the empty list, (). However, that should only be used for list contexts, and not as an "invalid" placeholder. Note that not only returns true for #f, and null? only returns true for (); be careful not to mix the two up.)

How do I check if System::Collections:ArrayList is empty / nullptr / null?

I'd like to know how in C++/CLI it is possible to check whether an ArrayList is existent.
System::Collections::ArrayList %queue_tx
I tried if ( nullptr != queue_tx ) { queue_tx.Add(msg); } but that didn't work. I'm passing queue_tx as a parameter to a function and there's supposed to be the possibility of this parameter not being set (or being set to nullptr).
The compiler throws '!=' : no conversion from 'System::Collections::ArrayList' to 'nullptr'.
How do I do this?
% defines a reference variable this is why it cannot be null
if you would have declared the ArrayList like this:
System::Collections::ArrayList^ queue_tx
then your nullptr check would be possible and have a meaning
otherwise just use the queue_tx.Count() to check if the collection is empty
I would recommend going over:
the difference between reference and pointer variables
When to use a Reference VS Pointers
It is quite impossible for a T% to be null.

Resources