I'm trying to write an expression that will call ToString on a property and assign it's value to a local variable. However, calling ToString on a object instance w/ an overload of ToString, causes an exception of "Ambigous Match Found" to be thrown. Here's an example:
var result = Expression.Variable(typeof(string), "result");
var matchTypeParameter = Expression.Parameter(typeof(MatchType), "matchType");
var targetProperty = Expression.Property(leadParameter, target);
var exp = Expression.Block(
//Add the local current value variable
new[] { result },
//Get the target value
Expression.Assign(result, Expression.Call(targetProperty, typeof(string).GetMethod("ToString"), null))
);
How can I call ToString if the instance has overloads for it? Thanks!
Replace:
typeof(string).GetMethod("ToString")
With:
typeof(string).GetMethod("ToString", Type.EmptyTypes)
In other words, get the method named "ToString" that takes zero arguments (empty type array).
Related
I have a shape like this
const type TFileInfo = shape(
'displayName' => string,
'givenName' => string,
'jobTitle' => string,
'businessPhones' => vec<string>
);
private Person::TFileInfo $person;
Now my constructor of the class looks like so
public function __construct(string $apiresponse) { // instance method
$json = \json_decode($response, /* associative = */ true);
TypeAssert\matches<self::TFileInfo>($json);
$this->person = $json; //OFFENDING LINE
$this->person['businessPhones1'] = "";
}
Now strangely the above code does not throw any error .
If I remove the offending line , then the last line throws a compile time error Expected nothing because the field 'businessPhones1' is not defined in this shape type, and this shape type does not allow unknown fields
What am I missing here ? Is there a better way to assign an API response to a typed variable ?
TypeAssert\matches doesn't prove that its argument is the type you specified, in contrast to the behavior of some other built-ins like is_null which are special-cased in the typechecker. Instead, it coerces the argument and returns it, so you need to move your standalone call to the assignment, i.e. $this->person = TypeAssert\matches<self::TFileInfo>($json);.
You might have expected a type error from the $this->person = $json assignment then, but in fact json_decode and some other unsafe built-in PHP functions are special-cased by the typechecker to be bottom types (convertible to anything) so they could be usable at all before type-assert. It remains this way today: see its type definition in the HHVM source, probably for compatibility.
One other interesting point about this case is that $this->person = $json coerces $this->person to a bottom type as well downstream of the binding. To my understanding, this is a specific behavior of the Hack typechecker to do this for a single level of property nesting, yet it preserves the types for properties of properties (the second example has_error):
<?hh // strict
class Box<T> { public function __construct(public T $v) {} }
function no_error<T>(Box<int> $arg): T {
$arg->v = json_decode('');
return $arg->v;
}
function has_error<T>(Box<Box<int>> $arg): T {
$arg->v->v = json_decode('');
return $arg->v->v;
}
It's difficult to explain the case by words, let me give an example:
var myObj = {
'name': 'Umut',
'age' : 34
};
var prop = 'name';
var value = 'Onur';
myObj[name] = value; // This does not work
eval('myObj.' + name) = value; //Bad coding ;)
How can I set a variable property with variable value in a JavaScript object?
myObj[prop] = value;
That should work. You mixed up the name of the variable and its value. But indexing an object with strings to get at its properties works fine in JavaScript.
myObj.name=value
or
myObj['name']=value (Quotes are required)
Both of these are interchangeable.
Edit: I'm guessing you meant myObj[prop] = value, instead of myObj[name] = value. Second syntax works fine: http://jsfiddle.net/waitinforatrain/dNjvb/1/
You can get the property the same way as you set it.
foo = {
bar: "value"
}
You set the value
foo["bar"] = "baz";
To get the value
foo["bar"]
will return "baz".
You could also create something that would be similar to a value object (vo);
SomeModelClassNameVO.js;
function SomeModelClassNameVO(name,id) {
this.name = name;
this.id = id;
}
Than you can just do;
var someModelClassNameVO = new someModelClassNameVO('name',1);
console.log(someModelClassNameVO.name);
simple as this
myObj.name = value;
When you create an object myObj as you have, think of it more like a dictionary. In this case, it has two keys, name, and age.
You can access these dictionaries in two ways:
Like an array (e.g. myObj[name]); or
Like a property (e.g. myObj.name); do note that some properties are reserved, so the first method is preferred.
You should be able to access it as a property without any problems. However, to access it as an array, you'll need to treat the key like a string.
myObj["name"]
Otherwise, javascript will assume that name is a variable, and since you haven't created a variable called name, it won't be able to access the key you're expecting.
You could do the following:
var currentObj = {
name: 'Umut',
age : 34
};
var newValues = {
name: 'Onur',
}
Option 1:
currentObj = Object.assign(currentObj, newValues);
Option 2:
currentObj = {...currentObj, ...newValues};
Option 3:
Object.keys(newValues).forEach(key => {
currentObj[key] = newValues[key];
});
I'm experimenting around the idea of a simple logger that would look like this:
log(constant: String, _ variable: [String: AnyObject]? = nil)
Which would be used like this:
log("Something happened", ["error": error])
However I want to prevent misuse of the constant/variable pattern like the following:
log("Something happened: \(error)") // `error` should be passed in the `variable` argument
Is there a way to make sure that constant wasn't constructed with a string interpolation?
You could use StaticString instead of String:
func log(constant: StaticString, _ variable: [String: AnyObject]? = nil) {
// You can retrieve `String` from `StaticString`
let msg = constant.stringValue
}
let foo = 1
log("test \(foo)") // -> error: cannot invoke 'log' with an argument list of type '(String)'
Is it possible to log variable name (not value) in JavaScript?
var max_value = 4;
console.log(max_value); // should log "max_value" as a string
UPDATE: I need a testing function that should be able to log any variable name (passed as an argument) as a string, not just this one variable.
There is a solution that can help you. I grabbed this function from this stackoverflow answer, which is able to get the name of the function parameters:
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
var fnStr = func.toString().replace(STRIP_COMMENTS, '');
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
if(result === null)
result = [];
return result;
}
then all you need to do now, is to use the name of your variable as a parameter of an anonymous function and pass all the function as argument of the getParamNames :
variablesNames = getParamNames(function (max_value, min_value) {});
This will return an array like this :
result => ["max_value", "min_value"];
Let's make it practical, first change the name of the getParamNames function to something easy and small like this :
function __ (func) {
// code here ...
}
second thing, instead of returning an array, just return the first element of the array, change this :
return result;
to this :
return result.shift();
now, you can get the name of your variable like this :
__(function( max_value ){});
I am using PredicateBuilder to generate where clause
var locationFilter = PredicateBuilder.True<dbCompanyLocation>();
locationFilter = locationFilter.And(s => s.IsPrimary == true && s.State == practiceState);
var companyPredicate = PredicateBuilder.True<dbCompany>();
companyPredicate = companyPredicate.And(c => c.dbCompanyLocations.Where(locationFilter));
I am getting following error, Any one can help for this or am i doing something wrong.
Instance argument: cannot convert from 'System.Data.Linq.EntitySet' to 'System.Linq.IQueryable'
The immediate problem seems to be that dbCompany.dbCompanyLocations is an EntitySet, which implements IEnumerable<T> rather than IQueryable<T>. This means its Where extension method expects a Func<dbCompanyLocation, bool>, however the locationFilter variable you are providing is an Expression<Func<dbCompanyLocation, bool>>.
You can create a Func<dbCompanyLocation, bool> from locationFilter by calling the Compile method.
Another problem however is that even if it did type check, c => c.dbCompanyLocations.Where(locationFilter) is not a predicate, since Where returns an IEnumerable<T> instead of a bool. You probably meant to use Any instead of Where i.e.
companyPredicate = companyPredicate.And(c => c.dbCompanyLocations.Any(locationFilter.Compile()));