Generic with default value of nil - swift

I'm attempting to create a generic class/struct initializer that converts any value it takes in and assigns it to its Double properties. (Note: the as! or as? pattern below is just being used to save space here. I'm actually using this extension to convert my values.)
The idea here is that I'd like to be able to mix Integers, Doubles, CGFloats, etc (i.e. anything in the Numeric generic type constraint) and have them all end up as Doubles. It works in other situations, but I'm running into an issue here.
In the pared down example below I'm creating a Vector class and the z property should be able to be nil in case we're only dealing with 2 dimensions.
struct Vector {
var x: Double
var y: Double
var z: Double?
public init<X: Numeric, Y: Numeric, Z: Numeric>(_ x: X, _ y: Y, _ z: Z? = nil){
self.x = x as! Double
self.y = y as! Double
self.z = z as? Double
}
}
var myVector = Vector(4, 3.4)
print("""
\(myVector.x)
\(myVector.y)
\(myVector.z)
"""
)
The problem is that I get an error that says Generic parameter 'Z' could not be inferred.

I would do this with two separate intitializers, one of which doesn't need to have an unused generic Z:
struct Vector {
var x: Double
var y: Double
var z: Double?
}
extension Vector {
public init<X: Numeric, Y: Numeric>(_ x: X, _ y: Y) {
self.init(x: x as! Double, y: y as! Double, z: nil as Double?)
}
public init<X: Numeric, Y: Numeric, Z: Numeric>(_ x: X, _ y: Y, _ z: Z? = nil) {
self.init(x: x as! Double, y: y as! Double, z: z as? Double)
}
}

Related

Swift closure compiling failed with expression too complex

public static func easeOutQuint(_ t: Float, _ b: Float, _ c: Float, _ d: Float = 1.0) -> Float {
return {
return c * ($0 * $0 * $0 * $0 * $0 + 1.0) + b
}(t / d - 1.0)
}
I'm not familiar with closure, so I can not fix it by myself, can someone help me?
Closures are a great tool but, in this particular example, you would be better off without them IMO...
For instance, you could rewrite your function simply as:
public static func easeOutQuint(_ t: Float, _ b: Float, _ c: Float, _ d: Float = 1.0) -> Float {
let x = (t / d - 1.0)
return c * (pow(x, 5) + 1) + b
}
And, by the way, this should compile just fine in any Swift compiler you come across ;)

How to compute a value to pass into a primary constructor from an auxiliary constructor?

I want to define an auxiliary constructor which should compute some value and use it in multiple parameters passed to a primary constructor. A natural way to express this would be to define local vals before calling the primary constructor, but this is not allowed by the language:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
}
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
val derivedFromX = Computed.veryComplexComputation(x)
val derivedFromY = derivedFromX * Computed.veryComplexComputation(y)
this(x, derivedFromX, derivedFromY)
}
}
An alternative is to repeat the computation, but with very complex computations this can be a problem (and it also leads to a code repetition):
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
this(
x,
Computed.veryComplexComputation(x),
Computed.veryComplexComputation(x) * Computed.veryComplexComputation(y)
)
}
}
The best trick I know is to use a third, private constructor taking a tuple of the parameters for the primary constructor, together with a helper function in the companion object:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private def computeArgs(x: Double, y: Double): (Double, Double, Double) = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
(x, derivedFromX, derivedFromY)
}
}
class Computed(x: Double, y: Double, z: Double) {
private def this(xyz: (Double, Double, Double)) =
this(xyz._1, xyz._2, xyz._3)
def this(x: Double, y: Double) =
this(Computed.computeArgs(x, y))
}
I think the best way is to add a suitable factory method to the companion object:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // can be private, if you wish
def apply(x: Double, y: Double): Computed = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
new Computed(x, derivedFromX, derivedFromY)
}
}
then you can instantiate your Computed type the same way as for case classes, foregoing the use of "new":
scala> val comp = Computed(4.0, 9.0)
comp: Computed = Computed#4de4e24f
(You might also want to consider making Computed a case class anyway - particularly if is entirely, or even mostly, used as a container for data)
One can (ab)use multiple parameter lists with default values, like this:
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double)(
derivedFromX: Double = Computed.veryComplexComputation(x)
)(
derivedFromY: Double = derivedFromX * Computed.veryComplexComputation(y)
) = {
this(x, derivedFromX, derivedFromY)
}
}
This exploits the fact each parameter list can access parameters from previous lists. Just do not forget to provide the empty parameter lists when calling the constructor:
new Computed(1, 2)()()
One can chain several auxiliary constructors, each of them performing one computation, using marker traits to distinguish between constructors to avoid overloading ambiguity.
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private trait DerivedFromX
private object DerivedFromX extends DerivedFromX
}
class Computed(x: Double, y: Double, z: Double) {
private def this(name: Computed.DerivedFromX, x: Double, derivedFromX: Double, y: Double) = {
this(x, derivedFromX, derivedFromX * Computed.veryComplexComputation(y))
}
def this(x: Double, y: Double) = this(Computed.DerivedFromX, x, Computed.veryComplexComputation(x), y)
}

