Closely related to the notion of type is that of class, which, roughly, is a kind of factory for instantiating objects that have a particular internal structure. Some languages have no classes, some conflate the notion of class and type, and some take great care to distinguish classes from types. Many languages provide a means for throwing or raising an exception when something has gone wrong, and a means to catch, or handle, thrown exceptions. Languages without an exception facility will often have a means to allow certain operations to return two values, one indicating success or failure, and the other for the expected value on success. You may also encounter option values, in which the value itself is tagged with an indication of it being a proper value or an error value. Modern languages support the notion of programming-in-the-large via modules or packages, which encapsulate strongly related entities of a library or application.
The programmer may export some of the entities to the rest of the program, leaving the others private to the module. There are, of course, many more language elements that we need to learn. It would be a tragedy, he says, if people were to miss these and other ideas, or worse, to simply master one way of programming and forget that they could ever have new ideas about programming models. After the obligatory introductory chapter outlining the book's goals and objectives, we present 12 chapters covering 12 languages. We've carefully chosen the order of languages to make a story out of the book. We start with JavaScript because it is extremely popular and full of modern and interesting features, including first-class functions, prototypes, and promises.
It has influenced hundreds of successors, including our second language, CoffeeScript. The next three languages, Lua, Python, and Ruby, are general-purpose scripting languages. They are followed by Julia, whose treatment of dynamic polymorphism via generic functions and multimethods contrasts nicely with Ruby's classes.
We then take a quick look at Java, a popular language in the enterprise computing space, and our first statically-typed language. Java was introduced along with the Java platform, which includes a virtual machine and a very extensive set of powerful libraries for just about every computing task imaginable. Hundreds of languages are targeted to this platform, including our next language, Clojure. Clojure will introduce us to a mostly-functional view of the world, with persistent data structures and software transactional memory.
Next up is Elm, which, like Java, is statically typed, but with an incredibly powerful type inference mechanism. We continue with Erlang, a functional language like Clojure and Elm, specifically designed for building large-scale, highly reliable systems. Our last two languages require a bit of memory management knowledge on the part of the programmer. First we visit Go, a language with explicit pointers and designed, like Erlang, with highly concurrent and distributed applications in mind. Occasionally we'll suggest that you write more substantial scripts, research various aspects of the language not covered in the chapter proper, or ask you to do some comparisons between languages.
2.2 Functions 2.2.1 General As in all programming languages, in Python a function is a block of code that performs a specific task, and that can be called several times by other parts of the program. We have already met the import command in several occasions. Some relevant mathematical functions available in Python are listed in Appendix A. You can also write your own functions to perform specialized tasks. Unlike older high-level programming languages, and as in C/C++, in Python there is no distinction between functions and subroutines.
The code of a Python function begins with a def statement and, if it must return values, ends with a return statement. The commands in the function definition are not executed as Python first passes over the lines, but only when the function is called by another part of the script. A function can have any number of arguments, including zero.
Elm is a functional language ideal for interactive applications. Like CoffeeScript, Elm applications transpile to JavaScript. But while CoffeeScript looks like Python or Ruby—with dynamic typing and assignable variables—Elm is part of the statically-typed "ML family" of languages, and borrows a little from Haskell. Elm will be the only ML language we will feature in this book, so take the time to enjoy the many features it offers. In this chapter we'll visit many of the ideas originating in the design and development of the ML languages, including type variables and extensive type inference.
We'll also encounter pattern matching and destructuring. Haskell programmers may find much of Elm quite familiar. It adds many new features of its own and fuses old and new ideas quite nicely. Elm also differs from JavaScript by living very far to the "pure" side of the functional language spectrum. Data structures are persistent, like those of Clojure.
We'll begin our exploration of Elm with our three standard introductory programs, running in the browser, since Elm doesn't usually script standard input and standard output. We'll then look at base language elements including modules, functions, and types. Additional Languages ■ 281 only later adopted, has yet to adopt, or may never adopt. It prohibits compilation of code in which local variables are not assigned, but guarantees initialization of certain other variables, including instance variables. In addition, programmers find many conveniences such as properties , namespaces, list comprehensions, operator overloading, and metaprogramming capabilities.
If you answer yes, give an example of a macro which cannot be easily simulated by regular "run-time" code that may, of course, use unevaluated expression objects. If you answer no, show how to duplicate the functionality of each of the macros defined in this chapter. 6.21 The variables generated during Julia's hygienic macro expressions start with the hash (#) character.
Why is this not problematic, given that the hash character begins comments in Julia source code? 6.22 Design a macro for an "until statement," similar to the "unless statement" presented in this chapter. 6.23 We did not cover coroutines in this chapter, so here is your chance to learn about them. Create two tasks, one that produces a million random integers in the range 0..99, and another that consumes these values by histogramming them into buckets for the values 0–9, 10–19, 20–29, and so on. 6.24 What are the possible status values of a Julia task?
How do these compare to the statuses of Lua's coroutines? 6.25 In the REPL, the return value of a remote call will display something like RemoteRef. 6.26 If you are on a Unix or Unix-like system with multiple cores, run a π-approximation script from this chapter under the Unix time command. You should notice that the real time is less than the user time. Experiment with different values of arguments to addprocs.
6.27 Research Julia's shared arrays and create an example that illustrates their usefulness. Java 1.3 This was primarily a maintenance release, focused on bug fixes, stability, and performance improvements. This release also brought in the HotSpot Java Vir‐ tual Machine, which is still in use today . Java 5 This large release of Java introduced a number of changes to the core language itself including generic types, enumerated types , annotations, varargs methods, autoboxing, and a new for loop. These changes were considered sig‐ nificant enough to change the major version number, and to start numbering as major releases.
This release included 3,562 classes and interfaces in 166 packages. Notable additions included utilities for concurrent programming, a remote management framework, and classes for the remote management and instrumentation of the Java VM itself. Java 6 This release was also largely a maintenance and performance release. It intro‐ duced the Compiler API, expanded the usage and scope of annotations, and provided bindings to allow scripting languages to interoperate with Java. There were also a large number of internal bug fixes and improvements to the JVM and the Swing GUI technology. Java 7 The first release of Java under Oracle's stewardship included a number of major upgrades to the language and platform.
Finding Area Of A Circle Using Circumference The introduction of try-with-resources and the NIO.2 API enabled developers to write much safer and less error-prone code for handling resources and I/O. The Method Handles API provided a simpler and safer alternative to reflection; in addition, it opened the door for invokedynamic (the first new bytecode since version 1.0 of Java). Java 8 This was a huge release—potentially the most significant changes to the lan‐ guage since Java 5 . Other major updates include a new date and time API, and major updates to the concurrency libraries. As a result, you must be careful to put any addition expressions in parentheses when combining them with string concatenation.
If you do not, the addition opera‐ tor is interpreted as a concatenation operator. Java has built-in string conversions for all primitive types. An object is converted to a string by invoking its toString() method. Some classes define custom toString() methods so that objects of that class can easily be converted to strings in this way.
An array is converted to a string by invoking the built-in toString() method, which, unfortunately, does not return a useful string representation of the array contents. Free; return 0; A string in C is a pointer to a block of memory. The "characters" of the string are the bytes1 of this memory block, up to, but not including, the first zero byte. Command line arguments are given as pointers into read only memory, so we must allocate a copy of our string that we will mutate as we generate our permutations. We need to allocate one byte more than the length of the string in order to copy over the zero byte that terminates the string.
No garbage collector will reclaim this memory, so we must call free ourselves. As we saw in Go, we can make pointers to objects using & and pass these pointers as arguments to other functions, as we've done in our swap function. C will not, as will Go, perform escape analysis on pointers to local variables and expressions and choose heap allocation for escaped objects.
Passing pointers to local variables into contexts that outlive the function owning the locals is asking for trouble! A compiler may emit a warning, but won't stop you from running such problematic, insecure code. At runtime, the function's frame can, and probably will, go away and leave the pointer dangling. It has a richer set of data structures than the original Lisp. It does a better job than most other Lisp dialects in isolating side effects and implementing concurrent features. Clojure interoperates with Java, so your Clojure program has access to the entire Java platform.
We'll then look at Clojure's various approaches to concurrency (one of the language's great strengths) visiting refs, agents, and software transactional memory. We'll close our tour with a look at the macro system, which takes advantage of Clojure's representation of code as data, and is considered by many to be the essential ingredient of any Lisp dialect. Java is a fairly classic example of a statically typed language. JavaScript is an example of a dynamically typed language that allows any variable to store any type of value. We have already met arrays and classes, two of Java's most widely used kinds of ref‐ erence type. This chapter starts by discussing another very important kind of refer‐ ence type—interfaces.
We then move on to discuss Java's generics, which have a major role to play in Java's type system. With these topics under our belts, we can discuss the differences between compile-time and runtime types in Java. To complete the full picture of Java's reference types, we look at specialized kinds of classes and interfaces—known as enums and annotations. We conclude the chapter by looking at lambda expressions and nested types, and then reviewing how enhanced type inference has allowed Java's non-denotable types to become usable by programmers. Reference Type Conversions Object references can be converted between different reference types.
As with prim‐ itive types, reference type conversions can be widening conversions (allowed auto‐ matically by the compiler) or narrowing conversions that require a cast . In order to understand reference type conversions, you need to understand that reference types form a hierarchy, usually called the class hierarchy. Every Java reference type extends some other type, known as its superclass. A type inherits the fields and methods of its superclass and then defines its own additional fields and methods.
A special class named Object serves as the root of the class hierarchy in Java. All Java classes extend Object directly or indirectly. The Object class defines a number of special methods that are inherited by all objects. The predefined String class and the Point class we discussed earlier in this chapter both extend Object.
Thus, we can say that all String objects are also Object objects. We can also say that all Point objects are Object objects. We cannot say that every Object is a String because, as we've just seen, some Object objects are Point objects.
Java Programs from the Top Down Before we begin our bottom-up exploration of Java syntax, let's take a moment for a top-down overview of a Java program. Java programs consist of one or more files, or compilation units, of Java source code. Near the end of the chapter, we describe the structure of a Java file and explain how to compile and run a Java program. Each compilation unit begins with an optional package declaration followed by zero or more import declarations.
These declarations specify the namespace within which the compilation unit will define names, and the namespaces from which the compi‐ lation unit imports names. We'll see package and import again later in this chapter in "Packages and the Java Namespace" on page 94. The optional package and import declarations are followed by zero or more refer‐ ence type definitions. We will meet the full variety of possible reference types in Chapters 3 and 4, but for now, we should note that these are most often either class or interface definitions. Within the definition of a reference type, we will encounter members such as fields, methods, and constructors. Meth‐ ods are blocks of Java code composed of statements.
With these basic terms defined, let's start by approaching a Java program from the bottom up by examining the basic units of syntax—often referred to as lexical tokens. Go also contains the interesting goto statement, though with limited capabilities compared to the unrestricted goto much maligned throughout the years. • Go is the first language in this text where pointers are explicitly marked in the syntax. We can in Go refer to the reference and the referent separately. Pointers are used where sharing is required, and sometimes simply as a convenience to avoid copying arrays and structs. • Go performs escape analysis during compilation to determine whether pointers to local variables or temporary expressions will outlive the function activation in which they were defined.
If so, the Go runtime will ensure the corresponding referents will be heap-allocated. There is no tuple type in Lua; functions actually can return multiple values. Local variables are introduced with the keyword local. Their scope begins on the statement after their declaration and runs until the end of the block.
While this rule is simple, it does mean the programmer must take care in creating local recursive functions. • Tables are used for both classic arrays (1-based sequences of numerically indexed values) and dictionaries (sets of key-value pairs). Both numeric and non-numeric indexed values can be mixed in a single table; it is up to the language implementation to keep the "array-part" access efficient. PREREQUISITIES This book is not for beginning programmers. We're assuming you know at least two languages pretty well, and hopefully a couple more. We will be covering many interesting features, and purposely do so with code that is often very dense, and sometimes cryptic, even when presenting unfamiliar paradigms for the first time.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.