How do you call an uncurried function with unit in ReScript/ReasonML? - reason

Say that I have an uncurried function like:
let echo(. a) = a;
I can call this funcition fine with most literals like:
echo(. 1)
echo(. "Hello")
but when I am trying to call it with void, I get an error:
echo(. ()) //This function has arity1 but was expected arity0
As a workaround, I can do this:
let myArg = ()
echo(. myArg)
Is there a way to avoid this?

I like this version as well:
echo(. ignore())
that way I don't need the dummy value workaround
Edit: This version is also now part of the docs: https://rescript-lang.org/docs/manual/latest/function#uncurried-function

It looks like you are trying to call an un curried function that takes one parameter with no arguments because that is what () means right. The only reason it works with
echo(. myArg) is in this case the compiler is declaring an un initialized variable called myArg and passing that to echo.
EDIT: you can look at what I mean at re-script playground here
let echo = (. a) => a;
let k =() => echo(. "String")
let myArg = ()
let s =() => echo (. myArg)
generates
// Generated by ReScript, PLEASE EDIT WITH CARE
'use strict';
function echo(a) {
return a;
}
function k(param) {
return echo("String");
}
function s(param) {
return echo(undefined);
}
var myArg;
exports.echo = echo;
exports.k = k;
exports.myArg = myArg;
exports.s = s;
/* No side effect */

Apparently, this is a known issue in rescript. See: https://github.com/rescript-lang/rescript-compiler/issues/3429

Related

How forall is implemented in Coq

In trying to understand how to implement forall in JS or Ruby, I would be interested to know how it's actually implemented in Coq. Maybe that will help shed some light. I don't seem to find the definition by searching around on Google. Mainly just looking for a link in the source code somewhere.
Coq's forall is a dependent product type and cannot be directly encoded in a dynamically typed languages like Javascript because they simply lack the concept of static type.
It serves the purpose of giving a static type to some nonsensical from the point of view of some languages, functions. Consider we have an infinite collection of types T1, T2...
Then this function cannot be assigned a (nontrivial) type by conventional methods:
function foo(n) {
return eval("new T" + n + "()");
}
However, we can give it dependent (forall) type, using a helper function
function H(n) {
return eval("T" + n);
}
The type of foo then will be forall n:Number, H(n) (given Number, returns an object of type H(n), ie Tn).
Unfortunately, there is no way for us to convey this information to the JS interpreter to statically enforce this contract. However, we can check it at runtime!
Lets start by making a small type checking framework.
function type_number(x) {
if (typeof x == "number") return x;
throw new Error("not a number");
}
function type_function(x) {
if (typeof x == "function") return x;
throw new Error("not a function");
}
function type_instance(clss) {
return function (x) {
if (x instanceof clss) return x;
throw new Error("not an instance of " + clss);
};
}
Now we can implement a non-dependent function type
function type_arrow(arg, ret) {
return function(f) {
f = type_function(f);
return function(x) {
return ret(f(arg(x)));
};
};
}
Here arg must be a type checker for the argument, and ret must be a type checker for the return value. For example:
// declare a function from numbers to numbers
var fn1 = type_arrow(type_number, type_number)((x) => x * x);
fn1(10); // works
fn1("asdsa"); // fails
// bad declaration, but, unfortunately, JS cannot possibly catch it at "compilation" time
var fn2 = type_arrow(type_number, type_number)((x) => "Hello!");
fn2(10); // fails, return value is not a number
Now to the fun part:
function type_forall(arg, ret) {
return function(f) {
f = type_function(f);
return function(x) {
var y = f(arg(x));
return ret(x)(y);
};
};
}
Notice how ret is now a curried function of two arguments. Given my first example, we can now give a type to foo:
function T1(){}
function T2(){}
function T3(){}
function T4(){}
function T5(){}
// ...etc
function foo(n) {
return eval("new T" + n + "()");
}
function H(n) {
return eval("T" + n);
}
function type_H(n) {
return type_instance(H(n));
}
var typed_foo = type_forall(type_number, type_H)(foo);
typed_foo(2); // successfully invokes and returns a T2 instance
Note that we cannot give a non-trivial type to foo with type_arrow - we need n to properly typecheck the return value.
But this is nowhere near the power Coq gives us, simply because it does not catch any errors at compile time. If you really want these guarantees, you must materialize language constructs as first class objects and perform your own type checking. One article I could recommend is http://augustss.blogspot.com/2007/10/simpler-easier-in-recent-paper-simply.html

What is the function of = sign in this particular closure statement?

