Optional arguments without ? identifier - nullable

In the Haxe 3 manual at http://haxe.org/manual/types-function-default-values.html, we have static function test(?i = 12, s = "bar").
Why isn't it static function test(?i = 12, ?s = "bar") or static function test(i = 12, s = "bar")?

Actually, there's a subtle difference between ?i=1 and i=1:
function test(?i=1):String is of type Null<Int> -> String
function test(i=1):String is of type Int -> String
While ?i indicates an optional argument – and that always implies nullability – i=1 indicates a default value and should eliminate the need for a Null<T> box.
See Optional Arguments and Nullability and an example.

Related

Understanding difference between int? and int (or num? and num) [duplicate]

This question already has answers here:
What is Null Safety in Dart?
(2 answers)
Closed 1 year ago.
After defining a map (with letters as keys and scrabble tile scores as values)
Map<String, int> letterScore //I'm omitting the rest of the declaration
when I experiment with this function (in DartPad)
int score(String aWord) {
int result = 0;
for (int i = 0; i < aWord.length; ++i) {
result += letterScore[aWord[i]];
}
return result;
}
I consistently get error messages, regardless of whether I experiment by declaring variables as num or int:
Error: A value of type 'int?' can't be assigned to a variable of type
'num' because 'int?' is nullable and 'num' isn't [I got this after declaring all the numerical variables as int]
Error: A value of type 'num' can't be returned from a function with
return type 'int'.
Error: A value of type 'num?' can't be assigned to a variable of type
'num' because 'num?' is nullable and 'num' isn't.
I understand the difference between an integer and a floating point (or double) number, it's the int vs int? and num vs num? I don't understand, as well as which form to use when declaring variables. How should I declare and use int or num variables to avoid these errors?
Take this for example:
int x; // x has value as null
int x = 0; // x is initialized as zero
Both the above code are fine and compilable code. But if you enable Dart's null-safety feature, which you should, it will make the above code work differently.
int x; // compilation error: "The non-nullable variable must be assigned before can be used"
int x = 0; // No Error.
This is an effort made from the compiler to warn you wherever your variable can be null, but during the compile time. Awesome.
But what happens, if you must declare a variable as null because you don't know the value at the compile time.
int? x; // Compiles fine because it's a nullable variable
The ? is a way for you tell the compiler that you want this variable to allow null. However, when you say a variable can be null, then every time you use the variable, the compiler will remind you to check whether the variable is null or not before you can use it.
Hence the other use of the ?:
int? x;
print(x?.toString() ?? "0");
Further readings:
Official Docs: https://dart.dev/null-safety/understanding-null-safety
Null-aware operators: https://dart.dev/codelabs/dart-cheatsheet

Why can't Object.runtimeType be used in an as expression?

According to the Dart docs for Object.runtimeType, the field's type is Type. Which is confusing because I get an error from the compiler complaining about this field not being a type.
See this sample code:
final double first = 1.0;
final int second = 2;
final third = second as double; // works fine, unlike declaration below.
assert(first.runtimeType == double); // true
final fourth = second as first.runtimeType;
The last line throws this compile-time error:
The name 'first.runtimeType' isn't a type, so it can't be used in an 'as' expression.
The sample code shows that first.runtimeType == double, so wouldn't it follow that _ as first.runtimeType is equivalent to _ as double?
I think it is simple actually, runtimeType is only available at RunTime and cannot be statically analyzed by the compiler.

Constant 'spacesLeft' inferred to have type '()', which may be unexpected Swift

