Even in monospace fonts, there's one character which is not constant width. Not only is its width different from other characters', it also varies depending on where this character is placed.
That makes this character super annoying to work with.
Can you guess which character it is?
Space . , / ?
umm... last time I typed code, space . , / ? were all constant width, and same width as A
Have to test it
@Wolf480pl using tap wen coding is good if you have people with bad sight in your team
that's what I've heard too.
If I had people with bad sight on my team and they said they need tabs, I'd go for tabs (except if it was big existing codebase, then I'd think twice).
But I don't think it's as much of an end-of-debate argument as some people make it sound.
It's tradeoffs all the way down
@Wolf480pl i use tabs but i dont think it really matters if the code works
Tab is 2, 4 or 8 spaces :3
@Wolf480pl I know it's a really unpopular opinion, but we should finally start storing code as binaries rather than text (ast + metadata + possibly higher level constructs), that's not the only seemingly "trivial", but actually constraining and complicating dev tools, thing it could solve
@polar wouldn't that mean you need language-specific editor to even read the code?
I wouldn't want that to happen, for the same reason that I prefer text-based network protocols over binary ones. Or text-based config files over binary ones.
@polar for some reason, it seems to me like your idea would fit well with Smalltalk and its eternally persistent state... which may be tempting on the surface, but I feel there's just too many things that could go wrong with it, and it'd be hard to debug.
And why would it be hard to debug?
Because you can't just use simple tools like a text editor or netcat to see what's going on. You need data-format-specific tools, and those tools are going to be complex, and going to have the same bugs that the code you're trying to debug has.
@Wolf480pl I like some smalltalk ideas :p
And you can't really netcat much on the internet anymore anyway, at least ssl client around that...
@polar ok, but when you have a working `openssl s_client`, you can use it to interact with all protocols that go over TLS, including those not invented yet, as long as they're text-based.
Similarly, if there was a generic repl for interactively typing and displaying some binary serialization format (BSON/JSONB? protobuf?) it'd be equally good.
The point is, being able to see and manipulate whatever is between the application-specific code and the generic layer below it.
@Wolf480pl you kind of provided an answer: you can have textual interface into the data in the file same as text protobufs. Actually it'd be much more natural to provide multiple "views" onto code/data, maybe even cross-language layers. It's storing the result as textual [protobuf] what I'm objecting to: for example, there's no good yaml and textpb editing libraries
TBH there's a lot of reasons it probably won't work (bug/versioning/complexity/UI complexity), but sb try sth pls
@polar ok, but that interface need to be independent of the language itself.
And as we know, each language has a different AST structure.
Maybe you could use some generic serialization format, but I don't think it'd gain you much...
Btw. I don't know enough details about how protobuf works, to be able to tell if what I said about it would be actually possible.
@Wolf480pl it does not need to cover the whole thing, and as long as you have a common unifying semantics, you can do that safely
At some not-so-far-into-the-future point we'll start to occasionally converse with computers about source code and program semantics rather than edit (more or less literally), imagine hours wasted and frustration due to having to parse and format for storage and store meta separately, rather that standardize meta (again, we'd probably get it wrong anyway,but:p)
@polar I'm not sure what separately-stored metadata you're talking about...
@Wolf480pl at the very least state of the conversation
@polar but nobody is storing that...
Why would you want to store it together with the code?
Why would you want the intermediate state of you being in the middle of modifying some function to be stored together with the code that everybody else works on?
@Wolf480pl you don't need to store it if you don't have formatting (instead you might want to store some new higher level transform?)
And we actually are storing editor and non-essential tool meta with code - see modelines, licenses and linter annotations
Either way, I've probably made you tired with this vague unresearched idea, sorry and thanks for replying!
@polar no, you haven't made me tired yet, and I've enjoyed the discussion so far.
As for linter annotations, etc - yes, we are storing it with the code. Exactly how you wanted them to be stored :)
And I think they way we're storing them (linter annotations, warning exemptions, docstrings, etc) with the code is good. I don't think changing the storage format would make them stored closer to the code than they're now.
Earlier you mentioned metadata that we *currently* store separately, but *should* be stored with the code.
If that was the case, that'd be a strong argument. But I can't think of any metadata like this... :/
@Wolf480pl I might have been confusing, but essentially: formatting data should not be needed and therefore not stored, BUT more of similar things will need to be stored if you develop AI powered UIs on top of text, and that'll be a mess or a limiting factor.
Instead I'd want to see new things stored, like safe macro-like constructs , that could maybe even become aware of things like protocol versioning with the tooling helping with the added complexity... Without crashing on parsing
>AI powered UIs
I wouldn't want that kind of UI.
I want my UI to be predictable.
I want to know exactly what it will do when I poke it in a particular way, and I want it to do the same thing when I poke it the same way.
I want my UI to be stupid.
@polar As for formatting data - good point.
So ideally, we'd store an AST in a canonical format, and then have some user-specific formatting configuration, and transform the AST into a readable format with that formatting configuration, and then back into canonical AST once the user is done editing.
But you never know whether the transformation is correct. There can always be bugs.
So you want to see the diff your changes made in the AST.
So you need a meaningful way to display AST diffs. And it should be as simple as possible, and shouldn't use the formatter, or you'll run into the same bugs that you're trying to detect.
@Wolf480pl there can be bugs, but even without exposing mutation as service, you can argue it'll be easier if you don't make the ast too low level
The end goal would be exactly not to have to verify diffs on AST as we understand it now, instead operate on a sufficiently higher but semantically sound level. Engineering effort probably seriously limiting how high you can get though
@polar I wouldn't feel comfortable unless I'm verifying diffs on the same data that is being stored in version control.
I'm fine not verifying AST inside compiler, or the generated assembly or binaries, because they're transient, and there's little chance of bugs there being able to propagate into other things unnoticed.
But bugs in tools whose output gets put into every commit in version control would cause effects that could propagate throughout codebase for years.
My intuition is that I want to be able to see all persistent state. And delete all transient state at any time, and rebuild it from the persistent state that I've verified with my eyes.
Of course, there's Ken Thompson's Trusting Trust, bugs in editors, bugs in hexdump, etc.
But the thinner the layer between our eyes and the persistent state, the more reproducible and observable our computing is.
@Wolf480pl I feel there're some specific tasks in which we fail awfully and more powerful UIs could help, like possibly (still de facto unsolved) UI programming, or protocol and (possibly recursive) data mapping (think translations between API layers, which often is "mostly copy by convention, except this and that", but adding one "that" sometimes means seriously reformatting your declarative writeup to date even when coded in a lazy declarative language); possibly anytime you care about specification more than implementation and implementation is "simple enough", but probably not only
@polar you know what's the name of specification precise enough that a program can be automatically generated from it?
@Wolf480pl Point partially taken, because a) sometimes the task does really not require more precision (and it'd be nice to add it only when it begins) b) code is currently very much occupied with character placement rather than execution instructions ;)
Actually, this ties slightly into sth else that I'm occasionally thinking about - why do code generators (which you could again argue overlap with alternative / high-level representations and better UIs) are so underused in practice? Mostly the same problem of working on multiple precision and abstraction levels in a sane way, and find an ecosystem that supports this natively and usably
@Wolf480pl which can contain, among other things, autoformatter settings, essential not to make a tool obligatory when storing text
@polar but those things are not specific to the particular file you're editing, are they?
AFAIK they're project-wide, and are supposed to be uniformly applied to all the code in a project.
@Wolf480pl and that gets you back to tabs in code as an accessibility and UI/UX issue - it's not even project specific, it's client leaking abstraction into abstract, and the easiest things we solve with binary storage 🤔
@Wolf480pl also, compilation units make some sense, but why stick to files as grouping mechanism (see smalltalk again, but also eg Joe Armstrong's ideas for Erlang searchable function directory, and generally operating on semantically-meaningful units rather than storage artifact)
@polar take a look at Java, with its one class per file. It makes you operate on semantically significant units, namely: classes.
you operate on semantically significant units, namely: modules.
That they map 1:1 to files doesn't make operating on logical units any harder. I'd even argue it makes it easier.
@Wolf480pl those are partially there, i still have useless things like a fixed method ordering and filesystem-dependent module hierarchy. And then aspects and metaclasses break this abstraction anyway by not allowing you to interpret it on its own
@polar you say that filesystem-dependent module hierarchy is useless. But would you not make a tree-like hierarchy for the modules anyway, even if there was no filesystem?
You say that method ordering is useless. It certainly is for the compiler. But programmers put meaning into method ordering. It can be an information to other programmers, similar to variable names and comments.
Unfortunately, I'm not familiar with aspects and metaclasses enough to tell how they fit in that picture.
Anyway, I think source code is actually mostly a way for humans to communicate *precisely* with each other. That it can be understood by a computer is only a side-effect of it being precise.
@Wolf480pl Tree-like hierarchy is actually occasionally objected to (see Erlang's creator who thinks flat searchable space would be better with proper way to reference individual functions, which in the context of that language makes a lot sense; but also module aliasing (DAGs), pulling in multiple versions (extra dimension on the tree), or module interfaces and functors (a tree with views into other nodes and node- or tree-parametrized tree nodes/higher level trees?)), and method ordering can be useful but as you note is for users, not for computer, so should be presentation layer - I can prefer to list them alphabetically or grouped by common argument, or decide to embed into interactive doc, and with binary store they could have identity and therefore reference same piece of code between all those views
Anyway, would be great to be as precise as need to be, and not more ;)
@polar well, you can decide to order methods alphabetically, but how do you communicate that to other developers?
Also, someone may put two methods next to each other if they're closely connected semantically, but how do they communicate that to other developers?
Ultimately, you need to store that information with the source code, the same way you store comments, docstrings, etc.
@polar I think binary storage itself doesn't solve that much in this case...
You'd think it'd help you avoid parsing, but you can't just memcpy your internal pointer-based data structures to disk and back, or you're risking really strange bugs, vulnerabilities, and incompatibilities.
So you need to parse it anyway.
Now, how is a binary format, eg. ASN.1 DER, easier to parse than JSON or S-expressions?
IMO what would actually make a difference in this case is using a generic pre-existing serialization format, and therefore parser, instead of rolling your own.
@Wolf480pl yeah, you could even have a protocol for applying mutations rather than parse binary data. You still need to serialize the protocol, but for some reason protobufs are easier than CPP's textual AST 🤔
@Wolf480pl also, it's a totally valid point that it's not making anything new possible at all; it's about cutting out some problems to allow to have new ones, hopefully with more productive results
@Wolf480pl in every case your interface is essentially a new language, the hard part is making conversion universally easier and allow experiments like visual representation for values and constructs 🤔 (do not think graphical OOP xD)
Welcome to your niu world ! We are a cute and loving international community Ｏ(≧▽≦)Ｏ !