Understanding Safe.Coerce in Purescript - purescript

I've been looking at the compiled version of some code snippets to dig into how my code is represented at runtime.
I'm not surprised to see that safe coerce and unsafe coerce are the same in the compiled JavaScript. There's a dictionary passed into safe coerce that's unused/undefined in the code I've looked at so far.
It seems like if the runtime representation of two types is the same, then there shouldn't be any runtime overhead for having/using such a type. This isn't true and I'm curious to understand why.
Coercing two types requires a function call at runtime. What I'm not understanding is that this function call appears to do nothing.
exports.unsafeCoerce = function (x) {
return x;
};
If I declare a newtype
newtype Selection = Selection Int
I see something similar in JavaScript:
var Selection = function (x) {
return x;
};
Which means I might see something like this in JavaScript:
return Selection(Data_Int.pow(2)(Safe_Coerce.coerce()(n) - 1 | 0));
which should be identical to this:
return Data_Int.pow(2)(n - 1 | 0);
In this case, both Selection and coerce only ever return what they're given. Once the type checking has been done, I'm not sure what purpose they continue to serve.

The reason the code is generated like it is, and not in a more efficient form like you suggest, is because the purs compiler has only a simplistic optimiser.
Why unsafeCoerce is defined as it is is because it is a PureScript function and must match the runtime representation of PureScript functions. Same goes for Selection.
Constraints are represented as functions on dictionaries. Some time ago there was an optimisation added such that empty dictionaries do not have to be constructed as empty JavaScript objects, and instead can be represented by undefined. That is why there is no argument passed to coerce.

Related

Do any programming languages provide the ability to name the return value of a function?

Quite commonly while programming I find it necessary to document the value that a function returns. In Java/Scala world, you often use comments above the function to do this.
However, this can stand out in contrast to the first-class documentation that function parameters get in all languages. For example:
def exponent(base: Int, power: Int): Int
Here we have the signature for a method that raises base to the power power and returns... probably the result of that computation? I know for certain it returns an Int, and it seems quite reasonable to infer that the return value is indeed the result of calculating base ^ power, but in many functions I've written and read it is not possible to infer the return value's semantic meaning quite so easily and you need to study the documentation and/or actually use the method to find out.
Which leads me to wonder, do any languages provide support for optionally declaring a semantic name for the return value?
def exponent(base: Int, power: Int): Int(exitCode)
A hah! Turns out this function actually returns an indication of whether the operation succeeded or failed! Look it is so clear right there in the method signature! My IDE could also intelligently create a variable with the same name when I call this method, a la:
// Typing in IntelliJ
exponent(5, 5)<TAB>
// Autocompletes to:
val exitCode = exponent(5, 5)
I'm not under any illusion that this is some sort of ground-breaking idea, but it seems like it could be generally useful, and I'm struck that I have never seen this concept implemented in any programming language.
Can you name any single programming language that does have this kind of semantic naming of return values?
In APL, for instance, the result of a function is declared as a variable. The function declaration in your example could be written like
exitCode ← base exponent power
in APL. However, a function with no side effects should always be named after the result it returns. If the function can fail I would use a value that is never returned on success, for instance -1 in this case.

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 {

Spread syntax in function call in Reason

In Javascript you can use the spread syntax in a function call like this:
console.log(...[1,2,3]);
Is there an equivalent in Reason? I tried the following:
let bound = (number, lower, upper) => {
max(lower, min(upper, number));
};
let parameters = (1,0,20);
bound(...parameters) |> Js.log;
But this gives an unknown syntax error:
Try reason snippet
There's not. Reason is a statically typed language, and lists are dynamically-sized and homogenous. It would be of very limited use, and not at all obvious how it would deal with too few or too many arguments. If you want to pass a list, you should just accept a list and deal with it appropriately, as a separate function if desired.
You could of course use a tuple instead, which is fixed-size and heterogenous, but I don't see a use-case for that either, since you might as well just call the function directly then.
For JavaScript FFI there is however the bs.splice attribute, which will allow you to apply a variable number of arguments to a js function using an array. But it needs to be called with an array literal, not just any array.

Swift syntax: UnsafeMutablePointers in CGPDFDocument.getVersion

Can anyone explain how I'm supposed to use the method 'getVersion' for CGPDFDocument in Swift?
Apple's documentation gives:
func getVersion(majorVersion: UnsafeMutablePointer<Int32>,
minorVersion: UnsafeMutablePointer<Int32>)
"On return, the values of the majorVersion and minorVersion parameters are set to the major and minor version numbers of the document respectively."
So I supply two variables as arguments of the function, and they get filled with the values on exit? Do they need to point to something in particular before the method is called? Why not just type them as integers, if that's what the returned values are?
You use it like this:
var major: Int32 = 0
var minor: Int32 = 0
document.getVersion(majorVersion: &major, minorVersion: &minor)
print("Version: \(major).\(minor)")
The function expects pointers, but if you pass in plain Int32 variables with the & operator, the Swift compiler is smart enough to call the function with pointers to the variables. This is documented in Using Swift with Cocoa and Objective-C: Interacting with C APIs.
The main reason the function works like this is probably that it's a very old C function that has been imported into Swift. C doesn't support tuples as return values; using pointers as in-out parameters is a way to have the function return more than one value. Arguably, it would have been a better design to define a custom struct for the return type so that the function could return the two values in a single type, but the original developers of this function apparently didn't think it was necessary — perhaps unsuprisingly, because this pattern is very common in C.

What is the difference between ByRef and Output method argument modifiers?

All is in the subject, really.
I fail to see what the difference in behavior is between those two methods for x:
// first version
Method m(ByRef x As whatever)
{
// play with x
}
// second version
Method m(Output x As whatever)
{
// play with x
}
There must be some reason why both those modifiers exist, however my "mastery" (uhm) of the language is not enough to understand the difference. I have tried and read the documentation, search it etc, to no avail so far.
So, what is the difference between those two argument modifiers?
Well those are just "prettifiers", they don't do much in terms of actual language behaviour, and only used to provide documentation. Idea is that arguments documented as ByRef provide both input and output, for example you can pass an array to be sorted, and Output arguments only provide output, for example list of errors. Output modifier was introduced later, and a lot of system code still use ByRef for both use cases.
If argument is actually passed by reference is only determined by method caller, and keyword doesn't really matter. You will call your method as ..m(.parameter) to pass variable by reference, and ..m(parameter) to pass variable by value.