Unable to understand extension function in Kotlin Android? - extension-function

I am not able to understand extension function and use it in my project. Can anyone guide me here please?

From the docs - “Kotlin provides the ability to extend a class with new functionality without having to inherit from the class or use design patterns such as Decorator. This is done via special declarations called extensions.”
To understand this in an easy way, let’s consider the below example:
First things first.
Write 10 and then put a dot(.) after it and then try to write addTwoNumbers().
You’ll be getting errors at this stage as there is no property named addTwoNumbers() for an integer.
Now, write this method:
fun Int.addTwoNumbers(y: Int): Int = this.plus(y) //“this” corresponds to the integer number. (In this example, “this” refers to 10).
Notice how we are using Int.addTwoNumbers().
Let’s try to follow the same thing again:
Write 10.
Put a dot(.) after it.
Try to write addTwoNumbers().
And this time you’ll notice, it’s appearing as if this is the property of integer.
Check the below code:
fun main() {
val sum = 10.addTwoNumbers(20) //here “this” will be assigned “10” and “y” will be assigned “20”
println("sum: $sum")
}
This will print sum: 30 in the console.
This phenomena is known as “Extension Function”.

Related

Kotlin Bundle.putString not explicitly adding "String" but instead is "String?"

val args = Bundle()
args.putString("type", details.type)
navigator.navigate(context!!, findNavController(), Destination.TYPE, args)
I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...
val type: String = arguments.getString("type")
The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?
It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.
It's a matter of knowledge that is available in the receiving Fragment.
The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).
Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.
There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.
I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.
val type: String = arguments!!.getString("type")!!
The code above will crash if either:
a) arguments weren't set, or
b) String with type wasn't put in the arguments Bundle.
You are right, that is a : null ability issue.
First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else
To read the string safely you can use:
val type: String = arguments?.getString("type").orEmpty()
The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.
The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.
If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.
isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.

How to import keys and values into variables from a map?

I need to export the keys and values from map in Dart. In PHP I use for that purpose function extract():
$array=array('one'=>1,'two'=>2,'three'=>3);
extract($array);
But I don't know, how to do the same thing in Dart. Is there any special function or construct for it? Or how can I reach the same result with forEach()? Is there anybody, who could help me?
Update 1: My target is from the map like this, but much complicated (example taken from Dart up and running):
var gifts = {
// Keys Values
'first' : 'partridge',
'second' : 'turtledoves',
'fifth' : 'golden rings'
};
in which I want to rewrite the result by any simple function or forEach() loop:
// something like gifts.forEach()? but how?
into variables:
assert(first=='partridge');
assert(second=='turtledoves');
assert(fifth=='golden rings');
//wow, rewritten! The code can continue and use just the variables:
querySelector('#animal').text=first;
Dart is a statically declared language. You cannot create new variable names at runtime, from a map or in any other way.
In order to refer to a variable, it must already be declared. That means that even if you could introduce new variables, you could not have any references to it in your existing code.
If the variables are already declared, and you just want to assign the values to them, you can use the mirror system, but I wouldn't recommend that. It is much simpler to just access the values directly in the map.

How do I pass an enumerated function argument in Julia?

