SlideShare uma empresa Scribd logo
1 de 56
Baixar para ler offline
Alexander Khokhlov
@nots_ioNots.io
ClojureScript journey
From little script,
to CLI program,
to AWS Lambda function
Co-Founder
Nots.io
01
README.md
Code Comments
JavaDoc
GDocs
Confluence / DokuWiki / Wiki system
Nots.io
Add docs for block of code,
function, module, file,
commit or branch
01
Notes, Tied
to Code
Easy to Discover
Easy to Explore
Easy to Get Scope
Easy to Ask and Discuss
01 • Nots.io
We Track
Relevance
You always know what’s fresh
and what’s not.
Promotes keeping docs
up-to-date.
Rewarding when everything is ✅
01 • Nots.io
Discuss with
your Team
You won’t loose a dispute
that is written down.
It’s tied and has context
01 • Nots.io
And many
more
Integration with GitHub
IDE/Editors plugins
Markdown formatting
@mentions
GitHub PR as a Note
Attachments
One-on-one conversations
…
01 • Nots.io
02
https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d
The task:
Detect comment scope
https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d
02 • The task
Analyze!
AST is the best
But tokens are good enough
Tokenizers
ANTLR

Pygments

vscode-textmate
02 • The task
vscode-textmate
02 • The task
https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d
var vsctm = require('vscode-textmate');
var registry = new vsctm.Registry({
loadGrammar: function (scopeName) {
var path = ‘./javascript.tmbundle/Syntaxes/JavaScript.plist';
if (path) {
return new Promise((c, e) => {
fs.readFile(path, (error, content) => {
if (error) { e(error); } else {
var rawGrammar = vsctm.parseRawGrammar(
content.toString(),
path);
c(rawGrammar);
}});});}
return null;
}});
// Load the JavaScript grammar and any other grammars included by it async.
registry.loadGrammar('source.js').then(grammar => {
// at this point `grammar` is available...
var lineTokens = grammar.tokenizeLine(
'function add(a,b) { return a+b; }');
for (var i = 0; i < lineTokens.tokens.length; i++) {
var token = lineTokens.tokens[i];
console.log('Token from ' + token.startIndex +
‘ to ' + token.endIndex);
}
});
Sample
vscode-textmate
02 • The task
https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d
{ tokens:
[ { startIndex: 0,
endIndex: 1,
scopes:
[ 'source.js',
'string.quoted.single.js',
'punctuation.definition.string.begin.js' ],
text: "'",
line: 0 },
{ startIndex: 1,
endIndex: 11,
scopes: [ 'source.js', 'string.quoted.single.js' ],
text: 'use strict',
line: 0 },
{ startIndex: 11,
endIndex: 12,
scopes:
[ 'source.js',
'string.quoted.single.js',
'punctuation.definition.string.end.js' ],
text: "'",
line: 0 },
{ startIndex: 12,
endIndex: 13,
scopes: [ 'source.js', 'punctuation.terminator.statement.js' ],
text: ';',
line: 0 },
Output
Tool which works
great with sequences
02 • The task
🤔
ClojureScript
03
03 • CLJS
LISP
03 • CLJS
LISP
03 • CLJS
Dialect of LISP
Dynamic
Immutable
Persistent
Compiled to JS
Homoiconic
Data-Driven
03 • CLJS
Data-driven
03 • CLJS
Composable
03 • CLJS
98 functions to work
with collections🔥
Isn’t that enough?
03 • CLJS
"It is better to have 100 functions
operate on one data structure than 10
functions on 10 data structures." 

—Alan Perlis
03 • CLJS
All together now
03 • CLJS
Interop
;; Globals
;; alert("Hello!")
(js/alert "Hello!")
;; Function Call
;; "string".toUpperCase()
(.toUpperCase "string")
;; Properties
;; "string".length
(.-length "string")
Interoperability
with JS
03 • CLJS
Interop
;; Chain calls
;; "string".toUpperCase().charCodeAt(1).toString()
(.toString (.charCodeAt (.toUpperCase "string") 1))
(.. "string" (toUpperCase) (charCodeAt 1) (toString))
(.. "string" toUpperCase (charCodeAt 1) toString)
(-> "string" .toUpperCase (.charCodeAt 1) .toString)
;; Chain properties
;; document.body.lastChild.innerHTML.length
(.. js/document -body -lastChild -innerHTML -length)
(-> js/document .-body .-lastChild .-innerHTML .-length)
Interoperability
with JS
03 • CLJS
Interop
(ns myapp)
(defn ^:export func [a]
(str "Hey, " a))
;; in JS:
;; myapp.func("NodeUA!");
How we did it
04
🏗
https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d
Tokenize
04 • How we did it
vscode-textmate
(require '[cljs.build.api :as b])
(b/build "src"
{:main 'notsapp.citation.core
:optimizations :simple
:target :nodejs
:npm-deps {:vscode-textmate “4.1.1”}
:install-deps true
:output-to "notsapp_citation.js"})
04 • How we did it
Get tokens
(ns notsapp.citation.registry
(:require [vscode-textmate :as vstm]
[cljs-node-io.core :as io]
[cljs-node-io.fs :as fs]))
(def reg (new vstm/Registry))
(defn load-all-grammars []
(->> (fs/readdir “grammars")
(filter #(re-find #".json$" %))
(map
#(let [grammar-path (str "grammars/" %)
grammar (io/slurp grammar-path)]
(->> (vstm/parseRawGrammar
grammar grammar-path)
(.addGrammar reg))))))
(defn tokenize-file [file source scope-name]
(when-let [grammar-promise
(.grammarForScopeName reg scope-name)]
(.then grammar-promise
#(.tokenizeLine % source)))))
04 • How we did it
(defn common-block-scopes [input-tokens]
(let [last-idx (-> input-tokens count dec)]
(->>
input-tokens
(keep-indexed
(fn [idx token]
(when (or
(re-find
#"((r)?n){2,}"
(-> token
:text
(str/replace #"[ t]+" "")))
(= idx last-idx))
idx)))
(cons 0)
distinct
(partition 2 1)
(map (fn [[start end]]
(subvec input-tokens (inc start) end))))))
Transform
stream of tokens
04 • How we did it
Transform to CLI
05
📺
05 • Transform to CLI
Transform to CLI
deps.edn
{:deps {org.clojure/clojure {:mvn/version "1.9.0"}
org.clojure/core.async {:mvn/version "0.4.490"}
org.clojure/clojurescript {:mvn/version "1.10.439"}
cljs-node-io {:mvn/version "1.1.2"}
org.clojure/tools.cli {:mvn/version "0.4.1"}
}}
Transform to CLI
clojure.tools.cli
(ns notsapp.citation.core
(:require [cljs.nodejs :as nodejs]
[clojure.tools.cli :as cli]))
(def cli-options
[["-l" "--lang LANG" "Language of a source code file passed via stdin"]
["-s" "--scope LINENUMBER" "Get the scope by given line number"
:parse-fn #(js/parseInt %)]
["-c" "--comments" "Show comments scopes"]
["-h" "--help"]])
(defn -main [& args]
(let [opts (cli/parse-opts args cli-options)
file (-> opts :arguments first)
lang (-> opts :options :lang)
scope-line-number (-> opts :options :scope)
show-comments? (-> opts :options :comments)]
(.exit nodejs/process 0))
(set! *main-cli-fn* -main)
05 • Transform to CLI
Transform to CLI
stdin
(defn read []
(.on
stdin
"readable"
(fn on-readable []
(let [string
(loop [buf (.alloc js/Buffer 0)]
(if-let [data (.read stdin)]
(recur (.concat js/Buffer #js [buf data]))
;else
(.toString buf "utf8")))]
(.removeListener stdin "readable" on-readable)
string))))
05 • Transform to CLI
Transform to CLI
stdout
(ns notsapp.citation.stdout
(:require [clojure.string :as str]
[cljs.nodejs :as nodejs]))
(def stdout (.-stdout nodejs/process))
(defn write [data]
(let [buf (.from js/Buffer data)
data-len (.-length buf)
len-buf (.alloc js/Buffer 4)]
(.writeUInt32BE len-buf data-len 0)
(->> #js [len-buf buf]
(.concat js/Buffer)
(.write stdout))))
05 • Transform to CLI
Compile & exec
> clj build.clj
> node notsapp_citation.js
(require '[cljs.build.api :as b])
(b/build
"src"
{:main 'notsapp.citation.core
:optimizations :simple
:target :nodejs
:npm-deps {:vscode-textmate “4.1.1”}
:install-deps true
:output-to "notsapp_citation.js"})build.clj
05 • Transform to CLI
06
Houston …
06 • AWS Lambda
AWS Lambda
Surprisingly
simple to
transform
; WAS
;(set! *main-cli-fn* -main)
;NOW
(set! (.-exports js/module) #js {:scopelambda scopelambda})
(defn scopelambda [event ctx cb]
(if-let [body (.parse js/JSON (.-body event))]
(cb
nil
#js {:statusCode 200
:headers #js {"Content-Type" "text/plain"}
:body "Hey There!"})
;or else return BAD REQUEST response
(cb
nil
#js {:statusCode 500
:headers #js {"Content-Type" "text/plain"}
:body "Cannot parse request body"})))
06 • AWS Lambda
Compile
build.clj
(require '[cljs.build.api :as b])
(b/build
"src"
{:main 'notsapp.citation.core
:optimizations :simple
:target :nodejs
:npm-deps {:vscode-textmate “4.1.1”}
:install-deps true
:output-to "notsapp_citation.js"})
$ clj build.clj
06 • AWS Lambda
Deploy & exec
$ serverless deploy
serverless.yml
package:
include:
- notsapp_citation.js
- node_modules/**
- grammars/**
exclude:
- src/**
- .git/**
- out/**
functions:
citation:
handler: notsapp_citation.scopelambda
$ serverless invoke -f citation -l
06 • AWS Lambda
07
Testing
07 • Testing
Testing
Entry point
(ns notsapp.citation.core-test
(:require [cljs.test :as t]
[cljs.nodejs :as nodejs]
[notsapp.citation.js-test]))
(nodejs/enable-util-print!)
(defn -main [& args]
(t/run-tests
'notsapp.citation.js-test))
(set! *main-cli-fn* -main)
Testing
The test
(ns notsapp.citation.js-test
(:require [cljs.test
:refer-macros [deftest is]
:as t]))
(t/use-fixtures
:once
{:before load-all-grammars})
(deftest js-scopes-arrow
(is (= (js-scope-arrow-funciton)
[[ 2, 2 ], [ 4, 5 ], [ 7, 8 ]])))
07 • Testing
Testing
Async tests
(deftest js-scopes-arrow
(t/async
done
(->
(tokenize-and-prepare-file
"samples/js/arrow-functions.js")
(.then
(fn [tokens]
(let [scope (js-scope-arrow tokens)]
(is (= scope [[2 2] [4 5] [7 8]])))
(done))))))
07 • Testing
Testing
Build & Execute
> clj build.clj
> node notsapp_tests.js
(require '[cljs.build.api :as b])
(b/build
(b/inputs "test" "src")
{:main 'notsapp.citation.core-test
:optimizations :none
:target :nodejs
:output-to "notsapp_tests.js"
:npm-deps {:vscode-textmate "3.3.3" }
:install-deps true
:output-dir "out_tests"})
07 • Testing
Final thoughts
08
08 • Final thoughts
Pros
Simple, Elegant & Readable
Easy to reason about
Small compassable libraries, not frameworks
Rich collection manipulation functions
FP, immutability, purity, first-class functions
High level data manipulation
CLJ/CLJS code reuse
Macros
Seamless interop with JS/Node.js
Cons
Learning curve, but it’s just an initial hump
Need to study FP
Good to deep dive into CLJ philosophy
Additional JS code added by CLJS itself
Still tangled error messages
Compiled code is hard to read
Need time to fully master the language
Know what you do
08 • Final thoughts
Best Fit
If the task is dedicated
If the team is skilled enough
If you see limit of your current stack
If you’re curious enough
If you want to broaden yours horizons
If you want to be 10x productive
In our opinion
08 • Final thoughts
Thank you
🤘
Alexander Khokhlov
point@nots.io
Nots.io
nots.io
blog.nots.io
@nots_io
facebook.com/nots.io

Mais conteúdo relacionado

Mais procurados

JSLT: JSON querying and transformation
JSLT: JSON querying and transformationJSLT: JSON querying and transformation
JSLT: JSON querying and transformationLars Marius Garshol
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015Fernando Hamasaki de Amorim
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Codemotion
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)Nikita Popov
 
POCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewPOCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewGünter Obiltschnig
 
The Why and How of Scala at Twitter
The Why and How of Scala at TwitterThe Why and How of Scala at Twitter
The Why and How of Scala at TwitterAlex Payne
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot CampTroy Miles
 
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computingCracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computingLuciano Mammino
 
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?SegFaultConf
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Expressjguerrero999
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with JasmineLeon van der Grient
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service ManagerChris Tankersley
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaHermann Hueck
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPGuilherme Blanco
 
The state of your own hypertext preprocessor
The state of your own hypertext preprocessorThe state of your own hypertext preprocessor
The state of your own hypertext preprocessorAlessandro Nadalin
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴명신 김
 
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Lucidworks
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scalaStratio
 

Mais procurados (20)

JSLT: JSON querying and transformation
JSLT: JSON querying and transformationJSLT: JSON querying and transformation
JSLT: JSON querying and transformation
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)
 
POCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and OverviewPOCO C++ Libraries Intro and Overview
POCO C++ Libraries Intro and Overview
 
The Why and How of Scala at Twitter
The Why and How of Scala at TwitterThe Why and How of Scala at Twitter
The Why and How of Scala at Twitter
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computingCracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
 
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Express
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
Scala active record
Scala active recordScala active record
Scala active record
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from Scala
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
The state of your own hypertext preprocessor
The state of your own hypertext preprocessorThe state of your own hypertext preprocessor
The state of your own hypertext preprocessor
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scala
 

Semelhante a "ClojureScript journey: from little script, to CLI program, to AWS Lambda function" Alexander Khokhlov

Shrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_youShrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_youSHRUG GIS
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADtab0ris_1
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.Mike Brevoort
 
Fighting Against Chaotically Separated Values with Embulk
Fighting Against Chaotically Separated Values with EmbulkFighting Against Chaotically Separated Values with Embulk
Fighting Against Chaotically Separated Values with EmbulkSadayuki Furuhashi
 
Mongodb intro
Mongodb introMongodb intro
Mongodb introchristkv
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable CodeBaidu, Inc.
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring ClojurescriptLuke Donnet
 
Web Performance Workshop - Velocity London 2013
Web Performance Workshop - Velocity London 2013Web Performance Workshop - Velocity London 2013
Web Performance Workshop - Velocity London 2013Andy Davies
 
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...NoSQLmatters
 
Shell Tips & Tricks
Shell Tips & TricksShell Tips & Tricks
Shell Tips & TricksMongoDB
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#Bertrand Le Roy
 
How to create a libcloud driver from scratch
How to create a libcloud driver from scratchHow to create a libcloud driver from scratch
How to create a libcloud driver from scratchMike Muzurakis
 
How to create a libcloud driver from scratch
How to create a libcloud driver from scratchHow to create a libcloud driver from scratch
How to create a libcloud driver from scratchMist.io
 
Microsoft 2014 Dev Plataform - Roslyn -& ASP.NET vNext
Microsoft 2014 Dev Plataform -  Roslyn -& ASP.NET vNextMicrosoft 2014 Dev Plataform -  Roslyn -& ASP.NET vNext
Microsoft 2014 Dev Plataform - Roslyn -& ASP.NET vNextRodolfo Finochietti
 

Semelhante a "ClojureScript journey: from little script, to CLI program, to AWS Lambda function" Alexander Khokhlov (20)

NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Shrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_youShrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_you
 
Getting Input from User
Getting Input from UserGetting Input from User
Getting Input from User
 
Unit-2 Getting Input from User.pptx
Unit-2 Getting Input from User.pptxUnit-2 Getting Input from User.pptx
Unit-2 Getting Input from User.pptx
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADta
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
Fighting Against Chaotically Separated Values with Embulk
Fighting Against Chaotically Separated Values with EmbulkFighting Against Chaotically Separated Values with Embulk
Fighting Against Chaotically Separated Values with Embulk
 
Mongodb intro
Mongodb introMongodb intro
Mongodb intro
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable Code
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
Web Performance Workshop - Velocity London 2013
Web Performance Workshop - Velocity London 2013Web Performance Workshop - Velocity London 2013
Web Performance Workshop - Velocity London 2013
 
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
 
Shell Tips & Tricks
Shell Tips & TricksShell Tips & Tricks
Shell Tips & Tricks
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
Latinoware
LatinowareLatinoware
Latinoware
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#
 
How to create a libcloud driver from scratch
How to create a libcloud driver from scratchHow to create a libcloud driver from scratch
How to create a libcloud driver from scratch
 
How to create a libcloud driver from scratch
How to create a libcloud driver from scratchHow to create a libcloud driver from scratch
How to create a libcloud driver from scratch
 
Microsoft 2014 Dev Plataform - Roslyn -& ASP.NET vNext
Microsoft 2014 Dev Plataform -  Roslyn -& ASP.NET vNextMicrosoft 2014 Dev Plataform -  Roslyn -& ASP.NET vNext
Microsoft 2014 Dev Plataform - Roslyn -& ASP.NET vNext
 

Mais de Julia Cherniak

"Definition of Done: Deadline driven development" Vitaliy Ratushnyi
"Definition of Done: Deadline driven development" Vitaliy Ratushnyi"Definition of Done: Deadline driven development" Vitaliy Ratushnyi
"Definition of Done: Deadline driven development" Vitaliy RatushnyiJulia Cherniak
 
"Muses Code JS or How Communities Change People" Tanya Butenko
"Muses Code JS or How Communities Change People" Tanya Butenko"Muses Code JS or How Communities Change People" Tanya Butenko
"Muses Code JS or How Communities Change People" Tanya ButenkoJulia Cherniak
 
"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко
"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко
"Принимают за hard skills, увольняют из-за soft skills" Павел ГалушкоJulia Cherniak
 
"It’s about time to embrace Streams" Luciano Mammino
"It’s about time to embrace Streams" Luciano Mammino"It’s about time to embrace Streams" Luciano Mammino
"It’s about time to embrace Streams" Luciano MamminoJulia Cherniak
 
"Node.js and Serverless" Viacheslav Panevskyi
"Node.js and Serverless" Viacheslav Panevskyi"Node.js and Serverless" Viacheslav Panevskyi
"Node.js and Serverless" Viacheslav PanevskyiJulia Cherniak
 
"Lift me up. Mentorship 101" Tanya Butenko
"Lift me up. Mentorship 101" Tanya Butenko"Lift me up. Mentorship 101" Tanya Butenko
"Lift me up. Mentorship 101" Tanya ButenkoJulia Cherniak
 
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D..."Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...Julia Cherniak
 
"Black Clouds and Silver Linings in Node.js Security" Liran Tal
"Black Clouds and Silver Linings in Node.js Security" Liran Tal"Black Clouds and Silver Linings in Node.js Security" Liran Tal
"Black Clouds and Silver Linings in Node.js Security" Liran TalJulia Cherniak
 
"The working architecture of NodeJs applications" Viktor Turskyi
"The working architecture of NodeJs applications" Viktor Turskyi"The working architecture of NodeJs applications" Viktor Turskyi
"The working architecture of NodeJs applications" Viktor TurskyiJulia Cherniak
 
"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren
"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren
"The search for App-iness : Progressive Web Apps" Jamie Maria SchourenJulia Cherniak
 
"The Future of Machine Learning & JavaScript"Asim Hussain
"The Future of Machine Learning & JavaScript"Asim Hussain"The Future of Machine Learning & JavaScript"Asim Hussain
"The Future of Machine Learning & JavaScript"Asim HussainJulia Cherniak
 

Mais de Julia Cherniak (11)

"Definition of Done: Deadline driven development" Vitaliy Ratushnyi
"Definition of Done: Deadline driven development" Vitaliy Ratushnyi"Definition of Done: Deadline driven development" Vitaliy Ratushnyi
"Definition of Done: Deadline driven development" Vitaliy Ratushnyi
 
"Muses Code JS or How Communities Change People" Tanya Butenko
"Muses Code JS or How Communities Change People" Tanya Butenko"Muses Code JS or How Communities Change People" Tanya Butenko
"Muses Code JS or How Communities Change People" Tanya Butenko
 
"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко
"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко
"Принимают за hard skills, увольняют из-за soft skills" Павел Галушко
 
"It’s about time to embrace Streams" Luciano Mammino
"It’s about time to embrace Streams" Luciano Mammino"It’s about time to embrace Streams" Luciano Mammino
"It’s about time to embrace Streams" Luciano Mammino
 
"Node.js and Serverless" Viacheslav Panevskyi
"Node.js and Serverless" Viacheslav Panevskyi"Node.js and Serverless" Viacheslav Panevskyi
"Node.js and Serverless" Viacheslav Panevskyi
 
"Lift me up. Mentorship 101" Tanya Butenko
"Lift me up. Mentorship 101" Tanya Butenko"Lift me up. Mentorship 101" Tanya Butenko
"Lift me up. Mentorship 101" Tanya Butenko
 
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D..."Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...
"Using Blockchain in Node.js project: JavaScript Ninja’s experience" Maksym D...
 
"Black Clouds and Silver Linings in Node.js Security" Liran Tal
"Black Clouds and Silver Linings in Node.js Security" Liran Tal"Black Clouds and Silver Linings in Node.js Security" Liran Tal
"Black Clouds and Silver Linings in Node.js Security" Liran Tal
 
"The working architecture of NodeJs applications" Viktor Turskyi
"The working architecture of NodeJs applications" Viktor Turskyi"The working architecture of NodeJs applications" Viktor Turskyi
"The working architecture of NodeJs applications" Viktor Turskyi
 
"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren
"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren
"The search for App-iness : Progressive Web Apps" Jamie Maria Schouren
 
"The Future of Machine Learning & JavaScript"Asim Hussain
"The Future of Machine Learning & JavaScript"Asim Hussain"The Future of Machine Learning & JavaScript"Asim Hussain
"The Future of Machine Learning & JavaScript"Asim Hussain
 

Último

Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxRTS corp
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 

Último (20)

Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 

"ClojureScript journey: from little script, to CLI program, to AWS Lambda function" Alexander Khokhlov

  • 1. Alexander Khokhlov @nots_ioNots.io ClojureScript journey From little script, to CLI program, to AWS Lambda function
  • 3.
  • 4.
  • 5.
  • 7. Nots.io Add docs for block of code, function, module, file, commit or branch 01
  • 8. Notes, Tied to Code Easy to Discover Easy to Explore Easy to Get Scope Easy to Ask and Discuss 01 • Nots.io
  • 9. We Track Relevance You always know what’s fresh and what’s not. Promotes keeping docs up-to-date. Rewarding when everything is ✅ 01 • Nots.io
  • 10. Discuss with your Team You won’t loose a dispute that is written down. It’s tied and has context 01 • Nots.io
  • 11. And many more Integration with GitHub IDE/Editors plugins Markdown formatting @mentions GitHub PR as a Note Attachments One-on-one conversations … 01 • Nots.io
  • 15. vscode-textmate 02 • The task https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d var vsctm = require('vscode-textmate'); var registry = new vsctm.Registry({ loadGrammar: function (scopeName) { var path = ‘./javascript.tmbundle/Syntaxes/JavaScript.plist'; if (path) { return new Promise((c, e) => { fs.readFile(path, (error, content) => { if (error) { e(error); } else { var rawGrammar = vsctm.parseRawGrammar( content.toString(), path); c(rawGrammar); }});});} return null; }}); // Load the JavaScript grammar and any other grammars included by it async. registry.loadGrammar('source.js').then(grammar => { // at this point `grammar` is available... var lineTokens = grammar.tokenizeLine( 'function add(a,b) { return a+b; }'); for (var i = 0; i < lineTokens.tokens.length; i++) { var token = lineTokens.tokens[i]; console.log('Token from ' + token.startIndex + ‘ to ' + token.endIndex); } }); Sample
  • 16. vscode-textmate 02 • The task https://medium.com/basecs/reading-code-right-with-some-help-from-the-lexer-63d0be3d21d { tokens: [ { startIndex: 0, endIndex: 1, scopes: [ 'source.js', 'string.quoted.single.js', 'punctuation.definition.string.begin.js' ], text: "'", line: 0 }, { startIndex: 1, endIndex: 11, scopes: [ 'source.js', 'string.quoted.single.js' ], text: 'use strict', line: 0 }, { startIndex: 11, endIndex: 12, scopes: [ 'source.js', 'string.quoted.single.js', 'punctuation.definition.string.end.js' ], text: "'", line: 0 }, { startIndex: 12, endIndex: 13, scopes: [ 'source.js', 'punctuation.terminator.statement.js' ], text: ';', line: 0 }, Output
  • 17. Tool which works great with sequences 02 • The task 🤔
  • 21. 03 • CLJS Dialect of LISP Dynamic Immutable Persistent Compiled to JS Homoiconic Data-Driven
  • 24. 03 • CLJS 98 functions to work with collections🔥 Isn’t that enough?
  • 25. 03 • CLJS "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." 
 —Alan Perlis
  • 26. 03 • CLJS All together now
  • 27. 03 • CLJS Interop ;; Globals ;; alert("Hello!") (js/alert "Hello!") ;; Function Call ;; "string".toUpperCase() (.toUpperCase "string") ;; Properties ;; "string".length (.-length "string") Interoperability with JS
  • 28. 03 • CLJS Interop ;; Chain calls ;; "string".toUpperCase().charCodeAt(1).toString() (.toString (.charCodeAt (.toUpperCase "string") 1)) (.. "string" (toUpperCase) (charCodeAt 1) (toString)) (.. "string" toUpperCase (charCodeAt 1) toString) (-> "string" .toUpperCase (.charCodeAt 1) .toString) ;; Chain properties ;; document.body.lastChild.innerHTML.length (.. js/document -body -lastChild -innerHTML -length) (-> js/document .-body .-lastChild .-innerHTML .-length) Interoperability with JS
  • 29. 03 • CLJS Interop (ns myapp) (defn ^:export func [a] (str "Hey, " a)) ;; in JS: ;; myapp.func("NodeUA!");
  • 30. How we did it 04 🏗
  • 32. vscode-textmate (require '[cljs.build.api :as b]) (b/build "src" {:main 'notsapp.citation.core :optimizations :simple :target :nodejs :npm-deps {:vscode-textmate “4.1.1”} :install-deps true :output-to "notsapp_citation.js"}) 04 • How we did it
  • 33. Get tokens (ns notsapp.citation.registry (:require [vscode-textmate :as vstm] [cljs-node-io.core :as io] [cljs-node-io.fs :as fs])) (def reg (new vstm/Registry)) (defn load-all-grammars [] (->> (fs/readdir “grammars") (filter #(re-find #".json$" %)) (map #(let [grammar-path (str "grammars/" %) grammar (io/slurp grammar-path)] (->> (vstm/parseRawGrammar grammar grammar-path) (.addGrammar reg)))))) (defn tokenize-file [file source scope-name] (when-let [grammar-promise (.grammarForScopeName reg scope-name)] (.then grammar-promise #(.tokenizeLine % source))))) 04 • How we did it
  • 34. (defn common-block-scopes [input-tokens] (let [last-idx (-> input-tokens count dec)] (->> input-tokens (keep-indexed (fn [idx token] (when (or (re-find #"((r)?n){2,}" (-> token :text (str/replace #"[ t]+" ""))) (= idx last-idx)) idx))) (cons 0) distinct (partition 2 1) (map (fn [[start end]] (subvec input-tokens (inc start) end)))))) Transform stream of tokens 04 • How we did it
  • 36. 05 • Transform to CLI Transform to CLI deps.edn {:deps {org.clojure/clojure {:mvn/version "1.9.0"} org.clojure/core.async {:mvn/version "0.4.490"} org.clojure/clojurescript {:mvn/version "1.10.439"} cljs-node-io {:mvn/version "1.1.2"} org.clojure/tools.cli {:mvn/version "0.4.1"} }}
  • 37. Transform to CLI clojure.tools.cli (ns notsapp.citation.core (:require [cljs.nodejs :as nodejs] [clojure.tools.cli :as cli])) (def cli-options [["-l" "--lang LANG" "Language of a source code file passed via stdin"] ["-s" "--scope LINENUMBER" "Get the scope by given line number" :parse-fn #(js/parseInt %)] ["-c" "--comments" "Show comments scopes"] ["-h" "--help"]]) (defn -main [& args] (let [opts (cli/parse-opts args cli-options) file (-> opts :arguments first) lang (-> opts :options :lang) scope-line-number (-> opts :options :scope) show-comments? (-> opts :options :comments)] (.exit nodejs/process 0)) (set! *main-cli-fn* -main) 05 • Transform to CLI
  • 38. Transform to CLI stdin (defn read [] (.on stdin "readable" (fn on-readable [] (let [string (loop [buf (.alloc js/Buffer 0)] (if-let [data (.read stdin)] (recur (.concat js/Buffer #js [buf data])) ;else (.toString buf "utf8")))] (.removeListener stdin "readable" on-readable) string)))) 05 • Transform to CLI
  • 39. Transform to CLI stdout (ns notsapp.citation.stdout (:require [clojure.string :as str] [cljs.nodejs :as nodejs])) (def stdout (.-stdout nodejs/process)) (defn write [data] (let [buf (.from js/Buffer data) data-len (.-length buf) len-buf (.alloc js/Buffer 4)] (.writeUInt32BE len-buf data-len 0) (->> #js [len-buf buf] (.concat js/Buffer) (.write stdout)))) 05 • Transform to CLI
  • 40. Compile & exec > clj build.clj > node notsapp_citation.js (require '[cljs.build.api :as b]) (b/build "src" {:main 'notsapp.citation.core :optimizations :simple :target :nodejs :npm-deps {:vscode-textmate “4.1.1”} :install-deps true :output-to "notsapp_citation.js"})build.clj 05 • Transform to CLI
  • 42. 06 • AWS Lambda AWS Lambda
  • 43. Surprisingly simple to transform ; WAS ;(set! *main-cli-fn* -main) ;NOW (set! (.-exports js/module) #js {:scopelambda scopelambda}) (defn scopelambda [event ctx cb] (if-let [body (.parse js/JSON (.-body event))] (cb nil #js {:statusCode 200 :headers #js {"Content-Type" "text/plain"} :body "Hey There!"}) ;or else return BAD REQUEST response (cb nil #js {:statusCode 500 :headers #js {"Content-Type" "text/plain"} :body "Cannot parse request body"}))) 06 • AWS Lambda
  • 44. Compile build.clj (require '[cljs.build.api :as b]) (b/build "src" {:main 'notsapp.citation.core :optimizations :simple :target :nodejs :npm-deps {:vscode-textmate “4.1.1”} :install-deps true :output-to "notsapp_citation.js"}) $ clj build.clj 06 • AWS Lambda
  • 45. Deploy & exec $ serverless deploy serverless.yml package: include: - notsapp_citation.js - node_modules/** - grammars/** exclude: - src/** - .git/** - out/** functions: citation: handler: notsapp_citation.scopelambda $ serverless invoke -f citation -l 06 • AWS Lambda
  • 47. 07 • Testing Testing Entry point (ns notsapp.citation.core-test (:require [cljs.test :as t] [cljs.nodejs :as nodejs] [notsapp.citation.js-test])) (nodejs/enable-util-print!) (defn -main [& args] (t/run-tests 'notsapp.citation.js-test)) (set! *main-cli-fn* -main)
  • 48. Testing The test (ns notsapp.citation.js-test (:require [cljs.test :refer-macros [deftest is] :as t])) (t/use-fixtures :once {:before load-all-grammars}) (deftest js-scopes-arrow (is (= (js-scope-arrow-funciton) [[ 2, 2 ], [ 4, 5 ], [ 7, 8 ]]))) 07 • Testing
  • 49. Testing Async tests (deftest js-scopes-arrow (t/async done (-> (tokenize-and-prepare-file "samples/js/arrow-functions.js") (.then (fn [tokens] (let [scope (js-scope-arrow tokens)] (is (= scope [[2 2] [4 5] [7 8]]))) (done)))))) 07 • Testing
  • 50. Testing Build & Execute > clj build.clj > node notsapp_tests.js (require '[cljs.build.api :as b]) (b/build (b/inputs "test" "src") {:main 'notsapp.citation.core-test :optimizations :none :target :nodejs :output-to "notsapp_tests.js" :npm-deps {:vscode-textmate "3.3.3" } :install-deps true :output-dir "out_tests"}) 07 • Testing
  • 52. 08 • Final thoughts Pros Simple, Elegant & Readable Easy to reason about Small compassable libraries, not frameworks Rich collection manipulation functions FP, immutability, purity, first-class functions High level data manipulation CLJ/CLJS code reuse Macros Seamless interop with JS/Node.js
  • 53. Cons Learning curve, but it’s just an initial hump Need to study FP Good to deep dive into CLJ philosophy Additional JS code added by CLJS itself Still tangled error messages Compiled code is hard to read Need time to fully master the language Know what you do 08 • Final thoughts
  • 54. Best Fit If the task is dedicated If the team is skilled enough If you see limit of your current stack If you’re curious enough If you want to broaden yours horizons If you want to be 10x productive In our opinion 08 • Final thoughts