[HN Gopher] Why do we need modules at all? (2011)
       ___________________________________________________________________
        
       Why do we need modules at all? (2011)
        
       Author : matthews2
       Score  : 126 points
       Date   : 2025-04-02 07:34 UTC (2 days ago)
        
 (HTM) web link (groups.google.com)
 (TXT) w3m dump (groups.google.com)
        
       | wruza wrote:
       | That would be too useful. Imagine adding tags to functions and
       | generally treat them as "items" which you can multi-categorize,
       | search through, select, etc like with any dataset. Way too
       | advanced.
        
       | ludston wrote:
       | We need modules so that my search results aren't cluttered with
       | contamination from code that is optimised to be found rather than
       | designed to solve my specific problem.
       | 
       | We need then so that we can find all functions that are core to a
       | given purpose, and have been written with consideration of their
       | performance and a unified purpose rather than also finding a grab
       | bag of everybody's crappy utilities that weren't designed to
       | scale for my use case.
       | 
       | We need them so that people don't have to have 80 character long
       | function names prefixed with Hungarian notation for every
       | distinct domain that shares the same words with different
       | meanings.
        
         | bob1029 wrote:
         | I feel like you are arguing more for namespaces than modules.
         | 
         | Having a hierarchical naming system that spans everything makes
         | it largely irrelevant how the functions themselves are
         | physically organized. This also provides a pattern for
         | disambiguating similar products by way of prefixing the real
         | world FQDNs of each enterprise.
        
           | ludston wrote:
           | It is irrelevant until you have 4gb of binaries loaded from
           | 50 repositories and then you are trying to find the
           | definition of some cursed function that isn't defined in the
           | same spot as everything it is related to, and now you have to
           | download/search through all 50 repositories because any one
           | of them could have it. (True story)
        
             | layer8 wrote:
             | Modules don't imply namespaces. You can run into the same
             | problem with modules. For example, C libraries don't
             | implicitly have namespaces. And the problem can be easily
             | solved by the repository maintaining a function index,
             | without having to change anything about the modules.
        
           | adrian_b wrote:
           | As another poster already said, providing namespaces is just
           | one of the functions of modules, the other being
           | encapsulation, i.e. the interface of a module typically
           | exports only a small subset of the internal symbols, the rest
           | being protected from external accesses.
           | 
           | While a function may have local variables that are protected
           | from external accesses, a module can export not only multiple
           | functions, but any other kinds of symbols, e.g. data types or
           | templates, while also being able to keep private any kind of
           | symbol.
           | 
           | In languages like C, which have separate compilation, but
           | without modules, you can partition code in files, then choose
           | for each symbol whether to be public or not, but with modules
           | you can handle groups of related symbols simultaneously, in a
           | simpler way, which also documents the structure of the
           | program.
           | 
           | Moreover, with a well-implemented module system, compilation
           | can be much faster than when using inefficient tricks for
           | specifying the interfaces, like header file textual
           | inclusion.
        
         | norman784 wrote:
         | Don't forget about encapsulation, there's most likely a lot of
         | functions that aren't relevant outside the module.
        
         | Gurkenglas wrote:
         | just deduce the domain from text similarity :o)
        
         | sweezyjeezy wrote:
         | I agree, but also agree with the author's statement "It's very
         | difficult to decide which module to put an individual function
         | in".
         | 
         | Quite often coders optimise for searchability, so like there
         | will be a constants file, a dataclasses file, a "reader"s file,
         | a "writer"s file etc etc. This is great if you are trying to
         | hunt down a single module or line of code quickly. But it can
         | become absolute misery to actually read the 'flow' of the
         | codebase, because every file has a million dependencies, and
         | the logic jumps in and out of each file for a few lines at a
         | time. I'm a big fan of the "proximity principle" [1] for this
         | reason - don't divide code to optimise 'searchability', put
         | things together that actually depend on each other, as they
         | will also need to be read / modified together.
         | 
         | [1] https://kula.blog/posts/proximity_principle/
        
           | ludston wrote:
           | Indeed! The traditional name for the proximity principle is
           | called "cohesion"[1].
           | 
           | [1] https://en.wikipedia.org/wiki/Cohesion_(computer_science)
        
           | feoren wrote:
           | > It's very difficult to decide which module to put an
           | individual function in
           | 
           | It's difficult because it is a core part of software
           | engineering; part of the fundamental value that software
           | developers are being paid for. Just like a major part of a
           | journalist's job is to first understand a story and then lay
           | it out clearly in text for their readers, a major part of a
           | software developer's job is to first understand their domain
           | and then organize it clearly in code for other software
           | developers (including themselves). So the act of deciding
           | which modules different functions go in _is_ the act of
           | software development. Therefore, these people:
           | 
           | > Quite often coders optimise for searchability, so like
           | there will be a constants file, a dataclasses file, a
           | "reader"s file, a "writer"s file etc etc.
           | 
           | Those people are shirking their duty. I _disdain_ those
           | people. Some of us software developers actually take our jobs
           | seriously.
        
           | hansvm wrote:
           | One thing I experimented with was writing a tag-based
           | filesystem for that sort of thing. Imagine, e.g., using an
           | entity component system and being able to choose a view that
           | does a refactor across all entities or one that hones in on
           | some cohesive slice of functionality.
           | 
           | In practice, it wound up not quite being worth it (the
           | concept requires the same file to "exist" in multiple
           | locations for that idea to work with all your other tools in
           | a way that actually exploits tags, but then when you
           | reference a given file (e.g., to import it) that needs to be
           | some sort of canonical name in the TFS so that on `cd`-esque
           | operations you can reference the "right" one -- doable, but
           | not agnostic of the file format, which is the point where I
           | saw this causing more problems than it was solving).
           | 
           | I still think there's something there though, especially if
           | the editing environment, programming language, and/or
           | representation of the programming language could be brought
           | on board (e.g., for any concrete language with a good LSP,
           | you can re-write important statements dynamically).
        
             | hansvm wrote:
             | Oops: important -> import
        
           | 6figurelenins wrote:
           | Not to pick on Rails, sorting files into "models / views /
           | controllers" seems to be our first instinct. My pantry is
           | organized that way: baking stuff goes here, oils go there,
           | etc.
           | 
           | A directory hierarchy feels more pleasant when it maps to
           | features, instead. Less clutter.
           | 
           | Most programmers do not care about OO design, but
           | "connascence" has some persuasive arguments.
           | 
           | https://randycoulman.com/blog/2013/08/27/connascence/
           | 
           | https://practicingruby.com/articles/connascence
           | 
           | https://connascence.io/
           | 
           | > Knowing the various kinds of connascence gives us a metric
           | for determining the characteristics and severity of the
           | coupling in our systems. The idea is simple: The more remote
           | the connection between two clusters of code, the weaker the
           | connascence between them should be.
           | 
           | > Good design principles encourages us to move from tight
           | coupling to looser coupling where possible. But connascence
           | allows us to be much more specific about what kinds of
           | problems we're dealing with, which makes it easier to reason
           | about the types of refactorings that can be used to weaken
           | the connascence between components.
        
         | taeric wrote:
         | We could get that without a hierarchical categorization of
         | code, though?
         | 
         | Makes me wonder what it would look like if you gave "topics" to
         | code as you wrote it. Where would you put some topics? And how
         | many would you have that are part of several topics?
        
           | hombre_fatal wrote:
           | There is a similar question about message board systems.
           | 
           | Instead of posting a topic in a subforum, what if subforums
           | were turned into tags and you just post your topic globally
           | with those tags. Now you can have a unified UI that shows all
           | topics, and people can filter by tag.
           | 
           | I experimented with this with a /topics page that implemented
           | such a UI. What I found was that it becomes one big soup that
           | lacks the visceral structure that I quickly found to be
           | valuable once it was missing.
           | 
           | There is some value to "Okay, I clicked into the WebDesign
           | subforum and I know the norms here and the people who
           | regularly post here. If I post a topic, I know who is likely
           | to reply. I've learned the kind of topics that people like to
           | discuss here which is a little different than this other
           | microclimate in the RubyOnRails subforum. I know the topics
           | that already exist in this subforum and I have a feel for it
           | because it's separate from the top-level firehose of
           | discussion."
           | 
           | I think something similar happens with modules and grouping
           | like-things into the same file. Microclimates and micronorms
           | emerge that are often useful for wrapping your brain around a
           | subsystem, contributing to it, and extending it. Even if the
           | norms and character change between files and modules, it's
           | useful that there are norms and character when it comes to
           | understanding what the local objective is and how it's trying
           | to solve it.
           | 
           | Like a subforum, you also get to break down the project
           | management side of things into manageable chunks without
           | everything always existing at a top organizational level.
        
             | efitz wrote:
             | I agree, but go farther:
             | 
             | Most things have multiple kinds of interesting properties.
             | And in general, the more complex the thing, the more
             | interesting properties it has. Ofc "interesting" is
             | relative to the user/observer.
             | 
             | The problem with hierarchical taxonomies, and with
             | taxonomies in general, is that they try to categorize
             | things by a single property. Not only that, the selection
             | of the property to classify against, is relevant to the
             | person who made the selection, but it might not be
             | relevant, or at least the most relevant, property for
             | others who need to categorize the same set of things.
             | 
             | Sometimes people discover "new" properties of things, such
             | as when a new tool or technique for examining the things,
             | comes into existence. And new reasons for classifying come
             | into existence all the time. So a hierarchical taxonomy
             | begins to become less relevant, as soon as it is invented.
             | 
             | Sometimes one wants to invent a new thing and needs to
             | integrate it into an existing taxonomy. But they have a new
             | value for the property that the taxonomy uses for
             | classification. Think back to SNMP and MIBs and OIDs. Now
             | the original classifier is a gatekeeper and you're at their
             | mercy to make space for your thing in the taxonomy.
             | 
             | In my experience, the best way to classify things,
             | ESPECIALLY man-made things, is to allow them to be freely
             | tagged with zero or more tags (or if you're a stickler, one
             | or more tags). And don't exert control over the tags, or
             | exert as little control as you can get away with. This
             | allows multiple organic taxonomies to be applied to the
             | same set of things, and adapts well to supporting new use
             | cases or not-previously-considered use cases.
        
             | skydhash wrote:
             | Tags are great only when hierarchical structures becomes
             | cumbersome. And even then, there's some limit to how much
             | tags you can have before they become useless.
        
             | taeric wrote:
             | Yeah, I suspect this is one where the general hierarchy
             | does lift quite heavily. Such that it isn't that I would
             | want to lose it, entirely. More that I think it is best
             | seen as a view of the system. Not a defining fact of it.
             | 
             | Is a lot like genres for music and such. In broad strokes,
             | they work really well. If taken as a requirement, though,
             | they start to be too restrictive.
        
         | AtlasBarfed wrote:
         | The article references the true granularity issue (actually the
         | function names need a version number as well, not sure in my
         | scan of the article if it was mentioned).
         | 
         | Modules being collections of types and functions obviously
         | increases coarseness. I'm not a fan of most import mechanisms
         | because it leaves versioning and namespace versioning (if it
         | has namespaces at all...) out, to be picked up poorly by build
         | systems and dependency graph resolvers and that crap.
        
           | poincaredisk wrote:
           | How do you imagine importing modules by version in the code?
           | Something like "import requests version 2.0.3"? This sounds
           | awful when you accidentally import the same module in two
           | different versions and chaos ensures.
        
             | _factor wrote:
             | Import latest where signed by a trusted authority.
        
       | unwind wrote:
       | Meta: this needs "(2011)" in the title, please.
        
       | jasode wrote:
       | If there are no modules but a "flat" global namespace which
       | requires every function name to be unique to avoid collisions...
       | it means people would inevitably _re-invent pseudo /fake
       | "modules" and hierarchy in metadata tags_ in large non-trivial
       | codebases.
       | 
       | Consider a function name: _log()_
       | 
       | Is it a function to log an event for audit history?
       | 
       | Or is it a function to get the mathematical natural logarithm of
       | a number?
       | 
       | The global namespace forces the functions to be named differently
       | (maybe use underscore '_') in "audit_log()" and the other
       | "math_log()". With modules, the names would isolated be colons
       | "::" or a period '.' : Audit.log() and Math.log(). Audit and Math
       | are isolated namespaces. You still have potential global
       | namespace collisions but it happens at the higher level of
       | _module names_ instead of the leaf function names. Coordinating
       | the naming at the level of modules to avoid conflicts is much
       | less frequent and more manageable.
       | 
       | Same issue in os file systems with proposing no
       | folders/directories and only a flat global namespace with
       | metadata tags. The filenames themselves would have embedded
       | substrings with underscores to recreate fake folder names. People
       | would reinvent hierarchy in tag names with concatenated
       | substrings like "tag:docs_taxes_archive" to recreate pseudo
       | folders/directories of "/docs/taxes/archive". Yes, some users
       | could deliberately avoid hiearchies and only name tags as 1-level
       | such as "docs", "taxes", "archive" ... but that creates new
       | organizational problems because some have "work docs" vs
       | "personal docs" ... which gravitates towards a hierarchical
       | organization again.
        
         | john2x wrote:
         | This is what Emacs Lisp has, and what indeed does happen with
         | libraries
        
           | _Wintermute wrote:
           | Happens with R as well where everything gets dumped into a
           | global namespace. It's a huge mess.
           | 
           | If you're lucky all functions will have a common prefix str_*
           | or fct_*. If you're unlucky then you have to figure out which
           | package has clobbered a standard library function, or the
           | exact ordering of your package import statements you need for
           | your code to run.
        
           | bfung wrote:
           | Same with S3 object names.
           | 
           | There's no directories in S3, just object names.
           | 
           | The feature of the object names being hierarchical with "/"
           | delimiters are out of habit and easier to reason about for
           | the avg user.
        
         | skydhash wrote:
         | Same thing happens to me with Bear.app (note taking). It only
         | has tags, and the first thing I believe everyone does is to go
         | with hierarchical structure again, because you need some tag,
         | but also an additional specifier. Which help with grouping an
         | location (And Bear.app have support for that naming scheme and
         | displays it as a tree).
        
       | DarkNova6 wrote:
       | Should have put on the (2011) label
        
       | MrBuddyCasino wrote:
       | We need modules because they demarcate social units of
       | collaboration.
        
         | greener_grass wrote:
         | This could be achieved with a hierarchical namespacing scheme
         | for functions, no?
         | universe.mega_corp.finance_dept.team_alpha.foo
         | 
         | But to use `universe.mega_corp.finance_dept.team_alpha.foo` in
         | your application, you don't import a module, just the function
         | `foo`.
         | 
         | Who controls what goes into the namespace
         | `universe.mega_corp.finance_dept.team_alpha`? That would be
         | Team Alpha in the Finance Department of Mega Corp.
         | 
         | I guess this is like tree-shaking by default.
        
           | sestep wrote:
           | I'm probably just missing something obvious, but in this
           | scenario with really long names, doesn't that just mean all
           | code will be extremely verbose? Or are you saying there'd be
           | some way to have shorter bindings to those longer names
           | within a specific context? But then what would that look
           | like? Typically we use modules to denote contexts within
           | which you can import longer fully-qualified names with
           | shorter aliases.
        
             | greener_grass wrote:
             | You would do something like:                   open
             | universe.mega_corp.finance_dept.team_alpha
             | 
             | Then when you use `foo`, the compiler would know you mean
             | `universe.mega_corp.finance_dept.team_alpha.foo`.
             | 
             | There will probably need to be some kind of lock-file or
             | hash stored with the source-code so that we know precisely
             | which version of
             | `universe.mega_corp.finance_dept.team_alpha.foo` was
             | resolved.
        
               | j_w wrote:
               | This is literally just                 using
               | universe.mega_corp.finance_dept.team_alpha;
               | 
               | Every argument made quickly becomes invalid because in
               | any sufficiently complex project, the function naming
               | scheme will end up replicating a module/namespace system.
        
               | ramses0 wrote:
               | This is kindof how golang works by default. `import
               | foo/bar/baz` then "foo" and "bar" effectively don't
               | exist, you only refer to "baz" in the end.
               | 
               | `import github.com/blah/baz`, `megacorp.com/finance/baz`,
               | ...
               | 
               | It all resolves to `baz.Something()`
        
       | Etheryte wrote:
       | As with other similar proposals, doesn't this simply move the
       | complexity around without changing anything else? Now instead of
       | looking for the right module or whatnot, you'll be sifting
       | through billions of function definitions, trying to find the very
       | specific one that does what you need, buried between countless
       | almost but not quite similar functions.
        
       | VMG wrote:
       | Functions are not isolated values.
       | 
       | They are nodes in a graph, where the other nodes are the input
       | types, output types and other functions.
       | 
       | It makes sense to cluster closely associated notes, hence
       | Modules.
        
       | anonzzzies wrote:
       | Makes me think of Unison [0]. I never used it but I found it
       | interesting to read about.
       | 
       | [0] https://www.unison-lang.org
        
         | aeonik wrote:
         | The Bruijn language is a really cool language that takes some
         | of theae ideas to the extreme and fundamentals.
         | 
         | Variables aren't named, they are beta reduced and referred to
         | by abstraction level.
         | 
         | https://text.marvinborner.de/2023-04-06-01.html
        
         | bradrn wrote:
         | Also Io, to some extent:
         | https://iolanguage.org/guide/guide.html#Importing
        
       | neongreen wrote:
       | > database of functions
       | 
       | This is exactly what Unison (https://www.unison-lang.org/) does.
       | It's kinda neat. Renaming identifiers is free. Uh... probably
       | something else is neat (I haven't used Unison irl)
        
         | brabel wrote:
         | A lot of things are neat because of this. Refactoring becomes
         | trivial and safe. If you do not change the type of the
         | refactored function, you can safely do a batch replace and
         | everywhere the old function was used, the new one will be used
         | after that. If you do change the type, the compiler interface
         | will guide you through an interactive flow where you have to
         | handle the change everywhere the function was being used. You
         | can stop in the middle and continue later... and once you're
         | done you just commit and push... all the while the code
         | continues to work. Even cooler, perhaps: no unit test is re-run
         | if not affected. And given the compiler knows the full AST of
         | everything , it knows exactly when a test must run again.
        
         | jweir wrote:
         | I tried it out. Fascinating language and a completely different
         | paradigm. The language itself is familiar, but the structure of
         | the program is different - no files - all functions are in a
         | database and their history. I found the language a bit
         | difficult to navigate, but that is probably because of my
         | experience of work with files, and having tools based on files.
        
       | landsman wrote:
       | What a mess
        
       | layer8 wrote:
       | Aside from grouping functions together that work together, for
       | example working with data types/structures also defined in or by
       | the module, modules also serve the purpose to hide
       | implementation-detail code ("private" functions) shared between
       | those functions. Modules provide a form of information hiding.
       | 
       | Furthermore, modules are the unit of versioning. While one could
       | version each individual function separately, that would make
       | managing the dependency graph with version compatibility
       | considerably more complex.
       | 
       | There is the adage "version together what changes together". That
       | carries over to modules: "group together in a module what changes
       | together". And typically things change together that are designed
       | together.
       | 
       | Namespaces are an orthogonal issue. You can have modules without
       | namespaces, and namespaces without modules.
        
       | gatinsama wrote:
       | "Namespaces are one honking great idea -- let's do more of
       | those!" Zen of Python
        
       | porkbrain wrote:
       | 1. Have a global append-only function key-value store.
       | 
       | 2. A key of a function is something like `keccak256(function's
       | signature + docstring)`
       | 
       | 3. A value is a list of the function's implementation (index
       | being the implementation's version) and some other useful
       | metadata such as the contributor's signature and preferred
       | function name. (Compiler emits a warning that needs to be
       | explicitly silenced if preferred name is not used.)
       | 
       | 4. IDE hints and the developer confirms to auto import the
       | function from the global KV store.
       | 
       | 5. Import hash can be prepended with a signers name that's
       | defined in some config file. This makes it obvious in git diffs
       | if a function changes its author. Additionally, the compiler only
       | accepts a short hash in import statements if used with a signer.
       | 
       | package.toml                 [signers]       mojmir = "mojmir's
       | pubkey"       radislava = "radislava's pubkey"
       | 
       | source.file                 // use publisher and short hash
       | import "mojmir@51973ec9d4c1929b@1" as log_v1;       // or full
       | hash       import "51973ec9d4c1929bdd5b149c064d46aee47e92a7e2bb5f
       | 7a20c7b9cfb0d13b39" as log_latest;       import
       | "radislava@c81915ad12f36c33" as ln;            log_v1("Hello");
       | log_latest(ln(0));
        
         | Philpax wrote:
         | You've just invented Unison :)
        
       | bionhoward wrote:
       | IMHO, aren't modules necessary for big projects to limit the
       | amount of complexity we have to deal with at any one time?
       | 
       | Our minds can (allegedly) only handle 7+/-2 concepts in working
       | memory at once. Your whole codebase has way more than that,
       | right? But one module could easily fit in that range.
        
       | andrewcl wrote:
       | Hard to see a world without modules as a means of
       | compartmentalization for various reasons. You do have to
       | appreciate the exercise what a world without them looks like /
       | the implications.
        
       | friendzis wrote:
       | Global namespace clobbering has huge implications. With
       | modules/namespaces you have a well defined and limited blast
       | radius: a change is limited to a module and calling code.
       | 
       | Now, imagine your environment of choice supported dynamic runtime
       | loading of code where the code is just dropped to the global
       | namespace. This screams "insecure" and "how do I know if I call
       | the code I want to call?".
       | 
       | Now imagine the only mitigating mechanism was `include_once`. It
       | would make sense software written in this environment requires
       | own CVE namespace as new security vulns are discovered every
       | second
        
         | jghn wrote:
         | What he wound up arguing for was that everything would have a
         | globally unique name.
        
       | rdtsc wrote:
       | I miss Joe, he left us too early. He always had wild ideas like
       | that. For a while he had this idea of a git + bittorrent he
       | called it gittorrent, only to find out someone had already used
       | the name. I think it was a bit of an extension of this universal
       | functions idea.
       | 
       | If you expand some of the comments below, he and other members of
       | the community at the time have a nice discussion about
       | hierarchical namespace.
       | 
       | I particularly like his "flat beer and chips" comment:
       | 
       | https://groups.google.com/g/erlang-programming/c/LKLesmrss2k
       | 
       | ---
       | 
       | > I'd like to know if there will be hierarchial modules in
       | Erlang, because tree of packages is a rather good idea:
       | 
       | No it's not - this has been the subject of long and heated
       | discussion and is why packages are NOT in Erlang - many people -
       | myself included - dislike the idea of hierarchical namespaces.
       | The _dot_ in the name has no semantics it 's just a separator.
       | The name could equally well be encoders.mpg.erlyvideo or
       | mpg.applications.erlvideo.encoder - there is no logical way to
       | organise the package name and it does not scale -
       | 
       | erlyvideo.mpegts.encoder erlyvideo.rtp.encoder
       | 
       | But plain module namespace is also ok. It would be impossible for
       | me to work with 30K LOC with plain function namespace.
       | 
       | The English language has a flat namespace.
       | 
       | I'd like a drink.alcoholic.beer with my food.unhealthy.hamburger
       | and my food.unhealthy.national.french.fries
       | 
       | I have no problem with flat beer and chips.
       | 
       | /Joe
       | 
       | ---
        
         | auggierose wrote:
         | but we _do_ have alcoholic beer, and non-alcoholic beer, and it
         | is nice to be able to say which one you want. And yes, there is
         | a separator here, too, it is called a space.
        
         | hinkley wrote:
         | Software development is continually emotionally stunted by a
         | lack of people with expertise in multiple other fields.
         | 
         | English absolutely has namespaces. Every in-group has
         | shibboleths and/or jargon, words that mark membership in the
         | group that have connotations beyond the many dictionary
         | definitions of that word (in fact I wonder how many words with
         | more than three definitions started out as jargon/slang words
         | that achieved general acceptance).
         | 
         | You cannot correctly parse a sentence without the context in
         | which it was written. It's a literary device some authors use.
         | By letting the reader assume one interpretation of a prophetic
         | sentence early on, the surprise the reader experiences when
         | they discover a different interpretation at the end intensifies
         | the effect.
        
           | rdtsc wrote:
           | > Software development is continually emotionally stunted by
           | a lack of people with expertise in multiple other fields.
           | 
           | I think Joe's point is about the perennial discussion whether
           | hierarchy is better than tags. It's as old as software or as
           | old as people started categorizing things. Some early
           | databases were hierarchical KV stores. Email clients and
           | services go through that too, is it better to group messages
           | by tags or have a single hierarchy of folders?
           | 
           | > English absolutely has namespaces
           | 
           | Sure, we can pick apart the analogy, after all we're not
           | programing in English unless we write LLM prompts (or COBOL
           | /s). Then if English has namespaces what would you pick
           | lager.flat.alcoholic or alcoholic.lager.flat or
           | lager.alcoholic.flat, etc? Is there a top-level "lager" vs
           | "ale" package, with a flat vs carbonated as next level?
        
             | d0mine wrote:
             | "whether hierarchy is better than tags" sounds like whether
             | hammer is better than a screwdriver. Use a tool appropriate
             | for the job.
             | 
             | Hierarchy seems more rigid less general than tags but when
             | it works--it works.
        
           | 0perator wrote:
           | It's arguable that any group's dialect is actually a fork of
           | English specialized for a specific culture, activity, or
           | context. Occasionally, elements of the fork are pulled into
           | upstream English as groups grow in popularity and jargon or
           | shibboleths become more commonly used across dialects.
        
           | froh wrote:
           | yes. and math/logics trained brains confuse hierarchical
           | namespaces with trees. names in nested namespaces should be
           | DAGs, maybe even arbitrary graphs, meaning a chair can be a
           | sit-on thing in several contexts, but not in all (think
           | meeting).
           | 
           | in many contemporary programming languages you can express
           | this, too, by exporting some imported name.
        
           | mechanicalpulse wrote:
           | I'm reminded of a Final Jeopardy! clue from a few years back
           | --
           | 
           | > As of 2013, this 3-letter verb common in sports, theater &
           | politics has the largest entry in the online OED.
           | 
           | The correct response? What is "run"?
        
         | twic wrote:
         | > The dot in the name has no semantics it's just a separator.
         | 
         | That's not true of all module systems. It's true in Java, but
         | not in Rust, where it establishes a parent-child relationship,
         | and in which context [1]:
         | 
         | > If an item is private, it may be accessed by the current
         | module and its descendants.
         | 
         | [1] https://doc.rust-lang.org/reference/visibility-and-
         | privacy.h...
        
           | kibwen wrote:
           | And privacy in Rust is load-bearing for encapsulating unsafe
           | operations from safe code, so it's not just a nice-to-have,
           | its fundamental to the language.
        
       | bjourne wrote:
       | This is an all-time classic, but, sadly, most HN commenters just
       | don't "get it". Perhaps because they have no experience with the
       | Erlang VM so they don't understand Joe's premises The Erlang VM
       | is best described as a dynamic process manager and a "function"
       | is just a callstack template. You want to fix a bug in your
       | _executing_ function _without stopping it_? Sure, no problem.
       | Just reload the function and have the VM seamlessly upgrade the
       | callstack to the new template. Since data is immutable it mostly
       | just works. Now since functions forms the basic unit of work in
       | Erlang modules are kind of irrelevant. Recompiling a module is
       | the same as recompiling every function in the module. Hence, what
       | use does the abstraction serve? The proliferation of  "utils" or
       | "misc" modules in not only Erlang but many other languages
       | supports his point.
       | 
       | Btw, the more experienced I've gotten the more I've found that
       | organizing code is mostly pointless. A 5000-line source file
       | (e.g., module) isn't necessarily worse than five 1000-line files.
        
         | skydhash wrote:
         | It's all related to naming. You can refer to a symbol with
         | auth/guard/token/authenticate or auth_guard_token_authenticate,
         | and what matters is the amount of characters you type
         | sometimes. Also you can have encapsulation with the first
         | option.
         | 
         | Smalltalk have the same live experience, but do have modules,
         | because it makes editing easier and encapsulation is nice for
         | readability and clarity.
        
           | bjourne wrote:
           | No, neither Smalltalk nor any of the Lisp environments that
           | purport to support hot code reloading have the same
           | facilities the Erlang VM has.
        
             | skydhash wrote:
             | Concurrency and tasks supervision is orthogonal to
             | modules/packages.
        
         | igouy wrote:
         | Is a 5,000-line function worse than 500 10-line functions?
         | 
         | (Locality of reference.)
        
       | jonnycat wrote:
       | This is one of those things where I don't agree with the
       | argument, but know the person making it knows _way_ more than I
       | do on the subject and has given it _way_ more thought. In these
       | cases it's usually best to sit back and listen a bit...
        
       | immibis wrote:
       | I think they already tried this "single flat key/value namespace
       | of all functions" in the JavaScript ecosystem - it was called
       | npm. It was a mess when someone claimed a function based on a
       | trademark and someone else deleted the function for padding a
       | string to a certain length with spaces on the left in
       | retaliation.
        
       | GrantMoyer wrote:
       | I think Hoogle[1] is proof this concept could work. Haskell has
       | modules, of course, but even if it didn't, Hoogle would keep it
       | still pretty usuable.
       | 
       | The import piece here which is mentioned but not very emphasized
       | in TFA is that Hoogle lets you search by meta data instead of
       | just by name. If a function takes the type I have, and transforms
       | it to the type I want, and the docs say it does what I want, I
       | don't really care what module or package it's from. In fact,
       | that's often how I use Hoogle, finding the function I need across
       | all Stack packages.
       | 
       | That said, while I think it could work, I'm not convinced it'd
       | have any benefit over the statys quo in practice.
       | 
       | [1]: https://hoogle.haskell.org/
        
         | kibwen wrote:
         | Hoogle works because of how richly-typed Haskell is, but Erlang
         | is dynamically-typed.
        
       | TOGoS wrote:
       | Unison of course works this way, as has been mentioned.
       | 
       | I like Deno for similar reason. It's a coarser level of
       | granularity, and not explicitly content-addressed, but you can
       | import specific versions of modules that are ostensibly
       | immutable, and if you want, you could do single-function modules.
       | 
       | I like the idea so much that I'm now kind of put off by any
       | language/runtime that requires users of my app/library to do a
       | separate 'package install' step. Python being the most egregious,
       | but even languages that I am otherwise interested in, like
       | Racket, I avoid because "I want imports to be unambiguous and
       | automatically downloaded."
       | 
       | Having a one-step way to run a program where all dependencies are
       | completely unambiguous might be my #1 requirement for programming
       | languages. I am weird.
       | 
       | One reason not to do things this way is if you want to be able to
       | upgrade some library independently of other components that
       | depend on it, but "that's what dependency injection is for". i.e.
       | have your library take the other library as an argument, with the
       | types/APIs being in a separate one. TypeScript's type system in
       | particular makes this work very easily. I have done this in Deno
       | projects to great effect. From what I've heard from Rich
       | Hickey[1] the pattern should also work well in Clojure
       | 
       | [1] something something union types being superior to what you
       | might call 'sum types'; can't find the link right now. I think
       | this causes some trouble in functional languages where instead of
       | something being A|B it has to be a C, where C = C A | C B. In the
       | former case an A is a valid A|B, but a C A is not an A, so you
       | can't expand the set of values a function takes without breaking
       | the API. Basically what union types require is that every value
       | in the language extends some universal tagged type; if you need
       | to add a tag to your union then it won't work.
        
       | surprisetalk wrote:
       | This post was a huge inspiration for scrapscript!
       | 
       | [0] https://scrapscript.org
        
       | codethief wrote:
       | > all functions go into a global (searchable) Key-value database
       | 
       | Very much related: https://scrapscript.org/
        
       | jiggawatts wrote:
       | I had a vaguely similar notion of a global proof database.
       | Picture something like a blockchain (actually a "blockgraph") of
       | Lean theorems built up from other theorems and axioms also on the
       | same distributed global data structure.
       | 
       | A use-case could be optimising compilers. These need to search
       | for alternative (faster) series of statements that are _provably
       | equivalent_ to the original given some axioms about the behaviour
       | of the underlying machine code and basic boolean algebra and
       | integer mathematics.
       | 
       | This could be monetised: Theorems along the shortest path from a
       | desired proof to the axioms are rewarded. New theorems can be
       | added by anyone at any time, but would generate zero income
       | unless they improve the state-of-the-art. Shortest-path searches
       | through the data structure would remain efficient because of this
       | incentive.
       | 
       | Client tools such as compilers could come with monthly
       | subscriptions and/or some other mechanism for payments, possibly
       | reusing some existing crypto coin. These tools advertise desired
       | proofs -- just like how blockchain clients advertise transactions
       | they like to complete along with a fee -- and then the community
       | can find new theorems to reach those proofs, hoping not just for
       | the one-time payment, but the ongoing reward if the theorems are
       | general and reusable for other purposes.
       | 
       | Imagine you're a FAANG and there's some core algorithm that uses
       | 1% of your global compute. You could advertise a desire to
       | improve the algorithm or the assembly code to be twice as
       | efficient for $1M. Almost certainly, this is worth it. If no
       | proof turns up, there's no payment. If a proof does turn up, a
       | smart contract debits the FAANG's crypto account and they receive
       | the chain of theorems proving that there's a more efficient
       | algorithm, which will save them millions of USD in infrastructure
       | costs. Maths geeks, AI bots, and whomever else contributed to the
       | proof get their share of the $1M prize.
       | 
       | It's like... Uber for Fields medals, used for industrial
       | computing.
       | 
       | Fully automated gig work for computer scientists and
       | mathematicians.
        
         | LegionMammal978 wrote:
         | The Metamath Proof Explorer (AKA the set.mm database) works on
         | a similar principle, of all theorems forming a tree of
         | backreferences that ultimately lead to the axioms [0].
         | 
         | Though it wouldn't make sense to build something like that on
         | top of such a fast-moving, complex, and bug-prone target like
         | Lean.
         | 
         | [0] https://us.metamath.org/mpeuni/mmset.html
        
       ___________________________________________________________________
       (page generated 2025-04-04 23:01 UTC)