I'm a C and Matlab programmer moving to Julia, and I'm trying to understand how function options should look when passed in.
Sometimes, a function provides different functionality based on an argument passed in with a limited number of different options. In C, it could look something like this:
enum Options{
OPTION_1,
OPTION_2
};
// Other arguments omitted
void foo(..., enum Options option){
switch(option){
case OPTION_1:
// Do something
break;
case OPTION_2:
// Do something else
break;
}
}
In Julia, I am not sure how to structure this. My first attempt used a hierarchy of abstract types, and then a function that accepts a singleton type to make the decision. See the following code:
abstract Options
abstract Option_1 <: Options
abstract Option_2 <: Options
function foo{T<:Options}(..., ::Type{T})
if isa(Option_1, Type{T}
//Do something
elseif isa(Option_2, Type{T})
//Do something else
end
end
However, this seems like a very strange way to approach the problem; creating types just to control function input feels awfully strange.
Also, to clarify, I don't think that this is a solution solvable by general parametric methods in Julia. I am looking for the user to be able to specify a flag (such as run version 1 or version 2), not have different functionality based on input type.
Thanks for the help!
I think parametric methods are actually exactly what you are looking for.
abstract Option_1
abstract Option_2
foo{T<:Options_1}(...) = do_something()
foo{T<:Options_2}(...) = do_something_else()
if there is common code between the two implementations then factor it out into another function and use it in both. Julia doesn't have enums but it does have ways to accomplish the same thing and parametric methods are a perfectly valid way to do so.
If you analyse your question, what you are doing is choosing one of two different functionalities via an argument. Thus you actually have two different functions mixed up inside a single function, and you can (and should) split the two different functionalities out into two different functions.
Once you have done this, it's a short step to realise that the way you decide which function to call is probably (or, at least, often) related to the type of an object. But maybe if you give some more details of your actual use case, we can suggest other alternatives. For example, it might just be a boolean variable that turns on or off a certain type of behaviour.
Note that in Julia v0.4 (the current stable version), you can also use #enum to create enums similar to those available in C: see the NEWS.md file.

Error with sequence argument when using QtConcurrent map

I'm trying to use QtConcurrent::map to run this function
//This function is used through QtConcurrent::map to create images from a QString path
void MainWindow::createQImage(QString* path) {
//create an image from the given path
QImage* t = new QImage(*path);
imageList->append(t);
}
on this container/sequence (declared in the mainwindow header and initialized in the mainwindow constructor)
QList<QImage *> *imageList = new QList<QImage *>;
Here's the code I'm trying to run
QFutureWatcher<void> futureWatcher;
futureWatcher.setFuture(QtConcurrent::map(imageList, &MainWindow::createQImage));
and here are the errors I'm getting:
request for member 'begin' in 'sequence', which is of non-class type 'QList<QImage*>*'
request for member 'end' in 'sequence', which is of non-class type 'QList<QImage*>*'
I need the "createQImage" function to be run for every element in "imageList," which can reach into the thousands. I believe the problem to be with the first parameter to the map function. And from what I've read, it may have to do with compatibility. There isn't much sample code online that I was able to relate to. I'm new to Qt and not the most experienced of programmers but I'd appreciate some help and feedback.
Alternatively, is there better way to do this using QtConcurrent?
Thanks in advance!
QtConcurrent::map wants a sequence as its first argument. You passed it a pointer to a sequence.
If you do
futureWatcher.setFuture(QtConcurrent::map(*imageList, &MainWindow::createQImage));
it should be happy.
Note that the compiler was reasonably clear about what the problem was. Take the time to read the errors carefully, they're usually not as cryptic as they perhaps at first seem. In this case it was telling you that the argument you passed was not of a class type. A quick look at the argument type at the end of the error reveals that it is a pointer.
QList, QImage, QString are Copy-On-Write types (see other Qt implicitly shared types), so you shouldn't use pointers to these types because they are basically already smart pointers.
And if you remove all pointers from your code, it should also fix the main problem.

VBScipt: Call builtin functions shadowed by global variables

VBScript on ASP Classic contains an "int" function. (It rounds numbers towards -∞.) Suppose that some excessively "clever" coder has created a global variable named "int". Is there any way to get at the original function? I've tried all manner of workarounds with scoping and dodgy execs, but no dice. I suspect that it is impossible, but I'm hoping that someone will know more about it than I do.
EDIT: Thanks for the responses. Since y'all asked, the global variable, called "Int" (though unfortunately, vbscript is not case-sensitive), is a factory for a class similar to Java's Integer. The default property is essentially a one-arg constructor; i.e. "Int(42)" yields a new IntClass object holding 42. The default property of IntClass in turn simply returns the raw number.
The creator was trying to work around the lack of proper namespaces and static methods, and the solution's actually pretty seamless. Pass in an IntClass where an int is expected and it will automatically trigger the default property. I'm trying to patch the last remaining seam: that external code calling "int" will not round properly (because the constructor uses CLng).
Not that I know of, getref only works on custom functions not on build-ins. I would suggest renaming the custom'int' function and update all references to this custom ones. You can use the search function visual studio (express) or any other tool of your liking for this. Shouldn't be to much work.
I didn't think reserved words would be allowed for function names or variables.
Duncanson's right. Do the pain and rename int. Chances are there are worse things going on than just this.
(why would someone make a global variable named int... that's going to take some thinking)
Or you can use CInt instead on Int
response.write trim(cint(3.14)) + "<br>"
Wrong!!
See NobodyMan comments

Resources