I'm new to Swift and is trying to learn the concept of closure. I saw this code online:
var sayHelloClosure: () -> () = {
print("hello from closure")
}
when I remove the = sign, the compiler output the error message:
Missing return in a function expected to return '() -> ()'
Could someone please tell me the use of = in this particular context?
Let's break that statement down:
var sayHelloClosure
Ok, we're creating a mutable variable
: () -> ()
It has a type of () -> (), a function with no arguments that returns void.
=
It's being set to something
{
print("hello from closure")
}
And that thing is a closure (basically a unnamed function) that takes no arguments and returns nothing (void)
Basically you now have a variable that points to a function that does what's in those braces.

Removing a closure from an array

Removing a closure from an array but not using it causes compiler error "Expression resolves to an unused function". Is there a good way to avoid this, other than assigning the function to a throwaway variable?
typealias StringFunction = () -> String
var list = [StringFunction]()
list.append({ "Hello World!" })
let hi = list[0]() // "Hello World!"
list.removeAtIndex(0) // Expression resolves to an unused function
let _ = list.removeAtIndex(0) // Works
Assigning the result of the expression to a throwaway variable is the correct way to do that. In fact, this is the idiomatic way to treat unused results in Swift.
Hence (as noted in the comments of another answer) the correct solution the is:
typealias StringFunction = () -> String
var list = [StringFunction]()
list.append({ "Hello World!" })
let hi = list[0]()
_ = list.remove(at: 0) // Note there's no need for `let`
Doing so not only makes your code clearer about your intent (i.e. it indicates that you definitely don't need the result of the method), but also helps the compiler perform all sorts of useful optimizations.
This compiled for me:
typealias StringFunction = () -> String
var list = [StringFunction]()
list.append({ "Hello World!" })
let hi = list[0]() // "Hello World!"
list.removeAtIndex(0)()
Although this does call the function. (thanks Martin R)

In Haxe, how do you read a variable name inside of a Macro?

I'm trying to use Macros to convert some variable declarations from this:
function test():Void {
var someComp:Component = __SOME_MACRO__();
// Or...
#getCompById var someComp:Component;
// Or even simpler...
getCompById(someComp, Component); //do some fancy macro magic...
// Also, if it's not possible/easy with a variable ...
getCompById("someComp", Component); //with a string of the variable name.
}
... to this:
function test() {
var someComp:Component = cast container.getCompById("someComp");
}
I'm leaning more toward the 3rd option (shorter syntax, same results).
But I have no idea how to write the macro (should it take a String as parameter? An expression?) and how to properly return that as a macro expression.
This is the (broken) code I've got so far:
macro static function getCompById(someVar:Expr, typeVar:Expr) {
return macro {
var someVar:typeVar = cast container.getCompById("someVar");
};
}
Any ideas?
The issue with the code you posted is first that you'd need reification escaping mechanisms for this to work correctly - so the first change would be to use the macro escapes:
return macro var $someVar:$typeVar = cast container.getCompById($v{someVar});
Now there will be some problems with this: It's expecting someVar to be of type String, and typeVar to be of type ComplexType. It's easy to get the string component from an Expr. It's not so easy however to transform an Expr into ComplexType. The easiest way to do that is to use the tink_macros library and use asComplexType
So the (untested) code will look something like:
using tink.MacroAPI;
using haxe.macro.Tools;
macro static function getCompById(someVarExpr:Expr, typeVarExpr:Expr)
{
var typeVar = typeVarExpr.toString().asComplexType();
switch (someVarExpr.getIdent())
{
case Success(someVar):
return macro var $someVar:$typeVar = cast container.getCompById($v{someVar});
case Failure(error): throw error;
}
}

Is there any way to not return something using CoffeeScript?

It seems like CoffeeScript automatically returns the last item in a scope. Can I avoid this functionality?
You have to explicitly return nothing, or to leave an expression evaluating to undefined at the bottom of your function:
fun = ->
doSomething()
return
Or:
fun = ->
doSomething()
undefined
This is what the doc recommends, when using comprehensions:
Be careful that you're not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value — like true — or null, to the bottom of your function.
You could, however, write a wrapper like this:
voidFun = (fun) ->
->
fun(arguments...)
return
(Notice the splat operator here (...))
And use it like this when defining functions:
fun = voidFun ->
doSomething()
doSomethingElse()
Or like this:
fun = voidFun(->
doSomething()
doSomethingElse()
)
Yes , with a return as the last line of a function.
For example,
answer = () ->
42
extrovert = (question) ->
answer()
introvert = (question) ->
x = answer()
# contemplate about the answer x
return
If you'd like to see what js the coffee compiles to, look at this. (I've used coffeescript redux for my example)
Just something fun(ctional)
suppressed = _.compose Function.prototype, -> 'do your stuff'
Function.prototype itself is a function that always return nothing. You can use compose to pipe your return value into this blackhole and the composed function will never return anything.
longRunningFunctionWithNullReturn = ->
longRunningFunction()
null
It seems functions in CoffeeScript must always return something, even null. In C, you have void as a return type.
->, the empty function, compiles to (function() {}), so it's the only function that doesn't return anything.