<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vijay Mathew</title>
    <description>The latest articles on DEV Community by Vijay Mathew (@vijaymathew).</description>
    <link>https://dev.to/vijaymathew</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4216909%2F0c7225f1-fe99-4fd3-98f8-41d42c9fbb07.jpg</url>
      <title>DEV Community: Vijay Mathew</title>
      <link>https://dev.to/vijaymathew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vijaymathew"/>
    <language>en</language>
    <item>
      <title>Nex: write code that keeps its promises!</title>
      <dc:creator>Vijay Mathew</dc:creator>
      <pubDate>Sat, 31 Oct 2026 02:27:47 +0000</pubDate>
      <link>https://dev.to/vijaymathew/nex-write-code-that-keeps-its-promises-2phg</link>
      <guid>https://dev.to/vijaymathew/nex-write-code-that-keeps-its-promises-2phg</guid>
      <description>&lt;p&gt;Code generation has become cheap. Ask a model for a function and you get one that looks right in seconds. Deciding whether it &lt;em&gt;is&lt;/em&gt; right still takes you just as long as it always did.&lt;/p&gt;

&lt;p&gt;Most languages don't help much with that. A type checker tells you that you passed an &lt;code&gt;Integer&lt;/code&gt; where an &lt;code&gt;Integer&lt;/code&gt; was expected. It has nothing to say about whether that integer should have been positive, or whether the account had enough money before &lt;code&gt;withdraw&lt;/code&gt; ran.&lt;/p&gt;

&lt;p&gt;I've been building &lt;strong&gt;Nex&lt;/strong&gt;, a small language that closes part of that gap. Every routine can state what it requires and what it guarantees, and Nex checks those promises each time the code runs. Nex is open source (MPL-2.0) and runs on the JVM. This post is a short tour.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bug nobody notices
&lt;/h2&gt;

&lt;p&gt;Here's a wallet with no contracts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight eiffel"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;W&lt;/span&gt;&lt;span class="n"&gt;allet&lt;/span&gt;
&lt;span class="k"&gt;feature&lt;/span&gt;
  &lt;span class="n"&gt;money&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;
  &lt;span class="n"&gt;spend&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="pi"&gt;.&lt;/span&gt;&lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt;
  &lt;span class="n"&gt;with_balance&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="nc"&gt;W&lt;/span&gt;&lt;span class="n"&gt;allet&lt;/span&gt;&lt;span class="pi"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_balance&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="mf"&gt;.2&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="pi"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spend&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="pi"&gt;.&lt;/span&gt;&lt;span class="n"&gt;money&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;-- -9.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The balance is now negative and the program keeps running with a value that shouldn't exist. The bug will show up later, after enough damage is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same wallet, with its promises written down
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight eiffel"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;W&lt;/span&gt;&lt;span class="n"&gt;allet&lt;/span&gt;
&lt;span class="k"&gt;feature&lt;/span&gt;
  &lt;span class="n"&gt;money&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;
  &lt;span class="n"&gt;spend&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;require&lt;/span&gt;
    &lt;span class="n"&gt;non_negative_amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;
    &lt;span class="n"&gt;enough&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt;
  &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="pi"&gt;.&lt;/span&gt;&lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;ensure&lt;/span&gt;
    &lt;span class="n"&gt;decreased&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;old&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt;
  &lt;span class="n"&gt;with_balance&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;invariant&lt;/span&gt;
  &lt;span class="n"&gt;never_negative&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;money&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three kinds of promise appear here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;require&lt;/code&gt; is the &lt;strong&gt;caller's&lt;/strong&gt; obligation. Spending more than you have is a bug in the code that called &lt;code&gt;spend&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ensure&lt;/code&gt; is the &lt;strong&gt;routine's&lt;/strong&gt; obligation. &lt;code&gt;old money&lt;/code&gt; is the value on entry, so the postcondition can describe the change, not just the final state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;invariant&lt;/code&gt; must hold for every &lt;code&gt;Wallet&lt;/code&gt;, after creation and before and after every call from outside.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the same call fails immediately, at the point where things went wrong, and the error names the clause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nex&amp;gt; w.spend(20.0)
