-
Notifications
You must be signed in to change notification settings - Fork 473
Closed
Labels
Description
tl;dr: For {j|This is a function: $someFunction|j} compiler doesn't throw type errors even if someFunction is a function, variant or anything not "stringable".
Bucklescript string interpolation seems that was introduced in #1316. @glennsl in this comment expresses his concerns with the current implementation, doesn't seem his comment got much attention. After discussing with him in Discord, we agreed there seem to be even more issues than stated before, which lead me to decide not to use string interpolation for now. I'll try to summarise the pros/cons of the current implementation, in hopes something can be improved.
Implicit vs explicit
Input
let ok = 1;
/*
String interpolation seems handy here. TBH I prefer the explicitness of the
string concatenation, but auto transforming to String here seems kind of ok.
*/
Js.log({j|This is $ok|j});
Js.log("This is " ++ string_of_int(ok));
Output
console.log("This is " + (String(1) + ""));
console.log("This is " + Pervasives.string_of_int(1));
Unnecessary String call
Input
let unnecessary = "unnecessary";
/* Compiled output of string interpolation adds unnecessary `String` call */
Js.log({j|This is $unnecessary|j});
Js.log("This is " ++ unnecessary);
Output
var unnecessary = "unnecessary";
console.log("This is " + (String(unnecessary) + ""));
console.log("This is unnecessary");
Unexpected error, due partial application
Input
let add = (~x, ~y=1, ()) => x + y;
let result = add(~x=1, ~y=3);
/*
Here, this aparently seems ok, but because result is still a partially applied
function and not a number, this result will be wrong.
Uncommenting string concatenation example will result in proper compiler error.
*/
/* Js.log("This is not ok" ++ result); */
Js.log({j|This is not ok $result))|j});
Output
function add(x, $staropt$star, _) {
var y = $staropt$star ? $staropt$star[0] : 1;
return x + y | 0;
}
var partial_arg = /* Some */[3];
function result(param) {
return add(1, partial_arg, param);
}
console.log("This is not ok " + (String(result) + "))"));
Unexpected error, due option type
Input
let getMyString = () => {
if (Js.Math.random() > 0.5) {
Some("Something");
}
else {
None;
}
};
let myString = getMyString();
/*
It might be obvious what's the problem here, but in a real world scenario might
be a bit more confusing. By mistake we passed an optional string to the string
interpolation, where we should have stracted the actual string before.
Uncommenting string concatenation example will result in proper compiler error.
*/
/* Js.log("This is actually optional " ++ myString); */
Js.log({j|This is actually optional $myString|j})
Output
function getMyString() {
if (Math.random() > 0.5) {
return /* Some */["Something"];
} else {
return /* None */0;
}
}
var myString = getMyString(/* () */0);
console.log("This is actually optional " + (String(myString) + ""));
And basically, you can add to the list any type error you can imagine
Input
let thisIsJustWrong = () => Js.log("This is wrong");
Js.log({j|This is just wrong $thisIsJustWrong|j});
Output
function thisIsJustWrong() {
console.log("This is wrong");
return /* () */0;
}
console.log("This is just wrong " + (String(thisIsJustWrong) + ""));
glennsl, ncthbrt and fakenickels