'Getting' Clojure

'Getting' Clojure

'(parentheses are just hugs for your code)

74bff20b7f21728b504dacb6255dee6d?s=128

Jason Lewis

July 19, 2013
Tweet

Transcript

  1. 'GETTING' CLOJURE '(PARENTHESES ARE JUST HUGS FOR YOUR CODE) Created

    by / Jason Lewis Gary Trakhman
  2. Javascript f u n c t i o n (

    ) { r e t u r n 5 ; } FUNCTIONS
  3. Put some parens around it, kill the braces ( f

    u n c t i o n ( ) r e t u r n 5 ; )
  4. Change 'function' to 'fn', makes args into a vector (

    f n [ ] r e t u r n 5 ; )
  5. Kill the 'return', last thing's always returned. Welcome to Clojure.

    ( f n [ ] 5 )
  6. Move the left parenthesis over a bit more... Done. s

    o m e F u n c t i o n ( a r g 1 , a r g 2 , a r g 3 ) ; ( s o m e F u n c t i o n a r g 1 a r g 2 a r g 3 ) CALLING STUFF
  7. THIS ISN'T AN ACCIDENT Javascript is 'Lisp in C's Clothing'

    Says Crockford: http://www.crockford.com/javascript/javascript.html
  8. PUT ANOTHER WAY... Q: Why do you think we've gotten

    so much mileage out of javascript? A: Lisp is very powerful, and it will never die
  9. Should look familiar Don't freak out DON'T FREAK OUT {

    : k e y 1 5 , : k e y 2 n i l } [ 1 2 3 4 " f i v e " ] [ 1 [ 2 ] # { 3 } { 4 4 } ( c o n s t a n t l y 5 ) ] = > ( r a n g e 1 0 ) ( 0 1 2 3 4 5 6 7 8 9 ) = > ( t a k e 1 1 ( r a n g e ) ) ( 0 1 2 3 4 5 6 7 8 9 1 0 ) = > ( l a s t ( r a n g e ) ) ; ; H o p e y o u d o n ' t m i n d w a i t i n g a l o n g t i m e . DATA
  10. Evals to... ; ; s e m i c o

    l o n s a r e c o m m e n t s , c o m m a s a r e i g n o r e d , ; ; c h e c k o u t t h i s w e i r d h a s h - m a p { : a - k e y w o r d 5 , " a s t r i n g k e y " " a s t r i n g v a l u e " , [ " a " : v e c t o r " a c t i n g " : a s [ : a : c o m p o u n d ] " k e y " ] ( f n [ ] " a n o - a r g f u n c t i o n t h a t r e t u r n s t h i s m u l t i - l i n e s t r i n g , t h e f u n c t i o n i t s e l f i s t h e v a l u e " ) , + ' ( f u n c t i o n s c a n b e k e y s t o o , a n d w h e n y o u q u o t e s y m b o l s , y o u j u s t h a v e s y m b o l s , n o t w h a t t h e y r e p r e s e n t ) } { : a - k e y w o r d 5 , " a s t r i n g k e y " " a s t r i n g v a l u e " , [ " a " : v e c t o r " a c t i n g " : a s [ : a : c o m p o u n d ] " k e y " ] # < u s e r $ e v a l 3 3 1 $ f n _ _ 3 3 2 u s e r $ e v a l 3 3 1 $ f n _ _ 3 3 2 @ a 5 8 5 e f > , # < c o r e $ _ P L U S _ c l o j u r e . c o r e $ _ P L U S _ @ 2 0 a 1 2 d 8 f > ( f u n c t i o n s c a n b e k e y s t o o a n d w h e n y o u q u o t e s y m b o l s y o u j u s t h a v e s y m b o l s n o t w h a t t h e y r e p r e s e n t ) } EVERYTHING IS DATA
  11. ANYTHING CAN BE A KEY, BECAUSE 1. Every object is

    also a 'value' 2. Values have true equality 3. Values Never Change (Immutability) 4. Without immutability, objects are just buckets in memory ...have you ever trusted a bucket with no values?
  12. Q: Why is this big news? A: I can write

    code and rest assured that other parts of my program can't change the data that I'm working on. Q: But I thought every program is simply a short-lived http request handler that talks to a database? We just throw the program state out after every request! A: Well, that's one way to do it.
  13. http://www.ibm.com/developerworks/library/wa-aj- multitier2/

  14. NODE.JS... http://www.andrerodrigues.me/isel- workshop/intro.html#/24

  15. NODE.JS... IS NOTHING NEW We can write our own loops

    Node.js assumes threaded programming is hard, and throws out the baby with the bath-water Threaded programming is hard without real 'Data' or 'Values' Composition of any sort is simpler with data
  16. APPROXIMATING NODE.JS 'Agents' are asynchronous queues, sharing threadpools to do

    work, storing the last value returned. ( d e f n i n c - l a s t [ v a l ] ( c o n j v a l ( i n c ( l a s t v a l ) ) ) ) ; ; W e m a k e a s e q u e n c e o f 1 0 i n c - l a s t t a s k s , ; ; t h e n f o l l o w - u p w i t h a ' p r i n t l n ' t a s k ( d e f t a s k s ( c o n c a t ( r e p e a t 1 0 i n c - l a s t ) [ ( f n [ v a l ] ( p r i n t l n v a l ) v a l ) ] ) )
  17. ; ; s t a r t s o f

    f w i t h a v a l u e o f [ 0 ] ( l e t [ a ( a g e n t [ 0 ] ) ] ( d o s e q [ t t a s k s ] ( s e n d a t ) ) ) ; ; p r i n t s : [ 0 1 2 3 4 5 6 7 8 9 1 0 ] Agents are not values, they are mutable references with asynchronous semantics Clojure has other mutable references types, acting as 'containers' for values, for various use cases. Nothing prevents you from making your own.
  18. ( l e t [ f ( f u t

    u r e ( d o - a - b u n c h - o f - s t u f f ) ) ] ; ; i n a n o t h e r t h r e a d ( d o - s t u f f - i n - t h i s - t h r e a d ) ; ; r e t u r n t h e v a l u e i n f , b l o c k i n g i f i t ' s n o t f i n i s h e d ( d e r e f f ) ) MORE! Basically, Clojure promotes your ability to do whatever you want, by simplifying things to their bare essence.
  19. WHAT WE REALLY WANT Tools that let us 1. Compose

    Systems 2. Change our minds 3. Re-use components in different contexts, processes, servers, etc.. Data/Values give us the ability to decouple things easily
  20. '(code is data) BRAINSPLODE

  21. Read-Eval-Print-Loop ( c l a s s ( r e

    a d - s t r i n g " ( + 1 2 ) " ) ) ; ; c l o j u r e . l a n g . P e r s i s t e n t L i s t ( m a p c l a s s ( r e a d - s t r i n g " ( + 1 2 ) " ) ) ; ; ( c l o j u r e . l a n g . S y m b o l j a v a . l a n g . L o n g j a v a . l a n g . L o n g ) R-E-P-L 1. Read: (read-string "(+ 1 2)") => '(+ 1 2) 2. Eval: (eval '(+ 1 2)) => 3 3. What if there's something in the middle?
  22. This is only the beginning ( d e f n

    o n l y - e v e n ! [ v a l ] ( i f ( a n d ( i n t e g e r ? v a l ) ( o d d ? v a l ) ) ( i n c v a l ) v a l ) ) ( m a p o n l y - e v e n ! ( r e a d - s t r i n g " ( + 1 2 ) " ) ) ; ; ' ( + 2 2 ) ( e v a l ( m a p o n l y - e v e n ! ( r e a d - s t r i n g " ( + 1 2 ) " ) ) ) ; ; 4
  23. Everybody likes chaining, right? How is this implemented? Is this

    reusable? $ ( " # p 1 " ) . c s s ( " c o l o r " , " r e d " ) . s l i d e U p ( 2 0 0 0 ) . s l i d e D o w n ( 2 0 0 0 ) ;
  24. What if, as a library author, you could just not

    write that fluent interface code at all? ( u s e ' c l o j u r e . s t r i n g ) ; ; T h e s e a r e e q u i v a l e n t ( m a p t r i m ( s p l i t ( u p p e r - c a s e " h o l a , w o r l d " ) # " , " ) ) ; ; ( " H O L A " " W O R L D " ) ( - > " h o l a , w o r l d " u p p e r - c a s e ( s p l i t # " , " ) ( - > > ( m a p t r i m ) ) ) ; ; ( " H O L A " " W O R L D " )
  25. Really useful when you're doing a lot of collection operations,

    filtering, etc. ( - > > ( r a n g e ) ( f i l t e r e v e n ? ) ( m a p ( p a r t i a l * 2 ) ) ( t a k e 1 0 ) ( i n t o [ ] ) ) ; ; [ 0 4 8 1 2 1 6 2 0 2 4 2 8 3 2 3 6 ] ; ; v e r s u s ( i n t o [ ] ( t a k e 1 0 ( m a p ( p a r t i a l * 2 ) ( f i l t e r e v e n ? ( r a n g e ) ) ) ) ) 1. I find the flat one easier to think about. 2. Semantically equivalent. 3. No burden on implementing code. Functions don't care about how they're used. Giving the user choices is more effective with more powerful languages. Leads to simple, composable libraries.
  26. Let's look at a real one. ( d e f

    m a c r o l a z y - s e q " T a k e s a b o d y o f e x p r e s s i o n s t h a t r e t u r n s a n I S e q o r n i l , a n d y i e l d s a S e q a b l e o b j e c t t h a t w i l l i n v o k e t h e b o d y o n l y t h e f i r s t t i m e s e q i s c a l l e d , a n d w i l l c a c h e t h e r e s u l t a n d r e t u r n i t o n a l l s u b s e q u e n t s e q c a l l s . S e e a l s o - r e a l i z e d ? " { : a d d e d " 1 . 0 " } [ & b o d y ] ( l i s t ' n e w ' c l o j u r e . l a n g . L a z y S e q ( l i s t * ' ^ { : o n c e t r u e } f n * [ ] b o d y ) ) ) ; ; s i m p l y r e t u r n s a l i s t , a l l o c a t e s a J a v a o b j e c t ( L a z y S e q ) a n d w r a p s ; ; y o u r e x p r e s s i o n s i n a f u n c t i o n ( m a c r o e x p a n d - 1 ' ( l a z y - s e q A N Y T H I N G 1 A N Y T H I N G 2 ) ) ; ; ' ( n e w c l o j u r e . l a n g . L a z y S e q ( f n * [ ] A N Y T H I N G 1 A N Y T H I N G 2 ) ) MACROS
  27. Let's create an infinite sequence representing a square-wave --__--__--__--__ No

    mutable variables ( d e f n s q u a r e - w a v e " t i s t h e p e r i o d f o r a h a l f - c y c l e " [ t ] ( l e t f n [ ( o s c [ c u r - v a l u e s o - f a r ] ( l e t [ s o - f a r ( m o d s o - f a r t ) n e x t - v a l ( i f ( z e r o ? s o - f a r ) ( - c u r - v a l u e ) c u r - v a l u e ) ] ( c o n s n e x t - v a l ( l a z y - s e q ( o s c n e x t - v a l ( i n c s o - f a r ) ) ) ) ) ) ] ( o s c 1 0 ) ) ) ( t a k e 1 0 ( s q u a r e - w a v e 3 ) ) ; ; ( - 1 - 1 - 1 1 1 1 - 1 - 1 - 1 1 )
  28. CALL TO ACTION 1. Learn Clojure 2. Build cool things

    3. Screencasts! (You ruby guys really know how to make good screencasts)
  29. DEMO TIME CLOJURE ON THE WEB Now clone this: https://github.com/canweriotnow/bohjure

  30. RESOURCES Clojure: http://clojure.org Fun Exercises: http://www.4clojure.com Cheatsheets: http://clojure.org/cheatsheet Building: https://github.com/technomancy/leiningen

    Insight: http://www.youtube.com/user/ClojureTV Community docs: http://clojuredocs.org Blogs: http://planet.clojure.in Light Table: http://www.lighttable.com this doc: http://gtrak.github.io/bohconf.clojure
  31. MORE DEMO TIME

  32. THANKS FOR COMING! WE ARE: Gary Trakhman Software Engineer at

    @gtrakGT Revelytix, Inc. Jason Lewis CTO at @canweriotnow An Estuary, LLC