Why do I have to store the result of a function in a variable? - kotlin

Is it because some functions will change the object and some don't so you have to store the returned value in a variable? I'm sure there's a better way to ask the question, but I hope that makes sense.
Example case: Why doesn't thisString stay capitalized? What happens to the output of the toUpperCase() function when I call it on thisString? Is there a name for this behavior?
var thisString: String = "this string"
var thatString: String = "that string"
thisString.toUpperCase()
thatString = thatString.toUpperCase()
println(thisString)
println(thatString)
which prints:
this string
THAT STRING

By convention if a function starts with the word to or a past participle, it always returns a new object and does not mutate the object it's called on. But that's not exclusively true. Functions that begin with a verb may or may not mutate the object, so you have to check the documentation to know for sure.
A mutable object might still have functions that return new objects. You have to check the documentation for the function you call.
For a function that returns a new object, if you don't do anything with the returned result or store it in a variable, it is lost to the garbage collector and you can never retrieve it.
String is an immutable class, so none of the functions you call on it will ever modify the original object. Immutable classes are generally less error-prone to work with because you can't accidentally modify an instance that's still being used somewhere else.
All the primitives are also immutable. If all the properties of a class are read-only vals and all the class types they reference are also immutable classes, then the class is immutable.
If you want an mutable alternative to String, you can use StringBuilder, StringBuffer, CharArray, or MutableList<Char>, depending on your needs. They all have different pros and cons.

Why doesn't thisString stay capitalized?
Because that's how the function was coded (emphasis mine):
"Returns a copy of this string converted to upper case using the rules of the default locale."
What happens to the output of the toUpperCase() function when I call it on thisString?
Nothing. If you don't assign it to a variable (save a reference to it) it's discarded.
Is there a name for this behavior?
AFAIK, this is simply "ignoring the return value".
Hope that helps.

Related

Passing an rvalue as a ByRef parameter to VB6?

Background: I've got a set of VB6 DLLs that share a common "interface". Whichever version is installed locally has members of this interface invoked via COM interop (from VB.Net code, which I suspect might matter). I noticed today that one of the invocations passes [what I understand to be] an rvalue (hereinafter "an rvalue") to a VB6 function that does not have that particular parameter defined as ByVal.
Example Code:
VB6:
Public Function VB6Function(input As String) As String
' Do interesting things with input
End Function
VB.Net:
' get an instance of the VB6 class and pass our trimmed localString to it
result = vb6Instance.VB6Function(localString.Trim())
' Do interesting things with localString
I have not yet noticed an instance of the VB6 code changing the value of input, but I also haven't done an exhaustive search of the different DLL implementations (there are several hundred).
What would happen if VB6Function did change the value of input when input is "an rvalue"? For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
What would happen if VB6Function did change the value of input when input is "an rvalue"?
Nothing. Or rather, nothing interesting.
When the called function changes the value of its argument, it makes no difference for the insides of that function whether the argument was provided byval or byref. All that matters is that there is a variable of certain type, thus, it can be acted upon.
For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
Why would it error out? The passed argument as correct type (string), that is all that matters.
There is no notion of an rvalue in VB.
When you pass what you would call an rvalue to a method accepting something by reference, the compiler automatically passes the reference to a temporary location where the rvalue actually resides. The method gets its value byref, the caller does not care about pointers.
localString.Trim() allocates and returns a string. It has an address and can be passed around. Your code does not explicitly capture that address, but the compiler has no problem passing it to VB6Function byref. If VB6Function changes the value, it changes what that temporary location points to, which has no observable difference because it's going to be destroyed after the call either way.
As for why some people may have preferred receiving strings byref in VBA, it's specifically to avoid copying the entire string each time when calling the function. In VB.NET it's not a problem because strings there are immutable and therefore can be passed byval without copying, but in VBA that is not the case, so a byval string needs to be cloned for the purpose of the call. People avoided that by specifying byref, even though that technically gave them the power to mess with the passed variable.

Determine whether a String is a compile-time constant

Given a reference to any String, is it possible to programmatically determine whether this is a reference to a compile time constant?
Or if it's not, then whether it's stored in the intern pool without doing s.intern() == s?
isConst("foo") -> true
isConst("foo" + "bar") -> true // 2 literals, 1 compile time string
isConst(SomeClass.SOME_CONST_STRING) -> true
isConst(readFromFile()) -> false
isConst(readFromFile().intern()) -> false // true would be acceptable too
(context for comments below: the question originally asked about literals)
To clarify the original question, every string literal is a compile-time constant, but not every compile-time constant has to originate from a string literal.
At runtime, there is no difference between a String object that has been constructed for a compile-time constant or constructed by other means. Strings constructed for compile-time constants are automatically added to a pool, but other strings may be added to the same pool manually via intern(). Since strings are constructed and added lazily, it is even possible to construct and add a string manually, so that compile-time constants with the same value get resolved to that string later-on. This answer exploits this possibility, to detect when the String instance for a compile-time constant is actually resolved.
It’s possible to derive from that answer a method to simply detect whether a string is in the pool or not:
public static boolean isInPool(String s) {
return s == new String(s.toCharArray()).intern();
}
new String(s.toCharArray()) constructs a string with the same contents, which is not in the pool and calling intern() on it must resolve to the same reference as s if s refers to an instance in the pool. Otherwise, intern() may resolve to another existing object or add our string or a newly constructed string and return a reference to it, depending on the implementation, but in either case, the returned reference will be different to s.
Note that this method has the side effect of adding a string to the pool if it wasn’t there before, which will stay there at least to the next garbage collection cycle, perhaps up to the next full gc, depending on the implementation.
The test method might be nice for debugging or satisfying curiosity, but there is no point in ever using it in production code. Application code should not depend on that property and the use case proposed in a comment, enforcing pooled strings in performance critical code, is not a good idea.
Besides the point that the test itself is expensive and counteracting the purpose of performance improvement, the underlying assumption that pooled strings are better than non-pooled is flawed. Not being in the pool doesn’t imply that the application will perform an expensive reconstruction every time it invokes the performance critical code. It may simply hold a reference in a variable or use a HashMap, both approaches way more efficient than calling intern(). In fact, even temporary strings can be the most efficient solution in some cases.

