NSPredicateEditorRowTemplate() gives syntax error "Type of expression is ambiguous without more context" - ambiguous

I fail in creating a NSPredicateEditorRowTemplate
func predicator() -> NSPredicateEditorRowTemplate {
let monthList = [NSExpression(forConstantValue:1),NSExpression(forConstantValue:2), NSExpression(forConstantValue:3) ]
let leftExp = NSExpression(forKeyPath:"monthP")
let monthTemplate = NSPredicateEditorRowTemplate (
leftExpressions: leftExp,
rightExpressions: monthList,
modifier: NSComparisonPredicate.Modifier(rawValue: 0),
operators: NSNumber(value:4),
options: 0)
return monthTemplate
}
When the code gets compiled, I receive the error message:
"Type of expression is ambiguous without more context"
I checked , if I have missed an argument, and if arguments are typed correctly. All seems ok. I even used the code completion help to avoid mistyping arguments.
No idea what could be wrong. Does anyone see the problem ?

Related

Type of expression is ambiguous without more context when replacing constant literal value with constant variable

I was wondering, what is a good way to fix the following compiler error?
class A {
var x: Int32
init() {
x = -1
}
}
let a: A? = nil
// No issue.
let ok: Int = Int(a?.x ?? -1)
// Type of expression is ambiguous without more context
let CONSTANT: Int = -1
let not_ok: Int = Int(a?.x ?? CONSTANT)
Any idea why we are getting Type of expression is ambiguous without more context if we use CONSTANT instead of -1?
What is a good way to fix the compiler error (retain same class, same type and same CONSTANT), yet still retain 1 liner?
It's for the same reason that you can say this:
let d = 3.0
let d2 = d + 1
But not this:
let i = 1
let d3 = d + i
Swift will cast the literal 1 to the required numeric type (here, Double), but it won't cast a variable away from its type.
So the answer is: make the types match.
The ?? operator is declared like this:
func ?? <T>(optional: T?, defaultValue: #autoclosure () throws -> T)
rethrows -> T
In the expression Int(a?.x ?? -1), the compiler needs to infer T for the
?? operator. It successfully infers T == Int32, because
the expression a?.x has the type Int32?.
it is okay for ?? to return Int32 here, because Int has an initialiser that takes Int32.
most relevantly, the literal -1 can be converted to Int32, because Int32 conforms to ExpressibleByIntegerLiteral.
If you instead do Int(a?.x ?? CONSTANT), however, that last point wouldn't work. ExpressibleByIntegerLiteral only works with literals, not any constant. The compiler sees CONSTANT as an expression of type Int, and tries very hard to find a type for the expression a?.x ?? CONSTANT, but it can't, and spits out a not-so-useful error message.
I suppose the error message is not very useful because it needs to consider quite a lot of things in this case (return type, the two parameters, overload resolution for Int.init), and it could be rather hard to pinpoint exactly where went wrong.
Anyway, to fix this, you can just convert the constant to Int32:
Int(a?.x ?? Int32(CONSTANT))
Or if you don't want to convert CONSTANT to an Int32 then back to Int again, you can rewrite this as:
a.map { Int($0.x) } ?? CONSTANT
"Map a to its x as an Int if a is not nil, otherwise CONSTANT".

Bunch of errors when I updated swift version

I updated an iOS application (not developed by myself) because as many of all you know if you want to upload a new build or a new application it should be now with the new SDK 13.
I haven't much experience with Swift and iOS but know I need to update this app previously running on swift 3 without problems, but when I converted it on Xcode 10.1 to swift 4 there were also a lot of new errors for me, I already found similar topics here about these type of errors, but since there isn't any documentation of the app and also I'm a newby on swift I not sure how to solve them. So at least I hope someone can help me to understand why there are this new errors just by updating the swift version.
The most recurrent errors I have are like this example, the following function was working, but with the update I have the following errors:
func showDeleteView()
{
let view: EliminarDialogView = try! SwiftMessages.viewFromNib()
view.configureDropShadow()
view.eliminarAction = { _ in self.handleDeleteToken() ; SwiftMessages.hide() }
view.cancelAction = { SwiftMessages.hide() }
var config = SwiftMessages.defaultConfig
config.interactiveHide = true
config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar)
config.duration = .forever
config.presentationStyle = .bottom
config.dimMode = .gray(interactive: true)
SwiftMessages.show(config: config, view: view)
Unable to infer complex closure return type; add explicit type to disambiguate
&
Cannot infer contextual base in reference to member 'window'
Also if I select to fix it by the IDE there's another error:
Value of type 'SwiftMessages.Config' has no member 'presentationContext'
What I found here and surfing on the Internet was about this need to receive the same kind of variable on the list but since there's also the use of "_" I'm not sure how to handle this here.
EDITED
The update of the pod helped! but about which line of code is having the errors:
Unable to infer complex closure return type; add explicit type to disambiguate
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Value of type 'ActivarViewController' has no member 'startAnimating'
On the following lines:
view.eliminarAction = { _ in self.handleDeleteToken() ; SwiftMessages.hide() }
self.present(alert, animated: true, completion: { _ in }) }
`self.startAnimating(nil, message: "Procesando código de activación", messageFont: nil, type: NVActivityIndicatorType.ballScaleMultiple)`
Could you please try to update SwiftMessages as follows:
pod 'SwiftMessages', '~> 5.0'
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?' - If there is no arguments then don't use Void in at all.
Value of type 'ActivarViewController' has no member 'startAnimating' - startAnimating starts the animation of the progress indicator, so it can be called via UIActivityIndicator.

