I've been trying to make my project a little bit more dynamic, so I've decided to write an add function, I got inspired from this example they have on the Alloy website :
pred add [b, b': Book, n: Name, t: Target] {
b'.addr = b.addr + n->t
}
But what I want to do is override the two objects "b" and "b' " (as in I want to add to the same object) but i can't seem to find a way how to do it.
If anyone has an idea I'll be thankful
You're not missing anything. The reason you cannot find a way to "add to the same object" is that you can't. Alloy doesn't have mutation; you cannot change any object in a model.
Applications that involve mutation are often modeled just as you model add in your example: with two parameters showing the pre-state and the post-state. In such a model, any two Book objects b1, b2 will show different states of the same mutable Book object in the application domain if and only if there is some n, t such that add[b1, b2, n, t] holds.
Related
C# 9 has a new feature. A record type. The record is just a class, but with a bunch of automatically created functions and properties. But basically the idea (as I undstand it) was, a class that behaves like structs, for things like copying, coimparison with Equals, immutibility and so on.
Also with the record type was a new feature with the keyword "with". To create a copy of a record, you can write something like that: var copy = original with { Property = new_value, };
Now I wondered, if records were designt to behave like structs (but are classes). Why doesn't the new "with" keyword works also with structs. I mean, as far as I can tell, structs have all features, that are necessary for this feature. Like they are copied by value.
Instead to use similar features for structs, I have to write a copy constructor and can then write: var copy = new StructType(original) { Property = new_value, };
Short answer:
That's how the feature was designed.
Long answer:
The compiler creates a synthesized clone method with a reserved name <Clone>$, when you use with keyword, the compiler calls this clone method, and then modifies whatever properties you want to modify.
structs or classes doesn't have a synthesized clone method. Hence, with can't be used with them.
You may want to write a language proposal to extend the usage of with keyword.
Edit:
Currently, there is a proposal for allowing record structs. See Proposal: record structs for more information. This is what you may want.
Suppose I define "Class original:" and create a class attribute "one = 4." Then I create an instance of the class "First = original()." My understanding is that First now contains a pointer to original and "First.one" will return "4." However, suppose I create "Second = original()" and then set "Second.one = 5." What exactly happens in memory? Does a new copy of Class original get created with a class attribute of 5?
I've created a Class original with class attribute one. I then created two instances of this class (First and Second) and verified that id(First.one) and id(Second.one) are pointing to the same place. They both return the same address. However, when I created Third=original() and set Third.one = 5 and then check id(Thrid.one) it appears to be pointing somewhere else. Where is it pointing and what happened? When I check original.one it still returns "4" so obviously the original object is not being modified. Thanks.
It appears you are asking about a piece of code similar to this:
class Original:
def __init__(self, n):
self.one = n
first = Original(4)
second = Original(4)
third = Original(5)
print(id(first.one))
# 140570468047360
print(id(second.one))
# 140570468047360
print(id(third.one))
# 140570468047336
Suppose I define "Class original:" and create a class attribute "one = 4." Then I create an instance of the class "First = original()." My understanding is that First now contains a pointer to original
No. The variable references the instance you created, not the class. If it referenced the class, there would be no way for you to get at the instance you just created.
The instance will, somewhere in its object header, of course contain a pointer to its class. Without that pointer, method lookup wouldn't be possible, since you wouldn't be able to find the class from the instance.
and "First.one" will return "4."
Yes. The attribute one of first contains a pointer to the object 4 (which is an instance of the class int).
[Note that technically, some Python implementations will perform an optimization and actually store the object 4 directly in the attribute instead of a pointer to the object. But that is an internal implementation detail.]
However, suppose I create "Second = original()" and then set "Second.one = 5." What exactly happens in memory? Does a new copy of Class original get created with a class attribute of 5?
No. Why would you need a separate copy of the class? The methods are still the same for both instances. In fact, that is precisely the reason why methods in Python take the instance as their first argument! That way, there need only be one method. (This is actually the same in every OO language, except that in most other languages, this argument is "invisible" and only accessible using a special keyword like self in Ruby, Smalltalk, Self, and Newspeak or this in Java, C#, and Scala.)
I've created a Class original with class attribute one. I then created two instances of this class (First and Second) and verified that id(First.one) and id(Second.one) are pointing to the same place. They both return the same address. However, when I created Third=original() and set Third.one = 5 and then check id(Thrid.one) it appears to be pointing somewhere else.
It is not quite clear to me what your question is here. first.one and second.one both point to 4, so they both point to the same ID since they both point to the same object. third.one points to 5, which is obviously a different object from 4, so naturally, it has a different ID.
It is, in fact, one of the requirement of IDs that different objects that exist at the same time must have different IDs.
Where is it pointing and what happened?
Again, it is not quite clear what you are asking.
It is pointing at 5, and nothing happened.
When I check original.one it still returns "4" so obviously the original object is not being modified.
Indeed, it isn't. Why would it be?
I have to model a system where an object of the class Person will invoke the static method getBook(...) : Book on the class Book which will return an instance of a particular book.
How do you reference the book instance obtained by the operation?
As of now, I can think of two approaches, neither of which I have ever seen/used, which is why I am looking for the correct approach.
The first approach is to invoke methods directly on the book instance obtained, e.g. if the reference returned by getBook(...) : Book is named matchingBook, I would use matchingBook.doSomething(...), much like having a local variable.
The second way, which I find more in the line of sequence diagrams is to let the book instance returned by the operation appear with its own lifeline, e.g. next to the Book class, and referencing it with an arrow labeled doSomething(...).
However, with the second approach, it is not that obvious that this object is in fact the one returned by the operation.
The second approach is the correct. To show that you are pointing to the returned object (matchingBook), you can add the variable name to the title of the lifeline, like this:
The second approach is the correct one. Anytime you call operations on an object returned by a first operation, you can't do better than a name match between the result of the first call and the lifeline.
Anyway I don't really understand what you expect of the first way: where would you put matchingBook.doSomething(...)? on a arrow pointing which lifeline?
I'm having a look at the code at this page:
http://golang.org/pkg/net/http/
And there's one thing I don't understand - at some point, a new structure is created and initialized like this:
client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
Why use & when creating this structure?
I've also read this blog post and structs are initialized like this:
r := Rectangle{}
What is the difference between both and how should I know which one to use?
The difference is in the type of your variable.
client := &http.Client{
makes client of type *http.Client
while
client := http.Client{
builds a http.Client.
The top one is returning a pointer. It is a Go idiom instead of using new. The second one is just a value object. If you need a pointer use the top.
Check the effective go doc for more about this
http://golang.org/doc/effective_go.html#allocation_new
In object-oriented programming, in order for an object to have dynamic lifetime (i.e. not tied to the current function call), it needs to be dynamically allocated in a place other than the current stack frame, thus you manipulate the object through a pointer. This is such a common pattern that in many object-oriented languages, including Java, Python, Ruby, Objective-C, Smalltalk, JavaScript, and others, you can only deal with pointers to objects, never with an "object as a value" itself. (Some languages though, like C++, do allow you to have "objects as values"; it comes with the RAII idiom which adds some complexity.)
Go is not an object-oriented language, but its ability to define custom types and define methods that operates on that custom type, can be made to work very much like classes and methods. Returning a pointer to the type from the "constructor" function allows the "object" to have a dynamic lifetime.
When we use reference, we use a single item throughout the program runtime. Even if we assign that to a new variable or pass through a function. But when we use value, we make new copies of individual items.
( Reference is not right word according to golang convention. "Address of value" would be more appropriate here https://golang.org/ref/spec#Package_initialization )
An example will make it much clear I hope.
type Employee struct {
ID int
Name string
Address string
}
func main() {
andy := &Employee{}
andy.Name = "Andy"
brad := andy
brad.Name = "Brad"
fmt.Println(andy.Name)
}
The result of this code block would be:
Brad
As we made new variable from it but still referring to same data. But if we use value instead of reference and keep the rest of the code same.
// from
andy := &Employee{}
// to
andy := Employee{}
This time the result would be:
Andy
As this time they both are individual items and not referring to same data anymore.
I am not sure whether this is the right forum to ask this question, but it refers to code, so I am asking here.
In the book "Groovy in action", section 7.1.4 (named parameters), the author says that usage of named params "crops up frequently in creating immutable classes that have some parameters that are optional".
What has immutability of the class got to do with optional parameters? I thought these 2 topics were completely orthogonal.
crops up frequently in creating immutable classes that have some parameters that are optional
the sentence above is a bit blurry as there is no such thing as "class parameters", i can only assume it relates to method/constructor parameters.
when we're talking about constructors, Groovy's named parameters make sense when its about optional parameters:
#groovy.transform.Immutable
class Person {
String firstName
String lastName
Integer age
}
def p = new Person(age: 42, lastName: 'Doe')
The above example shows how to create an immutable Person instance. The firstName is not provided as named parameter, it's optional. In fact, with named parameters it's possible to specify any parameter combo when making the constructor call without actually having to implement constructors for all combinations.
There is also the possibility of using named parameters in instance/static method calls, as shown in this blog post by Mr. Haki.
The key to that statement is that if you're dealing with an immutable class, the implication is that you have only one chance to set state - in a constructor. Normally you'd be able to manipulate an (mutable) object via setters, one-at-a-time, to build up the desired state. For an immutable, you'd have to create a ctor for every possible set of instantiation states instead, if a facility like optional params were not available. For a class with many fields, this could get messy.