Are instance methods closures? - ios

In the book, "Swift Programming Language 3.0", it mentioned that types of closure include:
Global functions are closures that have a name and do not capture
any values
Nested function are closures that have a name and can
capture values from their enclosing function
Closure expression are
unnamed closure written in a lightweight syntax that can capture
values from their surrounding context
I was just wondering does a function that exist in class scope count as a closure? One can certainly pass around such function as an argument to other function, but is it a closure?

Yes! Absolutely! Here's an example that uses the lowercased() method of String.
let aClosure: (String) -> () -> String = String.lowercased
let anUpperCasedString = "A B C"
print(anUpperCasedString)
let aLowerCaseString = aClosure(anUpperCasedString)()
print(aLowerCaseString)
You can see that the type of this closure is (String) -> () -> String. This is because String.lowercased is completely unapplied, it has no clue what instance it's operating on.
Calling aClosure(anUpperCasedString) will return a closure that's now () -> String. Baked into it is the instance it'll operate on. Only when you call this new closure with no params (()), will it actually execute the body of lowercased(), operating on the instance you gave it in the previous step, and return you the String result.
As a consequence, this is also valid:
let aLowerCaseString = String.lowercased("QWERTY")()
It just does all the steps above in one inlined step.
This technique is called function currying. This post talks more about this technique (called function currying) as it applies to instance methods in Swift.

Related

F# - How to defining multiple generic functions together