I am building a Tic Tac Toe game with an AI using Xcode 8 and Swift. Here are the relevant variables I am using that are contributing to the error:
var allSpaces: Set<Int> = [1,2,3,4,5,6,7,8,9]
var playerOneMoves = Set<Int>()
var playerTwoMoves = Set<Int>()
var nextMove: Int? = nil
Inside a function defining how the AI will play there are these variables:
var count = 0
let spacesLeft = allSpaces.subtract(PlayerOneMoves.union(playerTwoMoves))
The latter results in the compiler warning:
Constant 'spacesLeft" inferred to have type '()', which may be unexpected
There is an if statement just below that says:
if allSpaces.subtract(playerOneMoves.union(playerTwoMoves)).count > 0 {
nextMove = spacesLeft[spacesLeft.startIndex.advancedBy(Int(arc4random_uniform(UInt32(spacesLeft.count))))]
}
The condition gives the following error:
Value of tuple type '()' has no member 'count'
The statement gives the following error:
Type '()' has no subscript members
I am struggling to find a solution.
subtract modifies Set in place and doesn't return a value, you want to use subtracting
For the first warning, subtract returns Void, so use subtracting:
let spacesLeft = allSpaces.subtracting(playerOneMoves.union(playerTwoMoves))
For the second error, advancedBy is deprecated, you may change like this:
if spacesLeft.count > 0 {
nextMove = spacesLeft[spacesLeft.index(spacesLeft.startIndex, offsetBy: Int(arc4random_uniform(UInt32(spacesLeft.count))))]
}
Set.subtract is a mutating function, so it modifies the Set in place and its return value is Void, which is just a type alias for an empty tuple, (), hence the warning.
You should call Set.substracting, which is the non-mutating version of subtract and returns Set<Set.Element>.
The subtract(_:) function is a mutating function so it will mutate the Set your using to call the function.
From Apple Docs:
subtract(_:)
Removes the elements of the given set from this set.
The reason you're getting the errors is because this function returns Void which in Swift is a typealias for an empty tuple(from Swift's source code). Since Void has no subscripts nor count property/variable you get those errors.
Maybe you should take a look at the subtracting(_:) function, which returns a different Set.
From Apple Docs:
subtracting(_:)
Returns a new set containing the elements of this set that do not occur in the given set.

Swift3 error 'cannot be applied to operands of type

Getting the following error:
Binary operator '==' cannot be applied to operands of type 'UInt16' and '() -> UInt16'
in this section of code:
let array: [UInt16] = [3,4, 7]
let x = NSNumber(value: 4)
let option = array.filter { (test) -> Bool in
return test == x.uint16Value // compiler complains here
}
print(option) // "[4]"
Normally this type of error means two values of separate class are being compared. Here the compiler thinks I'm comparing a uint16 value with a function that returns a uint16 value.
What I mean to do is call NSNumber's uint16 property getter.
// defined in NSNumber
open var uint16Value: UInt16 { get }
I'm told to instead make a function call by adding parenthesis (e.g .uint16Value()). But this leads to the follow up error:
Cannot call value of non-function type 'UInt16'
I have dropped this exact code into a playground and it runs fantastically.
Has anyone else run into this? Or seen this type of behavior? Have you beaten it?
Update:
When setting to a local variable, no difference is made. I have recently run the migration tool from Swift 2.2 or 2.3 up to swift 3 in Xcode 8.0. It doesn't seem like there is anything wrong with syntax or migration.
let y = x.uint16Value
return test == y // compiler complains here

Cannot assign to a parameter

I have declared a function
func someFunction(parameterName: Int) {
parameterName = 2 //Cannot assign to let value parameter Name
var a = parameterName
}
and trying to assign it a value during runtime, but it gives me error
"Cannot assign to let value parameter Name".
Is the parameter name constant by default? Can I change it to a variable?
[In Swift >= 3.0] Function parameters are defined as if by let and thus are constants. You'll need a local variable if you intend to modify the parameter. As such:
func someFunction (parameterName:Int) {
var localParameterName = parameterName
// Now use localParameterName
localParameterName = 2;
var a = localParameterName;
}
[In Swift < 3.0] Declare the argument with var as in:
func someFunction(var parameterName:Int) {
parameterName = 2;
var a = parameterName;
}
use of inout has a different semantics.
[Note that "variable parameters" will disappear in a future Swift version.] Here is the Swift documentation on "variable parameters":
Function parameters are constants by default. Trying to change the
value of a function parameter from within the body of that function
results in a compile-time error. This means that you can’t change the
value of a parameter by mistake.
However, sometimes it is useful for a function to have a variable copy of a parameter’s value to work with. You can avoid defining a
new variable yourself within the function by specifying one or more
parameters as variable parameters instead. Variable parameters are
available as variables rather than as constants, and give a new
modifiable copy of the parameter’s value for your function to work
with.
Define variable parameters by prefixing the parameter name with the keyword var: ..."
Excerpt From: Apple Inc. “The Swift Programming Language.”
If you actually want to change the value stored in a location that is passed into a function, then, as #conner noted, an inout parameter is justified. Here is an example of that [In Swift >= 3.0]:
1> var aValue : Int = 1
aValue: Int = 1
2> func doubleIntoRef (place: inout Int) { place = 2 * place }
3> doubleIntoRef (&aValue)
4> aValue
$R0: Int = 2
5> doubleIntoRef (&aValue)
6> aValue
$R1: Int = 4
In order to modify the argument passed in, you have to designate it as an inout parameter:
func someFunction(inout parameterName:Int)
{
parameterName = 2;
var a = parameterName;
}
Note this will change the variable that was passed in as well. If that isn't what you're looking for, use var as GoZoner suggested.

Resources