How to instantiate a shape type object in hacklang - hacklang

This seems like it should be in the documentation, but it isn't.
I have a shape type.
type ThisIsMyShapeType = shape(
'some_prop' => bool,
);
How do I instantiate an object of this type ?

You use the same shape keyword:
$x = shape(
'some_prop' => true,
);
In Hack, shapes use structural typing so you don't need to declare your variable is a ThisIsMyShapeType -- the typechecker will verify that $x has all of the right fields to match the type.
There are quite a few examples in the official documentation.

Related

What is # symbol in ABAP?

I found a piece of code like in the picture, in this case I know more or less what it causes, but generally I don't know the #( ) syntax.
What is the #( ) syntax and where can I find more about it?
DATA: lv_str TYPE string VALUE 'ABCD'.
DATA: dref1 TYPE REF TO data.
DATA: dref2 TYPE REF TO data.
* Old Syntax
GET REFERENCE OF LV_STR INTO dref1.
* New Syntax
dref2 = REF #( LV_STR ).
BREAK-POINT.
The # is a placeholder for the type of the variable.
You could write line 11 as this as well:
dref2 = REF data( lv_str ).
That would do the same thing. The # automatically takes the type of the variable on the left, if you don't specify it.
I've not seen it with TYPE REF TO before this, but it's fairly common as
VALUE #( )
I haven't found any documentation on the REF #( ) version but here is the official SAP documentation for VALUE #( ), it explains what the # does too.
The documentation of the Reference Operator REF states:
The # character for a data type that is determined by the following hierarchy:
If the data type required in an operand position is unique and known completely, the operand type is used.
If the operand type cannot be derived from the context, the data type of dobj is used.
If the data type of dobj is not known statically, the generic type data is used.
And also, I think that the "mother" documentation chapter is Constructor Operators for Constructor Expressions:
If the data type required in an operand position is unique and can be identified completely, the # character can be used instead of an explicit type specification type and the operand type is used.
If the operand type is not unique and is not known completely, if possible, a type inference is performed to determine a data type.
This is described in each constructor expression.
(NEW, VALUE, CONV, CORRESPONDING, CAST, REF, EXACT, REDUCE, FILTER, COND, SWITCH)

How to convert data type if Variant.Type is known?

How do I convert the data type if I know the Variant.Type from typeof()?
for example:
var a=5;
var b=6.9;
type_cast(b,typeof(a)); # this makes b an int type value
How do I convert the data type if I know the Variant.Type from typeof()?
You can't. GDScript does not have generics/type templates, so beyond simple type inference, there is no way to specify a type without knowing the type.
Thus, any workaround to cast the value to a type only known at runtime would have to be declared to return Variant, because there is no way to specify the type.
Furthermore, to store the result on a variable, how do you declare the variable if you don't know the type?
Let us have a look at variable declarations. If you do not specify a type, you get a Variant.
For example in this code, a is a Variant that happens to have an int value:
var a = 5
In this other example a is an int:
var a:int = 5
This is also an int:
var a := 5
In this case the variable is typed according to what you are using to initialized, that is the type is inferred.
You may think you can use that like this:
var a = 5
var b := a
Well, no. That is an error. "The variable type can't be inferred". As far as Godot is concerned a does not have a type in this example.
I'm storing data in a json file: { variable:[ typeof(variable), variable_value ] } I added typeof() because for example I store an int but when I reassign it from the file it gets converted to float (one of many other examples)
It is true that JSON is not good at storing Godot types. Which is why many authors do not recommend using JSON to save state.
Now, be aware that we can't get a variable with the right type as explained above. Instead we should try to get a Variant of the right type.
If you cannot change the serialization format, then you are going to need one big match statement. Something like this:
match type:
TYPE_NIL:
return null
TYPE_BOOL:
return bool(value)
TYPE_INT:
return int(value)
TYPE_REAL:
return float(value)
TYPE_STRING:
return str(value)
Those are not all the types that a Variant can hold, but I think it would do for JSON.
Now, if you can change the serialization format, then I will suggest to use str2var and var2str.
For example:
var2str(Vector2(1, 10))
Will return a String value "Vector2( 1, 10 )". And if you do:
str2var("Vector2( 1, 10 )")
You get a Variant with a Vector2 with 1 for the x, and 10 for the y.
This way you can always store Strings, in a human readable format, that Godot can parse. And if you want to do that for whole objects, or you want to put them in a JSON structure, that is up to you.
By the way, you might also be interested in ResourceFormatSaver and ResourceFormatLoader.

How to use Nim's `of` operator with generics?

