Unknown variable within object - tcl

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

Related

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

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.

Parameters KFunction in Kotlin

I have a class that has the type parameter KFunction<*>
(It is understood that I will indicate the type of function that I want to work with in the future)
I want a class method to take the same parameters that KFunction has and call subscribers with those arguments. However, I don't know how to get the type of the function parameters. There are delegates in C #. How to do something like this in Kotlin?
My class:
class Event<Function: KFunction<*>> {
val subscribers = mutableListOf<Function>()
operator fun plus(increment: Function) {
subscribers.add(increment)
}
// i want arguments as KFunction
operator fun invoke(args: ???) {
subscribers.forEach { it(args) }
}
}
fun c(i: Int) {
println("result of function c: $i")
}
fun main() {
val event = Event<KFunction1<Int, Unit>>()
event + ::c
event(100) // passing arguments Int from KFunction1<Int, Unit>
}
Is there a way to implement my idea exactly like this?
So, it's implied that type, passed as a Function : KFunction<*> type parameter (KFunction1<Int, Unit> in this case) will have its own type parameters (Int and Unit in this case), and you want to declare args parameter as an uncertain amount of parameters with these exact types (excluding the last one, which represents type of function call result)?
I believe it's impossible.
The best you can do is to declare args as vararg with Any? type:
operator fun invoke(vararg args: Any?) = subscribers.forEach { it.call(*args) }
It seems that the only normal solution to problem is to accept only 1 abstract type of parameters.
class Event<ArgsT> {
private val subscribers = mutableListOf<(ArgsT) -> Any>()
operator fun plusAssign(increment: (ArgsT) -> Any) {
subscribers.add(increment)
}
operator fun invoke(params: ArgsT) {
subscribers.forEach { it(params) }
}
}
fun c(i: Int, b: Int) {
println(i + b)
}
data class Data(val i: Int, val b: Int)
fun main() {
val event = Event<Data>()
event += { (i, b) -> c(i, b) } // pass arguments using a lambda
event(Data(2, 5))
}

How to apply function to value defined in data class constructor before init method?

Let's say I have a data class like this:
data class MyData(val something: Int, val somethingElse : String) {
init {
require(something > 20) { "Something must be > 20" }
require(StringUtils.isNotEmtpy(somethingElse)) { "Something else cannot be blank" }
}
}
I'd like to be able to apply a function to somethingElse before the init method is called. In this case I want to remove all \n characters from the somethingElse String while maintaining immutability of the field (i.e. somethingElse must still be a val). I'd like to do something similar to this in Java:
public class MyData {
private final int something;
private final String somethingElse;
public MyDate(int something, String somethingElse) {
this.something = something;
this.somethingElse = StringUtils.replace(somethingElse, '\n', '');
Validate.isTrue(something > 20, "...");
Validate.isTrue(StringUtils.isNotEmtpy(this.somethingElse), "...");
}
// Getters
}
I could of course create a normal class (i.e. no data class) in Kotlin but I want MyData to be a data class.
What is the idiomatic way to do this in Kotlin?
While you can not literally do what you want, you can fake it.
Make all constructors of your data class private.
Implement factories/builders/whatevers on the companion as operator fun invoke.
Usages of Companion.invoke will -- in Kotlin! -- look just like constructor calls.
In your example:
data class MyData private constructor(
val something: Int,
val somethingElse : String
) {
init {
require(something > 20) { "Something must be > 20" }
require("" != somethingElse) { "Something else cannot be blank" }
}
companion object {
operator fun invoke(something: Int, somethingElse: String) : MyData =
MyData(something, somethingElse.replace("\n", " "))
}
}
fun main(args: Array<String>) {
val m = MyData(77, "something\nwicked\nthis\nway\ncomes")
println(m.somethingElse)
}
Prints:
something wicked this way comes
You'll note the helpful warning:
Private data class constructor is exposed via the generated 'copy' method.
This method can not be overridden (as far as I can tell) so you have to take care, still. One solution is to hide the actual data class away:
interface MyData {
val s: Int
val sE: String
private data class MyDataImpl(
override val s: Int,
override val sE: String
) : MyData {
init {
require(s > 20) { "Something must be > 20" }
require("" != sE) { "Something else cannot be blank" }
}
}
companion object {
operator fun invoke(s: Int, sE: String) : MyData =
MyDataI(s, sE.replace("\n", " "))
}
}
Now your invariant (no line breaks) is maintained, copy and other dangerous methods (if any, I haven't checked) are hidden away -- but therefore also unavailable, potentially removing some of the convenience data classes provide.
Choose your poison.

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();

D compile-time function type extraction

D2.056
Function is a struct holding the name and the type of the function (Name and Type respectively). Binds iterates over a list of Function structs and returns a mixin string. This mixin defines for each function a new name with a '2' appended.
void f() { writeln("f"); }
void g() { writeln("g"); }
struct Function(string name, Prototype)
{
const string Name = name;
mixin("alias Prototype Type;");
}
string Binds(Functions...)()
{
string r;
foreach (F; Functions)
{
// error:
r ~= to!string(typeid(F.Type)) ~ " " ~ F.Name ~ "2 = &" ~ F.Name ~ ";";
}
return r;
}
int main()
{
mixin (Binds!(
Function!("f", void function()),
Function!("g", void function())
));
f();
//f2();
return 0;
}
When compiling, the to!string(typeid(F.Type)) gives an error:
Error: Cannot interpret & D13TypeInfo_PFZv6__initZ at compile time
called from here: to(& D13TypeInfo_PFZv6__initZ)
called from here: Binds()
Firstly, I don't see why an explicit conversion to string is required (isn't typeid already a string, if not, whats the difference between typeid and typeof?).
Secondly, I can't figure out how to get the explicit function type written out so that it can be executed in main. I can't use F.Type since it is local to the foreach.
You've got a couple problems here, but the main one is that typeid returns an object of type TypeInfo (typeid expression). Fortunately, you can just use F.Type.stringof. Also note that you don't need the mixin to alias Prototype as Type:
void f() { writeln("f"); }
void g() { writeln("g"); }
struct Function(string name, Prototype)
{
const string Name = name;
alias Prototype Type;
}
string Binds(Functions...)()
{
string r;
foreach (F; Functions)
{
// error:
r ~= F.Type.stringof ~ " " ~ F.Name ~ "2 = &" ~ F.Name ~ ";";
}
return r;
}
import std.stdio,
std.conv;
int main()
{
mixin (Binds!(
Function!("f", void function()),
Function!("g", void function())
));
f();
f2();
return 0;
}
Running this prints:
f
f
which I believe is what you're looking for.