The B Language and Method: A Guide to Practical Formal Development

Free download. Book file PDF easily for everyone and every device. You can download and read online The B Language and Method: A Guide to Practical Formal Development file PDF Book only if you are registered here. And also you can download or read online all Book PDF file that related with The B Language and Method: A Guide to Practical Formal Development book. Happy reading The B Language and Method: A Guide to Practical Formal Development Bookeveryone. Download file Free Book PDF The B Language and Method: A Guide to Practical Formal Development at Complete PDF Library. This Book have some digital formats such us :paperbook, ebook, kindle, epub, fb2 and another formats. Here is The CompletePDF Book Library. It's free to register here to get Book file PDF The B Language and Method: A Guide to Practical Formal Development Pocket Guide.

Regular expressions sit just beneath context-free grammars in descriptive power: you could rewrite any regular expression into a grammar that represents the srings matched by the expression. But, the reverse is not true: not every grammar can be converted into an equivalent regular expression. To go beyond the expressive power of context-free grammars, one needs to allow a degree of context-sensitivity in the grammar. Context-sensitivity means that terminal symbols may also appear in the left-hand sides of rules.

While this change appears small, it makes grammars equivalent to Turing machines in terms of the languages they can describe. By restricting the rules so that the the left-hand side has strictly fewer symbols than all expansions on the right, context-sensitive grammars are equivalent to decidable linear-bounded automata. Even though some languages are context-sensitive, context-sensitive grammars are rarely used for describing computer languages.

For instance, C is slightly context-sensitive because of the way it handles identifiers and type, but this context-sensitivity is resolved by a special convention, rather than by introducing context-sensitivity into the grammar. As an aside, if you think you've invented a new parsing technique, you need to check this book first. Your peer reviewers will check it. The language of languages [ article index ] [] [ mattmight ] [ rss ]. Here's a version of io. ReadFull that uses them well:. Go's defer statement schedules a function call the deferred function to be run immediately before the function executing the defer returns.

It's an unusual but effective way to deal with situations such as resources that must be released regardless of which path a function takes to return. The canonical examples are unlocking a mutex or closing a file. Deferring a call to a function such as Close has two advantages. First, it guarantees that you will never forget to close the file, a mistake that's easy to make if you later edit the function to add a new return path. Second, it means that the close sits near the open, which is much clearer than placing it at the end of the function. The arguments to the deferred function which include the receiver if the function is a method are evaluated when the defer executes, not when the call executes.

Besides avoiding worries about variables changing values as the function executes, this means that a single deferred call site can defer multiple function executions. Here's a silly example. Deferred functions are executed in LIFO order, so this code will cause 4 3 2 1 0 to be printed when the function returns. A more plausible example is a simple way to trace function execution through the program. We could write a couple of simple tracing routines like this:. We can do better by exploiting the fact that arguments to deferred functions are evaluated when the defer executes.

The tracing routine can set up the argument to the untracing routine. This example:. For programmers accustomed to block-level resource management from other languages, defer may seem peculiar, but its most interesting and powerful applications come precisely from the fact that it's not block-based but function-based. In the section on panic and recover we'll see another example of its possibilities. Go has two allocation primitives, the built-in functions new and make. They do different things and apply to different types, which can be confusing, but the rules are simple.

Let's talk about new first. It's a built-in function that allocates memory, but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it. In Go terminology, it returns a pointer to a newly allocated zero value of type T. Since the memory returned by new is zeroed, it's helpful to arrange when designing your data structures that the zero value of each type can be used without further initialization.

This means a user of the data structure can create one with new and get right to work. For example, the documentation for bytes.

  1. Corruption by Design: Building Clean Government in Mainland China and Hong Kong?
  2. Über dieses Buch.
  3. Oracle Hackers Handbook: Hacking and Defending Oracle?
  4. What is an ontology and why we need it.
  5. Stumbling Toward the Constitution: The Economic Consequences of Freedom in the Atlantic World;

Buffer states that "the zero value for Buffer is an empty buffer ready to use. Mutex does not have an explicit constructor or Init method. Instead, the zero value for a sync. Mutex is defined to be an unlocked mutex. Values of type SyncedBuffer are also ready to use immediately upon allocation or just declaration.

In the next snippet, both p and v will work correctly without further arrangement. Sometimes the zero value isn't good enough and an initializing constructor is necessary, as in this example derived from package os. There's a lot of boiler plate in there. We can simplify it using a composite literal , which is an expression that creates a new instance each time it is evaluated. Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns.

