Version: 5.0.1
Moby: Racket for Mobile Phones
1 What is Moby?
Moby is a project from the PLT team. The Moby compiler
consumes Advanced Student Language (ASL) programs that use World
primitives, and produces applications for mobile platforms. The
current prototype supports web browsers and smartphones.
Our long-term goal is to make Racket the premiere reactive scripting
language for mobile phones.
Shriram Krishnamurthi presented the ideas behind Moby at ILC 2009 in
his talk The Moby Scheme Compiler for Smartphones.
Moby requires Racket 5.0.1.
2 Quick Start
Let’s see if Moby has been installed on your system. Run the following simple program.
#lang planet dyoo/moby:3:4 |
"hello world" |
true |
(define (f x) (* x x)) |
|
(check-expect (f 42) 1764) |
|
(check-expect (map f '(1 2 3 4 5)) |
(list 1 4 9 16 25)) |
On the very first run of this program, Racket may pause as it installs
the Moby PLaneT package and generates its documentation. Expect to wait a
few minutes for the installation to complete.
Moby programs can run in DrRacket as long as they don’t use any
Javascript-specific functions. Let’s create a simple application that
does use a Javascript context. The following example shows a rapidly
incrementing counter. Create a file "counter.rkt" in the
Module language with this content:
#lang planet dyoo/moby:3:4 |
(define initial-world 0) |
(big-bang initial-world (on-tick add1)) |
This program can be partially executed in Racket, but evaluation will
halt on the big-bang because it’s a function that requires a
Javascript context. The function run-in-browser
can be used to provide a Javascript environment in your web browser:
This will bring up a web server and a browser window with the running program.
As a warning, package generation may take about 30 seconds to complete.
Moby programs can be be translated to Android phone packages. To
create an Android apk package, you can use
create-android-phone-package. Create a file called
"build-counter.rkt" with the following content:
Running this will take "counter.rkt" and compile it to an Android package "counter.apk".
Because Moby programs use the web, they can dynamically
generate DOM trees and style them with CSS, as in the examples below.
This example renders the world as a paragraph of text, styled with a
font-size of 30. It uses draw-page and draw-css to
draw the web page. The background color of the paragraph changes
as the world reacts to the clock tick.
#lang planet dyoo/moby:3:4 |
|
; The world is a number. |
(define initial-world 0) |
|
(define (draw-html w) |
(list (js-p '(("id" "myPara"))) |
(list (js-text "hello world")))) |
|
(define (draw-css w) |
`(("myPara" ("font-size" "30") |
("background-color" |
,(format "rgb(~a, ~a, ~a)" |
(modulo w 255) |
(modulo w 255) |
(modulo w 255)))))) |
|
(big-bang initial-world |
(to-draw-page draw-html draw-css) |
(on-tick add1)) |
The next example shows an image and an input text field. As with the
previous example, it uses draw-html and draw-css to
construct the web page, and every time the world changes, the runtime environment
reacts by re-drawing the web page.
#lang planet dyoo/moby:3:4 |
(define (form-value w) |
(format "~a" w)) |
|
(define (update-form-value w v) |
(string->number v)) |
|
(define elt |
(js-input "text" update-form-value '())) |
|
(define (draw-html w) |
(list (js-div) |
(list (js-img "http://racket-lang.org/logo.png")) |
(list elt) |
(list (js-p '(("id" "aPara"))) |
(list (js-text (format "~a" w)))))) |
|
(define (draw-css w) |
'(("aPara" ("font-size" "50px")))) |
|
(big-bang false |
(to-draw-page draw-html draw-css)) |
One subtle point about this program is that elt is constructed at the toplevel
so that the element persists from one call of draw-html to the next.
If elt were inlined into draw-html’s definition, then the text field
would be cleared with every world update.
We can also use phone-specific features, such as geolocation.
The following program shows the current location.
#lang planet dyoo/moby:3:4 |
(require (planet dyoo/moby:3:4/phone/location)) |
|
(define (make-message w lat lng) |
(format "I think I am at: ~s ~s" lat lng)) |
|
(big-bang "initial state" |
(on-location-change make-message)) |
Note that the program requires phone/location, one of the
modules provided by this package. If this program is evaluated with
run-in-browser, the browser environment will provide a
control at the bottom of the page to allow the user to inject
artificial GPS positions for testing.
The last example is a phone mood ring called "mood-ring.rkt":
it shows a single DIV whose background color is controlled by the
phone’s orientation; it uses phone/tilt to get at the
orientation of the phone, and arbitrarily maps it to a color.
#lang planet dyoo/moby:3:4 |
(require (planet dyoo/moby:3:4/phone/tilt)) |
|
; The world is a color. |
(define initial-world (make-color 0 0 0)) |
|
; tilt: world number number number -> world |
; Tilting the phone adjusts the color. |
(define (tilt w azimuth pitch roll) |
(make-color (scale azimuth 360) |
(scale (+ pitch 90) 180) |
(scale (+ roll 90) 180))) |
|
; scale-azimuth: number -> number |
; Take a number going from 0-360 and scale it to a number between 0-255 |
(define (scale n domain-bound) |
(inexact->exact (floor (* (/ n domain-bound) 255)))) |
|
; User interface. |
(define view (list (js-div '((id "background"))))) |
|
(define (draw-html w) view) |
|
(define (draw-css w) |
(list (list "background" |
(list "background-color" |
(format "rgb(~a, ~a, ~a)" |
(color-red w) |
(color-green w) |
(color-blue w))) |
(list "width" "300") |
(list "height" "300")))) |
|
|
|
(big-bang initial-world |
(on-tilt tilt) |
(to-draw-page draw-html draw-css)) |
Again, to package the program, we use create-android-phone-package.
3 Running and packaging Android programs
Runs the given input-file in a Javascript context.
|
input-file : path-string? |
output-apk : path-string? |
Creates an Android phone package.
4 Phone API
The functions in this section provide access to features on a
smartphone. In order to make testing easier, if these functions are
used outside of a phone, Moby will inject mocks that allow the
user to simulate phone events.
The other language bindings of Moby language are provided by the js-vm
PLaneT package; please refer to the documentation of js-vm:
(part ("(planet main.rkt (dyoo js-vm.plt 1 8))" "top"))
Here is an example that shows the status of all three sensors:
#lang planet dyoo/moby:3:4 |
(require (planet dyoo/moby:3:4/phone/tilt)) |
(require (planet dyoo/moby:3:4/phone/location)) |
|
(define-struct gps (lat lng)) |
(define-struct tilt (a p r)) |
(define-struct accel (x y z)) |
|
(define-struct sensors (gps tilt accel)) |
|
(define (update-gps w lat lng) |
(make-sensors (make-gps lat lng) |
(sensors-tilt w) |
(sensors-accel w))) |
|
(define (update-tilt w a p r) |
(make-sensors (sensors-gps w) |
(make-tilt a p r) |
(sensors-accel w))) |
|
(define (update-accel w x y z) |
(make-sensors (sensors-gps w) |
(sensors-tilt w) |
(make-accel x y z))) |
|
(big-bang (make-sensors (make-gps "loading" "loading") |
(make-tilt "loading" "loading" "loading") |
(make-accel "loading" "loading" "loading")) |
(on-location-change update-gps) |
(on-tilt update-tilt) |
(on-acceleration update-accel)) |
4.1 Location (GPS)
(require (planet dyoo/moby:3:4/phone/location)) |
(on-location-change world-updater) → handler |
world-updater : (world [latitude number] [longitude number] -> world) |
Constructs a world handler that watches for changes in the phone’s geographic location.
4.2 Motion sensors and tilt
(require (planet dyoo/moby:3:4/phone/tilt)) |
(on-acceleration world-updater) → handler |
world-updater : (world [x number] [y number] [z number] -> world) |
Constructs a world handler that watches acceleration updates.
(on-shake world-updater) → handler |
world-updater : (world -> world) |
Constructs a world handler that watches the phone for shakes.
(on-tilt world-updater) → handler |
world-updater : (world [azimuth number] [pitch number] [roll number] -> world) |
Constructs a world handler that watches changes in orientation.
4.3 Internet access
(require (planet dyoo/moby:3:4/phone/internet)) |
This module does not provide any bindings, but is meant to notify
create-android-phone-package if a program needs permission to
access the internet. If your program is using image-url or
js-img, add a require to this module.