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

Racket - Lisp beyond do Clojure

By Ronie Uliana

Racket - Lisp beyond do Clojure

As always, new ideas to programming languages will probably come from Lisp (as Paul Graham said). However, my guess is these things are not coming from Clojure, but from another Lisp-like language: Racket. In this presentation I show some of the things I think (hope, actually) that other languages get.

  • 83,502