Introduction to EK9

EK9 is a general-purpose programming language that fuses Object Oriented and Functional programming with controlled Generic and Aspect Oriented Programming (AOP). It pulls widely used design patterns and framework ideas into the language, and the compiler itself provides a modular software ecosystem.

Its constructs are layered: they start very simple and build up to sophisticated software solutions.

An open question. Can one language fuse all these methodologies, and should it? Are the compromises severe enough to make the techniques less useful? Folding what are normally third-party libraries and build tools into one platform may look like a backwards step to many. Only time will tell.

Hello, World in EK9

#!ek9
defines module site.introduction.hello
  defines program

    HelloWorld()
      stdout <- Stdout()
      stdout.println("Hello, World")

Save it as helloworld.ek9 and run it:

$ ek9 helloworld.ek9
# On Linux/Unix/MacOS you can use this as well/instead
$ ./helloworld.ek9

The layout is minimal, much like Python. The module names a name space (site.introduction.hello), program names the kind of construct, and HelloWorld is the program with its body. <- declares a variable whose type is inferred: here Stdout, a class that prints Strings.

What's Different: EK9 vs Java/Python/C++

Coming from another language? EK9 departs on purpose from Java, Python, C++ and C#, based on decades of production bugs. These are not limitations: each departure removes a whole class of bug.

Three Critical Differences

