Save this in an.html file. function log(arg) { document.writeln(arg); } function identity(x) { return x; } log(identity(3));

Slides:



Advertisements
Similar presentations
Chapter 25 Lists, Stacks, Queues, and Priority Queues
Advertisements

The JavaScript Programming Language
CS Data Structures I Chapter 6 Stacks I 2 Topics ADT Stack Stack Operations Using ADT Stack Line editor Bracket checking Special-Palindromes Implementation.
JavaScript I. JavaScript is an object oriented programming language used to add interactivity to web pages. Different from Java, even though bears some.
Stacks.
Functional Programming in Scheme and Lisp.
CSC 270 Nov. 22, 2005 Last Day of Scheme Dr. Stephen Bloch
Introduction A function is called higher-order if it takes a function as an argument or returns a function as a result. twice :: (a  a)  a  a twice.
Intro to Scala Lists. Scala Lists are always immutable. This means that a list in Scala, once created, will remain the same.
Chapter 24 Lists, Stacks, and Queues
Main Index Contents 11 Main Index Contents Shifting blocks of elements… Shifting blocks of elements… Model of a list object… Model of a list object… Sample.
Arrays A list is an ordered collection of scalars. An array is a variable that holds a list. Arrays have a minimum size of 0 and a very large maximum size.
Programming with App Inventor Computing Institute for K-12 Teachers Summer 2012 Workshop.
Lecture 07 – Iterating through a list of numbers.
CSE Lecture 12 – Linked Lists …
Monads & Gonads Douglas Crockford.
the javascript language BY SA.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  Elements may appear more than once.
A Third Look At ML 1. Outline More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order.
C-LISP. LISP 2 Lisp was invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT).John McCarthyMassachusetts Institute.
Introducing JavaScript
1 Programming Languages (CS 550) Mini Language Interpreter Jeremy R. Johnson.
ICE1341 Programming Languages Spring 2005 Lecture #16 Lecture #16 In-Young Ko iko.AT. icu.ac.kr iko.AT. icu.ac.kr Information and Communications University.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
1 Programming Languages and Paradigms Lisp Programming.
CSE 341 Lecture 16 More Scheme: lists; helpers; let/let*; higher-order functions; lambdas slides created by Marty Stepp
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
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.
Javascript Client-side scripting. Up to now  We've seen a little about how to control  content with HTML  presentation with CSS  Javascript is a language.
© 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.
( (lambda (z) (define x (lambda (x) (lambda (y z) (y x)))) ( ( (x (lambda () z)) (lambda (z) z) 3 ) ) ) 2)
SchemeCOP Introduction to Scheme. SchemeCOP Scheme Meta-language for coding interpreters –“ clean ” semantics Scheme = LISP + ALGOL –simple.
JavaScript, Third Edition
LISP 1.5 and beyond A very quick tour. Data Atoms (symbols) including numbers – All types of numbers including Roman! (well, in the early days) – Syntactically.
F UNCTIONAL P ROGRAMMING 05 Functions. F UNCTIONS - G LOBAL F UNCTIONS fboundp Tells whether there is a function with a given symbol as its name > (fboundp.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
1 Lisp Functions –Built-in functions –Defining functions –Function Evaluation and Special Forms defun, if Control statements –Conditional if, cond –Repetition.
© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. C How To Program - 4th edition Deitels Class 05 University.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
VICTORIA UNIVERSITY OF WELLINGTON Te Whare Wananga o te Upoko o te Ika a Maui SWEN 432 Advanced Database Design and Implementation MongoDB Aggregation.
COP3530 Data Structures600 Stack Stack is one the most useful ADTs. Like list, it is a collection of data items. Supports “LIFO” (Last In First Out) discipline.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 7.
Chapter 9: MuPAD Programming II Procedures MATLAB for Scientist and Engineers Using Symbolic Toolbox.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
 Pearson Education, Inc. All rights reserved Arrays.
1 Append: process  (append list1 list2) (cons 1 (append ‘(2) list2)) (cons 1 (cons 2 (append ‘() list2))) (cons 1 (cons 2 list2)) (define (append list1.
Function Design in LISP. Program Files n LISP programs are plain text –DOS extensions vary; use.lsp for this course n (load “filename.lsp”) n Can use.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
CS190/295 Programming in Python for Life Sciences: Lecture 6 Instructor: Xiaohui Xie University of California, Irvine.
MIT-AITI: Functions Defining and Invoking Functions Functions as Data Function Scope: The call Object Function Arguments: The arguments objects Function.
1 Vectors, binary search, and sorting. 2 We know about lists O(n) time to get the n-th item. Consecutive cons cell are not necessarily consecutive in.
Click to add Text Javascript Presented by Bunlong VAN Basic.
CS314 – Section 5 Recitation 10
Introduction to Scheme
Using Lisp Lisp is a interactive system
REBOL Writing Functions.
Chapter 5 - Functions Outline 5.1 Introduction
6.001 SICP Data abstractions
ARRAYS MIT-AITI Copyright 2001.
CS5220 Advanced Topics in Web Programming JavaScript Basics
John McCarthy Pioneer in AI Also Lisp Formalize common-sense reasoning
topics mutable data structures
List and list operations (continue).
Lecture # , , , , מבוא מורחב.
Predefined Functions Revisited
CS3220 Web and Internet Programming JavaScript Basics
Presentation transcript:

Save this in an.html file. function log(arg) { document.writeln(arg); } function identity(x) { return x; } log(identity(3));

Fun With Functions Douglas Crockford

Write an identity function that takes an argument and returns that argument. identity(3) // 3

function identity(x) { return x; } var identity = function identity(x) { return x; };

function log(arg) { document.writeln(arg); } function identity(x) { return x; } log(identity(3));

Three Rules 1.If you have a question, you must ask it. 2.If you need more time, you must say so. 3.I won’t debug your stuff.

Quiz

What is x? function funky(o) { o = null; } var x = []; funky(x); log(x); A.null B.[] C.undefined D.throw

What is x? function funky(o) { o = null; } var x = []; funky(x); log(x); A.null B.[] C.undefined D.throw

function funky(o) { o = null; } var x = []; funky(x); log(x); x global [ ]

function funky(o) { o = null; } var x = []; funky(x); log(x); x global [ ] o funky

function funky(o) { o = null; } var x = []; funky(x); log(x); x global [ ] o funky

What is x? function swap(a, b) { var temp = a; a = b; b = temp; } var x = 1, y = 2; swap(x, y); log(x); A.1 B.2 C.undefined D.throw

What is x? function swap(a, b) { var temp = a; a = b; b = temp; } var x = 1, y = 2; swap(x, y); log(x); A.1 B.2 C.undefined D.throw

function swap(a, b) { var temp = a; a = b; b = temp; } var x = 1, y = 2; swap(x, y); log(x); global 1 2

function swap(a, b) { var temp = a; a = b; b = temp; } var x = 1, y = 2; swap(x, y); log(x); global 1 2 swap

function swap(a, b) { var temp = a; a = b; b = temp; } var x = 1, y = 2; swap(x, y); log(x); global 1 2 swap

Write three binary functions, add, sub, and mul, that take two numbers and return their sum, difference, and product. add(3, 4) // 7 sub(3, 4) // -1 mul(3, 4) // 12

function add(first, second) { return first + second; } function sub(first, second) { return first - second; } function mul(first, second) { return first * second; }

Write a function identityf that takes an argument and returns a function that returns that argument. var three = identityf(3); three() // 3

function identityf(x) { return function () { return x; }; }

Write a function addf that adds from two invocations. addf(3)(4) // 7

function addf(first) { return function (second) { return first + second; }; }

Write a function liftf that takes a binary function, and makes it callable with two invocations. var addf = liftf(add); addf(3)(4) // 7 liftf(mul)(5)(6) // 30

function liftf(binary) { return function (first) { return function (second) { return binary(first, second); }; }

Write a function curry that takes a function and an argument, and returns a function that can take a second argument. var add3 = curry(add, 3); add3(4) // 7 curry(mul, 5)(6) // 30

function curry(binary, first) { return function (second) { return binary(first, second); }; } function curry(func, first) { return liftf(func)(first); } currying schönfinkelisation

function curry(binary, first) { return function (second) { return binary(first, second); }; } function curry(binary, first) { return liftf(binary)(first); }

function curry(binary, first) { return function (second) { return binary(first, second); }; } function curry(func, first) { return liftf(func)(first); } currying schönfinkelisation

function curry(func) { var slice = Array.prototype.slice, args = slice.call(arguments, 1); return function () { return func.apply( null, args.concat(slice.call(arguments, 0)) ); }; } function curry(func,...first) { return function (...second) { return func(...first,...second); }; }

function curry(func) { var slice = Array.prototype.slice, args = slice.call(arguments, 1); return function () { return func.apply( null, args.concat(slice.call(arguments, 0)) ); }; } function curry(func,...first) { return function (...second) { return func(...first,...second); }; }

Without writing any new functions, show three ways to create the inc function. inc(5) // 6 inc(inc(5)) // 7

1. inc = addf(1); 2. inc = liftf(add)(1); 3. inc = curry(add, 1);

Write a function twice that takes a binary function and returns a unary function that passes its argument to the binary function twice. add(11, 11) // 22 var doubl = twice(add); doubl(11) // 22 var square = twice(mul); square(11) // 121

function twice(binary) { return function (a) { return binary(a, a); }; }

Write reverse, a function that reverses the arguments of a binary function. var bus = reverse(sub); bus(3, 2) // -1

function reverse(binary) { return function (first, second) { return binary(second, first); }; } function reverse(func) { return function (...args) { return func(...args.reverse()); }; }

Write a function composeu that takes two unary functions and returns a unary function that calls them both. composeu(doubl, square)(5) // 100

function composeu(f, g) { return function (a) { return g(f(a)); }; }

Write a function composeb that takes two binary functions and returns a function that calls them both. composeb(add, mul)(2, 3, 7) // 35

function composeb(f, g) { return function (a, b, c) { return g(f(a, b), c); }; }

Write a once function that allows a binary function to be called only once. var add_once = once(add); add_once(3, 4) // 7 add_once(3, 5) // undefined

function once(binary) { var flag = true; return function (a, b) { if (flag) { flag = false; return binary(a, b); } return undefined; }; }

function once(any) { var flag = true; return function (...all) { if (flag) { flag = false; return any(...all); } return undefined; }; }

Write a fromTo function that produces a generator that will produce values in a range. var index = fromTo(0, 3); index() // 0 index() // 1 index() // 2 index() // undefined

function fromTo(from, to) { return function () { var value = from; if (value < to) { from += 1; return value; } return undefined; }; }

Write an element function that takes an array and an optional generator (like the result of fromTo) and produces a generator that will produce the elements of the array. var ele = element([ 'a', 'b', 'c', 'd' ], fromTo(1, 3)); ele() // 'b' ele() // 'c' ele() // undefined

function element(array, gen) { if (gen === undefined) { gen = fromTo( 0, array.length ); } return function () { var index = gen(); if (index !== undefined) { return array[index]; } }; }

Write a collect function that takes a generator and an array and produces a function that will collect the results in the array. var array = [], col = collect(fromTo(5, 7), array); col() // 5 col() // 6 col() // undefined array // [5, 6]

function collect(gen, array) { return function () { var value = gen(); if (value !== undefined) { array.push(value); } return value; }; }

Write a filter function that takes a generator and a predicate and produces a generator that produces only the values approved by the predicate. var fil = filter(fromTo(0, 5), function third(value) { return (value % 3) === 0; }); fil() // 0 fil() // 3 fil() // undefined

function filter(gen, predicate) { return function () { var value; do { value = gen(); } while ( value !== undefined && !predicate(value) ); return value; }; }

function filter(gen, predicate) { return function recur() { var value = gen(); if ( value === undefined || predicate(value) ) { return value; } return recur(); }; }

Write a concat function that takes two generators and produces a generator that combines the sequences. var con = concat(fromTo(0, 3), fromTo(0,2)); con() // 0 con() // 1 con() // 2 con() // 0 con() // 1 con() // undefined

function concat(gen1, gen2) { return function () { var value; if (gen1 !== undefined) { value = gen1(); if (value !== undefined) { return value; } gen1 = undefined; } return gen2(); }; }

Write a repeat function that takes a generator and calls it until it returns undefined. var array = []; repeat(collect(fromTo(0, 4), array)); log(array); // 0, 1, 2, 3

function repeat(gen) { var value; do { value = gen(); } while (value !== undefined); } function repeat(func) { if (func() !== undefined) { return repeat(func); }

function repeat(gen) { var value; do { value = gen(); } while (value !== undefined); } function repeat(gen) { if (gen() !== undefined) { return repeat(gen); }

Write a map function that takes an array and a unary function, and returns an array containing the result of passing each element to the unary function. Use the repeat function. map([2, 1, 0], inc) // [3, 2, 1]

function map(array, unary) { var ele = element(array), result = []; repeat(collect(function () { var value = ele(); if (value !== undefined) { return unary(value); } }, result)); return result; }

Write a reduce function that takes an array and a binary function, and returns a single value. Use the repeat function. reduce([], add) // undefined reduce([2], add) // 2 reduce([2, 1, 0], add) // 3

function reduce(array, binary) { var ele = element(array), result; repeat(function () { var value = ele(); if (value !== undefined) { result = result === undefined ? value : binary(result, value); } return value; }); return result; }

Write a counter function that returns an object containing two functions that implement an up/down counter, hiding the counter. var object = counter(10), next = object.next, prev = object.prev; next() // 11 prev() // 10 prev() // 9 next() // 10

function counter(value) { return { next: function () { value += 1; return value; }, prev: function () { value -= 1; return value; } }; }

Make a revocable function that takes a unary function, and returns an object containing an invoke function that can invoke the unary function, and a revoke function that disables the invoke function. var rev = revocable(identity), invoke = rev.invoke; invoke(7); // 7 rev.revoke(); invoke(8); // undefined

function revocable(unary) { return { invoke: function (arg) { if (unary !== undefined) { return unary(arg); } }, revoke: function () { unary = undefined; } }; }

Make a function gensymf that makes a function that generates unique symbols. var geng = gensymf("G"), genh = gensymf("H"); geng() // "G1" genh() // "H1" geng() // "G2" genh() // "H2"

function gensymf(prefix) { var number = 0; return function () { number += 1; return prefix + number; }; }

Write a function gensymff that takes a unary function and a seed and returns a gensymf. var gensymf = gensymff(inc, 0), geng = gensymf("G"), genh = gensymf("H"); geng() // "G1" genh() // "H1" geng() // "G2" genh() // "H2"

function gensymff(unary, seed) { return function (prefix) { var number = seed; return function () { number = unary(number); return prefix + number; }; }

Make a function fibonaccif that returns a generator that will return the next fibonacci number. var fib = fibonaccif(0, 1); fib() // 0 fib() // 1 fib() // 2 fib() // 3 fib() // 5

function fibonaccif(a, b) { var i = 0; return function () { var next; switch (i) { case 0: i = 1; return a; case 1: i = 2; return b; default: next = a + b; a = b; b = next; return next; } }; }

function fibonaccif(a, b) { return function () { var next = a; a = b; b += next; return next; }; }

function fibonaccif(a, b) { return concat( concat( once(identityf(a)), once(identityf(b)) ), function fibonacci() { var next = a + b; a = b; b = next; return next; } ); }

var single = compuseu(identifyf, once); function fibonaccif(a, b) { return concat( concat(single(a), single(b)), function fibonacci() { var next = a + b; a = b; b = next; return next; } ); }

function fibonaccif(a, b) { return concat( element([a, b]), function fibonacci() { var next = a + b; a = b; b = next; return next; } ); }

Write a function m that takes a value and an optional source string and returns them in an object. JSON.stringify(m(1)) // {"value": 1, "source": "1"} JSON.stringify(m(Math.PI, "pi")) // {"value": …, "source": "pi"}

function m(value, source) { return { value: value, source: typeof source === 'string' ? source : String(value) }; }

Write a function addm that takes two m objects and returns an m object. JSON.stringify(addm(m(3), m(4))) // {"value": 7, "source": "(3+4)"} JSON.stringify(addm(m(1), m(Math.PI, "pi"))) // {"value": …, "source": "(1+pi)"}

function addm(a, b) { return m( a.value + b.value, "(" + a.source + "+" + b.source + ")" ); }

Write a function liftm that takes a binary function and a string and returns a function that acts on m objects. var addm = liftm(add, "+"); JSON.stringify(addm(m(3), m(4))) // {"value": 7, "source": "(3+4)"} JSON.stringify(liftm(mul, "*")(m(3), m(4))) // {"value": 12, "source": "(3*4)"}

function liftm(binary, op) { return function (a, b) { return m( binary(a.value, b.value), "(" + a.source + op + b.source + ")" ); }; }

Modify function liftm so that the functions it produces can accept arguments that are either numbers or m objects. var addm = liftm(add, "+"); JSON.stringify(addm(3, 4)) // {"value": 7, "source": "(3+4)"}

function liftm(binary, op) { return function (a, b) { if (typeof a === 'number') { a = m(a); } if (typeof b === 'number') { b = m(b); } return m( binary(a.value, b.value), "(" + a.source + op + b.source + ")" ); }; }

Write a function exp that evaluates simple array expressions. var sae = [mul, 3, 3]; exp(sae) // 9 exp(42) // 42

function exp(value) { return Array.isArray(value) ? value[0]( value[1], value[2] ) : value; }

Modify exp to evaluate nested array expressions. var nae = [ Math.sqrt, [ add, [square, 3], [square, 4] ] ]; exp(nae) // 5

function exp(value) { return Array.isArray(value) ? value[0]( exp(value[1]), exp(value[2]) ) : value; } // recursion: a function calls itself

Write a function addg that adds from many invocations, until it sees an empty invocation. addg() // undefined addg(2)() // 2 addg(2)(7)() // 9 addg(3)(4)(0)() // 7 addg(1)(2)(4)(8)() // 15

function addg(first) { function more(next) { if (next === undefined) { return first; } first += next; return more; } if (first !== undefined) { return more; } // retursion: a function returns itself

Write a function liftg that will take a binary function and apply it to many invocations. liftg(mul)() // undefined liftg(mul)(3)() // 3 liftg(mul)(3)(4)(0)() // 0 liftg(mul)(1)(2)(4)(8)() // 64

function liftg(binary) { return function (first) { if (first === undefined) { return first; } return function more(next) { if (next === undefined) { return first; } first = binary(first, next); return more; }; }

Write a function arrayg that will build an array from many invocations. arrayg() // [] arrayg(3)() // [3] arrayg(3)(4)(5)() // [3, 4, 5]

function arrayg(first) { var array = []; function more(next) { if (next === undefined) { return array; } array.push(next); return more; } return more(first); }

function arrayg(first) { if (first === undefined) { return []; } return liftg( function (array, value) { array.push(value); return array; } )([first]); }

Make a function continuize that takes a unary function, and returns a function that takes a callback and an argument. sqrtc = continuize(Math.sqrt); sqrtc(alert, 81) // 9

function continuize(unary) { return function (callback, x) { return callback(unary(x)); }; } function continuize(any) { return function (callback,...x) { return callback(any(...x)); }; }

function constructor(init) { var that = other_constructor(init), member, method = function () { // init, member, method }; that.method = method; return that; }

function constructor(spec) { let {member} = spec, {other} = other_constructor(spec), method = function () { // spec, member, other, method }; return Object.freeze({ method, other }); }

Make an array wrapper object with methods get, store, and append, such that an attacker cannot get access to the private array. myvector = vector(); myvector.append(7); myvector.store(1, 8); myvector.get(0) // 7 myvector.get(1) // 8

function vector() { var array = []; return { get: function get(i) { return array[i]; }, store: function store(i, v) { array[i] = v; }, append: function append(v) { array.push(v); } }; }

function vector() { var array = []; return { get: function get(i) { return array[i]; }, store: function store(i, v) { array[i] = v; }, append: function append(v) { array.push(v); } }; var stash; } myvector.store('push', function () { stash = this; }); myvector.append(); // stash is array

function vector() { var array = []; return { get: function (i) { return array[+i]; }, store: function store(i, v) { array[+i] = v; }, append: function (v) { array[array.length] = v; } }; }

Make a function that makes a publish/subscribe object. It will reliably deliver all publications to all subscribers in the right order. my_pubsub = pubsub(); my_pubsub.subscribe(log); my_pubsub.publish("It works!"); // log("It works!")

function pubsub() { var subscribers = []; return { subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { subscribers[i](publication); } }; }

function pubsub() { var subscribers = []; return { subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { subscribers[i](publication); } }; } my_pubsub.subscribe();

function pubsub() { var subscribers = []; return { subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { try { subscribers[i]( publication ); } catch (ignore) {} } }; } "

function pubsub() { var subscribers = []; return { subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { try { subscribers[i]( publication ); } catch (ignore) {} } }; } my_pubsub.publish = undefined;

function pubsub() { var subscribers = []; return Object.freeze({ subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { try { subscribers[i]( publication ); } catch (ignore) {} } }); }

function pubsub() { var subscribers = []; return Object.freeze({ subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { var i, length = subscribers.length; for (i = 0; i < length; i += 1) { try { subscribers[i]( publication ); } catch (ignore) {} } }); } my_pubsub.subscribe(function () { this.length = 0; }); "

function pubsub() { var subscribers = []; return Object.freeze({ subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { subscribers.forEach(function (s) { try { s(publication); } catch (ignore) {} }); } }); }

function pubsub() { var subscribers = []; return Object.freeze({ subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { subscribers.forEach(function (s) { try { s(publication); } catch (ignore) {} }); } }); } my_pubsub.subscribe(once(function () { my_pubsub.publish("Out of order"); })); "

function pubsub() { var subscribers = []; return Object.freeze({ subscribe: function (subscriber) { subscribers.push(subscriber); }, publish: function (publication) { subscribers.forEach(function (s) { setTimeout(function () { s(publication); }, 0); }); } }); } "