How to properly support Int values in CGFloat math in Swift?

Goal
I (like many others on the web) would like to use Int variables and literals in CGFloat math since readability & ease of development outweigh a possible loss in precision by far. This is most noticeable when you use manual layout throughout an app instead of using the Storyboard.
So the following should work without any manual CGFloat casts:
let a = CGFloat(1)
let b = Int(2)
let c = a / b // Cannot invoke / with an arguments list of type (CGFloat, Int)
let d = b / a // Cannot invoke / with an arguments list of type (Int, CGFloat)
let e = a / 2 // => CGFloat(0.5)
let f = 2 / a // => CGFloat(2.0)
let g = 2 / b // => Int(1)
let h = b / 2 // => Int(1)
let i = 2 / 2 // => Int(1)
let j: CGFloat = a / b // Cannot invoke / with an arguments list of type (CGFloat, Int)
let k: CGFloat = b / a // Cannot invoke / with an arguments list of type (Int, CGFloat)
let l: CGFloat = a / 2 // => CGFloat(0.5)
let m: CGFloat = 2 / a // => CGFloat(2.0)
let n: CGFloat = 2 / b // Cannot invoke / with an arguments list of type (IntegerLiteralConvertible, Int)
let o: CGFloat = b / 2 // Cannot invoke / with an arguments list of type (Int, IntegerLiteralConvertible)
let p: CGFloat = 2 / 2 // => CGFloat(1.0)
Approach
Since we cannot add implicit conversions to Swift types I had to add appropriate operators which take CGFloat and Int.
func / (a: CGFloat, b: Int) -> CGFloat { return a / CGFloat(b) }
func / (a: Int, b: CGFloat) -> CGFloat { return CGFloat(a) / b }
Problem
The two operators become ambiguous when Swift tries to implicitly create CGFloat values from integer literals. It doesn't know which of the two operands to convert (example case p).
let a = CGFloat(1)
let b = Int(2)
let c = a / b // => CGFloat(0.5)
let d = b / a // => CGFloat(2.0)
let e = a / 2 // => CGFloat(0.5)
let f = 2 / a // => CGFloat(2.0)
let g = 2 / b // => Int(1)
let h = b / 2 // => Int(1)
let i = 2 / 2 // => Int(1)
let j: CGFloat = a / b // => CGFloat(0.5)
let k: CGFloat = b / a // => CGFloat(2.0)
let l: CGFloat = a / 2 // => CGFloat(0.5)
let m: CGFloat = 2 / a // => CGFloat(2.0)
let n: CGFloat = 2 / b // => CGFloat(1.0)
let o: CGFloat = b / 2 // => CGFloat(1.0)
let p: CGFloat = 2 / 2 // Ambiguous use of operator /
Question
Is there any way to declare the operators in a way where there is no ambiguous use and all test cases succeed?
For starters, tl;dr: NO.
The problem is that we're asking the compiler to do too much implicitly.
I'm going to use regular functions for this answer, because I want it to be clear that this has nothing to do with operators.
So, we need the following 4 functions:
func foo(a: Int, b: Int) -> Int {
return 1
}
func foo(a: Int, b: Float) -> Float {
return 2.0
}
func foo(a: Float, b: Int) -> Float {
return 3.0
}
func foo(a: Float, b: Float) -> Float {
return 4.0
}
And now we're in the same scenario. I'm going to ignore all of the ones that work and focus on these two scenarios:
let bar1 = foo(1,2)
let bar2: Float = foo(1,2)
In the first scenario, we're asking Swift to implicitly determine just one thing: What type should bar1 be? The two arguments we pass to foo are 1, which is of type IntegerLiteralConvertible, and 2, which is again of the type IntegerLiteralConvertible.
Because there is only one override for foo which takes two Int arguments, Swift is able to figure out what type bar1 should be, and that's whatever type the foo(Int,Int) override returns, which is Int.
Now, consider the scenario in which we add the following function:
func foo(a: Int, b: Int) -> Float {
return 5.0
}
Now, scenario 1 becomes ambiguous:
let bar1 = foo(1,2)
We're asking Swift to determine TWO things implicitly here:
Which override of foo to use
What type to use for bar1
There is more than one way to satisfy the scenario. Either bar1 is an Int and we use the foo(Int,Int)->Int override, or bar2 is a Float, and we use the foo(Int,Int)->Float override. The compiler can't decide.
We can make the situation less ambiguous though as such:
let bar1: Int = foo(1,2)
In which case the compiler knows we want the foo(Int,Int)->Int override--it's the only one that satisfies the scenario. Or we can do:
let bar2: Float = foo(1,2)
In which case the compiler knows we want the foo(Int,Int)->Float override--again, the only way to satisfy the scenario.
But let's take a look back at my scenario 2, which is exactly the problem scenario you have:
let bar2: Float = foo(1,2)
There's not a foo(Int,Int)->Float override (forget everything about scenario 1 in which we added this override). However, the type IntegerLiteralConvertible can be implicitly cast to different types of numeric data types (only literal integers... not integer variables). So the compiler will try to find a foo override that takes arguments that IntegerLiteralConvertible can be cast to and returns a Float, which we've explicitly marked as bar2's type.
Well, IntegerLiteralConvertible can be cast as a Float, so the compiler finds three functions that take some combination of the right argument:
foo(Int,Float) -> Float
foo(Float,Int) -> Float
foo(Float,Float) -> Float
And the compiler doesn't know which to use. How can it? Why should it prioritize casting one or the other of your literals integers to a float?
So we get the ambiguity problem.
We can give the compiler another override. It's the same one we gave it in scenario 2: foo(Int,Int) -> Float, and now the compiler is okay with the following:
let bar2: Float = foo(1,2)
Because in this case, without implicitly casting the IntegerLiteralConvertibles, the compiler was able to find a function that matched: foo(Int, Int) -> Float.
So now you're thinking:
All right, let me just add this foo(Int,Int)->Float and everything will work!
Right?
Well, sorry to disappoint, but given the following two functions:
foo(Int,Int) -> Int
foo(Int,Int) -> Float
We will still run into ambiguity problems:
let bar3 = foo(1,2)
There are two overrides for foo that take an Int (or IntegerLiteralConvertible), and because we haven't specified bar3's type and we're asking the compiler both figure out the appropriate override and implicitly determine bar3's type, which it cannot do.