Consider a type hierarchy, where the base object is non-generic, but sub-types are:
type
TestBase = ref object of RootObj
DerivedA = ref object of TestBase
DerivedB[T] = ref object of TestBase
field: T
proc testProc(x: TestBase) =
if x of DerivedB: # <= what to do here
echo "it's a B!"
else:
echo "not a B"
Using the of operator like this won't compile, because it expects object types. What does work is e.g. to match for specific types like DerivedB[int], or making the proc itself generic in T, which is meaningless when passing in a DerivedA.
Is there a way to solve this problem generically without resorting to methods and dynamic dispatch?
The easiest solution here is to introduce a dummy base type for all of the generic derived types, with the only purpose of assisting in such checks. Here is an example:
type
TestBase = ref object of RootObj
DerivedA = ref object of TestBase
# I'm using illustrative names here
# You can choose something more sensible
DerivedDetector = ref object of TestBase
DerivedB[T] = ref object of DerivedDetector
field: T
proc testProc(x: TestBase) =
if x of DerivedDetector: # This will be true for all derived types
echo "it's a B!"
else:
echo "not a B"
testProc DerivedB[int](field: 10)
testProc DerivedA()
This solution won't increase the size of the objects and it doesn't introduce any run-time overhead in typical code.
If you can't modify the inheritance hierarchy (it may be part of a third-party library), there is a much more complicated solution based on the getTypeInfo proc from the system module. This proc returns an opaque pointer that can be used as an identifier for the type. You'll have to register all derived types with their identifiers in a hash table (you can do this at the start of the program) and then use that to make run-time checks against the type-info pointers of the input values in the proc.

what is nim type definition for generic procedure?

I have a strategies expressed as generics in nim:
proc fooStrategy[T](t: T, ...)
proc barStrategy[T](t: T, ...)
I would like to create a lookup table for the strategies by name... so I tried:
type
Strategy*[T] = proc[T](t: T, ...)
let strategies* = toTable[string, Strategy[T]]([
("foo", fooStrategy), ("bar", barStrategy)])
This doesn't work -- the type declaration fails. If I were to get by that I could guess that the table of strategies would also have problems. Is there another way to do this? "T" is supposed to be "some 1D collection type" -- could be sequence, array, vector from blas, etc. I could add concrete strategies to the table for common collections, but I still have the problem with the function pointer, as
type
Strategy* = proc(t: any, ...)
let strategies* = toTable[string, Strategy]([
("foo-seq[int]", fooStrategy[int]), ...])
still has problems. Any suggestions?
There are multiple issues with your code:
Firstly, initTable does not take a list of items for the table. It only takes an initial size. You want to use toTable instead.
Secondly, you must explicitly set a value for the generic parameter T when creating a table, because at runtime, all generic parameters must be bound to a type.
Thirdly, the proc types have to exactly match, including pragmas on the proc. This one's tricky.
Here is a working example:
import tables
type
Strategy*[T] = proc(t: T) {.gcsafe, locks: 0.}
proc fooStrategy[T](t: T) = echo "foo"
proc barStrategy[T](t: T) = echo "bar"
let strategies* = toTable[string, Strategy[int]]([
("foo", fooStrategy[int]), ("bar", barStrategy[int])
])
For this example, I create a table with Strategy[int] values (you cannot have a table with Strategy[T] values as this is not a concrete type). I instantiate both fooStrategy and barStrategy with [int] to match the table type. I added {.gcsafe, locks: 0.} to the type definition. If this is omitted, you will get a compiler error:
test.nim(9, 49) Error: type mismatch: got (Array constructor[0..1, (string, proc (t: int){.gcsafe, locks: 0.})])
but expected one of:
proc (pairs: openarray[(string, Strategy[system.int])]): Table[system.string, Strategy[system.int]]{.gcsafe, locks: 0.}
As you see, the compiler tells you in the first line what it sees and in the third line what it expects. it sees procs with {.gcsafe, locks: 0.} because those pragmas are implicitly assigned to the procs defined above. The pragmas change the type, so to be able to assign those procs to Strategy[T], you have to define the same pragmas to Strategy[T].

How Can a String Array Call Generic Select Method with <string,string>

I am new to Generic Classes and Generic Methods. I have a simple cpode:
Func<string, string> selector = str => str.ToUpper();
string[] words = { "orange", "apple", "Article", "elephant" };
IEnumerable<String> aWords = words.Select(selector);
When I look at Select method it says:
IEnumerable<String> IEnumerable<String>.Select<String, String>(Func<string,string> collector)
How does Select generic method knows that String,String types are coming? Does it implicitly come from "selector" delegate? I am really confused.
Thanks
The C# compiler infers the type arguments for Select so that you don't have to type them. It burns those types into the compiled assembly.
Does it implicitly come from "selector" delegate?
Exactly. C# has some type inference so that you have to type less.
The Select method itself has no idea what piece of code called it. All it knows is that the type arguments are properly provided.

Resources