Passing parameters of varying Types

I am using a procedure which involves parameter passing and the parameter being passed is a variable. Because I have explicitly declared the data type of another parameter, I need to do the same for this one. What data type do I declare the parameter as if it is a variable?
Thanks
An example of what you are doing and what Types you are dealing with would have been nice. You can implement Overloading to provide for different parameter Types:
Friend Function FooBar(n As Integer) As Integer
Friend Function FooBar(n As Int64) As Integer
Friend Function FooBar(n As Short) As Integer
The compiler will pick the function which matches the data type being passed. Internally, they might do whatever based on the Type passed, then call another procedure to perform any stuff common to them all.
There is probably a finite number of types you need it to work with. For instance Font, Point and Rectangle probably make no sense. Even Date is dubious because you cannot do stuff to a date in the same way as with an Int or Long. String is also not likely needed because you can always pass it as FooBar(CInt(someString)) provided it does contain a valid integer or whatever.
You can also use a generic to tell the function what you are passing:
Private Function FooBar(Of T)(parm As T) As Integer
' called as:
ziggy = FooBar(Of Int32)(n)
zoey = FooBar(Of String)(str)
This might even be Private Function FooBar(Of T)(parm As T) As T if the function return varies depending on the parameter Type passed. There are many uses for this (one of which is to avoid passing a param as Object), but as a general purpose way of passing any type you want it is not a good idea: internally you will likely have to have a big If/Else to handle the different types their own way.
Turning off Option Strict is never advisable since all sorts of unwanted type conversions can take place.
In VB.NET, you can use Object as the type but with Option Strict Off. You can pass any kind of parameter in that case.
for more information, refer : https://stackoverflow.com/a/2890023/3660930

Cancelling MATLAB object construction without exceptions?

In a MATLAB class I am writing, if the constructor is given 0 arguments, the user is asked to provide a file using uigetfile. If the user cancels the prompt, uigetfile returns 0. In that case it makes no sense to make the object. Is there some way of cancelling the object construction without throwing an exception? If I do an early return I get a malformed object that cannot be used. Here is what the code looks like:
classdef MyClass
methods
function self = MyClass(filename)
if nargin == 0
filename = uigetfile;
if filename == 0
%cancel construction here
return; %I still get a MyClass object with self.filename == []
end
end
self.filename = filename;
end
end
properties
filename;
end
end
However I am unsure if using uigetfile in the constructor is the right thing to do. Maybe it should be the resposibility of another part of my code.
In modern Matlab objects, I don't think it's possible to get out of the constructor without either returning a constructed object or throwing an error. (In the old style classes, the constructor was actually allowed to return whatever it wanted, including objects or primitives of other types, and oh man could that turn in to a mess.) When a constructor is called, the output argument is already intialized with an object with the default property values, so when you call return there, it just skips the rest of initialization and returns the object. If you try to replace out with something besides a MyClass object, that's an error.
Just reorganize the control flow to pull the GUI code out of the constructor, like you're speculating on at the end. Mixing it in to the constructor, especially conditionally, can cause problems. In particular, Matlab expects the zero-arg constructor to always return a scalar object with some sort of default values, because the zero-arg gets called implicitly when filling in elements during array expansion and so on. It's basically used as a prototype.

ComBSTR assignment

I'm confused about COM string assignments. Which of the following string assignment is correct. Why?
CComBSTR str;
.
.
Obj->str = L"" //Option1
OR should it be
Obj->str = CComBSTR(L"") //Option2
What is the reason
A real BSTR is:
temporarily allocated from the COM heap (via SysAllocString() and family)
a data structure in which the string data is preceded by its length, stored in a 32-bit value.
passed as a pointer to the fifth byte of that data structure, where the string data resides.
See the documentation:
MSDN: BSTR
Most functions which accept a BSTR will not crash when passed a BSTR created the simple assignment. This leads to confusion as people observe what seems to be working code from which they infer that a BSTR can be initialized just like any WCHAR *. That inference is incorrect.
Only real BSTRs can be passed to OLE Automation interfaces.
By using the CComBSTR() constructor, which calls SysAllocString(), your code will create a real BSTR. The CComBSTR() destructor will take care of returning the allocated storage to the system via SysFreeString().
If you pass the CComBSTR() to an API which takes ownership, be sure to call the .Detach() method to ensure the BSTR is not freed. BSTRs are not reference counted (unlike COM objects, which are), and therefore an attempt to free a BSTR more than once will crash.
If you use str = CComBSTR(L"") you use the constructor:
CComBSTR( LPCSTR pSrc );
If you use str = L"" you use the assignment operator:
CComBSTR& operator =(LPCSTR pSrc);
They both would initialize the CComBSTR object correctly.
Personally, I'd prefer option 1, because that doesn't require constructing a new CComBSTR object. (Whether their code does so behind the scenes is a different story, of course.)
Option 1 is preferred because it only does one allocation for the string where as option 2 does 2 (not withstanding the creation of a new temporary object for no particular reason). Unlike the bstr_t type in VC++ the ATL one does not do referenced counted strings so it will copy the entire string across.