Inheritance of Attributes on Blocks - sysml

I have a parent block (call it Block 1), which has an attribute. Lets call it VoltageIn. The attribute remains empty on this block.
The second block is a child of Block 1 (call it Block 2) and inherits the attribute VoltageIn. Here I want to give a value ( VoltageIn = 230V).
The third block (Block 3) is a child of Block 2 and therefore it inherits the attribute VoltageIn = 230V.
Now, my question is how to handle this with SysML?

The only way to give attributes values, is to create instances of the blocks. Create an instance of Block 2 and assign the value of 230V to VoltageIn. When you then create needed instances of Block 3, it will inherit that value.
Another way of going about this is to assign a default value to VoltageIn of Block 2 to 230V. This is then passed to Block 3. Sometimes you don't want to deal with instances, so this is another option.

Related

How to update single key/value from dictionary in morph?

In a previous question I asked how I could show the contents of a Dictionary in a GUI. I started from this idea to build a GUI with a slightly better look and feel. It mainly consists of RectangleMorphs glued together in columns and rows (cfr. the accepted answer in my previous question).
The problem now is that I would like my table to be updated when elements are added/removed/edited in my dictionary. I managed to write some Morph that consists of columns of CellMorphs, which inherit from RectangleMorph and have model and message as instance variables with the following update message:
update
" update the contents of this cell "
| value |
self removeAllMorphs.
(model = nil or: message = nil)
ifTrue: [ value := '' ]
ifFalse: [ value := model perform: message ].
self addMorph: value asMorph.
As can be seen, the CellMorph is a container for a Morph containing the actual content of the cell. This works great for displaying the size of the dictionary for instance:
d := Dictionary new.
d at: 'foo' put: 100.
d at: 'bar' put: 200.
cell := CellMorph new
model: d;
message: #size;
color: Color white.
cell openInWorld.
d at: 'boo' put: 300. " cell will be updated "
but I don't seem to get something similar working for the contents of the dictionary, because I can't find a way to access single keys or values with a message. The only solution I can think of is to create new columns with new cells every time, but this is so expensive and I can't imagine that this is a good idea...
Therefore my question:
Is there a way to update my Morph displaying the dictionary without creating billions of my CellMorphs or should I forget about my idea and rather work with rows of CellMorphs for instance in order to group the entries in the dictionary?
for completeness: the model: message in CellMorph looks like:
model: newModel
"change the model behind this cell"
model ifNotNil: [ model removeDependent: self ].
newModel ifNotNil: [newModel addDependent: self].
model := newModel.
self update.
update: aParameter does nothing more than call update. and I also added self changed. in all messages of Dictionary that I want the interface to be notified of (at: put:, removeKey:, etc.).
In the instance variable named 'message' you could have a Message object, instead of having only the selector.
An instance of Message has the receiver, selector and arguments. So, you could configure it with the dictionary keys sorted asArray in the receiver, the selector #at: and an index, to get a specific key. Accessing the value would be getting the value at: that key in the dictionary.
I think that a Message is not executed with object perform: message, you should check. message perform should work because it already has the receiver.
In any case, this complexity may show that having only (one) model and (one) message is not enough to get the model in th granularity you want, and you can possibly specialize a bit more, using the knowledge that the model is a dictionary. For instance, having an instance variable for key or for keyIndex.
Some side notes about the code:
(model = nil or: message = nil)
has comparisons with nil, that can be replaced by #isNil message or, if you want to stick with equality, use the faster == to compare identity, since nil is unique.
#or: is used to get the benefits of partial evaluation (the argument is evaluated only if the receiver is false). But that only works if you have a block as argument, otherwise the expression is evaluated before, to get the argument for the message in the stack.

Omnis Studio: Return more than 1 value

