Immutable Strings

Revision as of 09:07, 17 April 2007 by Paulb (Talk | contribs) (EMCA STRING_8 and STRING_32)

Author: Paul Bates


On the heals of a point raised on eiffelroom regarding read-only variants of an Eiffel STRING, this page has come about to discuss the possible options for introducing such new types.

The term read-only is not a fitting name so this page documents such string variants as being immutable with it's already implemented cousins STRING_8 and STRING_32 coined mutable.


There are a number of reason why Eiffel needs an immutable representation of a string, which no matter what should be able to be altered. This leads to the first rationale. A constant is a constant. The moment a constant changes it's has introduced


Section 8.29 of the Eiffel ECMA specification details the declaration and use of constants in Eiffel. To be padantic about the matter I extracted a dictional reference for the the word constant.

con·stant /ˈkɒnstənt/

    1. Not changing or varying; uniform; regular; invariable.

    7. Something that does not or cannot change or vary.

ECMA details the use of STRINGs as constants but in reality this is contracting to the definition and misleading in true semantics. STRINGs are mutable, "constant" or not. As a simple case example, take the following code snippet.

full_path: STRING_8
    Result := template_path
    Result.replace_sub_string_all ("$1", root_path)
    result_attached: Result /= Void
    not_result_is_empty: not Result.is_empty
template_path: STRING_8 = "$1\data\default.cfg"

The code demonstrates an all too common scenario. Once full_path has been called the contents of template_path are modified. Any other use of template path will yield a "constant" value that differs from that declared. The EMCA specification indicates that declaration of template_path pertains to the specification of a constant attribute (8.29.2 and 8.29.3.)

full_path, with once function semantics, is never a constant but is evaluated on a single as-needed basis. full_path actually demonstrates yet another rationale for introducing immutable strings into Eiffel.

A second rationale is through good design of a class' exported interface. A good design will yield immutable exported members as not to seemingly violate such principles of object orientation. I note "seemly" violated because by technical reference such principles are not violated. The principle in reference is one that states - a class, and it's descendants, should be the only entities to modify a respective runtime instantiation internal state. No client should be permitted to perform such modifications - Technically STRING is a reference type so a qualified call, like append, made on a STRING object, is modifying the internal state of that STRING object. However STRING has special reverence that binds it with the likes of INTEGER, NATURAL and CHARACTER. It's an inbuilt rudimentary type that is seen to be "a value". Almost all other reference types are just objects and runtime with no real discernible value.

feature -- Access
  selected_indexes: BILINEAR [NATURAL]
      -- Select item indexes
      Result := internal_selected_indexes.twin
      result_attached: Result /= Void
feature {NONE} -- Implementation
  internal_selected_indexes: ARRAYED_LIST [NATURAL]
      -- Mutable version of `internal_selected_indexes'

selected_indexes permits clients to access a list of index positions but never to extend of remove items from that structure. internal_selected_indexes is used internally to add or extend items based on some peripheral interaction.

As it stands today, with only mutable strings, this is not possible. A class attribute is open for modification by an unruly client.