# Create an object whose state changes on assignment

I find it deeply weird that this is possible in Ruby (I won't immediately say how):

obj = #code redacted

print obj.state # Some value.

LValue = obj

print obj.state # Different value!


Your challenge is to create code roughly of this form. Create an object and assign it to a variable. It should have some defined attribute (or deterministic, idempotent method) like state above, that changes after the object is assigned to a new identifier (LValue above), even if you still use the old identifier (obj above) to refer to it.

Edit for emphasis: state or the equivalent must be idempotent, so creating an accessor that modifies the value, or for any other reason returns different results when called several times in a row, isn't a valid solution. Or, more simply, it has to be the assignment that changes the state.

Any language with assignment is eligible, although there are probably some where there's no fully legitimate solution. I'll post my Ruby answer if nobody else gets it after a few days, and accept highest-voted answers on a rolling basis.

-
Must the LValue = obj line be required for state to actually change? (I could just make a property in C# that increments every time you get it) –  Tim S. Jun 4 '14 at 20:27
Yes, that's what I intended by saying the method needed to be idempotent. I'll edit to make that clearer. –  histocrat Jun 4 '14 at 20:33
Ok, thanks. I must've glossed over that part. –  Tim S. Jun 4 '14 at 20:36
Would simply returning the refcount of the object work? –  Nick T Jun 5 '14 at 22:51

## C++

This is trivial using the right tools.

#include <iostream>

using namespace std;

class Obj {
public:
int state;

Obj& operator= (Obj& foo) {
foo.state++;
this->state = foo.state - 2;
return *this;
}
};

int main() {
Obj a, b, c, d;
a.state = 3;
b.state = 4;

cout << a.state << " " << b.state << "\n";

c = a;
d = b;

cout << a.state << " " << b.state << " " << c.state << " " << d.state << "\n";

return 0;
}


Output:

3 4
4 5 2 3

-
The moment I saw the title, I knew someone would do operator overloading. It's the obvious way. Have an upvote. –  professorfish Jun 4 '14 at 16:09

# PHP (debug build, >= 5.4)

We use refcount of the object in a getter. (So, by the assignment, refcount increases and value changes)

class State {
public function __get($arg) { ob_start(); debug_zval_dump($this); // e.g. "object(State)#1 (0) refcount(6)"
return ob_get_clean()[29];
}
}

$obj = new State; var_dump($obj->state);
$a =$obj;
var_dump($obj->state);  - # C# Two simple options: class Obj { public int state; public static implicit operator int(Obj o) { return o.state++; } } static int LValueI; static Obj LValueM { set { value.state++; } } static void Main() { var obj = new Obj { state = 1 }; LValueI = obj; Console.WriteLine(obj.state); //2, caused by the implicit cast. LValueM = obj; Console.WriteLine(obj.state); //3, caused by the property setter. Console.ReadLine(); }  Or we could simply write to the same memory: [StructLayoutAttribute(LayoutKind.Explicit)] class Program { [FieldOffset(0)] int state = 1; [FieldOffset(1)] int LValue; void Test() { var obj = this; Console.WriteLine(state); //1 LValue = state; Console.WriteLine(state); //257 Console.ReadLine(); } static void Main() { new Program().Test(); } }  - # TeX, much shorter than other answers here \setbox0=\hbox{Hello world!} % Put stuff in the box 0. \message{\the\wd0} % Print the width of the box => non-zero \setbox2=\box0 % Put the box instead in box 2. \message{\the\wd0} % Now box 0 is void, hence has zero width.  As a typesetting system, TeX has a "box" type, which contains typeset material. Since the most common use case is to move this material around, split it, etc, rather than making copies of it, boxes are normally deleted when used (or rather, "box" variables are pointers and only one pointer at a time can point to an actual box in memory). No need for any magic. - # Fortran 03 This is somewhat similar to Hugo's D answer, but is a little more hidden (partly because who the #$%^ knows Object Oriented Fortran)?

module objects
implicit none

type ObjDef
integer :: state
contains
procedure :: initObject
procedure :: printObject
procedure :: setNew
end type
contains
subroutine initObject(this)
class(ObjDef) :: this
this%state = this%state + 1
end subroutine initObject

subroutine printObject(this)
class(ObjDef) :: this
print '(a,i0)',"this%state = ",this%state
end subroutine printObject

subroutine setNew(this,that)
class(ObjDef) :: this,that
that%state = this%state
end subroutine setNew

end module objects

program objectChange
use objects
type(ObjDef) :: a,b

call initObject(a)
call printObject(a)
call b%setNew(a)
call printObject(a)
end program objectChange


The output is

this%state = 1
this%state = 0


If you can figure out what happened, bonus points to you! If not:

When calling the procedure setNew in the form call b%setNew(a), b is implicitly the first argument, not the second.

-

## PowerShell

This creates an object whose state property is the names of the variables that point to the object.

$a = @{}| Add-Member -MemberType:16 -PassThru state -Value { (gv|?{$this -eq $_.Value}|%{$_.Name}) -join ','}

'Before: ' + $a.state$b = $a 'After: ' +$a.state


Output

Before: a,this
After: a,b,this


Note: This doesn't work if the assignment happens in a child scope.

'Before: ' + $a.state &{$b = $a} 'After: ' +$a.state


Outputs

Before: a,this
After: a,this

-

# Perl 5

Here's one way to do it in Perl:

package Magic {
sub new { bless {state => 1} }
use overload '""' => sub { $_[0]{state}++ }; } use feature 'say'; my$obj = new Magic;
say $obj->{state}; substr($_, 0) = $obj; say$obj->{state};


This outputs:

1
2


Explanation:

This is a straightforward application of overloading. Specifically, I overload the string conversion operator "", which gets called when the overloaded object is assigned to substr() (which, yes, is a legal lvalue in Perl).

There are also plenty of special variables in Perl which stringify anything assigned to them. For example, the following also works:

my $obj = new Magic; say$obj->{state};
$0 =$obj;
say $obj->{state};  ## Alternative solution Here's another way to it: package Magic { use Devel::Peek 'SvREFCNT'; sub new { bless \my$foo }
sub state { SvREFCNT ${$_[0]} }
}
use feature 'say';

my $obj = new Magic; say$obj->state;
my $other =$obj;
say $obj->state;  Here, state is a method (we could make it an attribute with further tie / overload shenanigans, but that would complicate things) that literally counts the number of references to the object. Thus, unlike in the first solution, you actually have to assign $obj to a normal variable that can hold an object reference to make the state change.

-

## C++11 (So you guys have forgotten about unique_ptr/shared_ptr :-) )

#include <iostream>
#include <memory>
using namespace std;
int main() {
std::unique_ptr<int> u1(new int(0)), u2;
std::shared_ptr<int> s1 = std::make_shared<int>(0), s2;
std::cout<<u1.get()<<" "<<u2.get()<<" "<<std::endl;
std::cout<<s1.use_count()<<" "<<s2.use_count()<<" "<<std::endl;
u2 = std::move(u1);
s2 = s1;
std::cout<<u1.get()<<" "<<u2.get()<<" "<<std::endl;
std::cout<<s1.use_count()<<" "<<s2.use_count()<<" "<<std::endl;
return 0;
}

-

# Python

It's cheating a little, but how about:

import gc
class A(object):
@property
def state(self):
return len(gc.get_referrers(self))

a = A()
print a.state
b = {"x": a}
print a.state
a.y = a
print a.state
del a
print b["x"].state

-

## C++11

though this can be extended for other languages that supports implicit / explicit destrucors

#include <iostream>
using namespace std;

class Foo {
int *ptr;
public:
Foo() {
ptr = new int(0);
}
int state() {
return *ptr;
}
~Foo() {
(*ptr)++;
}
};
int main() {
Foo a, b;
cout << a.state() << " " << b.state() << "\n";
{
Foo c, d;
c = a;
d = b;
}
cout << a.state() << " " << b.state()  << "\n";

return 0;
}


The default assignment operator performs a shallow copy. So the receiving object still owns the pointer and any change implicitly affects the original object;

-
Yeah, a new without a single delete in the program. Although, for this task it's good enough I think :) –  Ruslan Jun 5 '14 at 19:07
What are the outputs ? –  Nicolas Barbulesco Jun 7 '14 at 13:14
From what I understand (C++ is far away…), here the assignment does not change the state. Otherwise, move the cout line up before the } and tell whether that works. :-) –  Nicolas Barbulesco Jun 7 '14 at 13:28

