एक ऐसी वस्तु बनाएं जिसका राज्य असाइनमेंट पर बदलता है


31

मुझे यह बहुत अजीब लगता है कि रूबी में यह संभव है (मैं तुरंत नहीं कहूँगा कि कैसे):

obj = #code redacted

print obj.state # Some value.

LValue = obj

print obj.state # Different value!

आपकी चुनौती इस फ़ॉर्म के मोटे तौर पर कोड बनाने की है। एक ऑब्जेक्ट बनाएं और इसे एक वैरिएबल पर असाइन करें। इसमें stateऊपर की तरह कुछ परिभाषित विशेषता (या निर्धारक, सुस्पष्ट विधि) होनी चाहिए , जो कि वस्तु को एक नए पहचानकर्ता ( LValueऊपर) को सौंपे जाने के बाद बदल जाती है , भले ही आप अभी भी पुराने पहचानकर्ता ( objउपरोक्त) का उपयोग इसके संदर्भ में करते हों।

जोर देने के लिए संपादित करें : stateया समतुल्य होना अनिवार्य है, इसलिए मूल्य को संशोधित करने या किसी अन्य कारण से जब एक पंक्ति में कई बार कॉल किया जाता है, तो एक मान्य समाधान नहीं होता है। या, अधिक बस, यह असाइनमेंट होना चाहिए जो राज्य को बदलता है।

असाइनमेंट के साथ कोई भी भाषा योग्य है, हालाँकि कुछ ऐसे भी हैं जहाँ पूरी तरह से वैध समाधान नहीं है। मैं अपना रूबी जवाब पोस्ट करूंगा यदि कुछ दिनों के बाद कोई और नहीं मिलता है, और रोलिंग के आधार पर उच्चतम-मतदान जवाब स्वीकार करते हैं।


क्या वास्तव में बदलने के LValue = objलिए लाइन आवश्यक होनी चाहिए state? (मैं सिर्फ C # में एक संपत्ति बना सकता था जो हर बार आपको मिलता है)
टिम एस।

2
हां, यही मेरा उद्देश्य है कि जिस विधि की आवश्यकता है, वह निष्प्राण होनी चाहिए। मैं स्पष्ट करने के लिए संपादित करूँगा।
हिस्टोक्रेट

ठीक है धन्यवाद। मुझे उस हिस्से पर चमक आनी चाहिए।
टिम एस।

4
क्या केवल वस्तु के काम का रिफंड लौटाया जाएगा?
निक टी

क्या वस्तु में विनाशकारी परिवर्तन ही होगा? EmacsLisp: (setq a (list "val")) (setq b (nconc a "val2"))उदाहरण के लिए। उस बिंदु पर aमूल्यांकन समाप्त होता है ("val" . "val2")
जोनाथन लीच-पेपिन

जवाबों:


30

सी ++

यह सही उपकरण का उपयोग करके तुच्छ है।

#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;
}

आउटपुट:

3 4
4 5 2 3

12
जिस क्षण मैंने शीर्षक देखा, मुझे पता था कि कोई ऑपरेटर ओवरलोडिंग करेगा। यह स्पष्ट तरीका है। एक उत्थान है।

17

PHP (डिबग बिल्ड,> = 5.4)

हम एक गटर में वस्तु के रिफकाउंट का उपयोग करते हैं। (इसलिए, असाइनमेंट द्वारा, रिफंड बढ़ता है और मूल्य में परिवर्तन होता है)

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

14

सी#

दो सरल विकल्प:

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

या हम बस एक ही मेमोरी में लिख सकते हैं:

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

12

TeX, यहाँ अन्य उत्तरों की तुलना में बहुत कम है

\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.

टाइपसेटिंग सिस्टम के रूप में, टीएक्स में एक "बॉक्स" प्रकार होता है, जिसमें टाइपसेट सामग्री होती है। चूँकि सबसे आम उपयोग का मामला है इस सामग्री को इधर-उधर करना, इसे विभाजित करना, इत्यादि, इसकी प्रतियाँ बनाने के बजाय, आमतौर पर उपयोग किए जाने पर बक्से हटा दिए जाते हैं (या यों कहें कि, "बॉक्स" चर बिंदु होते हैं और एक समय में केवल एक सूचक इंगित कर सकता है। स्मृति में एक वास्तविक बॉक्स के लिए)। किसी जादू की जरूरत नहीं।


8

C ++ 11 (तो आप लोग यूनिक_प्रेट / शेयर_प्रेट :-) के बारे में भूल गए हैं)

#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;
}

7

फोरट्रान 03

