proj-oot-whyOotDesignIdeas

stuff moved from whyOot

---

An important kind of readability is 'skimmability'. Skimming can mean the ability to quickly, incrementally gaining a partial understanding of code without fully understanding the definitions of the terms that occur in that code; to glance through some code and figure out most of the general structure without understanding the particulars; to guess what 'the gist' of some code is without thinking it through; or to traverse a code path or chain to some desired end without having to understand exactly what the other things along the way mean.

As a means to the end of readability, we pursue various other design criteria. Readability implies that code does what you think it will do, so Oot must minimize 'gotchas' (this criteria is also known as the principal of least surprise or least astonishment). This is related to regularity, because special cases are easily forgotten (causing gotchas); and also to language size and simplicity, because in order to understand source code you must recall and understand the language features it uses, and it's hard to remember a large number of of rarely used features, or to understand complex ones. Concise code is often more readable, in that a small program is easier to hold in one's head (and hence to quickly understand). But skimmability can be opposed to conciseness; if you want to understand the gist of something without reading the definition of every terms it contains, then there must be some redundancy to tell you something about what kind of thing the unknown terms are or what role they serve, information that could already be had if you just read every term's definition.

---

The goal of 'handling implementation details for you' can add complexity. Under what circumstances is it worth adding this sort of thing to the language, rather than leaving it to be built in a framework?

Oot's approach to this tradeoff is:

---

It is inevitable that new programming language constructs will be discovered, and also that there will be application domains for which Oot is almost enough, except for the omission of a few constructs. todo

A language built upon a small core language is also more portable, as only the core really needs to be implemented on the underlying platform, although further optimization can be had by providing platform-optimized versions of other elements of the language.

What's all this you hear from those Lisp guys about a style of programming where first you augment the programming language to suit your domain, then you write a program in your new language? We'd like to do that too.

And what's all this about a small language, a gem-like thing of perfect beauty, in which can be written a (meta-circular) interpreter for itself in only a few pages? Around which a larger, more practical language can be built? That's pretty cool, also.

As a bonus, the effort to find a set of primitives that are good for building a larger language helps us find powerful primitives, and a self-hosting language built on a small core is easier to port. Furthermore, if the language is small enough, and the abstractions are powerful enough to allow it to be implemented concisely, then the language implementation will be readable by ordinary mortals (sans a million optimizations, but we can keep them in a separate module).

todo list meta-programming features

However, we are aware that use of meta-programming features can make source code hard for others to read. Oot provides an (approximate) ladder of meta-programming mechanisms, and encourages the use of the less powerful mechanisms when possible (temperance will also allow us to optimize your code more). The most powerful metaprogramming mechanisms are only for use when all else fails.

todo self-hosting

Oot itself is made of three parts; Oot Core; a language written in Oot Core using metaprogramming; and a large standard library of language-like constructs.

Oot strives to be small, but not minimalistic. For example, 'nand' gates are universal for Boolean functions, but instead Oot bases its Boolean functions on 'and', 'or', and 'not'. Furthermore, we do not try to be minimalistic in the sense that we aren't trying to provide an orthogonal basis set of core primitives. Rather, we strive to be 'multi-paradigm'; when there are multiple paradigms, each with their own characteristic primitives (and when each set of primitives cannot be expressed in terms of another paradigm's primitives except in a clunky or non-local fashion), we try to provide some close to the union of these primitives (or at least all of the 'popular' ones), so that the language can express any of these paradigms.

Used well, metaprogramming can make programs more readable, by making the language more expressive in exactly the ways that are needed for a particular program; the time cost of understanding the black magic is repaid in making it quicker to read the rest of the program. However, a downside of metaprogramming is that it can also be (ab)used to make code that is concise but cryptic.

---

safe (no segfaults, unless of course you call out to an extension/library written in another language)

---

Laziness

Oot has a lazy evaluation strategy; values aren't evaluated until they are needed. This allows for separation between definition of data structures in the abstract, and the control flow used to traverse them. For example, if you are writing a chess-playing program, you can represent the entire tree of possible chess board states in a data structure, and worry about how and how far you traverse this unrealized data structure elsewhere.

