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.
Related
I've been looking at the compiled version of some code snippets to dig into how my code is represented at runtime.
I'm not surprised to see that safe coerce and unsafe coerce are the same in the compiled JavaScript. There's a dictionary passed into safe coerce that's unused/undefined in the code I've looked at so far.
It seems like if the runtime representation of two types is the same, then there shouldn't be any runtime overhead for having/using such a type. This isn't true and I'm curious to understand why.
Coercing two types requires a function call at runtime. What I'm not understanding is that this function call appears to do nothing.
exports.unsafeCoerce = function (x) {
return x;
};
If I declare a newtype
newtype Selection = Selection Int
I see something similar in JavaScript:
var Selection = function (x) {
return x;
};
Which means I might see something like this in JavaScript:
return Selection(Data_Int.pow(2)(Safe_Coerce.coerce()(n) - 1 | 0));
which should be identical to this:
return Data_Int.pow(2)(n - 1 | 0);
In this case, both Selection and coerce only ever return what they're given. Once the type checking has been done, I'm not sure what purpose they continue to serve.
The reason the code is generated like it is, and not in a more efficient form like you suggest, is because the purs compiler has only a simplistic optimiser.
Why unsafeCoerce is defined as it is is because it is a PureScript function and must match the runtime representation of PureScript functions. Same goes for Selection.
Constraints are represented as functions on dictionaries. Some time ago there was an optimisation added such that empty dictionaries do not have to be constructed as empty JavaScript objects, and instead can be represented by undefined. That is why there is no argument passed to coerce.
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?”
Motivation is trying to use a callback with a C API where I pass in anything I want through a void pointer.
So suppose I have an x: UnsafePointer<Void>. I know what it really is, so I want to convert the pointer appropriately. What is the difference between using unsafeBitCast, or just applying UnsafePointer to x? In other words
Is
let y = unsafeBitCast(x, to: UnsafePointer<MyStruct>.self)
different from
let z = UnsafePointer<MyStruct>(x)
in some way?
unsafeBitCast is an unsafe conversion between any two Swift types of the same size. That is, you can write unsafeBitCast(x, UnsafePointer<MyStruct>.self), but you could have also written unsafeBitCast(x, MyClass.self) or unsafeBitCast(x, Int.self). This is generally very unsafe, because Swift doesn't guarantee much about the memory layout of its types. Using UnsafePointer or Unmanaged might be better options in your case.
The "coercion" UnsafePointer<MyStruct>(x) isn't really a special language feature, it's just an UnsafePointer initializer which takes another UnsafePointer. Its effect is to reinterpret the value at the same memory address as a different type, similar to casting between pointer types in C (or static_casting in C++). The conversion between the two Swift types (the two variants of UnsafePointer) is safe, but of course they are still UnsafePointers, so you must be certain you're accessing the memory correctly; you are still responsible for allocation and deallocation.
All is in the subject, really.
I fail to see what the difference in behavior is between those two methods for x:
// first version
Method m(ByRef x As whatever)
{
// play with x
}
// second version
Method m(Output x As whatever)
{
// play with x
}
There must be some reason why both those modifiers exist, however my "mastery" (uhm) of the language is not enough to understand the difference. I have tried and read the documentation, search it etc, to no avail so far.
So, what is the difference between those two argument modifiers?
Well those are just "prettifiers", they don't do much in terms of actual language behaviour, and only used to provide documentation. Idea is that arguments documented as ByRef provide both input and output, for example you can pass an array to be sorted, and Output arguments only provide output, for example list of errors. Output modifier was introduced later, and a lot of system code still use ByRef for both use cases.
If argument is actually passed by reference is only determined by method caller, and keyword doesn't really matter. You will call your method as ..m(.parameter) to pass variable by reference, and ..m(parameter) to pass variable by value.
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