Changes in doc/rob_thesis/intro.tex [f92aa32:9c14ae9]
- File:
-
- 1 edited
-
doc/rob_thesis/intro.tex (modified) (33 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/rob_thesis/intro.tex
rf92aa32 r9c14ae9 5 5 \section{\CFA Background} 6 6 \label{s:background} 7 \CFA \footnote{Pronounced ``C-for-all'', and written \CFA or Cforall.} is a modern non-object-orientedextension to the C programming language.7 \CFA is a modern extension to the C programming language. 8 8 As it is an extension of C, there is already a wealth of existing C code and principles that govern the design of the language. 9 9 Among the goals set out in the original design of \CFA, four points stand out \cite{Bilson03}. … … 16 16 Therefore, these design principles must be kept in mind throughout the design and development of new language features. 17 17 In order to appeal to existing C programmers, great care must be taken to ensure that new features naturally feel like C. 18 The remainder of this section describes some of the important new features that currently exist in \CFA, to give the reader the necessary context in which the new features presented in this thesis must dovetail. 18 The remainder of this section describes some of the important new features that currently exist in \CFA, to give the reader the necessary context in which the new features presented in this thesis must dovetail. % TODO: harmonize with? 19 19 20 20 \subsection{C Background} … … 29 29 A a1 = { 1, .y:7, 6 }; 30 30 A a2[4] = { [2]:a0, [0]:a1, { .z:3 } }; 31 // equ ivalent to31 // equvialent to 32 32 // A a0 = { 0, 8, 0, 1 }; 33 33 // A a1 = { 1, 0, 7, 6 }; … … 36 36 Designations allow specifying the field to initialize by name, rather than by position. 37 37 Any field not explicitly initialized is initialized as if it had static storage duration \cite[p.~141]{C11}. 38 A designator specifies the current object for initialization, and as such any undesignated sub -objects pick up where the last initialization left off.39 For example, in the initialization of @a1@, the initializer of @y@ is @7@, and the unnamed initializer @6@ initializes the next sub -object, @z@.40 Later initializers override earlier initializers, so a sub -object for which there is more than one initializer is only initialized by its last initializer.41 Th ese semantics can be seen in the initialization of @a0@, where @x@ is designated twice, and thus initialized to @8@.42 Note that in \CFA, designations use a colon separator, rather than an equals sign as in C , because this syntax is one of the few places that conflicts with the new language features.38 A designator specifies the current object for initialization, and as such any undesignated subobjects pick up where the last initialization left off. 39 For example, in the initialization of @a1@, the initializer of @y@ is @7@, and the unnamed initializer @6@ initializes the next subobject, @z@. 40 Later initializers override earlier initializers, so a subobject for which there is more than one initializer is only initailized by its last initializer. 41 This can be seen in the initialization of @a0@, where @x@ is designated twice, and thus initialized to @8@. 42 Note that in \CFA, designations use a colon separator, rather than an equals sign as in C. 43 43 44 44 C also provides \emph{compound literal} expressions, which provide a first-class mechanism for creating unnamed objects. … … 91 91 92 92 There are times when a function should logically return multiple values. 93 Since a function in standard C can only return a single value, a programmer must either take in additional return values by address, or the function's designer must create a wrapper structure t opackage multiple return-values.93 Since a function in standard C can only return a single value, a programmer must either take in additional return values by address, or the function's designer must create a wrapper structure t0 package multiple return-values. 94 94 \begin{cfacode} 95 95 int f(int * ret) { // returns a value through parameter ret … … 102 102 \end{cfacode} 103 103 The former solution is awkward because it requires the caller to explicitly allocate memory for $n$ result variables, even if they are only temporary values used as a subexpression, or even not used at all. 104 The latter approach:105 104 \begin{cfacode} 106 105 struct A { … … 113 112 ... res3.x ... res3.y ... // use result values 114 113 \end{cfacode} 115 requires the caller to either learn the field names of the structure or learn the names of helper routines to access the individual return values.114 The latter approach requires the caller to either learn the field names of the structure or learn the names of helper routines to access the individual return values. 116 115 Both solutions are syntactically unnatural. 117 116 118 In \CFA, it is possible to directly declare a function returning mu ltiple values.119 This extensionprovides important semantic information to the caller, since return values are only for output.120 \begin{cfacode} 121 [int, int] f() { // nonew type117 In \CFA, it is possible to directly declare a function returning mutliple values. 118 This provides important semantic information to the caller, since return values are only for output. 119 \begin{cfacode} 120 [int, int] f() { // don't need to create a new type 122 121 return [123, 37]; 123 122 } 124 123 \end{cfacode} 125 However, the ability to return multiple values is useless without a syntax for accepting the results from the function. 126 124 However, the ability to return multiple values requires a syntax for accepting the results from a function. 127 125 In standard C, return values are most commonly assigned directly into local variables, or are used as the arguments to another function call. 128 126 \CFA allows both of these contexts to accept multiple return values. … … 150 148 g(f()); // selects (2) 151 149 \end{cfacode} 152 In this example, the only possible call to @f@ that can produce the two @int@s required for assigning into the variables @x@ and @y@ is the second option.153 A similar reasoning holds calling the function @g@.150 In this example, the only possible call to @f@ that can produce the two @int@s required by @g@ is the second option. 151 A similar reasoning holds for assigning into multiple variables. 154 152 155 153 In \CFA, overloading also applies to operator names, known as \emph{operator overloading}. … … 168 166 bool ?<?(A x, A y); 169 167 \end{cfacode} 170 Notably, the only difference i s syntax.168 Notably, the only difference in this example is syntax. 171 169 Most of the operators supported by \CC for operator overloading are also supported in \CFA. 172 170 Of notable exception are the logical operators (e.g. @||@), the sequence operator (i.e. @,@), and the member-access operators (e.g. @.@ and \lstinline{->}). … … 174 172 Finally, \CFA also permits overloading variable identifiers. 175 173 This feature is not available in \CC. 176 \begin{cfacode} 174 \begin{cfacode} % TODO: pick something better than x? max, zero, one? 177 175 struct Rational { int numer, denom; }; 178 176 int x = 3; // (1) … … 188 186 In this example, there are three definitions of the variable @x@. 189 187 Based on the context, \CFA attempts to choose the variable whose type best matches the expression context. 190 When used judiciously, this feature allows names like @MAX@, @MIN@, and @PI@ to apply across many types.191 188 192 189 Finally, the values @0@ and @1@ have special status in standard C. … … 200 197 } 201 198 \end{cfacode} 202 Every if - and iteration-statement in C compares the condition with @0@, and every increment and decrement operator is semantically equivalent to adding or subtracting the value @1@ and storing the result.199 Every if statement in C compares the condition with @0@, and every increment and decrement operator is semantically equivalent to adding or subtracting the value @1@ and storing the result. 203 200 Due to these rewrite rules, the values @0@ and @1@ have the types \zero and \one in \CFA, which allow for overloading various operations that connect to @0@ and @1@ \footnote{In the original design of \CFA, @0@ and @1@ were overloadable names \cite[p.~7]{cforall}.}. 204 The types \zero and \one have special built -in implicit conversions to the various integral types, and a conversion to pointer types for @0@, which allows standard C code involving @0@ and @1@ to work as normal.201 The types \zero and \one have special built in implicit conversions to the various integral types, and a conversion to pointer types for @0@, which allows standard C code involving @0@ and @1@ to work as normal. 205 202 \begin{cfacode} 206 203 // lvalue is similar to returning a reference in C++ … … 296 293 This capability allows specifying the same set of assertions in multiple locations, without the repetition and likelihood of mistakes that come with manually writing them out for each function declaration. 297 294 298 An interesting application of return-type resolution and polymorphism is with type-safe @malloc@.299 \begin{cfacode}300 forall(dtype T | sized(T))301 T * malloc() {302 return (T*)malloc(sizeof(T)); // call C malloc303 }304 int * x = malloc(); // malloc(sizeof(int))305 double * y = malloc(); // malloc(sizeof(double))306 307 struct S { ... };308 S * s = malloc(); // malloc(sizeof(S))309 \end{cfacode}310 The built-in trait @sized@ ensures that size and alignment information for @T@ is available in the body of @malloc@ through @sizeof@ and @_Alignof@ expressions respectively.311 In calls to @malloc@, the type @T@ is bound based on call-site information, allowing \CFA code to allocate memory without the potential for errors introduced by manually specifying the size of the allocated block.312 313 295 \section{Invariants} 314 An \emph{invariant} is a logical assertion that is true for some duration of a program's execution. 296 % TODO: discuss software engineering benefits of ctor/dtors: {pre/post} conditions, invariants 297 % an important invariant is the state of the environment (memory, resources) 298 % some objects pass their contract to the object user 299 An \emph{invariant} is a logical assertion that true for some duration of a program's execution. 315 300 Invariants help a programmer to reason about code correctness and prove properties of programs. 316 301 317 302 In object-oriented programming languages, type invariants are typically established in a constructor and maintained throughout the object's lifetime. 318 Th ese assertions aretypically achieved through a combination of access control modifiers and a restricted interface.303 This is typically achieved through a combination of access control modifiers and a restricted interface. 319 304 Typically, data which requires the maintenance of an invariant is hidden from external sources using the \emph{private} modifier, which restricts reads and writes to a select set of trusted routines, including member functions. 320 305 It is these trusted routines that perform all modifications to internal data in a way that is consistent with the invariant, by ensuring that the invariant holds true at the end of the routine call. … … 322 307 In C, the @assert@ macro is often used to ensure invariants are true. 323 308 Using @assert@, the programmer can check a condition and abort execution if the condition is not true. 324 This powerful toolforces the programmer to deal with logical inconsistencies as they occur.309 This is a powerful tool that forces the programmer to deal with logical inconsistencies as they occur. 325 310 For production, assertions can be removed by simply defining the preprocessor macro @NDEBUG@, making it simple to ensure that assertions are 0-cost for a performance intensive application. 326 311 \begin{cfacode} … … 369 354 \end{dcode} 370 355 The D compiler is able to assume that assertions and invariants hold true and perform optimizations based on those assumptions. 371 Note, these invariants are internal to the type's correct behaviour. 372 373 Types also have external invariants with the state of the execution environment, including the heap, the open-file table, the state of global variables, etc. 374 Since resources are finite and shared (concurrency), it is important to ensure that objects clean up properly when they are finished, restoring the execution environment to a stable state so that new objects can reuse resources. 356 357 An important invariant is the state of the execution environment, including the heap, the open file table, the state of global variables, etc. 358 Since resources are finite, it is important to ensure that objects clean up properly when they are finished, restoring the execution environment to a stable state so that new objects can reuse resources. 375 359 376 360 \section{Resource Management} … … 382 366 The program stack grows and shrinks automatically with each function call, as needed for local variables. 383 367 However, whenever a program needs a variable to outlive the block it is created in, the storage must be allocated dynamically with @malloc@ and later released with @free@. 384 This pattern is extended to more complex objects, such as files and sockets, which can also outlive the block where they are created, and thus require their ownresource management.385 Once allocated storage escapes \footnote{In garbage collected languages, such as Java, escape analysis \cite{Choi:1999:EAJ:320385.320386} is used to determine when dynamically allocated objects are strictly contained within a function, which allows the optimizer to allocate them on the stack.}a block, the responsibility for deallocating the storage is not specified in a function's type, that is, that the return value is owned by the caller.368 This pattern is extended to more complex objects, such as files and sockets, which also outlive the block where they are created, but at their core is resource management. 369 Once allocated storage escapes a block, the responsibility for deallocating the storage is not specified in a function's type, that is, that the return value is owned by the caller. 386 370 This implicit convention is provided only through documentation about the expectations of functions. 387 371 388 372 In other languages, a hybrid situation exists where resources escape the allocation block, but ownership is precisely controlled by the language. 389 This pattern requires a strict interface and protocol for a data structure, consistingof a pre-initialization and a post-termination call, and all intervening access is done via interface routines.390 This kind of encapsulation is popular in object-oriented programming languages, and like the stack, it takes care ofa significant portion of resource management cases.373 This pattern requires a strict interface and protocol for a data structure, where the protocol consists of a pre-initialization and a post-termination call, and all intervening access is done via interface routines. 374 This kind of encapsulation is popular in object-oriented programming languages, and like the stack, it contains a significant portion of resource management cases. 391 375 392 376 For example, \CC directly supports this pattern through class types and an idiom known as RAII \footnote{Resource Acquisition is Initialization} by means of constructors and destructors. … … 396 380 On the other hand, destructors provide a simple mechanism for tearing down an object and resetting the environment in which the object lived. 397 381 RAII ensures that if all resources are acquired in a constructor and released in a destructor, there are no resource leaks, even in exceptional circumstances. 398 A type with at least one non-trivial constructor or destructor is henceforthreferred to as a \emph{managed type}.399 In the context of \CFA, a non-trivial constructor is either a user defined constructor or an auto -generated constructor that calls a non-trivial constructor.400 401 For the remaining resource ownership cases, programmer must follow a brittle, explicit protocol for freeing resources or an implicit p rotocol implemented via the programming language.382 A type with at least one non-trivial constructor or destructor will henceforth be referred to as a \emph{managed type}. 383 In the context of \CFA, a non-trivial constructor is either a user defined constructor or an auto generated constructor that calls a non-trivial constructor. 384 385 For the remaining resource ownership cases, programmer must follow a brittle, explicit protocol for freeing resources or an implicit porotocol implemented via the programming language. 402 386 403 387 In garbage collected languages, such as Java, resources are largely managed by the garbage collector. … … 405 389 There are many kinds of resources that the garbage collector does not understand, such as sockets, open files, and database connections. 406 390 In particular, Java supports \emph{finalizers}, which are similar to destructors. 407 Sadly, finalizers are only guaranteed to be called before an object is reclaimed by the garbage collector \cite[p.~373]{Java8}, which may not happen if memory use is not contentious.408 Due to operating -system resource-limits, this is unacceptable for many long running programs.409 Instead, the paradigm in Java requires programmers to manually keep track of all resources\emph{except} memory, leading many novices and experts alike to forget to close files, etc.410 Complicating the picture, uncaught exceptions can cause control flow to change dramatically, leaking a resource that appears on first glance to be released.391 Sadly, finalizers come with far fewer guarantees, to the point where a completely conforming JVM may never call a single finalizer. % TODO: citation JVM spec; http://stackoverflow.com/a/2506514/2386739 392 Due to operating system resource limits, this is unacceptable for many long running tasks. % TODO: citation? 393 Instead, the paradigm in Java requires programmers manually keep track of all resource \emph{except} memory, leading many novices and experts alike to forget to close files, etc. 394 Complicating the picture, uncaught exceptions can cause control flow to change dramatically, leaking a resource which appears on first glance to be closed. 411 395 \begin{javacode} 412 396 void write(String filename, String msg) throws Exception { … … 419 403 } 420 404 \end{javacode} 421 Any line in this program can throw an exception, which leads to a profusion of finally blocks around many function bodies, since it is not always clear when an exception may be thrown. 405 Any line in this program can throw an exception. 406 This leads to a profusion of finally blocks around many function bodies, since it isn't always clear when an exception may be thrown. 422 407 \begin{javacode} 423 408 public void write(String filename, String msg) throws Exception { … … 437 422 \end{javacode} 438 423 In Java 7, a new \emph{try-with-resources} construct was added to alleviate most of the pain of working with resources, but ultimately it still places the burden squarely on the user rather than on the library designer. 439 Furthermore, for complete safety this pattern requires nested objects to be declared separately, otherwise resources that can throw an exception on close can leak nested resources \cite{TryWithResources}.424 Furthermore, for complete safety this pattern requires nested objects to be declared separately, otherwise resources which can throw an exception on close can leak nested resources. % TODO: cite oracle article http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html? 440 425 \begin{javacode} 441 426 public void write(String filename, String msg) throws Exception { 442 try ( // try-with-resources427 try ( 443 428 FileOutputStream out = new FileOutputStream(filename); 444 429 FileOutputStream log = new FileOutputStream("log.txt"); … … 449 434 } 450 435 \end{javacode} 451 Variables declared as part of a try-with-resources statement must conform to the @AutoClosable@ interface, and the compiler implicitly calls @close@ on each of the variables at the end of the block. 452 Depending on when the exception is raised, both @out@ and @log@ are null, @log@ is null, or both are non-null, therefore, the cleanup for these variables at the end is appropriately guarded and conditionally executed to prevent null-pointer exceptions. 453 454 While Rust \cite{Rust} does not enforce the use of a garbage collector, it does provide a manual memory management environment, with a strict ownership model that automatically frees allocated memory and prevents common memory management errors. 455 In particular, a variable has ownership over its associated value, which is freed automatically when the owner goes out of scope. 456 Furthermore, values are \emph{moved} by default on assignment, rather than copied, which invalidates the previous variable binding. 457 \begin{rustcode} 458 struct S { 459 x: i32 460 } 461 let s = S { x: 123 }; 462 let z = s; // move, invalidate s 463 println!("{}", s.x); // error, s has been moved 464 \end{rustcode} 465 Types can be made copyable by implementing the @Copy@ trait. 466 467 Rust allows multiple unowned views into an object through references, also known as borrows, provided that a reference does not outlive its referent. 468 A mutable reference is allowed only if it is the only reference to its referent, preventing data race errors and iterator invalidation errors. 469 \begin{rustcode} 470 let mut x = 10; 471 { 472 let y = &x; 473 let z = &x; 474 println!("{} {}", y, z); // prints 10 10 475 } 476 { 477 let y = &mut x; 478 // let z1 = &x; // not allowed, have mutable reference 479 // let z2 = &mut x; // not allowed, have mutable reference 480 *y = 5; 481 println!("{}", y); // prints 5 482 } 483 println!("{}", x); // prints 5 484 \end{rustcode} 485 Since references are not owned, they do not release resources when they go out of scope. 486 There is no runtime cost imposed on these restrictions, since they are enforced at compile-time. 487 488 Rust provides RAII through the @Drop@ trait, allowing arbitrary code to execute when the object goes out of scope, allowing Rust programs to automatically clean up auxiliary resources much like a \CC program. 489 \begin{rustcode} 490 struct S { 491 name: &'static str 492 } 493 494 impl Drop for S { // RAII for S 495 fn drop(&mut self) { 496 println!("dropped {}", self.name); 497 } 498 } 499 500 { 501 let x = S { name: "x" }; 502 let y = S { name: "y" }; 503 } // prints "dropped y" "dropped x" 504 \end{rustcode} 436 On the other hand, the Java compiler generates more code if more resources are declared, meaning that users must be more familiar with each type and library designers must provide better documentation. 505 437 506 438 % D has constructors and destructors that are worth a mention (under classes) https://dlang.org/spec/spec.html … … 510 442 The programming language, D, also manages resources with constructors and destructors \cite{D}. 511 443 In D, @struct@s are stack allocated and managed via scoping like in \CC, whereas @class@es are managed automatically by the garbage collector. 512 Like Java, using the garbage collector means that destructors are called indeterminately, requiring the use of finally statements to ensure dynamically allocated resources that are not managed by the garbage collector, such as open files, are cleaned up.444 Like Java, using the garbage collector means that destructors may never be called, requiring the use of finally statements to ensure dynamically allocated resources that are not managed by the garbage collector, such as open files, are cleaned up. 513 445 Since D supports RAII, it is possible to use the same techniques as in \CC to ensure that resources are released in a timely manner. 514 Finally, D provides a scope guard statement, which allows an arbitrary statement to be executed at normal scope exit with \emph{success}, at exceptional scope exit with \emph{failure}, or at normal and exceptional scope exit with \emph{exit}. % https://dlang.org/spec/statement.html#ScopeGuardStatement 515 It has been shown that the \emph{exit} form of the scope guard statement can be implemented in a library in \CC \cite{ExceptSafe}. 516 517 To provide managed types in \CFA, new kinds of constructors and destructors are added to \CFA and discussed in Chapter 2. 446 Finally, D provides a scope guard statement, which allows an arbitrary statement to be executed at normal scope exit with \emph{success}, at exceptional scope exit with \emph{failure}, or at normal and exceptional scope exit with \emph{exit}. % cite? https://dlang.org/spec/statement.html#ScopeGuardStatement 447 It has been shown that the \emph{exit} form of the scope guard statement can be implemented in a library in \CC. % cite: http://www.drdobbs.com/184403758 448 449 % TODO: discussion of lexical scope vs. dynamic 450 % see Peter's suggestions 451 % RAII works in both cases. Guaranteed to work in stack case, works in heap case if root is deleted (but it's dangerous to rely on this, because of exceptions) 518 452 519 453 \section{Tuples} 520 454 \label{s:Tuples} 521 In mathematics, tuples are finite-length sequences which, unlike sets, a re ordered and allow duplicate elements.522 In programming languages, tuples provide fixed-sized heterogeneous lists of elements.455 In mathematics, tuples are finite-length sequences which, unlike sets, allow duplicate elements. 456 In programming languages, tuples are a construct that provide fixed-sized heterogeneous lists of elements. 523 457 Many programming languages have tuple constructs, such as SETL, \KWC, ML, and Scala. 524 458 … … 528 462 Adding tuples to \CFA has previously been explored by Esteves \cite{Esteves04}. 529 463 530 The design of tuples in \KWC took much of its inspiration from SETL \cite{SETL}.464 The design of tuples in \KWC took much of its inspiration from SETL. 531 465 SETL is a high-level mathematical programming language, with tuples being one of the primary data types. 532 466 Tuples in SETL allow a number of operations, including subscripting, dynamic expansion, and multiple assignment. … … 536 470 \begin{cppcode} 537 471 tuple<int, int, int> triple(10, 20, 30); 538 get<1>(triple); // access component 1 => 20472 get<1>(triple); // access component 1 => 30 539 473 540 474 tuple<int, double> f(); … … 548 482 Tuples are simple data structures with few specific operations. 549 483 In particular, it is possible to access a component of a tuple using @std::get<N>@. 550 Another interesting feature is @std::tie@, which creates a tuple of references, allowing assignment ofthe results of a tuple-returning function into separate local variables, without requiring a temporary variable.484 Another interesting feature is @std::tie@, which creates a tuple of references, which allows assigning the results of a tuple-returning function into separate local variables, without requiring a temporary variable. 551 485 Tuples also support lexicographic comparisons, making it simple to write aggregate comparators using @std::tie@. 552 486 553 There is a proposal for \CCseventeen called \emph{structured bindings} \cite{StructuredBindings}, that introduces new syntax to eliminate the need to pre-declare variables and use @std::tie@ for binding the results from a function call.487 There is a proposal for \CCseventeen called \emph{structured bindings}, that introduces new syntax to eliminate the need to pre-declare variables and use @std::tie@ for binding the results from a function call. % TODO: cite http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0144r0.pdf 554 488 \begin{cppcode} 555 489 tuple<int, double> f(); … … 566 500 Structured bindings allow unpacking any struct with all public non-static data members into fresh local variables. 567 501 The use of @&@ allows declaring new variables as references, which is something that cannot be done with @std::tie@, since \CC references do not support rebinding. 568 This extension requires the use of @auto@ to infer the types of the new variables, so complicated expressions with a non-obvious type must bedocumented with some other mechanism.502 This extension requires the use of @auto@ to infer the types of the new variables, so complicated expressions with a non-obvious type must documented with some other mechanism. 569 503 Furthermore, structured bindings are not a full replacement for @std::tie@, as it always declares new variables. 570 504 571 505 Like \CC, D provides tuples through a library variadic template struct. 572 506 In D, it is possible to name the fields of a tuple type, which creates a distinct type. 573 % http://dlang.org/phobos/std_typecons.html 574 \begin{dcode} 507 \begin{dcode} % TODO: cite http://dlang.org/phobos/std_typecons.html 575 508 Tuple!(float, "x", float, "y") point2D; 576 Tuple!(float, float) float2; // different type from point2D509 Tuple!(float, float) float2; // different types 577 510 578 511 point2D[0]; // access first element … … 588 521 The @expand@ method produces the components of the tuple as a list of separate values, making it possible to call a function that takes $N$ arguments using a tuple with $N$ components. 589 522 590 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML \cite{sml}.523 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML. 591 524 A function in SML always accepts exactly one argument. 592 525 There are two ways to mimic multiple argument functions: the first through currying and the second by accepting tuple arguments. … … 602 535 Tuples are a foundational tool in SML, allowing the creation of arbitrarily complex structured data types. 603 536 604 Scala, like \CC, provides tuple types through the standard library \cite{Scala}.537 Scala, like \CC, provides tuple types through the standard library. 605 538 Scala provides tuples of size 1 through 22 inclusive through generic data structures. 606 539 Tuples support named access and subscript access, among a few other operations. … … 614 547 \end{scalacode} 615 548 In Scala, tuples are primarily used as simple data structures for carrying around multiple values or for returning multiple values from a function. 616 The 22-element restriction is an odd and arbitrary choice, but in practice it does not cause problems since large tuples are uncommon.549 The 22-element restriction is an odd and arbitrary choice, but in practice it doesn't cause problems since large tuples are uncommon. 617 550 Subscript access is provided through the @productElement@ method, which returns a value of the top-type @Any@, since it is impossible to receive a more precise type from a general subscripting method due to type erasure. 618 551 The disparity between named access beginning at @_1@ and subscript access starting at @0@ is likewise an oddity, but subscript access is typically avoided since it discards type information. … … 620 553 621 554 622 \Csharp also has tuples, but has similarly strange limitations, allowing tuples of size up to 7 components. %https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx555 \Csharp has similarly strange limitations, allowing tuples of size up to 7 components. % TODO: cite https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx 623 556 The officially supported workaround for this shortcoming is to nest tuples in the 8th component. 624 557 \Csharp allows accessing a component of a tuple by using the field @Item$N$@ for components 1 through 7, and @Rest@ for the nested tuple. 625 558 626 In Python \cite{Python}, tuples are immutable sequences that provide packing and unpacking operations. 559 560 % TODO: cite 5.3 https://docs.python.org/3/tutorial/datastructures.html 561 In Python, tuples are immutable sequences that provide packing and unpacking operations. 627 562 While the tuple itself is immutable, and thus does not allow the assignment of components, there is nothing preventing a component from being internally mutable. 628 563 The components of a tuple can be accessed by unpacking into multiple variables, indexing, or via field name, like D. 629 564 Tuples support multiple assignment through a combination of packing and unpacking, in addition to the common sequence operations. 630 565 631 Swift \cite{Swift}, like D, provides named tuples, with components accessed by name, index, or via extractors. 566 % TODO: cite https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-ID448 567 Swift, like D, provides named tuples, with components accessed by name, index, or via extractors. 632 568 Tuples are primarily used for returning multiple values from a function. 633 569 In Swift, @Void@ is an alias for the empty tuple, and there are no single element tuples. 634 635 Tuples comparable to those described above are added to \CFA and discussed in Chapter 3.636 570 637 571 \section{Variadic Functions} … … 647 581 printf("%d %g %c %s", 10, 3.5, 'X', "a string"); 648 582 \end{cfacode} 649 Through the use of a format string, C programmers can communicate argument type information to @printf@, allowingC programmers to print any of the standard C data types.583 Through the use of a format string, @printf@ allows C programmers to print any of the standard C data types. 650 584 Still, @printf@ is extremely limited, since the format codes are specified by the C standard, meaning users cannot define their own format codes to extend @printf@ for new data types or new formatting rules. 651 585 … … 707 641 A parameter pack matches 0 or more elements, which can be types or expressions depending on the context. 708 642 Like other templates, variadic template functions rely on an implicit set of constraints on a type, in this example a @print@ routine. 709 That is, it is possible to use the @f@ routine onany type provided there is a corresponding @print@ routine, making variadic templates fully open to extension, unlike variadic functions in C.643 That is, it is possible to use the @f@ routine any any type provided there is a corresponding @print@ routine, making variadic templates fully open to extension, unlike variadic functions in C. 710 644 711 645 Recent \CC standards (\CCfourteen, \CCseventeen) expand on the basic premise by allowing variadic template variables and providing convenient expansion syntax to remove the need for recursion in some cases, amongst other things. … … 738 672 Unfortunately, Java's use of nominal inheritance means that types must explicitly inherit from classes or interfaces in order to be considered a subclass. 739 673 The combination of these two issues greatly restricts the usefulness of variadic functions in Java. 740 741 Type-safe variadic functions are added to \CFA and discussed in Chapter 4.
Note:
See TracChangeset
for help on using the changeset viewer.