Icon (programming language)

Last updated
Icon
Icon logo.png
Paradigms multi-paradigm: structured, text-oriented
Family SNOBOL
Designed by Ralph Griswold
First appeared1977;47 years ago (1977)
Stable release
9.5.24a / January 17, 2024;3 months ago (2024-01-17) [1]
Typing discipline dynamic
Website www.cs.arizona.edu/icon
Major implementations
Icon, Jcon
Dialects
Unicon
Influenced by
SNOBOL, SL5, ALGOL
Influenced
Unicon, Python, Goaldi, [2] jq

Icon is a very high-level programming language based on the concept of "goal-directed execution" in which code returns a "success" along with valid values, or a "failure", indicating that there is no valid data to return. The success and failure of a given block of code is used to direct further processing, whereas conventional languages would typically use boolean logic written by the programmer to achieve the same ends. Because the logic for basic control structures is often implicit in Icon, common tasks can be completed with less explicit code.

Contents

Icon was designed by Ralph Griswold after leaving Bell Labs where he was a major contributor to the SNOBOL language. SNOBOL was a string-processing language with what would be considered dated syntax by the standards of the early 1970s. After moving to the University of Arizona, he further developed the underlying SNOBOL concepts in SL5, but considered the result to be a failure. This led to the significantly updated Icon, which blends the short but conceptually dense code of SNOBOL-like languages with the more familiar syntax of ALGOL-inspired languages like C or Pascal.

Like the languages that inspired it, the primary area of use of Icon is managing strings and textual patterns. String operations often fail, for instance, finding "the" in "world". In most languages, this requires testing and branching to avoid using a non-valid result. In Icon most of these sorts of tests are simply unneeded, reducing the amount of code that must be written. Complex pattern handling can be done in a few lines of terse code, similar to more dedicated languages like Perl but retaining a more function-oriented syntax familiar to users of other ALGOL-like languages.

Icon is not object-oriented, but an object-oriented extension named Idol was developed in 1996 which eventually became Unicon. It also inspired other languages, with its simple generators being especially influential; Icon's generators were a major inspiration for the Python language. [3]

History

SNOBOL

The original SNOBOL effort, retroactively known as SNOBOL1, launched in the fall of 1962 at the Bell Labs Programming Research Studies Department. [4] The effort was a reaction to the frustrations of attempting to use the SCL language for polynomial formula manipulation, symbolic integration and studying Markov chains. SCL, written by the department head Chester Lee, was both slow and had a low-level syntax that resulting in volumes of code for even simple projects. After briefly considering the COMIT language, Ivan Polonsky, Ralph Griswold and David Farber, all members of the six-person department, decided to write their own language to solve these problems. [5]

The first versions were running on the IBM 7090 in early 1963, and by the summer had been built out and was being used across Bell. This led almost immediately to SNOBOL2, which added a number of built-in functions, and the ability to link to external assembly language code. It was released in April 1964 and mostly used within Bell, but also saw some use at Project MAC. The introduction of system functions served mostly to indicate the need for user functions, which was the major feature of SNOBOL3, released in July 1964. [6]

SNOBOL3's introduction corresponded with major changes within the Bell Labs computing department, including the addition of the new GE 645 mainframe which would require a rewrite of SNOBOL. Instead, the team suggested writing a new version that would run on a virtual machine, named SIL for SNOBOL Intermediate Language, allowing it to be easily ported to any sufficiently powerful platform. This proposal was accepted as SNOBOL4 in September 1965. By this time, plans for a significantly improved version of the language emerged in August 1966. [7] Further work on the language continued throughout the rest of the 1960s, notably adding the associative array type in later version, which they referred to as a table.

SL5 leads to Icon

Griswold left Bell Labs to become a professor at the University of Arizona in August 1971. [8] He introduced SNOBOL4 as a research tool at that time. [9] He received grants from the National Science Foundation to continue supporting and evolving SNOBOL. [10]

As a language originally developed in the early 1960s, SNOBOL's syntax bears the marks of other early programming languages like FORTRAN and COBOL. In particular, the language is column-dependant, as many of these languages were entered on punch cards where column layout is natural. Additionally, control structures were almost entirely based on branching around code rather than the use of blocks, which were becoming a must-have feature after the introduction of ALGOL 60. By the time he moved to Arizona, the syntax of SNOBOL4 was hopelessly outdated. [11]

