• No se han encontrado resultados

5.1 Análisis de los tiempos invisibles y no productivos

5.1.1 Análisis del Taladro CCDC 36

5.1.1.5 Tiempos invisibles de la Categoría 4 en la Sección 12 ¼‖

Labeled, unlabeled, and optional arguments can be mixed in many different combina- tions. However, there are some rules of thumb to follow.

• An optional parameter should always be followed by a non-optional parameter (usually unlabeled).

• The order of labeled arguments does not matter, except when a label occurs more than once.

• Labeled and optional arguments should be specified explicitly for higher-order functions.

The reason for following an optional parameter with an unlabeled one is that, oth- erwise, it isn’t possible to know when an optional argument has been omitted. The compiler produces a warning for function definitions with a final optional parameter.

# let f ~x ?(y = 1) = x - y;;

Characters 15-16:

Warning X: this optional argument cannot be erased. let f ~x ?(y = 1) = x - y;;

^

val f : x:int -> ?y:int -> int = <fun>

There is a slight difference between labeled and unlabeled arguments with respect to optional arguments. When an optional argument is followed only by labeled arguments, then it is no longer possible to omit the argument. In contrast, an unlabeled argument “forces” the omission.

# let add1 ?(x = 1) ~y ~z = x + y + z;;

val add1 : ?x:int -> y:int -> z:int -> int = <fun>

# add1 ~y:2 ~z:3;;

- : ?x:int -> int = <fun>

# let add2 ?(x = 1) ~y z = x + y + z;;

val add2 : ?x:int -> y:int -> int -> int = <fun>

# add2 ~y:2 3;;

- : int = 6

It is legal for a label to occur more than once in an argument list. If it does, then the arguments with that label are bound in the same order as the corresponding parameters.

# let h ~x:i ~x:j ?(y = 1) ~z = i * 1000 + j * 100 + y * 10 + z;;

val h : x:int -> x:int -> ?y:int -> z:int -> int = <fun>

# h ~z:3 ~x:4 ~y:5 ~x:6;;

CHAPTER 3. VARIABLES AND FUNCTIONS3.3. LABELED PARAMETERS AND ARGUMENTS For the final rule, explicit annotation for higher-order functions, consider the following definition of a functionapply.

# letapply g = g ~x:1 2 + 3;;

val apply : (x:int -> int -> int) -> int = <fun>

Note that the compiler infers that the function~ghas a labeled, not an optional argu-

ment. The syntaxg ~x:1is the same, regardless of whether the labelxis labeled or

optional, but the two are not the same. #apply (fun ?(x = 0) y -> x + y);;

Characters 6-31:

apply (fun ?(x = 0) y -> x + y);; ^^^^^^^^^^^^^^^^^^^^^^^^^

This function should have type x:int -> int -> int but its first argument is labeled ~?x

The compiler will always prefer to infer that an argument is labeled, not optional. If you want the other behavior, you can specify the type explicitly.

# letapply (g : ?x:int -> int -> int) = g ~x:1 2 + 3;;

val apply : (?x:int -> int -> int) -> int = <fun>

#apply (fun ?(x = 0) y -> x + y);;

3.4. EXERCISES CHAPTER 3. VARIABLES AND FUNCTIONS

3.4 Exercises

Exercise 3.1 Which of the following let-expressions is legal? For each expression that is legal, give its type and the value that it evaluates to. Otherwise, explain why the expression is not legal.

1. let x = 1 in x

2. let x = 1 in let y = x in y

3. let x = 1 and y = x in y

4. let x = 1 and x = 2 in x

5. let x = 1 in let x = x in x

6. let a’ = 1 in a’ + 1

7. let ’a = 1 in ’a + 1

8. let a’b’c = 1 in a’b’c

9. let x x = x + 1 in x 2 10. let rec x x = x + x in x 2 11. let (++) f g x = f (g x) in let f x = x + 1 in let g x = x * 2 in (f ++ g) 1 12. let (-) x y = y - x in 1 - 2 - 3 13. let rec (-) x y = y - x in 1 - 2 - 3 14. let (+) x y z = x + y + z in 5 + 6 7 15. let (++) x = x + 1 in ++x

