About coding style Spring February 9, 2004

Similar documents
1 Announcements. 2 Scan Implementation Recap. Recitation 4 Scan, Reduction, MapCollectReduce

Preparing for Class: Watch le Videos! What is an ML program?

7.3.3 A Language With Nested Procedure Declarations

CSci 4223 Principles of Programming Languages

Supplementary Notes on Concurrent ML

A Crash Course on Standard ML

Recursion. Tjark Weber. Functional Programming 1. Based on notes by Sven-Olof Nyström. Tjark Weber (UU) Recursion 1 / 37

CS 312 Problem Set 1: An Introduction to SML

Recursion. Lars-Henrik Eriksson. Functional Programming 1. Based on a presentation by Tjark Weber and notes by Sven-Olof Nyström

Higher-Order Functions

Chapter 3 Programming with Recursion

CS 312, Fall Exam 1

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

Computer Science 312 Fall Prelim 2 SOLUTIONS April 18, 2006

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

CSci 4223 Principles of Programming Languages

Call-by-name evaluation

Version 4, 12 October 2004 Project handed out on 12 October. Complete Java implementation due on 2 November.

Continuation Passing Style. Continuation Passing Style

CSE341, Fall 2011, Midterm Examination October 31, 2011

A quick introduction to SML

COP-5555 PROGRAMMING LANGUAGEPRINCIPLES NOTES ON RPAL

A Brief Introduction to Standard ML

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

Module 8: Local and functional abstraction

CSE3322 Programming Languages and Implementation

CSCE 314 Programming Languages

CSE 341 Section 5. Winter 2018

CSE341, Fall 2011, Midterm Examination October 31, 2011

Shell CSCE 314 TAMU. Higher Order Functions

CSE 341 : Programming Languages

SML A F unctional Functional Language Language Lecture 19

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

CIS 120 Midterm I February 16, 2015 SOLUTIONS

Programming Languages

Handout 2 August 25, 2008

Part I: Written Problems

15 150: Principles of Functional Programming. Exceptions

Introduction to Programming in ATS

Lecture Notes on Induction and Recursion

CS Lecture 6: Map and Fold. Prof. Clarkson Fall Today s music: Selections from the soundtrack to 2001: A Space Odyssey

15-122: Principles of Imperative Computation, Fall 2015

CS Lecture 6: Map and Fold. Prof. Clarkson Spring Today s music: Selections from the soundtrack to 2001: A Space Odyssey

CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists. Zach Tatlock Winter 2018

Function definitions. CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists. Example, extended. Some gotchas. Zach Tatlock Winter 2018

Assignment 0. Computer Science 52. Due Friday, September 7, 2018, at 5:00 pm

15 212: Principles of Programming. Some Notes on Continuations

What is a macro. CSE341: Programming Languages Lecture 15 Macros. Example uses. Using Racket Macros. Zach Tatlock Winter 2018

CSE341: Programming Languages Lecture 15 Macros. Zach Tatlock Winter 2018

Programming Languages and Techniques (CIS120)

Introduction to SML Basic Types, Tuples, Lists, Trees and Higher-Order Functions

The type checker will complain that the two branches have different types, one is string and the other is int

Programming Paradigms Languages F28PL, Lecture 1

CSci 4223 Lecture 12 March 4, 2013 Topics: Lexical scope, dynamic scope, closures

Homework 5. Notes. Turn-In Instructions. Reading. Problems. Handout 19 CSCI 334: Spring (Required) Read Mitchell, Chapters 6 and 7.

Exercise 1 ( = 24 points)

Contextual Analysis (2) Limitations of CFGs (3)

Functional Programming Mid-term exam Tuesday 3/10/2017

Programming Languages and Techniques (CIS120)

CSCC24 Functional Programming Typing, Scope, Exceptions ML

UNIVERSITY OF TORONTO Faculty of Arts and Science. Midterm Sample Solutions CSC324H1 Duration: 50 minutes Instructor(s): David Liu.

SML Style Guide. Last Revised: 31st August 2011

Australian researchers develop typeface they say can boost memory, that could help students cramming for exams.

CMSC 330, Fall 2013, Practice Problems 3

type environment updated subtype sound

Lecture 5: Lazy Evaluation and Infinite Data Structures

CSE341 Autumn 2017, Midterm Examination October 30, 2017

F28PL1 Programming Languages. Lecture 12: Standard ML 2

Exercise 1 ( = 18 points)

ormap, andmap, and filter

G Programming Languages - Fall 2012

CSc 520. Gofer III. Accumulative Recursion. Accumulative Recursion... Stack Recursion. Principles of Programming Languages. Christian Collberg

CSE 341: Programming Languages

ML Built-in Functions

Tentamen Functioneel Programmeren 2001 Informatica, Universiteit Utrecht Docent: Wishnu Prasetya

Homework 1. Notes. What To Turn In. Unix Accounts. Reading. Handout 3 CSCI 334: Spring, 2017

Introduction to SML Getting Started

CSC/MAT-220: Lab 6. Due: 11/26/2018

Inductive Data Types

Factorial. Next. Factorial. How does it execute? Tail recursion. How does it execute? More on recursion. Higher-order functions

CS1 Recitation. Week 2

02157 Functional Programming Lecture 1: Introduction and Getting Started

Lecture 15 CIS 341: COMPILERS

CSE341: Programming Languages Lecture 7 First-Class Functions. Dan Grossman Winter 2013

15-451/651: Design & Analysis of Algorithms November 20, 2018 Lecture #23: Closest Pairs last changed: November 13, 2018

CSE341 Spring 2016, Final Examination June 6, 2016

15 150: Principles of Functional Programming. More about Higher-Order Functions

Next. Tail Recursion: Factorial. How does it execute? Tail recursion. Tail recursive factorial. Tail recursive factorial.

(ii) Define a function ulh that takes a list xs, and pairs each element with all other elements in xs.

Programming Languages

Fall 2018 Stephen Brookes. LECTURE 2 Thursday, August 30

Higher Order Functions in Haskell

Functional programming Primer I

Recap from last time. Programming Languages. CSE 130 : Fall Lecture 3: Data Types. Put it together: a filter function

FUNCTIONAL PROGRAMMING

The Haskell HOP: Higher-order Programming

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

THAT ABOUT WRAPS IT UP Using FIX to Handle Errors Without Exceptions, and Other Programming Tricks

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Sample Exam; Solutions

Transcription:

About codg style 15-212 Sprg 2004 February 9, 2004 Contents 1 Correctness 2 2 Specification 2 3 Style 2 3.1 if-then- Expressions... 3 3.1.1 Boolean if-then- Expressions... 3 3.1.2 if-then- stead of Pattern Matchg... 4 3.2 Functions... 4 3.2.1 Multiple Evaluations... 4 3.2.2 Redefition of Library Functions... 5 3.2.3 Overly Complex Implementations... 6 3.3 Helper Functions... 6 3.3.1 Non-local Helper Functions... 6 3.3.2 Multiple Defitions of the Same Local Helper Function. 8 3.4 Pattern Matchg... 10 3.4.1 Redundant Cases... 10 3.4.2 Pattern Matchg Besides Function Arguments... 11 3.4.3 Bdgs to Identifiers and the Wildcard Pattern... 11 3.4.4 Multiple Patterns for Function Arguments Correspondg tothesameexpression... 11 3.5 ShadowgofPreviousBdgs... 12 1

A few students have asked what are the style guideles for a perfect homework. First of all, the code the homework is graded based on three ma components: correctness, specification, andstyle. 1 Correctness Correctness refers to the correctness of the function that is implemented, i.e., if the function computes the value requested the homework handout. 2 Specification Specification refers to the presence and correctness of the specification a comment before the function: the comment must conta the identifier beg declared, its type, an explanation of the meang of the value computed, a list of variants, and a list of possible effects. It is very important for the specification to be present for all functions, global, auxiliary and local functions: you can refer to the code distributed on the course webpage for some examples. Very simple helper functions and lambda expressions may not have a specification: if the function is very simple its meang can be understood without the help of a specification. Use your judgment to decide if a specification is needed for a helper function, when doubt, provide the specification: you will reduce the risk of losg specification pots. 3 Style Style refers to the way you implemented the requested function: most functions can be implemented many different ways, each one of them satisfies the correctness requirement, but some of them have a better style. In specific, sce the ma focus of the course is functional programmg, a functional style is to be preferred. Moreover, general an elegant solution should be preferred to a more efficient one, if the more efficient solution is much more complicated. However do not write a very elegant O(2 n ) solution stead of a bit less elegant O(n) one! Sometimes we might ask to implement a function followg particular requirements (e.g., request a recursive defition): if there exists a more efficient solution that does not adhere to such requirements, please do not use such solution as it will not be considered a correct solution to the problem, as it does not satisfy the explicit requirements. Often exercises are meant to test the ability to use a particular programmg technique (like the use of recursive function defitions) and if the solution does not follow the given requirement, it won t be useful establishg the ability to use such technique. In terms of style, one of the purposes of homework #1 was to get familiar with the functional programmg style. The best sources for learng good programmg style are the example code presented at lectures and recitation as well as the code distributed on the course webpage. The followg contas 2

some example of bad style that you can use to understand what you should avoid, and what to do stead: 3.1 if-then- Expressions 3.1.1 Boolean if-then- Expressions if a = b then true false It is bad style to have an if-then- expression whose type is bool. The previous expression is equivalent to a = b. Other examples clude: if a = b then false true is equivalent to: not (a = b) if a = b then if a > 0 then true false false is equivalent to: (a = b) andalso (a > 0) if a = b then true if a > 0 then true false is equivalent to: (a = b) or (a > 0) 3

3.1.2 if-then- stead of Pattern Matchg fun natpred (n: t) : t = if n = 0 then 0 n - 1 In this case, the if statement is used to discrimate over the value of an argument that is matched agast a constant. This should be done usg pattern matchg as follows: fun natpred (0: t) : t = 0 natpred (n: t) : t = n - 1 3.2 Functions 3.2.1 Multiple Evaluations if f (x) > 0 then f (x) 0 In this case function f is evaluated twice. Sce f does not have side effects (you are not allowed to use the imperative features of SML), the function will return the same value each time. If is better style to do the followg: val y = f (x) if y > 0 then y 0 or: fun positiveorzero (n:t): t = if n > 0 then n 0 positiveorzero (f (x)) 4

The second solution is to be preferred especially if the function positiveorzero is reused other parts of the code ( which case it has to be scoped accordgly). 3.2.2 Redefition of Library Functions val max: t * t -> t max (x,y) returns the maximum of two numbers. Invariants: none fun max (x: t, y: t): t = if x > y then x y val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list Invariants: l is not empty and every element of l is positive. fun maxlist ([]: t list): t = 0 maxlist (x::xs: t list): t = max (x, maxlist (xs)) There is another additional improvement that should be done to this code. The function max is actually equivalent to the library function Int.max. In general, you should not defe your own function when an equivalent function is present the library. Library functions are described the SML base library documentation, moreover, some of the most commonly used functions are also summarized the appix of the textbook. Try to avoid re-ventg the wheel, and make full use of the library functions. This is especially true the case of library functions for lists, like foldl, foldr, andmap, which can often be used to produce a very simple and elegant function that accomplishes the given task. val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list 5

Invariants: l is not empty and every element of l is positive. fun maxlist ([]: t list): t = 0 maxlist (x::xs: t list): t = Int.max (x, maxlist (xs)) 3.2.3 Overly Complex Implementations val divisible : t * t -> bool divisible (n, m) returns true if n is divisible by m Invariants: n >= 0 and m > 0 fun divisible(n: t, m: t): bool = if n = m then true if n < m then false divisible (n - m, m) In this case, while the function is correct, the implementation is overly complex: a natural number n is divisible by a positive natural number m, ifthe remader of the division of n by m is equal to zero. The remader can be obtaed by usg the mod operator. Moreover, the previous implementation has complexity O(n/m), while the mod operation can be done constant time. A better solution would be: val divisible : t * t -> bool divisible (n, m) returns true if n is divisible by m Invariants: x and y are strictly positive fun divisible(n: t, m: t): bool = (n mod m) = 0 3.3 Helper Functions 3.3.1 Non-local Helper Functions 6

val maxlisthelper : t * t list -> t maxlisthelper (max, list) computes the maximum of max and each value the list Invariants: none fun maxlisthelper (max: t, []: t list): t = max maxlisthelper (max: t, x::xs: t list): t = val newmax: t = if max > x then max x maxlisthelper (newmax, xs) val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list Invariants: l is not empty Effects: raises Invalid_argument if the list is empty fun maxlist ([]: t list): t = raise Invalid_argument maxlist (x::xs: t list): t = maxlisthelper (x, xs) In this case the maxlisthelper function is an auxiliary function that is used the defition of maxlist. Sce it has no specific use besides with maxlist, it should be defed as a local function. val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list Invariants: l is not empty Effects: raises Invalid_argument if the list is empty The function maxlist uses the local helper function: 7

val maxlisthelper : t * t list -> t maxlisthelper (max, list) computes the maximum of max and each value the list Invariants: none fun maxlist ([]: t list): t = raise Invalid_argument maxlist (x::xs: t list): t = fun maxlisthelper (max: t, []: t list): t = max maxlisthelper (max: t, x::xs: t list): t = val newmax: t = if max > x then max x maxlisthelper (newmax, xs) maxlisthelper (x, xs) 3.3.2 Multiple Defitions of the Same Local Helper Function val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list Invariants: l is not empty and every element of l is positive. The function maxlist uses the local helper function: val max: t * t -> t max (x,y) returns the maximum of two numbers. Invariants: none 8

fun maxlist ([]: t list): t = 0 maxlist (x::xs: t list): t = fun max (x: t, y: t): t = if x > y then x y max (x, maxlist (xs)) val maxfun t * (t -> t) * (t -> t) -> t maxfun (x, f, g) returns the maximum of f(x) and g(x). Invariants: f and g are defed at x. The function maxfun uses the local helper function: val max: t * t -> t max (x,y) returns the maximum of two numbers. Invariants: none fun maxfun (x: t, f: t -> t, g: t -> t): t = fun max (x: t, y: t): t = if x > y then x y max (f (x), g (x)) In this case the function max: t * t -> t is defed as a local helper function both maxlist and maxfun. It is better style to defe max as a non local helper function, especially given the general nature of the function max. val max: t * t -> t max (x,y) returns the maximum of two numbers. Invariants: none 9

fun max (x: t, y: t): t = if x > y then x y val maxlist : t list -> t maxlist (l) computes the maximum value contaed the list Invariants: l is not empty and every element of l is positive. fun maxlist ([]: t list): t = 0 maxlist (x::xs: t list): t = max (x, maxlist (xs)) val maxfun t * (t -> t) * (t -> t) -> t maxfun (x, f, g) returns the maximum of f(x) and g(x). Invariants: f and g are defed at x. fun maxfun (x: t, f: t -> t, g: t -> t): t = max (f (x), g (x)) 3.4 Pattern Matchg 3.4.1 Redundant Cases fun fib (0: t): t = 1 fib (1: t): t = 1 fib (2: t): t = 2 fib (n: t): t = fib(n-1) + fib(n-2) In this case the additional base case for n = 2 is not necessary. A better defition for the function fib would be: fun fib (0: t): t = 1 fib (1: t): t = 1 fib (n: t): t = fib(n-1) + fib(n-2) 10

3.4.2 Pattern Matchg Besides Function Arguments fun second (nil: t list) : t option = NONE second (x::nil: t list) : t option = NONE second (x::xs: t list) : t option = val second::rest : t list = xs SOME second In this case, the local defition is used to bd the second element of the list of the local variable second. While the code is correct and sometimes it is necessary to use pattern matchg besides function argument, this case this is not good style: the pattern matchg should have been done the argument pattern stead, makg it evident the tention. Moreover this approach works correctly only because the pattern (x::nil) appears before the pattern (x::xs). A better solution would be: fun second (nil: t list) : t option = NONE second (x::nil: t list) : t option = NONE second (x::second::rest: t list) : t option = SOME second 3.4.3 Bdgs to Identifiers and the Wildcard Pattern fun second (nil: t list) : t option = NONE second (x::nil: t list) : t option = NONE second (x::second::rest: t list) : t option = SOME second The previous function declaration can be further improved by replacg bdgs the patterns to identifiers that are never used with the wildcard pattern. fun second (nil: t list) : t option = NONE second (_::nil: t list) : t option = NONE second (_::second::_: t list) : t option = SOME second 3.4.4 Multiple Patterns for Function Arguments Correspondg to the Same Expression fun second (nil: t list) : t option = NONE second (_::nil: t list) : t option = NONE second (_::second::_: t list) : t option = SOME second 11

The pattern the previous defition is used only to discrimate between a list with at least 2 elements, and a list with fewer than 2 elements. The same result can be obtaed by the more compact: fun second (_::second::_: t list) : t option = SOME second second (_: t list) : t option = NONE Beware, however, that the use of the wildcard pattern as well as overlappg patterns (multiple pattern that can match the same value), can be sometimes misleadg. For stance, the last example and ::second:: both match the list [1,2,3]: however the first pattern will be the one chosen because it appears first. 3.5 Shadowg of Previous Bdgs fun convolve (1: t, f: t -> t, g: t -> t): t = f(1) * g(1) convolve (k: t, f: t -> t, g: t -> t): t = val f = fn (n: t) => f(n+1) f(0) * g(k) + convolve (k-1, f, g) The function convolve defes a bdg for f that overrides the previous bdg of f. In general, it is bad style to defe new bdgs for an identifier which shadow previous bdgs unless strictly necessary. In this case, it would have been better to create a new bdg with a different name, or use the lambda expression directly. fun convolve (1: t, f: t -> t, g: t -> t): t = f(1) * g(1) convolve (k: t, f: t -> t, g: t -> t): t = val f = fn (n: t) => f(n+1) f(1) * g(k) + convolve (k-1, f, g) or: fun convolve (1: t, f: t -> t, g: t -> t): t = f(1) * g(1) convolve (k: t, f: t -> t, g: t -> t): t = f(1) * g(k) + convolve (k-1, fn (n: t) => f(n+1), g) 12