A useful special case is infinite data structures; for example, you can have an array which contains all prime numbers; unless you try to traverse this array arbitrarily far, this does not cause your program to hang because thhe unaccessed members of the infinite array are never computed.

Lazy evaluation isn't always efficient, and the programmer can request strictness where desired.

(todo: actually, we're lenient; non-strict, but laziness isn't guaranteed either)

type system

todo

attributes

higher-order polymorphic

supports both parametric polymorphism (generics) and ad-hoc polymorphism

Operator overloading and polymorphism is useful for to allow the names of library functions which perform analogous operations on different types of data to be made more succinct and memorable by allowing the same function name to indicate different (but, by convention, closely related) functions depending on the type of the arguments. For example, '+' can refer to both integer addition and floating point addition depending on the types of its arguments; this is easier to remember than having a separate 'iadd' and 'fadd', and also more succinct (since the need to distingush between fewer function names means that the length of these names can be shorter).

Gradual typing

success typing

can use assertions to override/escape type system

"everything is an interface"

memory management

todo

Safety and error handling

Oot's approach to safety is to provide strong but optional safety constructs, and to provide an API to allow IDEs to determine which parts of code are safe. Two examples of this are its approach to static vs. dynamic typing, and to checked vs. unchecked exceptions.

Oot has gradual typing, meaning that you can write code without type annotations (and Oot will use dynamic typing to execute this code), or you can annotate some or all of your variables (allowing the compiler to typecheck your code, and also to achieve better performance by omitting dynamic typechecks). Similarly, by default Oot doesn't force you to handle or declare every type of exception that could be thrown by your code (that is, we don't have checked exceptions). Instead, Oot provides an API that allows IDEs to query Oot and ask which unhandled exceptions could be thrown by a given piece of code, and which variables are dynamically typed.

For larger projects which need more safety, Oot offers a 'strict' mode which requires all variables to be statically typed, and all exceptions to be handled.

todo

Libraries

Much of the practical utility of a language comes from its libraries. We value great libraries, and both the language and the community process are designed to encourage this.

---

A language is most useful when it is used by many people, so Oot's source code is made available under a permissive open-source license.

---

expression of computation

What is a programming language for? Oot is for two things. First, communication between humans, for example an algorithm description in a textbook. Second, software development.

To be good at the first thing, Oot must allow a writer to clearly communicate exactly what they are trying to say (expressivity), and must minimize the labor required for the reader to understand it (readability). To be good at the second thing, Oot must minimize the amount of labor necessary to design, develop, and maintain correct software.

---

exploration of brain-like computational architectures

