languages
#define languages: \
I----------------------------------------------------------------------------------------------\
I----------------------------------------------------------------------------------------------\
I----------------------------------------------------------------------------------------------\
I \
I /$$ \
I | $$ \
I | $$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ \
I | $$ |____ $$| $$__ $$ /$$__ $$| $$ | $$ |____ $$ /$$__ $$ /$$__ $$ /$$_____/ \
I | $$ /$$$$$$$| $$ \ $$| $$ \ $$| $$ | $$ /$$$$$$$| $$ \ $$| $$$$$$$$| $$$$$$ \
I | $$ /$$__ $$| $$ | $$| $$ | $$| $$ | $$ /$$__ $$| $$ | $$| $$_____/ \____ $$ \
I | $$$$$$$$| $$$$$$$| $$ | $$| $$$$$$$| $$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ /$$$$$$$/ \
I |________/ \_______/|__/ |__/ \____ $$ \______/ \_______/ \____ $$ \_______/|_______/ \
I /$$ \ $$ /$$ \ $$ \
I | $$$$$$/ | $$$$$$/ \
I \______/ \______/ \
I----------------------------------------------------------------------------------------------\
I----------------------------------------------------------------------------------------------\
I----------------------------------------------------------------------------------------------I
https://kidneybone.com/c2/wiki/SufficientlySmartCompiler
• the minimum requirement to be considered a programming language is to be Turing-complete
• not all languages are programming languages
Generations: Generations:
+------+----------------------------+
| I. | Binary code |
+------+----------------------------+
| II. | Assembly languages |
+------+----------------------------+
| III. | High-level languages |
+------+----------------------------+
| IV. | Domain specific languages |
+------+----------------------------+
| V. | Constraint based languages |
+------+----------------------------+
• the generational classification is important to understand
how languages depend on each other
• it would be highly impractical to implement a language of generation ${N}
without generation ${N}-1
• this schema has been widely used to advertise programming languages,
since from the understanding of a manager, the bigger a number, the better
• OOP is sometimes claimed to be the entirety of generation IV, do not fall for it
Turing_tarpit: Turing_tarpit:
• a Turing complete programming language which is impractical to use for common tasks,
due to a lack of features
Typing: Typing:
— weak/strong:
• the difficulty of converting between types in a programming language
is a spectrum ranging from strong typing to weak typing
• weak is the less difficult end
— dynamic/static:
• conversion safety checking/error handling done at runtime is called dynamic,
while performing it at compile time is called static
• the extend of how much dynamic and static typing a language uses
also fits on a spectrum
— gradual:
• pioneered by facebook
• type hints are allowed, but not required
• { python }
• arranging languages in such spectrum without strict quantities
only makes sense in edge cases and in terms of relations
• since proper quantities would be unreasonably hard to work out,
typing qualifications are highly subjective
{
Strong
▲ Ada
│
│ C#
│ Java
Python │
SQL │ Typescript
│ Haskell
Dynamic <──────────────┼───────────────> static
PHP │
Lua │ C
│ C++
Javascript │
Bash │
│
Tcl ▼
Weak
}
• notice that C/C++ fills in a special gap on the matrix
REPL:
• "Read Evaluate Print Loop"
• "shell"
• commonly implemented by interpreters
• less commonly implemented by JIT compilers
— process:
1. interactively read a command from the user using a text oriented intrface
2. execute the line; preserve the side effects internally for future eval-s
3. display the result of the command on the screen for the user as feedback
4. goto 1
• the exact behaviour that would be commonly used to define shells
Paradigms: Paradigms:
{
Paradigms
│
├── Declarative
│ ├── Functional
│ │
│ └── Logical
│
├── Imperative
│ ├── Procedural
│ │
│ └── Object-Oriented
│
├── Event-Driven
│
│
├── Concurrent
│
│
└── Stack-Oriented
}
OOP: OOP:
• "Object Oriented Programming"
• "ob-ject: to feel distate for something - Webster's Dictionary"
• a radical or radically Object Oriented language is one,
which does not allow free symbols or ambient class members
— The 3 pillars of OOP:
1. Encapsulation
2. Inheritance
3. Polymorphism
• i once knew a man who cla0
— OOP commandments:
• Favour composition over inheritance.
• Identify the aspects of your application that vary
and separate them from what stays the same.
• Encapsulate what varies.
• Strive for loose coupling between objects that interact.
• Program for an interface and not a implementation.
• Depend on abstractions. Do not depend on concrete classes.
• Classes should be open for extension, but closed for modification.
• A class should have only one reason to change.
— OOP and specifically radical OOP has a bit of a reputation of being overall bad,
this roots from typical negative experiences with common OOP miss usages,
one should be aware of such to be able to avoid them, here are some examples:
" \
The solution was simple and elegant: thanks to polymorphism, \
you weren't coupling the code which called the export method \
to concrete classes of nodes. \
Unfortunately, the system architect refused to allow you \
to alter existing node classes. He said that the code was \
already in production and he didn't want to risk breaking it \
because of a potential bug in your changes. \
" - an article on the visitor pattern
Whitespace: Whitespace:
— whitespace is usually defined as an arbitrary long combination
of the following characters:
' '
'\n'
'\t'
'\v'
• in some contexts when talking about significant whitespace,
newlines are excluded
Insensitive:
{ C language family; Ada }
• "does not have significant whitespace"
• a language is said to be whitespace insensitive
if whitespace between tokens is arbitrary
• new and creative ways to make code readable
• easy to auto generate with tools (promoting metaprogramming)
• new and creative ways to make code completely unreadable
• easy to create inconsistency, which will be unreadable
• can result in surprisingly heated arguments (and wasted man hours)
Sensitive:
{ Python; Yaml; Make; old Fortran }
• "has significant whitespace"
• whitespace could be used to denote blocks
• char columns have special significance
• most whitespace sensitive grammars are harder to implement
than insensitive alternatives;
the notable exception is when the dimensional position of a token is relevant
• project independent familiarity to the eye
• horrid nightmare to auto generate with tools (anti-metaprogramming)
Size:
• refers to the size of a language's feature-set
• most often measured in the lenght of the specification
— small:
• easy to implement on new architectures { Forth }
• ideal choice for bootstrapping { C }
• LLM generated code is easy to maintain;
contrast it with something like C++ or Rust,
those have large feature sets and the model
may choose to use any one them at any time;
the probability of running into solutions that the programmer
doesnt properly understand and therefor is unable to accurately
oversee is much higher
• since small languages usually produce small executables relative to the SLoC,
they are ideal for malware payloads
— large:
• more likely that the programmer can express his intent directly
• less likely that every member of a team is aware of a feature,
resulting in development friction
Healthy_stack_of_development_tools: Healthy_stack_of_development_tools:
• build-system
• metaprogramming-system
• language
• editor
• debugger
Core_functionalities:
• not all functions are created equal
• some features are more important for beginners than others
• with only these functionalities scouted,
otherwise unknown languages can be maneuvered without much hassle
○ template
— blocks:
• if
• while
• function
— eval
• bool conversion
• arithmetics
— debugging:
• stack trace
• value dumping
— strings:
• concatenation
• find substring
• replace at location
• replace all occurrences
• split by delimiter
— lists:
• append
• remove
• query size
• min/max
• find element
— I/O:
• console input
• console output
• file into string
— miscellaneous
• random number
Esolang: Esolang:
• "esoteric programming language"
• a strange, obscure and unconventional language which
is usually the product of recreational programming
• not designed with the intent of appealing to the masses
• tend to be clever turing-tarpits
Memelang: Memelang:
• a general purpose language which was not intended as a joke, but in effect is one
• all autists dream of their own language,
some come out as esolangs,
many end up as memelangs
• being referred to as a "C killer" is a strong indicator of a memelang
What_experiments_in_languages_have_tought_us_so_far:
Verbosity:
• too little verbosity is unreadable and unwritable { APL }
• too much verbosity is unreadbale and unwritable { Java }
Self_documentation:
• languages which are good for large projects self document
— C/C++ headers:
• lucky accident
• while header files came to exist because of compiler limitations,
they turned out very valuable
• the header is an explicit specification of a public API of a module
• reading a header is as convinient as it gets, especially if its commented
• many dislike them, because of the development over head,
ignoring the fact how it pays back in documentation;
very small projects probabily dont need then in the form
they are conventional, there are numerous solutions
• operator overloading should strictly be done in a "redirect to function" manner,
because otherwise it robs us from self-documentation;
operator-s dont have (universal) names after all,
and abstract types will have abstract operator-s
Domain_specific_languages:
• "DSL"
• the counter-part of general purpose languages
• designed to describe a single, specific subject
○ good DSLs are
• small
• easy to learn
• saving you from footguns
• saving you from boilerplate
○ bad DSLs are
• complicated
• attempting to encapsulate general purpose functionality { rust tbsp }
• aid to a non-existent problem { dbml }
Memory_models:
— stack:
{ Forth; Factor }
— manual:
{ C }
— RAII:
{ C++; C with extensions }
• "Resource Acquisition Is Initialization"
• auto destructors
• the invention of C++
• you tell the compiler what function to call when you leave to scope and it does it;
without you having to manually call the function
• less ugly than manual memory management
• less likely to produce errors because of a programmer with dementia
( we all have dementia)
• the hidden function call(s) can lead to hard to debug errors
• less likely to produce errors because of a programmer with dementia
( we all have dementia)
{
auto myvar(); // initialization (resource acquisition)
myvar.f(); // usage
} // automatic destruction according to how (the type of) myvar is defined
— garbage collected:
" \
Another attempted solution is garbage collection, which is a \
large enforcement structure that tracks everything and interrupts \
productive work in order to perform its function (much like a \
government agency, except in this case, the garbage collector is \
ostensibly doing something approximating useful work—although \
both function by stealing valuable resources involuntarily). \
" - Ryan Fleury
{ radically OOP languages (not exclusive) }
— borrow checked:
• garbage collection with compile time guarantees
• mitigates the problem of costly and unpredictable interruptions
• i dont care that it makes people seethe,
it is a glorified garbage collector regardless
HONOURABLE_MENTION_LANGAUGES: HONOURABLE_MENTION_LANGAUGES:
• the langauges listed here are the ones you should be generally aware of,
but do not deserve their own chapter for one reason or another
{no or super-niche usecase; flawed design; theres very little to be said; etc}
Brainfuck: Brainfuck:
• famous esoteric turning-tarpit language
• its a joke language
Comments:
• any non-instruction character
Buffers:
• a buffer pointer marks a specific position inside the buffer
• pointers are initialized to position 0
• brainfuck requires 2 buffers with pointers running around inside them,
similar to regular Turing Machines
instruction:
• code segment
• instructions are read from here
data:
• storage segment
• all positions are initialized to 0
Instructions:
• : increment the data pointer
< : decrement the data pointer
+ : increment data
— : decrement data
. : output data
, : input data
[ : if data == 0 then increment instruction pointer until MATCHING ']' + 1
] : if data != 0 then decrement instruction pointer until MATCHING '['
GO: GO:
• "Golang"
• compiled
• C inspired
• reasonably good performace
• intended for quick development
• built-in concurrency support
• unused variables result in compile errors,
this "feature" alone makes the language borderline unusable,
even if the rest is nice
Lisp: Lisp:
• from 1960; one of the oldest languages alive
• kebab-case by convention
• functional, but not purely functional
• unpopular outside of academia
• no "good" implementation as explained by Lisp enthusiasts
Comments:
; <...> : single line comment
(<statement>)
Statement:
<function>( <arg>+)
Dialects:
Scheme: pass
Script_fu:
• scripting language for GIMP
• terribly documented; i dont think anyone maintains or anyone alive knows it
Elisp:
• "Emacs LISP"
• scripting language for the emacs operating system
Smalltalk: Smalltalk:
• came out in 1972
• pioneer of OOP
• has reflections
• attempts to read like natural language (hence the name)
• interactive
• supports state snapshots by default
Comments:
"<...>" : multiline comment
<key: value> : so called pragma; reflectable meta data
category : conventional key to base IDE method sorting on
Operators:
• robust system created for operator overloading
• somewhat similar to how haskell deals with them
— unary:
<arg> <operator>
— binary:
<arg-1> <operator-char> <arg-2>
— keyword:
<arg-1> <operator-string>: <arg-2>
Variables:
| <name>+ |
<name> := <value>.
• dynamically typed
• case sensitive
• everything is an object; even speudo-primitive types inherit
{
| var |
var := 'Hello, world!'.
Transcript show: var.
}
Builtins:
snapshot
show
Classes:
<base> subclass: <name>.
• as a general base, the Object class is provided
• all classes in the language inherit from Object
Methods:
• no explicit function/procedure distinction
^<value> : returns <value>
• calling a method is called "sending a message"
• member variables can only be interacted with with messages;
therefor getters/setters are REQUIRED;
if im not mistaking this is the root of the modern obsession
for privates with getter and setters
Ruby: Ruby:
• object oriented
• scripting language
• not whitespace sensitive, but indenting with 2 spaces is recommended
• a dime a dozen
• whatever you wish to do, there exists a language that surpasses
ruby on that front
• unreadable error messages
• painless to pickup for anyone with any programming experience
Programs:
ruby : interpreter
irb : "Interactive RuBy"; shell; pretty good
gem : package manager
Extensions:
.rb : ruby script
.erb : template with embeded ruby (webdev thing)
Comments:
# single line
=begin multiline comment; note that the closing tag has to be on its own line
=end
• YARD ("Yet Another Ruby Documenter") is the preffered way to have inline documentation
• YARD is exceedingly mediocre (like the rest of the language)
Literals:
true
false
nil
Variables:
<name> = <value> : creates (or reassigns) the variable <name> with the value <value>
name:
@<...> : member variable
@@<...> : static member variable
Logic:
if <bool>
<...>
else
<...>
end
# switch equivalent
case <expression>
(when <value>
<...>)+
else
<...>
end
Loops:
# loop forever
loop <block> # I think this might be a method pretending to be a keyword
# loop if true
while <bool>
<...>
end
# loop if false
until <bool>
<...>
end
# foreach
for <var> in <range>
<...>
end
break
next // == continue
redo
Exceptions:
$ wc ruby_exception.txt # NOTE: it was an undefined variable
28 6692 282103 ruby_exception.txt
# try-catch-finally
begin
<...>
rescue
<...>
[retry]
ensure
<...>
end
Methods:
• yes, methods;
globally defined functions are private members of the Object class;
essentially the ambient class implemented for real
def <name>(<parameter>+)
<...>
end
return : explicit return
name <arg>+ : function call
name(<arg>+) : function call (also)
parameters:
<name> : normal
<name>: : named argument
<name>=<value> : default
*<name> : vararg
• the last eval expression is implicitly return-end
• unortodox amongst languages, ruby method names can include '!', '?' and '=';
.conventionally:
'?' : predicate
'!' : modifies the object
'=' : setter
Classes:
def class <name> (< <parent-class>)
<...>
end
def initialize : constructor method
<class>.new
Visibility:
• everything is implicit public by default
• using a visibility specifier applies to everything below
• C++ like
public
private
protected
Blocks:
{ [|<args>+|] <...> } : braced block syntax; conventionally for single line blocks
do [|<args>+|] <...> end : do block syntax; conventionally for multi line blocks
• lambda like
yield:
• every method can be passed exactly one block after its arguments
• method declaration independent
yield : reference to the block that was passed to the method
Misc:
<var> in <range> : returns whether <var> is within <range>
alias
undef
Prolog: Prolog:
• declarative
• purely logical programming language
gprolog [options] : launches interactive Prolog season
• GNU Prolog
files:
pl : rule file
dots:
• queer semi-colons
• intended to enforce a resemblance to natural language
• every statement must end with a '.' { rules; calls }
literals:
• any ascii string of printable chars starting with
a lower case letter { literal; pizza; dog }
variables:
• any ascii string of printable chars starting with
an upper case letter { literal; pizza; dog }
lists:
[<literal>(, <literal]>+]
{ [a, b, c] }
• can be split with operator|
rules:
• must be defined in a file
[name]([variable | literal](, [variable | literal])+)
[rule] := [rule]+
Recursive_rules:
len([], 0).
len([ _ | F], N) :- len(F, K), N is K+1.
# ---
len(L, N) :- len2(L, 0, N).
len2([], A, A).
len2([ _ | F], A, N) :- A2 is A+1, len2(F, A2, N).
importing:
[[file]]
• import-s the rules from [file]
• [file] shall not contain the file extension
$ cat e.pl
likes(me, vodka).
$ gprolog
GNU Prolog 1.5.0 (64 bits)
Compiled Jul 16 2021, 09:17:34 with gcc
Copyright (C) 1999-2021 Daniel Diaz
| ?- [e].
compiling [...]/e.pl for byte code...
[...]/e.pl compiled, 1 lines read - 345 bytes written, 6 ms
yes
| ?- likes(me, X).
X = vodka
yes
Rust: Rust:
# "Rust Implementation of the Buttplug Sex Toy Control Protocol"
# no, I'm not kidding; this only exists in Rust
https://buttplug.io/
• intended "C killer" (like many others before it)
• trendy and advertised endlessly
○ compiler
• the compile times are horrific
• dynamic linking seems to be broken(?)
• no standard, one compiler
○ from a forum post
"Any program uses multiple copies of the same\
library because the build script does not de-duplicate."
• surely, this must be false news? I hope
○ safety
— its not actually safe:
https://github.com/Speykious/cve-rs
• safety does not mean no leaks
• safety sure as hell does not mean cybersec,
because the cargo infrastructure is begging for
supply chain attacks
• runtime double borrows might as well be a segv-s or double free-s
○ development concerns
• encoding lifetimes is a large development time overhead
— supposedly small edits seems to result in cascading compile errors:
https://loglog.games/blog/leaving-rust-gamedev/
https://yieldcode.blog/post/one-year-of-rust-in-production/
• not to unintentionally compliment agile here,
but in most cases a buggy yet working program is better,
than one we will be able to compile within the next 2 months
• based on its parameters, its the ideal language,
for developing web-servers for moon rockets,
however for realistic tasks it lacks too much flexibility
without compensation
• hot reloading seems to be a mess(?)
• the syntax was designed for the compiler and not for humans
• the learning curve seems steep (and for what benefit?)
• Ada is always an option too
• the language forces a specific trade-off,
bringing its general purposefulness in question
{
resilience
/`\
/ \
/ \
/ .`\
/ rust; \
/ .` \
/ .` \
/_____:_________\
speed maintainability
}
Fish:
• "Friendly Interactive SHell"
• shell designed around interactive usage instead of scripting
• NOT POSIX compliant
— out of the box:
• syntax highlighting
• command completion
• path completion
Forth:
# quick introduction
https://learnxinyminutes.com/forth/
# interactive introduction
https://skilldrick.github.io/easyforth/
• stack oriented
• maps to machine code closely
• good for embedded and easier to implement than C
• forth projects will result in highly specialized,
almost entirely internal, DSL-like code