Would this function be allowed in Swift (if it wouldn't crash the compiler) - swift

I got this function, which is a minimised version of an actual use case:
func f (i:Int) -> <T> (x:T) -> T {
return { x in return x }
}
As you see I would like to compute a generic function based on some input.
But as you can see in Xcode or on swiftstub, this function crashes the compiler.
Does anybody know if Swift is supposed to support such definitions?

This no longer crashes the compiler when I try it on 1.2b3. However, it’s not valid syntax.
If you want to return a function where the type is determined up-front at the time f is called, this would do it:
func f<T>(i:Int) -> T -> T {
return { x in return x }
}
// need to tell the compiler what T actually is...
let g = f(1) as Int->Int
g(2) // returns 2
However, Swift does not support the ability to define “generic” closures, i.e. closures where the type is determined not on creation of the closure, but at the point when that closure is actually called. This would require higher-ranked polymorphism, something that isn’t currently available (though maybe in the future, who knows – would be a very nice feature to have). For now, the placeholders need to be fully determined at the call site.

Keep in mind that the "generic" nature of Swift generics is kind of a misnomer. The genericness is just a template notation; all genericness is compiled away at compile time - that is, all generics used in one part of your code are resolved (specified) by the way they are called in another part of your code.
But for that very reason, you can't return a generic function as a result of a function, because there is no way to resolve the generic at compile time.
So, while crashing the compiler is not nice (and Apple would like to know about it), your code should not compile either, and to that extent the compiler is correct to resist.

Related

How are methods evaluated in Scala?

Method types have no value. How do we evaluate a method?
Using SML as an example, I have
fun myFunc(x) = x + 5
val b = myFunc(2)
In the second expression, myFun has a type and a value, we use its type to do type checking and use its value together with its argument to evaluate value for b
But in Scala methods without a value how do we evaluate? I am pretty new to Scala so it may not be very clear.
def myFunc(x) = x + 5
val b = myFunc(2)
From val b = myFunc(2) to val b = 2 + 5, what happened in between? From where or what object do we know that myFunc(x) is x + 5?
THanks!!
The simple answer is: just because a method is not a value in the sense of "a thing that can be manipulated by you" doesn't mean that it is not a value in the sense of "a thing that can be manipulated by the author of the compiler".
Of course, a method will have an object representing it inside of the compiler. In fact, that object will probably look very similar to the object representing a function inside, say, the MLTon SML compiler or SML/NJ.
In SML, syntax is not a value, but you are not questioning how it is possible to write a function call either, aren't you? After all, in order to call a function in SML, I need to write a function call using function call syntax, so how can I do that when syntax is not a value?
Well, the answer is the same: just because syntax is not a value that the programmer can manipulate, the compiler (or more precisely the parser) obviously does know about syntax.
I can't tell you why the decision was made to have functions be values in Scala but not methods, but I can make a guess. Scala is an object-oriented language. In an object-oriented language, every value is an object, and every object has methods that are bound to that object. So, if methods are objects, they need to have methods, which are objects, which have methods, which are objects, and so on.
There are ways to deal with this, of course, but it makes the language more complex. For a similar reason, classes aren't objects (unlike, say, in Smalltalk, Python, and Ruby). Note that even in highly reflective, introspective, dynamic languages like Ruby, methods are not objects. Classes are, but not methods.
It is possible using reflection to get a proxy object that represents a method, but that object is not the method itself. And you can actually do the same in Scala as well.
And of course it is possible to turn a method into a function value by η-expansion.
I'm assuming that you're compiling to Java Virtual Machine (JVM) bytecode, such as with scalac, which is probably the most common way to use Scala. Disclaimer: I'm not an expert on the JVM, so some parts of this answer might be a bit wrong, but the general idea is right.
Essentially, a method is a set of instructions for the runtime to execute. It exists as part of the compiled code on disk (e.g. a .class file). When the JVM loads the class, it pulls the entire class file into memory, including the methods. When the JVM encounters a method call, it looks up the method and starts executing the instructions in it. If the method returns a result, the JVM makes that result available in the calling code, then does whatever you wanted to do with it there, such as assigning to a variable.
With that knowledge, we can answer some of your questions:
From val b = myFunc(2) to val b = 2 + 5, what happened in between?
This isn't quite how it works, as the JVM doesn't "expand" myFunc in place, but instead looks up myFunc and executes the instructions in it.
From where or what object do we know that myFunc(x) is x + 5?
Not from any object. While myFunc is in memory, it's in an area of memory that you can't access directly (but the JVM can).
why can't it be a value since it is a chunk of memory?
Not all memory fits into the nice abstractions of types and values.

Is there *any* situation under which "for _ in [1,2,3]" will not loop at all?

I was writing some code and made a mistake that simplifies to:
func f() -> Int {
for _ in [1,2,3] {
return 1
}
}
And the compiler shows me an error saying that f is missing an return, which caused me to realise my mistake. I forgot to put an if statement around the return!
But then I realised that the compiler is actually lying! The function will always return a value. Or will it? Is there any situation under which the for loop will not loop?
I'm asking this because other tautological constructs compiles fine:
if 1 < 2 {
return 1
}
while true {
return 1
}
And I also understand that the compiler can't evaluate every expression at compile time to see if they are tautologies. I know properties accesses and method calls usually don't get evaluated at compile time, so this is not expected to compile:
if "".isEmpty {
return 1
}
But generally literals are ok, right? After all, the compiler has to evaluate the literal [1,2,3] to translate it into machine code that says "create an array with 1, 2, 3".
So why is it not smart enough to figure out the for loop? Will the for loop not get run in some rare situation?
While for a human it is trivial to see that the loop will always repeat three times, because the list literal is a constant with three elements, this is a non-trivial thing to see for a compiler at the level of semantic analysis.
During semantic analysis, the compiler will evaluate "a generic list literal" ([1,2,3]) and determine that it is an expression of type Array<Int>. But now, of course, the information that this is a constant or that this array contains three elements is lost.
Semantic analysis is normally performed using the same (or a very similar) type system the programmer is using. Since there would be little benefit from attaching the number of elements in an array to the type (the number of elements is normally not known at compile time) compared to the cost, this is normally not done. On the other hand, constant folding (if 1 < 2 {) is easier to implement and occurs more often.
While on a lower-level the compiler will likely unroll this loop and use constant values, this happens much later – in Swift after generating the Swift Intermediate Language representation – and probably only just during code generation – after SIL has been emitted to LLVM IR and when LLVM optimizations are run.
for-in doesn't know if all it's going to get from an iterator is nil. You'll get the same error message, Missing return in a function expected to return 'Int', no matter what the sequence is.
extension Bool: Sequence, IteratorProtocol {
public func next() -> Void? { () }
}
for _ in true {

Why does a function have long-term write access to all of its in-out parameters?

According to the chapter of "Memory Safety" in the Swift Programming Language Guide (for Swift 4.2), there is a sentence "A function has long-term write access to all of its in-out parameters."
https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html
I created a new command line tool project to verify it in Xcode 10.1.
var stepSize = 1
func increment(_ number: inout Int) {
print(stepSize)
}
increment(&stepSize)
I expect the output to be 1, but the actual output is a crash log "Simultaneous accesses to 0x100587430, but modification requires exclusive access."
I know this is a conflict about accessing in-out parameters, but I don't know why this happens. Why does a function have long-term write access to all of its in-out parameters?
A consumer of this API sees func increment(_ number: inout Int), but not the implementation. It can only assume that increment(_:) makes writes to the parameters, because it can, in principle.
Even if the function implementation doesn't currently do any writes, the possibility is there, so the compiler has to assume the worst case scenario. Imagine if some client code was allowed to compile against this, treating is as if it's read only (because at the time, it may be the case). What should happen to the client code when someone adds number += 1 to the function body?
This is similar to having a function that declares it can throw, whose actual implementation doesn't throw. The compiler still treats it as throwing, and necessitates the error be handled with some variant of try.

Swift: Why to functions have parameters and return value types?

I'm filling a few gaps in my existing Swift programming language skills before moving onto the more advanced features.
I have checked Apples... "Swift Programming Language" guide and Google search shows lots of information about the rules around using the parameters, but I am looking for the overall Why , not the How...
Question:
Why is there a need to have parameters and return value types for functions in Swift?
(I am not asking about the parameter names etc., but a higher level (general) question on 'Why')
I have made a number of programs using simple C-Style functions in Swift, without a need for parameters or return values which works fine as I know what the functions should be doing for me.
Simple e.g.
func printName() {
print("John")
}
However, there are 'exceptions' like some in-built Swift functions.
E.g....
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return colors.count
}
etc. for table view or collection view usage .
So the only reason I see for using parameters + return values (type) in functions is to ensure only specific type of data is inputted and outputted.
In other words, its a way to avoid unexpected outcomes. So acting almost like a Switch statement, where if I have a specific condition is met -- a specific output will occur... (in functions... "an action").
Am I correct in this understanding, in trying to understand why / where one needs to use parameters & / or return values types with Functions? Or are there other practical reasons? If so can you provide an example?
Many thanks in advance!!!!
If you don't use parameters, you're tied to use what's visible in your scope.
if your function is inside a ViewController, all properties inside that VC, also global scope variables (horrible)
if your function is in global scope, you can only use global scope symbols (horrible, again)
You really do want to pass in things using parameters. This way you can:
auto check types (compiles is doing for you)
check for optionality
check value ranges
test your functions using Unit Tests. if you use global symbols, you're tied to that symbols, can't change them
less maintenance: changes outside your function doesn't affect you
Also, having a clear return type helps other developers and your future-self to understand what's returning from that function: a tuple? An optional array? A number? Also, having defined output types helps you with testing your functions.
Using only global variables & procedures (chunks of code to process those global vars) could work on a small scale. That's the old approach use with languages like FORTRAN, BASIC, COBOL... The moment your project grows, you need to isolate one part of your code from the other. For that:
use functions & a functional approach
use OOP
Let's imagine a sum function
func sum(a: Int, b:Int) -> Int {
return a + b
}
What happen if we remove the parameter types
func sum(a, b) -> Int {
return a + b // what?
}
Of course this is not allowed by the compiler but let's try to imagine.
Now a and b could be anything (like a String and a UIImage). How could we write the code to sum 2 things and get an Int?
Another test, let's remove the return type
func sum(a:Int, b:Int) -> ??? {
return a + b
}
Now let's try to invoke our crazy function
let tot: Int = sum(1, b: 2)
but since sum could return any kind of value how can we put the result into an Int constant?

Is there a way to declare an inline function in Swift?

I'm very new to the Swift language.
I wanted to declare an inline function just like in C++
so my func declaration looks like this:
func MyFunction(param: Int) -> Int {
...
}
and I want to do something like this:
inline func MyFunction(param: Int) -> Int {
...
}
I tried to search on the web but I didn't find anything relevant maybe there is no inline keyword but maybe there is another way to inline the function in Swift.
Swift 1.2 will include the #inline attribute, with never and __always as parameters. For more info, see here.
As stated before, you rarely need to declare a function explicitly as #inline(__always) because Swift is fairly smart as to when to inline a function. Not having a function inlined, however, can be necessary in some code.
Swift-5 added the #inlinable attribute, which helps ensuring that library/framework stuff are inlineable for those that link to your library. Make sure you read up about it, as there may be a couple of gotchas that might make it unusable. It's also only for functions/methods declared public, as it's meant for libraries wanting to expose inline stuff.
All credit to the answer, just summarizing the information from the link.
To make a function inline just add #inline(__always) before the function:
#inline(__always) func myFunction() {
}
However, it's worth considering and learning about the different possibilities. There are three possible ways to inline:
sometimes - will make sure to sometimes inline the function. This is the default behavior, you don't have to do anything! Swift compiler might automatically inline functions as an optimization.
always - will make sure to always inline the function. Achieve this behavior by adding #inline(__always) before the function. Use "if your function is rather small and you would prefer your app ran faster."
never - will make sure to never inline the function. This can be achieved by adding #inline(never) before the function. Use "if your function is quite long and you want to avoid increasing your code segment size."
I came across an issue that i needed to use #inlinable and #usableFromInline attributes that were introduced in Swift 4.2 so i would like to share my experience with you.
Let me get straight to the issue though, Our codebase has a Analytics Facade module that links other modules.
App Target -> Analytics Facade module -> Reporting module X.
Analytics Facade module has a function called report(_ rawReport: EventSerializable) that fire the reporting calls, This function uses an instance from the reporting module X to send the reporting calls for that specific reporting module X.
The thing is, calling that report(_ rawReport: EventSerializable) function many times to send the reporting calls once the users launch the app creates unavoidable overhead that caused a lot of crashes for us.
Moreover it's not an easy task to reproduce these crashes if you are setting the Optimisation level to None on the debug mode. In my case i was able only to reproduce it when i set the Optimisation level to Fastest, Smallest or even higher.
The solution was to use #inlinable and #usableFromInline.
Using #inlinable and #usableFromInline export the body of a function as part of a module's interface, making it available to the optimiser when referenced from other modules.
The #usableFromInline attribute marks an internal declaration as being part of the binary interface of a module, allowing it to be used from #inlinable code without exposing it as part of the module's source interface.
Across module boundaries, runtime generics introduce unavoidable overhead, as reified type metadata must be passed between functions, and various indirect access patterns must be used to manipulate values of generic type. For most applications, this overhead is negligible compared to the actual work performed by the code itself.
A client binary built against this framework can call those generics functions and enjoy a possible performance improvement when built with optimisations enabled, due to the elimination of abstraction overhead.
Sample Code:
#inlinable public func allEqual<T>(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
var iter = seq.makeIterator()
guard let first = iter.next() else { return true }
func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec(&iter)
}
return rec(&iter)
}
More Info - Cross-module inlining and specialization