Racket

Lisp beyond Clojure

Ronie Uliana

Software Architect

Data Scientist

Who is presenting?

working at

http://vagas.com

This talk is NOT...

  • Not about Clojure
  • Not about trolling Clojure
  • Not about the next big language

The talk IS...

About things that can become main stream (I hope) from another "Lisp-like":

Racket

Sobre Lisp-likes...

It's 2002, and programming languages have almost caught up with 1958.

Paul Graham

"Revenge of the Nerds"

Paul Graham

Lisp evolves

Clojure | Racket

(Common Lisp) => Clojure

  • Software Transactional Memory
  • Persistent Collections
  • Multimethods

(Lisp) => (Scheme) => Racket

  • Parameters
  • Custodians
  • Macros (Hygienic / Reader)
  • Modules
  • ...

Racket

A programmable programming language

Focus

build applications DSLs

(and then build applications)

... very interesting approach!

Parameters

How do you...

  • Get your database configuration?
  • Get the number of threads?
  • Maximum number of iterations?

with-bindings? Globals? Singleton? Read a config file in the middle of the code?

"sideband data"*

function arguments

*Avdi Grimm - Exceptional Ruby

Sideband data

#lang racket

(define number-of-threads
  (make-parameter 2))

(define (work)
  ;work hard!
  (displayln (number-of-threads)))

(work) 

(parameterize ([number-of-threads 42])
  (work))

(work)

Can it spread?

Languages have "thread local".

They are discouraged :(

Configs are a mess.

 

Racket parameters seems:

- Easy

- Useful

- Really easy

Parameters...

Custodians

How do you...

  • Open and close files?
  • Open and close connections?
  • Start and kill threads?
  • Manage resources?

open/finally/close? ensure? using? with-open? 

Custodian

Closes and clear...

(define (do-work a-function)
  (define cust (make-custodian))
  ...
  (parameterize ([current-custodian cust])
    (dynamic-wind
     (λ () ... inicializa
     (λ () ... faz algo/abre coisas
     (λ () (custodian-shutdown-all cust))))

File

Thread

Socket

?

Cust 1

Cust 2

Cust 3

Can it spread?

It releases all resources with a single call.

 

Racket custodians seems:

- Safe

- Easy

- Not yet polished

  ("dynamic-wind" needed)

Custodians...

Macros

Hygienic (simple)

Pattern-based Macros

(define (hello b)
  (let ([a "Hello,"]
        [c "!"])
    (format "~a ~a~a" a b c)))

I feel...

"let" with too much parenthesis

and nesting (nah, not really)

Pattern-based Macros

(define-syntax-rule (given (bind expr) ...)
  (begin
    (define bind expr) ...))
(define (hello b)
  (given [a "Hello, "]
         [c !])
  (format "~a ~a~a" a b c))

Pattern-based Macros

let's exaggerate :)

(define-syntax (given stx)
  (syntax-parse stx
    #:literals (=)
    [(_ bind = expr)
     #'(define bind expr)]
    [(_ bind = expr rest ...)
     #'(begin (define bind expr)
              (given rest ...))]))
(define (hello b)
  (given a = "Why"
         c = "???")
  (format "~a ~a~a" a b c))

Threading Macro

Racket style

#lang racket
(require threading)

(~>> '(100 200 300 400)
     (map add1)
     (take _ 2))

(~> '(100 200 300 400)
    (map add1 _)
    (take 2))

Can it spread?

Macros = metaprogramming

 

Racket macros seems:

- POWERFUL

- Simple Clean

Rust has "Pattern-based macros".

Elixir, Crystal, Julia...

Macros...

Macros

Reader... o_O

>_<

(regexp-match #px"\\d+" "123"

^_^

(regexp-match /\d+/ "123")

DEMO!

Can it spread?

Languages don't let you define literals.

Regexp, DateTime, Money, SQL, metrics, etc... (which system doesn't deal with them?)

 

Racket reader macros are:

- OMG Powerful

- The right way ®

- Still needs polishing

Reader macros

Modules

  1. File = module (roughly)

  2. A module has an interface

  3. The module is what it sees!

A module

is a language

Module

Module

I don't like "define"

hate-define.rkt
#lang racket
(provide (except-out (all-from-out racket) define)
         (rename-out (define def)))
hate-define-use.rkt
#lang s-exp "hate-define.rkt"
(define add2 (λ (x) (+ x 2)))
   (def add2 (λ (x) (+ x 2)))

Overwriting #%app

Let me show you a nice trick :)

Overwriting %#app

In Racket, every function application uses #%app behind the scenes...

(add1 10)
...
(%#app add1 10)

I can redefine #%app using modules

#lang racket
(provide (except-out (all-from-out racket) #%app)
         (rename-out [my-app #%app]))

(define-syntax-rule (my-app proc args ...)
  (begin
    (displayln proc)
    (#%app proc args ...)))
(add1 10)
...
(begin
  (displayln add1)
  (%#app add1 10))
(add1 10)
...
(%#app add1 10)

Can it spread?

Namespaces, import, requires are a mess. (Monkey patching, unpredictable effects, etc...)

Each language has a different way.

 

Racket modules seems:

- Poweful

- Simple

Modules!

More...

Phase Levels

Places (parallel processing)

Continuations (nothing new :p)

Contracts (Eiffel-like)

FFI

Tips:

Racket has no multimethods, that's a bit weird in the beginning (it has generics)

Collections are hmm... meh...  use: data/collections

Want to create your own language?

http://beautifulracket.com

Debugging:

racket -l errortrace -t <prog>

Thank you!

Ronie Uliana

ronie@vagas.com

@ronie

medium.com/@ronie

github.com/ruliana