In Java

I thought this was impossible in Java. But…

Main class :

public class MyAppOfCats {

public static void main(String[] args) {
Cat tom = new Cat();
System.out.println(tom.state());
// Output : NOT-BEST-CAT
Cat.bestCat = tom;
System.out.println(tom.state());
// Output : BEST-CAT
}

}


Class Cat :

public class Cat {

static Cat bestCat;

public Cat() {
super();
}

public String state() {
return ((this == Cat.bestCat) ? "BEST-CAT" : "NOT-BEST-CAT");
}

}


I have been inspired by @tbodt.

-
I know it's not code-golf, but you realize you can just remove the constructor and it's still the same, right? –  David Conrad Jun 6 '14 at 20:37
This isn't "an object whose state changes on assignment". This is you manipulating a global value and then printing something based on it. It's no different from Cat.x = 2 and then printing Cat.x. –  Chris Hayes Jun 8 '14 at 6:53
@Chris — The object state is based on a “global value”. So the object state changes on assignment. The question states ;-) that the state may be a deterministic, idempotent method. My method state() is such a method. –  Nicolas Barbulesco Jun 8 '14 at 11:40
No, the object state changes on this particular assignment. If I did Cat otherCat = tom the state wouldn't have changed at all. I have a hard time believing this meets the letter or spirit of the rules. –  Chris Hayes Jun 8 '14 at 16:08
@Chris — Of course the object changes on this assignment ! The question asks for an object whose state be changed by the assignment. Not for an object whose state be changed by any assignment. –  Nicolas Barbulesco Jun 8 '14 at 16:24