In fact, taking the address of a composite literal allocates a fresh instance each time it is evaluated, so we can combine these last two lines. The fields of a composite literal are laid out in order and must all be present. However, by labeling the elements explicitly as field : value pairs, the initializers can appear in any order, with the missing ones left as their respective zero values. Thus we could say.

As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. Composite literals can also be created for arrays, slices, and maps, with the field labels being indices or map keys as appropriate. In these examples, the initializations work regardless of the values of Enone , Eio , and Einval , as long as they are distinct. Back to allocation. The built-in function make T, args serves a purpose different from new T.

The reason for the distinction is that these three types represent, under the covers, references to data structures that must be initialized before use. A slice, for example, is a three-item descriptor containing a pointer to the data inside an array , the length, and the capacity, and until those items are initialized, the slice is nil. For slices, maps, and channels, make initializes the internal data structure and prepares the value for use. For instance,.

When making a slice, the capacity can be omitted; see the section on slices for more information. In contrast, new []int returns a pointer to a newly allocated, zeroed slice structure, that is, a pointer to a nil slice value.

Remember that make applies only to maps, slices and channels and does not return a pointer. To obtain an explicit pointer allocate with new or take the address of a variable explicitly. Arrays are useful when planning the detailed layout of memory and sometimes can help avoid allocation, but primarily they are a building block for slices, the subject of the next section.

To lay the foundation for that topic, here are a few words about arrays. The value property can be useful but also expensive; if you want C-like behavior and efficiency, you can pass a pointer to the array. Slices wrap arrays to give a more general, powerful, and convenient interface to sequences of data. Except for items with explicit dimension such as transformation matrices, most array programming in Go is done with slices rather than simple arrays. Slices hold references to an underlying array, and if you assign one slice to another, both refer to the same array. If a function takes a slice argument, changes it makes to the elements of the slice will be visible to the caller, analogous to passing a pointer to the underlying array.

A Read function can therefore accept a slice argument rather than a pointer and a count; the length within the slice sets an upper limit of how much data to read. Here is the signature of the Read method of the File type in package os :. The method returns the number of bytes read and an error value, if any. To read into the first 32 bytes of a larger buffer buf , slice here used as a verb the buffer. Such slicing is common and efficient. In fact, leaving efficiency aside for the moment, the following snippet would also read the first 32 bytes of the buffer. The length of a slice may be changed as long as it still fits within the limits of the underlying array; just assign it to a slice of itself.

The capacity of a slice, accessible by the built-in function cap , reports the maximum length the slice may assume. Here is a function to append data to a slice.

If the data exceeds the capacity, the slice is reallocated. The resulting slice is returned. The function uses the fact that len and cap are legal when applied to the nil slice, and return 0. We must return the slice afterwards because, although Append can modify the elements of slice , the slice itself the run-time data structure holding the pointer, length, and capacity is passed by value.

The idea of appending to a slice is so useful it's captured by the append built-in function. To understand that function's design, though, we need a little more information, so we'll return to it later. Go's arrays and slices are one-dimensional. To create the equivalent of a 2D array or slice, it is necessary to define an array-of-arrays or slice-of-slices, like this:.

A Guide to Practical Formal Development

Because slices are variable-length, it is possible to have each inner slice be a different length. That can be a common situation, as in our LinesOfText example: each line has an independent length. Sometimes it's necessary to allocate a 2D slice, a situation that can arise when processing scan lines of pixels, for instance.

There are two ways to achieve this. One is to allocate each slice independently; the other is to allocate a single array and point the individual slices into it. Which to use depends on your application. If the slices might grow or shrink, they should be allocated independently to avoid overwriting the next line; if not, it can be more efficient to construct the object with a single allocation. For reference, here are sketches of the two methods.

First, a line at a time:. Maps are a convenient and powerful built-in data structure that associate values of one type the key with values of another type the element or value. The key can be of any type for which the equality operator is defined, such as integers, floating point and complex numbers, strings, pointers, interfaces as long as the dynamic type supports equality , structs and arrays. Slices cannot be used as map keys, because equality is not defined on them.

Like slices, maps hold references to an underlying data structure. If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller. Maps can be constructed using the usual composite literal syntax with colon-separated key-value pairs, so it's easy to build them during initialization. Assigning and fetching map values looks syntactically just like doing the same for arrays and slices except that the index doesn't need to be an integer.

An attempt to fetch a map value with a key that is not present in the map will return the zero value for the type of the entries in the map. For instance, if the map contains integers, looking up a non-existent key will return 0. A set can be implemented as a map with value type bool. Set the map entry to true to put the value in the set, and then test it by simple indexing.