How can an operator be overloaded for different RHS types and return values?

Given the following struct:
struct Vector3D {
x: f32,
y: f32,
z: f32
}
I want to overload its * operator to do a dot product when the right hand side is a Vector3D, and to do an element-wise multiplication when the RHS is a f32. My code looks like this:
// Multiplication with scalar
impl Mul<f32, Vector3D> for Vector3D {
fn mul(&self, f: &f32) -> Vector3D {
Vector3D {x: self.x * *f, y: self.y * *f, z: self.z * *f}
}
}
// Multiplication with vector, aka dot product
impl Mul<Vector3D, f32> for Vector3D {
fn mul(&self, other: &Vector3D) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z
}
}
The compiler says for the first impl block:
Vector3D.rs:40:1: 44:2 error: conflicting implementations for trait `std::ops::Mul`
Vector3D.rs:40 impl Mul<f32, Vector3D> for Vector3D {
...
Vector3D.rs:53:1: 57:2 note: note conflicting implementation here
Vector3D.rs:53 impl Mul<Vector3D, f32> for Vector3D {
...
and vice versa for the other implementation.
As of Rust 1.0, you can now implement this:
use std::ops::Mul;
#[derive(Copy, Clone, PartialEq, Debug)]
struct Vector3D {
x: f32,
y: f32,
z: f32,
}
// Multiplication with scalar
impl Mul<f32> for Vector3D {
type Output = Vector3D;
fn mul(self, f: f32) -> Vector3D {
Vector3D {
x: self.x * f,
y: self.y * f,
z: self.z * f,
}
}
}
// Multiplication with vector, aka dot product
impl Mul<Vector3D> for Vector3D {
type Output = f32;
fn mul(self, other: Vector3D) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z
}
}
fn main() {
let a = Vector3D {
x: 1.0,
y: 2.0,
z: 3.0,
};
let b = a * -1.0;
let c = a * b;
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
}
The big change that allows this is the introduction of associated types, which shows up as the type Output = bit in each implementation. Another notable change is that the operator traits now take arguments by value, consuming them, so I went ahead and implemented Copy for the struct.
At the moment only a single impl is allowed per trait-type pair.
This situation will be improved with RFC 48, but it's not the full story (it's not really any of the story). The relevant section is Coherence, and it certainly doesn't mention the operator overloading case specifically, and essentially says it is still illegal:
The following example is NOT OK:
trait Iterator<E> { ... }
impl Iterator<char> for ~str { ... }
impl Iterator<u8> for ~str { ... }
Niko Matsakis (author of that RFC & Rust-type-system expert) has been thinking about these overloading traits specifically: he is the one who published ("What if I want overloading?") the trick below, but he has expressed his distaste towards it, mentioning that he'd like to allow implementations as you have written...
... which is where his RFC 135 comes in. The situation is described in detail in "multidispatch traits".
You can work-around it for now using secondary traits. The extra layer of traits allows you to write just one impl Mul<...> for Vector3D but comes at the cost of requiring a new trait for each type for which you wish to have multiple implementations of Mul.
#[deriving(Show)]
struct Vector3D {
x: f32,
y: f32,
z: f32
}
trait MulVec3D<Res> {
fn do_mul(&self, v: &Vector3D) -> Res;
}
// Multiplication with scalar
impl MulVec3D<Vector3D> for f32 {
fn do_mul(&self, v: &Vector3D) -> Vector3D {
Vector3D {x: v.x * *self, y: v.y * *self, z: v.z * *self}
}
}
// Multiplication with vector, aka dot product
impl MulVec3D<f32> for Vector3D {
fn do_mul(&self, v: &Vector3D) -> f32 {
self.x * v.x + self.y * v.y + self.z * v.z
}
}
impl<Res, RHS: MulVec3D<Res>> Mul<RHS, Res> for Vector3D {
fn mul(&self, rhs: &RHS) -> Res {
rhs.do_mul(self)
}
}
fn main() {
let a = Vector3D { x: 1.0, y: 2.0, z: 3.0 };
let b = Vector3D { x: -3.0, y: 2.0, z: -1.0 };
println!("{}, {}", a * 2f32, a * b); // Vector3D { x: 2, y: 4, z: 6 }, -2
}

How do I expose Scala constructor arguments as public members?

Look at this example:
class Point(x: Double, y: Double){
override def toString = "x: " + x + ", y: " + y
def +(sourcePoint: Point) : Point = {
return new Point(x + sourcePoint.x, y + sourcePoint.y
}
}
As you can see I want to define a + operator method on the Point class. But this won't work
because in that method, x and y can't be accessed on the sourcePoint local variable since they are private, so I changed the example into this:
class Point(_x: Double, _y: Double){
var x = _x
var y = _y
override def toString = "x: " + x + ", y: " + y
def +(sourcePoint: Point) : Point = {
return new Point(x + sourcePoint.x, y + sourcePoint.y)
}
}
That obviously worked, however is there an easier way to define these variables instead of going from _x -> x and _y -> y.
Thanks for help and time! :)
Yes, there is:
class Point(val x: Int, val y: Int)
using val is valid but then the parameter becomes final (constant).
If you want to be able to reassign the value you should use var instead. So
class Point(var x: Int, var y: Int)