Non-optional expression of type 'String' used in a check for optionals

I am getting this warning from Xcode Swift 5, here is my code I don't get what is wrong, I use this to remove any new line or tab at the end of my String (line)
My code:
let url: String = String(line.filter { !" \n\t\r".contains($0) })
UPDATE
I was doing it inside an if let and was using the type cast operator here is the solution and the rest of code and an example of the line value.
let line = " http://test.com/testing.php \n"
if let url: String = line.filter({!" \n\t\r".contains($0)}) as String?
{
//More action here
}
Thank you
to me this line looks good, but you may be missing the parentheses for the string filter method. Here's two ways I did it in playground. Let me know if this works for you, or how I can help further.
var line = "\t Hello, line removal \n \t Another new line \n"
let filteredClosure = line.filter { (char) -> Bool in
return !"\n\t\r".contains(char)
}
let filterShorthand = line.filter({!"\n\t\r".contains($0)})
With the line you provided, I would expect white-space to be removed too. If that's what you're looking for, add a space inside the filter string: " \n\t\r"

Swift 3 conversion gets 'Int1' is not convertible to 'Bool'

I'm converting Swift 2 code that compiles and runs to Swift 3 and am getting the following error:
'Int1' is not convertible to 'Bool'
The code is as follows:
isUpdated = sharedInstance.database!.executeUpdate(
"UPDATE Coin_Table SET upgrade=?, grade=?, WHERE coin_id=?",
withArgumentsInArray: [
coinInfo.upgrade, (coinInfo.grade != nil) ? coinInfo.grade! : NSNull(),
coinID])
The code above is using FMDB with the method defined in FMDB.h as
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
When compiling my code above it flags the "(coinInfo.grade !=" and gives the error.
I tried simplifying it to see if it would still happen:
let theArray: NSArray = [true ? "foo" : NSNull()]
and still get the same error, this time it flags the "true".
I've done a bunch of searches on this and haven't found anything close other than https://bugs.swift.org/browse/SR-2372 but that is an issue with tuples which I wouldn't think would affect my code.
Can anyone shed some light on this or suggest a workaround if it is a compiler bug?
Thanks
As you wrote yourself your issue is the same as a one described here. Bugs happens ))
Why not just to use a temporary variable to fix it:
let hasGrade: Any = (coinInfo.grade != nil) ? coinInfo.grade! : NSNull()
isUpdated = sharedInstance.database!.executeUpdate(
"UPDATE Coin_Table SET upgrade=?, grade=?, WHERE coin_id=?",
withArgumentsInArray: [
coinInfo.upgrade, hasGrade,
coinID])