I'm currently programming with Omnis Studio and I need your help.
I need to return more than 1 value, but Quit Method only allows 1 value.
Is there another option to return more than 1 value?
Thank you for your help!
You can use field reference parameters where the given parameter can be changed itself inside your method.
Another way is to return a row or list variable that contains different return values.
A list is a data structure that contains one or more columns and one or more rows. Each column can have its own data type.
A row variable is simply a list with only one row.
Calculate myRow as row(myVar1, myVar2, myVar3)
Quit method myRow
You can access the columns by name or even by number (in the sample above the columns don’t have a name):
Calculate mySecondVar as myRow.c2
In this case c2 stands for column 2 and refers to the second variable in that row.
This way you can easily return as much values as you like.
What you want to do is pass parameter(s) by reference.
You can do this in Omnis by defining your method's parameter to be of type 'field reference'.
This means that instead of passing a copy of the value of the variable you pass, it is passing a reference to the original variable.
So any operations performed on the field ref inside the method will actually be acting on the original variable passed in to your method.
E.g. We have a method, $myMethod, which has a parameter, pRef, of type Field Reference:
Calculate pRef as 123
Quit method "ABC"
We call this method from elsewhere:
Calculate lVar as 0
Calculate lReturn as $cinst.$myMethod(lVar)
After calling $myMethod, lReturn will be "ABC" and lVar will be 123.
(I hope this wasn't too late to help you)

Using Ruby to solve a quiz

So I found this quiz on a website that I was excited to solve with my newly acquired Ruby skills (CodeAcademy, not quite finished yet).
What I want to do is make an array with 100 entries, all set to "open". Then, I planned to create a method containing a for loop that iterates through every nth entry of the array and changes it to either "open" or "closed", based on what it was before. In the for loop, n should be increased from 1 to 100.
What I have so far is this:
change_state = Proc.new { |element| element == "open" ? element = "closed" : element = "open" }
def janitor(array,n)
for i in 1..n
array.each { |element| if array.index(element) % i == 0 then element.change_state end }
end
end
lockers = [*1..100]
lockers = lockers.map{ |element| element = "closed" }
result = janitor(lockers,100)
When trying to execute I receive an error saying:
undefined method `change_state' for "closed":String (NoMethodError)
Anybody an idea what is wrong here? I kinda think I'm calling the "change_state" proc incorrectly on the current array element.
If you know the quiz, no spoilers please!
As you have implemented change_state, it is not a method of any class, and definitely not one attached to any of the individual elements of the array, despite you using the same variable name element. So you cannot call it as element.change_state.
Instead, it is a variable pointing to a Proc object.
To call the code in a Proc object, you would use the call method, and syntax like proc_obj.call( params ) - in your case change_state.call( element )
If you just drop in that change, your error message will change to:
NameError: undefined local variable or method `change_state' for main:Object
That's because the change_state variable is not in scope inside the method, in order to be called. There are lots of ways to make it available. One option would be to pass it in as a parameter, so your definition for janitor becomes
def janitor(array,n,state_proc)
(use the variable name state_proc inside your routine instead of change_state - I am suggesting you change the name to avoid confusing yourself)
You could then call it like this:
result = janitor(lockers,100,change_state)
Although your example does not really need this structure, this is one way in which Ruby code can provide a generic "outer" function - working through the elements of an array, say - and have the user of that code provide a small internal custom part of it. A more common way to achieve the same result as your example is to use a Ruby block and the yield method, but Procs also have their uses, because you can treat them like data as well as code - so you can pass them around, put them into hashes or arrays to decide which one to call etc.
There may be other issues to address in your code, but this is the cause of the error message in the question.

How to (if possible) get the reference of an in-memory object (class instance)?

I'm trying to see if there's a way to get a refference of an object which is outside the local (and global) scope, but who exists in memory.
Let's say in my program, i've instantiated an object whose reference is this:
{O:9*\PROGRAM=ZAVG_DELETE_THIS\CLASS=LCL_SMTH}
Far away after tons of calls, in a context where i wouldn't be able to access this object, could i do something like getting the reference of this object simply by knowing the above string?
I was looking into the cl_abap_*descr classes, but i haven't found a method that takes the 'program_name', 'class_name' and 'instance_number', to return the reference of an object.
I'm trying to do this for the purpose of debugging, not to build something that works.
[EDIT 1]:
I assumed that the o:9 string was required in order to get the reference of the object. As pointed out in the response of #mydoghasworms, this isn't the case. It seems that i only need the local name of the variable which holds the reference.
I hope I understand your question correctly, because I am not sure what you mean with "for the purpose of debugging", but here goes:
You can access the variables of another program that are loaded in the memory of the same session (I am pretty sure it does not need to be in the call stack) using:
ASSIGN ('(PROGRAM)VARIABLE') TO LV_LOCAL.
With reference variables, it becomes a bit more tricky, but here is an example that will help to demonstrate.
Here is our calling program that contains a reference variable LR_TEST which we want to access somewhere else. For the purpose of the demonstration, I make reference to a locally defined class (because that's what I gather from your question).
REPORT ZCALLER.
class lcl_test definition.
public section.
data: myval type i.
methods: my_meth exporting e_val type i.
endclass.
data: lr_test type ref to lcl_test.
CREATE OBJECT lr_test.
lr_test->MYVAL = 22.
perform call_me(zcallee).
class lcl_test implementation.
method my_meth.
* Export the attribute myval as param e_val.
e_val = myval.
endmethod.
endclass.
Here is the program in which we want to access a variable from the above program.
REPORT ZCALLEE.
form call_me.
field-symbols: <ref>.
data: ld_test type ref to object.
data: lv_val type i.
* Exhibit A: Gettinf a reference to a 'foreign' object instance
assign ('(ZCALLER)LR_TEST') to <ref>.
* <ref> now contains a reference to the class instance from the program
* ZCALLER (not very useful, except for passing around maybe)
* Exhibit B: Getting a public attribute from a 'foreign' class instance
assign ('(ZCALLER)LR_TEST->MYVAL') to <ref>.
* <ref> now contains the value of the attribute MYVAL
* Exhibit C: Getting a reference to an instance and calling a method
assign ('(ZCALLER)LR_TEST') to <ref>. "Again the class reference
if sy-subrc = 0. "Rule: Always check sy-subrc after assign before
"accessing a field symbol! (but you know that)
ld_test = <ref>. "Now we have a concrete handle
* Now we make a dynamic method call using our instance handle
CALL METHOD ld_test->('MY_METH')
IMPORTING
e_val = lv_val.
endif.
endform.

Duplicate mongo mapper association for manipulation in memory

I would like to
1. Grab an object 1 and object 2 from the database (both have 2 has_many associations each)
2. Create object 3 which is a clone of object 1 and therefore has no associations yet
2. Duplicate object 2's associations and add them to object 3's associations
3. Use the new object 3 for operations in memory
4. Exit the process with no permanent change to the database - object 1 and object 2 still have their original associations when the process exits
What instead is happening
I grab an object 1 and object 2 from the database (both have 2 has_many associations each)
I create object 3 which is a clone of object 1 and therefore has no associations yet
I duplicate object 2's associations and add them to object 3's associations
I use the new object 3 for operations in memory
I exit the process HOWEVER there is now a permanent change to the database - object 2 no longer has its associations because their keys have been changed to the (Temporary) object 3 id.
Here is my code. Note that all contains an array with an arbitrary # of objects in it
object1 = all.last.clone #we take the most recently created object
all.each do |instance|
instance_association1 = (instance.association1).dup
object1.association1 += instance_association1 #BUG this moves the association
object1.association1.uniq!
instance_association2 = (instance.association2).dup
object1.association2 += instance_association2
object1.association2.uniq!
end
Note that now when I say:
all.last.association1, I get an empty array.
Help!!
MongoMapper's associations may be a little overzealous with saving. I want to overhaul it sometime, but it's not an easy problem.
The code that's going to tell you when saves happen is many_documents_proxy.rb. When you do my_association = [...], replace is the method that's called.
The only method that doesn't do any saving is build, so you may be able to build up your temporary object like so:
tmp = all.last.clone
all.each do |instance|
instance.association1.each { |doc| tmp.association1.build(doc.attributes) }
tmp.association1.uniq!
# ...
end
More generally, you can convert all your associated documents to arrays and not worry about saving...
associations1 = []
associations2 = []
all.each do |doc|
associations1 += doc.associations1.to_a
associations2 += doc.associations2.to_a
end
assocations1.uniq!
assocations2.uniq!
HOWEVER, watch out! Ruby's uniq method looks like it uses Ruby's #hash method to compute equality, which may not give you the results you want in this case. Do a few tests to make sure that my_obj.hash == my_obj2.hash if my_obj == my_obj2. See this discussion for strategies on implementing your own #hash method, if that's the route you need to go.

Resources