I have this function in swift
func *<T1:Sequence, T2:Sequence>(lhs: T1,rhs : T2) ->
[(T1.Iterator.Element,T2.Iterator.Element)]
{
let product = lhs.flatMap({ x in rhs.lazy.map{y in (x,y)}})
return product
}
I want to make it evaluate lazy. I know i can use lhs.lazy.flatmap but what should the return type be? Or is there a better or other way to do something like this?
You can create a type-erased sequence, which forward its operations to an underlying base
sequence having the same Element type, hiding the specifics of the
underlying sequence:
func *<T1:Sequence, T2:Sequence>(lhs: T1,rhs : T2) -> AnySequence<(T1.Iterator.Element,T2.Iterator.Element)>
{
return AnySequence (
lhs.lazy.flatMap { x in rhs.lazy.map { y in (x,y) }}
)
}
Then your code is independent of the actual implementation of lazy.flatMap and its exact return type (which may even change with
newer Swift releases).
Thanks to Alexander I came up with
func *<T1:Sequence, T2:Sequence>(lhs: T1,rhs : T2) ->
LazySequence<FlattenSequence<LazyMapSequence<T1,
LazyMapSequence<T2, (T1.Iterator.Element, T2.Iterator.Element)>>>> {
let product = lhs.lazy.flatMap({ x in rhs.lazy.map{y in (x,y)}})
print(type(of:product))
return product
}
That works but somehow that return type seems a bit to much for my taste.
Related
In the Introduction to Swift WWDC session, a read-only property description is demonstrated:
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description)
Are there any implications to choosing the above approach over using a method instead:
class Vehicle {
var numberOfWheels = 0
func description() -> String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description())
It seems to me that the most obvious reasons for choosing a read-only computed property are:
Semantics - in this example it makes sense for description to be a property of the class, rather than an action it performs.
Brevity/Clarity - prevents the need to use empty parentheses when getting the value.
Clearly the above example is overly simple, but are there other good reasons to choose one over the other? For example, are there some features of functions or properties that would guide your decision of which to use?
N.B. At first glance this seems like quite a common OOP question, but I'm keen to know of any Swift-specific features that would guide best practice when using this language.
It seems to me that it's mostly a matter of style: I strongly prefer using properties for just that: properties; meaning simple values that you can get and/or set. I use functions (or methods) when actual work is being done. Maybe something has to be computed or read from disk or from a database: In this case I use a function, even when only a simple value is returned. That way I can easily see whether a call is cheap (properties) or possibly expensive (functions).
We will probably get more clarity when Apple publishes some Swift coding conventions.
Well, you can apply Kotlin 's advices https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties.
In some cases functions with no arguments might be interchangeable
with read-only properties. Although the semantics are similar, there
are some stylistic conventions on when to prefer one to another.
Prefer a property over a function when the underlying algorithm:
does not throw
complexity is cheap to calculate (or caсhed
on the first run)
returns the same result over invocations
While a question of computed properties vs methods in general is hard and subjective, currently there is one important argument in the Swift's case for preferring methods over properties. You can use methods in Swift as pure functions which is not true for properties (as of Swift 2.0 beta). This makes methods much more powerful and useful since they can participate in functional composition.
func fflat<A, R>(f: (A) -> () -> (R)) -> (A) -> (R) {
return { f($0)() }
}
func fnot<A>(f: (A) -> Bool) -> (A) -> (Bool) {
return { !f($0) }
}
extension String {
func isEmptyAsFunc() -> Bool {
return isEmpty
}
}
let strings = ["Hello", "", "world"]
strings.filter(fnot(fflat(String.isEmptyAsFunc)))
There is a difference:
If you use a property you can then eventually override it and make it read/write in a subclass.
Since the runtime is the same, this question applies to Objective-C as well. I'd say, with properties you get
a possibility of adding a setter in a subclass, making the property readwrite
an ability to use KVO/didSet for change notifications
more generally, you can pass property to methods that expect key paths, e.g. fetch request sorting
As for something specific to Swift, the only example I have is that you can use #lazy for a property.
In the read-only case, a computed property should not be considered semantically equivalent to a method, even when they behave identically, because dropping the func declaration blurs the distinction between quantities that comprise the state of an instance and quantities that are merely functions of the state. You save typing () at the call site, but risk losing clarity in your code.
As a trivial example, consider the following vector type:
struct Vector {
let x, y: Double
func length() -> Double {
return sqrt(x*x + y*y)
}
}
By declaring the length as a method, it’s clear that it’s a function of the state, which depends only on x and y.
On the other hand, if you were to express length as a computed property
struct VectorWithLengthAsProperty {
let x, y: Double
var length: Double {
return sqrt(x*x + y*y)
}
}
then when you dot-tab-complete in your IDE on an instance of VectorWithLengthAsProperty, it would look as if x, y, length were properties on an equal footing, which is conceptually incorrect.
From the performance perspective, there seems no difference. As you can see in the benchmark result.
gist
main.swift code snippet:
import Foundation
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)
Output:
prop: 0.0380070209503174
func: 0.0350250005722046
prop: 0.371925950050354
func: 0.363085985183716
prop: 3.4023300409317
func: 3.38373708724976
prop: 33.5842199325562
func: 34.8433820009232
Program ended with exit code: 0
In Chart:
There are situations where you would prefer computed property over normal functions. Such as: returning the full name of an person. You already know the first name and the last name. So really the fullName property is a property not a function. In this case, it is computed property (because you can't set the full name, you can just extract it using the firstname and the lastname)
class Person{
let firstName: String
let lastName: String
init(firstName: String, lastName: String){
self.firstName = firstName
self.lastName = lastName
}
var fullName :String{
return firstName+" "+lastName
}
}
let william = Person(firstName: "William", lastName: "Kinaan")
william.fullName //William Kinaan
Semantically speaking, computed properties should be tightly coupled with the intrinsic state of the object - if other properties don't change, then querying the computed property at different times should give the same output (comparable via == or ===) - similar to calling a pure function on that object.
Methods on the other hand come out of the box with the assumption that we might not always get the same results, because Swift doesn't have a way to mark functions as pure. Also, methods in OOP are considered actions, which means that executing them might result in side effects. If the method has no side effects, then it can safely be converted to a computed property.
Note that both of the above statements are purely from a semantic perspective, as it might well happen for computed properties to have side effects that we don't expect, and methods to be pure.
Historically description is a property on NSObject and many would expect that it continues the same in Swift. Adding parens after it will only add confusion.
EDIT:
After furious downvoting I have to clarify something - if it is accessed via dot syntax, it can be considered a property. It doesn't matter what's under the hood. You can't access usual methods with dot syntax.
Besides, calling this property did not require extra parens, like in the case of Swift, which may lead to confusion.
An updated/fixed version of Benjamin Wen's answer incorporating Cristik's suggestion.
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.prop
}
let ending = CACurrentMediaTime()
return ending - starting
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.foo()
}
let ending = CACurrentMediaTime()
return ending - starting
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)
I am a beginner in Swift so some things aren't quite clear to me yet. I hope somebody would explain this to me:
// Creating Type Properties and Type Methods
class BankAccount {
// stored properties
let accountNumber: Int
let routingCode = 12345678
var balance: Double
class var interestRate: Float {
return 2.0
}
init(num: Int, initialBalance: Double) {
accountNumber = num
balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) -> Bool {
if balance > amount {
balance -= amount
return true
} else {
println("Insufficient funds")
return false
}
}
class func example() {
// Type methods CANNOT access instance data
println("Interest rate is \(interestRate)")
}
}
var firstAccount = BankAccount(num: 11221122, initialBalance: 1000.0)
var secondAccount = BankAccount(num: 22113322, initialBalance: 4543.54)
BankAccount.interestRate
firstAccount.deposit(520)
So this is the code. I am wondering why deposit() doesn't have a return arrow and return keyword and withdraw() does. When do I use a return arrow, in what situations, is there a rule or something? I don't understand.
In addition...
Everyone is so kind with your answers, it is getting clearer to me now.
In beginning of this tutorial there is practice code for functions
// Function that return values
func myFunction() -> String {
return “Hello”
}
I imagine this return value is not needed here but in tutorial they wanted to show us that it exists, am I right?
Furthermore, can I make a "mistake" and use return arrow and value in my deposit function somehow? I tried with this:
func deposit(amount : Double) -> Double {
return balance += amount
}
... but it generated error.
I saw advanced coding in my last firm, they were creating online shop with many custom and cool features and all code was full of return arrows. That confused me and I thought that it is a default for making methods/functions in OOP.
Additional question!
I wanted to play with functions so I want to create a function transferFunds() which transfers money from one account to another. I made function like this
func transferFunds(firstAcc : Int, secondAcc : Int, funds : Double) {
// magic part
if firstAcc == firstAccount.accountNumber {
firstAccount.balance -= funds
} else {
println("Invalid account number! Try again.")
}
if secondAcc == secondAccount.accountNumber {
secondAccount.balance += funds
} else {
println("Invalid account number! Try again.")
}
}
This is a simple code that came to my mind but I know it is maybe even stupid. I know there should be a code that check if there is enough funds in first account from which I am taking money, but okay... Lets play with this.
I want to specify accountNumbers or something else in parameters within function transferFunds() and I want to search through all objects/clients in my imaginary bank which use class BankAccount in order to find one and then transfer money. I don't know if I described my problem correctly but I hope you understand what I want to do. Can somebody help me, please?
So in Swift, a function that has no arrow has a return type of Void:
func funcWithNoReturnType() {
//I don't return anything, but I still can return to jump out of the function
}
This could be rewritten as:
func funcWithNoReturnType() -> Void {
//I don't return anything, but I still can return to jump out of the function
}
so in your case...
func deposit(amount : Double) {
balance += amount
}
your method deposit takes a single parameter of Type Double and this returns nothing, which is exactly why you do not see a return statement in your method declaration. This method is simply adding, or depositing more money into your account, where no return statement is needed.
However, onto your withdraw method:
func withdraw(amount : Double) -> Bool {
if balance > amount {
balance -= amount
return true
} else {
println("Insufficient funds")
return false
}
}
This method takes a single parameter of Type Double, and returns a Boolean. In regard to your withdraw method, if your balance is less than the amount you're trying to withdraw (amount), then that's not possible, which is why it returns false, but if you do have enough money in your account, it gracefully withdraws the money, and returns true, to act as if the operation was successful.
I hope this clears up a little bit of what you were confused on.
Welcome to programming! Good questions, stick with it and you'll do well.
The functions that have a return value are providing the calling code with information. For example, for the deposit function, there is the expectation that nothing unusual will happen, so it's not bothering to return anything that could be checked by the caller.
In the withdrawal function, it's possible that the amount to be withdrawn could be greater than the balance available. If this is the case, the function will return false. The calling function could check that value and notify the user that they're attempting to withdraw more than is available. Otoh, if a value of true is returned, then the program will deduct that amount from the balance and presumably provide the customer with the funds requested.
Check out Function Parameters and Return Values in the Swift docs:
Functions are not required to define a return type. Here’s a version of the sayHello function, called sayGoodbye, which prints its own String value rather than returning it:
func sayGoodbye(personName: String) {
println("Goodbye, \(personName)!")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"
Because it does not need to return a value, the function’s definition does not include the return arrow (->) or a return type.
In your example, deposit(_:) doesn't return anything, it just modifies an instance variable. This is typical of functions which will always succeed.
withdraw(:_), on the other hand, might fail (due to insufficient funds), so it returns a Bool indicating whether it worked or not.
This question can be referred as a language-agnostic one, so be my answer to you.
A method is a code block that contains a series of statements. Methods can return a value to the caller, but doesn't have to do so. It is the decision of you as the developer. Method that returns a value to the caller will consist the keyword: "return", and a value type declared in the method signature.
I would mention the Command Query Separation (CQS) principle coined by Bertrand Meyer. Martin Fowler rephrased: The fundamental idea is that we should divide an object's methods into two sharply separated categories:
Queries: Return a result and do not change the observable state of
the system (are free of side effects). Mark Seemann said queries do not mutate observable state. They are idempotent and safe to invoke.
Commands: Change the state of a system but do not return a value. You can, and it is safe to invoke queries from commands, but not vice versa.
Source: https://thenucleargeeks.com/2019/05/08/functions-in-swift/
In swift a function is defined by “func” keyword. When a function is declared based on requirement it may take one or more parameter, process it and return the valueFunction with no parameters and no return value.
Function with no parameter and no return type.
Syntax:
func function_name() {
--
}
func addTwoNumbers() {
let a = 1
let b = 2
let c = a+b
print(c) // 3
}
addTwoNumbers()
Function with no parameter and return type
Syntax:
func function_name() -> Data Type {
--
return some values
}
func addTwoNumbers()->Int {
let a = 1
let b = 2
let c = a+b
return c
}
let sum = addTwoNumbers()
print(sum) // 3
Function with parameter and return type
Syntax:
func function_name(arguments parameter_name: Data Type) -> Data Type {
------
return some values
}
func addTwoNumbers(arg param: Int)->Int {
let a = param
let b = 2
let c = a+b
return c
}
let sum = addTwoNumbers(arg: 4)
print(sum) // 6
Alternately you can skip the arg and directly pass the value to the function.
func addTwoNumbers(param: Int)->Int {
let a = param
let b = 2
let c = a+b
return c
}
let sum = addTwoNumbers(param: 4)
print(sum) // 6
Function with parameter and no return type
Syntax:
func function_name(arguments parameter_name: Data Type) {
----
return some values
}
func addTwoNumbers(arg param: Int){
let a = param
let b = 2
let c = a+b
print(c) //6
}
addTwoNumbers(arg: 4)
I am writing a library that creates extensions for default Swift types.
I would like to have a check on my Array extensions whether a certain type implements a certain protocol. See this method for example:
extension Array {
/// Compares the items using the given comparer and only returns non-equal values
/// :returns: the first items that are unique according to the comparer
func distinct(comparer: (T, T) -> Bool) -> [T] {
var result: [T] = []
outerLoop: for item in self {
for resultItem in result {
if comparer(item, resultItem) {
continue outerLoop
}
}
result.append(item)
}
return result
}
}
Now I'd like to rewrite this method to check if T is Equatable as such:
/// Compares the items using the given comparer and only returns non-equal values
/// :returns: the first items that are unique according to the comparer
func distinct(comparer: ((T, T) -> Bool)?) -> [T] {
var result: [T] = []
outerLoop: for item in self {
for resultItem in result {
if isEquatable ? comparer!(item, resultItem) : item == resultItem {
continue outerLoop
}
}
result.append(item)
}
return result
}
where isEquatable is a Bool value that tells me if T is Equatable. How can I find this out?
There isn’t a good way to do this in Swift at the moment.* This is why functions like sorted are either free-functions, or in the case of the member, take a predicate. The main problem with the test-and-cast approach you’re looking for is that Equatable and similar protocols have an associated type or rely on Self, and so can only be used inside a generic function as a constraint.
I’m guessing your goal is that the caller can skip supplying the comparator function, and so it will fall back to Equatable if available? And crash if it isn’t? The problem here is that the function is determining something at run time (the argument is Equatable) when this really ought to be determinable at compile time. This is not great - it’s much better to determine these things fully at compile time.
So you can write a free function that requires Equatable:
func distinct<C: CollectionType where C.Generator.Element: Equatable>
(source: C) -> [C.Generator.Element] {
var seen: [C.Generator.Element] = []
return filter(source) {
if contains(seen, $0) {
return false
}
else {
seen.append($0)
return true
}
}
}
let uniques = distinct([1,2,3,1,1,2]) // [1,2,3]
and then if you tried to call it with something that wasn’t comparable, you’d get a compile-time error:
let incomparable = [1,2,3] as [Any]
distinct(incomparable) // compiler barfs - Any isn’t Equatable
With the runtime approach, you’d only find this out when you ran the program.
The good news is, there are upsides too. The problem with searching an array for each element is the function will be very slow for large arrays, because for every element, the list of already-seen elements must be searched linearly. If you overload distinct with another version that requires the elements be Hashable (which Equatable things often are), you can use a set to track them:
func distinct<C: CollectionType where C.Generator.Element: Hashable>
(source: C) -> [C.Generator.Element] {
var seen: Set<C.Generator.Element> = []
return filter(source) {
if seen.contains($0) {
return false
}
else {
seen.insert($0)
return true
}
}
}
At compile time, the compiler will choose the best possible version of the function and use that. If your thing is hashable, that version gets picked, if it’s only equatable, it’ll use the slower one (this is because Hashable inherits from Equatable, and the compiler picks the more specialized function). Doing this at compile time instead of run time means you pay no penalty for the check, it’s all determined up front.
*there are ugly ways, but since the goal is appealing syntax, what’s the point… Perhaps the next version will allow constraints on methods, which would be nice.
I would like to implement some code so that I can call something like:
NSUserDefaults("key1", "value1")
let s = NSUserDefaults("key1") // "value1" expected
NSUserDefaults("key2", 2.01)
let s = NSUserDefaults("key2") // 2.01 expected
I have some code in concept as below, but obviously it's not going to work. So my question is, instead of writing a series of functions like class func bool(key: String, _ v: Bool? = nil) -> Bool? is there any way to take the advantage of generic please?
extension NSUserDefaults {
class func object<T: AnyObject>(key: String, _ v: T? = nil) -> T? {
if let obj: T = v {
NSUserDefaults.standardUserDefaults().setObject(obj, forKey: key)
NSUserDefaults.standardUserDefaults().synchronize()
} else {
return NSUserDefaults.standardUserDefaults().objectForKey(key) as T?
}
return v
}
}
Your syntax is going to wind up being very poor. This line can't work as written:
let s = NSUserDefaults("key1") // "value1" expected
Swift has to pick a type for s at compile time, not run time. So the only type it can assign here is Any (not even AnyObject is expansive enough if you want to return Double since Double is not AnyObject).
That means you have to explicitly call out let s : Any = ... (because Swift wisely won't let you create Any implicitly), and then you're going to wind up with an Any that you have to type-check somehow. When you're done, you're going to come full circle to objectForKey().
Even if you could get this syntax working, you shouldn't try to overload a single function syntax to do opposite things. That's very confusing. If you were going to build an extension like this, you should probably make it a subscript. That way you'd say defaults["key1"] and defaults["key2"] = 2.01. That's something may be able to build (though there will still be type annotation headaches required to deal with AnyObject?).
How can I make the RemoveDead function accept other slices of interfaces (or maybe even slices of struct pointers) that implement Liver with little impact on performance?
It seems to me that the function would have to take an interface{} as argument and do runtime conversions, but I'm not sure how to do the conversions. I would also guess that doing x.(Liver) is a lot slower than Liver(x), because the latter is a compile time conversion.
Is the best solution to copy-paste the function and change the argument and return type in each copy? Only three or four copies would be needed, but it would still feel like a very clumsy solution.
type Updater interface {
Liver
Update() bool
}
type Liver interface {
Alive() bool
}
func RemoveDead(all []Updater) []Updater {
for i := len(all) - 1; i >= 0; i-- {
if Liver(all[i]).Alive() == false {
all[i] = all[len(all)-1]
all = all[:len(all)-1]
}
}
return all
}
As you mentioned, a slice of type []Updater cannot be turned to a []Liver with a simple type assertion; their type are not interfaces, but slices of interfaces. For the same reason is it not possible to pass a []Updater to a function wanting an []interface{} as parameter.
However, you can do what you desire using the reflect package. Reflection is useful but will come at a cost on performance. If you consider the cost to high, then you will probably have to use the copy-paste solution.
The code below can surely be improved, but it shows how to solve the problem with reflection, and it might be useful when making a benchmark. Currently it regards any even U value as Alive:
package main
import (
"fmt"
"reflect"
)
type Updater interface {
Alive() bool
Update() bool
}
type Liver interface {
Alive() bool
}
type U int
func (u U) Alive() bool { return u % 2 == 0 }
func RemoveDead(all interface{}) interface{} {
v := reflect.ValueOf(all)
if v.Kind() != reflect.Slice {
panic("RemoveDead requires a slice")
}
for i := v.Len() - 1; i >= 0; i-- {
l := v.Index(i)
if l.Interface().(Liver).Alive() == false {
l.Set(v.Index(v.Len()-1))
v = v.Slice(0, v.Len()-1)
}
}
return v.Interface()
}
func main() {
u := []U{1,4,7,2,12}
fmt.Println("Before: ", u)
u = RemoveDead(u).([]U)
fmt.Println("After: ", u)
}
Output:
Before: [1 4 7 2 12]
After: [2 4 12]
Playground
You could define third interface:
type UpdaterLiver interface {
Updater
Liver
}
then change definition of RemoveDead to be
func RemoveDead(all []UpdaterLiver) []UpdaterLiver