SNOBOL ("StriNg Oriented and symBOlic Language") is a series of programming languages developed between 1962 and 1967 at AT&T Bell Laboratories by David J. Farber , Ralph Griswold and Ivan P. Polonsky, culminating in SNOBOL4. It was one of a number of text-string -oriented languages developed during the 1950s and 1960s; others included COMIT and TRAC .
73-635: SNOBOL4 stands apart from most programming languages of its era by having patterns as a first-class data type ( i.e. a data type whose values can be manipulated in all ways permitted to any other data type in the programming language) and by providing operators for pattern concatenation and alternation . SNOBOL4 patterns are a type of object and admit various manipulations, much like later object-oriented languages such as JavaScript whose patterns are known as regular expressions . In addition SNOBOL4 strings generated during execution can be treated as programs and either interpreted or compiled and executed (as in
146-449: A Snowball's chance in hell of finding a name". All of us yelled at once, "WE GOT IT — SNOBOL" in the spirit of all the BOL languages . We then stretched our mind to find what it stood for. Common backronyms of "SNOBOL" are 'String Oriented Symbolic Language' or (as a quasi-initialism ) 'StriNg Oriented symBOlic Language'. First-class object In a given programming language design ,
219-536: A first-class citizen is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument , returned from a function , and assigned to a variable . The concept of first- and second-class objects was introduced by Christopher Strachey in the 1960s. He did not actually define the term strictly, but contrasted real numbers and procedures in ALGOL : First and second class objects. In ALGOL,
292-462: A virtual machine to allow improved portability across computers. The SNOBOL4 language translator was still written in assembly language. However the macro features of the assembler were used to define the virtual machine instructions of the S NOBOL I mplementation L anguage, the SIL. This very much improved the portability of the language by making it relatively easy to port the virtual machine which hosted
365-433: A "array of characters" which may be stored in the same array but is often not null terminated. Using C string handling functions on such an array of characters often seems to work, but later leads to security problems . There are many algorithms for processing strings, each with various trade-offs. Competing algorithms can be analyzed with respect to run time, storage requirements, and so forth. The name stringology
438-414: A 10-byte buffer , along with its ASCII (or more modern UTF-8 ) representation as 8-bit hexadecimal numbers is: The length of the string in the above example, " FRANK ", is 5 characters, but it occupies 6 bytes. Characters after the terminator do not form part of the representation; they may be either part of other data or just garbage. (Strings of this form are sometimes called ASCIZ strings , after
511-449: A byte value in the ASCII range will represent only that ASCII character, making the encoding safe for systems that use those characters as field separators. Other encodings such as ISO-2022 and Shift-JIS do not make such guarantees, making matching on byte codes unsafe. These encodings also were not "self-synchronizing", so that locating character boundaries required backing up to the start of
584-409: A conditional branch dependent upon the success or failure of the subject evaluation, the pattern evaluation, the pattern match, the object evaluation or the final assignment. It can also be a transfer to code created and compiled by the program itself during a run. A SNOBOL pattern can be very simple or extremely complex. A simple pattern is just a text string (e.g. "ABCD"), but a complex pattern may be
657-462: A consequence, some people call such a string a Pascal string or P-string . Storing the string length as byte limits the maximum string length to 255. To avoid such limitations, improved implementations of P-strings use 16-, 32-, or 64-bit words to store the string length. When the length field covers the address space , strings are limited only by the available memory . If the length is bounded, then it can be encoded in constant space, typically
730-533: A dedicated string datatype at all, instead adopting the convention of representing strings as lists of character codes. Even in programming languages having a dedicated string type, string can usually be iterated as a sequence character codes, like lists of integers or other values. Representations of strings depend heavily on the choice of character repertoire and the method of character encoding. Older string implementations were designed to work with repertoire and encoding defined by ASCII, or more recent extensions like
803-414: A fixed length. A few languages such as Haskell implement them as linked lists instead. A lot of high-level languages provide strings as a primitive data type, such as JavaScript and PHP , while most others provide them as a composite data type, some with special language support in writing literals, for example, Java and C# . Some languages, such as C , Prolog and Erlang , avoid implementing
SECTION 10
#1732848120846876-453: A large structure describing, for example, the complete grammar of a computer language. It is possible to implement a language interpreter in SNOBOL almost directly from a Backus–Naur form expression of it, with few changes. Creating a macro assembler and an interpreter for a completely theoretical piece of hardware could take as little as a few hundred lines, with a new instruction being added with
949-462: A length code are limited to the maximum value of the length code. Both of these limitations can be overcome by clever programming. It is possible to create data structures and functions that manipulate them that do not have the problems associated with character termination and can in principle overcome length code bounds. It is also possible to optimize the string represented using techniques from run length encoding (replacing repeated characters by
1022-449: A machine word, thus leading to an implicit data structure , taking n + k space, where k is the number of characters in a word (8 for 8-bit ASCII on a 64-bit machine, 1 for 32-bit UTF-32/UCS-4 on a 32-bit machine, etc.). If the length is not bounded, encoding a length n takes log( n ) space (see fixed-length code ), so length-prefixed strings are a succinct data structure , encoding a string of length n in log( n ) + n space. In
1095-465: A one 8-bit byte per-character encoding) for reasonable representation. The normal solutions involved keeping single-byte representations for ASCII and using two-byte representations for CJK ideographs . Use of these with existing code led to problems with matching and cutting of strings, the severity of which depended on how the character encoding was designed. Some encodings such as the EUC family guarantee that
1168-542: A program treated specially (such as period and space and comma) were in the same place in all the encodings a program would encounter. These character sets were typically based on ASCII or EBCDIC . If text in one encoding was displayed on a system using a different encoding, text was often mangled , though often somewhat readable and some computer users learned to read the mangled text. Logographic languages such as Chinese , Japanese , and Korean (known collectively as CJK ) need far more than 256 characters (the limit of
1241-565: A real number may appear in an expression or be assigned to a variable, and either of them may appear as an actual parameter in a procedure call. A procedure, on the other hand, may only appear in another procedure call either as the operator (the most common case) or as one of the actual parameters. There are no other expressions involving procedures or whose results are procedures. Thus in a sense procedures in ALGOL are second class citizens—they always have to appear in person and can never be represented by
1314-452: A result, several incompatible dialects arose. As SNOBOL3 became more popular, the authors received more and more requests for extensions to the language. They also began to receive complaints about incompatibility and bugs in versions that they hadn't written. To address this and to take advantage of the new computers being introduced in the late 1960s, the decision was taken to develop SNOBOL4 with many extra datatypes and features but based on
1387-460: A result, the authors decided to extend it and tidy it up. SNOBOL2 did exist but it was a short-lived intermediate development version without user-defined functions and was never released. SNOBOL was rewritten to add functions, both standard and user-defined, and the result was released as SNOBOL3. SNOBOL3 became quite popular and was rewritten for other computers than the IBM 7090 by other programmers. As
1460-478: A separate integer (which may put another artificial limit on the length) or implicitly through a termination character, usually a character value with all bits zero such as in C programming language. See also " Null-terminated " below. String datatypes have historically allocated one byte per character, and, although the exact character set varied by region, character encodings were similar enough that programmers could often get away with ignoring this, since characters
1533-426: A sequence of data or computer records other than characters — like a "string of bits " — but when used without qualification it refers to strings of characters. Use of the word "string" to mean any items arranged in a line, series or succession dates back centuries. In 19th-Century typesetting, compositors used the term "string" to denote a length of type printed on paper; the string would be measured to determine
SECTION 20
#17328481208461606-579: A single garbage-collected heap. The "Hello, World!" program might be as follows... A simple program to ask for a user's name and then use it in an output sentence... To choose between three possible outputs... To continue requesting input until no more is forthcoming... The classic implementation was on the PDP-10 ; it has been used to study compilers , formal grammars , and artificial intelligence , especially machine translation and machine comprehension of natural languages . The original implementation
1679-405: A single line. Complex SNOBOL patterns can do things that would be impractical or impossible using the more primitive regular expressions used in most other pattern-matching languages. Some of this power derives from the so-called "SPITBOL extensions" (which have since been incorporated in basically all modern implementations of the original SNOBOL 4 language too), although it is possible to achieve
1752-405: A single long consecutive array of characters, a typical text editor instead uses an alternative representation as its sequence data structure—a gap buffer , a linked list of lines, a piece table , or a rope —which makes certain string operations, such as insertions, deletions, and undoing previous edits, more efficient. The differing memory layout and storage requirements of strings can affect
1825-437: A string datatype; such a meta-string is called a literal or string literal . Although formal strings can have an arbitrary finite length, the length of strings in real languages is often constrained to an artificial maximum. In general, there are two types of string datatypes: fixed-length strings , which have a fixed maximum length to be determined at compile time and which use the same amount of memory whether this maximum
1898-407: A string may either cause storage in memory to be statically allocated for a predetermined maximum length or employ dynamic allocation to allow it to hold a variable number of elements. When a string appears literally in source code , it is known as a string literal or an anonymous string. In formal languages , which are used in mathematical logic and theoretical computer science , a string
1971-402: A string, and pasting two strings together could result in corruption of the second string. Unicode has simplified the picture somewhat. Most programming languages now have a datatype for Unicode strings. Unicode's preferred byte stream format UTF-8 is designed not to have the problems described above for older multibyte encodings. UTF-8, UTF-16 and UTF-32 require the programmer to know that
2044-404: A string-specific datatype, depending on the needs of the application, the desire of the programmer, and the capabilities of the programming language being used. If the programming language's string implementation is not 8-bit clean , data corruption may ensue. C programmers draw a sharp distinction between a "string", aka a "string of characters", which by definition is always null terminated, vs.
2117-553: A subroutine. For example, neither Fortran IV nor C supports array assignment, and when they are passed as parameters, only the position of their first element is actually passed—their size is lost. C appears to support assignment of array pointers , but in fact these are simply pointers to the array's first element, and again do not carry the array's size. In most languages, data types are not first-class objects, though in some object-oriented languages, classes are first-class objects and are instances of metaclasses . Languages in
2190-497: A termination value. Most string implementations are very similar to variable-length arrays with the entries storing the character codes of corresponding characters. The principal difference is that, with certain encodings, a single logical character may take up more than one entry in the array. This happens for example with UTF-8, where single codes ( UCS code points) can take anywhere from one to four bytes, and single characters can take an arbitrary number of codes. In these cases,
2263-474: A text file that is both human-readable and intended for consumption by a machine. This is needed in, for example, source code of programming languages, or in configuration files. In this case, the NUL character does not work well as a terminator since it is normally invisible (non-printable) and is difficult to input via a keyboard. Storing the string length would also be inconvenient as manual computation and tracking of
SNOBOL - Misplaced Pages Continue
2336-609: A variable or expression (except in the case of a formal parameter)... Robin Popplestone gave the following definition: All items have certain fundamental rights. During the 1990s, Raphael Finkel proposed definitions of second and third class values, but these definitions have not been widely adopted. The simplest scalar data types, such as integer and floating-point numbers, are nearly always first-class. In many older languages, arrays and strings are not first-class: they cannot be assigned as objects or passed as parameters to
2409-669: A way to express BNF grammars, which are equivalent to context-free grammars and more powerful than regular expressions. The "regular expressions" in current versions of AWK and Perl are in fact extensions of regular expressions in the traditional sense , but regular expressions, unlike SNOBOL4 patterns, are not recursive, which gives a distinct computational advantage to SNOBOL4 patterns. (Recursive expressions did appear in Perl 5.10 , though, released in December 2007.) The later SL5 (1977) and Icon (1978) languages were designed by Griswold to combine
2482-492: Is a finite sequence of symbols that are chosen from a set called an alphabet . A primary purpose of strings is to store human-readable text, like words and sentences. Strings are used to communicate information from a computer program to the user of the program. A program may also accept string input from its user. Further, strings may store data expressed as characters yet not intended for human reading. Example strings and their purposes: The term string may also designate
2555-417: Is commonly referred to as a C string . This representation of an n -character string takes n + 1 space (1 for the terminator), and is thus an implicit data structure . In terminated strings, the terminating code is not an allowable character in any string. Strings with length field do not have this limitation and can also store arbitrary binary data . An example of a null-terminated string stored in
2628-711: Is disputed. Some authors require it be possible to create new functions at runtime to call them 'first-class'. Under this definition, functions in C are not first-class objects; instead, they are sometimes called second-class objects , because they can still be manipulated in most of the above fashions (via function pointers ). In Smalltalk , functions (methods) are first-class objects, just like Smalltalk classes. Since Smalltalk operators (+, -, etc.) are methods, they are also first-class objects. Some languages, such as Java and PHP , have an explicit reflection subsystem which allow access to internal implementation structures even though they are not accessible or manipulable in
2701-459: Is distinctive in format and programming style, which are radically different from contemporary procedural languages such as Fortran and ALGOL . SNOBOL4 supports a number of built-in data types , such as integers and limited precision real numbers , strings , patterns , arrays , and tables (associative arrays), and also allows the programmer to define additional data types and new functions . SNOBOL4's programmer-defined data type facility
2774-409: Is generally considered as a data type and is often implemented as an array data structure of bytes (or words ) that stores a sequence of elements, typically characters, using some character encoding . String may also denote more general arrays or other sequence (or list ) data types and structures. Depending on the programming language and precise data type used, a variable declared to be
2847-425: Is needed or not, and variable-length strings , whose length is not arbitrarily fixed and which can use varying amounts of memory depending on the actual requirements at run time (see Memory management ). Most strings in modern programming languages are variable-length strings. Of course, even variable-length strings are limited in length – by the size of available computer memory . The string length can be stored as
2920-402: Is practical to even attempt using regular expressions. SNOBOL4 pattern-matching uses a backtracking algorithm similar to that used in the logic programming language Prolog , which provides pattern-like constructs via DCGs . This algorithm makes it easier to use SNOBOL as a logic programming language than is the case for most languages. SNOBOL stores variables, strings and data structures in
2993-509: The ISO 8859 series. Modern implementations often use the extensive repertoire defined by Unicode along with a variety of complex encodings such as UTF-8 and UTF-16. The term byte string usually indicates a general-purpose string of bytes, rather than strings of only (readable) characters, strings of bits, or such. Byte strings often imply that bytes can take any value and any data can be stored as-is, meaning that there should be no value interpreted as
SNOBOL - Misplaced Pages Continue
3066-646: The Michigan Terminal System (MTS) provided pattern matching based on SNOBOL4 patterns. Several implementations are currently available. Macro SNOBOL4 in C written by Phil Budne is a free, open source implementation, capable of running on almost any platform. Catspaw, Inc provided a commercial implementation of the SNOBOL4 language for many different computer platforms, including DOS, Macintosh, Sun, RS/6000, and others, and these implementations are now available free from Catspaw. Minnesota SNOBOL4, by Viktors Berstis,
3139-507: The SNOBOL language of the early 1960s. A string datatype is a datatype modeled on the idea of a formal string. Strings are such an important and useful datatype that they are implemented in nearly every programming language . In some languages they are available as primitive types and in others as composite types . The syntax of most high-level programming languages allows for a string, usually quoted in some way, to represent an instance of
3212-413: The eval function of other languages). SNOBOL4 was quite widely taught in larger U.S. universities in the late 1960s and early 1970s and was widely used in the 1970s and 1980s as a text manipulation language in the humanities . In the 1980s and 1990s, its use faded as newer languages such as AWK and Perl made string manipulation by means of regular expressions fashionable. SNOBOL4 patterns include
3285-531: The functional programming family often also feature first-class types, in the form of, for example, generalized algebraic data types , or other metalanguage amenities enabling programs to implement extensions to their own implementation language. Few languages support continuations and GOTO -labels as objects at all, let alone as first-class objects. Many programming languages support passing and returning function values, which can be applied to arguments. Whether this suffices to call function values first-class
3358-433: The assignment of the seventh bit to (for example) handle ASCII codes. Early microcomputer software relied upon the fact that ASCII codes do not use the high-order bit, and set it to indicate the end of a string. It must be reset to 0 prior to output. The length of a string can also be stored explicitly, for example by prefixing the string with the length as a byte value. This convention is used in many Pascal dialects; as
3431-546: The backtracking of SNOBOL4 pattern matching with more standard ALGOL -like structuring. The initial SNOBOL language was created as a tool to be used by its authors to work with the symbolic manipulation of polynomials. It was written in assembly language for the IBM 7090 . It had a simple syntax, only one datatype, the string, no functions, and no declarations and very little error control. However, despite its simplicity and its "personal" nature its use began to spread to other groups. As
3504-435: The character value and a length) and Hamming encoding . While these representations are common, others are possible. Using ropes makes certain string operations, such as insertions, deletions, and concatenations more efficient. The core data structure in a text editor is the one that manages the string (sequence of characters) that represents the current state of the file being edited. While that state could be stored in
3577-452: The closest PC implementation to the original IBM mainframe version (even including Fortran-like FORMAT statement support) is also free. Although SNOBOL itself has no structured programming features, a SNOBOL preprocessor called Snostorm was designed and implemented during the 1970s by Fred G. Swartz for use under the Michigan Terminal System (MTS) at the University of Michigan . Snostorm
3650-428: The compositor's pay. Use of the word "string" to mean "a sequence of symbols or linguistic elements in a definite order" emerged from mathematics, symbolic logic , and linguistic theory to speak about the formal behavior of symbolic systems, setting aside the symbols' meaning. For example, logician C. I. Lewis wrote in 1918: A mathematical system is any set of strings of recognisable marks in which some of
3723-418: The core programming system by users can easily undermine performance optimisations made by language implementers. String (computer science) In computer programming , a string is traditionally a sequence of characters , either as a literal constant or as some kind of variable . The latter may allow its elements to be mutated and the length changed, or it may be fixed (after creation). A string
SECTION 50
#17328481208463796-511: The entire semester was focused on implementing SITBOL. It was over 80% complete by the end of the semester and was subsequently completed by Professor Gimpel and several students over the summer. SITBOL was a full-featured, high-performance SNOBOL4 interpreter. The Gnat Ada Compiler comes with a package (GNAT.Spitbol) that implements all of the Spitbol string manipulation semantics. This can be called from within an Ada program. The file editor for
3869-528: The equivalent capabilities normally thought of as "structured programming", most notably nested if/then/else type constructs. These features have since been added to most recent SNOBOL4 implementations. After many years as a commercial product, in April 2009 SPITBOL was released as free software under the GNU General Public License . According to Dave Farber, he, Griswold and Polonsky "finally arrived at
3942-530: The facilities that the interpreter provides. The classic implementation on the PDP-10 was quite slow, and in 1972 James Gimpel of Bell Labs, Holmdel, N.J. designed a native implementation of SNOBOL4 for the PDP-10 that he named SITBOL. He used the design as the basis of a graduate class in string processing that he taught that year at Stevens Institute of Technology (which is why it was named SITBOL). Students were given sections to implement (in PDP-10 assembler) and
4015-507: The fixed-size code units are different from the "characters", the main difficulty currently is incorrectly designed APIs that attempt to hide this difference (UTF-32 does make code points fixed-sized, but these are not "characters" due to composing codes). Some languages, such as C++ , Perl and Ruby , normally allow the contents of a string to be changed after it has been created; these are termed mutable strings. In other languages, such as Java , JavaScript , Lua , Python , and Go ,
4088-430: The implementation is usually hidden , the string must be accessed and modified through member functions. text is a pointer to a dynamically allocated memory area, which might be expanded as needed. See also string (C++) . Both character termination and length codes limit strings: For example, C character arrays that contain null (NUL) characters cannot be handled directly by C string library functions: Strings using
4161-428: The latter case, the length-prefix field itself does not have fixed length, therefore the actual string data needs to be moved when the string grows such that the length field needs to be increased. Here is a Pascal string stored in a 10-byte buffer, along with its ASCII / UTF-8 representation: Many languages, including object-oriented ones, implement strings as records with an internal structure like: However, since
4234-407: The length is tedious and error-prone. Two common representations are: While character strings are very common uses of strings, a string in computer science may refer generically to any sequence of homogeneously typed data. A bit string or byte string , for example, may be used to represent non-textual binary data retrieved from a communications medium. This data may or may not be represented by
4307-436: The logical length of the string (number of characters) differs from the physical length of the array (number of bytes in use). UTF-32 avoids the first part of the problem. The length of a string can be stored implicitly by using a special terminating character; often this is the null character (NUL), which has all bits zero, a convention used and perpetuated by the popular C programming language . Hence, this representation
4380-638: The name Symbolic EXpression Interpreter SEXI." All went well until one day I was submitting a batch job to assemble the system and as normal on my JOB card — the first card in the deck, I, in BTL standards, punched my job and my name — SEXI Farber. One of the Comp Center girls looked at it and said, "That's what you think" in a humorous way. That made it clear that we needed another name!! We sat and talked and drank coffee and shot rubber bands and after much too much time someone said — most likely Ralph — "We don't have
4453-447: The original assembly language directive used to declare them.) Using a special byte other than null for terminating strings has historically appeared in both hardware and software, though sometimes with a value that was also a printing character. $ was used by many assembler systems, : used by CDC systems (this character had a value of zero), and the ZX80 used " since this was
SECTION 60
#17328481208464526-400: The pattern itself during the matching operation. Patterns can be saved like any other first-class data item, and can be concatenated, used within other patterns, and used to create very complex and sophisticated pattern expressions. It is possible to write, for example, a SNOBOL4 pattern which matches "a complete name and international postal mailing address", which is well beyond anything that
4599-438: The same power without them. Part of this power comes from the side effects that it is possible to produce during the pattern matching operation, including saving numerous intermediate/tentative matching results and the ability to invoke user-written functions during the pattern match which can perform nearly any desired processing, and then influence the ongoing direction the interrupted pattern match takes, or even to indeed change
4672-603: The same way as ordinary objects. In other languages, such as those in the Lisp family, reflection is a central feature of the language, rather than a special subsystem. Typically this takes the form of some set of the following features: These allow varying forms of first-class access to the language implementation, and are, in general, manipulable in the same way as, and fully indistinguishable from, ordinary language objects. Because of this, their usage generally comes with some (cultural) stipulations and advice, as untested modification of
4745-434: The security of the program accessing the string data. String representations requiring a terminating character are commonly susceptible to buffer overflow problems if the terminating character is not present, caused by a coding error or an attacker deliberately altering the data. String representations adopting a separate length field are also susceptible if the length can be manipulated. In such cases, program code accessing
4818-497: The string data requires bounds checking to ensure that it does not inadvertently access or change data outside of the string memory limits. String data is frequently obtained from user input to a program. As such, it is the responsibility of the program to validate the string to ensure that it represents the expected format. Performing limited or no validation of user input can cause a program to be vulnerable to code injection attacks. Sometimes, strings need to be embedded inside
4891-402: The string delimiter in its BASIC language. Somewhat similar, "data processing" machines like the IBM 1401 used a special word mark bit to delimit strings at the left, where the operation would start at the right. This bit had to be clear in all other parts of the string. This meant that, while the IBM 1401 had a seven-bit word, almost no-one ever thought to use this as a feature, and override
4964-407: The strings are taken initially and the remainder derived from these by operations performed according to rules which are independent of any meaning assigned to the marks. That a system should consist of 'marks' instead of sounds or odours is immaterial. According to Jean E. Sammet , "the first realistic string handling and pattern matching language" for computers was COMIT in the 1950s, followed by
5037-428: The translator by recreating its virtual instructions on any machine which included a macro assembler or indeed a high level language. The machine-independent language SIL arose as a generalization of string manipulation macros by Douglas McIlroy , which were used extensively in the initial SNOBOL implementation. In 1969, McIlroy influenced the language again by insisting on addition of the table type to SNOBOL4. SNOBOL
5110-768: The value is fixed and a new string must be created if any alteration is to be made; these are termed immutable strings. Some of these languages with immutable strings also provide another type that is mutable, such as Java and .NET 's StringBuilder , the thread-safe Java StringBuffer , and the Cocoa NSMutableString . There are both advantages and disadvantages to immutability: although immutable strings may require inefficiently creating many copies, they are simpler and completely thread-safe . Strings are typically implemented as arrays of bytes, characters, or code units, in order to allow fast access to individual units or substrings—including characters when they have
5183-419: Was advanced at the time—it is similar to the records of the earlier COBOL and the later Pascal programming languages. All SNOBOL command lines are of the form Each of the five elements is optional. In general, the subject is matched against the pattern . If the object is present, any matched portion is replaced by the object via rules for replacement. The transfer can be an absolute branch or
5256-497: Was on an IBM 7090 at Bell Labs, Holmdel, N.J. SNOBOL4 was specifically designed for portability; the first implementation was started on an IBM 7094 in 1966 but completed on an IBM 360 in 1967. It was rapidly ported to many other platforms. It is normally implemented as an interpreter because of the difficulty in implementing some of its very high-level features, but there is a compiler , the SPITBOL compiler , which provides nearly all
5329-491: Was used at the eight to fifteen sites that ran MTS. It was also available at University College London (UCL) between 1982 and 1984. Snocone by Andrew Koenig adds block-structured constructs to the SNOBOL4 language. Snocone is a self-contained programming language, rather than a proper superset of SNOBOL4. The SPITBOL implementation also introduced a number of features which, while not using traditional structured programming keywords, nevertheless can be used to provide many of
#845154