How can I use getopt with command line arguments in Swift 3? - swift

I'm trying to use getopt with command line arguments in Swift 3. I have from Michele Dall'Agata's nice stackoverflow contribution:
let pattern = "abc:"
var buffer = Array( pattern.utf8 ).map { Int8($0) }
When I then use this code:
let option = Int( getopt( CommandLine.argc, CommandLine.arguments, buffer ) )
I get this error:
Cannot convert value of type '[String]' to expected argument type
'UnsafePointer<UnsafeMutablePointer<Int8>?>!'
for CommandLine.arguments, which I am trying to use as argv. Does anyone know the proper syntax for the 2nd argument for getopt? Thanks in advance!

#Hamish already answered the question and explained how to pass CommandLine.unsafeArgv to getopt() in Swift (and why).
Here is a complete self-contained example how a typical getopt
loop can be implemented in Swift 3:
var aFlag = false
var bFlag = false
var cValue: String?
while case let option = getopt(CommandLine.argc, CommandLine.unsafeArgv, "abc:"), option != -1 {
switch UnicodeScalar(CUnsignedChar(option)) {
case "a":
aFlag = true
case "b":
bFlag = true
case "c":
cValue = String(cString: optarg)
default:
fatalError("Unknown option")
}
}
print(aFlag, bFlag, cValue ?? "?")
Remarks:
You can pass a Swift string (here: "abc:") directly to a C
function expecting a (constant) C string, the compiler will automatically
generate a temporary UTF-8 representation.
getopt() return either -1 (if the argument list is exhausted) or an unsigned char converted to an int. Therefore it is safe to
convert the return value to CUnsignedChar (which is UInt8 in Swift).
while is used (abused?) with pattern matching plus an additional
boolean condition to implement the typical C pattern
while ((option = getopt(argc, argv, "abc:")) != -1) { ... }
in Swift.

CommandLine.arguments gives you a friendly Swift [String] of the arguments passed – however you're looking to send the arguments straight back to C. Therefore you can simply use CommandLine.unsafeArgv instead, which will give you the actual raw value of argv passed to your program.
let option = Int( getopt( CommandLine.argc, CommandLine.unsafeArgv, buffer ) )

Related

what is the best way to write this function? [duplicate]

just a short question. In Swift it is possible to solve the following code:
var a: String;
a = "\(3*3)";
The arithmetic operation in the string will be solved. But i can´t figure out, why this following variation doesn´t work.
var a: String;
var b: String;
b = "3*3";
a = "\(b)";
In this case the arithmetic operation in var a will not be resolved. Any ideas why and how i can this get to work. Some things would be much more easier if this would work. Thanks for your answers.
In the second case, you are interpolating a string, not an arithmetic expression. In your example, it's a string you chose at compile time, but in general it might be a string from the user, or loaded from a file or over the web. In other words, at runtime b could contain some arbitrary string. The compiler isn't available at runtime to parse an arbitrary string as arithmetic.
If you want to evaluate an arbitrary string as an arithmetic formula at runtime, you can use NSExpression. Here's a very simple example:
let expn = NSExpression(format:"3+3")
println(expn.expressionValueWithObject(nil, context: nil))
// output: 6
You can also use a third-party library like DDMathParser.
Swift 4.2
let expn = "3+3"
print(expn.expressionValue(with: nil, context: nil))
But I also have a solution thats not the most effective way but could be used in some cases if your sure it's only "y+x" and not longer string.
var yNumber: Int!
var xNumber: Int!
let expn: String? = "3+3"
// Here we take to first value in the expn String.
if let firstNumber = expo?.prefix(1), let myInt = Int(firstNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to yNumber
yNumber = myInt
}
// Here we take the last value in the expn string
if let lastNumber = optionalString?.suffix(1), let myInt = Int(lastNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to xNumber
xNumber = myInt
}
// Now you can take the two numbers and add
print(yNumber + xNumber)
// will print (6)
I can't recommend this but it works in some cases
This won't be solved because this is not an arithmetic operation, this is a string:
"3*3"
the same as this
"String"
Everything you put in " it's a string.
The second example lets you construct a new String value from a mix of constants, variables, literals, and expressions:
"\(3*3)"
this is possible because of string interpolation \()
You inserted a string expression which swing convert and create expected result.
You can try to use evaluatePostfixNotationString method from that class.
The whole project is about recognizing math expression from camera image and calculating it after.

Passing variadic arguments as an array in Swift