Chapter 13 Database Development Process

Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that 0 because it's not in the map at all? You can discriminate with a form of multiple assignment. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false. Here's a function that puts it together with a nice error report:.

XXI SBMF - Brazilian Symposium on Formal Methods |

To delete a map entry, use the delete built-in function, whose arguments are the map and the key to be deleted. It's safe to do this even if the key is already absent from the map. Formatted printing in Go uses a style similar to C's printf family but is richer and more general. The functions live in the fmt package and have capitalized names: fmt. Printf , fmt. Fprintf , fmt. Sprintf and so on.

The string functions Sprintf etc. You don't need to provide a format string. For each of Printf , Fprintf and Sprintf there is another pair of functions, for instance Print and Println. These functions do not take a format string but instead generate a default format for each argument. The Println versions also insert a blank between arguments and append a newline to the output while the Print versions add blanks only if the operand on neither side is a string.

In this example each line produces the same output. The formatted print functions fmt. Fprint and friends take as a first argument any object that implements the io. Writer interface; the variables os. Stdout and os. Stderr are familiar instances. Here things start to diverge from C. Moreover, that format can print any value, even arrays, slices, structs, and maps. Here is a print statement for the time zone map defined in the previous section. Note the ampersands. If you want to control the default format for a custom type, all that's required is to define a method with the signature String string on the type.

For our simple type T , that might look like this. If you need to print values of type T as well as pointers to T , the receiver for String must be of value type; this example used a pointer because that's more efficient and idiomatic for struct types. See the section below on pointers vs. Our String method is able to call Sprintf because the print routines are fully reentrant and can be wrapped this way.

There is one important detail to understand about this approach, however: don't construct a String method by calling Sprintf in a way that will recur into your String method indefinitely. This can happen if the Sprintf call attempts to print the receiver directly as a string, which in turn will invoke the method again. It's a common and easy mistake to make, as this example shows. It's also easy to fix: convert the argument to the basic string type, which does not have the method.

In the initialization section we'll see another technique that avoids this recursion. Another printing technique is to pass a print routine's arguments directly to another such routine. The signature of Printf uses the type Here is the implementation of the function log. Println we used above. It passes its arguments directly to fmt. Sprintln for the actual formatting. We write There's even more to printing than we've covered here.

See the godoc documentation for package fmt for the details. By the way, a Now we have the missing piece we needed to explain the design of the append built-in function. The signature of append is different from our custom Append function above. Schematically, it's like this:. You can't actually write a function in Go where the type T is determined by the caller. That's why append is built in: it needs support from the compiler.

What append does is append the elements to the end of the slice and return the result. The result needs to be returned because, as with our hand-written Append , the underlying array may change. This simple example. So append works a little like Printf , collecting an arbitrary number of arguments. But what if we wanted to do what our Append does and append a slice to a slice?

Easy: use This snippet produces identical output to the one above. Without that Complex structures can be built during initialization and the ordering issues among initialized objects, even among different packages, are handled correctly. Constants in Go are just that—constant.

They are created at compile time, even when defined as locals in functions, and can only be numbers, characters runes , strings or booleans. Because of the compile-time restriction, the expressions that define them must be constant expressions, evaluatable by the compiler. Sin math. Sin needs to happen at run time. In Go, enumerated constants are created using the iota enumerator. Since iota can be part of an expression and expressions can be implicitly repeated, it is easy to build intricate sets of values. The ability to attach a method such as String to any user-defined type makes it possible for arbitrary values to format themselves automatically for printing.

Although you'll see it most often applied to structs, this technique is also useful for scalar types such as floating-point types like ByteSize. The expression YB prints as 1.

  1. A Primer for Spatial Econometrics: With Applications in R.
  2. Bitter Demons!
  3. Lecture notes on general relativity;
  4. Formal Methods Teaching |

Variables can be initialized just like constants but the initializer can be a general expression computed at run time. Finally, each source file can define its own niladic init function to set up whatever state is required. Actually each file can have multiple init functions. And finally means finally: init is called after all the variable declarations in the package have evaluated their initializers, and those are evaluated only after all the imported packages have been initialized.

Besides initializations that cannot be expressed as declarations, a common use of init functions is to verify or repair correctness of the program state before real execution begins. As we saw with ByteSize , methods can be defined for any named type except a pointer or an interface ; the receiver does not have to be a struct. In the discussion of slices above, we wrote an Append function. We can define it as a method on slices instead. To do this, we first declare a named type to which we can bind the method, and then make the receiver for the method a value of that type.

