How to return a placeholder value in Hack? - hacklang

I am implementing a function that returns an Awaitable<T>- but for the moment, I just want to return a placeholder value.
How do I accomplish this?
In rust, I'd so something like invoke the unimplemented!() macro - in java/python, I'd return null or raise an exception

Control that always reaches an exception is a bottom type, so you can raise an exception to get any type:
function unimplemented<T>(): T {
throw new Exception("Unimplemented!");
}
If you want a usable placeholder value at runtime from your function, your only option is indeed null and a bunch of nullable annotations.

Related

TS: Cannot invoke an expression whose type lacks a call signature when defined dynamically, but it works

I'm still quite new to typescript, so please be gentle with me if I'm doing something with no sense for this technology!
The problem that I'm trying to solve is having a dynamic way to define how my application errors should be structured, but leaving to the users the faculty to enrich the messages.
So I tried to create this logic in a module that could be extended easily from the application, but I'm currently facing the problem:
Error:(35, 18) TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ErrorMessage' has no compatible call signatures.
What I thought it was a good idea (but please tell me if I'm wrong), was to use a register and a map to have the possibility to extend this mapping every time I want. So I created my ErrorMessage interface to be like the following:
export interface ErrorMessage {
actionMessage: string;
actionSubject: string;
originalErrorMessage?: string;
toString: () => string;
}
and a register for these, called ErrorResponseRegister, as it follows:
export enum defaultErrors {
ExceptionA = 'ExceptionA',
ExceptionB = 'ExceptionB',
}
export class ErrorResponseRegister {
private mapping: Map<string, ErrorMessage>;
constructor() {
this.mapping = new Map()
.set(defaultErrors.ExceptionA, exceptionAErrorMessage)
.set(defaultErrors.ExceptionB, exceptionBErrorMessage);
}
}
So at the end, every ErrorMessage function should look like:
export function exceptionAErrorMessage(originalErrorMessage?: string): ErrorMessage {
return {
enrichment1: "Something happened",
enrichment2: "in the application core",
originalErrorMessage: originalErrorMessage,
toString(): string {
return `${this.enrichment1} ${this.enrichment2}. Original error message: ${originalErrorMessage}`;
},
};
}
Please note I haven't used classes for this ones, as it doesn't really need to be instantiated
and I can have a bunch of them where the toString() method can vary. I just want to enforce the errors should have an enrichment1 and enrichment2 that highlight the problem in a better way for not-technical people.
So, now, back to code. When I'm trying to use the exceptionAErrorMessage statically, I can't see any problem:
console.log(exceptionAErrorMessage(originalErrorMessage).toString())
But when I try dynamically, using the map defined in the ErrorResponseRegister, something weird happens:
// In ErrorResponseRegister
public buildFor(errorType: string, originalErrorMessage?: string): Error {
const errorMessageBuilder = this.mapping.get(errorType);
if (errorMessageBuilder) {
return errorMessageBuilder(originalErrorMessage).toString();
}
return "undefined - do something else";
}
The code works as expected, the error returned is in the right format, so the toString function is executed correctly.
BUT, the following error appears in the IDE:
Error:(32, 18) TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ErrorMessage' has no compatible call signatures.
The line that causes the problem is
errorMessageBuilder(originalPosErrorMessage).toString()
Can someone help me to understand what I'm doing wrong?
It looks like your problem is you've mistyped mapping... it doesn't hold ErrorMessage values; it holds (x?: string)=>ErrorMessage values:
private mapping: Map<string, (x?: string) => ErrorMessage>;
What's unfortunate is that you initialize this variable via new Map().set(...) instead of the using an iterable constructor argument.
The former returns a Map<any, any> which is trivially assignable to mapping despite the mistyping. That is, you ran smack into this known issue where the standard library's typings for the no-argument Map constructor signature produces Map<any, any> which suppresses all kinds of otherwise useful error messages. Perhaps that will be fixed one day, but for now I'd suggest instead that you use the iterable constructor argument, whose type signature declaration will infer reasonable types for the keys/values:
constructor() {
this.mapping = new Map([
[defaultErrors.ExceptionA, exceptionAErrorMessage],
[defaultErrors.ExceptionB, exceptionBErrorMessage]
]); // inferred as Map<defaultErrors, (orig?: string)=>ErrorMessage>
}
If you had done so, it would have flagged the assignment as an error with your original typing for mapping (e.g., Type 'Map<defaultErrors, (originalErrorMessage?: string | undefined) => ErrorMessage>' is not assignable to type 'Map<string, ErrorMessage>'.) Oh well!
Once you make those changes, things should behave more reasonably for you. Hope that helps; good luck!
Link to code

Catching thrown Enum Values

Haxe permits the throwing of pretty much anything, but seems to be a bit limited in its catching ability. For example, I have a static error function that throws values of an ErrorType enum:
class Error
{
public static var CATCH_ALL:Bool = false;
public static function Throw(aError:ErrorType, ?ignore:Bool=false, ?inf:PosInfos):Void
{
trace('Error: $aError at ' + inf.className + ':' + inf.methodName + ':' + inf.lineNumber);
if (!CATCH_ALL && !ignore)
{
throw aError;
}
}
}
enum ErrorType
{
NULL_PARAM(msg:String);
NOT_FOUND(msg:String);
}
While I can catch pretty much anything, I am limited to basic types, class types and enum types. This means that I can catch every string, but not specifically a string containing "potato", for example. If I create multiple error classes, I can catch a specific class type while ignoring the others, but the same thing seems not to be possible with enum. Would there be an alternative to the following code that would compile?
try
{
Error.Throw(ErrorType.NULL_PARAM('Potato'));
}
catch (e:ErrorType.NULL_PARAM) trace(e); //does not work nor compile
catch (e:ErrorType) trace(e); //works, but catches every error
Selection of catch-expressions is limited to types / doesn't provide pattern matching capabilities like switch does:
Catch blocks are checked from top to bottom with the first one whose type is compatible with the thrown value being picked.
All values of the ErrorType enum are compatible with the ErrorType type. This means that unfortunately, I think the best you can do is to catch ErrorType and then do the selection inside the catch-block, using a switch and potentially re-throwing it. However, note that a simple throw e would currently cause the stack trace to be lost as discussed in #4159.

Applying default groovy method parameter value when passing null

In Groovy, if I have:
def say(msg = 'Hello', name = 'world') {
"$msg $name!"
}
And then call:
say() // Hello world!
say("hi") // Hi world!
say(null) // null world!
Why is the last one getting interpreted literally as null and not applying the default value? Doesn't this defeat the purpose of default method argument values? I do get that passing null is different from not passing anything w/r/t argument length.
My problem here is that if I now have a method that takes a collection as an argument:
def items(Set<String> items = []) {
new HashSet<>(items)
}
This will throw a NullPointerException if I call items(null) but work fine if I just say items(). In order for this to work right, I have to change the line to be new HashSet<>(items ?: []) which, again, seems to defeat the entire purpose of having default method argument values.
What am I missing here?
In Groovy, default parameters generates overloaded methods. Thus, this:
def items(Set<String> items = []) {
new HashSet<>(items)
}
Will generate these two methods (I used javap to get these values):
public java.lang.Object items(java.util.Set<java.lang.String>);
public java.lang.Object items();
So when you call items(null) you are, in fact, passing some value, and items(Set) method will be used.
You can also refer to this question about default parameters.

Groovy: how to test if a property access will be successful?

I have a variable Object foo, which is not null. I want to use foo.bar, but only if it won't bomb me with 'No such property: bar for class: Whatever'.
How should I do the following test:
if (/*test-here*/) {
use(foo.bar)
}
Use object.hasProperty(propertyName). This will return a truthy value (the property reference) if the property exists. Also object.metaClass.hasProperty(instance, propertyName) is possible. Use object.respondsTo(methodName) to test for method existence.
I do this in my Gradle scripts:
if(project.hasProperty("propertyThatMightExist")){
use(propertyThatMightExist)
}
If you're doing it on lots of foos and bars you could write (once, but before foo is created):
Object.metaClass.getPropertySafe =
{ delegate.hasProperty(it)?.getProperty(delegate) }
Then you can write:
foo.getPropertySafe('bar')
This worked for me :
Customer.metaClass.properties.find{it.name == 'propertyName'}.
Customer in this example is a domain class. Not sure if it will work for a plain Groovy class
boolean exist = Person.metaClass.properties.any{it.name == 'propName'}
if propName is an attribute ,exist=true // vice versa
I can't speak for Groovy specifically, but in just about every dynamic language I've ever used the idiomatic way of doing this is to just do it, and catch the exception if it gets thrown, and in the exception handler do whatever you need to do to handle the situation sensibly.

Add 'TimeOut' parameter to 'Func<>' in C# 4.0

Using C# 4.0 features I want a generic wrapper for encapsulating functions and add a TimeOut parameter to them.
For example we have a function like:
T DoLengthyOperation()
Using Func we have:
Func<T>
This is good and call the function even Sync (Invloke) or Async(BeginInvoke).
Now think of a TimeOut to be added to this behavior and if DoLengthyOperation() returns in specified time we have true returned, otherwise false.
Something like:
FuncTimeOut<in T1, in T2, ..., out TResult, int timeOut, bool result>
Implement C# Generic Timeout
Don't return true/false for complete. Throw an exception.
I don't have time to implement it, but it should be possible and your basic signature would look like this:
T DoLengthyOperation<T>(int TimeoutInMilliseconds, Func<T> operation)
And you could call this method either by passing in the name of any Func<T> as an argument or define it place as a lambda expression. Unfortunately, you'll also need to provide an overload for different kind of function you want, as there's currently no way to specify a variable number a generic type arguments.
Instead of mixing out and bool I would instead construct a separate type to capture the return. For example
struct Result<T> {
private bool _isSuccess;
private T _value;
public bool IsSucces { get { return _success; } }
public T Value { get { return _value; } }
public Result(T value) {
_value = value;
_isSuccess = true;
}
}
This is definitely possible to write. The only problem is that in order to implement a timeout, it's necessary to do one of the following
Move the long running operation onto another thread.
Add cancellation support to the long running operation and signal cancellation from another thread.
Ingrain the notion of timeout into the operation itself and have it check for the time being expired at many points in the operation.
Which is best for you is hard to determine because we don't know enough about your scenario. My instinct though would be to go for #2 or #3. Having the primary code not have to switch threads is likely the least impactful change to your code.

Resources