यह कुछ हद तक ह्यूगो के डी उत्तर के समान है, लेकिन थोड़ा अधिक छिपा हुआ है (आंशिक रूप से क्योंकि # $% ^ ऑब्जेक्ट ओरिएंटेड फोरट्रान को कौन जानता है)?

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

आउटपुट है

this%state = 1
this%state = 0

यदि आप पता लगा सकते हैं कि क्या हुआ है, तो बोनस अंक आपके लिए! अगर नहीं:

प्रक्रिया setNewको फॉर्म में बुलाते समय call b%setNew(a), bपहला तर्क है, दूसरा नहीं।


7

शक्ति कोशिका

यह एक ऐसी वस्तु बनाता है जिसकी stateसंपत्ति चर का नाम है जो ऑब्जेक्ट को इंगित करता है।

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

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

उत्पादन

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

नोट: यह काम नहीं करता है यदि असाइनमेंट चाइल्ड स्कोप में होता है।

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

आउटपुट

Before: a,this
After: a,this

Get-Variable स्मार्ट है!
mazzy 10

5

पर्ल ५

यह पर्ल में करने का एक तरीका है:

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};

यह आउटपुट:

1
2

स्पष्टीकरण:

यह ओवरलोडिंग का एक सीधा आवेदन है । विशेष रूप से, मैं स्ट्रिंग रूपांतरण ऑपरेटर को अधिभारित करता हूं "", जिसे कहा जाता है जब अतिभारित वस्तु को सौंपा जाता है substr()(जो, हां, पर्ल में एक कानूनी रूप से लंबित है)।

पर्ल में बहुत सारे विशेष चर भी हैं जो उन्हें सौंपे गए किसी भी चीज को सख्त करते हैं। उदाहरण के लिए, निम्नलिखित भी काम करता है:

my $obj = new Magic;
say $obj->{state};
$0 = $obj;
say $obj->{state};

दूसरा तरीका

यहाँ यह करने के लिए एक और तरीका है:

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;

यहाँ, stateएक विधि है (हम इसे आगे टाई / अधिभार shenanigans के साथ एक विशेषता बना सकते हैं, लेकिन यह चीजों को जटिल करेगा) जो वस्तु के संदर्भों की संख्या की शाब्दिक गणना करता है। इस प्रकार, पहले समाधान के विपरीत, आपको वास्तव में $objएक सामान्य चर को निर्दिष्ट करना होगा जो राज्य को बदलने के लिए एक वस्तु संदर्भ रख सकता है।


5

जावास्क्रिप्ट

ठीक है, इसलिए मैंने एक छोटा संस्करण बनाया जो एसएससीसीई के रूप में काम करता है, लेकिन अब जावास्क्रिप्ट को ठीक से पार्स करने की कोशिश नहीं करता है, इसलिए अधिक जटिल स्क्रिप्ट के अंदर डालने पर संदर्भ गिनती काम नहीं कर सकती है।

(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')
   }
}

2
यह समझाने के लिए कि आपका क्या करना है?
रयान

5
... दुनिया में यह क्या है? O_O
दरवाज़े

@Doorknob एक गेटर जो एक फ़ंक्शन को कॉल करने के परिणामस्वरूप परिणाम देता है, जो गिनता है कि एक पहचानकर्तानाम को कितनी बार एक असाइनमेंट अभिव्यक्ति में, किसी दिए गए सॉर्सेटेक्स्ट के भीतर किसी दिए गए लाइन तक, एक संलग्न फ़ंक्शन स्रोत और लाइन को पारित करने के लिए संदर्भित किया जाता है। गेट्टर को तर्कों के रूप में बुलाया गया। बाकी सब कुछ एक गन्दा भड़काऊ टोकन है। --- मुझे नहीं पता कि मुझे इसे और कैसे कॉल करना चाहिए । दूसरे शब्दों में। दूसरे शब्दों में: गेट्टर संदर्भों के असाइनमेंट की संख्या को उस लाइन तक x तक गिनता है जिसे इसे कहा जाता है, बाकी एक समाप्त टोकन नहीं है।
C5H8NNaO4

1
सबसे लंबा… और चौड़ा!
निकोलस बारबुल्स्को


4

अजगर

यह थोड़ा धोखा दे रहा है, लेकिन कैसे:

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

4

सी ++ 11

यद्यपि यह अन्य भाषाओं के लिए बढ़ाया जा सकता है जो निहित / स्पष्ट विध्वंसक का समर्थन करता है

#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;
}

डिफ़ॉल्ट असाइनमेंट ऑपरेटर एक उथली प्रति करता है। इसलिए प्राप्त वस्तु अभी भी सूचक का मालिक है और कोई भी परिवर्तन मूल वस्तु को प्रभावित करता है;


1
हाँ, कार्यक्रम में newएक भी बिना delete। हालाँकि, इस कार्य के लिए मुझे काफी अच्छा लगता है :)
रुस्लान

आउटपुट क्या हैं?
निकोलस बारबुल्स्को

