0

A value type is one whose instances are themselves saved in variables. A reference type is a type whose instances are saved somewhere and variables only hold the addresses of the instances.

Some languages, such as Java, have both types. For example String is a reference type and int is a value type.

public static void main(String[] args) {
    int i; // allocates 4 bytes on the stack, to store an actual integer value
    String s; // allocates 8 bytes on the stack (on 64 bit systems) to store an address
}

This is possible in statically typed languages, because the type of i isn't going to change; so after allocating 4 bytes for it, we can put in it any integer value.

However, what if the type of i were dynamic? For example in Python, the following is possible:

def demonstrate():
    i = 20
    name = 'george'
    if input() == 'Make a string':
        i = 'hello'
    print('i is ' + i)

All Python types are reference types. However suppose Python's int were a value type (and str still a reference type), and as a result we would try to actually put the number 20 inside i. In the stack after i, we would place an 8 byte reference to 'george'.

After that, we might want to change the value of i to 'hello'. This means reallocating room for it in the stack, instead of the room we previously allocated for the number 20.

My question is: is this possible (or practical)? Are there dynamic languages which support value types? If so, how?

closed as too broad by gnat, Mason Wheeler, durron597, user22815, GlenH7 Sep 25 '15 at 17:21

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    recommended reading: Why is “Is it possible to…” a poorly worded question? – gnat Sep 24 '15 at 20:54
  • Look up the space allocation for a union in C. Values in Python (and perl) are not simple memory locations. – user40980 Sep 24 '15 at 20:59
  • 1
  • 2
    Well, obviously it's possible, the implementer would just use a value instead of a pointer to a value. You have to track the type of each variable anyway, so toggling between a value type and a reference type is no different from toggling between two reference types. That's really it. – Ixrec Sep 24 '15 at 21:07
3

Yes, it’s possible, and in fact it’s common to “unbox” values of common types for performance reasons, usually with some form of “tagging” to indicate whether a value is boxed or unboxed.

The simplest possible representation is with one word for the type tag, and one word for the value or pointer, according to the tag.

enum Type { INTEGER, REFERENCE };

struct Value {
  Type type;
  union {
    uint64_t as_integer;
    Object *as_reference;
  } data;
};

But we can do better. For example, heap allocations in many systems are aligned to 8-byte boundaries, which means that the bottom 3 bits of any pointer ((uintptr_t)p & 7) are guaranteed to be 0. As such, we can use these bits to store the tag, and thus get unboxed representations of common types with only one word. Here’s one simple such design, for a 32-bit system:

(x & 7) == 0 => (x & ~7) is a pointer
(x & 7) == 1 => (x >> 3) is an integer

(This representation is used by OCaml, a statically typed language, to determine which values are references that need to be traced by the garbage collector.)

We could add up to 6 additional representations to this, for booleans and other common types we might wish to unbox, and a further 8 if we had a memory allocator that guaranteed 16-byte alignment.

In pointer magic for efficient dynamic value representations, Nikita Popov describes a system for embedding integers, booleans, and floating-point numbers in a single 64-bit word by making assumptions about the representation of floats (IEEE-754) and address spaces. A similar representation was used in Mozilla’s JägerMonkey JavaScript engine.

  • 1
    YARV (the most widely-used Ruby implementation) has Fixnums (Integers that fit into n-1 bit on an n-bit architecture) and flonums (Floats that fit into 62 bit on a 64-bit architecture) as immediate value types. – Jörg W Mittag Sep 24 '15 at 22:05
0

All Python types are reference types.

That is wrong. (Well, kind of.)

However suppose Python's int were a value type

No need to suppose. It is a value type. (Well, kind of.)

To be precise, you can't tell whether it's a value type or a reference type. In Python, ints are immutable, and for immutable types it is impossible to tell whether they are value types or reference types, so ints might be either and you wouldn't know the difference. They are, however, implemented as value types in all Python implementations I know of, and the language in the Python doc/spec strongly suggests implementing them as value types.

  • What do you mean by value type? – Winston Ewert Sep 25 '15 at 3:05
  • It is not impossible to tell whether it's a value type, and indeed it isn't a value type in CPython. An int has a persistent identity accessible via id(). Check the id throughout various transformations and you'll see that e.g. assignment and parameter passing keeps the same id and something like n + 1 - 1 will (for sufficiently large n that aren't interned) produce a separate object with a different id (i.e., the id is a real identity, rather than representing the integer's value). – user7043 Sep 25 '15 at 6:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.