## D

struct Obj {
int state;

void opAssign (ref Obj other) {
++other.state;
}
}

void main () {
import std.stdio;

Obj obj, lvalue;
writeln(obj);
lvalue = obj;
writeln(obj);
}


Output:

Obj(0)
Obj(1)

-

## Scala

Implicit conversions let you accomplish this while assigning to a normal local variable:

import scala.language.implicitConversions

class Obj {
var counter = 0
}

implicit def o2s(x: Obj): String = {
x.counter += 1
x.toString
}

val obj = new Obj
println(obj.counter)
val s: String = obj
println(obj.counter)


You can accomplish that with inferred types, too:

var s = ""
s = obj


You can also use a custom setter method, though that requires the L-value to be a field:

object L {
var _value = new Obj
def value = _value
def value_=(x: Obj): Unit = {
_value = x
x.counter += 1
}
}

val obj = new Obj
println(obj.counter)
L.value = obj
println(obj.counter)

-

# Ruby

As promised, here's the answer that inspired the question.

obj = Class.new { def self.state; to_s[/</] ? "Has not been assigned\n" : "Assigned to #{to_s}"; end }

print obj.state

LValue = obj

print obj.state


Class.new creates an anonymous class. Calling to_s on an anonymous class gives the default string representation of objects, which looks like #<Class:0x007fe3b38ed958>. However, once the class has been assigned to a constant, to_s becomes that constant. In Ruby, a constant is a variable that begins with an uppercase letter, so obj is a reference to the class that allows it to stay anonymous.

My code wraps to_s in a state method, so the output becomes

Has not been assigned
Assigned to LValue


Unlike most of the solutions here, this only works once: assigning obj to another constant won't change its string representation, and neither will assigning a new value to LValue.

-

# JavaScript

Ok, so i made a shorter version that works as SSCCE, but does no longer try to parse JavaScript properly, so the reference counting might not work when put inside a more complex script.

(function run () {
var lineOne = getLine (1), a, b, x, y, z;
var x = {
get state () {
var x=/([a-z]+)\s*=\s*([a-z]+)/,c;
return 1 + Object.keys (c = run.toString ().split ('\n').slice (0,getLine (2)).filter (function (a) {return (x.test (a))}).reduce (function (a,b,c,d) {var r=b.match (x),t=r[2];while (a[t]){t=a[t]};a[r[1]]=t;return a}, {v:0})).reduce (function (a,b) {return (c[b]=="x"?1:0) + a},0)
}
};
console.log (x.state);  //1
console.log (x.state);  //1
y = x;
console.log (x.state);  //2
z = y;
console.log (x.state);  //3
a = z;
b = a;
console.log (x.state);  //5
a = null;
console.log (x.state);  //4
b = null;
console.log (x.state);  //3
})() //1 1 2 3 5 4 3