1
जो मैं समझता हूं (सी ++ दूर है ...), यहां असाइनमेंट राज्य को नहीं बदलता है । अन्यथा, coutलाइन को आगे बढ़ाएं }और बताएं कि क्या काम करता है। :-)
निकोलस बारबुल्स्को

4

स्काला

सामान्य स्थानीय चर को निर्दिष्ट करते समय निहित रूपांतरण आपको इसे पूरा करने देते हैं:

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)

आप अनुमान लगा सकते हैं कि निम्न प्रकार भी हैं:

var s = ""
s = obj

आप एक कस्टम सेटर विधि का भी उपयोग कर सकते हैं, हालाँकि इसके लिए L- मान की आवश्यकता होती है:

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)

3

डी

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

आउटपुट:

Obj(0)
Obj(1)

3

माणिक

जैसा कि वादा किया गया था, यहां इसका जवाब है जिसने प्रश्न को प्रेरित किया।

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एक अनाम वर्ग बनाता है। to_sएक अनाम वर्ग पर कॉल करने से वस्तुओं का डिफ़ॉल्ट स्ट्रिंग प्रतिनिधित्व मिलता है, जो दिखता है #<Class:0x007fe3b38ed958>। हालाँकि, एक बार जब कक्षा को एक नियत स्थान पर सौंपा to_sजाता है , तो वह स्थिर हो जाता है। रूबी में, एक स्थिरांक एक चर है जो एक बड़े अक्षर से शुरू होता है, इसलिए objयह उस वर्ग का संदर्भ है जो इसे गुमनाम रहने की अनुमति देता है।

मेरा कोड to_sएक stateविधि में लपेटता है , इसलिए आउटपुट बन जाता है

Has not been assigned
Assigned to LValue

यहां अधिकांश समाधानों के विपरीत, यह केवल एक बार काम करता है: objकिसी अन्य स्थिरांक को असाइन करने से इसका स्ट्रिंग प्रतिनिधित्व नहीं बदलेगा, और न ही इसके लिए एक नया मान असाइन किया जाएगा LValue


3

जावा में

मुझे लगा कि जावा में यह असंभव था। परंतु…

मुख्य वर्ग:

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
  }

}

कक्षा बिल्ली:

public class Cat {

  static Cat bestCat;

  public Cat() {
    super();
  }

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

}

मैं @tbodt से प्रेरित रहा हूं।


1
मुझे पता है कि यह कोड-गोल्फ नहीं है, लेकिन आपको लगता है कि आप सिर्फ कंस्ट्रक्टर को हटा सकते हैं और यह अभी भी वही है, है ना?
डेविड कॉनरेड

2
यह "एक ऐसी वस्तु नहीं है जिसकी स्थिति असाइनमेंट पर बदलती है"। यह आप एक वैश्विक मूल्य में हेरफेर कर रहे हैं और फिर उसके आधार पर कुछ प्रिंट कर रहे हैं। यह Cat.x = 2मुद्रण से अलग नहीं है Cat.x
क्रिस हेस

@ क्रिस - वस्तु राज्य एक "वैश्विक मूल्य" पर आधारित है। तो वस्तु स्थिति असाइनमेंट पर बदल जाती है। प्रश्न में कहा गया है ;-) कि राज्य एक नियतात्मक, idempotent विधि हो सकती है। मेरी विधि अवस्था () एक ऐसी विधि है।
निकोलस बारबुल्स्को

नहीं, ऑब्जेक्ट स्थिति इस विशेष असाइनमेंट पर बदलती है । अगर मैं Cat otherCat = tomकरता तो राज्य बिल्कुल नहीं बदलता। मुझे विश्वास है कि यह नियमों के पत्र या भावना से मिलता है।
क्रिस हेयस

@ क्रिस - बेशक इस असाइनमेंट पर ऑब्जेक्ट बदलता है! प्रश्न उस वस्तु के लिए पूछता है जिसकी स्थिति असाइनमेंट द्वारा बदल दी जाती है। ऐसी वस्तु के लिए नहीं, जिसकी स्थिति किसी भी कार्य द्वारा बदल दी जाए।
निकोलस बारबुल्स्को

3

सी ++

यह व्यवहार वास्तव में मानक में निर्दिष्ट है (और यही कारण है कि इसे पदावनत किया गया था)।

#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';
}

उत्पादन

some address
0

इसके कारण जो प्रक्रिया होती है वह अभिजीत के उत्तर के समान होती है लेकिन बिना आवश्यकता के std::move और उसी तरह का है जैसा कि मारिनस का उत्तर है लेकिन स्वयं को परिभाषित करने के बजाय एक मानक वर्ग का उपयोग करना।