Error: Precondition violation: enough
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a wallet can't even start out broken:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nex&amp;gt; create Wallet.with_balance(-10.0)
Error: Class invariant violation: never_negative
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These aren't assertions from a library. They are part of the grammar, which is why &lt;code&gt;old&lt;/code&gt; can reach back to the value on entry. It's also why the contract can be the documentation: &lt;code&gt;nex doc&lt;/code&gt; extracts signatures and contracts into a reference that can't drift from the code, because it's generated from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the spec, let someone else write the code
&lt;/h2&gt;

&lt;p&gt;This is the part that matters most with AI in the picture. A &lt;em&gt;deferred&lt;/em&gt; class (an abstract class, in most languages) can state a contract without any implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight eiffel"&gt;&lt;code&gt;&lt;span class="k"&gt;deferred&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;D&lt;/span&gt;&lt;span class="n"&gt;iscount&lt;/span&gt;
&lt;span class="k"&gt;feature&lt;/span&gt;
  &lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;
    &lt;span class="k"&gt;note&lt;/span&gt; &lt;span class="s2"&gt;"The price after the discount."&lt;/span&gt;
  &lt;span class="k"&gt;require&lt;/span&gt;
    &lt;span class="n"&gt;non_negative_price&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;
  &lt;span class="k"&gt;deferred&lt;/span&gt;
  &lt;span class="k"&gt;ensure&lt;/span&gt;
    &lt;span class="n"&gt;never_more&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
    &lt;span class="n"&gt;never_negative&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the specification: a discount never raises the price and never takes it below zero. It says nothing about &lt;em&gt;how&lt;/em&gt; to compute it. Ask a model for a flat discount and you might get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight eiffel"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="n"&gt;lat_Off&lt;/span&gt; &lt;span class="k"&gt;inherit&lt;/span&gt; &lt;span class="nc"&gt;D&lt;/span&gt;&lt;span class="n"&gt;iscount&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt;
  &lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;feature&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;
  &lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="pi"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt;&lt;span class="pi"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="n"&gt;eal&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="pi"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It doesn't repeat a single clause, and it doesn't have to. In Nex, an implementation inherits every contract of the routine it implements, automatically. It works for the obvious test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nex&amp;gt; create Flat_Off.make(10.0).apply(50.0)
40.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it fails the first time the discount is bigger than the price:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nex&amp;gt; create Flat_Off.make(10.0).apply(5.0)
Error: Postcondition violation: never_negative
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A percentage discount configured at 150% fails the same way. Configured at -10%, it fails &lt;code&gt;never_more&lt;/code&gt;. The spec is the target the implementation has to hit, and the check that tells you whether it did. Whoever wrote the implementation, a person or a model, gets caught the same way.&lt;/p&gt;

&lt;p&gt;Inheritance works like this throughout Nex. A subclass can accept more and promise more, but never the reverse. Preconditions are combined with &lt;code&gt;or&lt;/code&gt; and postconditions and invariants with &lt;code&gt;and&lt;/code&gt;, so an override can't quietly break a promise its parent made.&lt;/p&gt;

&lt;p&gt;I wrote about where this leads in &lt;a href="https://schemer.in/nex/blog/when-code-is-cheap.html" rel="noopener noreferrer"&gt;When Code Is Cheap, Design the Promises&lt;/a&gt;. It covers how specifications and documentation change when code is cheap to generate. It also covers how to track the changes that matter as the code evolves: changes to what it &lt;em&gt;promises&lt;/em&gt;, not just changes to the code itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Isn't this just Eiffel?"
&lt;/h2&gt;

