Swift: Why to functions have parameters and return value types? - swift

I'm filling a few gaps in my existing Swift programming language skills before moving onto the more advanced features.
I have checked Apples... "Swift Programming Language" guide and Google search shows lots of information about the rules around using the parameters, but I am looking for the overall Why , not the How...
Question:
Why is there a need to have parameters and return value types for functions in Swift?
(I am not asking about the parameter names etc., but a higher level (general) question on 'Why')
I have made a number of programs using simple C-Style functions in Swift, without a need for parameters or return values which works fine as I know what the functions should be doing for me.
Simple e.g.
func printName() {
print("John")
}
However, there are 'exceptions' like some in-built Swift functions.
E.g....
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return colors.count
}
etc. for table view or collection view usage .
So the only reason I see for using parameters + return values (type) in functions is to ensure only specific type of data is inputted and outputted.
In other words, its a way to avoid unexpected outcomes. So acting almost like a Switch statement, where if I have a specific condition is met -- a specific output will occur... (in functions... "an action").
Am I correct in this understanding, in trying to understand why / where one needs to use parameters & / or return values types with Functions? Or are there other practical reasons? If so can you provide an example?
Many thanks in advance!!!!

If you don't use parameters, you're tied to use what's visible in your scope.
if your function is inside a ViewController, all properties inside that VC, also global scope variables (horrible)
if your function is in global scope, you can only use global scope symbols (horrible, again)
You really do want to pass in things using parameters. This way you can:
auto check types (compiles is doing for you)
check for optionality
check value ranges
test your functions using Unit Tests. if you use global symbols, you're tied to that symbols, can't change them
less maintenance: changes outside your function doesn't affect you
Also, having a clear return type helps other developers and your future-self to understand what's returning from that function: a tuple? An optional array? A number? Also, having defined output types helps you with testing your functions.
Using only global variables & procedures (chunks of code to process those global vars) could work on a small scale. That's the old approach use with languages like FORTRAN, BASIC, COBOL... The moment your project grows, you need to isolate one part of your code from the other. For that:
use functions & a functional approach
use OOP

Let's imagine a sum function
func sum(a: Int, b:Int) -> Int {
return a + b
}
What happen if we remove the parameter types
func sum(a, b) -> Int {
return a + b // what?
}
Of course this is not allowed by the compiler but let's try to imagine.
Now a and b could be anything (like a String and a UIImage). How could we write the code to sum 2 things and get an Int?
Another test, let's remove the return type
func sum(a:Int, b:Int) -> ??? {
return a + b
}
Now let's try to invoke our crazy function
let tot: Int = sum(1, b: 2)
but since sum could return any kind of value how can we put the result into an Int constant?

Related

Do any programming languages provide the ability to name the return value of a function?

Quite commonly while programming I find it necessary to document the value that a function returns. In Java/Scala world, you often use comments above the function to do this.
However, this can stand out in contrast to the first-class documentation that function parameters get in all languages. For example:
def exponent(base: Int, power: Int): Int
Here we have the signature for a method that raises base to the power power and returns... probably the result of that computation? I know for certain it returns an Int, and it seems quite reasonable to infer that the return value is indeed the result of calculating base ^ power, but in many functions I've written and read it is not possible to infer the return value's semantic meaning quite so easily and you need to study the documentation and/or actually use the method to find out.
Which leads me to wonder, do any languages provide support for optionally declaring a semantic name for the return value?
def exponent(base: Int, power: Int): Int(exitCode)
A hah! Turns out this function actually returns an indication of whether the operation succeeded or failed! Look it is so clear right there in the method signature! My IDE could also intelligently create a variable with the same name when I call this method, a la:
// Typing in IntelliJ
exponent(5, 5)<TAB>
// Autocompletes to:
val exitCode = exponent(5, 5)
I'm not under any illusion that this is some sort of ground-breaking idea, but it seems like it could be generally useful, and I'm struck that I have never seen this concept implemented in any programming language.
Can you name any single programming language that does have this kind of semantic naming of return values?
In APL, for instance, the result of a function is declared as a variable. The function declaration in your example could be written like
exitCode ← base exponent power
in APL. However, a function with no side effects should always be named after the result it returns. If the function can fail I would use a value that is never returned on success, for instance -1 in this case.

How exactly does a variadic parameter work?

