I followed this tutorial on using structs on GPU:
https://cuda.juliagpu.org/stable/tutorials/custom_structs/
It gives solid start, but I find the structs afterwards very confusing when I can't easily see types of each field.
I modified the Interpolate structure to this, which still works and I can successfully adapt it:
struct Interpolate{N <: Number,A <: DenseArray{N}}
xs::A
ys::A
end
This is better, because at least I can find the types there, but doesn't really fit with other non-CUDA structures.
This make me wonder, wouldn't it be possible to create macro, that modifies struct defined like this into the one above?
#some_magic_macro struct Interpolate
xs::DenseArray{Number}
ys::DenseArray{Number}
end
That would make the code a lot more friendly and CPU-style like more.
Related
I'm creating a custom terraform provider and I came across this issue.
I was trying to convert a schema.TypeList field into a struct, the TypeList looks something like this:
"template": {
Type: schema.TypeList,
Required: true,
ForceNew: false,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"lists_test": {
Type: schema.TypeSet,
Required: true,
ForceNew: false,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"name_test": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
},},
and the struct that I'm trying to align to looks something like this:
type TestStruct struct {
NameTest string `json:"name_test"`
ListsTests []string `json:"lists_test"`
}
I tried a couple of solutions, for instance I tried unmarshalling it to json. Something like below:
template := d.Get("template").([]interface{})[0].(map[string]interface{})
templateStr, err := json.Marshal(template)
templateConverted := &TestStruct{}
json.Unmarshal(template, templateConverted)
however, I'm getting an error json: unsupported type: SchemaSetFunc, which is probably because it's trying to marshal a schema.Schema type instead of map[string]interface{} type, which confuses me. I also tried to use gohcl.DecodeBody but I abandoned the idea since it's usage seems more inclined into reading direct tf files rather than *schema.ResourceData types.
Does anyone had the same experience dealing with this type of scenario? Any help or suggestion is appreciated. Thank you!
Terraform's older SDK (SDKv2) is not designed around the paradigm of decoding into a tagged structure, and instead expects you to use d.Get and manually type-assert individual values, which in your case would perhaps look something like this:
raw := d.Get("template").([]interface{})[0].(map[string]interface{})
t := &TestStruct{
NameTest: raw["name_test"].(string),
ListsTests: make([]string, len(raw["lists_test"].([]interface{})),
}
for i, itemRaw := range raw["lists_test"].([]interface{}) {
t.ListsTests[i] = itemRaw.(string)
}
The idiomatic style for most Terraform providers is to write logic like this in separate functions for each complex-typed attribute, where each returns an object of the appropriate type in the target platform's SDK. There would typically also be a matching function for going in the opposite direction: given an object from the target platform's SDK, return a map[string]interface{} that can be assigned to this attribute using d.Set.
However, just because there isn't something built in to the SDK to handle this, that doesn't mean you can't use other libraries that are more general utilities for use in any Go programs.
One example library is github.com/mitchellh/mapstructure, which is designed for exactly the goal you have in mind: to take a value of some interface type and try to use reflection to fit it onto a tagged structure type.
If you want to use that library then you would need to annotate your structure with mapstructure:, instead of the json: ones, and then pass your raw value to the mapstructure.Decode function:
raw := d.Get("template").([]interface{})[0].(map[string]interface{})
var t TestStruct
err := mapstructure.Decode(raw, &t)
Since the schema.ResourceData abstraction in SDKv2 guarantees to return specific data types based on the schema you defined, you should not typically get errors from mapstructure.Decode as long as your schema and your target type match, but still a good idea to check for errors anyway because otherwise your t value may not be completely populated, causing confusing broken behavior downstream.
This is not a typical implementation style used in the official providers, but there's no real harm in writing your provider in this way if you find this style more convenient, or easier to maintain.
Alternatively, if you are not already deeply invested in SDKv2 then you may wish to consider using Terraform Plugin Framework instead. As well as being designed around the type system of modern Terraform (whereas SDKv2 was designed for Terraform v0.11 and earlier), it also supports a programming style more like what you are aiming for, with methods like tfsdk.Plan.Get and tfsdk.Plan.GetAttribute that can decode directly into an appropriately-shaped and appropriately tagged "normal" Go value.
I can't easily show an example of that because it would presume a provider written in quite a different way, but hopefully you can see from the signature of those two functions how they might be used. There's some more commentary and examples in Accessing State, Config, and Plan.
I'm redoing the backend of a very basic framework that connects to a completely customizable frontend. It was originally in PHP but for the refactor have been plodding away in F#. Although it seems like PHP might be the more suited language. But people keep telling me you can do everything in F# and I like the syntax and need to learn and this seemingly simple project has me stumped when it comes to JSON. This is a further fleshed out version of my question yesterday, but it got alot more complex than I thought.
Here goes.
The frontend is basically a collection of HTML files, which are simply loaded in PHP and preg_replace() is used to replace things like [var: varName] or [var: array|key] or the troublesome one: [lang: hello]. That needs to be replaced by a variable defined in a translation dictionary, which is stored as JSON which is also editable by a non-programmer.
I can't change the frontend or the JSON files, and both are designed to be edited by non-programmers so it is very likely that there will be errors, calls to language variables that don't exist etc.
So we might have 2 json files, english.json and french.json
english.json contains:
{
"hello":"Hello",
"bye":"Goodbye"
}
french.json:
{
"hello": "Bonjour",
"duck": "Canard"
//Plus users can add whatever else they want here and expect to be able to use it in a template
}
There is a template that contains
<b>[lang: hello]</b>
<span>Favourite Animal: [lang:duck]</span>
In this case, if the language is set to "english" and english.json is being loaded, that should read:
<b>Hello</b>
<span>Favourite Animal: </span>
Or in French:
<b>Bonjour</b>
<span>Favourite Animal: Canard</span>
We can assume that the json format key: value is always string:string but ideally I'd like to handle string: 'T as well but that might be beyond the scope of this question.
So I need to convert a JSON file (called by dynamic name, which gave F# Data a bit of an issue I couldn't solve last night as it only allowed a static filename as a sample, and since these two files have potential to be different from sample and provided, the type provider doesn't work) to a dictionary or some other collection.
Now inside the template parsing function I need to replace [lang: hello] with something like
let key = "duck"
(*Magic function to convert JSON to usable collection*)
let languageString = convertedJSONCollection.[key] (*And obviously check if containsKey first*)
Which means I need to call the key dynamically, and I couldn't figure out how to do that with the type that FSharp.Data provided.
I have played around with some Thoth as well to some promising results that ended up going nowhere. I avoided JSON.NET because I thought it was paid, but just realised I am mistaken there so might be an avenue to explore
For comparison, the PHP function looks something like this:
function loadLanguage($lang='english){
$json = file_get_contents("$lang.json");
return json_decode($json, true);
}
$key = 'duck';
$langVars = loadLanguage();
$duck = $langVars[$key] || "";
Is there a clean way to do this in F#/.NET? JSON seems really painful to work with in comparison to PHP/Javascript and I'm starting to lose my mind. Am I going to have to write my own parser (which means probably going back to PHP)?
Cheers to all you F# geniuses who know the answer :p
open Thoth.Json.Net
let deserialiseDictionary (s: string) =
s
|> Decode.unsafeFromString (Decode.keyValuePairs Decode.string)
|> Map.ofList
let printDictionary json =
json
|> deserialiseDictionary
|> fun m -> printfn "%s" m.["hello"] // Hello
For the question about 'T the question becomes, what can 'T be? For json it very limited, it can be a number of things, string, json-object, number, bool or json array. What should happen if it is bool or a number?
This might seem like a silly question, but I want to make a struct with a collection of functions, but the functions bind to the struct. I can sorta see that this is a cycle, but humor me with this example:
type FuncType func() error
type FuncSet struct {
TokenVariable int
FuncTyper FuncType
}
and I want to be able to create a function bound to the FuncSet type so it can operate on TokenVariable, thusly:
func (f *FuncSet) FuncType() error {
f.TokenVariable = 100
return nil
}
However, this changes the signature of the type (I can't find any information about type bindings as part of function type specifications) such that assigning this function to the struct element tells me this function/variable is not found.
I can see an easy work-around for this, by prefixing the parameters with a pointer to the struct type, it's just a bit ugly.
I looked around a little further and discovered that what I'm kinda looking for is like a closure in that it can be passed a variable from the immediate outer scope but... well, I'll be glad to be corrected about this absence of type binding in function types, but for now passing the pointer to the type looks like the way to go.
I think I found the solution:
type nullTester func(*Bast, uint32) bool
type Bast struct {
...
isNull nullTester
...
}
func isNull(b *Bast, d uint32) bool {
return d == 0
}
and then I can bind it to the type like this:
func NewBast() (b *Bast) {
...
b.isNull = isNull
...
}
// IsNull - tests if a value in the tree is null
func (b *Bast) IsNull(d uint32) bool {
return b.isNull(b, d)
}
It seems a bit hackish and I'm not sure what's going to happen in a second library that I will write that sets a different type for the uint32 parameter, but go vet is happy so maybe this is the correct way to do it.
It does seem to me that func types should really have a field in the grammar to specify a binding type, but maybe I just found a hack that sorta lets me do polymorphism. In calling programs all they will see is the nice exported function that binds to the type as planned and I get my readability as well as being able to retarget the base library to store a different type of data.
I think this is the proper solution. I just can't find anything that confirms or denies whether in a type Name func specification there is any way of asserting the type. It really should not match up, since the binding is part of the signature, but the syntax for type with functions does not appear to have this type binding.
My actual code is here, and you can see by looking at it what I am aiming to do:
https://github.com/calibrae-project/bast/blob/master/pkg/bast/bast.go
The differences between the type of data the tree stores is entirely superficial, because it is intended to be primarily used for sorting unsigned integers of various lengths, and one important thing it needs to have is to be able to work from a, for example, 64 bit integer but sort only by the first or last half (as I have a bigger project that treats these hash values as coordinates in an adjacency list). In theory it could be used instead of a hash table lookup as well, with a low variance in time to find elements because of the binary tree structure.
It's not a conventional, reference-vector based tree, and the store itself is an array with an unconventional power of two mapping, a 'dense' tree, and the purpose above all, for implementing this way, is that when the tree is walked, as well as rotated, much of the time it is sequential blocks of memory being accessed which should make for a lot less cache misses than a conventional binary tree (and for which reason generally this type of application just uses some kind of sort like a bucket sort).
You could use an anonymous field with an interface that defines the method set that you want to use (that might change).
Go playground here
You'd define your interface
type validator interface {
IsRightOf(a, b interface{}) bool
... // other methods
}
and your type:
type Bast struct {
validator // anonymous interface field
... // some fields
}
Then you can access the methods of validator from the Bast type
b := bast.New()
b.IsRightOf(c, d) // this is valid, you do not need to do b.validator.IsRightOf(...)
because validator is an interface you can change those methods how you like.
Since SWIG can't parse the __attribute__((packed)) on some C structs I'd like to wrap, I work around this by putting a
#define __attribute__(x)
in my .i file.
When will this come and bite me?
This is actually perfectly sane. SWIG doesn't need to know anything about the layout of the structs you're wrapping in order to be able to generate correct code. (It doesn't even need to know about all the members they contain even).
The reason for this is that the code which is generated is largely just marshaling data. In C you can legally write:
void show_a(const struct foo *instance) {
printf("%s", instance->b);
}
Regardless of whether foo was defined as:
struct foo {
double a;
char *b;
}
or
struct foo {
char *b;
double a,c;
int xyz;
}
The only place where the packing/alignment matters is when creating new structs. This is handled correctly though also, provided you don't also hide the attribute from the C compiler itself, because the generated C wrapper code will be using the real definition and not the pseudo one that you showed in the interface file.
It's a little bit clunky, but you can convince yourself of this as required by reading through the generated wrapper.
The general answer is that you can lie to SWIG itself quite a lot and it'll all work out alright in the end when the C compiler sees the generated code and reconciles it with the real definitions/declarations.
In the specific case the short answer is: so long as you only put that #define in the .i file and then only in a place where it doesn't get passed out to your generated module_wrap.c you're fine.
import std.stdio;
class IntegerContainer
{
public int Integer = 1;
}
void DoubleInteger(IntegerContainer Container)
{
Container.Integer *= 2;
}
void main()
{
IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one.
DoubleInteger(Container); // Internal integer changes to two inside the function.
writefln(Container.Integer); // Prints "2."
}
In D, reference vs. value is a trait of the type, rather than of the function parameter. Coming from C++, this feels really bad to me.
It looks like there's a ref keyword to force pass-by-reference for functions accepting structs. Is there such an equivalent for passing classes by value?
For example, let's say I want to make a function function that returns a sorted copy of a custom container class. In C++, that's as simple as using Foo Sorted(Foo Object), as opposed to Foo Sort(Foo& Object). I see no way of doing this in D without manually copying the object.
Classes are reference types by design. They're not supposed to be passed by value. It's exactly the same with Java and C#. However, unlike Java and C#, D has full-fledged user-defined value types as well, since it has structs (C# has structs too, but they're much more limited). The fact that C++ conflates the two causes problems such as object slicing.
Now, obviously there are times when you want to copy a reference type. The solution to that is cloning. You give your class a clone function which returns a copy of the object it's called on. That way, you can copy it when you need to, and it only gets copied when you need it to be. Java and C# have a standard clone function that most types implement, but for whatever reason D does not. I'm not sure why. But it's still easy enough to declare such a function yourself for your own types. It just isn't going to be on Object, which would allow you to use it on pretty much any class object without caring what the actual type was like you can do in Java and C#. You could always create a copy constructor instead, if you prefer, but it's less flexible, because you have to know the type of the object being copied, whereas with clone, it can be any type derived from the type that clone returns (which would be Object in the case of Java and C# but would be whatever you decide in D, since the function is non-standard).
Yeah, just use a struct instead of a class.
But if you want to copy an object, then you have to implement cloning yourself. Note that the D designers didn't make this up; it's the exact same way in C#, and pretty similar in Java. The goal is to prevent objects from being copied excessively, which is seen as a downside of C++ (since it's very hidden in the code).
Even in C++ this:
Foo Sorted(Foo Object)
is not that useful. What if the Object is already sorted and you don't need to create a copy?
In D you will need to provide clone() of some such for your class and call it if needed.
Otherwise use structs as Mehrdad mentioned.
Edit: It is not clear what exactly "copying the object" should do. If it has array of objects inside shall it clone that array? And what about object references it contains? It is actually good that monsieur Walter Bright, author of D, did not provide copying of class instances by default.