TclOO : Get the name of class where the object was created - tcl

I have two classes :
oo::class create p1 {
constructor {} {
# Here I would like to know where the object was created.
# Inside second class or other
}
}
oo::class create p2 {
constructor {} {
}
}
oo::define p2 {
method testSecond {} {
set obj [p1 new]
}
}
set obj1 [p1 new]
set obj2 [p2 new]
$obj2 testSecond
I have try :
puts "Infoname Class= [info object class [self]]" inside p1 class constructor. But each time I have Infoname Class= ::p1.

Objects are created globally, so they store no information about who created them.
If you insist, you can check via uplevel in the constructor:
oo::class create p1 {
constructor {} {
set ns [uplevel 1 [list namespace current]]
if {[info object isa object $ns]} {
puts "Infoname Class= [info object class $ns]"
} else {
puts Other
}
}
}
But that is very fragile. I would not recommend it.

Related

Why apply() instead of function invokation

The following code does the same thing. The functions tr and td take a function literal with receiver object as input in order to add tr or td tag inside of a table.
class TABLE : Tag("table") {
fun tr(init: TR.() -> Unit) {
children += TR().apply(init)
}
}
class TR : Tag("tr") {
fun td(init: TD.() -> Unit) {
val td = TD()
td.init()
children += td
}
}
My Question is why do I need to use .apply() instead of:
class TABLE : Tag("table") {
fun tr(init: TR.() -> Unit) {
children += TR().init()
}
}
I guess it has something to do with the compiler looking for init() in the tr-object. But shouldn't this be decided on runtime?
As already suggested in my comment, using .apply you can chain invocations of init and += together, because apply returns the target of its invocation.
If you prefer to use init(), you can obtain the same result with
val tr = TR()
children += tr
tr.init()
The key aspect of the chained variation is that the applyfunction of the Kotlin's standard library is defined as an extension function of a generic typeT, accepting a *lambda with receiver as its sole parameter, as you can see here:
inline fun <T> T.apply(block: T.() -> Unit): T
In order to explain its meaning, you can implement this function yourself:
fun <T> T.myApply(block: T.() -> Unit) : T {
this.block()
return this
}
The following example mimics your code, using a fake MyClass type in place of the original TR:
fun <T> T.myApply(block: T.() -> Unit) : T {
this.block()
return this
}
class MyClass(val text: String) {
fun foo() : Unit {
println("foo $text")
}
}
fun initializer(mc: MyClass) {
println("initializer ${mc.text}")
mc.foo()
}
fun run(init: MyClass.() -> Unit) {
val result = MyClass("first").myApply(init)
val x = MyClass("second")
x.init()
}
fun main(args: Array<String>) {
run(::initializer)
}
You can play with this example in order to follow the flow from run to MyClass.foo, through the function accepting init as lambda with receiver parameter: I hope this can help you to clarify your understanding of the key charateristics of both the original and the alternative implementation of tr.

Unknown variable within object

