I was wondering if there's a way, in a fact, to force an attribute of a signature be empty. I tried this way but it seems not work:
sig C {
myattribute: lone Type
}
sig Type {
att1: Int
att2: ..... etc..
}
fact {
all c: C|
(my condition)
<=>
(
no c.myattribute
)
}
As for now we can just think about defing a structure with an abstract signature this way:
abstract sig GeneralType {}
one sig Empty extends GeneralType {}
sig NotEmpty extends GeneralType {...arguments (att1,2....}
The existing code should already work given the right my condition. (wmeyer is indeed correct in suggesting that.)
You can test your constraint to make sure it is behaving as you would expect:
sig Type { }
sig C {
myattribute: lone Type
}
fact {
all c: C | no c.myattribute
}
run { } for 5
check {
all c: C | no c.myattribute
} for 5
Related
What I wanna do is so simple.
In the example below,
interface InterfaceA { a: string, b: number }
interface InterfaceB { c: keyof InterfaceA }
const testMethod = (test: InterfaceB) => {
const TestObject: InterfaceA = { a: '', b: 1 }
TestObject[test.c] =
}
causes 'Type 'any' is not assignable to type 'never'' error.
I thought that test.c can be assigned in TestObject since c is the key of Interface A.
How can I make things work?
You are receiving this error because the type of test.c can not be narrowed down any more than keyof InterfaceA. In other words, if we try to assign to TestObject[test.c] typescript wont be able to determine if we need to assign a string or a number. So it determines that the type must be all valid types at the same time, in this case number & string. However no value can be both a number and a string at the same time, so the resulting type ends up being never (See this playground for an example).
We can solve this by helping typescript narrow down the actual type of test.c like this:
interface InterfaceA {
a: string,
b: number
}
interface InterfaceB {
c: keyof InterfaceA
}
const testMethod = (test: InterfaceB) => {
const TestObject: InterfaceA = { a: '', b: 1 }
switch (test.c) {
case 'a':
TestObject[test.c] = 'foo';
break;
case 'b':
TestObject[test.c] = 42;
break;
}
}
playground
In Perl 6, a multi-dispatch language, you can find out if there is a method that matches a name. If there is, you get a list of Method objects that match that name:
class ParentClass {
multi method foo (Str $s) { ... }
}
class ChildClass is ParentClass {
multi method foo (Int $n) { ... }
multi method foo (Rat $r) { ... }
}
my $object = ChildClass.new;
for $object.can( 'foo' )
.flatmap( *.candidates )
.unique -> $candidate {
put join "\t",
$candidate.package.^name,
$candidate.name,
$candidate.signature.perl;
};
ParentClass foo :(ParentClass $: Str $s, *%_)
ChildClass foo :(ChildClass $: Int $n, *%_)
ChildClass foo :(ChildClass $: Rat $r, *%_)
That's fine, but it's a lot of work. I'd much rather have something simpler, such as:
$object.can( 'foo', $signature );
I can probably do a lot of work to make that possible, but am I missing something that's already there?
As I hit submit on that question I had this idea, which still seems like too much work. The cando method can test a Capture (the inverse of a signature). I can grep those that match:
class ParentClass {
multi method foo (Str $s) { ... }
}
class ChildClass is ParentClass {
multi method foo (Int $n) { ... }
multi method foo (Rat $r) { ... }
}
my $object = ChildClass.new;
# invocant is the first thing for method captures
my $capture = \( ChildClass, Str );
for $object.can( 'foo' )
.flatmap( *.candidates )
.grep( *.cando: $capture )
-> $candidate {
put join "\t",
$candidate.package.^name,
$candidate.name,
$candidate.signature.perl;
};
I'm not sure I like this answer though.
I'm trying to add a map to my datatype that maps member name strings to the local offset of the member variable like this:
struct E
{
B memberX;
B memberY;
constexpr static entry map[] = {
{ "memberX", offsetof( E, memberX ) },
{ "memberY", offsetof( E, memberY) }
};
};
This doesn't compile with VS2015. If fails at { "memberX", offsetof( E, memberX ) }, with error C2227.
Besides, I know that offsetof doesn't work reliably for non pod types.
Do you have a suggestion how to do what I want in a compatible, modern way?
Thanks!
Not that this way is modern, but offsetof is often defined as following:
#define offsetof(type, memb) (intptr_t)&(((type)NULL)->memb)
so you can try using that as alternative.
I am assuming that you want to use the offsets only to access the members later. In that case and given that all members have the same type, a pointer-to-data-member is probably safer and more general:
struct E
{
B memberX;
B memberY;
static const auto& getMemberMap {
static const std::map<std::string, B E::*> memberMap {
{ "memberX", &E::memberX },
{ "memberY", &E::memberY }
};
return memberMap;
};
B& getMember(const std::string& str) {
auto it = getMemberMap().find(str);
if(it == getMemberMap().end()) {
// throw some exception
}
return this->*(it->second);
};
};
std::map does not have a constexpr constructor, so the map will be built runtime rather than compile-time, but you can replace it with your own implementation.
I used a local static variable instead of a static member because you required the initializiation to be contained in the class definition.
Why does the following
class Test {
#Test
void go() {
def foo1 = new MockFoo1() as Foo
def foo2 = new MockFoo2() as Foo
}
interface Foo {}
class MockFoo1 {}
class MockFoo2 {}
}
Result in a java.lang.IllegalArgumentException: argument type mismatch on the foo2 coercion?
This only happens if I coerce 2 objects of 2 different types to the same interface during a single path of execution. The groovy approved way of using closures or maps to achieve this kind of duck typing works fine.
Any light shed appreciated.
It's a bug with the ProxyGenerator adapterCache. As a workaround, you can also use some Groovy trickery to make this work:
interface Foo {
static a = {
[MockFoo1, MockFoo2].each {
it.metaClass.asType = { Class klazz ->
try {
DefaultGroovyMethods.asType(delegate, klazz)
} catch (e) {
def cache = ProxyGenerator.INSTANCE.#adapterCache.#cache
cache.each { k, v ->
cache.remove(k)
}
DefaultGroovyMethods.asType(delegate, klazz)
}
}
}
}()
}
class MockFoo1 {}
class MockFoo2 {}
def a = new MockFoo1() as Foo
def b = new MockFoo2() as Foo
assert a instanceof Foo
assert b instanceof Foo
Hope this helps!
The following code sample:
interface I<out T>
where T : class, I<T>
{
T GetT();
}
interface J : I<J>
{
}
abstract class B<T> : I<T>
where T : B<T>
{
T I<T>.GetT()
{
return null;
}
}
class C : B<C>, J
{
}
fails to compile (under VS2010 with SP1) with the following error:
Error 4 'C' does not implement interface member 'I<J>.GetT()'
However, C does implement (through its base B<C>) I<C>, which, due to I being declared covariant, should capture I<J> as well (as C : J).
Is this a compiler bug? If not, why am I not allowed to do that?
Even though it is covariant, you cannot change the return type of the interface. This is no different from the covariance in non-Generic classes.
interface Animal
{
Animal GetAnimal();
}
class Cat : Animal
{
//Not ALlowed
Cat GetAnimal()
{
return this;
}
//Allowed
Animal GetAnimal()
{
return this;
}
}
The problem is that C as a specialization of B<C> returns C I<C>.GetT(), however the specification of J requires J GetT().
Try the following:
interface I<out T>
where T : class, I<T>
{
T GetT();
}
interface J : I<J>
{
}
abstract class B<T,U> : I<U>
where T : B<T,U>, U
where U : class, I<U>
{
U I<U>.GetT()
{
return null;
}
}
class C : B<C,J>, J
{
}