संपादित करें: मैं कुछ स्पष्टीकरण जोड़ रहा हूं। आउटपुट में, "कुछ पता" वास्तव में आवंटित पूर्णांक के पते के लिए एक हेक्स मान होगा। std::auto_ptrजब अपने स्टोर पॉइंटर को किसी दूसरे को सौंपा जाए और auto_ptrइसके इंटरनल पॉइंटर को 0. पर सेट किया जाए, तो कॉलिंग get()स्टोर पॉइंटर तक पहुंच को फिर से प्राप्त करता है।


मुझे संदेह है कि यहां "आउटपुट" वास्तविक आउटपुट नहीं है।
निकोलस बारबुल्स्को

क्या आप बता सकते हैं कि यह क्या करना चाहिए? विशेष रूप से विधि get()? यह अंत में 0 क्यों लौटेगा?
निकोलस बारबुल्स्को

@ निकोलस येप। यह आउटपुट सही आउटपुट नहीं है, लेकिन एक अधिक सामान्य आउटपुट (मेरे पास एक कंपाइलर तक पहुंच नहीं है, इसलिए मेरे पास उस समय मान्य पते का उदाहरण नहीं था)।
जोकर

1
हम्म, यह जीसीसी पर संकलन करने में विफल रहता है 4.8।
माइकल हैम्पटन

1
मैंने संकलन त्रुटियों को ठीक किया। यदि आप c ++ 11 के लिए संकलन कर रहे हैं तो अभी भी चेतावनी है क्योंकि auto_ptrपदावनत किया गया है।
JKor


2

अजगर 2.x

मैं एक अतिरिक्त वर्ग को परिभाषित किए बिना ऐसा करने का उचित तरीका नहीं खोज सका।

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

2

जावा

अन्य सभी समाधान अपनी भाषा के ऑपरेटर के ओवरलोडिंग के रूप का उपयोग करते हैं। जावा में ऑपरेटर ओवरलोडिंग नहीं है, इसलिए मुझे लगा कि मैं फंस गया हूं। लेकिन मैं कुछ लेकर आया था।

यहाँ मुख्य वर्ग है:

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

कुछ संदिग्ध रेखाएँ हैं, लेकिन अगर Thingकक्षा पूरी तरह से सामान्य होती तो वे कुछ भी नहीं करते । यह नहीं है:

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 {
        Thread t = new Thread() {
            public void run() {
                Thing t = otherThing;
                while (true)
                    if (t != otherThing) {
                        t = otherThing;
                        t.state++;
                    }
            }
        };
        t.setDaemon(true);
        t.start();
    }
}

यह थ्रेड्स के कारण काम करने की गारंटी नहीं है, लेकिन मैंने इसे JDK 1.8u5 पर परीक्षण किया, और यह वहां काम करता है।



@KyleKanos को सभी यूनिकोड वर्ण> U + 00FF से छुटकारा मिला
tbodt

1

आम लिस्प

मैं एक वेक्टर से बंधित विशेष चर की संख्या के रूप में राज्य को परिभाषित करता हूं। तो, एक विशेष चर के लिए असाइनमेंट राज्य को बदलता है।

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

आउटपुट:

1 
2 
2 
3 

यह केवल विशेष चर के काम के साथ काम करता है, न कि शाब्दिक चर के लिए, न ही किसी वस्तु के भीतर स्लॉट के लिए।

उससे सावधान रहें do-all-symbolsसभी पैकेजों में दिखने वाले , इसलिए यह उन चर को याद करता है जिनके पास कोई पैकेज नहीं है। यह एक से अधिक पैकेज में मौजूद (जब एक पैकेज दूसरे पैकेज से प्रतीक को आयात करता है) डबल-काउंट प्रतीक हो सकता है।

माणिक

रूबी लगभग समान है, लेकिन मैं राज्य को परिभाषित करता हूं कि एक सरणी का संदर्भ देने वाले स्थिरांक की संख्या।

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

आउटपुट:

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

यह रूबी वस्तुओं के लिए हिस्टोक्रेट के उत्तर का एक सामान्यीकरण है जो वर्ग या मॉड्यूल नहीं हैं। चेतावनी दिखाई देती है क्योंकि कॉन्‍फ़िगरेशन लगातार कुछ कोड को कॉन्फ़िगर करता है जिससे चेतावनी बनती है।


0

सी ++

परिणाम विभिन्न प्लेटफार्मों में भिन्न हो सकते हैं। आइडोन पर परीक्षण किया गया

#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;
}

आउटपुट:

1234
13010

0

सी#

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

आउटपुट:

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

यह क्या करता है? क्या यह ऑपरेटर को ओवरलोड कर रहा है =?
निकोलस बारबुल्स्को

@ निकोलस बिल्कुल नहीं। यह जब एक से कास्टिंग है Bएक करने के लिए Aक्योंकि, implicit operator A(B b)दुष्प्रभाव है।
क्लिक करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.