explore a few languages
discuss why they're "next-generation"
do some speculation and futurism
... because all our mainstream languages are old
... because productivity gains with elevated abstractions
... because functional programming couldn't get out of its own way
Julia: dynamically-typed high-performance general-pupose
Crystal: statically-typed Ruby-esque general-purpose
Jolie: service-oriented
Pony: type-safe, memory-safe, exception-safe, concurrent
Wing: cloud-oriented
Wasp: full-stack web app
Mint: web-oriented
This is a "survey talk"
we want to cover a bunch of languages
in less than an hour
hello, here it is, goodbye
very happy to discuss any of these afterwards
The point here is "to know what you don't know"
... and give you some signposts for exploring
... and maybe give a talk at a future conference!
https://julialang.org/
compiled (via LLVM)
complex and rational numbers
object-oriented and functional via multiple dispatch
dynamically-typed
parallel, async, multithreaded processing
implicit distribution capabilities
metaprogramming (code is data is code)
Julia distributed invocations
$ julia -p 2 julia> r = remotecall(rand, 2, 2, 2) Future(2, 1, 4, nothing) julia> s = @spawnat 2 1 .+ fetch(r) Future(2, 1, 5, nothing) julia> fetch(s) 2×2 Array{Float64,2}: 1.18526 1.50912 1.16296 1.60607
With some interesting metaprogramming support
julia> ex1 = Meta.parse("1 + 1") :(1 + 1) julia> dump(ex1) Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol + 2: Int64 1 3: Int64 1 julia> ex2 = Expr(:call, :+, 1, 1) :(1 + 1) julia> ex1 == ex2 true julia>
Hosting Julia in native code
#include <julia.h> JULIA_DEFINE_FAST_TLS int main(int argc, char *argv[]) { jl_init(); /* run Julia commands */ jl_eval_string("print(sqrt(2.0))"); jl_atexit_hook(0); return 0; }
$ gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib -Wl,-rpath,$JULIA_DIR/lib test.c -ljulia
Homebrew (macOS, Linux): brew install julia
Chocolatey (Windows): choco install julia
Downloads: https://julialang.org/downloads/
Build from source: https://github.com/JuliaLang/julia
Hello, world
println("Hello, world!")
Run
julia hello.jl
Or run interactively
$ julia _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.9.1 (2023-06-07) _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release |__/ | julia> print("Hello world") Hello world julia>
--project=
dir: Set dir as the home project/environment
-p
/--procs
: Launches N additional local worker processes
--machine-file
file: Run processes on hosts listed in file
type-inferencing helps keep syntax clean
metaprogramming (code as data)
strong math/science features/ecosystem
performance of native (LLVM)
interoperability across other LLVM-based platforms (GraalVM, etc)
clear embedding API--viable scripting engine
https://crystal-lang.org/
web playground: https://play.crystal-lang.org/#/cr
native compilation (via LLVM)
heavily Ruby-inspired syntax
statically type-checked, type-inferenced
non-nillable types (compile-time nil checks)
macro metaprogramming system
An HTTP server
require "http/server" server = HTTP::Server.new do |context| context.response.content_type = "text/plain" context.response.print "Hello world! The time is #{Time.local}" end address = server.bind_tcp 8080 puts "Listening on http://#{address}" server.listen
https://crystal-lang.org/install/
Online playground: https://play.crystal-lang.org/#/cr
Download: https://crystal-lang.org/install/from_targz
Package managers:
Homebrew/Linuxbrew: brew install crystal-lang
Ubuntu: curl -fsSL https://crystal-lang.org/install.sh | sudo bash
From sources: https://crystal-lang.org/install/from_sources/
self-hosting, so you need Crystal to build Crystal
Create a project
crystal init app hello
Hello, world: src/hello.cr
# TODO: Write documentation for `Hello` module Hello VERSION = "0.1.0" # TODO: Put your code here end
Run
crystal run src/hello.cr
Compile
crystal build src/hello.cr; ./hello
Ruby syntax
static types
compiled performance
a service-oriented programming language
"it is designed to reason effectively about the key questions of (micro)service development, including the following:
What are the APIs exposed by services?
How can these APIs be accessed?
How are APIs implemented in terms of concurrency, communication, and computation?
built on top of the JVM
"More in general, Jolie brings a structured linguistic approach to the programming of services, including constructs for access endpoints, APIs with synchronous and asynchronous operations, communications, behavioural workflows, and multiparty sessions. Additionally, Jolie embraces that service and microservice systems are often heterogeneous and interoperability should be a first-class citizen: all data in Jolie is structured as trees that can be semi-automatically (most of the time fully automatically) converted from/to different data formats (JSON, XML, etc.) and communicated over a variety of protocols (HTTP, binary protocols, etc.). Jolie is an attempt at making the first language for microservices, in the sense that it provides primitives to deal directly with the programming of common concerns regarding microservices without relying on frameworks or external libraries."
Contract-driven development, defined by formal APIs
Structural typing instead of nominative typing
Components are services
Decouple access points from business logic
Abstract data manipulation
defined by formal APIs
service APIs should be defined in a formal language
technology agnostic
unambiguous
machine readable
based on well-known abstractions.
ironically, WSDL wasn't wrong--just bad
instead of nominative typing
since, really, the contents (structure) are what's transferred
... and any nominative information is lost
service are independently executable software artifacts
services should be clearly identifiable in source code
scope of their definition should be clearly demarcated and delimited
any given logic can/should be accessed via multiple media
therefore coupling logic to access is an antipattern
implementation of business logic should be abstract from how data is represented on the wire
Jolie requires Java 11+ to run
Download the Jolie installer
https://www.jolie-lang.org/downloads.html
currently https://github.com/jolie/jolie/releases/download/v1.11.0/jolie-1.11.0.jar
Run the installer
java -jar jolie-1.11.0.jar
Linux/macOS/WSL Homebrew
brew install jolie
Docker
docker pull jolielang/jolie
docker run -it -v /host:/container –name CONTAINERNAME jolielang/jolie
edit files in your /host
, which will appear in /container
Or build from source
git clone https://github.com/jolie/jolie.git
cd jolie
mvn install
binaries will be in dist
folder
Then (optionally) set up Jolie for the local user
scripts/dev-setup.sh ~/bin
Run Jolie: jolie --version
currently returns Jolie 1.11.2 (C) 2006-2022 the Jolie developers
from your favorite editor, create hello.ol
run the file with jolie hello.ol
connect to the service: http://localhost:9000/hello?name=Fred
Hello world
type HelloRequest { name:string } interface HelloInterface { requestResponse: hello( HelloRequest )( string ) } service HelloService { execution: concurrent inputPort HelloService { location: "socket://localhost:9000" protocol: http { format = "json" } interfaces: HelloInterface } main { hello( request )( response ) { response = "Hello " + request.name } } }
services as a first-class concept
JVM underpining makes for easy integration
built-in data types beyond typical primitives
structural typing makes more sense for services
https://www.ponylang.io/
statically-typed, object-oriented
actor-model
capabilities-secure
type-safe
memeory-safe
exception-safe
data-race free
deadlock-free
high-performance
Pony Philosophy: "Get Stuff Done"
No loadable code; everything is known to the compiler
type system guarantees
If your program compiles, it won't crash.
There will never be an unhandled exception.
There's no such thing as null.
There will never be a data race.
Your program will never deadlock.
Your code will always be capabilities-secure.
All message passing is causal. (Not casual!)
a classic concurrency problem
Producer: generate data (at max speed)
Consumer: consume data (at max speed)
producer cannot outstrip consumer (lost data)
consumer cannot outstrip producer (duped data)
Main
actor Main """ Producer-Consumer concurrency problem. Pony has no blocking operations. The Pony standard library is structured in this way to use notifier objects, callbacks and promises to make programming in this style easier. """ new create(env: Env) => let buffer = Buffer(20, env.out) let producer = Producer(2, buffer, env.out) let consumer = Consumer(3, buffer, env.out) consumer.start_consuming() producer.start_producing() env.out.print("**Main** Finished.")
Producer
use "collections" actor Producer var _quantity_to_produce: U32 let _buffer: Buffer var _num: U32 = 0 let _out: OutStream new create(quantity_to_produce: U32, buffer: Buffer, out: OutStream) => _quantity_to_produce = quantity_to_produce _buffer = buffer _out = out be start_producing(count: U32 = 0) => _buffer.permission_to_produce(this) if count < _quantity_to_produce then start_producing(count + 1) end be produce() => _out.print("**Producer** Producing product " + _num.string()) let prod: Product = Product(_num, "Description of product " + _num.string()) _buffer.store_product(prod) _num = _num + 1
Consumer
use "collections" actor Consumer var _quantity_to_consume: U32 let _buffer: Buffer let _out: OutStream new create(quantity_to_consume: U32, buffer: Buffer, out: OutStream) => _quantity_to_consume = quantity_to_consume _buffer = buffer _out = out be start_consuming(count: U32 = 0) => _buffer.permission_to_consume(this) if count < _quantity_to_consume then start_consuming(count + 1) end be consuming(product: Product) => _out.print("**Consumer** Consuming product " + product.id.string()) _quantity_to_consume = _quantity_to_consume -1
Buffer
actor Buffer let capacity: USize var _products: Array[Product] var _future_products: USize = 0 var _producers_waiting: Array[Producer] = Array[Producer] var _consumers_waiting: Array[Consumer] = Array[Consumer] let _out: OutStream new create(capacity': USize, out: OutStream) => capacity = capacity' _products = Array[Product](capacity) _out = out
Buffer
be permission_to_consume(cons: Consumer) => let debug_string = "**Buffer** Permission_to_consume" _out.print(debug_string) try _out.print(debug_string + ": Calling consumer to consume") cons.consuming(_products.delete(0)?) // Fails if products is empty. try _out.print(debug_string + ": Calling producer to produce") _producers_waiting.delete(0)?.produce() end // If there are no producers in waiting, do nothing. else _out.print(debug_string + ": Storing consumer in waiting") _consumers_waiting.push(cons) end be permission_to_produce(prod: Producer) => let debug_string = "**Buffer** Permission_to_produce" _out.print(debug_string) if (_products.size() + _future_products) < capacity then _future_products = _future_products + 1 _out.print(debug_string + ": Calling producer to produce") prod.produce() else _producers_waiting.push(prod) _out.print(debug_string + ": Storing producer in waiting") end
Buffer
be store_product(product: Product) => let debug_string = "**Buffer** Store_product" _out.print(debug_string) _future_products = _future_products - 1 try _out.print(debug_string + ": Calling consumer to consume") _consumers_waiting.delete(0)?.consuming(product) else _out.print(debug_string + ": Storing product") _products.push(product) end
https://github.com/ponylang/ponyc/blob/main/INSTALL.md
requires a C/C++ compiler ($CC
and $CXX
env vars on *nix)
Homebrew/Linuxbrew: brew install ponyc
Build from source: https://github.com/ponylang/ponyc/blob/main/BUILD.md
Hello World: helloworld/main.pony
actor Main new create(env: Env) => env.out.print("Hello, world!")
Compile the code
cd helloworld; ponyc
Directory name is the name of the program
./helloworld
all the safety, everywhere we can get it
actors as first-class language constructs
https://www.winglang.io/
combines infrastructure and runtime code
cloud services as first-class citizens
local simulation (of cloud services)
deploy to any cloud
bring cloud; let q = new cloud.Queue(); let b = new cloud.Bucket() as "Bucket: Last Message"; q.addConsumer(inflight (m: str) => { b.put("latest.txt", m); }); new cloud.Function(inflight (s: str) => { log("Cloud Function was called with ${s}"); q.push(s); });
https://www.winglang.io/docs/
Wing CLI
Requires Node v20+
NPM package: npm i -g winglang
Wing Console: download installer (macOS, Windows)
Hello... er, Cloud
bring cloud; let bucket = new cloud.Bucket(); let queue = new cloud.Queue(); queue.setConsumer(inflight (message: str) => { bucket.put("wing.txt", "Hello, ${message}"); });
Test it in the Wing Console
wing it hello.w
code and infrastructure, as code
local simulation
... and testing
https://wasp-lang.dev/
configuration/language for full-stack web apps
builds on top of React, Node, and Prisma
ReactJS: SPA framework for browser-based UIs
Node: server-side JS execution engine
Prisma: object-relational mapper
compiler (transpiler) unifies the three
Hello world
app todoApp { title: "ToDo App", // visible in the browser tab auth: { // full-stack auth out-of-the-box userEntity: User, methods: { google: {}, gitHub: {}, email: {...} } } } route RootRoute { path: "/", to: MainPage } page MainPage { authRequired: true, // Limit access to logged in users. component: import Main from "@client/Main.tsx" // Your React code. } query getTasks { fn: import { getTasks } from "@server/tasks.js", // Your Node.js code. entities: [Task] // Automatic cache invalidation. } entity Task {=psl ... psl=} // Your Prisma data model.
https://wasp-lang.dev/docs/quick-start
Curl/shell: curl -sSL https://get.wasp-lang.dev/installer.sh | sh
(No package manager support yet)
Create the project
wasp new TodoApp
Start the server
cd TodoApp; wasp start
Browse to http://localhost:3000
full-stack web application language
capture routes, types, "screens" all in one place
validation of application flow/constructs
easier reuse of constructs/components
https://mint-lang.com/
"programming language for writing single page applications"
incorporates HTML, CSS, JS into one unified language
written in Crystal
Hello world
component Main { fun render : Html { <button> "Click ME!" </button> } }
Counter component
component Counter { state counter = 0 fun increment { next { counter: counter + 1 } } fun decrement { next { counter: counter - 1 } } fun render { <div> <button onClick={decrement}>"Decrement"</button> <span><{ Number.toString(counter) }></span> <button onClick={increment}>"Increment"</button> </div> } }
https://mint-lang.com/install
Package managers:
Homebrew/Linuxbrew: brew install mint-lang
Download the (single) prebuilt binary
Build from source: git clone https://github.com/mint-lang/mint.git
Docker:
git clone https://github.com/mint-lang/mint-docker.git
cd mint-docker
docker-compose up
mint init hello-world
Main (source/Main.mint)
component Main { style app { justify-content: center; flex-direction: column; align-items: center; display: flex; background-color: #282C34; height: 100vh; width: 100vw; font-family: Open Sans; font-weight: bold; } fun render : Html { <div::app> <Logo/> <Info mainPath="source/Main.mint"/> <Link href="https://www.mint-lang.com/"> "Learn Mint" </Link> </div> } }
Info (source/Info.mint)
component Info { property mainPath : String style info { font-size: calc(10px + 2vmin); color: #939DB0; } style path { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; font-style: italic; font-weight: 100; color: #E06C75; } fun render : Html { <p::info> <{ "Edit " }> <code::path> <{ mainPath }> </code> <{ " and save to reload." }> </p> } }
Link (source/Link.mint)
component Link { property children : Array(Html) = [] property href : String style link { font-size: calc(10px + 2vmin); text-decoration: none; color: #DDDDDD; &:hover { text-decoration: underline; } } fun render : Html { <a::link href="#{href}" target="_blank"> <{ children }> </a> } }
mint start
Browse to http://127.0.0.1:3000/
Edit source/Main.mint
(or any of the other files)
Browser page refreshes
https://ui.mint-lang.com/
loads of examples
"unified UI" front-end Web language
captures (calling into) services as part of the language
JS interoperability makes it play well in the Web world
integrated testing as a component (not as HTML, CSS, JS, separately)
There's a whole crop of interesting new languages out there
Many of these aren't ready for production use
but some are oh, so close...
All of them present some fascinating new ideas
... some of which you might want to steal (!)
If one of these doesn't get your motor running...
Odin: data-oriented systems programming
https://odin-lang.org/
Zig: statically-typed compiled metaprogrammaing
https://ziglang.org/
Fantom: static and dynamic typing actor concurrency
https://fantom.org/
Red: homoiconic high-level (CLI and GUI)
https://www.red-lang.org/
Wyvern: type-specific languages
http://wyvernlang.github.io/
Ballerina: service-oriented programming
https://www.ballerina.io/
Idris: purely-functional type-driven development
https://www.idris-lang.org/
Nim: statically-typed compiled dependency-free
https://nim-lang.org/
Unison: statically-typed, content-addressed
https://www.unison-lang.org/
Who is this guy?
Architect, Engineering Manager/Leader, "force multiplier"
Principal -- Neward & Associates
http://www.newardassociates.com
Educative (http://educative.io) Author
Performance Management for Engineering Managers
Author
Professional F# 2.0 (w/Erickson, et al; Wrox, 2010)
Effective Enterprise Java (Addison-Wesley, 2004)
SSCLI Essentials (w/Stutz, et al; OReilly, 2003)
Server-Based Java Programming (Manning, 2000)