Exercise 3.2 What are the values of the following expressions? 1. let x = 1 in let x = x + 1 in x 2. let x = 1 in let f y = x in let x = 2 in f 0 3. let f x = x - 1 in let f x = f (x - 1) in f 2

CHAPTER 3. VARIABLES AND FUNCTIONS 3.4. EXERCISES 4. let y = 2 in

let f x = x + y in

let f x = let y = 3 in f y in

f 5

5. let rec factorial i =

if i = 0 then 1 else i * factorial (i - 1)

in

factorial 5

Exercise 3.3 Write a functionsumthat, given two integer boundsnandmand a function f, computes a summation.

sum n m f = Pmi=nf(i).

Exercise 3.4 Euclid’s algorithm computes the greatest common divisor (GCD) of two integers. It is one of the oldest known algorithms, appearing in Euclid’sElementsin roughly 300 BC. It can be defined in pseudo-code as follows, where represents assignment. gcd(n, m) = whilem6= 0 if n > m n←n−m else m←m−n return n

Write an OCaml function %% that computes the GCD using Euclid’s algorithm (so n %% mis the GCD of the integersnandm). You should define it without assignment, as

a recursive function. [Note, this is Euclid’s original definition of the algorithm. More modern versions usually use a modulus operation instead of subtraction.]

Exercise 3.5 Suppose you have a function on integersf : int -> intthat is mono-

tonically increasing over some range of arguments from 0 up to n. That is, f i < f (i + 1)for any 0 i < n. In additionf 0 < 0 andf n > 0. Write a

functionsearch f nthat finds the smallest argumentiwheref i 0.

Exercise 3.6 Adictionaryis a data structure that represents a map from keys to values. A dictionary has three operations.

• empty : dictionary

• add : dictionary -> key -> value -> dictionary

• find : dictionary -> key -> value

The valueemptyis an empty dictionary; the expressionadd dict key valuetakes an

existing dictionarydictand augments it with a new bindingkey -> value; and the

expressionfind dict keyfetches the value in the dictionarydictassociated with the key.

3.4. EXERCISES CHAPTER 3. VARIABLES AND FUNCTIONS One way to implement a dictionary is to represent it as a function from keys to values. Let’s assume we are building a dictionary where the key type isstring, the

value type isint, and the empty dictionary maps every key to zero. This dictionary can be implemented abstractly as follows, where we write7→for the map from keys to values.

empty = key7→0

add(dict,key, v) = key07→

½

v ifkey0=key

dict(key) otherwise

find(dict,key) = dict(key) 1. Implement the dictionary in OCaml.

2. Suppose we have constructed several dictionaries as follows. let dict1 = add empty "x" 1

let dict2 = add dict1 "y" 2 let dict3 = add dict2 "x" 3 let dict4 = add dict3 "y" 4

What are the values associated with"x"and"y"in each of the four dictionaries?

Exercise 3.7 Partial application is sometimes used to improve the performance of a multi-argument function when the function is to be called repeatedly with one or more of its arguments fixed. Consider a functionf(x, y)that is to be called multiple times withxfixed. First, the function must be written in a formf(x, y) =h(g(x), y)from some functionsgandh, wheregrepresents the part of the computation that uses only the valuex. We then write it in OCaml as follows.

let f x =

let z = g(x) in fun y ->h(z, y)

Callingf on its first argument computesg(x)and returns a function that uses the value (without re-computing it).

Consider one root of a quadratic equation ax2+bx+c = 0 specified by the quadratic formula r(a, b, c) = −b+√b24ac

2a . Suppose we wish to to evaluate the

quadratic formula for multiple values of awith b andc fixed. Write a function to compute the formula efficiently.

Exercise 3.8 Astreamis an infinite sequence of values supporting an operationhd(s)

that returns the first value in the streams, andtl(s)that returns a new stream with the first element removed.

One way to implement a stream is to represent it as a function over the nonnegative integers. Given a streams : int -> int, the first element is(s 0), the second is

(s 1),etc. The operations are defined as follows. let hd s = s 0

