I'm trying to create 2 protocols ArithmeticType and MathematicType that will be used in where clauses of generic operator functions
protocol ArithmeticType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
}
extension Int : ArithmeticType {
}
extension Double : ArithmeticType {
}
extension Float : ArithmeticType {
}
ArithmeticType works as expected and either Int, Float and Double conform to it. However the following fails
import Darwin
protocol MathematicType {
func sin(x: Self) -> Self
}
extension Double : MathematicType {
}
extension Float : MathematicType {
}
on console output of the playground I read:
Playground execution failed: <EXPR>:35:1: error: type 'Double' does not conform to protocol 'MathematicType'
extension Double : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Double -> Self'
func sin(x: Self) -> Self
^
<EXPR>:39:1: error: type 'Float' does not conform to protocol 'MathematicType'
extension Float : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Float -> Self'
func sin(x: Self) -> Self
^
I would like that math functions behave like the operators above. Is there any way?
== EDIT:
Now I realize that trying to simplify my question was a bad idea. the context is this class (vector of optional values)
class Vector<T> {
var data=[T?]()
init(fromArray: Array<T>) {
for i in fromArray {
data.append(i)
}
}
init() {
}
init(count: Int){
for i in 0..<count {
data.append(nil)
}
}
init(count: Int, repeatedValue: T) {
for i in 0..<count {
data.append(repeatedValue)
}
}
func count() -> Int {
return data.count
}
func append(newElement: T?) {
data.append(newElement)
}
subscript(index: Int) -> T? {
let i = index>0 ? index % count() : -index % count()
return data[i]
}
}
outside of it I defined a generic function for the + operator
func +<T where T: ArithmeticType>(left: Vector<T>, right: Vector<T>) -> Vector<T> {
let resultCount = max(left.count(),right.count())
var result = Vector<T>()
for i in 0..<resultCount {
if left[i] != nil && right[i] != nil {
result.append(left[i]!+right[i]!)
}
else {
result.append(nil)
}
}
return result
}
that works as expected, however when I tried to define a generic sin function as
func sin<T where T : FloatingPointType>(x: Vector<T>) -> Vector<T>{
var result = Vector<T>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(sin(o))
}
else {
result.append(nil)
}
}
return result
}
I got "could not find an overload of sin that accepts the supplied arguments"
then my attempt with MathemticType trying to mimic what I already done for + operator
(ArithmeticType was inspired from IntegerAritmeticType source found by command clicking on import swift more than my knowledge of what I was doing)
== UPDATE
If I write a specialized function only for Double
func sin(x: Vector<Double>) -> Vector<Double>{
var result = Vector<Double>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(Darwin.sin(o))
}
else {
result.append(nil)
}
}
return result
}
it works as expected.
So the question may become "How can I generalize this to either Double and Float" ?
The compiler error is because you declared sin() as a method of the MathematicType protocol, and then declared that Double implements MathematicType, but didn't actually write the sin() method.
extension Double {
func sin(x: Double) -> Double {
return Darwin.sin(x)
}
}
I don't think that's what you want, though, is it? You want to be able to write this:
let myAngle = 3.14159
let sineValue = myAngle.sin()
If that's the case, your protocol and extension would need to look like this:
protocol MathematicType {
func sin() -> Self
}
extension Double : MathematicType {
func sin() -> Double {
return Darwin.sin(self)
}
}
Your MathematicType protocol, and your declarations of conformance to it in Float and Double extensions, say that Float and Double should provide sin as an instance method. That is, you're saying one should be able to write code like:
let zero = 0.0 // inferred type Double
zero.sin(1.5707963268) // returns about 1.0
Notice that invocation of sin isn't actually related to the value of zero, so this probably isn't the behavior you want.
You're probably looking to have sin be a free function, so you can just write:
sin(1.5707963268)
Right?
In that case, your work is already done... the standard library defines both:
func sin(x: Double) -> Double
func sin(x: Float) -> Float
If what you actually want is for your MathematicType to be usable as a generic parameter, meaning "a type you can take the sine of", you'll need a generic sin function. Something like this (quick kludgy solution, there's probably better):
func sine<T: FloatingPointType>(x: T) -> T {
if let v = x as? Double {
return sin(v) as T
}
if let v = x as? Float {
return sin(v) as T
}
fatalError("unknown FloatingPointType")
}
(Notice also that there's already a protocol that both Float and Double conform to, so I've used that in the example.)
I think the issue is that operator requirements and instance method requirements are different, even though they syntactically look similar. Operators are always defined at the global level, so an operator requirement is a requirement on an operator at the global level. On the other hand, instance method requirements are requirements on instance methods. There is no way to specify a global function requirement.
Related
I'm writing a algorithm testbench to compare performance in Rust.
I want to store a bunch of function for an algorithm in a struct, and apply those functions to some data.
When I call the function by reference, which stored in the struct, I couldn't figure out the lifetime.
struct Alg<'a, 'b, 'c> {
alg1: &'c Fn(&'a A<'a>, &'b B<'b>) -> usize,
alg2: &'c Fn(&'a A<'a>, &'b B<'b>) -> String,
}
struct A<'a> {
a_str: &'a str,
}
struct B<'b> {
b_str: &'b str,
}
fn concat<'a, 'b>(_a: &'a A<'a>, _b: &'b B<'b>) -> String {
_a.a_str.to_string() + &_b.b_str.to_string()
}
fn length<'a, 'b>(_a: &'a A<'a>, _b: &'b B<'b>) -> usize {
_a.a_str.len() + _b.b_str.len()
}
fn run1<'a, 'b, 'c>(_a: &'a A<'a>, _b: &'b B<'b>, _f_c: &'c Alg<'a, 'b, 'c>) {
println!("{}", &(_f_c.alg1)(_a, _b));
}
fn run2<'a, 'b, 'c>(_a: &'a A<'a>, _b: &'b B<'b>, _f_c: &'c Alg<'a, 'b, 'c>) {
println!("{}", &(_f_c.alg2)(_a, _b));
}
fn main() {
let f_struct = Alg {
alg1: &length,
alg2: &concat,
};
for _i in 0..2 {
let a_str = "ABC";
let a = A { a_str: a_str };
for _j in 0..2 {
let b_str = "BCD";
let b = B { b_str: b_str };
println!("{}", concat(&a, &b)); // This works
println!("{}", (f_struct.alg1)(&a, &b)); // I expect that `concat` or `length` in `f_struct` may finished borrowing `a` or `b' here, as like as `println!("{}",concat(&a,&b))`
//run1(&a,&b,&f_struct);
//run2(&a,&b,&f_struct);
}
}
}
When I run this, I get an error message like:
error[E0597]: `a` does not live long enough
--> src/main.rs:43:44
|
43 | println!("{}", (f_struct.alg1)(&a, &b)); // I expect that `concat` or `length` in `f_struct` may finished borrowing `a` or `b' here, as like as `println!("{}",concat(&a,&b))`
| --------------- ^^ borrowed value does not live long enough
| |
| borrow used here, in later iteration of loop
...
47 | }
| - `a` dropped here while still borrowed
error[E0597]: `b` does not live long enough
--> src/main.rs:43:48
|
43 | println!("{}", (f_struct.alg1)(&a, &b)); // I expect that `concat` or `length` in `f_struct` may finished borrowing `a` or `b' here, as like as `println!("{}",concat(&a,&b))`
| --------------- ^^ borrowed value does not live long enough
| |
| borrow used here, in later iteration of loop
...
46 | }
| - `b` dropped here while still borrowed
What is the difference between println!("{}",concat(&a,&b)) and println!("{}",(f_struct.alg1)(&a,&b))?
I thought that I have to indicate something that the function no more borrows the value with lifetime 'a or 'b, but I couldn't find it from rust-by-example or rust-book.
I've tried to apply coercion like 'c: 'a + 'b, but this seems not to help.
These questions are related, but not so clear to me.
Rust lifetime error
Rust lifetime error expected concrete lifetime but found bound lifetime
Questions about Rust lifetime
Point
I want to store functions in the struct
I could try another way like not to store functions in the struct
But I want to understand the reason when this approach is impossible
Quick solution
You have too many lifetime specifiers. Remove the lifetimes for references in your function parameters. Eg. replace alg1: &'c Fn(&'a A<'a>, &'b B<'b>) -> usize with alg1: &'c Fn(&A<'a>, &B<'b>) -> usize (and similar changes to all functions (playground).
Explanation
First, let's simplify your code a bit and rename some of the lifetimes so that we know which one we are talking about:
struct Alg<'Alg_a, 'Alg_b> {
alg1: &'Alg_b Fn(&'Alg_a A<'Alg_a>) -> usize,
}
struct A<'A_a> {
a_str: &'A_a str,
}
fn length<'L_a>(a: &'L_a A<'L_a>) -> usize {
a.a_str.len()
}
fn main() {
let f_struct = Alg {
alg1: &length,
};
for _i in 0..2 {
let a_str = "ABC";
let a = A { a_str: a_str };
println!("{}", length (&a)); // This works
println!("{}", (f_struct.alg1) (&a)); // This doesn't
}
}
You can check on the playground that this exhibits the same error as your code.
When you call (f_struct.alg1)(&a), the compiler tries to find good values for the lifetimes 'Alg_a and 'Alg_b associated with f_struct. Since f_struct is defined outside the loop, then those lifetimes must be the same for all iterations of the loop. However Alg::alg1 is defined as Fn(&'Alg_a …) which means that 'Alg_a must be the lifetime of the parameter a which is only valid for a single loop iteration. Hence the error.
By not specifying the lifetime of the parameter, I allow the compiler to choose different lifetimes for the parameter a and for 'Alg_a, and in particular to choose a different lifetime for the parameter each time the function is called. So the lifetime for the parameter can be limited to a single loop iteration while 'Alg_a may be longer:
struct Alg<'Alg_a, 'Alg_b> {
alg1: &'Alg_b Fn(&A<'Alg_a>) -> usize,
}
struct A<'A_a> {
a_str: &'A_a str,
}
fn length<'L_a>(a: &A<'L_a>) -> usize {
a.a_str.len()
}
fn main() {
let f_struct = Alg {
alg1: &length,
};
for _i in 0..2 {
let a_str = "ABC";
let a = A { a_str: a_str };
println!("{}", length (&a)); // This works
println!("{}", (f_struct.alg1) (&a)); // Now this does too
}
}
playground
Why does calling length directly work?
When calling length directly, the compiler only needs to determine the lifetime 'L_a and there is nothing that requires this lifetime to last for more than a single loop iteration, so there is no conflict.
Note
As noted by #VikramFugro, this only work because a_str = "ABC" creates a slice with a 'static lifetime which can be shrunk down to 'Alg_a or 'L_a as required. Using a dynamic string (let a_str = String::from("ABC")) does not work. We need to declare alg1 as &'Alg_b for<'F_a> Fn(&A<'F_a>) -> usize instead of using the 'Alg_a lifetime on the Alg struct:
struct Alg<'Alg_b> {
alg1: &'Alg_b for<'F_a> Fn(&A<'F_a>) -> usize,
}
playground
Additionally, Rust 2018 allows us to use an anonymous lifetime '_ instead of the for<'a> … syntax, for example &'Alg_b Fn(&A<'_>) -> usize (playground).
I'm using 1.6.0 (stable), but any future/nightly feature that enables this or that I can watch/track is cool too.
what I'd like in theory (simplified for brevity):
let a:fn(&lib_plotMote::mask::Mask) -> bool = {fn(_)->true};
the closest I've gotten:
let a:fn(&lib_plotMote::mask::Mask) -> bool = { fn anon(_:&Mask)->bool{true}; anon };
No.
Closures are the "anonymous function" feature of Rust.
That said, you can slightly reduce the redundancy in what you have:
let a: fn(_) -> _ = { fn anon(_: &Mask) -> bool { true }; anon };
Here is an example:
use std::iter::Filter;
use std::slice::Iter;
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing);
ys
}
fn main () {
}
Compilation fails with:
src/main.rs:8:5: 8:7 error: mismatched types:
expected `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool>`,
found `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool {test1::nothing}>`
(expected fn pointer,
found fn item) [E0308]
src/main.rs:8 ys
^~
This is because the inferred type of ys has the type of a specific function item in it. In this particular case the issue is easy to fix: one can either explicitly specify the type without the function item in the binding, or avoid the let altogether.
Both of these work:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys: Filter<Iter<i32>, fn(&&i32) -> bool> = xs.iter().filter(nothing);
ys
}
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
xs.iter().filter(nothing)
}
Therefore, as the Reference says, indeed Rust is capable of performing this coercion itself. But what if the code was more complex and I had to perform this cast manually? How would I do this?
In this case as won’t work, and transmute seems to be an overkill, although, I believe, it would do the job.
You can actually cast using as:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing as fn(&&i32) -> bool);
^~~~~~~~~~~~~~~~~~~~
ys
}
However you need to use as to change the function's type, not the Filter type, as as is not allowed to change arbitrary types.
Personally, I consider the necessity of the cast a short-coming and hope that type inference will improve to the point it becomes unnecessary. The fact that it works for a direct return is a red-herring, it should probably work with an intermediate value too.
I thought closures and functions are same thing. But when referencing to a property inside local function compiler doesn't require self. But inside closure it requires to write self. What i mean is why this two things are different?
The sample code for clarity:
class Foo {
let bar = "bar"
func baz() {
func localBaz() {
println(bar) // No complain from compiler.
}
let bazClosure = {
println(self.bar) // Here if I write just println(bar), compiler complains.
}
}
}
You expectation is wrong - functions and closures in Swift are not the same thing. A func essentially sets up a lazy var binding with a [unowned self] declaration. Thus, if you want to get rid of func you could transform the following:
class Foo {
let bar = "bar"
// this is not your 'baz'; just an example
func baz () { println (bar) }
}
}
as
class Foo {
let bar = "bar"
lazy var baz = { [unowned self] in println (self.bar) }
}
You can see that func is doing more than just a closure.
Furthermore, and importantly, func sets up a recursive binding environment which allows the body of func bar to reference bar. Thus you can write:
1> class Foo {
2. func fact (x:Int) -> Int {
3. if 1 == x { return x }
4. else { return x * fact (x - 1) }}
5. }
6> Foo().fact(5)
$R0: (Int) = 120
but not
7> class Foo {
8. lazy var fact = { (x:Int) -> Int in
9. if 1 == x { return x }
10. else { return x * fact (x - 1) }}}
repl.swift:10:27: error: variable used within its own initial value
else { return x * fact (x - 1) }}}
^
Indeed, I do not know why closure need self in swift to access instance properties but let's think about it.
Your baz() is a class function, I mean it belongs to the class Foo and the closure like a external function. In Objective-C all class function actually need a self argument to invoke that function.
Therefore a closure need a self pointer (or something named self reference the instance of Foo) to access its property.
I'm trying to write some helper functions and am getting an 'Invalid Redeclaration' error of some similar methods. If anyone can explain why these methods collide I would be very thankful.
func CGRectModify(rect: CGRect, x: CGFloat) -> CGRect {
return CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height)
}
func CGRectModify(rect: CGRect, y: CGFloat) -> CGRect {
return CGRectMake(rect.origin.x, y, rect.size.width, rect.size.height)
}
func CGRectModify(rect: CGRect, width: CGFloat) -> CGRect {
return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height)
}
func CGRectModify(rect: CGRect, height: CGFloat) -> CGRect {
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height)
}
I would think that because the second parameter has a different external name, the method would be understood to have a different signature. It seems that is not the case.
I've been using Apple's doc for reference, but in the section of Local and External Parameter Names for Methods I could not find my answer. Any input is much appreciated.
The rule of "automatic external parameter names" for functions are different from methods.
Swift applies different rules depends on the type of callables.
Functions/Closures → document
No "automatic external parameter names" are performed.
func f(x:Int, y:Int) { /* ... */ }
let c = { (x:Int, y:Int) -> Void in /* ... */ }
f(1, 2)
c(1, 2)
Initializers → document
"automatic external parameter names" are the default for every parameters.
class Foo {
init(x:Int, y:Int) { /* ... */ }
}
let foo = Foo(x: 1, y: 2)
Methods → document
"automatic external parameter names" except for the first parameter.
extension Foo {
func bar(x:Int, y:Int) { /* ... */ }
}
foo.bar(1, y:2)
Subscript → document missing?
No "automatic external parameter names" are performed.
extension Foo {
subscript(x:Int, y:Int) -> Void {
get { /* ... */ }
}
}
foo[1, 2]
And a special rule for ...
Default Values
func fz(x:Int, y:Int, z:Int = 1) { /* ... */ }
fz(1, 1, z: 1)
Of course you can override these default behaviors using:
_ name:Type: disable "automatic external parameter names"
#name:Type: force "automatic external parameter names"
externalName internalName:Type: explicit external name
This actually looks like a bug in the documentation. In the section I originally linked to, Local and External Parameter Names for Methods the follow explanation is written.
This default behavior effectively treats the method as if you had written a hash symbol (#) before the numberOfTimes parameter:
func incrementBy(amount: Int, #numberOfTimes: Int) {
count += amount * numberOfTimes
}
This is not the case. When I do add the hash symbol (#) to my second parameter, the compiler error does not occur.
func CGRectModify(rect: CGRect, #height: CGFloat) -> CGRect {
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height)
}