I'm a Swift newbie and am having a bit of trouble understanding what a variadic parameter is exactly, and why it's useful. I'm currently following along with the online Swift 5.3 guide, and this is the example that was given for this type of parameter.
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
Apparently, the variadic parameter called numbers has a type of Double..., which allows it to be used in the body of the function as a constant array. Why does the function return Double(numbers.count) instead of just numbers.count? And instead of creating a variadic parameter, why not just create a parameter that takes in an array that's outside of the function like this?
func addition(numbers : [Int]) -> Int
{
var total : Int = 0
for number in numbers
{
total += number
}
return total
}
let totalBruhs : [Int] = [4, 5, 6, 7, 8, 69]
addition(numbers: totalBruhs)
Also, why can there only be one variadic parameter per function?
Variadic parameters need (well, not need, but nice) to exist in Swift because they exist in C, and many things in Swift bridge to C. In C, creating a quick array of arbitrary length is not so simple as in Swift.
If you were building Swift from scratch with no backwards compatibility to C, then maybe they'd have been added, and maybe not. (Though I'm betting yes, just because so many Swift developers are used to languages where they exist. But then again, languages like Zig have intentionally gotten rid of variadic parameters, so I don't know. Zig also demonstrates that you don't need variadic parameters to bridge to C, but still, it's kind of nice. And #Rob's comments below are worth reading. He's probably not wrong. Also, his answer is insightful.)
But they're also convenient because you don't need to add the [...], which makes it much nicer when there's just one value. In particular, consider something like print:
func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
Without variadic parameters, you'd need to put [...] in every print call, or you'd need overloads. Variadic doesn't change the world here, but it's kind of nice. It's particularly nice when you think about the ambiguities an overload would create. Say you didn't have variadics and instead had two overloads:
func print(_ items: [Any]) { ... }
func print(_ item: Any) { print([item]) }
That's actually a bit ambiguous, since Array is also a kind of Any. So print([1,2,3]) would print [[1,2,3]]. I'm sure there's some possible work-arounds, but variadics fix that up very nicely.
There can be only one because otherwise there are ambiguous cases.
func f(_ xs: Int..., _ ys: Int...)
What should f(1,2,3) do in this case? What is xs and what is ys?
The function you've shown here doesn't return Double(numbers.count). It converts numbers.count to a Double so it can be divided into another Double. The function returns total / Double(numbers.count).
And instead of creating a variadic parameter, why not just create a parameter that takes in an array that's outside of the function ... ?
I agree with you that it feels intuitive to use arrays for arithmetic functions like “mean”, “sum”, etc.
That having been said, there are situations where the variadic pattern feels quite natural:
There are scenarios where you are writing a function where using an array might not be logical or intuitive at the calling point.
Consider a max function that is supposed to be returning the larger of two values. It doesn’t feel quite right to impose a constraint that the caller must create an array of these values in order to return the larger of two values. You really want to allow a nice, simple syntax:
let result = max(a, b)
But at the same time, as an API developer, there’s also no reason to restrict the max implementation to only allow two parameters. Maybe the caller might want to use three. Or more. As an API developer, we design API’s for naturally calling points for the primary use cases, but provide as much flexibility as we can. So a variadic function parameter is both very natural and very flexible.
There are lots of possible example of this pattern, namely any function that naturally feels like it should take two parameters, but might take more. Consider a union function for two rectangles and you want the bounding rectangle. Again, you don’t want the caller to have to create an array for what might be a simple union of two rectangles.
Another common example would be where you might have a variable number of parameters but might not be dealing with arrays. The classic example would be printf pattern. Or another is where you are interacting with some SQL database and might be binding values to ? placeholders in the SQL or the like (to protect against SQL injection attacks):
let sql = "SELECT book_id, isbn FROM books WHERE title = ? AND author = ?"
let resultSet = db.query(sql, title, author)
Again, in these cases, suggesting that the caller must create an array for this heterogenous collection of values might not feel natural at the calling point.
So, the question isn’t “why would I use variadic parameter where arrays are logical and intuitive?” but rather “why would I force the use of array parameters where it might not be?”

