Suppress Swift compiler warning - ios

I'm using the Nimble assertion framework for unit testing in Swift (Xcode 6.3 beta). It works fine, but the compiler gives a warning for one of the lines in the Nimble source code:
public func expect<T>(expression: () -> T?, file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T> {
return Expectation(
expression: Expression(
expression: expression,
location: SourceLocation(file: file, line: line),
isClosure: true))
}
The warning is for the first line:
Closure parameter prior to parameters with default arguments will not
be treated as a trailing closure
It's not a very serious issue, but I'd like to keep the number of compiler warnings low (zero) in my projects. Is there a way to remove this warning?

You can avoid the warning if the method signature will look like:
public func expect<T>(expression: (() -> T?), file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T>
added extra parenthesis around the first argument, tested with Swift 2.0 and Xcode 7.1
Another way of fixing it is to have all attributes with default value before the closure attribute as trailing closure is a quite convenient thing to have

#Julian Król answer is wrong for two reasons:
the code snippet demonstrate the wrong syntax, the correct will be:
public func expect<T>(expression: (() -> T?), file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T>
even with right syntax in Xcode 7.1 it does not fix the issue, cause you can not call this methods with trailing closure- it will give you compile error like Missing argument for parameter #1 in call.
With provided code you will only get rid of warning but you will not be able to use trailing closure when you call this function.
It fixes warning because in Swift tuple with one child is interchangeable with just single variable. And even ((((value)))) is the same as just value. Also looks like compiler does not recognize tuple with closure child as standalone closure in function arguments list.

To all the future readers of this topic: the answer is just for the case, when you have trailing closures. AFAIK, there is no way you can suppress Swift warnings like you would do in Objective-C (disable warnings for specific lines), maybe when the source of the Swift compiler will be open source, there will be some valid solutions, and this answer will be updated. Until then, you can check these answers (not Swift specific):
In Xcode, how to suppress all warnings in specific source files?
Is there a way to suppress warnings in Xcode?
If you can change the signature of expect, then put the parameter expression to the end, like:
public func expect<T>(file: String = __FILE__, line: UInt = __LINE__, expression: () -> T?) -> Expectation<T>
To be honest, it is poor design to have a closure parameter as the first parameter.

Looks like a very serious warning to me, that you most definitely should not ignore. It seems that what you think is a function call with a closure parameter is actually a function call without a closure parameter, followed by a closure.
You easily avoid the warning and fix the problem by putting the closure into the parameter list, or assigning it to a variable before the call and passing that variable.

Related

Xcode 8 :function types cannot have argument label breaking my build

It seems that for some reason Swift have chosen to make coding in it less readable by forcing users to remove completion handler parameter labels. I have read the Swift discussion and still think it's a mistake. At least they could have made it optional.
When building using Xcode 8 - is there a way to force the compiler to use Swift 2.3 so I don't get these errors anymore?
I have updated the option to use legacy Swift (under build settings)
but I still seem to get this error:
Function types cannot have argument label 'isloggedIn'; use '_'
instead
How can I keep my labels in my completion handlers?
The Swift designers decided to prohibit argument labels for function types.
The reasoning is explained here: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
This is a frustrating and questionable choice, as prohibiting argument labels makes it much easier to incorrectly invoke closures, which seems more important than simplifying the language's type system.
Usability > ideology.
A workaround to consider. You can't do:
func doStuff(completion: (foo: Int, bar: String) -> Void) {
...
completion(foo: 0, bar: "")
}
... but you can do:
func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
...
completion((foo: 0, bar: ""))
}
i.e. have a single unnamed argument to your closure which is a tuple, in this case (foo: Int, bar: String).
It's ugly in its own way, but at least you retain the argument labels.
Based on the information above - it appears that the only way to really fix this and ensure that its performant is to raise a proposal to
Make argument labels optional with a view to :
improving the speed of development ( without argument labels it requires us to scroll up to the top of the method each time we put in the completion handler.
Reduce Errors : ( I have already had several errors caused due to incorrect completion handler entries especially with those that expect boolean values)
Make code more readable across team members. Not everyone has only one team member and thus being able to easily pick up other peoples code is a must have.
Lastly good programming practice means that the solution should look as much like the actual item being developed. completionhandler: (newvalues, nil) looks less like the item being managed than completionhandler(results: newValue, error:nil)
I would love for people reading this to share their feedback/ comments
on this below before I submit it so I can show there are others that
support this.
Edit:
I have submitted the pitch here :
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html
which appears to have been agreed. It looks like its going to happen, however the discussion is whether this is submitted as a Swift 4 improvement ( highly probable)
You have to use _ to make your parameters unnamed, and that is unfortunate. Instead of tacking _ on to each parameter and then blindly calling your function I would suggest making a wrapper object.
Since losing named parameters for function types introduces more risk that you will call the function with the wrong values, I would suggest wrapping the parameters in a struct and having that be the one and only parameter to your function.
This way the fields of you struct are named, and there is only one type of value to pass into your function. It is more cumbersome than if we were able to name the parameters of the function, but we can't. At least this way you'll be safer and you'll feel less dirty.
struct LineNoteCellState {
var lineNoteText: String?
var printOnInvoice = false
var printOnLabel = false
}
Here is an example of it being used:
cell.configure(editCallback: { (_ state: LineNoteCellState) in
self.lineNoteText = state.lineNoteText
self.printOnInvoice = state.printOnInvoice
self.printOnLabel = state.printOnLabel
})
Semi-workaround, note the _
completion: (_ success: Bool) -> Void

Cannot convert from `GLib.TypeClass' to `GLib.ObjectClass'

I was trying to compile libfriends (source) against valac (.28) and libgee (1.0). I specifically compiled these against Ubuntu-16.04 stack.
But I am getting following error
entry.vala:397.38-397.38: warning: if-statement without body
if (_selected != value);
^
entry.vala:172.52-172.86: error: Argument 1: Cannot convert from `GLib.TypeClass' to `GLib.ObjectClass'
binding_set = Gtk.BindingSet.by_class (typeof (InputTextView).class_ref ());
I don't really find anything wrong with code. Any Idea?
The entire buildlog is here: https://launchpadlibrarian.net/263631082/buildlog_ubuntu-xenial-i386.libfriends_0.1.2+14.10.20140709+201606051415~ubuntu16.04.1_BUILDING.txt.gz
I just checked and it compiles with valac-0.18, but doesn't compile with valac-0.28.
So there must have been a change between those valac versions that does more strict type checking in this case.
GLib.TypeClass (really GTypeClass in C) is the parent class of GLib.ObjectClass (really GObjectClass in C).
So the compiler is correct to not allow this without a cast. I don't know if the cast is correct in this situation, but it makes the code compile:
binding_set = Gtk.BindingSet.by_class ((ObjectClass) typeof (InputTextView).class_ref ())
See also valadoc for GObjectClass where a similar typecast is done in the example code:
http://valadoc.org/#!api=gobject-2.0/GLib.ObjectClass

Swift `in` keyword meaning?

I am trying to implement some code from parse.com and I notice a keyword in after the void.
I am stumped what is this ? The second line you see the Void in
PFUser.logInWithUsernameInBackground("myname", password:"mypass") {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
// Do stuff after successful login.
} else {
// The login failed. Check error to see why.
}
}
The docs don't document this. I know the in keyword is used in for loops.
Anyone confirm?
In a named function, we declare the parameters and return type in the func declaration line.
func say(s:String)->() {
// body
}
In an anonymous function, there is no func declaration line - it's anonymous! So we do it with an in line at the start of the body instead.
{
(s:String)->() in
// body
}
(That is the full form of an anonymous function. But then Swift has a series of rules allowing the return type, the parameter types, and even the parameter names and the whole in line to be omitted under certain circumstances.)
Closure expression syntax has the following general form:
The question of what purpose in serves has been well-answered by other users here; in summary: in is a keyword defined in the Swift closure syntax as a separator between the function type and the function body in a closure:
{ /parameters and type/ in /function body/ }
But for those who might be wondering "but why specifically the keyword in?", here's a bit of history shared by Joe Groff, Senior Swift Compiler Engineer at Apple, on the Swift forums:
It's my fault, sorry. In the early days of Swift, we had a closure
syntax that was very similar to traditional Javascript:
func (arg: -> Type, arg: Type) -> Return { ... }
While this is nice and regular syntax, it is of course also very bulky
and awkward if you're trying to support expressive functional APIs,
such as map/filter on collections, or if you want libraries to be able
to provide closure-based APIs that feel like extensions of the
language.
Our earliest adopters at Apple complained about this, and mandated
that we support Ruby-style trailing closure syntax. This is tricky to
fit into a C-style syntax like Swift's, and we tried many different
iterations, including literally Ruby's {|args| } syntax, but many of
them suffered from ambiguities or simply distaste and revolt from our
early adopters. We wanted something that still looked like other parts
of the language, but which could be parsed unambiguously and could
span the breadth of use cases from a fully explicit function signature
to extremely compact.
We had already taken in as a keyword, we couldn't use -> like Java
does because it's already used to denote the return type, and we were
concerned that using => like C# would be too visually confusing. in
made xs.map { x in f(x) } look vaguely like for x in xs { f(x) },
and people hated it less than the alternatives.
*Formatting and emphasis mine. And thanks to Nikita Belov's post on the Swift forums for helping my own understanding.

Function type vs Closure type

I want to create a vector of functions
let all_rerankers = vec![ match_full
, match_partial
, match_regex
, match_camel_case
];
However, match_camel_case needs one more parameter than other functions, so I though I could define a closure for match_camel_case
// 3 is the extra parameter needed by match_camel_case
let close_camel_case = |str: &str, keyword: &str| {
match_camel_case(str, keyword, 3)
};
and then specify the type of my vector:
let all_rerankers: Vec<|str: &str, kwd: &str| -> MatchScore>
= vec![ match_full
, match_partial
, match_regex
, close_camel_case
];
However compiling it shows me that Rust treats them differently:
mismatched types: expected `fn(&str, &str) -> MatchScore`,
found `|&str, &str| -> MatchScore`
(expected extern fn, found fn)
close_camel_case
^~~~~~~~~~~~~~~~
(and similar type error in my vec! macro)
It also seem to distinguish between Fn type and closure type. I can make this compile by wrapping every match_* function in a closure, but I'm sure there's a better solution.
Question:
What is the actual mismatch here? the error message seems to suggest Fn vs closure type, but then there's also expected extern fn, found fn in the error message
How can I make the type match? (namely, convert closure into fn type, since it's pure)
my rustc version: rustc 0.12.0-pre-nightly (09cebc25a 2014-09-07 00:31:28 +0000) (can upgrade if needed)
This looks like some unfortunate problem in type inference. If you do this:
let mut all_rerankers: Vec<|str: &str, kwd: &str| -> MatchScore> = Vec::new();
all_rerankers.push(match_full);
all_rerankers.push(match_partial);
all_rerankers.push(match_regex);
all_rerankers.push(close_camel_case);
Then everything is fine. The duplication is extensive, but you can easily write a macro whose invocation could look like this:
push_to!(all_rerankers;
match_full,
match_partial,
match_regex,
close_camel_case
)
This probably deserves creating an issue in Rust bug tracker, but old closures will be deprecated soon, so I'm not sure if this is worth fixing.

Why does the F# compiler give an error for one case but not the other?

I'm working on a platform invoke call from F#, and I am getting a compiler error I really can't make that much sense out of. First, let me show the C signature of what I am doing:
int Foo(
ULONG_PTR *phHandle,
DWORD flags
);
In F#, I think the correct way to invoke this natively is as so:
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
[<Out>]nativeint& phHandle,
uint32 flags
)
If I try to call this in a class, I get a compilation error when calling it like so:
type Class1() =
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
member this.Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
The error is:
A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
Weirdly, when I do this all in a module, the compilation errors go away:
module Module1 =
[<DllImport("somedll.dll")>]
extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
let Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
Why does this compile as a module, but not as a class?
I don't think it's valid to define an extern method within a class in F#.
If you pull up the F# 3.0 language specification and search for DllImport, near the bottom is a table listing some special attributes and how they can be used. The text for [<DllImport>] says:
When applied to a function definition in a module, causes the F# compiler to ignore the implementation of the definition, and instead compile it as a CLI P/Invoke stub declaration.
That seems to indicate that it's only valid to declare extern methods (that use [<DllImport>]) on functions defined in a module; it doesn't say anything about class members though.
I think you're running into a compiler bug. Please submit this code to fsbugs#microsoft.com so they can fix the error message emitted by the compiler -- it should really be giving you an error about defining an extern method in a class since that's not allowed by the language spec.
Whether this is a bug not withstanding, maybe this is what's going on: If APlatformInvokeCall were considered a static member function, that member have a single argument of tuple type. Tuples are compiled into objects of generic type (see here, at the bottom, or 5.1.3 in the spec). In this case that tuple is
System.Tuple<nativeint&, uint32>
But ECMA 335 II.9.4 says you can't instantiate generic types at byref types. This explains the error reported.
This explanation fits the fact mentioned above that Class1 works (well, compiles) if you modify the extern declaration and call to take instead a single argument. It also fits the fact that the module version works, since in that version there is no considering APlatFormInvokeCall a member function.
The simple solution is to check the spec, here is the class definition grammar:
type type-name pat_opt as-defn)opt =
class
class-inherits-decl_opt
class-function-or-value-defns_opt
type-defn-elements
end
then we have
class-function-or-value-defn :
attributes_opt staticopt let rec_opt function-or-value-defns
attributes_opt staticopt do expr
which doesn't allow extern.
and
type-defn-element :
member-defn
interface-impl
interface-signature
which isn't what you want either.
As a result, we can see that using extern as you are trying to use it can't be done inside a class.

Resources