CHAPTER 3. VARIABLES AND FUNCTIONS 3.4. EXERCISES For this exercise, we’ll assume that we’re working with streams of integers, so the type

streamisint -> int. We’ll write a stream as a sequence(x0, x1, x2, . . .). 1. Define the following stream functions.

• (+:) : stream -> int -> stream. Add a constant to a stream. (x0, x1, x2, . . .) +: c = (x0+c, x1+c, x2+c, . . .).

• (-|) : stream -> stream -> stream. Subtract two streams pointwise.

(x0, x1, x2, . . .) -| (y0, y1, y2, . . .) = (x0−y0, x1−y1, x2−y2. . . .). • map : (int -> int) -> stream -> stream.

Apply a function to each element of the stream.

map f (x0, x1, x2, . . .) = (f x0, f x1, f x2, . . .). 2. A “derivative” function can be defined as follows.

let derivative s = tl s -| s

Define a functionintegral : stream -> streamsuch that, for any streams, integral (derivative s) = s +: cfor some constantc.

Chapter 4

Basic pattern matching

One of ML’s more powerful features is the use ofpattern matchingto define computa- tion by case analysis. Pattern matching is specified by amatchexpression, which has

the following syntax. matchexpression with

| pattern1 -> expression1 | pattern2 -> expression2 . . . | patternn -> expressionn

The first vertical bar|is optional.

When amatchexpression is evaluated, the expressionexpression to be matched is first evaluated, and its value is compared with the patterns in order. If patterni is

the first pattern to match the value, then the expressionexpressioni is evaluated and

returned as the result of thematch.

A simple patternis an expression made of constants and variables. A constant pattern c matches values that are equal to it, and a variable patternx matches any expression. A variable patternxis a binding occurrence; when the pattern match is successful, the variablexis bound the the value being matched.

For example, Fibonacci numbers can be defined succinctly using pattern matching. Fibonacci numbers are defined inductively: fib 0 = 0,fib 1 = 1, and for all other

natural numbersi,fib i = fib (i - 1) + fib (i - 2).

# let recfib i = match iwith

0 -> 0 | 1 -> 1

| j -> fib (j - 2) + fib (j - 1);;

val fib : int -> int = <fun>

#fib 1;; - : int = 1 #fib 2;; - : int = 1 #fib 3;; - : int = 2

4.1. FUNCTIONS WITH MATCHINGCHAPTER 4. BASIC PATTERN MATCHING # fib 6;;

- : int = 8

In this code, the argumentiis compared against the constants 0 and 1. If either of these cases match, the return value is equal toi. The final pattern is the variablej, which matches any argument. When this pattern is reached,jtakes on the value of the argument, and the bodyfib (j - 2) + fib (j - 1)computes the returned value.

Note that variables occurring in a pattern are always binding occurrences. For example, the following code produces a result you might not expect. The first case matches all expressions, returning the value matched. The toploop issues a warning for the second and third cases.

# let zero = 0;; # let one = 1;; # let rec fib i =

matchi with zero -> zero | one -> one

| j -> fib (j - 2) + fib (j - 1);;

Characters 57-60:

Warning: this match case is unused. Characters 74-75:

Warning: this match case is unused. | one -> one

^^^

| j -> fib (j - 2) + fib (j - 1);; ^

val fib : int -> int = <fun>

# fib 1;;

- : int = 1

# fib 2002;;

- : int = 2002

4.1 Functions with matching

It is quite common for the body of an ML function to be a match expression. To

simplify the syntax somewhat, OCaml allows the use of the keywordfunction(instead

offun) to specify a function that is defined by pattern matching. Afunctiondefinition

is like afun, where a single argument is used in a pattern match. Thefibdefinition

usingfunctionis as follows.

# let rec fib =function 0 -> 0

| 1 -> 1

| i -> fib (i - 1) + fib (i - 2);;

val fib : int -> int = <fun>

# fib 1;;

- : int = 1

# fib 6;;

CHAPTER 4. BASIC PATTERN MATCHING 4.2. PATTERN EXPRESSIONS

Documento similar