How to work around "type interface has no field or method" error? - struct

I want to write an abstraction to the mgo API:
package manager
import "labix.org/v2/mgo"
type Manager struct {
collection *mgo.Collection
}
func (m *Manager) Update(model interface{}) error {
return m.collection.UpdateId(model.Id, model)
}
When compiling I get "model.Id undefined (interface{} has no field or method Id)" which itself is obvious.
Is this a totally wrong approach from my side or is there an easy workaround how to let the compiler "trust" that there will be an Id property on runtime on passed structs.

You could defined an interface which declares an Id function
type Ider interface {
Id() interface{}
}
If your model is an Ider, then your function will work.
func (m *Manager) Update(model Ider) error {
Considering the mgo#Collection.UpdateId() function takes interface{}, it will accept an Ider.

Related

What is the name of this programming language feature and are there any real-world languages that support it?

Let a tree data structure be defined as such:
A tree has one Node as its root. A Node is either a Leaf or it is an Inner Node which has one or more Nodes as its children.
In some kind of pseudo OO programming language we may define a tree like this:
Node := InnerNode | Leaf
Leaf {
isLeaf() : TRUE
}
InnerNode {
isLeaf() : FALSE
children() : List<Node>
}
Tree {
root() : Node
}
Now we can define two functions, 'bad_code' and 'good_code'. The function 'bad_code' does not compile, the other function does:
function bad_code(Node anyNode) : void {
// this will give a compile time error "type Node does not define method children()"
anyNode.children();
}
function good_code(Node anyNode) : void {
// the compiler understands that all Nodes must have a method called isLeaf() which
// returns a boolean
let b : boolean <- anyNode.isLeaf();
if (b == FALSE) {
// this will not give a compile time error because the compiler can deduce that
// anyNode must be of type InnerNode which has the method children()
anyNode.children();
}
}
Question:
Is the above an example of a language feature that has been defined / described in some official way?
If so: what is this language feature officially called?
Are there any real-world programming languages which implement this language feature?
Can this language feature be implemented as a compile time check with zero costs at runtime?
What you're describing is that the compiler uses the control-flow graph to narrow the type of a variable, so that when an if statement tests a condition which relates to the type of a variable, a more specific type for the same variable can be inferred for the body of the if statement.
This is called control-flow type narrowing, and it's done in e.g. Typescript. It is purely a static check, done at compile-time with no runtime penalty; in fact, types in Typescript are not available at runtime at all.
type TreeNode = InnerNode | Leaf
interface Leaf {
isLeaf: true
}
interface InnerNode {
isLeaf: false
children: Node[]
}
function bad_code(anyNode: TreeNode): void {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
function good_code(anyNode: TreeNode): void {
if (!anyNode.isLeaf) {
// narrowed type to anyNode: InnerNode
console.log(anyNode.children);
}
}
Note that Typescript requires you to do this in a particular way; we test anyNode.isLeaf directly rather than storing it in a variable b: boolean first, because Typescript doesn't keep track of the relationship between the two variables b and anyNode:
function bad_in_typescript(anyNode: TreeNode): void {
let b: boolean = anyNode.isLeaf;
if (!b) {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
}
Also, in the above code isLeaf is a property instead of a method. Typescript does have a related feature called user-defined type guards which allow a method's return type to be something like this is Leaf, indicating that the method returns true only when called on something of type Leaf:
type TreeNode = InnerNode | Leaf
interface BaseNode {
isLeaf(): this is Leaf
isInner(): this is InnerNode
}
interface Leaf extends BaseNode {}
interface InnerNode extends BaseNode {
children(): Node[]
}
However, Typescript is still a bit more limited than your example; we have to test anyNode.isInner() because !anyNode.isLeaf() won't necessarily do the same narrowing. (Typescript uses structural types, so in fact this Leaf is a supertype of InnerNode, which causes some problems for the union type. If you give Leaf a property like value: number which InnerNode doesn't have, then !anyNode.isLeaf() works how you would expect.)
Typescript Playground Link for version with properties
Typescript Playground Link for version with methods

TS: Cannot invoke an expression whose type lacks a call signature when defined dynamically, but it works

I'm still quite new to typescript, so please be gentle with me if I'm doing something with no sense for this technology!
The problem that I'm trying to solve is having a dynamic way to define how my application errors should be structured, but leaving to the users the faculty to enrich the messages.
So I tried to create this logic in a module that could be extended easily from the application, but I'm currently facing the problem:
Error:(35, 18) TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ErrorMessage' has no compatible call signatures.
What I thought it was a good idea (but please tell me if I'm wrong), was to use a register and a map to have the possibility to extend this mapping every time I want. So I created my ErrorMessage interface to be like the following:
export interface ErrorMessage {
actionMessage: string;
actionSubject: string;
originalErrorMessage?: string;
toString: () => string;
}
and a register for these, called ErrorResponseRegister, as it follows:
export enum defaultErrors {
ExceptionA = 'ExceptionA',
ExceptionB = 'ExceptionB',
}
export class ErrorResponseRegister {
private mapping: Map<string, ErrorMessage>;
constructor() {
this.mapping = new Map()
.set(defaultErrors.ExceptionA, exceptionAErrorMessage)
.set(defaultErrors.ExceptionB, exceptionBErrorMessage);
}
}
So at the end, every ErrorMessage function should look like:
export function exceptionAErrorMessage(originalErrorMessage?: string): ErrorMessage {
return {
enrichment1: "Something happened",
enrichment2: "in the application core",
originalErrorMessage: originalErrorMessage,
toString(): string {
return `${this.enrichment1} ${this.enrichment2}. Original error message: ${originalErrorMessage}`;
},
};
}
Please note I haven't used classes for this ones, as it doesn't really need to be instantiated
and I can have a bunch of them where the toString() method can vary. I just want to enforce the errors should have an enrichment1 and enrichment2 that highlight the problem in a better way for not-technical people.
So, now, back to code. When I'm trying to use the exceptionAErrorMessage statically, I can't see any problem:
console.log(exceptionAErrorMessage(originalErrorMessage).toString())
But when I try dynamically, using the map defined in the ErrorResponseRegister, something weird happens:
// In ErrorResponseRegister
public buildFor(errorType: string, originalErrorMessage?: string): Error {
const errorMessageBuilder = this.mapping.get(errorType);
if (errorMessageBuilder) {
return errorMessageBuilder(originalErrorMessage).toString();
}
return "undefined - do something else";
}
The code works as expected, the error returned is in the right format, so the toString function is executed correctly.
BUT, the following error appears in the IDE:
Error:(32, 18) TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ErrorMessage' has no compatible call signatures.
The line that causes the problem is
errorMessageBuilder(originalPosErrorMessage).toString()
Can someone help me to understand what I'm doing wrong?
It looks like your problem is you've mistyped mapping... it doesn't hold ErrorMessage values; it holds (x?: string)=>ErrorMessage values:
private mapping: Map<string, (x?: string) => ErrorMessage>;
What's unfortunate is that you initialize this variable via new Map().set(...) instead of the using an iterable constructor argument.
The former returns a Map<any, any> which is trivially assignable to mapping despite the mistyping. That is, you ran smack into this known issue where the standard library's typings for the no-argument Map constructor signature produces Map<any, any> which suppresses all kinds of otherwise useful error messages. Perhaps that will be fixed one day, but for now I'd suggest instead that you use the iterable constructor argument, whose type signature declaration will infer reasonable types for the keys/values:
constructor() {
this.mapping = new Map([
[defaultErrors.ExceptionA, exceptionAErrorMessage],
[defaultErrors.ExceptionB, exceptionBErrorMessage]
]); // inferred as Map<defaultErrors, (orig?: string)=>ErrorMessage>
}
If you had done so, it would have flagged the assignment as an error with your original typing for mapping (e.g., Type 'Map<defaultErrors, (originalErrorMessage?: string | undefined) => ErrorMessage>' is not assignable to type 'Map<string, ErrorMessage>'.) Oh well!
Once you make those changes, things should behave more reasonably for you. Hope that helps; good luck!
Link to code

Forward operators in haxe

I'm trying to write my own boolean "abstract" with some additional functions.
#forward
abstract MyBool(Bool) {
public inline function new(b:Bool) {
this = b;
}
#:from
public static inline function fromBool(b:Bool):MyBool {
return new MyBool(b);
}
#:to
public inline function toBool():Bool {
return this;
}
// some additional functions
}
In principal this works fine:
var t:T = true;
if(t) {
trace("1");
}
t.someStrangeMethod();
However #:forward does not forward basic boolean-operators like "!":
var f:T = false;
if(!f) { // fails here, because "!" is not defined as an operator for MyBool ...
trace("2");
}
The error message is "MyBool should be Bool", which I find quite strange because MyBool is an abstract of a Bool with #:forward annotation and there is a #:to-method.
Of course there are some easy workarounds. One could either use:
if(!f.toBool()) {
trace("2");
}
and/or add a function annotated with #:op(!A) to the abstract:
#:op(!A)
public inline function notOp():Bool {
return !this;
}
However I do not like both methods:
I dislike adding #:op(...) to MyBool, because creating a method for each possible operator would require much code (Maybe not with a boolean, but e.g. with an Int, Float, ...).
I dislike using !var.toBool(). If someone has already written quite some code (s)he does not want to go through all of it, when (s)he simply wants to change Bool to a MyBool ... I mean of course (s)he could also cast Bool to MyBool whenever adding new code, but that can be horrible too.
So I was wondering if anyone has a better idea? Is there maybe another "#:forward"-like compiling metadata, I do not know about yet?
There's an open feature request regarding this:
Can #:forward also forward underlying operator overloads? (#5035)
One way to make your code example work is to allow implicit conversions with to Bool. I'm not entirely sure why the equivalent #:to function doesn't work here, as the Haxe Manual states that "Class field casts have the same semantics".
abstract MyBool(Bool) to Bool {
Apart from that, I think the only options is to declare an #:op function for each operator you want to support. If declared without a body, the underlying type's operator will be forwarded:
#:op(!A) function notOp():MyBool;
If your main goal is to just add methods to the Bool type, then perhaps avoid the problem altogether by instead creating a class that adds methods to Bool via static extension (documented in the Haxe manual). This method would eliminate the need for operator forwarding.

TCL: pass an object as an argument of a procedure with ActiveTcl 8.6

I'm new to object-oriented programming in TCL. I installed ActiveTCL 8.6 which includes the package TclOO in order to use classes and objects in TCL. I would like to create an object and call various procedures in order to use it. For instance, I tried the following piece of code:
oo::class create Test {
method func {} {
puts "Hello World!"
}
}
proc speak { myObj } {
myObj func
}
Test create testObj
testObj func; # This prints "Hello World!"
speak testObj; # This raises an error -> invalid command name "myObj"
What should I do in order to use the object testObj in the "speak" procedure?
When you pass an object, you're actually passing the name of the object. The variable, the formal parameter, is then holding the name and you dereference the variable to use the object (and not the variable itself):
proc speak { myObj } {
$myObj func
}
Note that you can also use a one-argument set to read the variable; this code below is equivalent to that above, but more long-winded:
proc speak { myObj } {
[set myObj] func
}
It's also possible to make an alias to the object that can then have any name you want it to, but this is not recommended for procedures as such names are always effectively global.
# Don't do this!
proc speak { myObj } {
interp alias {} $myObj {} myObj
myObj func
}
This makes a lot more sense when you're passing an object into a constructor or storing it in a namespace that has many commands that may use it. (In fact, rename the object into the other object or namespace and the object will become managed by the lifetime of the entity which you moved it into; this is the simplest, most recommended way of doing UML Composition, and is used extensively inside the implementation of TDBC drivers. The key is the lifetime; procedure calls aren't usually things you want to limit passed-in objects' lifetime to.)

Generics and Anonymous types

I have a function,
public static IPagedResponse<T> GetPagedResponse<T, TAnon>(
this IQueryable<TAnon> query,
QueryableRequestMessage request)
where T : class
{
//...
}
I'm trying to pass query as an IQueryable of an anonymous type.
var query = _repository.All.Select(
i => new //anon type
{
i.Id,
i.Name,
}
);
var result = query.GetPagedResponse<EftInterfaceDto, ??????>(request);
The issue is I don't know what to put in place of ??????? It can't seem to infer it. And any combinations using .GetType() or typeof() I have tried, failed.
I tried changing the function to be IQueryable<dynamic> but that resulted in other errors, about dynamic not being allowed in Expression trees.
HACK:
I can make it work if I change my function to this:
public static IPagedResponse<T> GetPagedResponse<T, TAnon>(
this IQueryable<TAnon> query,
QueryableRequestMessage request,
T typeSample)
where T : class
{
//...
}
And then pass in an instance of T
var result = query.GetPagedResponse(request, new SomeClassOfT());
This way, I can use type inference to determine the anonymous type TAnon, and don't need to be explicit in the call to the generic (no <types> required).
However, I don't want to do this, as it's clearly not clear what I'm doing.

Resources