We have this:
repository.Add<Customer>(c);
...
IQueryable<Customer> result1 = repository.All<Customer>();
Console.WriteLine( result1.Count() );
IQueryable<ICustomer> result2 = result1.Cast<ICustomer>();
Console.WriteLine( result2.Count() ); // error here
That gives the following error:
Expression of type 'System.Collections.Generic.IEnumerable`1[Data.Customer]' cannot be used for parameter of type 'System.Linq.IQueryable' of method 'System.Linq.IQueryable`1[Data.ICustomer] Cast[ICustomer]] (System.Linq.IQueryable)'
Is it possible to work via interfaces?
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;
}
I have a mapFunction as below
Function1<CompanyInfoRecordNew, CompanyInfoTransformedRecord> mapFunction = ( record ) ->{
CompanyInfoTransformedRecord transRec = new CompanyInfoTransformedRecord();
//popluate
return transRec ;
};
Which takes CompanyInfoRecordNew object and return CompanyInfoTransformedRecord.
But while invoking this as below
JavaRDD companyInfoTransformedRecord = baseDs.map(mapFunction, comanyInfoTransEncoder);
Giving Error :
The method map(Function1, Encoder) in the type Dataset is not applicable for the arguments (Function1, Encoder)
What is wrong here ?
Code Link for the same :
https://gist.github.com/BdLearnerr/cbfea1c8471557bb33449f882cc1854a
How to return a List from map function?
Code updated in the link
https://gist.github.com/BdLearnerr/cbfea1c8471557bb33449f882cc1854a
Section 2 :
MapFunction<CompanyInfoRecordNew, List<CompanyInfoTransformedRecord>> mapFunction = ( record ) ->{
List<CompanyInfoTransformedRecord> transRecList = new ArrayList<CompanyInfoTransformedRecord>();
return transRecList ;
}
Dataset<List<CompanyInfoTransformedRecord>> companyInfoTransformedRecords = baseDs.map(mapFunction, comanyInfoTransEncoder);
//Error
The method map(Function1, Encoder) in the
type Dataset is not applicable for the arguments
MapFunction>,
Encoder)
companyInfoTransformedRecord.show();
Not able to do show due to error , how to get show() working. ??
Your imports are wrong, instead of this:
import org.apache.calcite.linq4j.function.Function1;
Use this
org.apache.spark.api.java.function.MapFunction;
baseDs.map(new MapFunction<CompanyInfoRecordNew, CompanyInfoTransformedRecord>() {...}, encoder);
To take an object and return list of objects we need to use flatmap instead of map as below
FlatMapFunction<Original, Derived> flatMapFunction = ( record ) ->{
List<Derived> transRecList = new ArrayList<Derived>();
Derived transRec = new Derived();
transRecList.add(transRec);
Derived transRec2 = new Derived();
transRecList.add(transRec2);
return (Iterator<Derived>) transRecList.iterator();
};
Dataset Deriveds = baseDs.flatMap(flatMapFunction, comanyInfoTransEncoder);
I'm trying to understand golang interface, my problem is that why err2.What undefined.
Here is a simple code. The output indicates that both err and err2 have same type as *main.MyError, but err2 have no field "What", so there must be some difference between err and err2, but I cannot figure out the difference here. I just began learning golang not long before, any help will be greatly appreciated.
package main
import (
"fmt"
"time"
"reflect"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
err := &MyError{time.Now(), "Hello"}
fmt.Println(reflect.TypeOf(err))
fmt.Println(err.What)
err2 := run()
fmt.Println(reflect.TypeOf(err2))
fmt.Println(err2.What)
}
expected output:
main.MyError
Hello
main.MyError
it didn't work
actual output:
\# command-line-arguments
./test.go:34:18: err2.What undefined (type error has no field or method What)
The function run() returns a value of type error, which is an interface type. Yes, it wraps a value of concrete type *MyError, but to get access to MyError's fields, you need to use a type assertion:
fmt.Println(err2.(*MyError).What)
Try it on the Go Playground.
Note that a value of error type may contain values of other concrete types, actually any that implements the error interface. If it would contain a value of another type, the above type assertion would result in a runtime panic.
If you're unsure err2 actually holds a value of type *MyError and you want to avoid the runtime panic, you may use the special form of type assertion to get this information and only act if it is so:
if myerror, ok := err2.(*MyError); ok {
fmt.Println(myerror.What) // Here myerror has static type *MyError
} else {
fmt.Println("Some other error:", err2)
}
Try this one on the Go Playground.
I think the interface of error type is let you use Error() method without any detail in the concrete structure. You can check on the Go Playground
Our code has a SqlExpression, which at its bare minimum is something like:
var q = db.From<Users>();
q.Where(u => u.Age == 25);
totalRecords = db.Scalar<int>(q.ToCountStatement());
q.ToCountStatement() generates the following query:
SELECT COUNT(*) FROM "Users" WHERE ("Age" = #0)
However, db.Scalar() throws an exception: Must declare the scalar variable "#0". This has started occurring in recent versions (tested in 4.0.54). The same code was working fine until v4.0.50. I've checked the release notes, but couldn't find a related change.
Even passing a parameter throws the same exception:
totalRecords = db.Scalar<int>(q.ToCountStatement(), 25);
Is it a bug, or my oversight?
Secondly, is it possible to get q.ToCountStatement() to generate a more optimized query with COUNT(Age) or COUNT([PrimaryKey]) instead of COUNT(*)?
Now that OrmLite defaults to parameterized queries you also need to provide the queries db parameters when executing a query (if you've specified any params), e.g:
var q = db.From<Users>().Where(u => u.Age == 25);
var count = db.Scalar<int>(q.ToCountStatement(), q.Params);
You can also use OrmLite's explicit Count() API's, e.g:
db.Count<User>(x => x.Age == 25);
Or with a typed SqlExpression:
var q = db.From<User>().Where(x => x.Age == 25);
db.Count(q);
Otherwise another way to specify db params is to use an anonymous object, e.g:
db.Scalar<int>("SELECT COUNT(*) FROM Users WHERE Age=#age", new { age = 25});
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).