Say I have either
msg = "Saved Successfully"
or
msg = -> "Saved #{#course.title} Successfully"
Is there anyway to elegantly get the value of msg without knowing whether it's a function or a regular variable rather than doing
success_message = if typeof msg is 'function' then msg() else msg
There's a CoffeeScript shorthand you can take advantage of:
f?()
is equivalent to
f() if typeof f is 'function'
which means that you can write
success_message = msg?() ? msg
This works because msg?() has the value undefined if msg isn't a function.
Caveat: This will fail if msg() returns null, setting success_message to the msg function.
Really, if you're going to do this in your application, you should write a utility function:
toVal = (x) -> if typeof x is 'function' then x() else x
successMessage = toVal msg
You could even attach toVal to the Object prototype if you're feeling adventurous..
Related
I am working with F# to develop PowerShell tooling. I am currently running into a block because Async<_>is a generic type that is not derived from a non-generic type, so I can't request an Async<_> or Async as a parameter value - I have to specify the exact generic type parameter.
(For those unfamiliar with the interaction between these two languages, I can write a class in a .NET language such as F#, derive it from a class in the PowerShell library, and give it a specific attribute and when I run PowerShell and import my library, my class is exposed as a command. The command type can't be generic. Properties of the type are exposed as PowerShell parameters.)
As far as I'm aware I can't avoid this by having a generic member on a non-generic type, so ideally I'd have a transformation attribute (for non-PS users, transformation attributes effectively perform type conversion during runtime parameter binding) to turn Async<_> into Async<obj>. For the most part, this would work great for me. However, I can't figure out a way to check if a value is Async<_>, because the check computation :? Async<_> at compile time ends up as computation :? Async<obj>, which is not, unfortunately, the same, and returns false when passed Async<int>.
I ran into a similar issue in C# and was able to leverage the dynamic keyword after running a reflection test, and making the parameter be of the derived base type System.Threading.Tasks.Task, e.g.
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHeirarchy;
var isTaskOf = task.GetType()
.GetProperty("GetAwaiter", flags)
.PropertyType
.GetMethod("GetResult", flags)
.ReturnType != typeof(void);
if (isTaskOf) {
var result = await (dynamic)task;
}
I am willing to do something like this in F# if possible, but:
I have not ben able to successfully get the dynamic lookup operator ? to compile. Specifically, "none of the types 'Async<'a>, string' support the '?' operator". Not sure what I'm doing wrong as the explanations look straightforward and I can't find any other reports of this message or requirements for that operator.
I don't know if that would even work or if that operator is only used to dynamically access a member of an object.
The solutions I have tried are:
/// Transform from Async<_> to Async<obj>
override _.Transform(_, item : obj) : obj =
match item with
// only matches Async<obj>. I get a compiler warning that _ is constrained to obj
| :? Async<_> as computation ->
let boxedComputation : Async<obj> = async { return! computation }
boxedComputation
// if the value is not an async computation, let it pass through. This will allow other transformation or type converters to try to convert the value
| _ -> item
override _.Transform(_, item) =
// no compiler warning about the type being constrained to obj, but the if test does not pass unless item is Async<obj>
if (item :? Async<_>) then async { return! item :?> Async<_> }
else item
The other thing I can think of is to use reflection entirely - get the async type, call all of the AsyncBuilder methods reflectively to create a computation expression, and then cast it to Async. As I'm fairly new to F# I'm not sure how well I'd be able to piece together a computation expression like that, and either way it seems a lot more complicated than it ought to be. I'm hoping there is some better way to identify the return type of an async computation and/or just box the result without caring what type it actually is.
EDIT
After trying something ridiculously complicated using reflection with the AsyncBuilder type I realized I could leverage it a little more simply. Here is my current working solution, but I'm still looking out for any better options.
static let boxAsyncReturnValue v = async { return v :> obj }
static let bindFunctionReflected = typeof<FSharpAsyncObjTransformationAttribute>.GetMethod(
nameof boxAsyncReturnValue,
BindingFlags.NonPublic ||| BindingFlags.Static
)
override _.Transform(engineIntrinsics, item) =
// I need to identify the current return type of the computation, and quit if "item" is not Async<_>
if item = null then item else
let itemType = item.GetType()
if not itemType.IsGenericType then item else
let genericItemType = itemType.GetGenericTypeDefinition()
if genericItemType <> typedefof<Async<_>> then item else
let returnType = itemType.GetGenericArguments()[0]
if returnType = typeof<obj> then item else
bindFunctionReflected.MakeGenericMethod(itemType).Invoke(null, [|item|])
This is how I would do it:
let convert (a: Async<_>) =
async {
let! x = a
return box x
}
And at compile time it behaves as you'd expect:
let a = async { return "hello" }
let o: Async<obj> = convert a
let res = Async.RunSynchronously o
printfn "%s" res // Error: expected type 'string' but is type 'obj'
printfn "%s" (unbox<string> res) // compiles, prints the string
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
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
The following CoffeeScript code:
foo = (x) ->
alert("hello") unless x?
alert("world") unless y?
is compiled to:
var foo;
foo = function(x) {
if (x == null) {
alert("hello");
}
if (typeof y === "undefined" || y === null) {
return alert("world");
}
};
Why is foo's argument x is not checked for undefined, while y is?
The undefined check is to prevent the ReferenceError exception that's thrown when you retrieve the value of a nonexistent identifier:
>a == 1
ReferenceError: a is not defined
The compiler can see that the x identifier exists, because it's the function argument.
The compiler cannot tell whether the y identifier exists, and the check to see whether y exists is therefore needed.
// y has never been declared or assigned to
>typeof(y) == "undefined"
true
In javascript to check if a variable was never created, we just do
if (typeof MyVariable !== "undefined"){ ... }
I was wonder how I do that in coffeescript?... I try something like
if (MyVariable?false){ ... }
but this check if MyVariable is a function if so that will call MyVariable(false) if not that will call void(0) or something like that.
Finally I found this easy way to do it:
if (MyVariable?){ ... }
that will generate:
if (typeof MyVariable !== "undefined" && MyVariable !== null){ ... }
UPDATE 04/07/2014
Demo Link
First, to answer your question:
if typeof myVariable isnt 'undefined' then # do stuff
Magrangs' solution will work in most cases, except when you need to distinguish between undefined and false (for example, if myVariable can be true, false or undefined).
And just to point out, you shouldn't be wrapping your conditions in parentheses, and you shouldn't be using curly braces.
The then keyword can be used if everything is on the same line, otherwise use indentation to indicate what code is inside of the condition.
if something
# this is inside the if-statement
# this is back outside of the if-statement
Hope this helps!
This answer is for an older version of coffeescript. See Jaider's answer above if you want a more up to date answer (as of July 2014)
This coffeescript does what you want I think:
if not MyVariable?
MyVariable = "assign a value"
Which produces:
if (!(typeof MyVariable !== "undefined" && MyVariable !== null)) {
MyVariable = "assign a value";
}
N.b. if you make an assignment to MyVariable first, even if you set MyVariable to undefined as in this code, then this compiles to:
if (!(MyVariable != null)) {
MyVariable = "assign a value";
}
I believe this works because the != used by CoffeeScripts Existential Operator (the question mark) coerces undefined to be equal to null.
p.s. Can you actually get if (MyVariable?false){ ... } to work? It doesn't compile for me unless there's a space between the existential operator and false i.e. MyVariable? false which then makes CoffeeScript check it like a function because of the false which it thinks is a parameter for your MyVariable, for example:
if MyVariable? false
alert "Would have attempted to call MyVariable as a function"
else
alert "but didn't call MyVariable as it wasn't a function"
Produces:
if (typeof MyVariable === "function" ? MyVariable(false) : void 0) {
alert("Would have attempted to call MyVariable as a function");
} else {
alert("but didn't call MyVariable as it wasn't a function");
}
typeof MyVariable isnt "undefined"
from js2coffee
In addition to Jaider's answer above (I couldn't comment due to insufficient reputation), be careful that it's a different case if it's something inside an object/array:
someArray['key']?
will be converted to:
someArray['key'] != null
Screenshot from js2coffee.org:
I just use:
if (myVariable)
//do stuff
As undefined is falsy it will only do stuff if myVariable is not undefined.
You just have to be aware that it will 'do stuff' for values that are 0, "" and null
The cleanest way I've found to assign a variable to an undefined and not-null variable is using unless:
unless ( myVar? )
myVar = 'val'
Why not just use the OR idiom?
myVar or 'val'
So, the result will equal myVar, unless it is undefined in which case it will equal 'val'.