The idea of having the language force the programmer to check for all cases of an algebraic type had not been invented at the time. It's hard to blame them for the problem. I mean, yeah, they should have arrived at that solution, but it took a few more years of language research to hit upon it.
No doubt the videography is skilled, and well-composed, however I can't help that I get a profound sadness from their videos. It's like an odd dystopia mishmash of characters from a Wes Anderson film and Stepford Wives. Possibly not the target audience here though the music is pleasant.
Jokes aside the compiler-checked acknowledgements are kind of clever. The example in the docs is deliberately confrontational, but there's a kernel of a neat idea there. Imagine needing to write:
// I acknowledge that the internal structure of this data is subject to change without notice
x = foo.state
Or perhaps:
// I acknowledge that this data is a complicated graph of pointers and is easy to break in subtle ways
foo.xyz[0].bar[1] = &foo.asdf[3]
Or perhaps:
// I acknowledge that this data is heavily cached and I need to call rebuild() before changes take effect
x.something = "Hello"
x.rebuild()
Wouldn't these use-cases be better solved by public accessor methods though? I really liked the idea at first blush too, but the more I thought about it, the more I came around to the fact that it's ultimately the class maintainer's responsibility to ensure that the directives in those comments are followed safely. In cases like your first example, it's dangerous not just for the x reference of foo.state, but also any other concurrent references to the object, to perform modifications at all.
Maybe a read-only version, so you can grep state at a point in time?
> it's ultimately the class maintainer's responsibility
It's ultimately the responsibility of the programmer who's building a tool/product/etc, because everything is ultimately their responsibility.
As programmers we ~always have the nuclear option available to us of forking the code and implementing all the necessary accessors ourselves, but sometimes that's really just a bunch of pointless busywork and there's no reason we should have to put up with it in those cases.
This can be a contentious subject because there's a lot of nuance and the right answer is often context-dependent. But I personally think that the Java style of "we must absolutely protect the library user from themselves and childproof everything" is waaaay too far in the wrong direction.
I would much rather that a language have mechanisms to clearly communicate "don't touch this unless you have a good reason, but if you need to here's how" rather than saying in effect "you, the person using this library, are dumb and need to be prevented from messing with the library maintainer's perfect vision".
And so I think the "required acknowledgement" thing has the glimmer of a really neat innovation in it (although if I were to copy the idea for a language of my own I would probably make it obligatory, such that every struct allows breakglass access to private fields with a default acknowledgement, and all the library author can do is change the acknowledgement text).
> This can be a contentious subject because there's a lot of nuance and the right answer is often context-dependent. But I personally think that the Java style of "we must absolutely protect the library user from themselves and childproof everything" is waaaay too far in the wrong direction.
I tend to agree with this sentiment; especially when the 'child-proofing' means to do the thing right with the library/api in question is more work than just rolling your own.
> I would much rather that a language have mechanisms to clearly communicate "don't touch this unless you have a good reason, but if you need to here's how" rather than saying in effect "you, the person using this library, are dumb and need to be prevented from messing with the library maintainer's perfect vision".
In some cases I've seen/used the term 'Unsafe'.
C# language-ext uses this for some methods that can return null (as opposed to un-Unsafe-suffixed methods, which will throw on null). I've also used it for some 'low level' methods in libraries, where it is a case of 'you need to read the docs to know how to not turn it into a footgun'.
The problem of course is that in my main language (C#), the word 'unsafe' has other connotations (i.e. pointer arithmetic.)
When I first submitted my PR, there were numerous developers who did not like the term 'Unsafe' for the reasons mentioned above. I asked what it should have been called in that context instead, and floated 'Yolo' as a tongue-in-cheek suggestion.
(That being said, If there -was- a word to use to denote 'with great power comes with great responsibility' people would suggest, I'd love to hear it.)
; We had fun deciding on these.
ReadEnvStr $1 IPromiseNotToComplainWhenPortableAppsDontWorkRightInProgramFiles
${If} $1 S== "I understand that this may not work and that I can not ask for help with any of my apps when operating in this fashion."
${DebugMsg} "You're making me sad by the way you voided your warranty, running in Program Files."
${Else}
; This string doesn't let on about the disable switch (by design)
MessageBox MB_OK|MB_ICONSTOP `$(LauncherProgramFiles)`
Quit
${EndIf}
I’ve done one or two other extremely verbose environment variable names and values or function names, but this is the only one that’s springing to mind right now.
Not sure quite why we decided to allow it at all there, but I suspect I just had too much fun with it. Not sure why it ended up spelled “can not” instead of “cannot”, either.
(If you’re wondering about ${…} on If/Else/EndIf, that’s because NSIS is basically an assembly language and has only jumps for control flow; LogicLib.nsh provides nice control flow constructs via defines and macros, abstracting the automatic creation of labels and the right jumps so that that `${If} $1 S== "…"` compiles to `StrCmpS $1 "…" 0 ‹auto-else-label›`, `${Else}` to `Goto ‹auto-endif-label›; ‹auto-else-label›:`, and ${EndIf} to `‹auto-endif-label›:`.)
At first I was confused why do we need another language. But then I kept reading. Will I program in Ok? Probably not. But did I enjoy reading the readme? Definitely. It just kept getting better and better.
The idea of logical operators not applying to variables seemed awesome. Though I do hate the lack of ==.
I think it's short-sighted. Separation of concerns is not a rule to be applied blindly: it requires understanding that separation also increases the complexity of the system. Deciding where to split, what abstractions to create, is not easy. Naming is hard, and yet here we are required to come up with names for these functions that could perfectly be inlined without any negative consequences.
I get that long switch cases get tedious, but the same applies to any piece of code, including a function. I don't think this is a solution, but rather, an annoyance.
> Separation of concerns is not a rule to be applied blindly
A switch statement that only calls functions is almost like a state machine transition table (granted not a very good one).
Organizing conditional logic into a state machine is an excellent separation of concerns. The state machine becomes essentially an abstract model of your system that says what to do and when to do it, but not the low level details of how to do it.
The functions that define how to do it are the refinement of the model. You then have something thats directly mappable to TLA+, which you can use to model check your system.
Thanks for the vote of confidence, but maybe it would be more relevant to ask whether I could write better software in this language than I could in other languages (taking as given good organization and model checking). I agree with your paraphrase of Lamport as far as it goes -- the language will not save you if you don't have a clear model of the problem. But languages are more or less suited to mapping from algorithms to code, and (relatedly) organization of that code.
I made it to the comparison operators before convincing myself that it really was a joke. The buildup on this is brilliant -- the crossover between clueless arrogance and absurdity is very subtle.
Same spot for me. Up to that point, I was 50/50 on whether this was taking itself seriously or not. Then the "simplification" of >= for everything made me smile. OK?
> For extenuating circumstances, you can define a privacy acknowledgement with the pack keyword, allowing external code to access a [notaclass's] fields if they include the acknowledgement in a comment, preceded by 'I acknowledge that'
Hmm. This has some interesting bits even if it's ultimately a joke. I'm feeling some "alternate universe lua" vibes with ideas like using switch cases for everything.
Also, I really REALLY like how nulls are NO!s instead of nils or something similar. Getting flashbacks to a beloved TMBG album (https://www.youtube.com/watch?v=hsoFghzIQ0s)
94 comments
[ 2.9 ms ] story [ 62.0 ms ] threads/Tony Hoare/Robert Griesemer, Rob Pike, and Ken Thompson/
> The idea of having the language force the programmer to check for all cases of an algebraic type had not been invented at the time.
Brilliant
(and sometimes the 36-bit machines would even limit identifiers to 6 6-bit characters)
https://aplwiki.com/wiki/OK
It is a joke language that is equivalent to brainfuck, and doesn't contain the word "monkey".
https://www.dangermouse.net/esoteric/ook.html
There's excellent videography and creative design in almost all of them.
Maybe a read-only version, so you can grep state at a point in time?
It's ultimately the responsibility of the programmer who's building a tool/product/etc, because everything is ultimately their responsibility.
As programmers we ~always have the nuclear option available to us of forking the code and implementing all the necessary accessors ourselves, but sometimes that's really just a bunch of pointless busywork and there's no reason we should have to put up with it in those cases.
This can be a contentious subject because there's a lot of nuance and the right answer is often context-dependent. But I personally think that the Java style of "we must absolutely protect the library user from themselves and childproof everything" is waaaay too far in the wrong direction.
I would much rather that a language have mechanisms to clearly communicate "don't touch this unless you have a good reason, but if you need to here's how" rather than saying in effect "you, the person using this library, are dumb and need to be prevented from messing with the library maintainer's perfect vision".
And so I think the "required acknowledgement" thing has the glimmer of a really neat innovation in it (although if I were to copy the idea for a language of my own I would probably make it obligatory, such that every struct allows breakglass access to private fields with a default acknowledgement, and all the library author can do is change the acknowledgement text).
I tend to agree with this sentiment; especially when the 'child-proofing' means to do the thing right with the library/api in question is more work than just rolling your own.
> I would much rather that a language have mechanisms to clearly communicate "don't touch this unless you have a good reason, but if you need to here's how" rather than saying in effect "you, the person using this library, are dumb and need to be prevented from messing with the library maintainer's perfect vision".
In some cases I've seen/used the term 'Unsafe'.
C# language-ext uses this for some methods that can return null (as opposed to un-Unsafe-suffixed methods, which will throw on null). I've also used it for some 'low level' methods in libraries, where it is a case of 'you need to read the docs to know how to not turn it into a footgun'.
The problem of course is that in my main language (C#), the word 'unsafe' has other connotations (i.e. pointer arithmetic.)
When I first submitted my PR, there were numerous developers who did not like the term 'Unsafe' for the reasons mentioned above. I asked what it should have been called in that context instead, and floated 'Yolo' as a tongue-in-cheek suggestion.
(That being said, If there -was- a word to use to denote 'with great power comes with great responsibility' people would suggest, I'd love to hear it.)
Not sure quite why we decided to allow it at all there, but I suspect I just had too much fun with it. Not sure why it ended up spelled “can not” instead of “cannot”, either.
(If you’re wondering about ${…} on If/Else/EndIf, that’s because NSIS is basically an assembly language and has only jumps for control flow; LogicLib.nsh provides nice control flow constructs via defines and macros, abstracting the automatic creation of labels and the right jumps so that that `${If} $1 S== "…"` compiles to `StrCmpS $1 "…" 0 ‹auto-else-label›`, `${Else}` to `Goto ‹auto-endif-label›; ‹auto-else-label›:`, and ${EndIf} to `‹auto-endif-label›:`.)
A world with golang and no nil values would be a dream.
The idea of logical operators not applying to variables seemed awesome. Though I do hate the lack of ==.
I get that long switch cases get tedious, but the same applies to any piece of code, including a function. I don't think this is a solution, but rather, an annoyance.
A switch statement that only calls functions is almost like a state machine transition table (granted not a very good one).
Organizing conditional logic into a state machine is an excellent separation of concerns. The state machine becomes essentially an abstract model of your system that says what to do and when to do it, but not the low level details of how to do it.
The functions that define how to do it are the refinement of the model. You then have something thats directly mappable to TLA+, which you can use to model check your system.
I agree with Leslie Lamport - the problem is not the programming language, it’s the way you think about systems.
You mean like in the language this is a parody of?
Not going to lie, I want this in Java yesterday.
https://stackoverflow.com/questions/1196192/how-to-read-the-...
Also, I really REALLY like how nulls are NO!s instead of nils or something similar. Getting flashbacks to a beloved TMBG album (https://www.youtube.com/watch?v=hsoFghzIQ0s)