Griswold began the effort of implementing SNOBOL's underlying success/failure concept with traditional flow control structures like if/then. This became SL5, short for "SNOBOL Language 5", but the result was unsatisfying. [11] In 1977, he returned to the language to consider a new version. He abandoned the very powerful function system introduced in SL5 with a simpler concept of suspend/resume and developed a new concept for the natural successor to SNOBOL4 with the following principles; [11]

The new language was initially known as SNOBOL5, but as it was significantly different from SNOBOL in all but the underlying concept, a new name was ultimately desired. After considering "s" as a sort of homage to "C", but this was ultimately abandoned due to the problems with typesetting documents using that name. A series of new names were proposed and abandoned; Irving, bard, and "TL" for "The Language". It was at this time that Xerox PARC began publishing about their work on graphical user interfaces and the term "icon" began to enter the computer lexicon. The decision was made to change the name initially to "icon" before finally choosing "Icon". [11] [lower-alpha 1]

Language

Basic syntax

The Icon language is derived from the ALGOL-class of structured programming languages, and thus has syntax similar to C or Pascal. Icon is most similar to Pascal, using := syntax for assignments, the procedure keyword and similar syntax. On the other hand, Icon uses C-style braces for structuring execution groups, and programs start by running a procedure called main. [13]

In many ways Icon also shares features with most scripting languages (as well as SNOBOL and SL5, from which they were taken): variables do not have to be declared, types are cast automatically, and numbers can be converted to strings and back automatically. [14] Another feature common to many scripting languages, but not all, is the lack of a line-ending character; in Icon, lines that do not end with a semicolon get ended by an implied semicolon if it makes sense. [15]

Procedures are the basic building blocks of Icon programs. Although they use Pascal naming, they work more like C functions and can return values; there is no function keyword in Icon. [16]

proceduredoSomething(aString)write(aString)end

Goal-directed execution

One of the key concepts in SNOBOL was that its functions returned the "success" or "failure" as primitives of the language rather than using magic numbers or other techniques. [17] [18] For instance, a function that returns the position of a substring within another string is a common routine found in most language runtime systems; in JavaScript one might want to find the position of the word "World" within a "Hello, World!" program, which would be done with position="Hello, World".indexOf("World"), which would return 7. If one instead asks for the position="Hello, World".indexOf("Goodbye") the code will "fail", as the search term does not appear in the string. In JavaScript, as in most languages, this will be indicated by returning a magic number, in this case -1. [19]

In SNOBOL a failure of this sort returns a special value, fail. SNOBOL's syntax operates directly on the success or failure of the operation, jumping to labelled sections of the code without having to write a separate test. For instance, the following code prints "Hello, world!" five times: [20]

* SNOBOL program to print Hello WorldI=1LOOPOUTPUT="Hello, world!"I=I+1LE(I,5):S(LOOP)END

To perform the loop, the less-than-or-equal operator, LE, is called on the index variable I, and if it Succeeds, meaning I is less than 5, it branches to the named label LOOP and continues. [20]

Icon retained the concept of flow control based on success or failure but developed the language further. One change was the replacement of the labelled GOTO-like branching with block-oriented structures in keeping with the structured programming style that was sweeping the computer industry in the late 1960s. [11] The second was to allow "failure" to be passed along the call chain so that entire blocks will succeed or fail as a whole. This is a key concept of the Icon language. Whereas in traditional languages one would have to include code to test the success or failure based on boolean logic and then branch based on the outcome, such tests and branches are inherent to Icon code and do not have to be explicitly written. [21]

For instance, consider this bit of code written in the Java programming language. It calls the function read() to read a character from a (previously opened) file, assigns the result to the variable a, and then writes the value of a to another file. The result is to copy one file to another. read will eventually run out of characters to read from the file, potentially on its very first call, which would leave a in an undetermined state and potentially cause write to cause a null pointer exception. To avoid this, read returns the special value EOF (end-of-file) in this situation, which requires an explicit test to avoid writeing it:

while((a=read())!=EOF){write(a);}

In contrast, in Icon the read() function returns a line of text or &fail. &fail is not simply an analog of EOF, as it is explicitly understood by the language to mean "stop processing" or "do the fail case" depending on the context. The equivalent code in Icon is: [18]

whilea:=read()dowrite(a)

This means, "as long as read does not fail, call write, otherwise stop". [18] There is no need to specify a test against the magic number as in the Java example, this is implicit, and the resulting code is simplified. Because success and failure are passed up through the call chain, one can embed function calls within others and they stop when the nested function call fails. For instance, the code above can be reduced to: [22]

whilewrite(read())

In this version, if the read call fails, the write call fails, and the while stops. [22] Icon's branching and looping constructs are all based on the success or failure of the code inside them, not on an arbitrary boolean test provided by the programmer. if performs the then block if its "test" returns a value, and performs the else block or moves to the next line if it returns &fail. Likewise, while continues calling its block until it receives a fail. Icon refers to this concept as goal-directed execution. [23]

It is important to contrast the concept of success and failure with the concept of an exception; exceptions are unusual situations, not expected outcomes. Fails in Icon are expected outcomes; reaching the end of a file is an expected situation and not an exception. Icon does not have exception handling in the traditional sense, although fail is often used in exception-like situations. For instance, if the file being read does not exist, read fails without a special situation being indicated. [18] In traditional language, these "other conditions" have no natural way of being indicated; additional magic numbers may be used, but more typically exception handling is used to "throw" a value. For instance, to handle a missing file in the Java code, one might see:

try{while((a=read())!=EOF){write(a);}}catch(Exceptione){// something else went wrong, use this catch to exit the loop}

This case needs two comparisons: one for EOF and another for all other errors. Since Java does not allow exceptions to be compared as logic elements, as under Icon, the lengthy try/catch syntax must be used instead. Try blocks also impose a performance penalty even if no exception is thrown, a distributed cost that Icon normally avoids.

Icon uses this same goal-directed mechanism to perform traditional boolean tests, although with subtle differences. A simple comparison like ifa<bthenwrite("a is smaller than b") does not mean, "if the conditional expression evaluation results in or returns a true value" as they would under most languages; instead, it means something more like, "if the conditional expression, here < operation, succeeds and does not fail". In this case, the < operator succeeds if the comparison is true. The if calls its then clause if the expression succeeds, or the else or the next line if it fails. The result is similar to the traditional if/then seen in other languages, the if performs then if a is less than b. The subtlety is that the same comparison expression can be placed anywhere, for instance:

write(a<b)

Another difference is that the < operator returns its second argument if it succeeds, which in this example will result in the value of b being written if it is larger than a, otherwise nothing is written. As this is not a test per se, but an operator that returns a value, they can be strung together allowing things like if a < b < c, [22] a common type of comparison that in most languages must be written as a conjunction of two inequalities like if (a < b) && (b < c).

A key aspect of goal-directed execution is that the program may have to rewind to an earlier state if a procedure fails, a task known as backtracking. For instance, consider code that sets a variable to a starting location and then performs operations that may change the value - this is common in string scanning operations for instance, which will advance a cursor through the string as it scans. If the procedure fails, it is important that any subsequent reads of that variable return the original state, not the state as it was being internally manipulated. For this task, Icon has the reversible assignment operator, <-, and the reversible exchange, <->. For instance, consider some code that is attempting to find a pattern string within a larger string:

{(i:=10)&(j:=(i<find(pattern,inString)))}

This code begins by moving i to 10, the starting location for the search. However, if the find fails, the block will fail as a whole, which results in the value of i being left at 10 as an undesirable side effect. Replacing i := 10 with i <- 10 indicates that i should be reset to its previous value if the block fails. This provides an analog of atomicity in the execution.

Generators

Expressions in Icon may return a single value, for instance, 5 > x will evaluate and return x if the value of x is less than 5, or else fail. However, Icon also includes the concept of procedures that do not immediately return success or failure, and instead return new values every time they are called. These are known as generators, and are a key part of the Icon language. Within the parlance of Icon, the evaluation of an expression or function produces a result sequence. A result sequence contains all the possible values that can be generated by the expression or function. When the result sequence is exhausted, the expression or function fails.

Icon allows any procedure to return a single value or multiple values, controlled using the fail, return and suspend keywords. A procedure that lacks any of these keywords returns &fail, which occurs whenever execution runs to the end of a procedure. For instance:

proceduref(x)ifx>0then{return1}end

Calling f(5) will return 1, but calling f(-1) will return &fail. This can lead to non-obvious behavior, for instance, write(f(-1)) will output nothing because f fails and suspends operation of write. [24]

Converting a procedure to be a generator uses the suspend keyword, which means "return this value, and when called again, start execution at this point". In this respect it is something like a combination of the static concept in C and return. For instance: [18]

procedureItoJ(i,j)whilei<=jdo{suspendii+:=1}failend

creates a generator that returns a series of numbers starting at i and ending a j, and then returns &fail after that. [lower-alpha 2] The suspend i stops execution and returns the value of i without reseting any of the state. When another call is made to the same function, execution picks up at that point with the previous values. In this case, that causes it to perform i +:= 1, loop back to the start of the while block, and then return the next value and suspend again. This continues until i <= j fails, at which point it exits the block and calls fail. This allows iterators to be constructed with ease. [18]

Another type of generator-builder is the alternator, which looks and operates like the boolean or operator. For instance:

ify<(x|5)thenwrite("y=",y)

This appears to say "if y is smaller than x or 5 then...", but is actually a short-form for a generator that returns values until it falls off the end of the list. The values of the list are "injected" into the operations, in this case, <. So in this example, the system first tests y < x, if x is indeed larger than y it returns the value of x, the test passes, and the value of y is written out in the then clause. However, if x is not larger than y it fails, and the alternator continues, performing y < 5. If that test passes, y is written. If y is smaller than neither x or 5, the alternator runs out of tests and fails, the if fails, and the write is not performed. Thus, the value of y will appear on the console if it is smaller than x or 5, thereby fulfilling the purpose of a boolean or. Functions will not be called unless evaluating their parameters succeeds, so this example can be shortened to:

write("y=",(x|5)>y)

Internally, the alternator is not simply an or and one can also use it to construct arbitrary lists of values. This can be used to iterate over arbitrary values, like:

everyi:=(1|3|4|5|10|11|23)dowrite(i)

As lists of integers are commonly found in many programming contexts, Icon also includes the to keyword to construct ad hoc integer generators:

everyk:=itojdowrite(k)

which can be shortened:

everywrite(1to10)

Icon is not strongly typed, so the alternator lists can contain different types of items:

everyi:=(1|"hello"|x<5)dowrite(i)

This writes 1, "hello" and maybe 5 depending on the value of x.

Likewise the conjunction operator, &, is used in a fashion similar to a boolean and operator: [25]

everyx:=ItoJ(0,10)&x%2==0dowrite(x)

This code calls ItoJ and returns an initial value of 0 which is assigned to x. It then performs the right-hand side of the conjunction, and since x % 2 does equal 0, it writes out the value. It then calls the ItoJ generator again which assigns 1 to x, which fails the right-hand-side and prints nothing. The result is a list of every even integer from 0 to 10. [25]

The concept of generators is particularly useful and powerful when used with string operations, and is a major underlying basis for Icon's overall design. Consider the indexOf operation found in many languages; this function looks for one string within another and returns an index of its location, or a magic number if it is not found. For instance:

s="All the world's a stage. And all the men and women merely players";i=indexOf("the",s);write(i);

This will scan the string s, find the first occurrence of "the", and return that index, in this case 4. The string, however, contains two instances of the string "the", so to return the second example an alternate syntax is used:

j=indexOf("the",s,i+1);write(j);

This tells it to scan starting at location 5, so it will not match the first instance we found previously. However, there may not be a second instance of "the" -there may not be a first one either- so the return value from indexOf has to be checked against the magic number -1 which is used to indicate no matches. A complete routine that prints out the location of every instance is:

s="All the world's a stage. And all the men and women merely players";i=indexOf("the",s);whilei!=-1{write(i);i=indexOf("the",s,i+1);}

In Icon, the equivalent find is a generator, so the same results can be created with a single line:

s:="All the world's a stage. And all the men and women merely players"everywrite(find("the",s))

Of course there are times where one does want to find a string after some point in input, for instance, if scanning a text file that contains a line number in the first four columns, a space, and then a line of text. Goal-directed execution can be used to skip over the line numbers:

everywrite(5<find("the",s))

The position will only be returned if "the" appears after position 5; the comparison will fail otherwise, pass the fail to write, and the write will not occur.

The every operator is similar to while, looping through every item returned by a generator and exiting on failure: [24]

everyk:=itojdowrite(someFunction(k))

There is a key difference between every and while; while re-evaluates the first result until it fails, whereas every fetches the next value from a generator. every actually injects values into the function in a fashion similar to blocks under Smalltalk. For instance, the above loop can be re-written this way: [24]

everywrite(someFunction(itoj))

In this case, the values from i to j will be injected into someFunction and (potentially) write multiple lines of output. [24]

Collections

Icon includes several collection types including lists that can also be used as stacks and queues, tables (also known as maps or dictionaries in other languages), sets and others. Icon refers to these as structures. Collections are inherent generators and can be easily called using the bang syntax. For instance:

lines:=[]# create an empty listwhileline:=read()do{# loop reading lines from standard inputpush(lines,line)# use stack-like syntax to push the line on the list}whileline:=pop(lines)do{# loop while lines can be popped off the listwrite(line)# write the line out}

Using the fail propagation as seen in earlier examples, we can combine the tests and the loops:

lines:=[]# create an empty listwhilepush(lines,read())# push until emptywhilewrite(pop(lines))# write until empty

Because the list collection is a generator, this can be further simplified with the bang syntax:

lines:=[]everypush(lines,!&input)everywrite(!lines)

In this case, the bang in write causes Icon to return a line of text one by one from the array and finally fail at the end. &input is a generator-based analog of read that reads a line from standard input, so !&input continues reading lines until the file ends.

As Icon is typeless, lists can contain any different types of values:

aCat:=["muffins","tabby",2002,8]

The items can included other structures. To build larger lists, Icon includes the list generator; i := list(10, "word") generates a list containing 10 copies of "word". Like arrays in other languages, Icon allows items to be looked up by position, e.g., weight := aCat[4]. Array slicing is included, allowing new lists to be created out of the elements of other lists, for instance, aCat := Cats[2:4] produces a new list called aCat that contains "tabby" and 2002.

Tables are essentially lists with arbitrary index keys rather than integers:

symbols:=table(0)symbols["there"]:=1symbols["here"]:=2

This code creates a table that will use zero as the default value of any unknown key. It then adds two items into the table, with the keys "there" and "here", and values 1 and 2.

Sets are also similar to lists but contain only a single member of any given value. Icon includes the ++ to produce the union of two sets, ** the intersection, and -- the difference. Icon includes a number of pre-defined "Cset"s, a set containing various characters. There are four standard Csets in Icon, &ucase, &lcase, &letters, and &digits. New Csets can be made by enclosing a string in single quotes, for instance, vowel := 'aeiou'.

Strings

In Icon, strings are lists of characters. As a list, they are generators and can thus be iterated over using the bang syntax:

write(!"Hello, world!")

Will print out each character of the string on a separate line.

Substrings can be extracted from a string by using a range specification within brackets. A range specification can return a point to a single character, or a slice of the string. Strings can be indexed from either the right or the left. Positions within a string are defined to be between the characters 1A2B3C4 and can be specified from the right −3A−2B−1C0

For example,

"Wikipedia"[1]==>"W""Wikipedia"[3]==>"k""Wikipedia"[0]==>"a""Wikipedia"[1:3]==>"Wi""Wikipedia"[-2:0]==>"ia""Wikipedia"[2+:3]==>"iki"

Where the last example shows using a length instead of an ending position

The subscripting specification can be used as a lvalue within an expression. This can be used to insert strings into another string or delete parts of a string. For example:

s:="abc"s[2]:="123"snowhasavalueof"a123c"s:="abcdefg"s[3:5]:="ABCD"snowhasavalueof"abABCDefg"s:="abcdefg"s[3:5]:=""snowhasavalueof"abefg"

String scanning

A further simplification for handling strings is the scanning system, invoked with ?, which calls functions on a string:

s?write(find("the"))

Icon refers to the left-hand-side of the ? as the subject, and passes it into string functions. Recall the find takes two parameters, the search text as parameter one and the string to search in parameter two. Using ? the second parameter is implicit and does not have to be specified by the programmer. In the common cases when multiple functions are being called on a single string in sequence, this style can significantly reduce the length of the resulting code and improve clarity. Icon function signatures identify the subject parameter in their definitions so the parameter can be hoisted in this fashion.

The ? is not simply a form of syntactic sugar, it also sets up a "string scanning environment" for any following string operations. This is based on two internal variables, &subject and &pos; &subject is simply a pointer to the original string, while &pos is the current position within it, or cursor. Icon's various string manipulation procedures use these two variables so they do not have to be explicitly supplied by the programmer. For example:

s:="this is a string"s?write("subject=[",&subject,"], pos=[",&pos,"]")

would produce:

subject=[this is a string], pos=[1] 

Built-in and user-defined functions can be used to move around within the string being scanned. All of the built-in functions will default to &subject and &pos to allow the scanning syntax to be used. The following code will write all blank-delimited "words" in a string:

s:="this is a string"s?{# Establish string scanning environmentwhilenotpos(0)do{# Test for end of stringtab(many(' '))# Skip past any blanksword:=tab(upto(' ')|0)# the next word is up to the next blank -or- the end of the linewrite(word)# write the word}}

There are a number of new functions introduced in this example. pos returns the current value of &pos. It may not be immediately obvious why one would need this function and not simply use the value of &pos directly; the reason is that &pos is a variable and thus cannot take on the value &fail, which the procedure pos can. Thus pos provides a lightweight wrapper on &pos that allows Icon's goal-directed flow control to be easily used without having to provide hand-written boolean tests against &pos. In this case, the test is "is &pos zero", which, in the odd numbering of Icon's string locations, is the end of the line. If it is not zero, pos returns &fail, which is inverted with the not and the loop continues.

many finds one or more examples of the provided Cset parameter starting at the current &pos. In this case, it is looking for space characters, so the result of this function is the location of the first non-space character after &pos. tab moves &pos to that location, again with a potential &fail in case, for instance, many falls off the end of the string. upto is essentially the reverse of many; it returns the location immediately prior to its provided Cset, which the example then sets the &pos to with another tab. Alternation is used to also stop at the end of a line.

This example can be made more robust through the use of a more appropriate "word breaking" Cset which might include periods, commas and other punctuation, as well as other whitespace characters like tab and non-breaking spaces. That Cset can then be used in many and upto.

A more complex example demonstrates the integration of generators and string scanning within the language.

proceduremain()s:="Mon Dec 8"s?write(Mdate()|"not a valid date")end# Define a matching function that returns# a string that matches a day month dayofmonthprocedureMdate()# Define some initial valuesstaticdatesstaticdaysinitial{days:=["Mon","Tue","Wed","Thr","Fri","Sat","Sun"]months:=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}everysuspend(retval<-tab(match(!days))||# Match a day=" "||# Followed by a blanktab(match(!months))||# Followed by the month=" "||# Followed by a blankmatchdigits(2)# Followed by at least 2 digits)&(=" "|pos(0))&# Either a blank or the end of the stringretval# And finally return the stringend# Matching function that returns a string of n digitsprocedurematchdigits(n)suspend(v:=tab(many(&digits))&*v<=n)&vend

Criticisms

Laurence Tratt wrote a paper on Icon examining its real-world applications and pointing out a number of areas of concern. Among these were a number of practical decisions that derive from their origins in string processing but do not make as much sense in other areas. [24] Among them:

The decision to fail by default at the end of procedures makes sense in the context of generators, but less so in the case of general procedures. Returning to the example noted above, write(f(-1)) will not output which may be expected. However: [24]

x:=10(additionallines)x:=f(-1)write(x)

will result in 10 being printed. This sort of issue is not at all obvious as even in an interactive debugger all the code is invoked yet x never picks up the expected value. This could be dismissed as one of those "gotchas" that programmers have to be aware of in any language, but Tratt examined a variety of Icon programs and found that the vast majority of procedures are not generators. This means that Icon's default behaviour is only used by a tiny minority of its constructs, yet represents a major source of potential errors in all the others. [24]

Another issue is the lack of a boolean data type [lower-alpha 3] and conventional boolean logic. While the success/fail system works in most cases where the ultimate goal is to check a value, this can still lead to some odd behaviour in seemingly simple code: [25]

proceduremain()ifcthen{write("taken")}end

This program will print "taken". The reason is that the test, c, does return a value; that value is &null, the default value for all otherwise uninitiated variables. [26] &null is a valid value, so if c succeeds. To test this, one needs to make the test explicit, c === &null. Tratt supposed that it detracts from the self-documenting code, having supposed erroneously that it is testing "is c zero" or "does c exist". [25]

See also

Notes

  1. According to an interview in 1985, Griswold states that the term 'icon' was not being used until Smalltalk was released to the public some time later. He expressed his annoyance that the term was now confusing people who thought the language had graphical elements. [12]
  2. The fail is not required in this case as it is immediately before the end. It has been added for clarity.
  3. Although, as Tratt points out, K&R C also lacks an explicit boolean type and uses 0 for false and any non-zero for true. [24]

Related Research Articles

Eiffel is an object-oriented programming language designed by Bertrand Meyer and Eiffel Software. Meyer conceived the language in 1985 with the goal of increasing the reliability of commercial software development; the first version becoming available in 1986. In 2005, Eiffel became an ISO-standardized language.

Backtracking is a class of algorithms for finding solutions to some computational problems, notably constraint satisfaction problems, that incrementally builds candidates to the solutions, and abandons a candidate ("backtracks") as soon as it determines that the candidate cannot possibly be completed to a valid solution.

In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. In contrast to pattern recognition, the match usually has to be exact: "either it will or will not be a match." The patterns generally have the form of either sequences or tree structures. Uses of pattern matching include outputting the locations of a pattern within a token sequence, to output some component of the matched pattern, and to substitute the matching pattern with some other token sequence.

<span class="mw-page-title-main">Conditional (computer programming)</span> Control flow statement that executes code according to some condition(s)

In computer science, conditionals are programming language commands for handling decisions. Specifically, conditionals perform different computations or actions depending on whether a programmer-defined Boolean condition evaluates to true or false. In terms of control flow, the decision is always achieved by selectively altering the control flow based on some condition . Although dynamic dispatch is not usually classified as a conditional construct, it is another way to select between alternatives at runtime. Conditional statements are the checkpoints in the programme that determines behaviour according to situation.

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. In some languages, particularly C++, function objects are often called functors.

In computer science, a generator is a routine that can be used to control the iteration behaviour of a loop. All generators are also iterators. A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately. In short, a generator looks like a function but behaves like an iterator.

In computer programming, the ternary conditional operator is a ternary operator that is part of the syntax for basic conditional expressions in several programming languages. It is commonly referred to as the conditional operator, ternary if, or inline if. An expression a ? b : c evaluates to b if the value of a is true, and otherwise to c. One can read it aloud as "if a then b otherwise c". The form a ? b : c is by far and large the most common, but alternative syntaxes do exist; for example, Raku uses the syntax a ?? b !! c to avoid confusion with the infix operators ? and !, whereas in Visual Basic .NET, it instead takes the form If(a, b, c).

In computer science, a parsing expression grammar (PEG) is a type of analytic formal grammar, i.e. it describes a formal language in terms of a set of rules for recognizing strings in the language. The formalism was introduced by Bryan Ford in 2004 and is closely related to the family of top-down parsing languages introduced in the early 1970s. Syntactically, PEGs also look similar to context-free grammars (CFGs), but they have a different interpretation: the choice operator selects the first match in PEG, while it is ambiguous in CFG. This is closer to how string recognition tends to be done in practice, e.g. by a recursive descent parser.

The computer programming languages C and Pascal have similar times of origin, influences, and purposes. Both were used to design their own compilers early in their lifetimes. The original Pascal definition appeared in 1969 and a first compiler in 1970. The first version of C appeared in 1972.

<span class="mw-page-title-main">JavaScript syntax</span> Set of rules defining correctly structured programs

The syntax of JavaScript is the set of rules that define a correctly structured JavaScript program.

In computer programming, homoiconicity is a property of some programming languages. A language is homoiconic if a program written in it can be manipulated as data using the language. The program's internal representation can thus be inferred just by reading the program itself. This property is often summarized by saying that the language treats code as data.

In computer programming, a semipredicate problem occurs when a subroutine intended to return a useful value can fail, but the signalling of failure uses an otherwise valid return value. The problem is that the caller of the subroutine cannot tell what the result means in this case.

<span class="mw-page-title-main">Python syntax and semantics</span> Set of rules defining correctly structured programs

The syntax of the Python programming language is the set of rules that defines how a Python program will be written and interpreted. The Python language has many similarities to Perl, C, and Java. However, there are some definite differences between the languages. It supports multiple programming paradigms, including structured, object-oriented programming, and functional programming, and boasts a dynamic type system and automatic memory management.

In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.

This Comparison of programming languages (associative arrays) compares the features of associative array data structures or array-lookup processing for over 40 computer programming languages.

The syntax and semantics of PHP, a programming language, form a set of rules that define how a PHP program can be written and interpreted.

In type theory, an intersection type can be allocated to values that can be assigned both the type and the type . This value can be given the intersection type in an intersection type system. Generally, if the ranges of values of two types overlap, then a value belonging to the intersection of the two ranges can be assigned the intersection type of these two types. Such a value can be safely passed as argument to functions expecting either of the two types. For example, in Java the class Boolean implements both the Serializable and the Comparable interfaces. Therefore, an object of type Boolean can be safely passed to functions expecting an argument of type Serializable and to functions expecting an argument of type Comparable.

The structure of the Perl programming language encompasses both the syntactical rules of the language and the general ways in which programs are organized. Perl's design philosophy is expressed in the commonly cited motto "there's more than one way to do it". As a multi-paradigm, dynamically typed language, Perl allows a great degree of flexibility in program design. Perl also encourages modularization; this has been attributed to the component-based design structure of its Unix roots, and is responsible for the size of the CPAN archive, a community-maintained repository of more than 100,000 modules.

In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.

Smart Pascal is a Object Pascal programming language that is derived from Delphi Web Script, its adapted for Smart Mobile Studio, commercial development JavaScript, machine code.

References

Citations

  1. Townsend, Gregg (January 26, 2024). "Update version to 9.5.22e". GitHub .
  2. "Goaldi". GitHub .
  3. Schemenauer, Neil; Peters, Tim; Hetland, Magnus Lie (18 May 2001). "PEP 255 – Simple Generators". Python Enhancement Proposals. Python Software Foundation. Retrieved 9 February 2012.
  4. Griswold 1981, pp. 601, 602.
  5. Griswold 1981, pp. 602.
  6. Griswold 1981, pp. 606.
  7. Griswold 1981, pp. 608.
  8. Griswold 1981, pp. 609.
  9. Griswold 1981, pp. 629.
  10. Shapiro 1985, pp. 346.
  11. 1 2 3 4 5 Griswold & Griswold 1993, p. 53.
  12. Shapiro 1985, p. 350.
  13. Griswold & Griswold 2002, p. xv.
  14. Griswold & Griswold 2002, p. xvi.
  15. Griswold & Griswold 2002, p. 10.
  16. Griswold & Griswold 2002, p. 1.
  17. Griswold & Griswold 2002, p. 4.
  18. 1 2 3 4 5 6 Tratt 2010, p. 74.
  19. "Array.prototype.indexOf()". MDN Web Docs. 27 June 2023.
  20. 1 2 Lane, Rupert (26 July 2015). "SNOBOL - Introduction". Try MTS.
  21. Tratt 2010, p. 73.
  22. 1 2 3 Griswold 1996, p. 2.1.
  23. Griswold 1996, p. 1.
  24. 1 2 3 4 5 6 7 8 Tratt 2010, p. 75.
  25. 1 2 3 4 Tratt 2010, p. 76.
  26. Griswold & Griswold 2002, p. 128.

Bibliography