Neurons have an individual refractory period between spikes on the order of milliseconds, yet the brain can respond to a stimulus on the order of a hundred milliseconds. This suggests that the number of serial computation steps involved in recognizing a stimulus, deciding what to do, and orchestrating the motor response are on the order of hundreds of steps (Jerome A. Feldman, http://dl.acm.org/citation.cfm?id=42378 ?). This is many fewer serial steps than a typical computer must execute to accomplish a similar task. But the brain has billions of neurons running in paradigm, whereas a typical computer only has a handful of CPUs. This suggests that in order to explore or simulate brain-like computation, a very different programming paradigm is needed, one which relies on massive concurrency in place of long serial executions.

Another seeming property of the brain's computation architecture is that its 'CPUs' are mixed in with its memory. One consequence is NUMA

Yet another is that the brain is robust to errors (both incorrect or unavilable input, and also internal errors) and never 'crashes'. These sort of ideas are related to 'connectionism', a programme to model cognitive processes with interconnected networks of simple units. It is unclear exactly how the brain actually works, but in order to gain intuition in this area, one idea is to try to create programming languages that seem like they may be suited to this sort of thing. Oot is one such attempt.

Possibly the intuitions programmers develop while using such a language will also be of use for writing practical concurrent software on today's computers, a problem which is attracting the attention of programming language designers due to the the inability of Moore's Law to continue to exponentially increase the serial speed of CPUs, while still permitting a rapid increase in the number of CPUs running in parallel.

Another approach to modeling cognitive processess is symbolist A.I., with methods such as the representation of knowledge as a graph of 'nodes' representing various concepts. This is less alien to traditional programming practices than massive concurrency, and hence less in need of language support, yet Oot also intends to serve this application.

Conventional embedded systems with just one or a few processors is not a target application of Oot, however, if there were a machine that you could buy for around $100 with around 64K very slow, cheap, error-prone processors each with somewhere between 128 bytes to 32K of memory, i hope that Oot would be an okay language with which to program that machine. In fact, Oot seeks to be a general-purpose glue language in another sense; Oot seeks to be an okay language for programs that run on systems with a MIXTURE of: traditional systems (one or a few high-speed CPUs with a large shared memory); GPUs (massively SIMD); massively parallel MIMD systems (many slow CPUs each with a little bit of attached memory).

---

prototyping

Both client-side application programs (web, desktop, mobile) and server-side backends.

Oot is suitable for writing programs which respond interactively to the user via a variety of UI paradigms. The implementation conveniently runs on various desktop, server, and mobile platforms, and the data model, binding facilities, event system, support for reactive functional programming, component architecture system, object oriented and metaprogramming facilities attenuate the boilerplate that traditionally clutters the connection between programs and UI frameworks.

Oot is designed so that a prototype can be extended (rather than rewritten), until such time as either it needs to be rearchitected, or rewritten in a more efficient language.

---

we want Oot to be simple, but complexity in the form of very general/abstract/powerful operators is better than complexity in the form of many special cases. For example, Python's 'and' and 'or' are short-circuiting and also return the last argument they evaluate; this allows them to be used for things such as "(propertyThatXMustHave(x) and x) or default". This is complex, but we prefer this type of complexity to the complexity of having a large number of fundamental constructs.

In addition, we hate having many things in Oot Core much more than we hate having many things in Oot. That is to say, adding an additional construct to Oot via metaprogramming is not nearly as disliked as adding an addition to Oot by extending Oot Core.

---

in fact, we favor general primitive abstractions over simple ones; eg we favor 'switch' over 'if'; this fits our (subjective) criterion of 'power', because the expressivity is worth the complexity here

yet, we still try to preserve 'if's in translations to the core language and to bytecode, so that we can use platform-dependent optimizations for it. This goes with our design goal of preserving intent.

---

The five general abstract design goals listed in whyOot can be mapped to the Wu Xing five elements:

Oot prioritizes them in the order above. However, readability is emphasized because although in theory i would not greatly restrict metaprogrammability or expressiveness for a gain in readability, in practice i feel that most other contemporary programming languages don't think enough about readability, so by comparison to the mainstream, readability will appear to be a high priority in Oot.

---

i guess really we may as well list 7, in declining order of priority for oot:

simplicity, metaprogrammability, expressiveness, readability, conciseness, safety, performance

---

CGI:

https://www.devever.net/~hl/mildlydynamic

    13
    dvogel edited 26 hours ago | link | flag | 

As mentioned in the article, there were other Apache modules providing similar functionality, such as mod_python. There were also CGI approaches to the same template-forward bent, such as Mason (which was perl). If there was anyone saying “why support another since we already have PHP?” it was admins on shared hosting services. Each additional module was yet another security threat vector and a customer service training.

    5
    ewintr 13 hours ago | link | flag | 

I was at a talk given by Rasmus Lerdorf (creator of PHP) once and he claimed it was because the PHP implementation was the most basic, limited version possible and it therefore it was very simple to isolate different users from each other. This made PHP very popular with cheap shared hosters. Whereas the Perl implementation was much more thorough and hooked (not sure what the correct terms are) into the whole of Apache and therefore it needed a dedicated server. Much more expensive.

    ~
    hlandau 11 hours ago | link | flag | 

Yeah. Even though mod_php is a single module loaded into a single Apache instance, it was designed with some sandboxing options like safe_mode. Or you could use PHP CGI and isolate things even better (running as the user’s UID).

Other language hosting modules for Apache like mod_perl didn’t offer the same semantics. I also recall mod_perl being pretty oriented towards having access to the web server’s configuration file to set it up. People did use Perl before the rise of PHP, but most often via CGI (remember iKonboard?)

 hoistbypetard 5 hours ago | link | flag |

mod_perl was more oriented toward exposing the apache extension API so that you could build apache modules in perl, as I remember it. It got used to write some cool web applications (slashcode springs to mind) that’d have been hard to write (at that scale) any other way at the time. But mod_php was a very different beast, just aiming to be a quick way to get PHP to work well without the overhead of CGI.

I agree with the article… there’s nothing now (other than PHP, which I still use now for the kind of pages you mention, the same way I did in the early ‘00s) that’s nearly as low-friction as PHP was back then to just add a couple of dynamic elements to your static pages.

~ gcupc 5 hours ago

link flag

Yeah, I was at a small web hosting company in the late ’90s, early 2000s, and we used PHP CGI with our shared hosting.

pm 25 hours ago

link flag
    It’s not like you couldn’t build a similar system based on Python or Ruby or JS.

Not quite. The article touches this, although not explicitly, you have to read a bit between the lines.

PHP allowed for easy jump in and out static and dynamic context like no other alternative. It still does this better than anything else. This was in the core of the language no need to install third party libraries. It also included a MySQL? client library in its core with work out if the box. Essentially, it shipped with everything necessary in the typical setup. No need to fiddle with server set up.

The language was also arguably more approachable for beginners than perl with a multitude of simple data structures easily accessible through the infamous array() constructor. It also retained familiarity for C programmers, which were a big audience back then. While python for example, didn’t.

One thing I don’t agree with is the simplicity nor the deployment model. It’s only simple in the context of the old shared hosting reality. If you include setting up the server yourself like we do nowadays, it is actually more cumbersome than a language that just allows you to fire up a socket listening on port 80 and serve text responses.

It.s.how it was marketed and packages that made all the difference.

    9
    hobbified 23 hours ago | link | flag | 

Yes, but it was “better” in the sense of “making it easy to do things that are ultimately a lousy idea”. It’s a bit better now, but I used it back then and I remember what it was like.

Convenience feature: register_globals was on by default. No thinking about nasty arrays, your query params are just variables. Too bad it let anyone destroy the security of all but the most defensively coded apps using nothing more than the address bar.

Convenience feature: MySQL? client out of the box. Arguably the biggest contributor to MySQL’s? success. Too bad it was a clumsy direct port of the C API that made it far easier to write insecure code than secure. A halfway decent DB layer came much, much later.

Convenience feature: fopen makes URLs look just like files. Free DoS? amplification!

Convenience feature: “template-forward”, aka “my pages are full of business logic, my functions are full of echo, and if I move anything around all the HTML breaks”. Well, I guess you weren’t going to be doing much refactoring in the first place but now you’ve got another reason not to.

The deployment story was the thing back then. The idea that you signed up with your provider, you FTP’d a couple files to the server, and… look ma, I’m on the internet! No configuration, no restarting, no addr.sin_port = htons(80). It was the “serverless” of its day.

    18
    ubernostrum 22 hours ago | link | flag | 
    Yes, but it was “better” in the sense of “making it easy to do things that are ultimately a lousy idea”. It’s a bit better now, but I used it back then and I remember what it was like.

It was better, in the sense of democratizing web development. I wouldn’t be here, a couple decades later, if not for PHP making it easy when I was starting out. The fact that we can critique what beginners produced with it, or the lack of grand unified design behind it, does not diminish that fact. PHP was the Geocities of dynamic web apps, and the fact that people now recognize how important and influential Geocities was in making “play around with building a web site” easy should naturally lead into recognizing how important and influential PHP was in making “play around with building a dynamic web app” easy.

    ~
    hlandau 11 hours ago | link | flag | 

Author here, I couldn’t have put it better. “PHP was the Geocities of dynamic web apps” — this is a brilliant way to put it. In fact I’m now peeved I didn’t think of putting it like this in the article. I’m stealing this phrase for future use. :)

    ~
    hobbified 15 hours ago | link | flag | 
            But I am really not sure you can do anything about bad programmers. No matter how much safety you put in place. […] Can you really blame a language for people doing things like throwing a string in an SQL query without escaping it?
        Since you mention magic quotes … there’s a terrible feature that could have been a good feature! There are systems that make good use of types and knowledge of the target language to do auto-escaping with reasonable usability and static guarantees, where just dropping the thing into the query does the secure thing 98% of the time and throws an “I couldn’t figure this out, please hint me or use a lower-level function” compile error the other 2%. PHP could have given developers that. Instead it gave developers an automatic data destroyer masquerading as a security feature, again, enabled by default. That’s the kind of thing that pisses me off.