Java 5+ allows passing variadic arguments either as an array, or individually. I expected Swift to allow passing variadic arguments as an array as well, but have no luck so far.
Here is a sample program, I tried in a playground. It creates an array of CVarArg and passes it to String(format:...)
let printData: [(format: String, param: [CVarArg])] =
[(format: "This is blank", param: []),
(format: "This is %# %#", param: ["Swift", "language"])
]
for index in 0...1 {
let pdata = printData[index]
print (String(index+1) + " " + String(format: pdata.format, pdata.param))
}
I expected:
1 This is blank
2 This is Swift language
Instead it prints:
1 This is blank
2 This is (
Swift,
language
) (null)
Tried using CVarArg... as a type:
let printData: [(format: String, param: CVarArg...)]
or bridging to CVarArg... :
String(format: pdata.format, pdata.param as CVarArg...)
In both cases I get compilation errors.
Is there a way to change the syntax of the above code to allow interpreting [CVarArg] in the expected way.
I think your problem is that tuples do not support variadic arguments. So
(format: "This is %# %#", param: ["Swift", "language"])
is a tuple of two things: a string and an array and String(format:,_) sees the array as only one object. To solve your immediate problem, use String(format:,arguments:). e.g.
for index in 0...1 {
let pdata = printData[index]
print (String(index+1) + " " + String(format: pdata.format, arguments: pdata.param))
}
Given how easy it is to create a literal array, I'd question the need to use variadic arguments anywhere in Swift.

Idiomatic way to unwrap an integer string input

Sorry if this is a basic question, but I am learning Swift and I don’t understand how to unwrap inputs from readLine().
For example, I would expect this
let n: Int = Int(readLine(strippingNewline: true) ?? -1)
to work, but it doesn’t. Nor does replacing the -1 with a "-1" to match types.
let n: Int = Int(readLine(strippingNewline: true) ?? "-1")
What is the “right” way to do this then? Can someone explain exactly what Swift is doing when it unwraps optionals and uses them as arguments for a constructor like Int?
The whole concept of optionals is a bit foreign to me (a Python programmer); in Python you handle invalid input the “ghetto way”, putting out fires only after they happen:
try:
n = int(input())
except ValueError:
n = None
but I assume the paradigm in Swift is different.
There are two optionals at play here.
First, readLine(strippingNewline: true) is optional. It can return nil if there's no input recieved prior to the End of File (EOF) character being received. It must be unwrapped before being passed into Int()
Secondly, Int() is optional, because the String it was given may not be a valid string representation of a number.
Do not use -1 in Swift to represent "no value". This is called a sentinel value, and it's exactly what optionals are invented to prevent. How do you distinguish between a -1 meaning "no/invalid input", and a -1 meaning "the user's input was -1?
Here is how I would write this code:
guard let userInput = readLine(strippingNewline: true) else {
// If we got to here, readLine(strippingNewLine:) returned nil
fatalError("Received EOF before any input was given")
}
// If we got to here, then userInput is not nil
if let n = Int(userInput) {
// If we got to here, then userInput contained a valid
// String representation of an Int
print("The user entered the Int \(n)")
}
else {
// If we got to here, then userInput did not contain a
// valid String representation of an Int.
print("That is not a valid Int.")
}

How to handle initial nil value for reduce functions

I would like to learn and use more functional programming in Swift. So, I've been trying various things in playground. I don't understand Reduce, though. The basic textbook examples work, but I can't get my head around this problem.
I have an array of strings called "toDoItems". I would like to get the longest string in this array. What is the best practice for handling the initial nil value in such cases? I think this probably happens often. I thought of writing a custom function and use it.
func optionalMax(maxSofar: Int?, newElement: Int) -> Int {
if let definiteMaxSofar = maxSofar {
return max(definiteMaxSofar, newElement)
}
return newElement
}
// Just testing - nums is an array of Ints. Works.
var maxValueOfInts = nums.reduce(0) { optionalMax($0, $1) }
// ERROR: cannot invoke 'reduce' with an argument list of type ‘(nil, (_,_)->_)'
var longestOfStrings = toDoItems.reduce(nil) { optionalMax(count($0), count($1)) }
It might just be that Swift does not automatically infer the type of your initial value. Try making it clear by explicitly declaring it:
var longestOfStrings = toDoItems.reduce(nil as Int?) { optionalMax($0, count($1)) }
By the way notice that I do not count on $0 (your accumulator) since it is not a String but an optional Int Int?
Generally to avoid confusion reading the code later, I explicitly label the accumulator as a and the element coming in from the serie as x:
var longestOfStrings = toDoItems.reduce(nil as Int?) { a, x in optionalMax(a, count(x)) }
This way should be clearer than $0 and $1 in code when the accumulator or the single element are used.
Hope this helps
Initialise it with an empty string "" rather than nil. Or you could even initialise it with the first element of the array, but an empty string seems better.
Second go at this after writing some wrong code, this will return the longest string if you are happy with an empty string being returned for an empty array:
toDoItems.reduce("") { count($0) > count($1) ? $0 : $1 }
Or if you want nil, use
toDoItems.reduce(nil as String?) { count($0!) > count($1) ? $0 : $1 }
The problem is that the compiler cannot infer the types you are using for your seed and accumulator closure if you seed with nil, and you also need to get the optional type correct when using the optional string as $0.

