Jump to content

Racket features: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
{{subst:prod|how-to guide}}
Added link to main article
Line 4: Line 4:
}}
}}
{{expert-subject|1=programming languages|date=August 2011}}
{{expert-subject|1=programming languages|date=August 2011}}

{{main|Racket (programming language)}}
This article includes source code and examples for the [[Racket (programming language)|Racket]] programming language. Please refer to the main article for more information.

== Examples ==
== Examples ==



Revision as of 12:18, 16 August 2011

This article includes source code and examples for the Racket programming language. Please refer to the main article for more information.

Examples

The following examples intend to give an overall perspective on how Racket can be used in different application domains. Most of them come from Racket's home page. To run them, install Racket, start DrRacket, paste the example program into the top area in DrRacket, and click the Run button. Alternatively, save the program to a file and run racket on the file.

Network programming

Racket makes it easy to use TCP sockets and spawn threads to handle them. This program starts a server at TCP port 12345 that echos anything a client sends back to the client.

 
#lang racket  ; An echo server
(define listener (tcp-listen 12345))
(let echo-server ()
  (define-values (in out) (tcp-accept listener))
  (thread (lambda () (copy-port in out)
                     (close-output-port out)))
  (echo-server))

The next example implements a web server using the web-server/insta language. Each time a connection is made to the server, the start function is called to get the HTML to send back to the client.

 
#lang web-server/insta
;; A "hello world" web server
(define (start request)
  (response/xexpr
   '(html
     (body "Hello World"))))}