~ ubernostrum 22 hours ago

link flag
    I’m still wondering why only PHP became available as an easy in-process scripting language. It’s not like you couldn’t build a similar system based on Python or Ruby or JS. Maybe it was the ubiquity of Apache, and the Apache developers not wanting to add another interpreter when “we already have PHP?”

I am someone who is, these days, primarily known for doing Python stuff. But back in the early 2000s I did everything I could in PHP and only dabbled in Perl a bit because I had some regular business from clients who were using it.

And I can say beyond doubt that PHP won, in that era, because of the ease it offered. Ease of writing — just mix little bits of logic in your HTML! — and ease of deployment via mod_php, which for the developer was far easier than messing around with CGI or CGI-ish-but-resident things people were messing with back then. There are other commenters in this thread who disagree because they don’t like the results that came of making things so easy (especially for beginning programmers who didn’t yet know “the right way” to organize code, etc.) or don’t like the way PHP sort of organically grew from its roots as one guy’s pile of helper scripts, but none of that invalidates the ease PHP offered back then or the eagerness of many people, myself included, to enjoy that easiness.

hobbified 25 hours ago

link flag

The other options did exist. There were mod_perl and mod_python for in-process (JS wasn’t really a sensible server-side option at the time we’re talking about), mod_fastcgi and mod_lisp for better-than-CGI out-of-process (akin to uwsgi today), and various specialized mod_whatevers (like virgule) used by individual projects or companies. mod_perl probably ran a sizeable fraction of the commercial web at one point. But they didn’t take PHP’s niche for various reasons, but largely because they weren’t trying to.