swift, optional unwrapping, reversing if condition

Let's say I have function which returns optional. nil if error and value if success:
func foo() -> Bar? { ... }
I can use following code to work with this function:
let fooResultOpt = foo()
if let fooResult = fooResultOpt {
// continue correct operations here
} else {
// handle error
}
However there are few problems with this approach for any non-trivial code:
Error handling performed in the end and it's easy to miss something. It's much better, when error handling code follows function call.
Correct operations code is indented by one level. If we have another function to call, we have to indent one more time.
With C one usually could write something like this:
Bar *fooResult = foo();
if (fooResult == null) {
// handle error and return
}
// continue correct operations here
I found two ways to achieve similar code style with Swift, but I don't like either.
let fooResultOpt = foo()
if fooResult == nil {
// handle error and return
}
// use fooResultOpt! from here
let fooResult = fooResultOpt! // or define another variable
If I'll write "!" everywhere, it just looks bad for my taste. I could introduce another variable, but that doesn't look good either. Ideally I would like to see the following:
if !let fooResult = foo() {
// handle error and return
}
// fooResult has Bar type and can be used in the top level
Did I miss something in the specification or is there some another way to write good looking Swift code?
Your assumptions are correct—there isn't a "negated if-let" syntax in Swift.
I suspect one reason for that might be grammar integrity. Throughout Swift (and commonly in other C-inspired languages), if you have a statement that can bind local symbols (i.e. name new variables and give them values) and that can have a block body (e.g. if, while, for), those bindings are scoped to said block. Letting a block statement bind symbols to its enclosing scope instead would be inconsistent.
It's still a reasonable thing to think about, though — I'd recommend filing a bug and seeing what Apple does about it.
This is what pattern matching is all about, and is the tool meant for this job:
let x: String? = "Yes"
switch x {
case .Some(let value):
println("I have a value: \(value)")
case .None:
println("I'm empty")
}
The if-let form is just a convenience for when you don't need both legs.
If what you are writing is a set of functions performing the same sequence of transformation, such as when processing a result returned by a REST call (check for response not nil, check status, check for app/server error, parse response, etc.), what I would do is create a pipeline that at each steps transforms the input data, and at the end returns either nil or a transformed result of a certain type.
I chose the >>> custom operator, that visually indicates the data flow, but of course feel free to choose your own:
infix operator >>> { associativity left }
func >>> <T, V> (params: T?, next: T -> V?) -> V? {
if let params = params {
return next(params)
}
return nil
}
The operator is a function that receives as input a value of a certain type, and a closure that transforms the value into a value of another type. If the value is not nil, the function invokes the closure, passing the value, and returns its return value. If the value is nil, then the operator returns nil.
An example is probably needed, so let's suppose I have an array of integers, and I want to perform the following operations in sequence:
sum all elements of the array
calculate the power of 2
divide by 5 and return the integer part and the remainder
sum the above 2 numbers together
These are the 4 functions:
func sumArray(array: [Int]?) -> Int? {
if let array = array {
return array.reduce(0, combine: +)
}
return nil
}
func powerOf2(num: Int?) -> Int? {
if let num = num {
return num * num
}
return nil
}
func module5(num: Int?) -> (Int, Int)? {
if let num = num {
return (num / 5, num % 5)
}
return nil
}
func sum(params: (num1: Int, num2: Int)?) -> Int? {
if let params = params {
return params.num1 + params.num2
}
return nil
}
and this is how I would use:
let res: Int? = [1, 2, 3] >>> sumArray >>> powerOf2 >>> module5 >>> sum
The result of this expression is either nil or a value of the type as defined in the last function of the pipeline, which in the above example is an Int.
If you need to do better error handling, you can define an enum like this:
enum Result<T> {
case Value(T)
case Error(MyErrorType)
}
and replace all optionals in the above functions with Result<T>, returning Result.Error() instead of nil.
I've found a way that looks better than alternatives, but it uses language features in unrecommended way.
Example using code from the question:
let fooResult: Bar! = foo();
if fooResult == nil {
// handle error and return
}
// continue correct operations here
fooResult might be used as normal variable and it's not needed to use "?" or "!" suffixes.
Apple documentation says:
Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties.
How about the following:
func foo(i:Int) ->Int? {
switch i {
case 0: return 0
case 1: return 1
default: return nil
}
}
var error:Int {
println("Error")
return 99
}
for i in 0...2 {
var bob:Int = foo(i) ?? error
println("\(i) produces \(bob)")
}
Results in the following output:
0 produces 0
1 produces 1
Error
2 produces 99