ted.neward@newardassociates.com | Blog: http://blogs.newardassociates.com | Github: tedneward | LinkedIn: tedneward
The question everybody asks is always the same:
... which is usually just a mask for the real question:
We stand on the threshold of a Renaissance in programming languages
the next N years will be all about:
pushing new boundaries
exploring new approaches
getting over the "object-oriented" hill
maybe even making money with them!
Practitioners
Academics
... want to figure out new ways of doing stuff
more efficiently
more succinctly
more flexibly
more portably
or doing entirely new stuff we couldn't do before!
... all within programming languages or platforms
virtual machines as a language?
Self
Simula
Occam
ML
... want to get stuff done
quickly (on time)
cheaply (under budget)
correctly
with minimal surprise
For the most part...
... these two groups have been uninterested in working together
In fact...
... they've been downright hostile towards one another
... don't get languages done enough to be useful
they lack good integration possibilities
they lack decent "commodity" features (such as GC)
... because getting those details right is hard
and has nothing to do with language design
which, remember, is the Academics' entire goal
don't get exposed
Practitioners never discover the concepts that might be useful
don't get used
Practitioners never learn how to use the new concept or tool
don't get discussed
Practitioners can't gather/provide feedback on the concept or language
... which means the feedback loop is broken!
they cram new features in their current language
lookin' at you, C#
lookin' at you, Java
or argue about whose mainstream language is best
lookin' at you, audience!
Virtualization
Language Tools
Linguistic Focus
Services/microservices
Virtualization helps programmers
abstractions mean developers don't need physical details
so these "low-level" details can be safely ignored
or "trap doors" exist to allow dropping to a lower level
... allowing programmers to focus on the problem
Virtualization helps language designers
abstractions allow deference of physical details (CPU, memory, etc)
so these "low-level" details can be safely ignored
or "trap doors" (FFI) exist to allow dropping to a lower level
... allowing language designers to focus on the language
Necessary for any successful endeavor
IDEs
analyzers/linters
debuggers
profilers
Necessary for any successful language endeavor
parser generators
AST generators
grammar debuggers
optimizing backends
With the desire to create "no-dependencies" deployments...
... using a language-agnostic network interface (HTTP/JSON)...
... suddenly nobody cares what you write code in
This allowed several languages to challenge Java/.NET in the enterprise
... and increased the encapsulation barrier to callers
Enter NodeJS, Go, Rust, you name it
... but why stop there?
If the encapsulation barrier is truly opaque, why not...
Each language seeks to conceptualize certain constructs directly within the language
Niklaus Wirth called this a "separation of concerns"
We call these constructs "first-class citizens"
... and sometimes language hide details behind "syntactic sugar"
language shapes thought
Greeks had no concept of "blue"
never appears in any of the ancient texts (Homer, etc)
kyaenos was often used for colors on the darker end of the spectrum
violet, black, dark blue, brown, dark green
glaukos used infor lighter colors
yellow, grey, light green, or light blue
... but no "blue", as we know it
so could they not see it at all, or....?
"Homer’s comparison of the sea not to the sky, or another blue-colored thing, but to wine, (is) quite interesting. Throughout Homer’s poetry, the sea is referred to as 'wine-dark.'"
https://greekreporter.com/2024/02/17/did-ancient-greeks-see-blue/
Eskimos, "snow", and you
What's the difference between
"friend" and "bestie"?
"house" and "home" and the Spanish casa?
the "love" you feel for pets, family, and spouse?
single entry point
well-defined parameters and return values
union of state and data (object)
relationships between types (inheritance)
encapsulation of details (access control)
Type inference
"pure" functions, higher-order functions
partial application of functions and currying
sequential and monadic comprehensions
Conditionals
recursion
dynamic typing
functions-as-types
garbage collection
programs as expressions
a symbol type
a notation for code using trees of symbols and constants (AST)
dynamic evaluation of code
Consider the Haskell concept of a list
let numbers = [ 1, 2, 3 ]
We can do a few things with a list
let headOfList = head numbers print headOfList {- 1 -} let lastNumber = last numbers print lastNumber {- 3 -} let tailOfList = tail numbers print tailOfList {- [2, 3] -} let takeSomeOfList = take 2 numbers print takeSomeOfList {- [1, 2] -}
We can create a list out of a range of values
let numberRange = [1..100] print numberRange {- [1, 2, 3, ... , 99, 100] -} let evens = [2, 4..100] print evens {- [2, 4, 6, ... , 98, 100] -}
We can create a list out of code
let otherEvens = [x | x <- [1..10]] print otherEvens let squares = [x*x | x <- [1..10]] print squares let fizzBuzz = [ if x `mod` 5 == 0 then "BUZZFIZZ" else if x `mod` 3 == 0 then "BUZZ" else if x `mod` 4 == 0 then "FIZZ" else show x | x <- [1..25]] print fizzBuzz
We can even create an infinite list
let forever = [1..] {- printing forever is a bad idea.... -} let foreverLove = cycle ["LOVE"] print $ take 3 foreverLove {- ["LOVE", "LOVE", "LOVE"] -}
What a silly idea... Infinite lists
I mean, who ever would have a collection that goes on forever?
What kind of list goes on forever?
Haskell calls these infinite lists "streams", by the way
What if we had a Java Iterator... without a Collection?
An "evens" for-comprehension, in Java
class EvensToAHundredComprehensionIterator implements Iterable<Integer> { public Iterator<Integer> iterator() { return new Iterator<Integer>() { int count = 0; public boolean hasNext() { return count <= 100; } public Integer next() { if (count % 2 == 0) return count++; else { count++; return next(); } } public void remove() { } }; } }
Using it in Java
for (int val : new EvensToAHundredComprehensionIterator()) { System.out.print(val + ".."); } System.out.println();
How about an Iterator that knows how to read a file?
class FileIterator implements Iterable<String> { BufferedReader br; private FileIterator(BufferedReader br) { this.br = br; } public static FileIterator open(String filename) throws IOException { FileReader fr = new FileReader(filename); BufferedReader br = new BufferedReader(fr); return new FileIterator(br); }
How about an Iterator that knows how to read a file?
public Iterator<String> iterator() { Iterator<String> ret = new Iterator<String>() { String line = null; public boolean hasNext() { return line != null; } public String next() { String result = line; try { line = br.readLine(); } catch (IOException ioEx) { line = null; } return result; } public void remove() { } }; ret.next(); return ret; } }
How about an Iterator that knows how to read a file?
for (String line : FileIterator.open("./ItWithoutColl.java")) { System.out.println("FOUND>>> " + line); }
Gong down this path leads you to a number of interesting things... some of which were captured in Guava
Iterables
Iterators
... and some of which were captured in Java8
java.util.stream.*
first-class functions ("lambdas"/function literals syntax)
But think about infinite streams again for a second
But think about infinite streams again for a second
... what if we think about external events as streams?
user input
push notifications from the server
timer events
... and our responses to those events as functions?
in other words, putting some code around "take"ing one incoming atom at a time, processing it, and moving on to the next (if it's available)
Congratulations
Congratulations
... for you have just taken your first steps to understanding
Functional programming
Functional reactive programming
Reactive architectures
Redux
... and a few more things
concurrency and the end of the "free lunch"
"pure" object model drawbacks
application security
distribution models
"user enablement"
user interface expression
... and a whole bunch more we haven't thought of yet
Katahdin
Jolie
Ballerina
Wing
Wasp
Inform7
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."
Hello Jolie
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 } } }
ANTLR (parser generator) generates C#/Java/Python/C++ parsers and ASTs
Several packages provide JVM or CLR bytecode generation
LLVM is a back-end compiler toolchain (Swift, Crystal, Rust, more)
and lots of other languages are open-source, for reference and instruction
You can build a toy language in a week; a substantive one, in months
Or take an existing language and mod it
formal fork of the language (easier if it's OSS, of course)
"internal" DSL
Or... Javascript + XML (e4x)
// Use an XML literal to create an XML object var order = <order> <customer> <firstname>John</firstname> <lastname>Doe</lastname> </customer> <item> <description>Big Screen Television</description> <price>1299.99</price> <quantity>1</quantity> </item> </order> // Construct the full customer name var name = order.customer.firstname + " " + order.customer.lastname; // Calculate the total price var total = order.item.price * order.item.quantity;
Academics don't have a great record w/languages
Of course, Practitioners don't always, either....
"... but my boss won't let me!"
"... but my team won't let me!"
"... but what if I'm wrong?"
some bosses are just unshakeable
either go above them
or around them
or find a new boss
most bosses are willing to listen; make your case about them
benefits to the team
means by which you mitigate the costs
make sure there's a support structure in place
for some, demonstrate the utility after the fact
consider your team composition; will this benefit some but not others?
show them, don't tell them
create some examples
look to solve small problems quickly
get them involved in the process/R&D
Do your homework
Try to anticipate the problems
Be ready to be wrong about some parts
Remember: "Faint heart never won fair lady"
Look to language enhancements; where'd they come from?
Look to new languages coming out
what do they do
how do they do it
why'd they choose to do it that way
Explore creating your own new languages
start by reinventing the wheel
maybe build an "esoteric" language, just for fun
then turn your imagination loose a little