What is the non-synchronized equivalent to a protected type in Ada? - oop

Ada has a construct called "protected types", where you have a collection of variables and subprograms associated with a type, and the subprograms have implicit synchronization. These types can be instantiated and each instance will have its own memory where the variables live. This looks a lot like the class/object duality in mainstream OOP languages such as C++ and Java, minus inheritance, plus mandatory implicit synchronization.
Is there an equivalent to this construct, minus the synchronization? If not, what's the rationale behind this design choice?
To be entirely clear, I'm aware that Ada supports different styles of OOP without any kind of synchronization. My question is about the specific style of OOP I mentioned - as it is one of the most common styles found in mainstream languages, and is indeed also present in Ada in some form.
To further clarify the question, which had been intentionally (and misguidedly) left open-ended, I am aware that the answer is "packages". But then, consider the following:
We have packages, which are units containing variables and subprograms, of which several instances can be created
We have types, which are enums or projections/mod of built-it types (I know this is a very approximate definition, specifics don't really matter here)
We have protected types, which are... units containing variables and subprograms, of which several instances can be created. Plus, they have synchronization.
This begs the thought: why "protected types" and not "protected packages"? This thought is the origin of the present question.

OOP is a set of concepts in programming without any dependence in a particular syntax. According to the Ada 95 Rationale: "Type extension in Ada 95 builds upon the existing Ada 83 concept of a derived type. In Ada 83, a derived type inherited the operations of its parent and could add new operations; however, it was not possible to add new components to the type. The whole mechanism was thus somewhat static. By contrast, in Ada 95 a derived type can also be extended to add new components."
In Ada a type is a type, independently of it providing OOP features or not. Ada 95 provided extension on top of other POO features already provided by Ada 83 types. The advantage of that is that you can turn easily a non-tagged type to a tagged type, if you later need type-extension, without affecting current uses of the type. This also avoids introducing hidden features in the OOP syntax, like friend classes (types sharing the package), static members (global package variables), the implicit this, or const at the end of a method to indicate that this object is not modified, etc.
Why protected types do not follow this pattern? They probably follow that of Ada 83 task types, but the latter don't have a private part, so it is still inconsistent. The design probably chose syntax of task types as inspiration, but added private part for efficiency (that was the main concern: "protected types allows a more efficient implementation of standard problems of shared data access").

So this is an answer to the title of this question:
"What is the non-synchronized equivalent to a protected type in Ada?"
I'm adding this mainly for people searching this question looking for the answer to the topic's title question.
Take a simple example protected type:
protected type My_Type is
procedure Set_Value(Value : Integer);
function Get_Value return Integer;
private
The_Value : Integer := 0;
end My_Type;
protected body My_Type is
procedure Set_Value(Value : Integer) is
begin
The_Value := Value;
end Set_Value;
function Get_Value return Integer is
begin
return The_Value;
end Get_Value;
end My_Type;
The equivalent non synchronized version would be to use a record type (or a tagged record if you want type extension) within a package paired with the operations on that type:
package My_Types is
-- For type extension use:
-- type My_Type is tagged private;
type My_Type is private;
procedure Set_Value(Self : in out My_Type; Value : Integer);
function Get_Value(Self : My_Type) return Integer;
private
-- For type extension use:
-- type My_Type is tagged record
type My_Type is record
The_Value : Integer := 0;
end record;
end My_Types;
package body My_Types is
procedure Set_Value(Self : in out My_Type; Value : Integer) is
begin
Self.The_Value := Value;
end Set_Value;
function Get_Value(Self : My_Type) return Integer is
begin
return Self.The_Value;
end Get_Value;
-- Alternate syntax:
-- function Get_Value(Self : My_Type) return Integer is (Self.The_Value);
end My_Types;
Operations declared within a package that operate on a type in the package before that type is frozen are "associated" to that type (Ada calls them primitive operations). This includes functions that return those types.
For the "why" each layout was chosen differently, I don't really know. It might be helpful to take a look at the bottom of the following page and look through all the comments/emails/discussions of the ARG (credit to Simon Wright for the initial link):
http://archive.adaic.com/standards/ada95.html
If I had to guess without fully reading those sections Simon pointed me to (I will get to reading them all the way through), I would wager it has to do with the fact that records existed as is before protected types existed and protected types were thought more of an extension of the tasking model, so they iterated on the task type layout for protected type. Some of what I did read(here and here) already led me to believe they ran into some existing issues (either technical or philosophical) trying to layout protected types more like records.
Note that protected types do not give the full set of "information hiding" capabilities as most programmers expect, such as public vs private member variables (only private for protected types).
Credit to Simon Wright for the links I provided

The standard way to define a complete type (data + operations) is Ada is with a package containing the type declaration (often private) and the subprograms for the type.
In general, encapsulation and information hiding (package) are orthogonal to types and subprograms in Ada. In many commonly used languages, encapsulation and information hiding are provided only by the class construct.

This is a bit of a ramble round the topic ...
If you had a protected package, what parts of its contents would be synchronised? Any variable, spec or body? any type? child packages? And, to be able to create multiple instances of the package, it’d have to be generic. How then could you create an instance within a record? I think it needs to be a type.
As I understand it, there’s not really a parallel to package in C++, so you’d have to say protected class Foo ... which seems hard to distinguish from a protected type.
Given packages, which already encapsulate everything else, I guess the design team could have gone with something like
type P is record
...
end record;
pragma Protected (P);
where primitive operations of P would be synchronised, but you then have the problem of clarity (primitiveness being easy to get wrong) and of visibility (you really don’t want any of the components of P being accessible from outside). What syntax do we use for entry operations? Protected types seem a reasonable compromise.

Is there an equivalent to this construct, minus the synchronization?
If not, what's the rationale behind this design choice?
Ok, the other answers are really quite good, but here's the simple answer:
Ada defines a “type” as a set of values and a set of operations on those values; the notion of “subtype” is likewise defined as a type with an additional (possibly null) set of constraints on its values. — This leads to the ability to say “Subtype Natural is Integer 0..Integer'Last;” — In Ada 83 there was no way to add values to a type, but there was type-derivation where you could 'inherit' a type, possibly adding other operations and/or altering representational items. (Thus you could have “Type Native_Data is array(1..10, 1..200) of Integer;” and “Type External_Data is new Native_Data;” with "For External_Data'Convention use Fortran;"1 and convert between native and external formats via conversion: Data:= Native_Data( From_Disk(File => "Import.dat") ).)
So, Ada95 built atop type-derivation allowing more values which are the type-extension (as well as the more operations). — Ada95 also extended the library/compilation-units structure from a 'flat' notion to a hierarchical one, but the basic unit of organization was (and is still) the package.
Now, we get to protected types, protected types are synchronization types, the data encapsulated into the construct and manipulated via accessors and mutators — this construct is pretty much the bastard child of packages and tasks: it is structured reminiscent of the package and has the queue-like access (entries, functions. procedures) of tasks, albeit a bit more 'exposed'/explicit than the implicit nature of task entries and the rendezvous.
So then, what is a protected type without synchronization?
Simple, a regular type.
This begs the thought: why "protected types" and not "protected
packages"?
While I'm sure that the above provides enough information for you to suss things out, the simple answer is this:
Packages are really interfaces (in the general notion, not the keyword/tagged-type notion) and namespaces: they declare the public view and also segregate the private implementation, as well as encapsulating the scope of the things within.
Thus a “Protected Package” would essentially be the protected type "but with namespacing" — and thus be a really redundant construct, not to mention that one of the motivating factors for protected types was the ability to drop the active thread of control required from tasks for synchronization: all that can be handled by the compiler inserting the proper queuing/bookkeeping around accesses without any of the complexity (and timing/scheduling impositions) that a task would require — so there would have to be special rules for a "protected package" either disallowing Task or requiring some special form, which would add complexity to the compiler.
1 — Fortran uses column-major ordering for its multidimensional arrays, Ada uses row-major ordering [I don't recall if this is required by the LRM]; this 'trick' allows you to have the compiler handle the "trans-positioning", as well as using the type-system to keep track of which is which. (You can use this with things like network-format vs native-format in protocols, too.)

Related

What are the pros and cons of typing interface method parameters generic to make the interface more accessible?

I have an application that creates xml strings from abap structures using many different simple transformations and consequently many different abap structures.
I want to use a more flexible OO approach with an Interface to do this but due to the different structures the method signatures importing parameter is always different.
What are the pros and cons of typing the importing parameter generic instead so I can implement one method from one interface in each class handling the different transformations?
INTERFACE if_transformer.
METHODS transform_xml
IMPORTING isource_structure TYPE REF TO data
RETURNING VALUE(rxml_string) TYPE string.
ENDINTERFACE.
...
CLASS material_transformer definition.
PUBLIC SECTION.
INTERFACES if_transformer.
ENDCLASS.
CLASS material_transformer IMPLEMENTATION.
METHOD if_transformer~transform_xml.
FIELD-SYMBOLS <structure> TYPE concrete_structure.
ASSIGN isource_structure->* TO <structure>.
...
ENDMETHOD.
ENDCLASS.
The more specific your types, the earlier you notice errors, the easier your interfaces can be understood, and the less overhead you have in validating and casting/converting to the concrete types you want to handle.
For example, consider you type the method add_number as methods add_number importing n type i. The compiler will then reject the wrong statement add_number( 'xyz' ) and this class of errors will never make it into executable code. In turn, anybody reading that method's declaration can easily see that the method accepts only integer numbers, not floats, not packeds, and definitely not strings that contain numbers. Within the method, you can probably directly take the input n and do something with it, such as result = sum_so_far + n, without having to first validate the input or convert it to something else.
In contrast, consider you type the same method add_number as methods add_number importing n type ref to data. The compiler will gladly accept add_number( ref #( 'xyz' ) ), although it is complete nonsense; this class of error will thus only be detected at runtime, with type conversion exceptions that the code around this will have to react to in a meaningful way. People reading the method's declaration have to consult its docu, unit tests, and/or code to find out what kind of input it accepts; there is no way to guess it from the specification alone. Finally, within the method, you will first have to validate and convert the input before you can process it, such as is_integer( n ), cast, assign, and the like; in case the input is unacceptable, you need to find suitable error handling mechanisms, such as throwing nice exceptions.
With softly typed languages like JavaScript, using generic types is the default. However, history shows that people often prefer stronger typing, at least on the server side, leading to follow-up evolutions such as TypeScript or Deno. With strongly-typed languages like ABAP, the rule of thumb is to choose a data type as precise as possible.
Note that there are several levels of relaxation in generic types. For example, you should consider resorting to "partially" generic types like simple, which accepts ABAP structures, or standard table, which accepts tables, before resorting to the maximum-generic type data.
Excellent answer by Florian. I might add that an approach I've used in similar scenarios is to use a factory class that inspects the input data and instantiates the appropriate class to deal with it.

Overloading with different interface procedures in Fortran

Say you have two subroutines which have different interfaces and you have two types where each corresponds to one of the procedures.
type, abstract :: base
contains
procedure :: pointer_to_routine
end type base
type, extends(base) :: first_case
contains
procedure :: pointer_to_routine => first_case_routine
end type first_case
type, extends(base) :: second_case
contains
procedure :: pointer_to_routine => first_sec_routine
end type second_case
So this is not valid Fortran code, but it is kind of the idea I want to do. If the routines had similar interfaces I could define an abstract interface and deferred attribute in the base declared type.
But since my two routines have different interfaces, I am not sure how this can work out.
Essentially, one routine needs more inputs than another, so one solution would be to add the remaining inputs as just dummy inputs, although, this could potentially cause a bit confusion, And I am wondering if there is a more convenient solution.
All solutions you can invent for this will be workarounds. The language is simply designed that way that all procedures with the same binding name as in the parent type should have the same interface. Note that other languages have similar problems/features Override method with different signature.
You can use dummy arguments if you know they will be needed in general but not in a specific case. They can be optional arguments. You can also make the input arguments contained in a polymorphic derived type.That will bring new issues though.

What is the antonym of encapsulation?

Using online dictionary tools doesn't really help. I think the way encapsulate is use in computer science doesn't exactly match its meaning in plain English.
What is the antonym of computer science's version of encaspulate? More specifically, what is an antonym for encapsulate that would work as a function name.
Why should I care? Here's my motivation:
// A class with a private member variable;
class Private
{
public:
// Test will be able to access Private's private members;
class Test;
private:
int i;
}
// Make Test exactly like Private
class Private::Test : public Private
{
public:
// Make Private's copy of i available publicly in Test
using Private::i;
};
// A convenience function to quickly break encapsulation on a class to be tested.
// I don't have good name for what it does
Private::Test& foo( Private& p )
{ return *reinterpret_cast<Private::Test*>(&p); } // power cast
void unit_test()
{
Private p;
// using the function quickly grab access to p's internals.
// obviously it would be evil to use this anywhere except in unit tests.
assert( foo(p).i == 42 );
}
The antonym is "C".
Ok, just kidding. (Sort of.)
The best terms I can come up with are "expose" and "violate".
The purpose behind encapsulation is to hide/cover/protect. The antonym would be reveal/expose/make public.
How about Decapsulation..
Though it aint a computer science term, but in medical science, Surgical removal of a capsule or enveloping membrane.. Check out here..
"Removing/Breaking encapsulation" is about the closest thing I've seen, honestly.
If you think of the word in the English sense, to encapsulate means to enclose within something. But in the CS sense, there's this concept of protection levels and it looks like you want to imply circumventing the access levels as well, so something like "extraction" doesn't really convey the meaning you're looking for.
But if you just think of it in terms of what the access levels are, it looks like you're making something public so, how about "publicizing"?
This is not such a simple question - Scott Meyers had an interesting article to demonstrate some of the nuances around encapsulation here.
I'll start with the punchline: If
you're writing a function that can be
implemented as either a member or as a
non-friend non-member, you should
prefer to implement it as a non-member
function. That decision increases
class encapsulation. When you think
encapsulation, you should think
non-member functions.
How about "Bad Idea"?
The true antonym of "Encapsulation" is "Global State".
The general opposite of encapsulation is coupling and we often talk about systems that are tightly coupled or loosely coupled.
The reason you'd want components to be encapsulated is because it makes it easier to reason about how they work.
Take the analogy of trains: the consequence of coupling the railcars is that the driver must consider the characteristics (inertia, length) of the entire train.
Obviously, though, we couple systems because we need them to work together.
Inverted encapsulation and data structures
There's another term that I've been digging for, which is how I came across this question, that refers to a non-standard style of data structures.
The standard style of encapsulation is exemplified by Java's LinkedList; the actual nodes of the list are designed to be inaccessible to the consumer. The theory is that this is an implementation detail and can change to improve performance, while existing code will continue to run.
Another style is the classic functional cons-list. This is a singly linked list, and the idea is that it's so simple that there's nothing to improve about the data structure, e.g.
data [a] = [] | a : [a] deriving (Eq, Ord)
-- Haskellers then work directly with the list
-- There's nothing to hide because it's so simple
typicalHaskell :: [a] -> b
typicalHaskell [] = emptyValue
typicalHaskell h : t = h `doAThing` (typicalHaskell t)
That's the definition from Haskell's standard prelude though the report notes that isn't valid Haskell syntax, and in practice [a] is defined in the guts of the compiler.
Then there's what I'm calling an "inverted" data structure, but I'm still looking for the correct term. This is, I think, really the opposite of encapsulation.
A good example of this is Python's heapq module. The data structure here is a binary heap, but there isn't a Heap class. Rather, you get a collection of functions that operate on generic Python lists and you're responsible for using those methods correctly to ensure the heap invariants are maintained.
How about "spaghetti"?

What is the difference between the concept of 'class' and 'type'?

i know this question has been already asked, but i didnt get it quite right, i would like to know, which is the base one, class or the type. I have few questions, please clear those for me,
Is type the base of a programing data type?
type is hard coded into the language itself. Class is something we can define ourselves?
What is untyped languages, please give some examples
type is not something that fall in to the oop concepts, I mean it is not restricted to oop world
Please clear this for me, thanks.
I didn't work with many languages. Maybe, my questions are correct in terms of : Java, C#, Objective-C
1/ I think type is actually data type in some way people talk about it.
2/ No. Both type and class we can define it. An object of Class A has type A. For example if we define String s = "123"; then s has a type String, belong to class String. But the vice versa is not correct.
For example:
class B {}
class A extends B {}
B b = new A();
then you can say b has type B and belong to both class A and B. But b doesn't have type A.
3/ untyped language is a language that allows you to change the type of the variable, like in javascript.
var s = "123"; // type string
s = 123; // then type integer
4/ I don't know much but I think it is not restricted to oop. It can be procedural programming as well
It may well depend on the language. I treat types and classes as the same thing in OO, only making a distinction between class (the definition of a family of objects) and instance (or object), specific concrete occurrences of a class.
I come originally from a C world where there was no real difference between language-defined types like int and types that you made yourself with typedef or struct.
Likewise, in C++, there's little difference (probably none) between std::string and any class you put together yourself, other than the fact that std::string will almost certainly be bug-free by now. The same isn't always necessary in our own code :-)
I've heard people suggest that types are classes without methods but I don't believe that distinction (again because of my C/C++ background).
There is a fundamental difference in some languages between integral (in the sense of integrated rather than integer) types and class types. Classes can be extended but int and float (examples for C++) cannot.
In OOP languages, a class specifies the definition of an object. In many cases, that object can serve as a type for things like parameter matching in a function.
So, for an example, when you define a function, you specify the type of data that should be passed to the function and the type of data that is returned:
int AddOne(int value) { return value+1; } uses int types for the return value and the parameter being passed in.
In languages that have both, the concepts of type and class/object can almost become interchangeable. However, there are many languages that do not have both. For instance, I believe that standard C has no support for custom-defined objects, but it certainly does still have types. On the otherhand, both PHP and Javascript are examples of languages where type is very loosely defined (basically, types are either single item, collection/array/object, or undefined [js only]), but they have full support for classes/objects.
Another key difference: you can have methods and custom-functions associated with a class/object, but not with a standard data-type.
Hopefully that clarified some. To answer your specific questions:
In some ways, type could be considered a base concept of programming, yes.
Yes, with the exception that classes can be treated as types in functions, as in the example above.
An untyped language is one that lets you use any type of variable interchangeably. Meaning that you can handle a string with the same code that handles an int, for instance. In practice most 'untyped' languages actually implement a concept called duck-typing, so named because they say that 'if it acts like a duck, it should be treated like a duck' and attempt to use any variable as the type that makes sense for the code encountered. Again, php and javascript are two languages which do this.
Very true, type is applicable outside of the OOP world.

Non-nullable reference types

I'm designing a language, and I'm wondering if it's reasonable to make reference types non-nullable by default, and use "?" for nullable value and reference types. Are there any problems with this? What would you do about this:
class Foo {
Bar? b;
Bar b2;
Foo() {
b.DoSomething(); //valid, but will cause exception
b2.DoSomething(); //?
}
}
My current language design philosophy is that nullability should be something a programmer is forced to ask for, not given by default on reference types (in this, I agree with Tony Hoare - Google for his recent QCon talk).
On this specific example, with the unnullable b2, it wouldn't even pass static checks: Conservative analysis cannot guarantee that b2 isn't NULL, so the program is not semantically meaningful.
My ethos is simple enough. References are an indirection handle to some resource, which we can traverse to obtain access to that resource. Nullable references are either an indirection handle to a resource, or a notification that the resource is not available, and one is never sure up front which semantics are being used. This gives either a multitude of checks up front (Is it null? No? Yay!), or the inevitable NPE (or equivalent). Most programming resources are, these days, not massively resource constrained or bound to some finite underlying model - null references are, simplistically, one of...
Laziness: "I'll just bung a null in here". Which frankly, I don't have too much sympathy with
Confusion: "I don't know what to put in here yet". Typically also a legacy of older languages, where you had to declare your resource names before you knew what your resources were.
Errors: "It went wrong, here's a NULL". Better error reporting mechanisms are thus essential in a language
A hole: "I know I'll have something soon, give me a placeholder". This has more merit, and we can think of ways to combat this.
Of course, solving each of the cases that NULL current caters for with a better linguistic choice is no small feat, and may add more confusion that it helps. We can always go to immutable resources, so NULL in it's only useful states (error, and hole) isn't much real use. Imperative technqiues are here to stay though, and I'm frankly glad - this makes the search for better solutions in this space worthwhile.
Having reference types be non-nullable by default is the only reasonable choice. We are plagued by languages and runtimes that have screwed this up; you should do the Right Thing.
This feature was in Spec#. They defaulted to nullable references and used ! to indicate non-nullables. This was because they wanted backward compatibility.
In my dream language (of which I'd probably be the only user!) I'd make the same choice as you, non-nullable by default.
I would also make it illegal to use the . operator on a nullable reference (or anything else that would dereference it). How would you use them? You'd have to convert them to non-nullables first. How would you do this? By testing them for null.
In Java and C#, the if statement can only accept a bool test expression. I'd extend it to accept the name of a nullable reference variable:
if (myObj)
{
// in this scope, myObj is non-nullable, so can be used
}
This special syntax would be unsurprising to C/C++ programmers. I'd prefer a special syntax like this to make it clear that we are doing a check that modifies the type of the name myObj within the truth-branch.
I'd add a further bit of sugar:
if (SomeMethodReturningANullable() into anotherObj)
{
// anotherObj is non-nullable, so can be used
}
This just gives the name anotherObj to the result of the expression on the left of the into, so it can be used in the scope where it is valid.
I'd do the same kind of thing for the ?: operator.
string message = GetMessage() into m ? m : "No message available";
Note that string message is non-nullable, but so are the two possible results of the test above, so the assignment is value.
And then maybe a bit of sugar for the presumably common case of substituting a value for null:
string message = GetMessage() or "No message available";
Obviously or would only be validly applied to a nullable type on the left side, and a non-nullable on the right side.
(I'd also have a built-in notion of ownership for instance fields; the compiler would generate the IDisposable.Dispose method automatically, and the ~Destructor syntax would be used to augment Dispose, exactly as in C++/CLI.)
Spec# had another syntactic extension related to non-nullables, due to the problem of ensuring that non-nullables had been initialized correctly during construction:
class SpecSharpExampleClass
{
private string! _nonNullableExampleField;
public SpecSharpExampleClass(string s)
: _nonNullableExampleField(s)
{
}
}
In other words, you have to initialize fields in the same way as you'd call other constructors with base or this - unless of course you initialize them directly next to the field declaration.
Have a look at the Elvis operator proposal for Java 7. This does something similar, in that it encapsulates a null check and method dispatch in one operator, with a specified return value if the object is null. Hence:
String s = mayBeNull?.toString() ?: "null";
checks if the String s is null, and returns the string "null" if so, and the value of the string if not. Food for thought, perhaps.
A couple of examples of similar features in other languages:
boost::optional (C++)
Maybe (Haskell)
There's also Nullable<T> (from C#) but that is not such a good example because of the different treatment of reference vs. value types.
In your example you could add a conditional message send operator, e.g.
b?->DoSomething();
To send a message to b only if it is non-null.
Have the nullability be a configuration setting, enforceable in the authors source code. That way, you will allow people who like nullable objects by default enjoy them in their source code, while allowing those who would like all their objects be non-nullable by default have exactly that. Additionally, provide keywords or other facility to explicitly mark which of your declarations of objects and types can be nullable and which cannot, with something like nullable and not-nullable, to override the global defaults.
For instance
/// "translation unit 1"
#set nullable
{ /// Scope of default override, making all declarations within the scope nullable implicitly
Bar bar; /// Can be null
non-null Foo foo; /// Overriden, cannot be null
nullable FooBar foobar; /// Overriden, can be null, even without the scope definition above
}
/// Same style for opposite
/// ...
/// Top-bottom, until reset by scoped-setting or simply reset to another value
#set nullable;
/// Nullable types implicitly
#clear nullable;
/// Can also use '#set nullable = false' or '#set not-nullable = true'. Ugly, but human mind is a very original, mhm, thing.
Many people argue that giving everyone what they want is impossible, but if you are designing a new language, try new things. Tony Hoare introduced the concept of null in 1965 because he could not resist (his own words), and we are paying for it ever since (also, his own words, the man is regretful of it). Point is, smart, experienced people make mistakes that cost the rest of us, don't take anyones advice on this page as if it were the only truth, including mine. Evaluate and think about it.
I've read many many rants on how it's us poor inexperienced programmers who really don't understand where to really use null and where not, showing us patterns and antipatterns that are meant to prevent shooting ourselves in the foot. All the while, millions of still inexperienced programmers produce more code in languages that allow null. I may be inexperienced, but I know which of my objects don't benefit from being nullable.
Here we are, 13 years later, and C# did it.
And, yes, this is the biggest improvement in languages since Barbara and Stephen invented types in 1974.:
Programming With Abstract Data Types
Barbara Liskov
Massachusetts Institute of Technology
Project MAC
Cambridge, Massachusetts
Stephen Zilles
Cambridge Systems Group
IBM Systems Development Division
Cambridge, Massachusetts
Abstract
The motivation
behind the work in very-high-level languages is to ease the
programming task by providing the programmer with a language
containing primitives or abstractions suitable to his problem area.
The programmer is then able to spend his effort in the right place; he
concentrates on solving his problem, and the resulting program will be
more reliable as a result. Clearly, this is a worthwhile goal.
Unfortunately, it is very difficult for a designer to select in
advance all the abstractions which the users of his language might
need. If a language is to be used at all, it is likely to be used to
solve problems which its designer did not envision, and for which the
abstractions embedded in the language are not sufficient. This paper
presents an approach which allows the set of built-in abstractions to
be augmented when the need for a new data abstraction is discovered.
This approach to the handling of abstraction is an outgrowth of work
on designing a language for structured programming. Relevant aspects
of this language are described, and examples of the use and
definitions of abstractions are given.
I think null values are good: They are a clear indication that you did something wrong. If you fail to initialize a reference somewhere, you'll get an immediate notice.
The alternative would be that values are sometimes initialized to a default value. Logical errors are then a lot more difficult to detect, unless you put detection logic in those default values. This would be the same as just getting a null pointer exception.