Racket features: Difference between revisions
{{subst:prod|how-to guide}} |
Jarnaldich (talk | contribs) 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 may have been previously nominated for deletion: Wikipedia:Articles for deletion/Racket features exists. It is proposed that this article be deleted because of the following concern:
If you can address this concern by improving, copyediting, sourcing, renaming, or merging the page, please edit this page and do so. You may remove this message if you improve the article or otherwise object to deletion for any reason. Although not required, you are encouraged to explain why you object to the deletion, either in your edit summary or on the talk page. If this template is removed, do not replace it. This message has remained in place for seven days, so the article may be deleted without further notice. Find sources: "Racket features" – news · newspapers · books · scholar · JSTOR Nominator: Please consider notifying the author/project: {{subst:proposed deletion notify|Racket features|concern=how-to guide}} ~~~~ Timestamp: 20110816110845 11:08, 16 August 2011 (UTC) Administrators: delete |
This article needs attention from an expert in programming languages. Please add a reason or a talk parameter to this template to explain the issue with the article.(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))