This still requires the method to return the updated slice. We can eliminate that clumsiness by redefining the method to take a pointer to a ByteSlice as its receiver, so the method can overwrite the caller's slice. In fact, we can do even better. If we modify our function so it looks like a standard Write method, like this,. Writer , which is handy. For instance, we can print into one. The rule about pointers vs. This rule arises because pointer methods can modify the receiver; invoking them on a value would cause the method to receive a copy of the value, so any modifications would be discarded.

The language therefore disallows this mistake. There is a handy exception, though. When the value is addressable, the language takes care of the common case of invoking a pointer method on a value by inserting the address operator automatically. In our example, the variable b is addressable, so we can call its Write method with just b.

Write for us. By the way, the idea of using Write on a slice of bytes is central to the implementation of bytes. Interfaces in Go provide a way to specify the behavior of an object: if something can do this , then it can be used here. We've seen a couple of simple examples already; custom printers can be implemented by a String method while Fprintf can generate output to anything with a Write method.

Interfaces with only one or two methods are common in Go code, and are usually given a name derived from the method, such as io. Writer for something that implements Write. A type can implement multiple interfaces. For instance, a collection can be sorted by the routines in package sort if it implements sort. Interface , which contains Len , Less i, j int bool , and Swap i, j int , and it could also have a custom formatter. In this contrived example Sequence satisfies both. The String method of Sequence is recreating the work that Sprint already does for slices.

We can share the effort and also speed it up if we convert the Sequence to a plain []int before calling Sprint. This method is another example of the conversion technique for calling Sprintf safely from a String method. Because the two types Sequence and []int are the same if we ignore the type name, it's legal to convert between them. The conversion doesn't create a new value, it just temporarily acts as though the existing value has a new type. There are other legal conversions, such as from integer to floating point, that do create a new value.

It's an idiom in Go programs to convert the type of an expression to access a different set of methods. As an example, we could use the existing type sort. IntSlice to reduce the entire example to this:. Now, instead of having Sequence implement multiple interfaces sorting and printing , we're using the ability of a data item to be converted to multiple types Sequence , sort.

IntSlice and []int , each of which does some part of the job. That's more unusual in practice but can be effective. Type switches are a form of conversion: they take an interface and, for each case in the switch, in a sense convert it to the type of that case.

Here's a simplified version of how the code under fmt. Printf turns a value into a string using a type switch. If it's already a string, we want the actual string value held by the interface, while if it has a String method we want the result of calling the method. The first case finds a concrete value; the second converts the interface into another interface. It's perfectly fine to mix types this way. What if there's only one type we care about? If we know the value holds a string and we just want to extract it?

It could be two friends chatting to each other interactional and ordering a meal transactional. Real interaction patterns Teach real interaction patterns. Introduce the following basic interactional pattern: Initiate, Respond, Follow-up. This is a simplification of Amy Tsui's work. See Tsui The following interaction could be analysed as follows: A: What did you do last night?

A Guide to Practical Formal Development

Follow-up What did you see? Initiate A: No it's difficult with the kids Respond B: Yeah of course follow-up Understanding spoken English After a listening exercise give students the tapescript. Using part of it, students mark the stressed words, and put them into groups tone units. You can use phone numbers to introduce the concept of tone units. The length of a tone unit depends on the type of spoken text. Compare a speech with an informal conversation. In the same lesson or subsequent listening lessons you can focus on reductions in spoken speech, for example, linking, elision and assimilation.

Preparation and rehearsal Before a spoken task, give students some preparation and rehearsal time. Students will need guidance on how to use it. A sheet with simple guidelines is effective. Real-life tasks Try to use real-life tasks as part of your teaching. Brown and Yule suggest the following: When teaching spoken language, focus on teaching longer transactional turns.

This is because native speakers have difficulty with them and because students need to be able to communicate information efficiently whether in their country or in a native-speaker country. Teach interactional language by using an awareness-raising approach. For example, with monolingual classes by listening to a recorded L1conversation before a similar L2 recording. For recordings of native-speaker interactional and transactional conversations, have a look at 'Exploring Spoken English' by McCarthy and Carter It not only contains a variety of text types, but each recording comes with analysis.

Imagine you have been working on the language that would be useful for the following task: 'Having a conversation with a stranger on public transport'. You have now reached the stage where you wish students to perform the task. Rather than just give students 10 minutes to prepare and rehearse the task, give students guided preparation time.

A simple preparation guide for the task could be a few key questions like: How will you start the conversation? What topics are you going to talk about? How are you going to move from one topic to another? How are you going to end the conversation?