Concrete Syntax - Connector on relation field - lightning-workbench

I have the following Signature:
abstract sig Node{
arc: set Node}
Is it possible in a way to specify the arc relation as a Connector in the concrete syntax relation?
sig P extends Node{token:Int}{tokens>=0}
It could also help me for the case above, the tokens field.
Best,

In F-Alloy, you can map a relation to a signature by defining a mapping from a pair of signatures (typing the relation) to the target signature.
This means that any combination of atoms in this pair of signatures are to be mapped to a new atom typed by the target signature.
In order to enforce the combinations for which an atom is created to be the ones of the relation you want to represent, you need to write a specific constraint in the guard predicate.
For your example, you would thus have the mapping:
mapArc: Node -> Node -> CONNECTOR
and the following guard:
pred guard_mapArc(n1:Node,n2:Node){
// the image of n1 via the arc relation is n2
}
Also don't forget that the value predicate should keep a reference of the combinations of atoms.
pred value_mapArc(n1:Node,n2:Node,c:CONNECTOR){
// state properties of c in function of the given n1 and n2
}
Hope it helps

Related

In TinkerPop can vertex properties contain complex objects?

I am playing with TinkerGraph and gremlin-scala and I see that it is capable of persisting complex objects:
case class InnerObj(a: Int, b: String)
case class ComplexObj(a: Int, b: InnerObj)
case class SuperComplexObj(a : String, b: ComplexObj)
class GremlinQueriesSpec extends FlatSpec
with ScalaFutures with MustMatchers {
behavior of "Gremlin queries"
it must "be able to persist complex objects containing collections" taggedAs Integration in {
val g = TinkerGraph.open()
implicit val graph = g.asScala
val user = RandomData.randomUserDataAggregate
graph + user
graph.V().toCC[UserDataAggregate].toList() must be eq List(user)
}
}
However, docs are not completely clear to me. On ะตั€ัƒ one hand there's not much structure available for property values besides lists, sets, and metaproperties. On the other hand docs say:
A Property denotes a key/value pair associated with an Edge. A
property is much like a Java8 Optional in that a property can be not
present (i.e. empty). The key of a property is always a String and the
value of a property is an arbitrary Java object. Each underlying graph
engine will typically have constraints on what Java objects are
allowed to be used as values.
Ok, it looks like it depends on the implementation. But is possible to work with nested objects in Gremlin queries?
It is indeed dependent on the implementation. You are using TinkerGraph which can in turn store any Java object so you're free to put whatever you like in there:
gremlin> g.addV().property('function',{it.length()})
==>v[2]
gremlin> g.V().sideEffect{println(it.get().value('function')("four"))}
4
==>v[2]
crazy right? Of course, you will need to consider issues like serialization and such if you start sticking random odds/ends in there and need to persist those objects or push them over the wire (like through Gremlin Server).
There is no problem with a nested object as a value for a TinkerGraph property. Just be careful. Really stop to think about your schema before going to deep down the path of storing complex Java objects as properties. Perhaps it would be better to just model those objects as elements of the graph as first class citizens to enable Gremlin traversals to work over them directly.

Class DefaultGraphTraversal<S,E> what is the class purpose? and what are S and E classes represent?

Couldn't figure from the documentation and the source code what do they represent?
http://tinkerpop.apache.org/javadocs/3.2.5/full/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/DefaultGraphTraversal.html
In Apache TinkerPop/Gremlin a Traversal is analogous to a query and a query can return more than just vertices.
<S,E> are type variables that form the Java generic definition for the DefaultGraphTraversal class. They aren't specific classes, but represent the "start" (for S) and "end" (for E) types that will go into and come out of the traversal respectively. In a sense, those types become defined when you form the traversal you want to execute. g.V().count() returns a GraphTraversal<Vertex,Long> where the S is defined as Vertex and the E is defined as a Long - the start to the traversal is a Vertex and the end to the traversal is a Long.

How to obtain a KType in Kotlin?