Racket also includes the functions you would need to write scrapers and robots. As an example, the following function would list the Google results for a search string.

 
#lang racket ; Simple web scraper
(require net/url net/uri-codec)
(define (let-me-google-that-for-you str)
  (let* ([g "http://www.google.com/search?q="]
         [u (string-append g (uri-encode str))]
         [rx #rx"(?<=<h3 class=\"r\">).*?(?=</h3>)"])
    (regexp-match* rx (get-pure-port (string->url u)))))}

The library also includes support for protocols other than http:

#lang racket ; Sending email from racket
(require net/sendmail)
(sleep (* (- (* 60 4) 15) 60)) ; 4h - 15m
(send-mail-message
 (getenv "EMAIL") "Parking meter alert!"
 (list (getenv "EMAIL")) null null
 '("Time to go out and move your car."))

Filesystem manipulation, text processing and scripting

Racket is suitable for the kind of tasks often tackled with scripting languages like Perl or Python.

In the following example, the in-directory function constructs a sequence that walks a directory tree (starting with the current directory, by default) and generates paths in the tree. The for form binds p to each path in the sequence, and regexp-match? applies a pattern to the path.

 
#lang racket
;; Finds Racket sources in all subdirs
(for ([path (in-directory)])
  (when (regexp-match? #rx"[.]rkt$" path)
    (printf "source file: ~a\n" path)))

The next example uses a hash table to record previously seen lines. You can run this program in DrRacket, but it makes more sense from the command line, where it could be used as a filter.

#lang racket
;; Report each unique line from stdin
(let ([saw (make-hash)])
  (for ([line (in-lines)])
    (unless (hash-ref saw line #f)
      (displayln line))
    (hash-set! saw line #t)))}

The following example is a command-line script. To run the example, install Racket, paste the example program into a file, and run racket on the file with command-line arguments after the filename. Alternatively, for a Unix installation, you can add #!/usr/bin/env racket at the top and make the file executable, and then you can run the file directly. You could also generate a standalone executable from DrRacket and deploy it to a machine with no Racket installed.

The script is a kind of grep utility expecting three command-line arguments: a base directory, a file extension and a (perl-compatible) regular expression. It will recursively search all subdirs from the base directory for files ending in the given extension and then, for each of their lines matching the given regular expression, will output the name of the file, the line number, and the line contents.

 
#!/usr/bin/env racket
#lang racket
(command-line
 #:args (base-dir ext re)
 (for ([p (in-directory)]
       #:when (regexp-match? (string-append "[.]" ext "$") p)
       [(line num) (in-indexed (file->lines p))])
      (when (regexp-match? (pregexp re) line)
            (printf "~a:~a: ~a~n" p num line))))

Graphics

The 2htdp/image library provides easy-to-use functions for constructing images, and DrRacket can display an image result just as it can display a number result. In this case, a sierpinski function is defined and called (at the same time) to generate a Sierpinski triangle of depth 6.

#lang racket  ; A picture
(require 2htdp/image)
(let sierpinski ([n 8])
  (if (zero? n)
    (triangle 2 'solid 'red)
    (let ([t (sierpinski (- n 1))])
      (freeze (above t (beside t t))))))

The next program uses the plot library to draw plots of functions. Note that the plots are actual value, which DrRacket shows in graphical form.

#lang racket   ; draw a graph of cos
(require plot) ; and deriv^3(cos)
(define ((deriv f) x)
  (/ (- (f x) (f (- x 0.001))) 0.001))
(define (thrice f) (lambda (x) (f (f (f x)))))
(plot (mix (line ((thrice deriv) sin) #:color 'red)
           (line cos #:color 'blue)))}

GUI programming

This simple guesing game demonstates Racket's class-based GUI toolkit. The frame% class implements a top-level window, and button% obviously implements a button. The check function defined here produces an function that is used for the button's callback action.

#lang racket/gui ; A GUI guessing game
(define f (new frame% [label "Guess"]))
(define n (random 5))  (send f show #t)
(define ((check i) btn evt)
  (message-box "." (if (= i n) "Yes" "No")))
(for ([i (in-range 5)])
  (make-object button% (format "~a" i) f (check i)))

The GUI can be hand-coded in this way or with the help of a Designer program installable from Planet.

The foreign function interface

In case Racket libraries are not enough, you can always extend Racket's functionality by writing C extensions. Pulling out a foreign function is easy, and can even be done dynamically on the REPL.

 
#lang scheme/base ; Simple use of the FFI
(require ffi/unsafe)
(define mci-send-string
  (get-ffi-obj "mciSendStringA" "Winmm"
    (_fun _string [_pointer = #f] [_int = 0]
          [_pointer = #f] -> [ret : _int])))
(mci-send-string "play sound.wav wait")

Language extensions

Racket is useful for building other languages, and the Racket distribution comes with a range of different task-specific languages, which we will present here.

These domain-specific languages are not restricted to s-expression based syntaxes, like you would expect from any lisp with a macro system. Since Racket will let you affect the way a stream of characters will be translated into the s-expressions presented to the macro layer as a starting point, there's no restriction on the surface syntaxes of these extension languages.

Logic programming

This example uses the pre-packaged Racket implementation of Datalog, a logic programming language. If you use this from DrRacket, you'll see that it provides proper highlighting, Check Syntax, and a Datalog-specific REPL.

 
#lang datalog
ancestor(A, B) :- parent(A, B).
ancestor(A, B) :-
  parent(A, C), D = C, ancestor(D, B).
parent(john, douglas).
parent(bob, john).
ancestor(A, B)?

As you can see, Datalog syntax is not based on s-expressions, and thus doesn't look like a lisp at all. There is another language which will let you embed logic programming into the racket language, called racklog.

Scribble

The scribble family of languages make it easy to write and process textual content in Racket. In fact, Racket's documentation was written this way. To run the example, install Racket, start DrRacket, and paste the example program into the top area in DrRacket. When a program in a Scribble language is opened in DrRacket, a Scribble HTML button appears for rendering the document to HTML. Click it.

 
{#lang scribble/base
@; Generate a PDF or HTML document  
@title{Bottles --- @italic{Abridged}}
@(apply itemlist
  (for/list ([n (in-range 100 0 -1)])
    @item{@(format "~a" n) bottles.}))}

Typed Racket

In case your system grows bigger, you may eventually want to typecheck your code. Racket has a language extension that introduces a [[type system]] that will ensure that your program is typechecked before any execution. This type system is designed to let you add types after you've worked for a while in untyped mode, even if your untyped program wouldn't fit nicely in a conventional type system.

 
#lang typed/racket
;; Using higher-order occurrence typing
(define-type SrN (U String Number))
(: tog ((Listof SrN) -> String))
(define (tog l)
  (apply string-append (filter string? l)))
(tog (list 5 "hello " 1/2 "world" (sqrt -1)))

Lazy data structures

The lazy language implements lazy data structures in Racket, more like Haskell than Lisp. In the example, fibs is an infinite list whose 1000th element will not be computed until its value is really needed for printing.

 
#lang lazy
;; An infinite list:
(define fibs
  (list* 1 1 (map + fibs (cdr fibs))))

;; Print the 1000th Fibonacci number:
(print (list-ref fibs 1000))

Educational tools

Racket's mission includes education at all levels. This program uses the htdp/bsl teaching language, the 2htdp/image library for creating pictures in the teaching languages, and the 2htdp/universe library for interactive animations.

 
#lang htdp/bsl ; Any key inflates the balloon
(require 2htdp/image) (require 2htdp/universe)
(define (balloon b) (circle b "solid" "red"))
(define (blow-up b k) (+ b 5))
(define (deflate b) (max (- b 1) 1))
(big-bang 50 (on-key blow-up) (on-tick deflate)
          (to-draw balloon 200 200))