Three dots in Swift init method - swift

I was looking at some Apple Combine source code and saw a Publisher name MergeMany with an init method defined like this:
public init(_ upstream: Upstream...)
What are the three dots ... after the Upstream? The value of Upstream is just another publisher as defined in the Struct definition.
public struct MergeMany<Upstream> : Publisher where Upstream : Publisher {

The three dots mean that it is a variadic function and can take a list of Upstream. This is a function of the Swift Language and not the Combine Framework.
From Sergio Pietri's Blogpost:
Why should we use variadic functions? When you declare this type of function you are adding flexibility to the code. For example: the printf is probably the most notable function that uses this principle. The printf will take N amount of arguments and has many different parameters to format the output it will print.
And from the Swift documentation:
A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name.
The values passed to a variadic parameter are made available within the function’s body as an array of the appropriate type. For example, a variadic parameter with a name of numbers and a type of Double... is made available within the function’s body as a constant array called numbers of type [Double].

Related

Passing an array or a variable number of parameters to format function in scala

In Scala we can use the format method on a string and use format specifiers like example
"The %s costs %s".format(name, price.toString)
I need to define a method that takes a variable number of string parameters. Is there a way i can pass an array, list or a variable number of parameters to format ?.

PL/Python3 with VARIADIC arrays as arguments

I'm using plpython3u to process a result that contains an arbitrary number of columns each of which hold an array (of varying lengths > 0). In python, I'd be expecting to process this data as a multidimensional array but I'm having trouble getting it from Postgres into my function.
The function declaration I am using looks like this:
CREATE OR REPLACE FUNCTION is_set_cover_possible(VARIADIC args numeric[][])
The problem is that when I try
SELECT is_set_cover_possible(ARRAY[1,2],ARRAY[1,2]);
I get:
No function matches the given name and argument types. You might need to add explicit type casts.
If I pass in (ARRAY[1,2]) the function returns a result without failing so it seems postgres can't handle the multidimensional declaration above.
So, if it's actually possible: How do I declare the function so as to receive a list of arrays?
You cannot to do it. Arguments used as variadic arguments cannot be arrays.
Implementation of variadic arguments was at time when this was not possible technically. Now it is possible, but nobody implemented it.

What is the meaning of the : in Swift function signatures and why is there no comma when it seems there should be one?

Here's an example of what I'm talking about: https://developer.apple.com/documentation/foundation/nsmutableorderedset/1410287-insert
The insert function is shown as insert(_:at:)
When it's actually used, the insert function looks more like:
namesArray.insert("John", at: 3)
There's no : after "John" (though I suppose it could be "John":String -- is that what it's there for?), and the , that actually needs to go there is not mentioned in the function signature in the documentation. Am I just supposed to know/assume that the comma goes there when I actually use it? Is this the case for all Swift functions?
Please note that this is not a question about the underscore, _ -- I understand why it's there and what it's for. I'm specifically asking about the reasons for including : and not including , in the function signature.
The convention, frequently seen in documentation, is a concise way of referring to a function, using only the function name and argument labels.
So consider this function declaration:
func insert(_ objects: [Any], at indexes: IndexSet)
This is
a method called insert;
the first parameter name is called objects, this parameter has no argument label (designated with the _) and has a type of [Any]; and
the second parameter name is indexes, its argument label is at and has a type of IndexSet.
So you call it like so:
insert(someObjects, at: someIndex)
When you call it, you don’t care what the parameter names that are used inside that function, but rather just what the argument labels are. So, the convention when referring to that method in documentation is to omit the parameter names and types and just use the function name and the argument labels, but no comma:
insert(_:at:)
Note, you’d never actually use this syntax in your code. This is just a documentation convention employed to distill long function declarations down to something more manageable and concise:
For more information about argument labels and parameter names, see Function Argument Labels and Parameter Names
A : in the function signature always means an input argument to the function. The function signature contains the argument label followed by a :. The _ means there's no argument label, in which case you can omit the : as well when supplying that specific input argument to the function call.
This is exactly what you see with the insert(_:at:) function. You supply two input arguments to it, "John" and 3, but it only needs an argument label for the second input argument, hence you only need one :. It's also important to note that at call time, you separate the input arguments using ,, not :.
Swift functions have a unique way of specifying the signature, which is a carry over pattern from Objective C. There are 3 parts to specifying each input argument to the function signature. The signature for the function you mentioned is as follows:
func insert(_ objects: [Any],
at indexes: IndexSet)
Let's look at the second argument first:
at indicates the argument label, which is how the caller specifies the parameter.
indexes indicates the function's parameter name to the object. This means that in the body of the function, whatever was passed as at: would be referred to as indexes.
IndexSet is the type of the argument.
Part 1 can be something besides a name, too:
if it is not specified, the argument name and parameter label are the same. For example, if the signature were func insert(objects: [Any], indexes: IndexSet), the function would be called as o.insert(objects: ['a','b'], at: [1,2]).
If it is an underscore (_), then the argument has no label for the caller. This allows the caller to use the simpler, intuitive call o.insert(['a','b'], at: [1,2]).
In a signature, the colon separates the name of a parameter from its value. Functions have this anatomy:
func functionName(label1 parameter1: Type1, label2 paramter2: Type2) -> ReturnType {
...
}
where labels are the names seen when calling the function and parameters are the names of the values as used in the body of the function. A label of _ removes the label from the parameter when calling it.
When calling a function, the colon simply separates parameter labels from the values passed to the function. Commas separate different parameters. A parameter with no label requires no colon. The following function would have no colons at all:
func myFunc(_ par1: Int, _ par2: String) {
print(par1, par2)
}
myFunc(3, "what") // 3 "what"