Would this function be allowed in Swift (if it wouldn't crash the compiler)

I got this function, which is a minimised version of an actual use case:
func f (i:Int) -> <T> (x:T) -> T {
return { x in return x }
}
As you see I would like to compute a generic function based on some input.
But as you can see in Xcode or on swiftstub, this function crashes the compiler.
Does anybody know if Swift is supposed to support such definitions?
This no longer crashes the compiler when I try it on 1.2b3. However, it’s not valid syntax.
If you want to return a function where the type is determined up-front at the time f is called, this would do it:
func f<T>(i:Int) -> T -> T {
return { x in return x }
}
// need to tell the compiler what T actually is...
let g = f(1) as Int->Int
g(2) // returns 2
However, Swift does not support the ability to define “generic” closures, i.e. closures where the type is determined not on creation of the closure, but at the point when that closure is actually called. This would require higher-ranked polymorphism, something that isn’t currently available (though maybe in the future, who knows – would be a very nice feature to have). For now, the placeholders need to be fully determined at the call site.
Keep in mind that the "generic" nature of Swift generics is kind of a misnomer. The genericness is just a template notation; all genericness is compiled away at compile time - that is, all generics used in one part of your code are resolved (specified) by the way they are called in another part of your code.
But for that very reason, you can't return a generic function as a result of a function, because there is no way to resolve the generic at compile time.
So, while crashing the compiler is not nice (and Apple would like to know about it), your code should not compile either, and to that extent the compiler is correct to resist.

Is there a way to declare an inline function in Swift?

I'm very new to the Swift language.
I wanted to declare an inline function just like in C++
so my func declaration looks like this:
func MyFunction(param: Int) -> Int {
...
}
and I want to do something like this:
inline func MyFunction(param: Int) -> Int {
...
}
I tried to search on the web but I didn't find anything relevant maybe there is no inline keyword but maybe there is another way to inline the function in Swift.
Swift 1.2 will include the #inline attribute, with never and __always as parameters. For more info, see here.
As stated before, you rarely need to declare a function explicitly as #inline(__always) because Swift is fairly smart as to when to inline a function. Not having a function inlined, however, can be necessary in some code.
Swift-5 added the #inlinable attribute, which helps ensuring that library/framework stuff are inlineable for those that link to your library. Make sure you read up about it, as there may be a couple of gotchas that might make it unusable. It's also only for functions/methods declared public, as it's meant for libraries wanting to expose inline stuff.
All credit to the answer, just summarizing the information from the link.
To make a function inline just add #inline(__always) before the function:
#inline(__always) func myFunction() {
}
However, it's worth considering and learning about the different possibilities. There are three possible ways to inline:
sometimes - will make sure to sometimes inline the function. This is the default behavior, you don't have to do anything! Swift compiler might automatically inline functions as an optimization.
always - will make sure to always inline the function. Achieve this behavior by adding #inline(__always) before the function. Use "if your function is rather small and you would prefer your app ran faster."
never - will make sure to never inline the function. This can be achieved by adding #inline(never) before the function. Use "if your function is quite long and you want to avoid increasing your code segment size."
I came across an issue that i needed to use #inlinable and #usableFromInline attributes that were introduced in Swift 4.2 so i would like to share my experience with you.
Let me get straight to the issue though, Our codebase has a Analytics Facade module that links other modules.
App Target -> Analytics Facade module -> Reporting module X.
Analytics Facade module has a function called report(_ rawReport: EventSerializable) that fire the reporting calls, This function uses an instance from the reporting module X to send the reporting calls for that specific reporting module X.
The thing is, calling that report(_ rawReport: EventSerializable) function many times to send the reporting calls once the users launch the app creates unavoidable overhead that caused a lot of crashes for us.
Moreover it's not an easy task to reproduce these crashes if you are setting the Optimisation level to None on the debug mode. In my case i was able only to reproduce it when i set the Optimisation level to Fastest, Smallest or even higher.
The solution was to use #inlinable and #usableFromInline.
Using #inlinable and #usableFromInline export the body of a function as part of a module's interface, making it available to the optimiser when referenced from other modules.
The #usableFromInline attribute marks an internal declaration as being part of the binary interface of a module, allowing it to be used from #inlinable code without exposing it as part of the module's source interface.
Across module boundaries, runtime generics introduce unavoidable overhead, as reified type metadata must be passed between functions, and various indirect access patterns must be used to manipulate values of generic type. For most applications, this overhead is negligible compared to the actual work performed by the code itself.
A client binary built against this framework can call those generics functions and enjoy a possible performance improvement when built with optimisations enabled, due to the elimination of abstraction overhead.
Sample Code:
#inlinable public func allEqual<T>(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
var iter = seq.makeIterator()
guard let first = iter.next() else { return true }
func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec(&iter)
}
return rec(&iter)
}
More Info - Cross-module inlining and specialization

how to pass n argunment to the method

example
add(int a, int b) Here we pass two argument int a, int b,
can we pass n argument with different data types like int,float,long,
is it possible?
I means i need to write only one method which handles n Arguments.
Yes, it is possible to pass arguments with different data types to Objective-C methods. I assume you're speaking about Objective-C, since the question is tagged iphone.
For example, you could have a method like:
- (void)foo:(int)foo bar:(float)bar baz:(long)baz {
// ...
}
If you are talking about C, you could have a function:
void myfunc(int foo, float bar, long baz) {
// ...
}
If you want to write functions that have variable sized argument lists (so it can take 1 parameter, or 2 parameters, or 3, ...), I suggest you take a look at this blog post which discusses variable argument lists in Objective-C/Cocoa or Apple's technical Q&A on variable argument lists.
- (int)add:(int)number1 to:(int)number2 {
return number1 + number2;
}
call it using [obj add:2 to:4]; where obj is the object receiving the add message.
You may use any type of arguments in the above to achieve what you have in mind. For example:
- (void)add:(int)number1 to:(float)number2 {
//print result here
}
Standard type conversions etc would apply like in any programming language.
If you are talking about totally arbitrary number of arguments, take a look at Variadic functions in Objective C (Google it). Plenty of good tutorials in the first search results page.
Anything is possible, but I am pretty certain it would require some serious hacking to get it to work for variable data types. If you can change the requirements to be a variable number of specific data type, then you should look at an excellent tutorial at "Cocoa with Love" : variable-argument-lists-in-cocoa