Why is the variable not visible to the proc if called from another proc?
package require itcl
itcl::class foo {
protected variable _name
proc constructor {} {
set _name Juan
}
proc name {} {
return $_name
}
proc name2 {} {
return [name]
}
}
set bar [foo ::#auto]
puts [$bar name]
puts [$bar name2]
This outputs:
Juan
can't read "_name": no such variable
I'm not fully conversant with incrTcl, but I think you don't use proc at all. The constructor should be
constructor {} {
set _name Juan
}
and use the method keyword
method name {} {
return $_name
}
method name2 {} {
return [name]
}
Then
% set bar [foo ::#auto]
::foo0
% puts [$bar name]
Juan
% puts [$bar name2]
Juan

Kotlin initialize a variable before its declaration?

Here is my test code:
class Test {
init {
a = 1
}
constructor() {
a = 2
}
private var a: Int
init {
a = 3
}
}
If I remove the secondary constructor:
class Test {
init {
a = 1 // Error: Variable cannot be initialized before declaration
}
// constructor() {
// a = 2
// }
private var a: Int
init {
a = 3
}
}
I know that
During an instance initialization, the initializer blocks are executed in the same order as they appear in the class body.
But why can I initialize the variable before its declaration if there is a secondary constructor?
Update:
And I found an interesting thing:
class Test {
init {
a = log(1)
}
constructor() {
a = log(2)
}
private var a: Int = log(0)
init {
a = log(3)
}
}
fun log(i: Int): Int {
println(i)
return i
}
fun main(args: Array<String>) {
Test()
}
The output is: 1 0 3 2, this is same as Java, declaration and initialization are two different step, but that is weird for Kotlin's primary constructor, Er...
This is expanding from Michael's comment which refers to the Kotlin documentation:
Note that code in initializer blocks effectively becomes part of the primary constructor. Delegation to the primary constructor happens as the first statement of a secondary constructor, so the code in all initializer blocks is executed before the secondary constructor body. Even if the class has no primary constructor, the delegation still happens implicitly, and the initializer blocks are still executed.
In other words, the init() blocks get associated to the (implicit) primary constructor, which is executed as the first line of your secondary constructor. -Kf
From my point of view it relates not to kotlin but to JVM bytecode which does not actually has "initialization" of variables it just fills them up in constructor, you can inspect it with some decompiler.
Your example looks like minor inconsistency. It's provoked by a fact the first example has no primary constructor, but the second has one. However, https://youtrack.jetbrains.com/issue/KT-22317 was created.

How to get an object by its uid?

Is there any way to get an object by it's UID so that the following code would work?
When the function finishes, the value of property "xxx" should be "string two" not "string one".
// Test class
public function test():void {
this.xxx = "string one";
foo.bar(this.xxx);
trace(this.xxx); // Prints: string two
}
// Foo class
public function bar(value:*):void {
// ... What would I have to do here to get the property, not its value?
value = "string two";
}
What about using the Box brackets? I know this is not the OO way of doing the thing but Action script supports it and it looks like a good alternative here.
class Test {
public var xxx:String;
public function test():void {
this.xxx = "string one";
foo.bar(this,"xxx"); // actual name of property as string ;litral
trace(this.xxx); // Prints: string two
}
}
class Foo {
public function bar(test:*,prop:String):void {
//test could be from any class .
test[prop] = "string two";
}
}
This should do the trick. But You need to make sure whichever code calls "bar" method passes a valid object which has "xxx" property defined as this code is not type safe any more.
A function's parameter (a reference to a variable) can't be changed. It's not a pointer. You can assign other variables to it, but it won't change the argument passed to that function. But you can change the argument's properties:
class Test {
public var xxx:String;
public function test():void {
this.xxx = "string one";
foo.bar(this);
trace(this.xxx); // Prints: string two
}
}
class Foo {
public function bar(test:Test):void {
test.xxx = "string two";
}
}
Of course for this to work, the class Foo has to know Test and also which property to change. This makes everything less dynamic and is maybe not what you want. It's a case where you could use an Interface. Or you might want to stick to common patterns like using a getter and assigning the value to the appropriate property:
class Test {
public var xxx:String;
public function test():void {
this.xxx = "string one";
this.xxx = foo.getValue();
trace(this.xxx); // Prints: string two
}
}
class Foo {
public function getValue():String{
return "string two";
}
}
To get to a property, the easiest way is to encapsulate the property into an object, pass it to the function, and then retrieve it:
// Test class
public function test():void {
var obj: Object = new Object();
obj.variable = "string one";
foo.bar(obj);
trace(obj.variable); // Prints: string two
}
// Foo class
public function bar(value:Object):void {
value.variable = "string two";
}
But why would you want to do this? It's much better in every way to just do xxx = foo.bar();
Pass-by-value:
When passing a variable into a function the variable is copied. Any changes you make to the variable aren't reflected back once you exit.
Pass-by-reference:
When passing a variable into a function, the "pointer" to the variable is passed. Any changes you make to the variable are copied over.
In AS3, everything is pass-by-reference, except primitives (Boolean, String, int, uint, etc), which have special operators behind the scenes to make them act like pass-by-value. As xxx is a String, this is what's happening. (Also, Strings are immutable; you can't actually change their value).
How to fix it (as others have said):
Pass the Test object itself to the bar() function: bar( this );
Encapsulate the xxx parameter in it's own object and pass that: bar( {prop:this.xxx} );
Have bar() return the value and set it: this.xxx = bar();

Grails JSONBuilder

If I have a simple object such as
class Person {
String name
Integer age
}
I can easily render it's user-defined properties as JSON using the JSONBuilder
def person = new Person(name: 'bob', age: 22)
def builder = new JSONBuilder.build {
person.properties.each {propName, propValue ->
if (!['class', 'metaClass'].contains(propName)) {
// It seems "propName = propValue" doesn't work when propName is dynamic so we need to
// set the property on the builder using this syntax instead
setProperty(propName, propValue)
}
}
def json = builder.toString()
This works fine when the properties are simple, i.e. numbers or strings. However for a more complex object such as
class ComplexPerson {
Name name
Integer age
Address address
}
class Name {
String first
String second
}
class Address {
Integer houseNumber
String streetName
String country
}
Is there a way that I can walk the entire object graph, adding each user-defined property at the appropriate nesting level to the JSONBuilder?
In other words, for an instance of ComplexPerson I would like the output to be
{
name: {
first: 'john',
second: 'doe'
},
age: 20,
address: {
houseNumber: 123,
streetName: 'Evergreen Terrace',
country: 'Iraq'
}
}
Update
I don't think I can use the Grails JSON converter to do this because the actual JSON structure I'm returning looks something like
{ status: false,
message: "some message",
object: // JSON for person goes here
}
Notice that:
The JSON generated for the ComplexPerson is an element of a larger JSON object
I want to exclude certain properties such as metaClass and class from the JSON conversion
If it's possible to get the output of the JSON converter as an object, I could iterate over that and remove the metaClass and class properties, then add it to the outer JSON object.
However, as far as I can tell, the JSON converter only seems to offer an "all or nothing" approach and returns it output as a String
I finally figured out how to do this using a JSONBuilder, here's the code
import grails.web.*
class JSONSerializer {
def target
String getJSON() {
Closure jsonFormat = {
object = {
// Set the delegate of buildJSON to ensure that missing methods called thereby are routed to the JSONBuilder
buildJSON.delegate = delegate
buildJSON(target)
}
}
def json = new JSONBuilder().build(jsonFormat)
return json.toString(true)
}
private buildJSON = {obj ->
obj.properties.each {propName, propValue ->
if (!['class', 'metaClass'].contains(propName)) {
if (isSimple(propValue)) {
// It seems "propName = propValue" doesn't work when propName is dynamic so we need to
// set the property on the builder using this syntax instead
setProperty(propName, propValue)
} else {
// create a nested JSON object and recursively call this function to serialize it
Closure nestedObject = {
buildJSON(propValue)
}
setProperty(propName, nestedObject)
}
}
}
}
/**
* A simple object is one that can be set directly as the value of a JSON property, examples include strings,
* numbers, booleans, etc.
*
* #param propValue
* #return
*/
private boolean isSimple(propValue) {
// This is a bit simplistic as an object might very well be Serializable but have properties that we want
// to render in JSON as a nested object. If we run into this issue, replace the test below with an test
// for whether propValue is an instanceof Number, String, Boolean, Char, etc.
propValue instanceof Serializable || propValue == null
}
}
You can test this by pasting the code above along with the following into the grails console
// Define a class we'll use to test the builder
class Complex {
String name
def nest2 = new Expando(p1: 'val1', p2: 'val2')
def nest1 = new Expando(p1: 'val1', p2: 'val2')
}
// test the class
new JSONSerializer(target: new Complex()).getJSON()
It should generate the following output which stores the serialized instance of Complex as the value of the object property:
{"object": {
"nest2": {
"p2": "val2",
"p1": "val1"
},
"nest1": {
"p2": "val2",
"p1": "val1"
},
"name": null
}}
In order for the converter to convert the whole object structure you need to set a property in the config to indicate that, otherwise it will just include the ID of the child object, so you need to add this:
grails.converters.json.default.deep = true
For more information go Grails Converters Reference.
However, like you mentioned it in the comment above it is all or nothing, so what you can do is create your own marshaller for your class. I had to do this before because I needed to include some very specific properties, so what I did was that I created a class that extends org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller. Something like:
class MyDomainClassJSONMarshaller extends DomainClassMarshaller {
public MyDomainClassJSONMarshaller() {
super(false)
}
#Override
public boolean supports(Object o) {
return (ConverterUtil.isDomainClass(o.getClass()) &&
(o instanceof MyDomain))
}
#Override
public void marshalObject(Object value, JSON json) throws ConverterException {
JSONWriter writer = json.getWriter();
Class clazz = value.getClass();
GrailsDomainClass domainClass = ConverterUtil.getDomainClass(clazz.getName());
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
writer.object();
writer.key("class").value(domainClass.getClazz().getName());
GrailsDomainClassProperty id = domainClass.getIdentifier();
Object idValue = extractValue(value, id);
json.property("id", idValue);
GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties();
for (GrailsDomainClassProperty property: properties) {
if (!DomainClassHelper.isTransient(transientProperties, property)) {
if (!property.isAssociation()) {
writer.key(property.getName());
// Write non-relation property
Object val = beanWrapper.getPropertyValue(property.getName());
json.convertAnother(val);
} else {
Object referenceObject = beanWrapper.getPropertyValue(property.getName());
if (referenceObject == null) {
writer.key(property.getName());
writer.value(null);
} else {
if (referenceObject instanceof AbstractPersistentCollection) {
if (isRenderDomainClassRelations(value)) {
writer.key(property.getName());
// Force initialisation and get a non-persistent Collection Type
AbstractPersistentCollection acol = (AbstractPersistentCollection) referenceObject;
acol.forceInitialization();
if (referenceObject instanceof SortedMap) {
referenceObject = new TreeMap((SortedMap) referenceObject);
} else if (referenceObject instanceof SortedSet) {
referenceObject = new TreeSet((SortedSet) referenceObject);
} else if (referenceObject instanceof Set) {
referenceObject = new HashSet((Set) referenceObject);
} else if (referenceObject instanceof Map) {
referenceObject = new HashMap((Map) referenceObject);
} else {
referenceObject = new ArrayList((Collection) referenceObject);
}
json.convertAnother(referenceObject);
}
} else {
writer.key(property.getName());
if (!Hibernate.isInitialized(referenceObject)) {
Hibernate.initialize(referenceObject);
}
json.convertAnother(referenceObject);
}
}
}
}
}
writer.endObject();
}
...
}
That code above is pretty much the same code as it is DomainClassMarshaller, the idea would be that you add or remove what you need.
Then in order for Grails to use this new converter what you need is to register it in the resources.groovy file, like this:
// Here we are regitering our own domain class JSON Marshaller for MyDomain class
myDomainClassJSONObjectMarshallerRegisterer(ObjectMarshallerRegisterer) {
converterClass = grails.converters.JSON.class
marshaller = {MyDomainClassJSONMarshaller myDomainClassJSONObjectMarshaller ->
// nothing to configure, just need the instance
}
priority = 10
}
As you can see this marshaller works for a specific class, so if you want to make more generic what you can do is create a super class and make your classes inherit from that so in the support method what you do is say this marshaller support all the classes that are instances of that super class.
My suggestion is to review the grails code for the converters, that will give you an idea of how they work internally and then how you can extend it so it works the way you need.
This other post in Nabble might be of help too.
Also, if you need to do it for XML as well then you just extend the class org.codehaus.groovy.grails.web.converters.marshaller.xml.DomainClassMarshaller and follow the same process to register it, etc.