
Loyola University Chicago Loyola eCommons Computer Science: Faculty Publications and Other Works Faculty Publications 9-2009 Scientific Programming: The Promises of Typed, Pure, and Lazy Functional Programming: Part II Konstantin Läufer Loyola University Chicago, [email protected] George K. Thiruvathukal Loyola University Chicago, [email protected] Follow this and additional works at: https://ecommons.luc.edu/cs_facpubs Part of the Computer Sciences Commons Recommended Citation K. Laufer and G. K. Thiruvathukal, "Scientific Programming: The Promises of Typed, Pure, and Lazy Functional Programming: Part II," in Computing in Science & Engineering, vol. 11, no. 5, pp. 68-75, Sept.- Oct. 2009. doi: 10.1109/MCSE.2009.147 This Article is brought to you for free and open access by the Faculty Publications at Loyola eCommons. It has been accepted for inclusion in Computer Science: Faculty Publications and Other Works by an authorized administrator of Loyola eCommons. For more information, please contact [email protected]. This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License. Copyright © 2009 Konstantin Läufer and George K. Thiruvathuka S cieNTIFic P ROGRAMMING Editors: Konstantin Läufer, [email protected] Konrad Hinsen, [email protected] THE PROMISES OF TY P ED, PURE , AND LAZY FUNC T IONA L PROGRAMMING : PAR T II By Konstantin Läufer and George K. Thiruvathukal This second installment picks up where Konrad Hinsen’s article “The Promises of Functional Programming” from the July/August 2009 issue left off, covering static type inference and lazy evaluation in functional programming languages. n the first installment in this series first installment,1 we can create a list but we can’t prepend an element to an- on functional programming, Kon- from some elements and then prepend other element Irad Hinsen introduced the func- an element to that list: tional programming paradigm, which Integer i = new Integer(4); encourages recursion and higher-order user=> (cons 3 (list 4)) i.add(3); functional abstraction in algorithms. (3 4). In this second installment, we explore or several other aspects of the functional However, we can’t prepend an element paradigm. Using examples in the Clo- to another element List<Integer> l = new jure, Java, and Haskell languages, we Integer(4); discuss some of the benefits of static user=> (cons 3 4) l.add(3); typing with type inference and pure, java.lang. side-effect-free functional program- IllegalArgumentException: In the first case, the error message ming with lazy evaluation. In particu- Don’t know how to create ISeq is The method add(int) is un- lar, we argue that these features make from: Integer defined for the type Integer, Haskell a compelling choice for gen- while in the second case, it’s Type eral software development. The scien- because the predefined cons function mismatch: cannot convert from tific computing community, however, requires its second argument to be of a Integer to List<Integer>. Java’s will likely require better numeric li- list type. Clojure’s type system de- type system detected these errors, brary support and efficient functional tected the attempt to invoke the func- reported them while we were edit- versions of scientific algorithms before tion on an argument of the wrong type, ing or compiling the program con- accepting Haskell more widely. reported a type error, and stopped pro- taining this code, and refused to let gram execution. Clojure uses dynamic us run it. Java uses static typing: type Dynamic and Static Typing typing: type errors don’t get detected errors are detected at compile time Type systems in programming lan- until the program executes. Other lan- and programs with type errors won’t guages ensure that we correctly use guages with dynamic typing include even compile. Other languages that every program element according to its Groovy, JavaScript, Lisp, Objective- use static typing include Ada, C, C++, type—that is, according to the abstrac- C, Perl, Python, Ruby, Scheme, and C#, Fortran, Haskell, Java, ML, Pas- tion the program element represents. Smalltalk. cal, and Scala. Among those, the ones Typically, numeric values participate Now, let’s look at the behavior of that also support higher-order fea- in arithmetic operations and compari- Java’s type system. We can create a list tures such as first-class functions (C#, sons, lists participate in element access from some elements and then prepend Haskell, ML, and Scala) or first-class and concatenation, and so on. an element to that list objects (Ada, C#, Java, and Scala) are First, let’s look at type system be- called higher-order typed, or HOT. havior in Clojure, a modern LISP List<Integer> l = Arrays. Assuming a sound type system, dialect that runs on the Java Virtual asList(4); static typing represents a conservative Machine. As Hinsen showed in the l.add(3); approach: a program will be allowed to 68 Copublished by the IEEE CS and the AIP 1521-9615/09/$26.00 © 2009 IEEE COMPUTING IN SC IEN C E & ENGINEERING ON TYPECAS T ING AND In this example, we mix strings and real URL objects CO NVERSI O NS within the same collection. We then iterate through the collection and do something with the strings. We use the ven in typed languages such as C++, C#, and Java, we instanceof operator to determine which objects are Emust sometimes convert a numeric value from one strings, cast them from type Object to the more specific type to another. When going from 16-bit integer to a type String, and do something string-specific, such as 32-bit integer, for example, there’s no loss of information, creating a URL from it. If we hadn’t used the instanceof and it’s safe to just let the conversion happen implicitly. In operator, the cast would have failed as soon as the iteration the other direction, however, part of the original number reached the URL instance. might get lost and conversion should happen only if the Casts from a more general to a more specific type can programmer takes responsibility. The programmer takes fail at runtime—as, for example, when an object isn’t of this responsibility using a typecast—or simply, cast— the expected specific type or a more specific type.T here- construct. In the following Java snippet, for example, the fore, we note that only programs without casts are guaran- last line would cause a compile-time error without the cast: teed to be free of type errors at runtime. By contrast, casts in the opposite direction (from a specific to a more general int i = 25; class) can never fail, so they don’t need a runtime check. float x = i; Finally, casts between unrelated classes, such as String int k = (int) f; to Integer, can never succeed, so they always cause a compile-time type error. In contrast, Haskell provides such conversions using ex- Casting versus conversion functions was a huge sub- plicit conversion functions. In the equivalent situation, for ject of debate in the C++ community back when cycles example, we could choose from among ceiling, floor, were precious and any stealth data “transformation” (no round, and truncate. matter how trivial) could incur a substantial performance There are similar situations where programmers think overhead. (This was due to the copy-construction cascad- they know far more about a certain object’s type than the ing effect, which is no longer an issue in most modern compiler could possibly know. Such a situation might arise object-oriented languages as they typically copy refer- with heterogeneous, predefined type collections, where ences instead of values.) Today, however, casting is often a programmers are unable to define a specific common ab- liability that actually causes runtime typing errors—even in straction after the fact (another would be to define wrap- programming languages with well-founded type systems pers with a common interface for the predefined types): like Java. Worse, it’s well known (especially among seasoned C/C++ programmers such as ourselves) that not all casts List<Object> links = should be allowed. For example, there is a natural promo- new ArrayList<Object>(); tion of short -> int -> long -> long long (in C) that links.add(“http://www.computer.org/cise”); is lossless; however, the reverse transformation is unnatu- links.add(new URL(“http://cise.aip.org/”)); ral, highly error-prone, and nonportable, especially in a //... heterogeneous computing world that still features 16-, 32-, for (final Object o : links) and 64-bit processors. Using conversion functions (instead if (o instanceof String) { of casts) lets you ensure that all meaningful conversions are String s = (String) o; performed correctly (forward and backward, by making all URL link = new URL(s); down conversions explicit and precise) with only a slight // do something with the link inconvenience to the programmer (and inlining can help } alleviate most performance issues). run only if we can guarantee that it’s checker would still reject the follow- That might seem a little restrictive; free of type errors. Thus, a program ing program, even though the errone- dynamically typed languages would that passes type checking is guaran- ous code would always be skipped: have no complaints about it. But sup- teed not to fail at runtime because of pose the conditional expression is type errors (with some restrictions, as if (3 > 4) { much more complex and evaluates to we discuss in the sidebar “On Type- List<Integer> l = new true on some rare occasions as part of casting and Conversions”). Because Integer(4); some mission-critical software—such conditions aren’t evaluated until run- l.add(3); as air-traffic control, Internet routers, time, for example, the static type } and ATM machines—where every SEPTEMBER /OC TOBER 2009 69 S cieNTIFic P ROGRAMMING single line of code, reachable or not, It’s important to distinguish this from Let’s see how this works out in must be checked before it’s embedded what happens in languages like Py- Haskell (using the Glasgow Haskell and deployed on a large scale.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages9 Page
-
File Size-