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: +------+----------------------------+ | 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: • a Turing complete programming language which is impractical to use for common tasks, due to a lack of features Typing: — weak/strong: • the difficulty of converting between types in a programming language is a spectrum ranging from strong typing to weak typingweak 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 { // Reasonably accurate placing of languages in a matrix, representing the typing spectrum 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 │ ├── Declarative │ ├── Functional │ │ │ └── Logical │ ├── Imperative │ ├── Procedural │ │ │ └── Object-Oriented │ ├── Event-Driven │ │ ├── Concurrent │ │ └── Stack-Oriented /* Whats very important to understand regarding paradigms, * is that you are not supposed to classify any language into a single category. * Each of these terms is used to describe a general feature set. * For example, C++ is both procedural and object-oriented, * early Javascript was event-driven and object-oriented, * and Go is procedural and concurrent. * These features need-not to be implemented by the language either, * many object-oriented libraries follow the functional paradigm, * the inversion of control pattern is for creating event-driven environments * and goruotines can be seamlessly implemented in C. * "Declarative" and "imperative" are the odd ones here, * because they define sets of similar paradigms. */ } 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 // ?!; corrpution, revert from history — 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 is usually defined as an arbitrary long combination of the following characters: ' ' '\n' // new line '\t' // tab '\v' // vertical tab 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: • 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:"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: • 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: • 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: • 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:"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: • 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: • 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>. // create new child class of <base> with 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: • 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: • 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 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: // ?!; maybe move"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