Swift syntax: UnsafeMutablePointers in CGPDFDocument.getVersion

Can anyone explain how I'm supposed to use the method 'getVersion' for CGPDFDocument in Swift?
Apple's documentation gives:
func getVersion(majorVersion: UnsafeMutablePointer<Int32>,
minorVersion: UnsafeMutablePointer<Int32>)
"On return, the values of the majorVersion and minorVersion parameters are set to the major and minor version numbers of the document respectively."
So I supply two variables as arguments of the function, and they get filled with the values on exit? Do they need to point to something in particular before the method is called? Why not just type them as integers, if that's what the returned values are?
You use it like this:
var major: Int32 = 0
var minor: Int32 = 0
document.getVersion(majorVersion: &major, minorVersion: &minor)
print("Version: \(major).\(minor)")
The function expects pointers, but if you pass in plain Int32 variables with the & operator, the Swift compiler is smart enough to call the function with pointers to the variables. This is documented in Using Swift with Cocoa and Objective-C: Interacting with C APIs.
The main reason the function works like this is probably that it's a very old C function that has been imported into Swift. C doesn't support tuples as return values; using pointers as in-out parameters is a way to have the function return more than one value. Arguably, it would have been a better design to define a custom struct for the return type so that the function could return the two values in a single type, but the original developers of this function apparently didn't think it was necessary — perhaps unsuprisingly, because this pattern is very common in C.

Changes in terminology for Swift function parameter labels

Swift provides the ability to give both an internal and external name/label for parameters of functions. But lately Apple seems to have resorted to only saying "Argument" and "Parameter" names/labels and dropped the use of internal/external to describe these things.
In the Swift documents, and WWDC videos, there are a few unclear efforts to describe the difference between a function's parameters and arguments, without referring to these as the outward facing or internal, such as:
Each function parameter has both an argument label and a parameter
name. The argument label is used when calling the function; each
argument is written in the function call with its argument label
before it. The parameter name is used in the implementation of the
function. By default, parameters use their parameter name as their
argument label.
Imagine a jump() function.
Internally, the names of "when" and "height" might be different, and these are the internal names. External and internal don't seem to be at all confusing, other than the ordering in the Function Definition and then Declaration:
func jump(_ who: String, whenToJump when: Float, howHigh height: Int){
// wait for whenToJump
// adjust who.y by howHigh
)
Which of these is a parameter, in the sense Apple is referring to them, and which is an argument?
Everything is described in detail in the section
Function Argument Labels and Parameter Names
in The Swift Programming Language (Swift 3)
Briefly, the differences between Swift 2 and Swift 3 are
"External name" (Swift 2) is now "Function Argument Label" (Swift 3)
"Internal name" (Swift 2) is now "Parameter Name" (Swift 3)
In (Swift 2) the first parameter is _ name (internal, but no external) by default
In (Swift 3) the first parameter is name name (function argument label and parameter name) by default.