~ jmtd 25 minutes ago

link flag
    It’s not like you couldn’t build a similar system based on Python or Ruby or JS.

There’s ERuby which was exactly this. But by then PHP was entrenched.

I did a side project recently in ERuby and it was a pleasure to return to it after >10 years away.

mordae 21 hours ago

link flag

I worked at at shared hosting at the time of the PHP boom. It all boiled down to the safe mode. No other popular competitor (Perl / Python) had it.

Looking back, it would have been fairly cheap to create a decent language for the back-end development that would have worked way better. PHP language developers were notoriously inept at the time. Everyone competent was busy using C, Java, Python and/or sneering at the PHP crowd, though.

...

The canonical way to serve HTML from Scheme is to use SXML (XML as s-expressions), which is not vulnerable to (most) injection problems and also allows you to effortlessly transfer between code and data (by using Scheme’s quasiquote) in a way that can’t leave you with mismatched closing tags as an added benefit!

...

hlandau edited 5 hours ago

link flag

Indeed, you’re preaching to the choir in my case.

Though the article I wrote is in part motivated by the fun I’ve had with PHP in the “hackish state” in the past, I’ve honestly come to the view that templating is one thing PHP should (ironically, given its origins) never be used for. The reason for this is that the lack of autoescaping makes its use as a templating language unconscionable from a security perspective nowadays, in my view.

