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.
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 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:
#lang racket (require (planet dyoo/moby:3:10)) (create-android-phone-package "counter.rkt" "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:10 ; 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:10 (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.
#lang planet dyoo/moby:3:10 (require (planet dyoo/moby:3:10/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:10 (require (planet dyoo/moby:3:10/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.
#lang racket (require (planet dyoo/moby:3:10)) (create-android-phone-package "mood-ring.rkt" "mood.apk")
|(require (planet dyoo/moby:3:10))|
|(run-in-browser input-file) → void|
|input-file : path-string?|
|input-file : path-string?|
|output-apk : path-string?|
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.
Here is an example that shows the status of all three sensors:
#lang planet dyoo/moby:3:10 (require (planet dyoo/moby:3:10/phone/tilt)) (require (planet dyoo/moby:3:10/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))
|(require (planet dyoo/moby:3:10/phone/location))|
|(on-location-change world-updater) → handler|
|world-updater : (world [latitude number] [longitude number] -> world)|
|(require (planet dyoo/moby:3:10/phone/tilt))|
|(on-acceleration world-updater) → handler|
|world-updater : (world [x number] [y number] [z number] -> world)|
|(on-shake world-updater) → handler|
|world-updater : (world -> world)|
|(on-tilt world-updater [delay-in-seconds]) → handler|
|world-updater : (world [azimuth number] [pitch number] [roll number] -> world)|
|delay-in-seconds : real? = 1|
|(require (planet dyoo/moby:3:10/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.