&lt;p&gt;Nex owes a lot to Eiffel, where Design by Contract comes from, and the syntax shows it. Here are the main differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contract inheritance is automatic.&lt;/strong&gt; Eiffel asks you to opt in with &lt;code&gt;require else&lt;/code&gt; and &lt;code&gt;ensure then&lt;/code&gt;. In Nex, the safe combination is the only behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A small core.&lt;/strong&gt; The grammar is small enough to learn in full. Libraries and host integrations live outside the language, so it doesn't grow a keyword for every feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Objects and functions together.&lt;/strong&gt; Classes and inheritance sit beside first-class functions, so you can use whichever fits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The JVM.&lt;/strong&gt; Nex compiles a program to a single jar that runs anywhere Java does, and it can call Java libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  "Why not Java with assertions?"
&lt;/h2&gt;

&lt;p&gt;You can get part of the way there, but it takes discipline. Java's &lt;code&gt;assert&lt;/code&gt; is off unless you pass &lt;code&gt;-ea&lt;/code&gt;. There's no &lt;code&gt;old&lt;/code&gt;, so every postcondition about change needs local variables captured by hand. There are no class invariants, so the check has to be repeated at the end of every public method. And nothing makes a subclass honour its parent's contract.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://schemer.in/nex/blog/design-by-contract.html" rel="noopener noreferrer"&gt;Classes and their Contracts&lt;/a&gt; puts the same class side by side in Java and Nex.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Nex isn't
&lt;/h2&gt;

&lt;p&gt;Runtime contracts aren't proofs. A contract catches a broken promise when the code path that breaks it runs. A path no test or user exercises can still be wrong. In short: you state what a program must do, and Nex checks it.&lt;/p&gt;

&lt;p&gt;It's at version 0.6.7, so the language can still change between releases. The tooling that exists today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a REPL&lt;/li&gt;
&lt;li&gt;a compiler to standalone jars&lt;/li&gt;
&lt;li&gt;a formatter&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nex doc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a language server, with a VS Code extension and an Emacs mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The essay &lt;a href="https://schemer.in/nex/designed-for-correctness.html" rel="noopener noreferrer"&gt;Designed for Correctness&lt;/a&gt; explains the design choices in more depth, including why contracts make Nex a good first language for teaching software engineering in the age of Generative AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You need Java 17 or later. On Linux and macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/vijaymathew/nex/main/bootstrap-install.sh&lt;span class="o"&gt;)&lt;/span&gt; jvm &lt;span class="nt"&gt;--install-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Windows, user-local installs and building from source are covered on the &lt;a href="https://schemer.in/nex.html#install" rel="noopener noreferrer"&gt;install page&lt;/a&gt;. Then run &lt;code&gt;nex&lt;/code&gt; to open the REPL.&lt;/p&gt;

&lt;p&gt;Where to go next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://schemer.in/nex/tutorial.html" rel="noopener noreferrer"&gt;A Tour of Nex&lt;/a&gt;: the whole language in one fast walkthrough.&lt;/li&gt;
&lt;li&gt;Three free books: &lt;a href="https://schemer.in/nex/docs/programming-with-nex/cover.html" rel="noopener noreferrer"&gt;Programming with Nex&lt;/a&gt; for your first programs, &lt;a href="https://schemer.in/nex/docs/beyond-code/cover.html" rel="noopener noreferrer"&gt;Beyond Code&lt;/a&gt; for software engineering through Nex, and &lt;a href="https://schemer.in/nex/docs/tight-core-open-edge/cover.html" rel="noopener noreferrer"&gt;Tight Core, Open Edge&lt;/a&gt; for correct and flexible design.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vijaymathew/nex" rel="noopener noreferrer"&gt;The code on GitHub&lt;/a&gt;, and &lt;a href="https://github.com/vijaymathew/nex/discussions" rel="noopener noreferrer"&gt;Discussions&lt;/a&gt; for questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd like to hear what you think, especially from anyone who has tried Design by Contract in another language. What made it stick, or made you drop it?&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
