How to access class or record field with the name of the field as a string? - reflection

Say you have a record or class:
record R {
var value: int;
}
How can I access the field value by using the string "value"?
For example, in Python, you can access fields using the getattr built-in:
class C:
def __init__(self, val):
self.value = val
c = C(2)
print(getattr(c, 'value')) # prints 2
What would this look like in Chapel?

The Reflection module's getField() and getFieldRef() routines provide this capability. For example, the following program both reads and writes the field 'value' (TIO):
use Reflection;
record R {
var value: int;
}
var myR = new R(2);
writeln(getField(myR, "value")); // print the field from 'myR' named "value"
getFieldRef(myR, "value") = 42; // get a reference to the field from 'myR' named "value" and assign to it
writeln(myR); // print the resulting record

Related

Deferencing type maps

I am trying to dereference a channel and use the payload in the channel to check if there is an entry in the map or not.
If the map is of not type it works but if the map has a type I always get the error that type <map> is not an expression.
type writechan chan UserProfile
type usersmap map[string]UserProfile
var myuserprofile UserProfile
myuserprofile = <-myuserchannel
var username = myuserprofile.name
if _, ok := usersmap[username]; ok {
fmt.Println("Already registered ")
} else {
usersmap[username] = myuserprofile
}
The error message says type usersmap is not an expression" in the if line . If I don't use the type usermap but a normal map say map[string]string it works fine.
type usersmap map[string]UserProfile
This is a type declaration, it does not create a variable named usersmap. After this type declaration you may use the usersmap (type) identifier to create a variable like this:
var umap usersmap
And to initialize it:
umap = make(usersmap)
Or in one line:
var umap = make(usersmap)
Or using a short variable declaration with initialization:
umap := usersmap{}
Also to create a variable of map type you don't necessarily have to create a new type, you may simply write:
var umap = make(map[string]UserProfile)

Looping through dictionary in Swift 3 errror

I have a dictionary that I declare like so:
var dictBarData = [String: Any]()
I then declare and populate a second dictionary like so, and then add the second dictionary to the first:
var dictThisBar = [String:Any]()
dictThisBar["category"] = category
dictThisBar["barValue"] = value
dictThisBar["barView"] = vThisBar
dictBarData[String(barIndex)] = dictThisBar
When I go to retrieve them I do this:
for (key, value) in dictBarData {
let dictThisBar = dictBarData[key]
for(key, value) in dictThisBar {
}
}
But I am getting an error on the second for loop, type Any does not conform to protocol sequence. Type Any does not conform to sequence protocol
According to the declaration all values in dictBarData are Any.
You have to cast the value down to
let dictThisBar = dictBarData[key] as! [String:Any]
However it's highly recommended to use optional bindings
if let dictThisBar = dictBarData[key] as? [String:Any] { ...

Set a struct field with field type of a interface

Is there any way to set an interface field using reflect? When i tried to set it, it paniced saying that the value is non addressable.
type A interface{...}
func CreateA(name string) A {...}
type B struct {
field A
should A
mirror A
}
// normal way of initializing
var b = B{
field: CreateA("field"),
should: CreateA("should"),
mirror: CreateA("mirror"),
}
func MirrorField(b *B) {
t := reflect.TypeOf(b)
v := reflect.ValueOf(b)
for i := 0; i < t.NumField(); i++ {
setTo = CreateA(t.Field(1).Name)
fieldVal := v.Field(i)
fieldVal.Set(reflect.ValueOf(setTo))
}
}
// what i want is something like
var b = &B{}
MirrorField(b)
Interfaces don't have fields, they only define a method set of the value they contain. When reflecting on an interface, you can extract the value with Value.Elem().
You also can't Set unexported fields. You need to capitalize the field names in your B type. When iterating over the fields, use Value.CanSet() to test if they are settable. CanSet() will also return false is the value isn't addressable, or the value is still in an interface.
A working example of your code:
http://play.golang.org/p/Mf1HENRSny

How to insert values into a nested Swift Dictionary

I'm trying to insert new key-value pair in dictionary, which nested in another one Dictionary:
var dict = Dictionary<Int, Dictionary<Int, String>>()
dict.updateValue([1 : "one", 2: "two"], forKey: 1)
dict[1]?[1] // {Some "one"}
if var insideDic = dict[1] {
// it is a copy, so I can't insert pair this way:
insideDic[3] = "three"
}
dict // still [1: [1: "one", 2: "two"]]
dict[1]?[3] = "three" // Cannot assign to the result of this expression
dict[1]?.updateValue("three", forKey: 3) // Could not find a member "updateValue"
I believe should be a simple way to handle it, but I spent an hour and still can't figure it out.
I can use NSDictionary instead, but I really like to understand how I should manage nested Dictionaries in Swift?
Dictionarys are value types so are copied on assignment. As a result you are going to have to get the inner dictionary (which will be a copy), add the new key, then re-assign.
// get the nested dictionary (which will be a copy)
var inner:Dictionary<Int, String> = dict[1]!
// add the new value
inner[3] = "three"
// update the outer dictionary
dict[1] = inner
println(dict) // [1: [1: one, 2: two, 3: three]]
You could use one of the new utility libraries such as ExSwift to make this a bit simpler:
dict[1] = dict[1]!.union([3:"three"])
This uses the union method that combines two dictionaries.

Upcasting F# record created through reflection

I've been messing about with F# and it's Reflection, trying to create a Record type object dynamically from within F#, I got most of it working (as you can see below) but one thing - the record I create through reflection has type "obj" instead the one it should ("Person") and I can't seem to be able to upcast it in any way.
#light
type Person = {
Name:string;
Age:int;
}
let example = {Name = "Fredrik"; Age = 23;}
// example has type Person = {Name = "Fredrik"; Age = 23;}
let creator = Reflection.FSharpValue.PrecomputeRecordConstructor(example.GetType(),
System.Reflection.BindingFlags.Public)
let reflected = creator [| ("thr" :> obj); (23 :> obj) |]
// here reflected will have the type obj = {Name = "thr"; Age = 23;}
// Function that changes the name of a Person record
let changeName (x:Person) (name:string) =
{ x with Name = name }
// Works with "example" which is has type "Person"
changeName example "Johan"
// But not with "reflected" since it has type "obj"
changeName reflected "Jack" // Error "This expression has type obj but is here used with type Person. "
// But casting reflected to Person doesn't work either
(reflected :> Person) // Type constraint mismatch. The type obj is not compatible with
// type Person. The type 'obj' is not compatible with the type 'Person'.
// C:\Users\thr\Documents\Visual Studio 2008\Projects\
// Reflection\Reflection\Script.fsx 34 2 Reflection
Try using the other cast operator (as you're casting the other way this time)
So changeName (reflected :?> Person) "Jack"

Resources