What's Missing/Different Why It Matters Learn More
No break/continue/return statements These jumps compile cleanly and do the wrong thing (Apple's goto fail, 2014). Use stream pipelines, guards and multiple case values instead. Each word is an error: E01070, E01071, E01072. Control Flow Philosophy
Tri-State Semantics (Absent/Unset/Set) Not null vs not-null: a value is an object that is either set or unset, and absence (null) is designed never to be observable - the compiler rejects reading a value that may not have been assigned. There is no null (E01073). Tri-State Semantics
Types are Closed by Default Use as open to allow extension; extending a closed type is E05030. Built-in types (List, Dict) cannot be extended. Use composition and traits instead. Closed by Default

Why This Matters for Developers

You will reach for patterns from your previous language and get compiler errors. That is intentional: the compiler stops the bug before it happens. Give it a week and the patterns become natural.

Quick Start Advice:

Main Features

Why try EK9? You will find most of its features in other modern languages. What is different is the effect of the syntax, the layering and the structure in combination.

General Features
Specific new Features

This page is long: it covers the rationale, the state of development and the licensing. To see the language first, start with the list of examples, or read structure, basics and then operators.

Treat this manual as a stream of consciousness; criticism accepted. Send suggestions for improvement to ek9lang@gmail.com.

There is a lot here; it takes time to understand it all. Besides the examples throughout, some sections hold code that solves general problems in different ways in EK9. Reviewing those helps as much as reading the pages.

Every example on these pages is compiled by the current compiler, and every output shown is captured from a real run. This is not theoretical ideas or vapour-ware.

Where to go next:

TL;DR

For the licensing and the current state of development, jump to those sections or keep reading.

If you are new to software development and think you might use EK9, there is a brief overview of other languages to consider. It is not there to dissuade you from EK9, but to help you make an informed choice.

The same section outlines the mainstream current languages EK9 has taken design and structure from; each is excellent in its own right. What matters to any developer is supporting tools (an IDE), ease of syntax, a big library of functions, classes and components, and above all wide adoption: code examples and a supportive, informed developer community.

The purpose of creating EK9

EK9 is designed to reduce boilerplate code and punctuation, and it provides pragmatic type inference. Its default operator syntax has EK9 generate many simple operators for you.

It borrows constructs and syntax from other languages (layout, functions, classes, etc), so it should feel familiar, but it defines several new concepts. It also (re)introduces older Unix ideas such as streaming/pipelining, and limited operator overloading that Unix/Linux and C/C++ developers will know. The main additions over other languages are here.

There is no totally new concept that will change the world, but there are more abstractions and improvements. Everything EK9 offers could be written in C or assembly; the concepts and abstractions are the value being added, not ease of implementation. Design note: folding design patterns into the language makes the argument, from subroutines to components and from Spring's annotations to compile-time checks.

A language that is easy to read and to start with, and that also serves small, medium, large and very large applications, is a challenge. Some early examples may look trivial and easy in many other languages. Look further, especially in the structure and standard types sections: their examples start simple and become progressively more fully featured.

Why was it created?

Like most programming languages, EK9 fills a perceived gap. The 'hello world' example shows the influence of Unix, C, Java and Python. EK9 also takes features from older languages such as Haskell, newer ones such as Swift, and ones such as Java and C# that have proven robust and utilitarian over time. Long-lived design patterns, and the acceptance of HTTP/REST/HTML/CSS/JSON/SQL, also shaped the design.

Some languages (Java in particular) have struggled to incorporate new ideas elegantly (opinion); others, like Python, have not kept backwards compatibility in every release. That is not a criticism of either: once the DNA of a language is set, additions such as Generics and Functions never fit as fully as they would have if designed in from the outset.

Rather than retrofit these concepts into an existing language, experiments on paper tested how such diverse and seemingly incompatible ideas could be forged together. It became obvious that a new language was necessary. If you question the need to forge them together at all, read the other languages section: there are many good alternatives to EK9.

Third-party APIs and libraries using Annotations extend existing languages, but they are non-standard and not compiled and checked as part of the language, or their checks are delayed until run time. These drivers are why EK9 has Templates/Generics and Classes/Functions baked in from the start.

The Elephant in the Braces { }

Why indentation, as in Python, rather than the '{' '}' that C, C++, C#, Java, Javascript, Scala, Dart and Kotlin use to define blocks?

Because of ';}});': excessive, confusing punctuation. The Python-like layout does not suit everyone and has drawbacks - white space is invisible, which cuts both ways - but avoiding punctuation, especially {, [ and ( mixed together, is worth it.

Why EK9 does it this way. Clarity on the eye is the main reason EK9 follows Python and YAML in its layout.

The Current Situation in Development of EK9

EK9 is new and still unproven in production. The language is complete for its first release, the compiler implements it, and the tooling around it (IDE, debugger, test runner, coverage, profiling, an MCP server for AI assistants) works today. Every example on this site is compiled by the current compiler, and the ones that print are run and their output checked.

What it does not have yet: production users, a mature standard library, a body of third-party libraries, or a community to ask. The native back end (through LLVM) is well advanced but not complete.

A beta release is planned for mid-2027, for those prepared to take a risk on a new platform: researchers and academics, students and hobbyists, and startups that value catching mistakes at compile time over a large ecosystem. If you need a production platform with a large library ecosystem today, EK9 is not that yet.

Read on if:

Creating a modern language from scratch is a very long term undertaking and needs more than coders: testing and documentation are as critical as the language, the compiler and the IDE plug-ins. With so many good modern languages available, the bar for something new is very high; a language that is only slightly better won't be adopted.

Many languages take decades to establish themselves and some stay niche; others, like C, will probably be around forever. The hope is that EK9 proves useful to developers whose work suits it.

Why EK9 does it this way. EK9 is not meant to denigrate other languages or frameworks. It is another go at evolving programming by adding alternative constructs. It may succeed, find a niche, or not; but evolution should at least be attempted.

Current development and tooling

The language is defined for its first release and the compiler implements it: every example on these pages is compiled by it, and the ones that print are run and their output checked. The compiler builds an IR (intermediate representation) that a back end turns into output. Today's back end generates Java bytecode for the JVM. A native back end through LLVM, with its own C runtime, is well advanced: parity tests run the same programs on both back ends. It is not complete yet. The compiler has the concept of a target architecture, and the IR keeps other targets possible, such as wasm, JavaScript, or MSIL/CIL for Microsoft environments.

The rest of the tooling comes with the compiler, in the one ek9 command:

Timing

Are you wasting your time reading this? Is a manual premature?

EK9 has been defined and redefined, on paper, from 2010 onwards.

The first grammar was written in 2018 and has changed enormously since. But the language has now found itself: a few decisions constrain, enable, restrict and link its concepts together, like DNA. Getting there took many steps, some of them retrograde, to find balance.

Many features were tried, removed, reintroduced and sometimes removed again, usually because they created a mismatch or contradiction, even when they were very desirable. This manual was first written to define what the language is (and is not): a concrete target of what counts as an EK9 source file. The language is now defined and implemented; what remains before a beta is breadth (the standard library, the native back end) and testing it with real users.

Documentation, support, code examples and community decide adoption more than the nature of the language does. The hope is that you find EK9 compelling, elegant, succinct and fun, but it is communities that create robust applications and drive widespread adoption. With so many good languages developed in the last decade (and more, like Ecstasy, in development), the language, runtime and tooling have to be very, very good.

I have benefited throughout my working life from a wide range of programming languages, tools and operating systems: Pascal, C, C++, ADA, Java, Python, Javascript, KSH, CSH, BASH and Unix, many design patterns and many APIs and frameworks. Each had clear advantages over the others in specific areas.

But some good ideas had become too complex, ran out of steam, had special cases, or forced strange sequences of punctuation that 'jarred'. EK9 is my attempt to forge several ideas together into a cohesive programming language.

Some developers will find the whole approach 'wrong minded'; for some it will be too big, and for others the layout and syntax won't feel right. Bjarne Stroustrup has some comments on languages worth reading, and there are other languages if EK9 does not feel right for you.

Licensing

The EK9 compiler and tools are proprietary; the EK9 runtime is licensed under the Apache License 2.0. Both are copyrighted by Stephen John Limb. The text of this site, every example on it and the Q&A corpus are dedicated to the public domain under CC0 1.0. See the license for details.

The EK9 language has a trade mark. It decides what counts as a valid EK9 source file, which has to be controlled for compatibility; see the trade mark policy.

For licensing inquiries, contact ek9lang@gmail.com.

EK9 language

EK9 is a compiled, strongly typed language (there wasn't an EK1...EK8 and there won't be an EK10).

New Starters

Start with the section on structure. EK9 has the normal constructs and concepts of most imperative languages, including the basics of variable declarations and code comments.

Then read about the built-in types (Integers, Strings, etc) and the operators; together they let you do basic processing. EK9 has several kinds of operator, including a 'fuzzy match'.

Flow control covers if/else, for/do/while and switch. They are like most languages, with additions: guards, assign-if-unset and multiple values in a switch case. Exceptions and error handling is also like other languages with Exceptions, but EK9 has the idea of unset (a bit like an Optional) built into every type.

If you have used Pascal, C, Java or C#, skim these sections (noting the additions) and move on to Records, Classes, Functions and Traits. The concepts exist in most OO languages, even where the syntax differs. First class functions may be new; they turned out to be essential to other capabilities, such as pipeline processing.

If the layout and approach fit the way you like to work, EK9 has much more in the same vein. If they don't, look at other languages instead.

Learning with an AI

An AI assistant makes a good study partner: ask it to explain a construct, to write a small example that you then compile and change, or to tell you what an error means. EK9 suits this way of learning. Whatever the AI writes still has to get past the compiler, so a mistake in its code shows up as an error you can both read, not as a program that quietly does the wrong thing.

Most AI models have seen little EK9, so give yours the reference first:

An assistant that supports the Model Context Protocol (MCP) can go further. Started with ek9 -mcp, the compiler gives it tools to compile your code, read the errors, explain an error code and search the Q&A, so it works on your files under the same checks you do. The set-up is in the MCP server section.

Experienced Developers

Functions and classes are on an equal footing: both were built in from the outset and they complement each other.

There is no null in EK9. It has only Objects, no primitives, and any value can be unset: it has no valid value. For example, a Float divided by zero is unset, and any operation on that unset value gives an unset result. EK9 has operators designed to work with unset values.

There are new ideas that may fill a gap in how you have solved problems before. Extension by composition pulls an architectural design approach into the language. It changes how you build reusable elements: you compose them rather than rely only on inheritance, which allows much more reuse.

EK9 has extension through inheritance, and you can extend functions the same way: you can write an abstract function. With dynamic classes and dynamic functions you can define something similar to (but not the same as) a lambda.

The sections on readable pipelines and pipelines if lambdas were used explain why pure lambdas are not in EK9. That is by design, and some developers will miss them.

Functions can be passed around as variables (delegates, as Microsoft calls them). Combined with classes, this varies behaviour per object instance: a method can delegate to a function, so to change what a class does you do not always need to extend it - give it a different delegate. Together with traits this gives much more flexibility through extension by composition.

Whetting your appetite for more

The capabilities above are similar to other languages; the areas below start to become EK9 specific.

The functional idea of pure (immutability, no side effects) is built in. Pure scopes are limited in assignments and mutations of data, so EK9 needs no explicit immutable data structures and no final, const or similar keywords.

For example, the + operator must be declared pure (E07500): it must not mutate. The += operator is not pure and does mutate state.

EK9 has Generic/Template development (see this article if the terms are new). There are limits on how generic types are defined and used: pragmatic restrictions to limit complexity. Some developers will find them too limiting; for most they give capable constructs for code that works with a range of types in a parametric polymorphic way.

EK9 comes with generic types that were designed in from the outset, not added later - the language needs them. They include:

Folding design patterns into the language

Some developers and language theorists argue that a language should be minimal: more keywords and concepts mean more to learn, and patterns come in and out of fashion. Lisp and Clojure take that route, and there is much to be said for it. EK9 goes against it, in a controlled way.

None of the patterns is compulsory. If you write web services, you have to know the HTTP verbs anyway, so having them in the language means you don't also learn a third-party API. If you don't write web services, you never need the verbs at all. Design note: folding design patterns into the language sets out the criticism and the reasoning in full.

Dispatcher

The next ideas pull design patterns into the language. Some exist as third-party APIs or techniques; Swift includes the following dispatch idea.

A dispatcher method on a class handles polymorphic types. You mark one method as a dispatcher that accepts a base type or trait, then write methods of the same name that accept classes extending that base type. When you call the dispatcher, EK9 works out which method is the best match for the argument.

This removes the need for casting or instance of checks. EK9 has no syntax to cast or test the type of an Object, and no word null; other mechanisms make them unnecessary.

Why EK9 does it this way. Without the dispatcher, EK9 would have been forced to introduce casting and instance of. Without operator overloading and ? (is set), it would have to use null.

Dependency Injection (DI) and Inversion of Control (IOC)

If you use Spring but feel it has gone too far from its original idea of IOC and Dependency Injection, EK9 has a more limited, constrained approach built in: components/applications and dependency injection.

This is the main reason EK9 has no static or global variables: with IOC/DI neither is needed. You can still reach a singleton through DI, but it is more loosely bound. DI also complements the constants construct, letting more complex Object instances be used throughout your software.

EK9 also has Aspect Oriented Programming (AOP), designed to dovetail with dependency injection rather than be a separate tool kit. It lets you intercept method calls on a component and do processing before and after the method call.

None of these concepts is new; they exist in different languages, APIs and toolkits. EK9 brings them together with a simple syntax and compiles them. With IOC/DI, variable scope is simpler: there are no global variables fixed in their naming. You can still have a global variable if you have to, but only through IOC.

Why EK9 does it this way. The IOC and aspect-oriented features are deliberately watered down and constrained in where they apply, to prevent overuse. If that is too minimal for you, Java or Kotlin with Spring may suit you better than EK9.

Defaulting Constructors and Operators

The Java project Lombok uses Annotations to generate methods automatically. Both 'Spring' and 'Lombok' are, in effect, an additional programming language on top of Java, written in Annotations.

Generating 'default constructors' and methods like 'toString' or 'hashCode' from a class's fields is a reasonable idea. Lots of getters and setters are not: the class starts to look like a DTO.

EK9 has a simple syntax for a 'default constructor' and for generating simple operators, but no generated getters and setters. Use a record to hold DTO values and compose it with the class, or write the getters and setters yourself if you want them.

EK9 has named arguments, so Object construction is clearer, but every argument must be supplied (unlike Python). You can have several constructors; if you have many parameters, review your design, or group related data in records (better still, use composition with several constructs).

A drunkard's walk?

You may be thinking: design patterns, no null, strange syntax and very specific constructs where a class would do - is this a drunkard's walk, picking up this and that in an incoherent, haphazard way, with every 'buzz word', technique and paradigm in it?

Most large-scale software uses many of these techniques in some form, but always inconsistently, or with so many dependencies that fusing them takes real work. EK9 is a tool box: if you don't need a tool, don't use it.

New/revisited concepts

The ideas that follow rework existing concepts that are often found not in programming languages but in Unix/Linux shells or in third-party components and APIs.

Pipeline processing

Many OO APIs chain methods to filter, map and reduce, in what is called method chaining or a fluent interface. Both are similar in concept to the pipeline Douglas McIlroy created for processing text files on Unix (a very clever idea). So streaming Objects and piping file contents will be familiar to many developers.

EK9 combines both with the functional programming style and the Monad concept from Haskell. A stream of Objects (and Function delegates) is sent through a processing pipeline, where commands (listed below), some with a function, control the flow or transform the contents or type of the Objects that continue down the pipeline.

The pipe '|' symbol joins the parts of the pipeline, as in Unix. The stages include:

EK9 adds:

The terminal part of a pipeline collects the results. If you have used shell commands like 'ps -fe | grep mysql', you will feel at home with EK9 pipelines.

Streams/Pipelines explains them all; you may find them one of the main reasons to consider EK9. They remove the need for complex nested for loops over collections (though you can still write those). They present the processing readably, and they reuse functions that have a single, testable (and pure) purpose. Above all they remove endless null checking (an idea from Haskell): EK9 uses is set instead; see operators.

Why EK9 does it this way. The Unix pipeline has stayed in use since the 1970s, so the concept has proven its worth; its syntax is familiar, readable and terse. Functional programming is accepted again (for some it never went away). And in the object-oriented world, the many different methods each API offers for the same streaming leads to confusion, repetition and inconsistency.

This is an important point, and many may disagree: an object-oriented technique has been misused to create a functional programming flow. It is like using a screwdriver as a chisel; you can, but why not use a chisel if that is what's needed?

Pulling pipelines into the language, with the is set nature of Objects (Haskell's Maybe/Monad) and Generics (containers of zero or more Objects), gives one standard syntax and promotes functions as solid, testable building blocks. Neither the functional nor the Object-Oriented approach is claimed to be better; each has strengths and weaknesses, and EK9 lets you use both in harmony.

Threads

Does EK9 use Threads or Cooperative multi-tasking (like Javascript)? EK9 assumes Threaded implementations, and the pipeline above has async, which calls several functions at the same time.

Threads appear elsewhere too: in Network Types the TCP server, and to some degree the UDP server, accept multiple concurrent clients, and signal handling implies multi-threading. For that, EK9 has a Mutex Lock built in. Where you can, avoid simultaneous access to data structures: it leads to complexity, defects and performance issues.

There are no promises or await keywords. If you want to run several tasks at once, stream pipelines and async are the only way.

Without Objects and Generics there could be no Lists, and without Lists, Functions and is set there could be no Pipelines. Each construct matters, and each is used where it fits.

Preview

Here is a preview of how EK9 forges Unix pipelines with functional programming, Monads and an object-oriented approach. cat starts streaming a collection, people is a List of Person (Person is a record), lastNameAndDob, lastNameComparison and the rest are functions, and stdout is an instance of the Stdout class, which prints Strings to the terminal.

Readable pipeline
cat people | uniq by lastNameAndDob | sort with lastNameComparison | group by personProfession | sort by professionComparison | map with personToString > stdout

The flow of the pipeline is obvious. For longer pipelines there is a column layout that is easier still to read:

cat people
  | uniq by lastNameAndDob
  | sort with lastNameComparison
  | group by personProfession
  | sort by professionComparison
  | map with personToString
  > stdout

Readability and testability are the main reasons EK9 does not promote in-line lambdas. The column layout, with short lines, is always easier to read, at the cost of longer methods and functions. Here is lastNameAndDob (the backtick String builds the person's last name and date of birth - each ${...} inserts a value as text):

'lastNameAndDob' function implementation
lastNameAndDob() as pure
  -> p as Person
  <- rtn as String: `${p.last} ${p.dob}`

With in-line lambdas in the pipeline, you would have to name the variable being accepted (here 'p') and add a new operator '=>'. An excerpt would then read:

Obfuscated pipeline (not supported)
cat people
| uniq by (p) => $ p.last + " " + $ p.dob
| sort with lastNameComparison
| group by personProfession
| sort by professionComparison
| map with personToString
> stdout

You are drawn into the lastNameAndDob implementation, and it distracts you from the flow of the pipeline: you lose your place in what the pipeline is for. Imagine the full pipeline with every implementation detail exposed, some over several lines: much harder to understand, test, maintain and alter.

Why EK9 does it this way. When every operation has to be a function, writing a unit test for it is straightforward. An in-line lambda cannot be tested in isolation and cannot be reused, which leads to copy-paste and code that is not DRY. Generic collections, record/class objects and functions each do what they are best at, and the result is readable, re-usable, simple, maintainable and strongly typed. Writing functions instead of in-line lambdas costs more; that cost is acknowledged and accepted.

Web Services

EK9 has support built into the language to define web services and resources, i.e. HTTP end points. These capabilities usually come from third-party APIs with bespoke Annotations, but HTTP and REST/RESTful web services are here to stay. For REST, read the original dissertation by Roy Thomas Fielding (Dr). The same web service methods can implement GraphQL.

Technologies that were once an aside to mainstream programming are now a fundamental building block, and EK9 treats them as one. Below is a simple GET; Web Services shows all the verbs. Read operators first: POST is +=, 'adding' a resource, in keeping with how EK9 treats collections.

You can go beyond CRUD (RPC) and implement level 3 REST with HATEOAS, which is driven by the content. EK9 provides the basics: HTTP and its verbs.

#!ek9
defines module site.introduction.addresses

  defines service

    //define the service called 'Addresses', map it to a URI of '/addresses' and open it to callers
    Addresses for :/addresses open

      //A GET
      listByPostCode() as GET for :/{postCode}
        ->
          postCode as String :=: PATH "postCode"
          acceptLanguage as String :=: HEADER "Accept-Language"
        <-
          response as HTTPResponse: (postCode, acceptLanguage) with trait of HTTPResponse
            //override HTTPResponse content, status and so on to complete processing.
            override content()
              <- rtn as Bytes: Bytes().withUtf8(`{"postCode": "${postCode}"}`)
            override contentType() as pure
              <- rtn as String: "application/json"
            override contentLanguage() as pure
              <- rtn as String: acceptLanguage
            override status() as pure
              <- rtn as Integer: 200
            default operator ?

The key concept in REST is the resource. In EK9 it can be any content, serialised from any of the constructs - typically records and/or classes, as they hold state. A String in a particular layout (i.e. JSON) works too, if that is appropriate.

EK9 philosophy (or approach)

EK9 blends existing language constructs, concepts, design patterns and sometimes syntax, gently and cohesively. So an individual EK9 construct is not always as capable, terse or flexible as its counterpart in another language.

Linked together, though, the approaches give a solution that is more explicit, simpler to develop, more capable overall and reusable, and above all readable. The focus is code that is reasonably terse, understandable and reusable, rather than quick to write the first time. Long-lived code is always read many more times than it is written.

EK9 is statically, strongly typed, and favours readability, reuse and composition over terseness. For that reason there are no list comprehensions (E01081); pipelines deliver the same functionality.

Lambdas

EK9 separates how functionality is implemented from where and how it is used (abstraction). Including the details of a lambda where it is used flies in the face of that; compare the function pipeline with the in-line lambda pipeline. A simple operation like the proposed lambda is likely to be needed elsewhere, so define a function and reuse it; a more complex one has even more reason to be a named, testable function.

There is a compromise: a dynamic function that extends an abstract function can be written in-line, but only as a single line. See DynamicMathExample1 and DynamicMathExample2 for why. Because abstract functions infer the incoming and returning parameters, the main cost of declaring them is mitigated. Only by writing EK9 code and the worked examples did it become obvious that this compromise should be made. Designing a language is all about compromises; in-line lambdas will be missed by some developers.

Break and Return

EK9 does not use break or return for flow control. Functions and Methods return values, but always at the end of the scope block, and a loop cannot be broken out of early. Like most things in software design, this is subject to heated debate.

Why EK9 does it this way. There are already several ways to control flow: if/else if/else, switch and try/catch/finally with exceptions. The wish to 'return' early or 'break' out of a loop comes from a procedural, imperative approach. Its biggest cost is how hard it becomes for a human (not a compiler) to follow the path through a block. Logic near the end of a function or method may no longer run, so the code is harder to reason about, refactor and modify. The design note on break, continue and return gives the record behind the decision.

Break and Return Alternative

Instead of many for loops and if/else branches, use pipeline processing: combinations of filter, head, tail and skip do what early returns and breaks did, in a standard, maintainable and obvious syntax. You may find it constraining at first. It leads to more small, discrete functions, which promotes re-use and unit testing, and each function name (ideally a meaningful one) documents what it does.

User Interface, SQL and Libraries

EK9 leaves three things outside the language:

Design note: what EK9 leaves out explains each decision.

Conclusion

EK9 was developed over many years by looking at which techniques and technologies work and which don't. The hope is that its syntax, mechanisms and layered approach give you a range of tools for software that is flexible, pragmatic, maintainable and clear.

Some developers with similar experience will have drawn the same conclusions; some will strongly disagree with the direction EK9 has taken. There is ample choice: select the language that suits your experience, your nature and your project.

Many larger applications are now microservices, some running in containers behind caches, load-balancers and façades.

Finally

EK9 is big, and in some ways a departure from existing languages. To be widely adopted it has to give real, significant benefits over other languages; "a bit easier or better here and there" is not enough.

Languages usually become popular not through syntax but by solving a major development problem or finding a niche. It is not yet clear how EK9 will. Its syntax and constructs give developers ways to express themselves, but that is unlikely to be enough on its own: it needs a compelling set of APIs that give developers value.

The layout has some general aspects:

It may take a while to get your 'eye in'. Once you are used to the indentation and to -> and <-, the flow of data should visually 'click'. You should be able to 'step back' and see the structure without reading the words - the shape of the wood rather than each tree. It sounds a bit hippy and new-age, but the syntax and file layout were designed to be pleasing on the eye and readable for humans (indentation, columns, structure and direction).

Operators get particular focus because they carry consistent meaning taught in schools from an early age, such as +/-. They solve many of the naming and semantic problems of languages without operators.

Next Steps

Go to structure for much more detail on the constructs outlined above.

Other Languages

Other languages may suit specific programming tasks better. Before looking into EK9, consider what kind of solution you want to build.

Compiled to produce native applications

Compiled and strongly typed languages that use a runtime

Choosing between Java, Scala and Kotlin (all on the JVM) comes down to preference and balance; there is no big issue with any of them.

C# is a bigger decision: it takes you well into the Microsoft camp. It is a very, very good language and addresses many of the issues that emerged in Java.

Other Compiled and strongly typed languages of note

Interpreted/Scripted Languages

Other Languages worth considering

Next Steps

To understand more about EK9, read structure next.