Fundamentally one of the reasons the software industry has so many security issues is its failure to practice problem class elimination. The aviation industry has been good at practicing problem class elimination: when an accident happens, we try to figure out how to prevent that entire class of accidents from happening again. Terrain collisions keep happening, so someone invented GPWS, etc.

We have comparable things now with memory-safe languages, prepared statements, and autoescaping, etc. Yet embarrassingly SQL injection, XSS, etc. are still an absurdly common vulnerabilities.

I’ve actually come to the conclusion that generating (X)HTML using string templating systems is fundamentally a hack and always has been. The rejection of XHTML by web developers and the notion of having to generate well-formed XML as being unreasonably burdensome, as represented by the HTML5 movement, was very telling. In any other case this wouldn’t be taken seriously — if someone claimed that having to write (or generate) grammatically correct C code is unreasonably burdensome, we’d be laughing.

This is as opposed to serializing an AST, as in the case of SXML or DOM serialization — an approach which makes outputting malformed XML literally impossible. Problem class elimination. XSS is eliminated but not even by autoescaping — it would be a mistake to call it autoescaping, it’s simply correct serialization of a string as a string in the target format.

But string templating systems with autoescaping tacked on remain dominant. Autoescaping isn’t perfect either as it isn’t context-sensitive and just assumes escaping a given set of characters will suffice. I suspect the reason string templating for HTML remains dominant is because of how cumbersome (and historically, less performant) AST-based templating languages have historically been (see XSLT).

We have seen some progress with the rise of JSX, though. But you’re correct, there really is no nicer environment for writing and generating XML than Scheme. I use it as a typesetting environment for some yet-unpublished projects of mine, with an executable Scheme program that generates SXML transformable ultimately to XHTML or TeX?. Aside from how useful quasiquoting is in general, I like to define terminology for technical writing as Scheme defines, which has the interesting attribute that references to terms defined earlier in a document (which should be turned into hyperlinks, etc.) are actually checked at build time:

(dt bipipe "bipipe" "A combination of two "unipipes", one in each direction.")

( ... (p "A "bipipe" is realized as two realized "unipipes"."))

Now that I’ve written this comment, I guess this does raise the question of why not apply this to a PHP-like application, where you write websites in SXML for mildly dynamic applications. Honestly, that’s a really nice idea, and would lead to the levels of creativity enabled both by Scheme and by a PHP-style hackish environment (while being actually conscionable to use, unlike PHP-as-a-templating-language). I might seriously look into that…

...

Amen, brother! https://www.more-magic.net/posts/structurally-fixing-injection-bugs.html

~ basus 59 minutes ago

link flag

I recommend you look at Scribble or Pollen. Neither of them are really geared towards websites, which makes them less than dynamic than what you’d want for some things, but they do let you write XML pretty easily, and make it easy to layer on abstractions and computations. I’m working on a system called Colophon to try and make Pollen friendlier for websites.

https://docs.racket-lang.org/scribble/ https://docs.racket-lang.org/pollen/ https://colophon.basus.me/

ngrilly 1 hour ago

link flag

redbean, a web server shipped as a single binary executable, including Lua and SQLite, seems to be a perfect fit: https://redbean.dev/

~ adi_onl edited 6 hours ago

link flag

This exact gap is what I belive https://mkws.sh and https://adi.onl/pp.html fills. Generate your static site but go dynamic if you prefer via pp and CGI. pp is like a mini PHP.

~ carlmjohnson 5 hours ago

link flag

A lot of the example usecases in the article can be handled by client side JavaScript?. The things that client side JS can’t do are remote persistence: database calls and file uploads. There are number of things like CloudFlare? workers, Netlify functions, etc. that tackle making it easy to run JS on the server side, but old PHP came with a database API and file storage (that was totally insecure if anyone uploads a PHP file, lol), so to really be as good as old PHP was, they should have that built-in. Also PHP had sessions as a language concept. It would be interesting to think about how you could create a platform today that has the best both worlds.

---