F# Discriminated Union Type Issue

I'm having a problem getting my DU working as expected. I've defined a new DU which either has a result of type <'a> or any Exception derived from System.Exception
open System
// New exceptions.
type MyException(msg : string) = inherit Exception(msg)
type MyOtherException(msg : string) = inherit MyException(msg)
// DU to store result or an exception.
type TryResult<'a, 't> =
| Result of 'a
| Error of 't :> Exception
//This is fine.
let result = Result "Test"
// This works, doing it in 2 steps
let ex = new MyOtherException("Some Error")
let result2 = Error ex
// This doesn't work. Gives "Value Restriction" error.
let result3 = Error (new MyOtherException("Some Error"))
I can't understand why it is allowing me to create an "Error" if I do it in 2 steps, but when i'm doing the same thing on a single line, I get a Value Restriction error.
What am i missing?
Thanks
UPDATE
Looking at the post by #kvb, adding type information each time I need to create an Error seemed a bit verbose, so I wrapped it up into an additional method which creates an Error and is a bit more succinct.
// New function to return a Result
let asResult res : TryResult<_,Exception> = Result res
// New function to return an Error
let asError (err : Exception) : TryResult<unit,_> = Error(err)
// This works (as before)
let myResult = Result 100
// This also is fine..
let myResult2 = asResult 100
// Using 'asError' now works and doesn't require any explicit type information here.
let myError = asError (new MyException("Some Error"))
I'm not sure if specifying an Error with 'unit' will have any consequences I haven't foreseen yet.
TryResult<unit,_> = Error(err)
Consider this slight variation:
type MyOtherException(msg : string) =
inherit MyException(msg)
do printfn "%s" msg
let ex = new MyOtherException("Some Error") // clearly, side effect occurs here
let result2 = Error ex // no side effect here, but generalized value
let intResults = [Result 1; result2]
let stringResults = [Result "one"; result2] // can use result2 at either type, since it's a generalized value
let result3 = Error (MyOtherException("Some Error")) // result would be of type TryResult<'a, MyOtherException> for any 'a
// In some other module in a different compilation unit
let intResults2 = [Result 1; result3] // why would side effect happen here? just using a generic value...
let stringResults2 = [Result "one"; result3] // likewise here...
The issue is that it looks like result3 is a value, but the .NET type system doesn't support generic values, it only supports values of concrete types. Therefore, the MyOtherException constructor needs to be called each time result3 is used; however, this would result in any side effects occurring more than once, which would be surprising. As Ringil suggests, you can work around this by telling the compiler to treat the expression as a value anyway:
[<GeneralizableValue>]
let result3<'a> : TryResult<'a,_> = Error(new MyOtherException("Some Error"))
This is fine as long as the constructor doesn't have side effects.
You can do:
let result3<'a> = Error (new MyOtherException("Some Error"))
EDIT:
As for why you can't do it in one step, first note that this results in the same error:
let result4 = Result (new MyOtherException("Some Error"))
As does this:
let result4 = Result ([|1;|])
But that this works:
let result4 = Result ([1;])
What's similar about Exception and Arrays, but not Lists? It's their mutability. The value restriction will bother you when you try to do make a TryResult with a type that is mutable in a single step.
Now as for why the two step process solves this, it's because the constructor make the whole function not generalizable because you're applying a function to the constructor. But splitting it into two steps solves that. It is similar to Case 2 here on MSDN.
You can read more about it at the above MSDN article and the why this happens in this more indepth blog post.

Resources