OK:
let em inp=sprintf"<em>%A</em>"inp
let bold inp=sprintf"<b>%A</b>"inp
printfn"%s"<|em"blabla"///<em>blabla</em>
Trying to define together (with compiling error):
let em2,bold2=
let tag a b=sprintf"<%s>%A</%s>"a b a
(fun inp->tag"em"inp),tag"b"
Error:
Value restriction. The value 'em2' has been inferred to have generic type
val em2 : ('_a -> string -> string)
Either make the arguments to 'em2' explicit or, if you do not intend for it to be generic, add a type annotation.F# Compiler(30)
I don't think this is going to work, because the F# compiler doesn't consider a tuple to be a "simple immutable value":
The compiler performs automatic generalization only on complete function definitions that have explicit arguments, and on simple immutable values.
This means that the compiler issues an error if you try to compile code that is not sufficiently constrained to be a specific type, but is also not generalizable. The error message for this problem refers to this restriction on automatic generalization for values as the value restriction.
Instead, I think you have to define them separately, like this:
let tag a b=sprintf"<%s>%A</%s>"a b a
let em2 inp=tag"em"inp
let bold2 b=tag"b"b
If your desire here is to hide the definition of tag, you can make it private.
I like the idea of centralizing the logic (here: HTML formatting) in a single factory function, to enforce the DRY principle.
Instead of fully hiding the tag factory function in a closure, we can hide it just from other modules, making it private which is usually enough encapsulation. After some renaming:
let private inside tag content = // 'a -> '-b -> string
$"<{tag}>{content}</{tag}>" // 👈 F# 5 interpolated string
Then, the usual way in F# to generate the specific function is through partial application. Since the current inside function is generic, we can't use the point free notation (meaning implicit parameter content) without loosing the generic type:
let em = inside "em" // ⚠️ obj -> string
We have 2 solutions:
Have explicit content parameter: let em content = inside "em" content but it's less elegant.
Change the signature of inside function and make all parameters of type string. In fact, the function inside does not care about the type of its parameters - it only cares about strings since it casts them to string implicitly using the ToString() method which can lead to bad surprises when calling this function.
let private inside tag content = // string -> string -> string
$"<%s{tag}>%s{content}</{tag}>" // 👈 %s to indicate parameters are strings
let em = inside "em" // string -> string
let strong = inside "strong"

What is the difference between '(String)' and 'String' in a Swift error message

I wrote a function that takes a non-optional String as a parameter.
I declared a variable property of type String, which is also not an optional.
When I try to call my function with this property as an argument, I get the following error.
Cannot invoke 'localesForCountryCode' with an argument list of type '(String)'
Notice that the error lists the type as '(String)' not 'String'. What do the parens signify? I thought they meant that the type was optional, but nothing is declared as an optional anywhere.
My Function (An extension of NSLocale):
func localesForCountryCode(countryCode: String) -> [NSLocale] {
let localeIdentifiers = localeIdentifiersForCountryCode(countryCode)
var locales = [NSLocale]()
for localeIdentifier in localeIdentifiers {
let localeForIdentifier = NSLocale(localeIdentifier: localeIdentifier)
locales.append(localeForIdentifier)
}
return locales
}
Code That Calls My Function
let currentCountryCode = "US"
var localesForCurrentCountry = [NSLocale]()
func updateWithNewLocation(newLocation: CLLocation) {
geoCoder.reverseGeocodeLocation(newLocation, completionHandler: { (placemarks, error) -> Void in
if placemarks.count > 0 {
let placemark = placemarks.first as! CLPlacemark
self.currentCountry = placemark.country
self.localesForCurrentCountry = NSLocale.localesForCountryCode(self.currentCountryCode)
}
})
}
Update 1
When I move my function code from the NSLocale extension to the view controller from which I am calling the function, the error goes away. Any ideas why this may be the case? Absolutely no changes to the function were made.
Update 2
I continue to run into this problem. The following is another example. Again, it seems to happen only when a function is called as a class method.
I was rereading your question and realized that your question is not really your question. Your problem has nothing to do with parentheses (see below about why). You're just calling the wrong method. NSDateComponentsFormatter is a class. stringFromTimeInterval() is an instance method. You have to crate an actual date formatter to work with. If you want a default one, you can do this:
return NSDateComponentsFormatter().stringFromTimeInterval(unwrappedTimespan)
Note the extra set of parentheses. Your probably don't want the default one, though. You probably want to configure one. See Date Formatters for an introduction to that topic. Note that date formatters can be pretty expensive to create, so you usually want to reuse them.
You're doing the same thing with localesForCountryCode. This is an instance method, not a class method. You have to create an NSLocale first.
This does open up an interesting topic, though. Why does NSDateComponentsFormatter.stringFromTimeInterval() act like a function that you're just passing the wrong arguments to? Why doesn't it say "hey, you're calling a class method?" It's because it is a function that you're just passing the wrong arguments to.
Every method is really just a curried function that takes the target object as the first parameter. See Ole Begemann's quick intro to the topic: Instance Methods are Curried Functions in Swift.
Some more on your explicit question about parentheses:
As others have noted, a (String) is a one-tuple of String. The important point is that in Swift, any type is trivially convertible to a one-tuple of that type, so the extra parentheses here are unimportant. There is no meaningful distinction between String and (String) in Swift.
All Swift functions technically take one value and return one value. So one can correctly think of:
func f(x: Int, y: Int) -> Int
as a function that takes a tuple (Int,y:Int) and returns an Int (or possibly (Int); I believe Swift actually does the former, though). This is subtly connected to how currying works in Swift. In a simpler case:
func f(x: Int)
This is a function that technically takes (Int) and returns (). That's why sometimes you will see (Type) show up in error messages. But it is not a meaningful distinction.
String - it's simple String type.
But (String) - it's a compound type called Tuple.
That means you passing to you function Tuple, not String.
A compound type is a type without a name, defined in the Swift language itself. There are two compound types: function types and tuple types. A compound type may contain named types and other compound types. For instance, the tuple type (Int, (Int, Int)) contains two elements: The first is the named type Int, and the second is another compound type (Int, Int).
In general the error message says (String) because that is the tuple / list of parameters. If you method would expect a String and afterwards an Int an error message might mention (String, paramName: Int)
So basically so far everything looks fine. You need to show us the code for us to be able to fix your exact problem. Because String and (String) normally should match in the given scenario.
Consider the following example:
func k (a:String, b:Int) {}
k(12, b:"123")
which will cause the error
Cannot invoke 'k' with an argument list of type (Int, b:String)
While
k("12", b:123)
does what you would expect.

swift callback doesn't print

I try to understand the main concept of callbacks in swift
I have the following code:
typealias ImageHandler = (String,NSError?) -> Void
func PostOnSocialMedia(image:String?){
println(0)
Post({(image)->Void in
println(1)
})
println(2)
}
func Post(handler:ImageHandler){
println(3)
}
my code output is 0,3,2 and my question is why doesn't print the number 1.
It’s not printing 1 because you are passing in a function that is never called.
This:
Post({ (image)->Void in
println(1)
})
declares a temporary function (a “closure expression” – a quick easy way to declare anonymous functions, between the { }) that takes an argument of a (String,NSError?) pair, and returns nothing. Then it passes that function into the Post function.
But the Post function does nothing with it. For a function to run, it needs to be called. If you changed your Post function like so:
func Post(handler:ImageHandler){
println(3)
// call the handler that was passed in...
handler("blah",nil)
}
you’ll see it printing a 1.
Note, the image argument received by PostOnSocialMedia and the image argument variable inside the temporary function are two different variables – scoping rules mean the one declared inside the temp function masks the one in the outer scope. But they are very different (in fact, they’re different types – one is a string, and the other is a 2-tuple of a string and an error).
Try reading this for a short intro on first-order functions and closures in Swift.

How am I meant to use Filepath.Walk in Go?

The filepath.Walk function takes a function callback. This is straight function with no context pointer. Surely a major use case for Walk is to walk a directory and take some action based on it, with reference to a wider context (e.g. entering each file into a table).
If I were writing this in C# I would use an object (with fields that could point back to the objects in the context) as a callback (with a given callback method) on it so the object can encapsulate the context that Walk is called from.
(EDIT: user "usr" suggests that the closure method occurs in C# too)
If I were writing this in C I'd ask for a function and a context pointer as a void * so the function has a context pointer that it can pass into the Walk function and get that passed through to the callback function.
But Go only has the function argument and no obvious context pointer argument.
(If I'd designed this function I would have taken an object as a callback rather than a function, conforming to the interface FileWalkerCallback or whatever, and put a callback(...) method on that interface. The consumer could then attach whatever context to the object before passing it to Walk.)
The only way I can think of doing it is by capturing the closure of the outer function in the callback function. Here is how I am using it:
func ScanAllFiles(location string, myStorageThing *StorageThing) (err error) {
numScanned = 0
// Wrap this up in this function's closure to capture the `corpus` binding.
var scan = func(path string, fileInfo os.FileInfo, inpErr error) (err error) {
numScanned ++
myStorageThing.DoSomething(path)
}
fmt.Println("Scan All")
err = filepath.Walk(location, scan)
fmt.Println("Total scanned", numScanned)
return
}
In this example I create the callback function so its closure contains the variables numScanned and myStorageThing.
This feels wrong to me. Am I right to think it feels weird, or am I just getting used to writing Go? How is it intended for the filepath.Walk method to be used in such a way that the callback has a reference to a wider context?
You're doing it about right. There are two little variations you might consider. One is that you can replace the name of an unused parameter with an underbar. So, in your example where you only used the path, the signature could read
func(path string, _ os.FileInfo, _ error) error
It saves a little typing, cleans up the code a little, and makes it clear that you are not using the parameter. Also, for small functions especially, it's common skip assigning the function literal to a variable, and just use it directly as the argument. Your code ends up reading,
err = filepath.Walk(location, func(path string, _ os.FileInfo, _ error) error {
numScanned ++
myStorageThing.DoSomething(path)
})
This cleans up scoping a little, making it clear that you are using the closure just once.
As a C# programmer I can say that this is exactly how such an API in .NET would be meant to be used. You would be encouraged to use closures and discouraged to create an explicit class with fields because it just wastes your time.
As Go supports closures I'd say this is the right way to use this API. I don't see anything wrong with it.

Why can't a function with byref be converted directly to delegate?

Under normal circumstances, F# functions can be converted to delegates by calling new DelegateType and passing in the function as an argument. But when the delegate contains byref parameter, this is not possible directly. For example the code:
type ActionByRef<'a> = delegate of 'a byref -> unit
let f (x:double byref) =
x <- 6.0
let x = ref 42.0
let d = new ActionByRef<_>(f)
won't compile, giving the following error:
This function value is being used to construct a delegate type whose signature includes a byref argument. You must use an explicit lambda expression taking 1 arguments.
Following the error, modifying the code to use
let d = new ActionByRef<_>(fun x -> f(&x))
works. But my question is: why is this necessary? Why won't F# allow the conversion from named function to this delegate, but conversion from lambda is fine?
I came upon this behavior when researching another question. I realize byref is meant only for compatibility with other .Net languages.
I think the problem is that byref<'T> is not an actual type in F# - it looks like a type (to make the language simpler), but it gets compiled to a parameter marked with the out flag. This means that byref<'T> can be only used in a place where the compiler can actually use the out flag.
The problem with function values is that you can construct function e.g. by partial application:
let foo (n:int) (b:byref<int>) =
b <- n
When you pass foo as an argument to a delegate constructor, it is a specific case of partial application (with no arguments), but partial application actually needs to construct a new method and then give that to the delegate:
type IntRefAction = delegate of byref<int> -> unit
let ac = IntRefAction(foo 5)
The compiler could be clever and generate new method with byref parameter (or out flag) and then pass that by reference to the actual function, but in general, there will be other compiler-generated method when you don't use the fun ... -> ... syntax. Handling this would add complexity and I think that's a relatively rare case, so the F# compiler doesn't do that and asks you to be more explicit...

Resources