the scheme language -- using it on the iphone
Post on 22-Jun-2015
9.283 Views
Preview:
DESCRIPTION
TRANSCRIPT
Writing iPhone apps in Schemeλ
λ
What is Scheme?
• Scheme is a dialect of Lisp, around since the 70s
• Functional, although not “pure”
• Extremely minimal, concise, and expressive
• Fully defined in R5RS [1]
• Build bigger parts from smaller parts
λ
Implementations
• Scheme by itself is the language specification
• There are many implementations of Scheme, each with different strengths:
• Gambit-C: speed, portability
• PLT: ease-of-use, libraries
• Scheme48: modules, formal semantics
• etc.
λ
Syntax• Uses S-expressions and prefix notation
• (function arg1 arg2 ...)
• (+ 5 5)
• 10
• (- (foo 3 2) 1)
• ?
• (+ 1 2 3 4 5)
• 15
λ
Syntax
λ
Functions• `define` declares functions
• (define (multiply x y) (other-function x) (* x y))
• The last value is returned, so unless `other-function` has a side effect, that call is essentially ignored
• `define` also create variables
• (define foo 5)
λ
Functions• `lambda` creates an anonymous function
• (lambda () (+ 1 2))
• (lambda (x y) (* x y))
• lambdas are ubiquitous in Scheme, too powerful to fully explain here, but it’s another dimension of Scheme’s expressiveness
• Our “multiply” function could be defined as:
• (define multiply (lambda (x y) (* x y)))
λ
Functions
• Functions are full closures with tail-recursion where possible
• (define (foo x y) (define z (get-z-axis)) (lambda () (+ x y z)))
• (define (bar) (read-network-blocking-and-act) (bar))
λ
Identifiers
• The name of an identifier is very flexible; can contain almost any character
• Very expressive
• (define the-number 5)
• (define !@#$%^&* 10)
• (define (is-alive?) ...)
λ
Lists
• The list is Scheme’s fundamental data structure
• Special syntax for lists:
• ‘(1 2 3 “foo”)
• ‘(1 2 3 (4 5 6))
• `(1 2 3 ,data) (define data “foo”)
• `(1 2 3 ,@data) (define data ‘(4 5 6))
λ
Lists• Lists are made up of “cons cells” or pairs
• Fundamental list functions:
• car
• (car ‘(1 2 3)) => 1
• cdr
• (cdr ‘(1 2 3)) => (2 3)
• cons
• (cons 1 ‘(2 3)) => (1 2 3)
λ
Lists
• Question: is a function not simply a list of elements?
• ‘(define (foo x y) (* x y))
• Yes, it is.
• In fact, any code in Scheme is data — simply a list of elements.
λ
Macros• Macros are Scheme functions that take
arguments and expand into different code
• Macros usually parse code, which is easy in Scheme because code is data!
• (define-macro (my-define func . body) (let ((name (car func)) (args (cdr func))) `(define ,name (lambda ,args ,@body))))
• (my-define (foo x y) (* x y)) expands into
• (define foo (lambda (x y) (* x y)))
λ
Macros
• Macros are lazy
• Macros allow an extremely powerful tool for extending the language for your needs
• Any new construct can be integrated
• You could redefine `if`
• Other macro systems exist which integrate pattern matching and other features
λ
Say again?
• Because of consistency and conciseness, it’s easy to write reusable, small bits of code in Scheme, which is good
• Other libraries implement tons of stuff, such as object systems, vectors, etc.
• SRFI’s
• Not covered: continuations, eval, and more
• Questions or comments?
λ
Practical Examples
• It turns out that it’s easy to implement functional programming in an imperative language like C [3]
• Gambit-C is a Scheme system which takes Scheme and compiles it to C [2]
• Extremely fast and portable
• Easy to interface to C/C++/Obj-C libraries
λ
Taking Scheme to the iPhone
• Cross-compiled Gambit’s run-time library for the ARM architecture (for the iPhone)
• Compiled my Scheme code to C
• Linked everything together, and it ran fine!
• Wasn’t that easy? [4]
Example
λ
Benefits
• Write iPhone apps in Scheme, of course
• Garbage collector
• Faster, real-time development
• Load in Scheme files at run-time
• Much more sane debugging
λ
Loading in Scheme at run-time
• Scheme has a `load` procedure which takes a filename, loads in the code and evaluates it
• In Gambit, this function loads code at run-time (`include` does the same thing at compile-time)
• Compile an app with a `load` statement, install it once, and develop with interpreted code forever.
Example
λ
Sane Debugging
• What is a REPL?
• Read-Eval-Print-Loop
• A debugger is a REPL with special commands
• Gambit comes with a nice command-line debugger, so we want this to work for our iPhone apps.
λ
Sane Debugging
• Since code is simply S-expressions, it’s really easy to parse, pass around the network, etc.
• We’ve created a “remote debugger” which implements the functionality of a networked REPL
• Instead of reading from the console, the REPL reads and writes from/to a network port
• A “debugging server” gives you access to REPLs running inside the application
Example
λ
• Compiling to C makes it easy to fine tune hotspots in your application
• (define fast-sqrt (c-lambda (float) float “fast_sqrt”))
• Once you’ve written and debugged your app sanely, profile and optimize specific parts of your app
• Re-write small pieces of code in C
• Use `declare` in Gambit
Optimizing
λ
• Another benefit of concise syntax is more advanced text editing
• Instead of thinking in terms of lines, think in terms of S-expressions
• Paredit implements key-bindings in Emacs to manipulate S-expressions
• Really powerful way of writing code
Paredit
Example
[1] R5RS: http://schemers.org/Documents/Standards/R5RS/
[2] Gambit Scheme: http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_Page
[3] 90 Minute Scheme-to-C compiler http://lambda-the-ultimate.org/node/349
[4] Writing iPhone apps in Scheme: http://jlongster.com/blog/2009/06/17/write-apps-iphone-scheme/
For more info, check out my blog:http://jlongster.com/blog
@jlongster
top related