function getLine(n) {
try {
to
} catch (dat) {
var stack = dat.stack.split('\n');
for (var i = 0; i < stack.length; i++) {
if (~stack[i].indexOf ('getLine')) break;
}
return dat.stack.split ('\n')[i + ~~n].match (/:(\d+)/)[1] - ~~window.hasOwnProperty ('__commandLineAPI')
}
}

-
Care to explain what your doing? –  ryan Jun 6 '14 at 16:30
... what in the world is this? O_o –  Doorknob Jun 6 '14 at 16:38
@Doorknob A getter that returns the result, of calling a function, which counts how often an identifiername is being referenced as rval, in an assignment expression, within a given sourcetext up to a given line, passing its enclosing functions source and the line the getter got called from as arguments. Everything else is a messy provisorical tokenizer. --- I don't know how else i should call it. In other words. In other words: The getter counts the number of assignments of references to x up to the line it got called from, the rest is a not finished tokenizer. –  C5H8NNaO4 Jun 6 '14 at 16:57
The longest …and the widest ! –  Nicolas Barbulesco Jun 7 '14 at 13:44
@NicolasBarbulesco I made it shorter –  C5H8NNaO4 Jun 8 '14 at 1:13

# C++

This behavior is actually specified in the standard (and that's why it was deprecated).

#include<iostream>
#include<memory>
int main()
{
std::auto_ptr<int> a(new int(0));
std::cout<<a.get()<<'\n';
std::auto_ptr<int> b = a;
std::cout<<a.get()<<'\n';
}


Output

some address
0


The process that causes this is the same as Abhijit's answer but without requiring a std::move and the same as marinus' answer but using a standard class instead of defining it myself.

Edit: I'm adding some explanation. In the output, "some address" will actually be a hex value for the address of the allocated integer. std::auto_ptr releases its stores pointer when assigned to another auto_ptr and sets its internal pointer to 0. Calling get() retrieves access to the stores pointer.

-
I suspect that the "output" here is not the real output. –  Nicolas Barbulesco Jun 7 '14 at 13:34
Can you explain what this is supposed to do ? Especially the method get() ? Why would it return 0 at the end ? –  Nicolas Barbulesco Jun 7 '14 at 13:37
@Nicholas yep. This output is not the true output, but a more general output (I also didn't have access to a compiler so I didn't have an example of a valid address at the time). –  JKor Jun 7 '14 at 19:36
Hm, this fails to compile on gcc 4.8. –  Michael Hampton Jun 8 '14 at 2:04
I fixed the compilation errors. There are still warnings if you are compiling for c++11 because auto_ptr is deprecated. –  JKor Jun 8 '14 at 6:05

# Python 2.x

I couldn't find a proper way to do this without defining an extra class.

class State(object):
def __init__(self):
self.state = 0
def __set__(self, obj, other):
# Keep different references
other.state += 1
self.state += 2

class Program(object):
obj, value = State(), State() # Create two State-objects
def __init__(self):
print "Before assignment:", self.obj.state, self.value.state # 0 0
self.value = self.obj # Set value to obj (supposedly)
print "After  assignment:", self.obj.state, self.value.state # 1 2
self.value = self.obj
print "2nd    assignment:", self.obj.state, self.value.state # 2 4

Program()

-

# Java

All the other solutions use their language's form of operator overloading. Java doesn't have operator overloading, so I thought I was stuck. But I came up with something.

Here's the main class:

public class Program {
public static void main(String[] args) {
Thing thing = new Thing(0);
System.out.println(thing.getState());
Thing.otherThing = thing;
System.out.println(thing.getState());
}
}


There are a few suspicious lines, but they wouldn't do anything if the Thing class was completely normal. It isn't:

public class Thing {
private int state;

public Thing(int state) {
this.state = state;
}

public int getState() {
return state;
}

// Please do your best to ignore the rest of this class.
public static volatile Thing otherThing;
static {
public void run() {
Thing t = otherThing;
while (true)
if (t != otherThing) {
t = otherThing;
t.state++;
}
}
};
t.setDaemon(true);
t.start();
}
}


