Returning empty UDT From a function - vb6

I have written a function that returns a User Defined Type.
How can i return a empty UDT in case of any error from the function?
I tried setting function to 'Nothing',but it is throwing 'Object Required' error.
Thanks in advance.

If at all possible, use a Class/Object instead. Even doing something as simple as turning this type:
Public Type EmpRecord
FName As String
LName As String
HiredDate As Date
End Type
into a class can be done by adding a Class to your project called EmpRecord and including just this in it:
Public FName As String
Public LName As String
Public HiredDate As Date
Then you can return Nothing from a function that gets an error while retrieving the record.

In VB6, a user-defined type is a "value type", while a class is a "reference type". Value types are typically stored on the stack (unless they're a member of a class). Reference types are stored as a pointer on the stack pointing to a place in the heap where the actual instance data is stored.
That means a reference to a class can be Nothing (the pointer is zero), whereas a value type can't.
There are multiple ways to solve your problem:
Add a Boolean member to your user-defined type to indicate success or failure.
Create another "wrapper" UDT like (see below) and return it from your function.
Change your UDT into a class, which can be Nothing (as tcarvin said).
Write the function to return a Boolean and take a ByRef parameter. The results are written to the parameter passed in if the function result is True. (A lot of people don't like this, but it's a common solution you should be aware of.)
Wrapper:
Public Type Wrapper
Success As Boolean
Inner As YourOriginalUDT
End Type
Function with ByRef:
Function Foo(ByRef Result As YourOriginalUDT) As Boolean
...
If Success Then
Foo = True
Result.A = A
Result.B = B
Result.C = C
... etc. ...
End If
End Function

A UDT can't be empty.
You can either use a "dummy" unintialised UDT, or just set all it's members back to the default values.

Related

Method Reference - passing Function to method with Consumer argument

I'm learning about Method References from Java 8 and I have difficulties understanding why does this work?
class Holder {
private String holded;
public Holder(String holded) {
this.holded = holded;
}
public String getHolded() {
return holded;
}
}
private void run() {
Function<Holder, String> getHolded = Holder::getHolded;
consume(Holder::getHolded); //This is correct...
consume(getHolded); //...but this is not
}
private void consume(Consumer<Holder> consumer) {
consumer.accept(null);
}
As you can see in run method - Holder::getHolded returns unbound method reference which you can invoke by passing object of type Holder as an argument. Like this: getHolded.apply(holder)
But why it casts this unbound method reference to Consumer when it is invoked directly as an method argument, and it does not doing it when I'm passing Function explicitly?
Two things here, lambda expressions are poly expressions - they are inferred by the compiler using their context (like generics for example).
When you declare consume(Holder::getHolded);, compiler (under the so-called special void compatibility rule) will infer it to Consumer<Holder>.
And this might not look obvious, but think of a simplified example. It is generally more than ok do call a method and discard it's return type, right? For example:
List<Integer> list = new ArrayList<>();
list.add(1);
Even if list.add(1) returns a boolean, we don't care about it.
Thus your example that works can be simplified to:
consume(x -> {
x.getHolded(); // ignore the result here
return;
});
So these are both possible and valid declarations:
Consumer<Holder> consumer = Holder::getHolded;
Function<Holder, String> function = Holder::getHolded;
But in this case we are explicitly telling what type is Holder::getHolded,, it's not the compiler inferring, thus consume(getHolded); fails, a Consumer != Function after all.
Java 8 introduced 4 important "function shapes" in the package java.util.function.
Consumer -> accepts a method reference (or a lambda expression) that takes one argument but doesn't return anything
Supplier -> accepts a method reference (or a lambda expression) that takes no argument and returns an object.
Function -> accepts a method reference (or a lambda expression) that takes one argument and returns an object.
Predicate -> accepts a method reference (or a lambda expression) that takes one argument and returns a boolean.
Read the Java docs for more detail.
To answer your question on why the first one works but the second one errors out, read following:
The second statement
consume(getHolded);
doesn't work because the type of the argument getHolded is Function<Holder, String> whereas the consume method expects an argument of type Consumer<Holder>. Since there is no parent-child relationship between Function and Consumer, it requires an explicit cast without which the compiler rightly errors out.
The first statement
consume(Holder::getHolded);
works because the method getHolded is declared as public String getHolded() meaning that it doesn't take any argument and returns a String. As per the new void compatibility rule, void types are inferred as the class containing the referenced method. Consider the following statement:
Consumer<Holder> consumer = Holder::getHolded;
This is a valid statement even though the method getHolded doesn't accept any arguments. This is allowed to facilitate inferring void types. Yet another example is the one you have mentioned yourself:
Function<Holder, String> getHolded = Holder::getHolded;
This is also a valid statement where you have said that the function object getHolded is a Function that returns String and accepts a type Holder even though the assigned method reference doesn't take any argument.
Sharing just a summary of the four types of Method References under the hood:
Reference to a static method:
Type::staticMethod ===>>> x -> Type.staticMethod(x)
Reference to an instance method of a particular object:
instance::instanceMethod ===>>> x -> instance.instanceMethod(x)
Reference to an Instance Method of an Arbitrary Object of a Particular Type:
Type::instanceMethod ===>>> x -> x.instanceMethod() OR (x, y) -> x.instanceMethod(y)
Reference to a constructor:
Type::new ===> x -> new Type(x)

HP-UFT / VBscript - Setting an array value through a function with an array index reference

I have an issue with assigning/retrieving correct values to/from an array which is within a class in VBScript. Whenever I try to set the array's value through a stand-alone function, it just does not work and I keep getting the old array values.
Here is an example code:
Class NewClass
Public TestValues
Public Sub Init()
TestValues = array("value0", "value1", "value2")
End Sub
End Class
Class NewFunctions
Public Function GetValue(xRef)
GetValue = xRef(2)
print "Value within Function: " & xRef(2)
End Function
Public Sub SetValue(xRef, xValue)
xRef(2) = xValue
print "Value within Sub: " & xRef(2)
End Sub
End Class
Dim MyClass, MyFunction
Set MyClass = New NewClass
Set MyFunction = New NewFunctions
Now, when I try to set the index 2 of the given array MyClass.TestValues with the SetValue Sub, it claims the new value has been set, but when I then call GetValue for this array or print out the content of the MyClass.TestValues(2) directly, I am still getting the old values:
MyFunction.SetValue MyClass.TestValues, "newvalue2"
It returns: Value within Sub: newvalue2
But when I retrieve the value with GetValue:
MyFunction.GetValue MyClass.TestValues
It returns: Value within Function: value2, which is the old value.
When I, however, set the array directly:
Myclass.TestValues(2) = "newvalue2"
then calling with:
MyFunction.GetValue MyClass.TestValues
gives me correct result: Value within Function: newvalue2
I am not sure whether this is a general VBScript behavior and I am making a mistake in hoping to change array values in this 'dirty' manner or whether this is strictly HP-UFT (Unified Functional Testing) related, since this is where I could observe this.
I am not a profficient VBScripter either so I appreciate any help.
This is a documented behaviour
Argument in a Class
If the parameter is specified as ByRef, the argument is passed by
value if the variable sent as an argument is in a class

How to expose an array of UDTs through a property?

I have a class cDept which has a UDT defined.
public type udtEmp
Name as string
Id as long
end type
I have an array defined:
private m_Emps() as udtEmp
I want to expose the array through a property. I tried the following:
Public Property Get Employees() As udtEmp()
Employees= m_Emps
End Property
So far everything compiles. Now I instantiate the class and try to access the property.
dim myUdt as udtEmp
dim oDept as cDept
set oDept = new cDept
myUdt = oDept.Employees(1) ' -- error
I get an error stating Wrong number of arguments or invalid property assignment.
What am I missing?
(Not tested)
I think your property access is trying to use the '1' as an argument to the property (which has no arguments), thus the 'wrong number' error. Rather than trying to property get the array and then index access the array, will it work to have the property get (or a different one) return the desired array element?
Public Property Get Employees(ndx as long) As udtEmp
Employees= m_Emps(ndx)
End Property

Inconsistent behavior of enum as constrained parameter in generic

Why it is not possible to cast something that extends number to number?
Here is simple example in which I'm trying to pass enum as a generic argument to function.
enum Ev {A, B}
function fun<E extends number>(x: {[ix: number]: any}, e: E)
{
return x[<number>e]
}
// no error here, so I assume is true that `Ev extends number`
fun({0:0}, Ev.A)
It seems a bit inconsistent that some type extends number but I get this error when trying to cast it to number:
Neither type 'E' nor type 'number' is assignable to the other.
Edit: Here is almost the same example but with class instead of number (this compiles without error):
class A {}
function fun<E extends A>(x: {[ix: number]: any}, e: E)
{
return x[<A>e]
}
Primitive types cannot be inherited from, as some have special "abilities" that require a special instance, and creating a new derived object would prevent that ability. For instance, there is no way to call the string constructor for a new custom derived object, so no way to apply it to a user instance. This is why nothing inherits from number, or anything else.
Why it is not possible to cast something that extends number to number?
As Ryan has pointed out in this issue, it seems like a bug in the language; however, take note that this form of constraint is only useful when the return type of the function is the constraint on the type parameter. For example:
function f<T extends number>(input: T) : T { return input; }
var t = f(Ev.A); // t : Ev
An issue with the constraint in the function you provided, is that it doesn't prevent passing in a number value. Since it's not possible to constrain to an enum member, you might as well just define your function with the constraint on the parameter instead:
function fun(x: {[ix: number]: any}, e: number)
{
return x[e];
}
A complaint you had with doing this was that it wasn't self documenting code. I would say it's better to give your function a descriptive name that says its intent rather than relying on generics that offer no constraint benefit beyond a number constraint. Also remember that there's no way to force a developer to write the generic part when calling the function. They can easily write fun({0:0}, Ev.A) instead of fun<Ev>({0:0}, Ev.A).

an IXMLDOMAttribute as return value of a VBScript function

I'm creating XML documents with VBScript and MSXML DOM. In order to structure and simplify my code I'm using classes and thus methods (functions in VBS) too.
Here is a little function that troubles me:
function createAttribute(name, value)
dim doc
Set doc = CreateObject("Msxml2.DOMDocument.4.0")
dim attr
set attr= doc.createNode(2,name,"")
attr.NodeValue=value
createAttribute=attr
end function
The assignment createAttribute=attr, where I'm setting the return value of the function, causes the following error:
Object doesn't support this property or method
As the web resources on XML processing with VBS are rather sparse, I hope some of you can help me to understand whats going on here. Here are my questions:
What object does not support what property or method?
Can i pass objects of any given class as return values of VBS functions?
Can i pass an object of the class IXMLDOMAttribute as a return value to a VBS function?
I think the problem is that attr is an object, so you need to use set to apply the return value. Otherwise, you may simply be returning attr's default property value (if it has one):
set createAttribute = attr
You don't show how you use the return value, so I can't comment on that but it is possibly the source of the error.

Resources