Icon+Unicon/Intro: Difference between revisions

m
(→‎Contractions: - extreme title, more examples, replace due to logged out)
 
(30 intermediate revisions by 3 users not shown)
Line 10:
 
These are general language references.
 
===== Unicon =====
 
* [http://unicon.org/book/ub.pdf Book: Programming with Unicon 2nd edition; Jeffrey, Mohamed, Gharaibeh, Pereda, Parlett - note also documents details of the Icon Programming Library]
* [http://unicon.org/utr/utr8.pdf Unicon Language Reference]
 
===== Icon =====
* [http://www.cs.arizona.edu/icon/ftp/doc/lb1up.pdf Book: The Icon Programming Language, 3rd Edition; Griswold and Griswold]
* [http://unicon.org/book/ub.pdf Book: Programming with Unicon; Jeffrey, Mohamed, Pereda, Parlett - note also documents details of the Icon Programming Library]
* [http://www2.cs.uidaho.edu/~jeffery/icon/humanists/humanist.pdf Book: Icon Programming for Humanists; Corré]
* [http://www.tools-of-computing.com/tc/CS/iconprog.pdf Book: Icon Programming Language Handbook by T.W. Christopher]
Line 18 ⟶ 24:
==== Articles, Newsletters ====
Excellent sources of programming insight.
* [http://www.cs.arizona.edu/icon/analyst/contents.htm Newsletter: Table of Contents for the Icon Analyst from 1990-2001] discussing advanced Icon programming and [http://www.cs.arizona.edu/icon/analyst/ia.htm Archived issues]
* [http://www.cs.arizona.edu/icon/inl/inlinlx.htmtxt Newsletter: Archived issuesTable of Contents for the Icon Newsletter from 1979-2000] discussing Icon programming and [http://www.cs.arizona.edu/icon/inl/inl.htm Archived issues]
* [http://unicon.org/generator/ Newsletter: Archived issues of the Generator from 2004-2005] discussing Unicon programming]
 
==== Programming Libraries ====
* [http://www.cs.arizona.edu/icon/library/ipl.htm Code: The Icon Programming Library and index]
* [https://tapestry.tucson.az.us/twiki/bin/view/UniLib/WebHome Code: The Unicon Library]
* [https://tapestry.tucson.az.us/twiki/bin/view/Main/WebHome Code: The Tapestry TWiki examples of Icon and Unicon programs]
 
==== Graphics, Network Messaging, Threads, Patterns, etc. ====
These represent extensions that have been integrated into the core langauge(s).
* [http://www.cs.arizona.edu/icon/ftp/doc/gb1up.pdf Book: Graphics Programming in Icon; Griswold,Jeffery, and Townsend]
* [http://unicon.org/utr/utr6b.pdf An IVIB Primer (Visual Interface Builder, UTR6b)]
* [http://unicon.org/utr/utr9autr9b.pdf Unicon 3D Graphics User's Guide and Reference Manual (UTR9b superseding UTR9a)]
* [http://unicon.org/utr/utr13utr10.pdf TheDebugging Uniconwith MessagingUDB Facilities(UTR10)]
* [http://unicon.org/utr/utr10utr12.pdf DebuggingUi: witha UDBUnicon Development Environment (UTR12)]
* [http://unicon.org/utr/utr12utr13.pdf Ui: aThe Unicon DevelopmentMessaging Facilities Environment(UTR13)]
* [http://unicon.org/utr/utr14.pdf Unicon Threads User's Guide and Reference Manual (UTR14)]
* [http://unicon.org/utr/utr18.pdf Pattern Matching in Unicon (UTR18)]
 
==== Implementation ====
Line 40 ⟶ 50:
** [http://www.cs.arizona.edu/icon/ftp/doc/ipd261.pdf Report: IPD261 Icon's run-time implementation language]
* [http://unicon.org/book/ib.pdf Book: The Implementation of Icon and Unicon: a Compendium; Jeffery]
* [http://unicon.org/utr/utr5autr5b.pdf The Implementation of Graphics in Unicon Version 1112 (UTR5b)]
 
== Icon and Unicon Differences ==
Line 187 ⟶ 197:
 
Files and windows (mutable) allow Icon/Unicon to interface with the operating system. Operations on files and windows have side effects and they are considered mutable. Sockets and pipes are also implemented as "files".
 
=== Keywords ===
Icon and Unicon has a list of special variables known as keywords. Syntactically, keywords are variable names preceded by an &.
 
Keywords can be used to inquire about the current state of the program, as constants, and to modify the operation (tracing and error control). For a list of keywords see [[Special_variables#Icon_and_Unicon]].
 
== Operators and Procedures ==
Line 385 ⟶ 400:
 
====suspend expr====
Suspend is semantically similar to 'return' with the exception that it sets up the possibility of producing additional results if needed. Rather than terminating the procedure as return does, suspend returns a result while leaving the procedure in suspension in the event additional results are needed. A suspended procedure will resume at the next point in the code. This capability is built directly into the run time rather than being an artificially constructed behaviour provided by Python or C#'s use of the 'yield' keyword. Every and all expressions may suspend or be involved in a suspending expression without any effort. Behaviorally this is closer to Prolog which also supports backtracking as a core part of the language. If the ''expr'' is capable of yielding more than one result, then suspend (if driven) will progressively yield all of those values. If the expression fails, execution continues within the procedure until the next suspend, return, or fail.
 
A procedure can contain several uses of ''suspend'' and it's quite reasonable for the procedure to execute many of them in any chosen order.
Line 451 ⟶ 466:
 
====until====
Until will loop untilwhile the expression fails. An optional expression can evaluated upon success via the do clause.
 
====every====
Line 517 ⟶ 532:
 
Steve Wampler's "Fun With Co-Expressions" articles in The Generator
* [http://www.unicon.org/generator/TheGeneratorVol1No1Letter.pdf| "Fun With Co-Expressions, part 1"]
* [http://www.unicon.org/generator/v2n1.pdf| "Fun With Co-Expressions, part 2"]
* [http://www.unicon.org/generator/v2n2.pdf| "Fun With Co-Expressions, part 3"]
 
Other articles
* [http://www.drones.com/coexp/| Shamim Mohamed's article on co-expressions]
 
==== Example: Function Composition ====
Line 617 ⟶ 632:
This is probably only lovable by J programmers.
 
=== An Ugly Example ===
 
The following procedure "IsFilled" was taken from the [[Sierpinski_carpet#Icon_and_Unicon|Sierpinski Carpet task]]:<lang Icon>procedure IsFilled(x,y). It has the benefit of being clear. It makes use of only a few natural contractions, augmented division and chaining of comparison operators.
Here is another example taken from [[Sierpinski_carpet|Sierpinski Carpet]] which we will explain in detail:
 
The procedure IsFilled is used to determine if the carpet is to be filled. The original version is a fairly straightforward translation of Java which in turn was translated from Python. About the only natural contraction for the language is the use of the fact that operators return values and comparisons can be chained.<lang Icon>procedure IsFilled(x,y)
while x ~= 0 & y ~= 0 do {
if x % 3 = y %3 = 1 then fail
Line 629 ⟶ 643:
end</lang>
 
We can transform this. Even if this result isn't helpful, understanding what can be done and how it works may be useful for less extreme cases.
Taken to extremes we can write the following:<lang Icon>procedure IsFilled(x,y)
 
every | ((1 = x % 3 = y %3 & break)) | (x /:= 3 & y /:= 3) | return
Firstly, we can rewrite the while condition in the following ways:<lang Icon>while x ~= 0 & y ~= 0 do { # original
until not ( x ~= 0 & y ~= 0) do { # inverted
every | (0 = (x|y) & break) | &null do { # converted to an every loop (but incomplete)</lang>
One point worth noting is that expressions normally use short circuit evaluation. This construct forces both alternatives to be generated even if the second isn't needed. If ''y'' is a complex expression with side-effects this could have unexpected results.
 
The final transformation of a while into an ''every'' expression can be useful sometimes, but its not without challenges and can produce ugly results.
 
The failing condition can also be converted as in these examples:<lang Icon>
if x % 3 = y %3 = 1 then fail # original
( x % 3 = y %3 = 1) & fail ) | &null # converted for use with every | expr</lang>
 
The ''do'' part can be converted using conjunction.<lang Icon>
x /:= 3 # original
y /:=3 # ...
( x /:= 3 & y /:=3 ) # contracted</lang>
 
Putting these together and eliminating the trailing ''return'' in favor of the default fail at end, we get the rather odd looking:<lang Icon>procedure IsFilled(x,y)
every | ( (0 = (x|y) & return) | &null,
(( x % 3 = y %3 = 1) & break ) | &null,
( x /:= 3 & y /:=3 ) )
end</lang>
 
It's tempting to remove the ''| &null'' choices and convert the conjunction ''(expr1, expr2, expr3)'' to alternations but this isn't equivalent.
How did we get to this point:
* You can convert ''while'' loops into ''every'' loops with unary alternation (| expr)
* The first expression needs to cause procedure failure when x and y mod 3 are both 1. Using break exits the loop and fails by default at the end of the procedure.
* The second alternate expression divides x and y by 3 for the next iteration. This expression always succeeds and the loop continues. While there is nothing wrong with its position here, the construction is somewhat misleading.
* The last alternative succeeds ending the procedure. Often ending an every in "| return" is a bit of a cheap trick to save a line. However, here it works because we need the implicit failure at ''end''.
 
The abovealternations iswith a&null fairlycan elegantbe ifeliminated somewhatby extremerewiring examplethe path of aalternatives contraction.with Anot somewhat more intuitive version might beexpressions:<lang Icon>procedure IsFilled(x,y)
every | (1not = x % 3(0 = (x|y %3), break) | return)) do&
(not ( x /:=% 3 &= y /:%3 = 31, break )) &
( x /:= 3 & y /:=3 )
end</lang>
 
I'll resist compressing this into a one-liner.
And lastly a contrived and somewhat grotesque version:
 
<lang Icon>procedure IsFilled(x,y)
The need for alternation with &null may require some explaining. Repeated alternation is defined as:
every (x *:= 3, y *:= 3, | (x /:= 3, y /:= 3,(x % 3 = y %3 = 1, break))) | return
<pre> |expr repeatedly evaluates expr, producing its entire result
sequence each time, but failing if evaluation of expr results
in an empty result sequence.</pre>
 
The additional alternations are required to prevent the expression from running out of results. Part of this is due to the use of ''return'' and ''break'' to exit the loop preventing further results being generated.
 
The loop can be abstracted so:
<lang Icon>every (|A()) | B() | C()</lang>
 
Without the &null alternations (or the not expressions), once the repeated alternation fails there are no more results left to generate or backtrack into and the expression must move on. In the example, neither A() nor B() would not produce any results as they exit if successful. Since C() produces only one result and that ends the evaluation.
 
Overall, this example is not a very good use of these techniques.
 
== Odds and Ends ==
This section is a catchall for a number of Odds and Ends. In some cases, the the only criteria for inclusion is that they may be found a bit odd and have no other logical home.
 
=== &fail considered harmful? ===
 
Okay, &fail is not the evil subversive scourge of programming that the GOTO was once (still is?). However, at first glance it seems to be an oddity, it's easy to wonder about it's real worth.
 
In a recent discussion, someone expressed that &fail seemed like an anchor to the notion of languages that return Boolean values. And while that isn't quite how it works the appeal of that idea, especially to people new to the language, makes sense on some gut level. '&fail' simply causes the current expression to fail. Yet, you will occasionally see it used like so:
<lang Icon>...
return &fail # &fail fails and return causes the procedure to fail.
write("Surprise!") # never executed
end</lang>
Yet, in this example:
... in which the conditional failure is moved to the bottom of the loop. The leading expressions are only evaluated once as the generated looping doesn't begin until the alternation operator. Now it's fairly common to need to initialize a variable at the beginning of a loop. This can be easily done with every, but it becomes a bit strained when performing multiple initializations.
<lang Icon>...
suspend &fail # &fail fails and suspend fails
write("Surprise!") # this time this IS executed, and the procedure fails when it runs into the 'end' statement
end</lang>
Just for completeness:
<lang Icon>...
fail &fail # is a syntax error as fail takes no expression
</lang>
As one can see this is less about the behavior of &fail as it is about the behavior of return and suspend.
 
'&fail' does have uses as can be seen in this example from [https://www.cs.arizona.edu/icon/progcorn/pc_inl21.htm| The Icon Newsletter's Programming Corner]:
<lang Icon>
# The outcome of a looping expression such as
 
while expr1 do expr2
 
# need not be failure. If a break expression in either expr1 or expr2 is evaluated,
# the outcome of the looping expression is the outcome of the argument of the break expression.
 
# It is common to omit the argument of a break expression. In this case, the argument defaults to a null value.
# Consequently, if the break expression in
 
while expr1 do {
. . .
break
. . .
}
 
# is evaluated, the outcome of the looping expression is the null value.
# In fact, if this effect is not wanted,
 
break &fail
 
# can be used to assure the outcome of the looping expression is failure.
 
# However, the argument of a break expression can be a generator. For example, if break 1 to 5
# is evaluated in a looping expression, the result sequence for the looping expression is {1, 2, 3, 4, 5}.
</lang>
 
=== Semi-colons ===
 
Unicon and Icon don't require you insert semi-colons as line terminators like some languages. Instead the compiler/translator detects the end of an expression and automatically inserts one for you. Two caveats, (1) you must insert them yourself if you wish to write multiple expressions in a line, and (2) if you split an expression across a line boundary at an operator you must leave the operator on the first line or your expression will be prematurely terminated. As follows:
<lang Icon> x := 1; y := 2; z:= -3 # 1st case
s3 := s1 ||
s2 # 2nd case - like this
s3 := s1
|| s2 # ... not this</lang>
 
The other place this comes up is writing one-liners. While not a recommended style, there are tasks that require it [[Narcissist]] and [[Quine]] are examples. Consider for example the following two programs:
<lang Icon>procedure main();sub();end;procedure sub();write("1st example");end</lang>
<lang Icon>procedure main();sub();end procedure sub();write("2nd example");end</lang>
 
It might seem natural at first to write the first example, however, no semi-colon is needed between and end and procedure declaration. The second case is correct and the first generates a compile error.
 
= Run Time Considerations =
Line 709 ⟶ 817:
== Minor Differences ==
 
There are numerous minor differences between Icon and Unicon and they are not rigorously documented. See [http://unicon.org/generator/| The Generator articles entitled: Under-documented Unicon] for more information or contribute below.
 
=== Co-expression Calling ===
Line 719 ⟶ 827:
 
=== Procedure Parameter Type Casting ===
Unicon procedure definitions allow for specification of type coercion functions and default values. TheThere proceduresare maycurrently betwo arbitrary ones not restricted to simple type conversion.cases:
* for records and structures the type of the parameter is tested
<lang Unicon>
* for types with type coercion functions (e.g. integer, real, numeric, string) the function is called to test type and perform type coercion.
procedure f1(i:integer:1,r:real,s:string,L:list,x:mycoercionproc)</lang>
<lang Unicon>procedure f1(i:integer:1,r:real,s:string,n:numeric,S:set,L:list,x:myrecordtype)</lang>
 
=== Event monitoring and cross-co-expression introspection ===
Line 734 ⟶ 843:
Unicon extended the behavior of a number of procedures.
<lang Unicon> reverse(x) # Icon x is string, Unicon x is string,list</lang>
== The Unicon Pre-processor ==
Unicon implements some of its functionality in the translator (icont) and the rest in the pre-processor (unicon). The pre-processor is typically used for syntactic enhancements like objects and parameter type checking.
 
If you are interested in seeing the code generated by the pre-processor, try the following command:
<pre>unicon -E source.icn</pre>
Anonymous user