A typical Strict file is easy to understand and very short. Unlike other languages following the Coding Style is enforced. That is why the language is called Strict, humans and machines can understand it easily, machines can generate code easily and overall it is fun to use! Strict is a simple, efficient, and portable programming language that is mostly working like functional programming languages. It only includes the minimum set of features needed to write meaningful, efficient, and portable programs.
has App has log Run log.Write("Hello World")
The first line implements the App interface, which provides us with the Run entry point method. The next line injects the Log class, the member is called log, the parser automatically interprets this as the type Log, which isn't written. Normally every method starts with a test, but if a method doesn't mutate anything and doesn't return, there is nothing we can or need to test.
The main difference to any other language out there is that it can be actually understood and written by machines (unless we are just consuming external libraries). It is also the only language we know of that completely enforces tests and clean code, other languages have great concepts and frameworks and many people doing it correctly, but in no way is it enforced by the language itself, which leads very often to code that is not reusable, can't be understood and a messy eco system of hard to use or even broken libraries, version conflicts and many other pain points.
Strict is both readable by humans and machines. It has a simple syntax and throws away much of the boilerplate code that has to be written in other languages. The language constructs are easy to understand and code can be read like a good novel. In the compiler pipeline the full source code and the AST are always available to let tools go back and forth easily and quickly. Even if not in memory the .silk files of compiled packages can be read and both the AST and full source code can be reconstructed at any time with ease.
Lower case means private, constructors don't exist like in go and are autogenerated, for factories we can simply use the from keyword and methods appear in the way they are called. Every method must start with at least one test, which are always running in the backrgound via the IDE (ala NCrunch, we call it SCrunch). Any slow running class will fail all tests it is involved it (tests run in less than 10ms) and thus require a Mock implementation that can be used instead of the real thing (e.g. database, file or web access, etc.)
Empty lines can't be written, they are shown by the editor as separators, whitespaces are not allowed and comments can only rarely appear in front of a method, nowhere else. Empty parenthesis are removed, almost everything is immutable and functional, writing mutable code is possible (mostly for optimizations), but highly discouraged (no automatic concurrency). Most of the formatting work is done automatically in any supported IDE or Editor: Visual Studio, Visual Studio Code, IntelliJ, Atom, etc.
The main goal of any strict package is to be as reusable as possible. The main problem with most of the code out there, especially with very low level languages is that the code is NOT reusable. If anything changes, any library is different, the PC achitecture is different, if the sun is shining or there isn't a full moon, the code breaks and it is certainly not reusable in all other domains. Code is usually rigid, fragile, we cannot take code and reuse it, etc. it is always coupling and dependencies! Uncle Bob explains this well in this video.
How do we archive this? Strict checks ALL public code that exists at all times, if there is a package, type, method or even clever algorithm that already exists, it will refuse to compile the code again and force the code to resue the existing code instead. This means there is NO copy+pasting, you can't just take a library you like and make a 5% change to it, you can't take a type or method and just change a detail that doesn't really change the algorithm. High level policies and algorithms should not be coupled with low level crap (as Uncle Bob says in the above video at 34:20).
Packages are small and are very different from what you might know from big frameworks like Java, .NET or std. Strict starts out empty, it doesn't know anything, there are no classes known by default. Most of the time you use the Strict.Base package by using any base type like Any, Number, Type, Iteration, etc. but you don't have to. If you are writing a library the App trait is never imported or used. Simply generate a small bit of strict code to any other language and you will see only the types that were used are generated (which is a super tiny fraction). This makes the language very fast to parse and use.
All packages are automatically imported and used (based on build.yml settings, by default anything locally available and that can be downloaded from https://github.com/strict-lang), there is no import, include or using statement, the Editor figures this all out for you. You just type what you want to do and if there is a type already, it will be presented to you, otherwise you become the creator of a new feature (for everyone to use if you choose to publish publicly).
Strict source files are stored in folders (directories) whose names are used as the last element of the namespace (package if it is at the root level) name. The preceding elements, if any, are made up of the parent folders’ name(s) so that the topmost parent folder adds the first element of the dotted package name, its first child adds the second element of the dotted package name, and so on, until the innermost folder, which adds the final element of the dotted package name.
Strict source files ends in the extension
.strict. The filename is always the type name and the folder structure must always match the namespace.
Each source file is divided into one or more lines. Empty lines may not appear in Strict source files. The line separator character is always the \n line-feed (utf8 character 10 - LF) character, never utf8 character 13 - Carriage Return or a combination of these two.
Each source file consists of one or more lines separated by line-feed character (\n). The last line must not end with \n, no padding is allowed anywhere in the file.
Each source file’s character encoding format is always Unicode UTF-8 without a Byte Order Mark (BOM). A BOM will cause the file to be rejected. These characters may not appear in Strict source files at all:
- ASCII 0 (
NUL) through ASCII 8 (Backspace,
- ASCII 11 (Vertical Tab,
VT) through ASCII 31 (Unit Separator,
- ASCII 127 (Delete,
The presence of an invalid Unicode UTF-8 byte sequence or an invalid Unicode code point will cause the source file to be rejected by the compiler.
Indentation is always done using tab (utf8 character 9 - Horizontal Tabulator) characters only. Thus space (utf8 character 32) may never appear in indentation (similar to python, only one way to indent is allowed). A single tabulator stop character is visibly shown as two space characters, thus the indenting level is two characters per level.
Strict does not allow comments at all because of the extremely simple nature of most Strict modules. Most files don’t need elaborate commenting as the code should be always self explanatory (otherwise the AI could not read it anyways). If you need to explain some behavior or internals about the code use a Readme.md in the folder.
Code from the outside can be imported via external Method(parameters) feature (just to interface to C, for C++ or C# or Java put it in a type matching the class name). If a namespace doesn't match use external namespace Name.
If .strict code is opened and does not show any errors, it already is compiled and will work on your machine and in production. Strong typing, lots of semantic analysis and testing (built into the language) ensure that code works as expected when deployed. Not only does the compiler understand whats going on through the tests in each method, it can also modify any written code to a more efficient algorithm in realtime or even figure out what you want to do and generate the code for you based on the test without you having written any execution code yet.
The time of single core processors is at an end. Programs start to improve performance by leveraging the machines ability to execute work concurrently. Concurrency, however, comes with a lot of pitfalls. Strict takes the burdon of synchronization and shared state management of the programmer. It is written in a way that can both utilize hundereds or thousands of local threads and also distribute computation accross multiple PCs in the network or cloud if configured for that usecase. Internally it provides coroutines for easy and fast asynchronous execution.
By default all code is executed in parallel (think async/await/coroutines/tasks in other languages), but the compiler will automatically inline code and execute loops sequentially for performance reasons. However in theory all tests, all methods, all calls, all loops are executed in parallel and have to be designed that way (immutable and threadsafe), it is up to the compiler to optimize code paths (unlike other languages were parallelism is optional and hard to enforce correctly). For details see Concurrency
Composition instead of just Object Oriented
Everything in Strict is an object. However static methods and inheritance have purposefully been ommited. Instead objects are composed of other objects and features. Core concepts like encapsulation are still embraced by the language and normal usage and implementation of interfaces or external classes is no problem.
Due to the fact that there are no static methods (or any globals), no inheritance and everything can be executed in parallel an obvious conclusion is that this could be accomplished via purely functional programming. All fields are constant by default, methods usually have no side effects and are pure, but the programmer is still able to create mutable fields and methods that have side effects (e.g. void methods and especially calling external libraries). However, this is not the norm. In any case the compiler will optimize code into a more efficient code path, no matter if it sees mutable fields that can be optimized into non mutable fields, or is just optimizing calls away, precalculating parameters, optimizes tail recursion calls, makes code lock free, etc.
Strict can run in its own VM, which is what is used for testing, development and the IDE. Often you might want to dock your code to a bigger project or framework written in a JDK or .NET language and utilize many benefits there, or you want to run on a specific platform and use all tools and other languages there. Strict is flexible and can run on any x64 or ARM64 platform, plus you can generate code in C#, Java, C++ or specific platforms like Arduino or just write your own backend to generate something you need. Older x86 also will work, but are not in the focus for optimizations, in fact using the c backend, anything that can run c, can be used.
Easy to learn
Like Python or many newer languages, Strict is very easy to read and learn. It is obvious what source code does when you see it for the first time, especially as every method has tests showing how it works.
However writing Strict code is more painful if you don't know the rules and as the name implies the language doesn't allow unclean or hacky code by default. We heavily recommend using the Strict IDE to get started easily. Strict enforces a consistent and reusable code base accross all projects, not just the commonly used packages.
Strict is open source, free to use and modify, we welcome an open ecosystem. Our usecase is to make machines more intelligent, hopefully both you can benefit from the clean code and the growing ecosystem can be utilized by machines in the future to make a better world for all of us :)
Strict can be written just as a text file or from an Editor like Visual Studio Code or Atom, or you can use a full IDE like Visual Studio or IntelliJ, which we would recommend for any serious user. All these tools already provide a great user experience and have huge communities, Strict fits in nicely.
The backend is very different from most IDEs as most professional code crafters use a wide list of tools, like having the Visual Studio 2019 IDE with lots of features and plugins enabled. Visual Studio itself has not just the normal compiling, there is Code Lens, Refactoring, Code Analysis and much more. Then you might want to have a great editing experience, hotkeys and way more refactorings, you add ReSharper, which runs everything in parallel in the background as well. And to top things of you add NCrunch, which again runs in parallel in the background and has to compile everything at realtime again every time you type in any letter. This is a great experience if you have a super fast PC and a smaller project, but the bigger the project grows the less fun this can be and you might need to scale down a little.
With Strict everything is in one pipeline, the parser, compiler, SCrunch, Refactorings, Code Hints, Annotations, etc. is all coming from the same place and even adding more stuff at any point is easily possible. The main advantage is that compiled code is 100% equal to source code and can always be converted back and forth, thus we can keep everything compiled until something changes in a much easier and faster way. Our goal is to have all useful Strict libraries that are open be compiled and available all the time with any Editor (this is why Strict doesn't have any import, using or include statement, the parser knows everything there is already and fills it in, for conflicts you have to specify with of two possible types you need exactly).
mutable elements Iterator(Compared) Sort Sort(3, 2, 1) is (1, 2, 3) Sort(7, 77, 111, -1, 11) is (-1, 7, 11, 77, 111) for rightIndex from elements.Range() for leftIndex from 0 to elements.Range().End - rightIndex maybeSwap(leftIndex) maybeSwap(index) Sort(1, 2, 3).maybeSwap(1) is (1, 2, 3) Sort(3, 1).maybeSwap(0) (1, 3) if elements(index) > elements(index) + 1 elements.Swap(index, index + 1)
Very good book about Structure and Interpretation of Computer Programs (great way to learn functional programming ala Lisp/Scheme or nowadays Clojure): https://web.mit.edu/alexmv/6.037/sicp.pdf
Good free book about Programming in Go: https://www.golang-book.com/books/intro
The best guide for Strict and Test Driven Development is the Clean Code book and video series by Uncle Bob: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
Really great list of books for any expert code crafter: https://www.quora.com/What-are-the-must-read-books-for-software-engineers/answer/Jason-Roell