I'm experimenting with the reflection functionality in Kotlin, but I can't seem to understand how to obtain a KType value.
Suppose I have a class that maps phrases to object factories. In case of ambiguity, the user can supply a type parameter that narrows the search to only factories that return that type of object (or some sub-type).
fun mapToFactory(phrase: Phrase,
type: KType = Any::class): Any {...}
type needs to accept just about anything, including Int, which from my experience seems to be treated somewhat specially. By default, it should be something like Any, which means "do not exclude any factories".
How do I assign a default value (or any value) to type?
From your description, sounds like your function should take a KClass parameter, not a KType, and check the incoming objects with isSubclass, not isSubtype.
Types (represented by KType in kotlin-reflect) usually come from signatures of declarations in your code; they denote a broad set of values which functions take as parameters or return. A type consists of the class, generic arguments to that class, and nullability. The problem with types at runtime on JVM is that because of erasure, it's impossible to determine the exact type of a variable of a generic class. For example if you have a list, you cannot determine the generic type of that list at runtime, i.e. you cannot differentiate between List<String> and List<Throwable>.
To answer your initial question though, you can create a KType out of a KClass with createType():
val type: KType = Any::class.createType()
Note that if the class is generic, you need to pass type projections of generic arguments. In simple cases (all type variables can be replaced with star projections), starProjectedType will also work. For more info on createType and starProjectedType, see this answer.
Since Kotlin 1.3.40, you can use the experimental function typeOf<T>() to obtain the KType of any type:
val int: KType = typeOf<Int>()
In contrast to T::class.createType(), this supports nested generic arguments:
val listOfString: KType = typeOf<List<String>>()
The typeOf<T>() function is particularly useful when you want to obtain a KType from a reified type parameter:
inline fun <reified T> printType() {
val type = typeOf<T>()
println(type.toString())
}
Example usage:
fun main(args: Array<String>) {
printType<Map<Int, String>>()
// prints: kotlin.collections.Map<kotlin.Int, kotlin.String>
}
Since this feature is still in experimental status, you need to opt-in with #UseExperimental(ExperimentalStdlibApi::class) around your function that uses typeOf<T>(). As the feature becomes more stable (possibly in Kotlin 1.4), this can be omitted. Also, at this time it is only available for Kotlin/JVM, not Kotlin/Native or Kotlin/JS.
See also:
Release announcement
API Doc (very sparse currently)

How does Rust implement reflection?

Rust has the Any trait, but it also has a "do not pay for what you do not use" policy. How does Rust implement reflection?
My guess is that Rust uses lazy tagging. Every type is initially unassigned, but later if an instance of the type is passed to a function expecting an Any trait, the type is assigned a TypeId.
Or maybe Rust puts a TypeId on every type that its instance is possibly passed to that function? I guess the former would be expensive.
First of all, Rust doesn't have reflection; reflection implies you can get details about a type at runtime, like the fields, methods, interfaces it implements, etc. You can not do this with Rust. The closest you can get is explicitly implementing (or deriving) a trait that provides this information.
Each type gets a TypeId assigned to it at compile time. Because having globally ordered IDs is hard, the ID is an integer derived from a combination of the type's definition, and assorted metadata about the crate in which it's contained. To put it another way: they're not assigned in any sort of order, they're just hashes of the various bits of information that go into defining the type. [1]
If you look at the source for the Any trait, you'll see the single implementation for Any:
impl<T: 'static + ?Sized > Any for T {
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}
(The bounds can be informally reduced to "all types that aren't borrowed from something else".)
You can also find the definition of TypeId:
pub struct TypeId {
t: u64,
}
impl TypeId {
pub const fn of<T: ?Sized + 'static>() -> TypeId {
TypeId {
t: unsafe { intrinsics::type_id::<T>() },
}
}
}
intrinsics::type_id is an internal function recognised by the compiler that, given a type, returns its internal type ID. This call just gets replaced at compile time with the literal integer type ID; there's no actual call here. [2] That's how TypeId knows what a type's ID is. TypeId, then, is just a wrapper around this u64 to hide the implementation details from users. If you find it conceptually simpler, you can just think of a type's TypeId as being a constant 64-bit integer that the compiler just knows at compile time.
Any forwards to this from get_type_id, meaning that get_type_id is really just binding the trait method to the appropriate TypeId::of method. It's just there to ensure that if you have an Any, you can find out the original type's TypeId.
Now, Any is implemented for most types, but this doesn't mean that all those types actually have an Any implementation floating around in memory. What actually happens is that the compiler only generates the actual code for a type's Any implementation if someone writes code that requires it. [3] In other words, if you never use the Any implementation for a given type, the compiler will never generate it.
This is how Rust fulfills "do not pay for what do you not use": if you never pass a given type as &Any or Box<Any>, then the associated code is never generated and never takes up any space in your compiled binary.
[1]: Frustratingly, this means that a type's TypeId can change value depending on precisely how the library gets compiled, to the point that compiling it as a dependency (as opposed to as a standalone build) causes TypeIds to change.
[2]: Insofar as I am aware. I could be wrong about this, but I'd be really surprised if that's the case.
[3]: This is generally true of generics in Rust.