It's not guaranteed to work because of the threads, but I tested it on JDK 1.8u5, and it works there.

-
@KyleKanos Got rid of all unicode chars >U+00FF –  tbodt Jun 5 '14 at 22:44

# C++

The result may differ in different platforms. Tested on ideone.

#include <iostream>
#include <cassert>
// File format: [ciiiiciiii...] a char (1 byte) followed by its state (4 bytes)
// Each group takes 5 bytes
char Buffer[30]; // 5*6, six groups

struct Group {
char c;
int state;
};

int main(void) {
assert(sizeof(char) == 1);
assert(sizeof(int) == 4);

Group& first_group = *(Group*)(&Buffer[0]); // Group 1 is at 0
Group& second_group = *(Group*)(&Buffer[5]); // Group 2 is at 5

first_group.c = '2';
first_group.state = 1234;

std::cout << first_group.state << std::endl;

second_group = first_group;

std::cout << first_group.state << std::endl;

return 0;
}


Output:

1234
13010

-

## C#

class A
{
public int N { get; set; }
public override string ToString() { return N.ToString(); }
}
class B
{
public int N { get; set; }
public override string ToString() { return N.ToString(); }
public static implicit operator A(B b) { b.N = -b.N; return new A { N = b.N }; }
}
public static void Test()
{
A a = new A { N = 1 };
B b = new B { N = 2 };
Console.WriteLine("a is {0}, b is {1}", a, b);
Console.WriteLine("a is {0}, b is {1}", a, b);
a = b;
Console.WriteLine("a is {0}, b is {1}", a, b);
Console.WriteLine("a is {0}, b is {1}", a, b);
}


Output:

a is 1, b is 2
a is 1, b is 2
a is -2, b is -2
a is -2, b is -2

-
What does this do ? Is this overloading the operator = ? –  Nicolas Barbulesco Jun 7 '14 at 13:20
@Nicolas Not exactly. It's when casting from a B to an A, because the implicit operator A(B b) has side-effects. –  ClickRick Jun 8 '14 at 22:22

# Common Lisp

I define state as the number of special variables bound to a vector. So, assignment to a special variable changes the state.

(defgeneric state (object)
(:documentation "Get the state of this object."))

(defmethod state ((object vector))
;; The state of a vector is the number of symbols bound to it.
(let ((count 0))
;; Iterate each SYM, return COUNT.
(do-all-symbols (sym count)
;; When SYM is bound to this vector, increment COUNT.
(when (and (boundp sym) (eq (symbol-value sym) object))
(incf count)))))

(defparameter *a* #(this is a vector))
(defparameter *b* nil)
(defparameter *c* nil)

(print (state *a*))
(setf *b* *a*)
(print (state *a*))
(print (state *a*))
(setf *c* *a*)
(print (state *a*))


Output:

1
2
2
3


It only works with assignments to special variables, not to lexical variables, nor to slots within an object.

Beware that do-all-symbols looks in all packages, so it misses variables that have no package. It might double-count symbols that exist in more than one package (when one package imported the symbol from another package).

# Ruby

Ruby is almost the same, but I define state as the number of constants referring to an array.

class Array
# Get the state of this object.
def state
# The state of an array is the number of constants in modules
# where the constants refer to this array.
ObjectSpace.each_object(Module).inject(0) {|count, mod|
count + mod.constants(false).count {|sym|
begin
mod.const_get(sym, false).equal?(self)
rescue NameError
false
end
}
}
end
end

A = %i[this is an array]
puts A.state
B = A
puts A.state
puts A.state
C = A
puts A.state


Output:

state-assign.rb:9:in const_get': Use RbConfig instead of obsolete and deprecated Config.
1
2
2
3
`

This is a generalization of histocrat's answer to Ruby objects that are not classes or modules. The warning appears because the Config constant autoloads some code that made the warning.

-

## protected by TimtechJun 8 '14 at 20:38

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.