Advertisement

Handles

Started by November 05, 2024 05:03 PM
10 comments, last by WitchLord 7 hours, 3 minutes ago

My thinking is a bit warped by C# and I don't quite understand why AS needs handles.

In C# there are also two categories of types: reference types (classes) and value types (structs and int, float, etc).

And C# does just fine without handles: obj1 = obj2 is always a copy of a reference if the type is class or a copy of a value if the type is a value.

Why it's need to write @obj = @obj2 in AS if user almost always want to copy a reference? Even in C++ ptr1 = ptr2 - is a pointer copy, not the object.

Image@ img = Image(src_image_path);
@img = img.expand(img_border_size);

In C#:

class Image // reference type
{
   public Image() {} // contructor
}

Image img1 = new Image();
Image img2 = img1; // img1 and img2 contains pointer to the same object

struct Point // value type
{
    public int x;
    public int y;
    
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

Point p1 = new Point(10, 20);
Point p2 = p1; // copy
Advertisement

I never programmed AS, but at first glance it looks to me asif the author decided that pointers are special and values are normal. Depending on where you're coming from, making an explicit difference between the two can make sense.

Eg if your previous experience is BASIC, the entire reference notion is unknown, so annotating references explicitly helps.

I don't know if you can do this in AS, but as the notation makes pointers explicit, “A = B” is different from “@A = @B”. You cannot do this in C# in this way, and need a “strange” notation like “A = B.clone()” or something like that. If you're not used to C#, that may look weird too. In other words, you can argue that C# is weird just as easily as you can for AS or any other language when you compare them.

That holds for all languages. Different people with different backgrounds experience a language differently. Not everybody has a C# background, what's natural to you may not be natural to someone else and vice versa.

In any case, I am not sure what you're trying to say. The language is what it is. It's not C# because its ideas are different. That holds for all languages. They are all unique.

Changing the meaning of eg “@A” is not an option either. There are a zillion lines of code written in the language. If you ever change something like the meaning of “A” or “@A”, all those zillion lines of code immediately die. Users will be angry, and that's something you want to avoid as language author.

>The language is what it is. It's not C# because its ideas are different. That holds for all languages. They are all unique.

I can't speak for everyone, just for myself. Personally, I like AS because it's LIKE C++/C#, not because it's "different". If I needed a "different" language, I'd choose LUA or Python.

> You cannot do this in C# in this way, and need a “strange” notation like “A = B.clone()”

This is the most clear and obvious way. Much more visual than *a = *b in C++.

Moreover, in this aspect AS does the opposite of C++:

In C++:

ptr1 = ptr2; // Copy ptr
*ptr1 = *ptr2; // Clone obj

In AS:

handle1 = handle2; // Clone obj
@handle1 = @handle2; // Copy handle

>There are a zillion lines of code written in the language.

You exaggerate. It's a good language, but few people know about it.

> Users will be angry, and that's something you want to avoid as language author.

I haven't used AS 1, but I think the current AS 2 is not compatible with it.

The ‘@’ operator is closer to the ‘&’ operator in C++ than the ‘*’ operator:

obj2 = obj1; // object copy
auto &ref1 = obj1; // creates reference to existing object.
auto ptr1 = &obj1; // creates pointer to existing object
ptr1 = &obj2; // assigns to exiting pointer
&ref1 = &obj2; // would assign to an existing reference, if &ref1 were an lvalue

Of course &ref1 is an rvalue in C++, so the last line above doesn't work.

Advertisement

Handler is definitely not a ref, there are already refs in AS. Moreover, if you consider Handler to be a reference, then this code will be very strange.

  object@ obj_h;
  {
    object obj;
    @obj_h = @obj;

    // The object would normally die when the block ends,
    // but the handle is still holding a reference to it
  }

  // The object still lives on in obj_h ...
  obj_h.Method();

Also object@ can be null

In fact, if considering the handler as a pointer, this code also looks strange. Because Object obj is also a pointer.

In c# this code will be

Object obj = null;
{
    Oject obj1 = new Object();
    obj = obj1;
}
obj.Method();

in C++

shared_ptr<Object> obj;
{
    shared_ptr<Object>obj1 = make_shared<Object>();
    obj = obj1;
}
obj->Method();

The reason for the handles in AngelScript is to allow interoperability with C++, as in C++ references and pointers are treated differently, even though they are represented the same way in memory. The handles in AngelScript are kind of a mashup of C++ references, pointers, and shared_ptr. 🙂

As for the syntax. Well, that was a decision made 20 years back. Maybe if I were to design the language today I would do it differently. But I'm not about to redesign the language at this point, as there is not enough reason for me to start working on AngelScript 3. The switch from AngelScript 1 to AngelScript 2 was only done when it became apparent that AngelScript 1 had some serious flaws that I couldn't fix without a complete redesign.

There is an engine property asEP_ALLOW_IMPLICIT_HANDLE_TYPES that you can turn on from the application. This changes the language behavior to be more like Java/C#, in that all reference types are implicitly treated as handles, and the assignment operator will be done by default as a handle assignment rather than a value assignment.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement