Plus a few random things

Slides:



Advertisements
Similar presentations
CMSC 330: Organization of Programming Languages Tuples, Types, Conditionals and Recursion or “How many different OCaml topics can we cover in a single.
Advertisements

Types of Recursive Methods
More about functions Plus a few random things. 2 Tail recursion A function is said to be tail recursive if the recursive call is the very last thing it.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Chapter 5 C Functions The best way to develop and maintain a large program is to divide it into several smaller program modules, each of which is more.
Week 9: Methods 1.  We have written lots of code so far  It has all been inside of the main() method  What about a big program?  The main() method.
ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens.
16-Jun-15 Recursion. 2 Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example:
1 Gentle Introduction to Programming Session 2: Functions.
Imperative programming public int factorial (int N){ int F = 1; for(X=N; X>1; X-- ){ F= F*X; } return F; } Functional programming (defun factorial(N) (cond.
© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Chapter 5 - Functions Outline 5.1Introduction 5.2Program.
 2007 Pearson Education, Inc. All rights reserved C Functions.
 2007 Pearson Education, Inc. All rights reserved C Functions.
CMPE-013/L: “C” Programming Gabriel Hugh Elkaim – Spring 2012 CMPE-013/L Functions Gabriel Hugh Elkaim Spring 2012.
Methods. Why methods? A method gives a name to something that you want to do, so you don’t have to think about how to do it, you just do it The name should.
Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.
© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. C How To Program - 4th edition Deitels Class 05 University.
Fall Week 3 CSCI-141 Scott C. Johnson.  Say we want to draw the following figure ◦ How would we go about doing this?
Haskell. 2 GHC and HUGS Haskell 98 is the current version of Haskell GHC (Glasgow Haskell Compiler, version 7.4.1) is the version of Haskell I am using.
224 3/30/98 CSE 143 Recursion [Sections 6.1, ]
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
Python uses boolean variables to evaluate conditions. The boolean values True and False are returned when an expression is compared or evaluated.
Monads. foo1 Method to print a string, then return its length: scala> def foo1(bar: String) = { | println(bar) | bar.size | } foo1: (bar: String)Int scala>
Functions. Motivation What is a function? A function is a self-contained unit of program code designed to accomplish a particular task. We already used.
CSIS 113A Lecture 5 Functions. Introduction to Functions  Building Blocks of Programs  Other terminology in other languages:  Procedures, subprograms,
1 Recursion Recursive function: a function that calls itself (directly or indirectly). Recursion is often a good alternative to iteration (loops). Its.
CSC 1010 Programming for All Lecture 5 Functions Some material based on material from Marty Stepp, Instructor, University of Washington.
Lets and Loops Tail Recursion.
Chapter 9: Value-Returning Functions
User-Written Functions
Instant Scala.
Recursion DRILL: Please take out your notes on Recursion
Lesson #6 Modular Programming and Functions.
COMP 170 – Introduction to Object Oriented Programming
Repetition Structures Chapter 9
Lesson #6 Modular Programming and Functions.
CSE 341 Lecture 5 efficiency issues; tail recursion; print
Haskell.
Recursion, Tail Recursion
Functions.
Chapter 5 - Functions Outline 5.1 Introduction
Lesson #6 Modular Programming and Functions.
Call Stacks, Arguments and Returns
Strings, Line-by-line I/O, Functions, Call-by-Reference, Call-by-Value
Important Concepts from Clojure
Important Concepts from Clojure
Haskell Dealing with impurity 30-Nov-18.
FP Foundations, Scheme In Text: Chapter 14.
CISC101 Reminders Assn 3 due tomorrow, 7pm.
Plus a few random things
Functions Chapter 9 Copyright © 2008 W. W. Norton & Company.
Cases and Classes and Case Classes
C Programming Getting started Variables Basic C operators Conditionals
Plus a few random things
Lesson #6 Modular Programming and Functions.
Recursion Taken from notes by Dr. Neil Moore
Recursion, Higher-order-functions
Important Concepts from Clojure
The structure of programming
Chapter 1 Section 3.
Plus a few random things
The structure of programming
CISC101 Reminders Assignment 3 due today.
Thinking procedurally
Plus a few random things
Monads.
Lecture 3 More on Flow Control, More on Functions,
Plus a few random things
Presentation transcript:

Plus a few random things More about functions Plus a few random things

Tail recursion A function is said to be tail recursive if the recursive call is the very last thing it does, in any recursive branch Example #1: def collatz(n: Int): Int = { if (n == 1) 1 else if (n % 2 == 0) collatz(n / 2) else collatz(3 * n + 1) } There is no recursion if n == 1 In each other case, the last operation is a recursive call A good compiler can replace tail recursion with a loop def collatz(n: Int): Int = { var nn = n while (nn != 1) { if (nn % 2 == 0) nn = nn / 2 else nn = 3 * nn + 1 } nn } This is desirable because loops don’t cause the stack to grow

Factorial Here’s everybody’s first recursive function: def factorial(n: Long): Long = { if (n == 0 || n == 1) 1 else n * factorial(n - 1) } This is not tail recursive, because there is a multiplication that is performed after the recursive call Can the factorial function be rewritten to be tail recursive? Yes it can, and the technique for doing so can be applied to a lot of other functions, so it’s worth learning I’ll leave this as an exercise, since if you figure it out yourself you are much more likely to remember how to do it Here are three hints, which you can uncover one at at time if you get stuck (the text is white; select it and change the color) Use two functions; the second one should do all the recursive work The second function should have two parameters One of the parameters should be 1

Currying Here’s a function to find the hypotenuse of a right triangle: def hyp(a: Double, b: Double) = sqrt(a * a + b * b) Suppose you were to call it this way: val h = hyp(5.0, 12.0) You can think of this as the compiler substituting a value for each variable Suppose we substitute 5.0 for a first: sqrt(a * a + b * b) becomes sqrt(5.0 * 5.0 + b * b) And afterwards substitute 12.0 for b: sqrt(5.0 * 5.0 + b * b) becomes sqrt(5.0 * 5.0 + 12.0 * 12.0) which is then calculated (giving 13.0) Now suppose we stop after step 1 What we have after step 1 is a partially applied function Currying is a way to make partially applied functions

Currying in Scala Instead of giving our hyp function one parameter list, we can give it two parameter lists: scala> def hyp(a: Double)(b: Double) = sqrt(a * a + b * b) hyp: (a: Double)(b: Double)Double Now when we call it, we have to give it two argument lists, not just one list with two arguments: scala> hyp(5)(12) res2: Double = 13.0 We can stop with just the first list (but we need to use an underscore to tell Scala we know we left something out) scala> val h5 = hyp(5) _ h5: (Double) => Double = <function1> scala> h5(12) res3: Double = 13.0 With more parameters, we can break up the parameter list any way we like def foo(a: Int)(b: Int, c: String)(d: Double) = {...}

Another way to curry Here’s a function written in the usual way: scala> def avg(a: Double, b: Double) = (a + b) /2.0 avg: (a: Double,b: Double)Double Here we’re calling it in the usual way: scala> avg(5, 12) res6: Double = 8.5 Here we’re calling it with the first argument specified (5) but the second argument unspecified (_) scala> val a5 = avg(5, _: Double) a5: (Double) => Double = <function1> Notice that we had to specify the type of the omitted parameter Also pay careful attention to the type of the result Now let’s call our new, curried function: scala> a5(12) res7: Double = 8.5

Call-by-name parameters When using a function as a argument, the function parameter is used only when requested: Example: def foo(f: Int => Int) { println("In foo with " + f(10)) } foo(factorial) // prints "In foo with 3628800" Other types of parameters are first evaluated, then their values are passed into the function: Example: def foo(n: Long) { println(n} } foo(factorial(10)) What is passed into the function is the number 3628800 By using => as the first part of the type in a function definition, the function will treat a parameter as a function Example: def foo(f: => Int) { println("In foo with " + f(10)) } foo(factorial) // prints "In foo with 3628800" This is an example of call-by-name

Lazy evaluation Lazy evaluation is a technique whereby a computation is not actually performed until and unless the result is needed lazy val xxx = someLongAndExpensiveComputation ... if (we decide that we need xxx) { use xxx // The computation is done here } Ranges in Scala are lazy scala> println((1 to Int.MaxValue) take 3) Range(1, 2, 3) The Stream class supports lazy evaluation, and therefore allows “infinite” data structures (example from Programming Scala by Wampler & Payne) scala> lazy val fib: Stream[Int] = Stream.cons(0, Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2))) fib: Stream[Int] = <lazy> cons is like :: scala> fib.take(10).print 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, empty

Building control structures When calling a curried function, you can replace the last set of parentheses with braces scala> hyp(5) { 12 } res27: Double = 13.0 You can only put expressions inside parentheses, but you can put multiple “statements” inside braces This, plus currying, plus lazy evaluation, allows you to build your own control structures scala> def repeat(n: Int)(body: => Unit) { | for (i <- 1 to n) body | } repeat: (n: Int)(body: => Unit)Unit scala> repeat(3) { | println("Hello") | } Hello Hello Hello

XML XML is built into Scala as a data type—not just as something supported by some package scala> val name = "Dave" name: java.lang.String = Dave scala> val x = <html><body><h1>Hello, {name}!</h1></body></html> x: scala.xml.Elem = <html><body><h1>Hello, Dave!</h1></body></html>

DSL Scala has superb support for Domain Specific Languages A parser combinator is a function that takes only other functions as parameters and returns only functions BNF is essentially built into Scala as a combinator library Example: Arithmetic expressions (adapted from Odersky, pp. 620-621) BNF: <expr> ::= <term> { “+” <term> | “-” <term> } <term> ::= <factor> { “*” <factor> | “/” <factor> } <factor> ::= <floatingPointNumber> | “(” <expr> “)” Scala (~ is used to indicate one thing follows another in sequence): import scala.util.parsing.combinator._ class Arith extends JavaTokenParsers { def expr: Parser[Any] = term ~ rep("+" ~ term | "-" ~ term) def term: Parser[Any] = factor ~ rep("*" ~ factor | "/" ~ factor) def factor: Parser[Any] = floatingPointNumber | "(" ~ expr ~ ")" }

The End