Take address of value inside an interface

How do I take the address of a value inside an interface?
I have an struct stored in an interface, in a list.List element:
import "container/list"
type retry struct{}
p := &el.Value.(retry)
But I get this:
cannot take the address of el.Value.(retry)
What's going on? Since the struct is stored in the interface, why can't I get a pointer to it?
To understand why this isn't possible, it is helpful to think about what an interface variable actually is. An interface value takes up two words, with the first describing the type of the contained value, and the second either (a) holding the contained value (if it fits within the word) or (b) a pointer to storage for the value (if the value does not fit within a word).
The important things to note are that (1) the contained value belongs to the interface variable, and (2) the storage for that value may be reused when a new value is assigned to the variable. Knowing that, consider the following code:
var v interface{}
v = int(42)
p := GetPointerToInterfaceValue(&v) // a pointer to an integer holding 42
v = &SomeStruct{...}
Now the storage for the integer has been reused to hold a pointer, and *p is now an integer representation of that pointer. You can see how this has the capacity to break the type system, so Go doesn't provide a way to do this (outside of using the unsafe package).
If you need a pointer to the structs you're storing in a list, then one option would be to store pointers to the structs in the list rather than struct values directly. Alternatively, you could pass *list.Element values as references to the contained structures.
A type assertion is an expression that results in two values. Taking the address in this case would be ambiguous.
p, ok := el.Value.(retry)
if ok {
// type assertion successful
// now we can take the address
q := &p
}
From the comments:
Note that this is a pointer to a copy of the value rather than a pointer to the value itself.
โ€” James Henstridge
The solution to the problem is therefore simple; store a pointer in the interface, not a value.
Get pointer to interface value?
Is there a way, given a variable of interface type, of getting a
pointer to the value stored in the variable?
It is not possible.
Rob Pike
Interface values are not necessarily addressable. For example,
package main
import "fmt"
func main() {
var i interface{}
i = 42
// cannot take the address of i.(int)
j := &i.(int)
fmt.Println(i, j)
}
Address operators
For an operand x of type T, the address operation &x generates a
pointer of type *T to x. The operand must be addressable, that is,
either a variable, pointer indirection, or slice indexing operation;
or a field selector of an addressable struct operand; or an array
indexing operation of an addressable array. As an exception to the
addressability requirement, x may also be a composite literal.
References:
Interface types
Type assertions
Go Data Structures: Interfaces
Go Interfaces
In the first approximation: You cannot do that. Even if you could, p itself would the have to have type interface{} and would not be too helpful - you cannot directly dereference it then.
The obligatory question is: What problem are you trying to solve?
And last but not least: Interfaces define behavior not structure. Using the interface's underlying implementing type directly in general breaks the interface contract, although there might be non general legitimate cases for it. But those are already served, for a finite set of statically known types, by the type switch statement.

Resources