urbit / developers.urbit.org

Website for the Urbit Foundation's developer program
https://developers.urbit.org
16 stars 56 forks source link

Document Hoon conventions #302

Closed ajlamarc closed 1 year ago

ajlamarc commented 1 year ago

Per @jalehman's request, this post should make it somewhere into the documentation (the next page after the current style guide). But, there's discussion to be had on its suggested conventions.

Runes to avoid

Other discussion points

Will turn into a PR once there's some level of agreement.

ajlamarc commented 1 year ago

I'll add some basic reasoning. Most developers won't be writing hoon full time. Instead, the "set and forget it" nature of Gall agents means they will be referenced rarely - nuance in syntax will be forgotten, and it's expensive to reference the documentation every time you see a :^ or equivalent. Minimizing the number of runes / conventions used will improve developer productivity.

rabsef-bicrym commented 1 year ago

original

addendum:

i don't know enough about programming in the wild to know if this is true:

Since Hoon is also highly irregular, this is a big roadblock to understanding other developers’ code.

as compared to other languages. is hoon irregular? it doesn't seem so to me. it seems most regular.

lastly:

I wouldn't include any suggestions that prohibit the boilerplate of, e.g., rudder. Rudder is not permitted under this framework and it therefore is untenable for me. I'll call this passing the paltest. If I can't integrate paldev products in my hoon, I can't use the framework.

Fang- commented 1 year ago

The basic reasoning you gave sounds like this is trying to define a set of runes/hoon style which is more minimal than the full set, but still plenty to get you off the ground and writing real-world hoon. This is a good aim, I believe hoon school takes this approach also, but probably not something "the" style guide should adopt. The style guide is for code style guidelines in the general case, not code style catered towards a specific audience.

(Alternatively, we can point to the style guide's wording, "our way of writing Hoon code", and say it's talking about kernel & core distribution code specifically. In that case, there is a specific audience: people who do write hoon full-time, or those who want to do work in the same context.)

Minimizing the number of runes / conventions used will improve developer productivity.

Doubtful to me whether this is actually true. If anything it's probably heavily context-dependent.

There's all kinds of things I could pick at here, but probably not worth it until we conclude whether we want to turn the style guide towards this direction in the first place. "Accessibility-maxed hoon style" has its place, but I don't think the "official" style guide is it. (Happy to still give more detailed thoughts in dms or elsewhere if you really want them.)

dr-frmr commented 1 year ago

Agreed with rabsef on all points. Most of all, I don't buy the premise that reducing the size of the rune set changes the difficulty of grokking Hoon. Most of the runes you recommend using use ones you don't recommend under the hood!

And as long as we're proposing style guidelines, I think this proposal is missing the most obfuscatory practice in userspace code today: the use of kernel-style 3 and 4 letter faces everywhere. Once you learn the runes, all Hoon is equally readable. Specific runes don't change this, but what does is when you have to internalize a new metaphor or set of metaphors (often nonsensical) for every app you read.

polwex commented 1 year ago

For the record I agree with almost all suggestions by the @ajlamarc . A lot of people like to make paintings using hoon and reading code can get very annoying.

That said Urbit devs are what we are and herding cats never take us anywhere. Guess we'll have company wide style guides and that'll be that.

rabsef-bicrym commented 1 year ago

I'm inclined to accept @dr-frmr's suggestion that names, rather than runes, and patterns (again rather than runes), make reading harder.

In that direction, I would imagine you @polwex would be against nested core patterns that result in lines like: ca-abet:ca-prep:ca-read:ca-rite:ca-this:ca-that:(ca-abel:calk mar vaz)

I don't think the suggestions above fully solve for your concern.

Sincerely, a painter.

dr-frmr commented 1 year ago

A lot of people like to make paintings using hoon and reading code can get very annoying.

Runes are the only thing saving us from this! Learning every rune is a hard ceiling on complexity and from there, you get full readability (accounting for variable naming).

bacwyls commented 1 year ago

Never: abbreviate a label; pack characters (try to reduce the length of labels, or make lengths match up between parallel labels); use intentionally vague and meaningless words; or use nonsense text that isn’t a word.

The existing style guide already has a strong opinion against bad names.

IMO this style guide shouldn't be accepted into official docs. That would imply its contents are generally agreed upon by userspace developers, which isn't true. Plus it imposes on hoon devs that they shouldn't make full use of the language, which I'm against on GP.

I do think the broad idea here is worth considering, though. When making stylistic decisions in userspace code, there could be a lot to gain from catering to an audience that:

Beginners could read your agent with minimal context-switching to hoon documentation, and then write their own agent in the same basic style as yours. If beginners aren't led by example, they might not know that it's possible for them to write a good agent without having to first become a hoon expert. The barrier to entry for userspace dev could go a lot lower.

polwex commented 1 year ago

Runes are the only thing saving us from this!

A few runes are doing the same thing but inverting the order of the arguments they take. e.g. :- :_

Which is fine. I understand painting is fun. But it does get annoying to read. No other language has stuff like ?: vs ?.. Well ruby if kinda does.

On Earth there's two kinds of languages, right? Python-ish (one single way to do one thing) and Ruby-ish (many different ways to do the same thing). Hoon is surely Ruby-ish in this divide. 70% of runes are sugar over the real basic runes and there's a lot of runes which are really just painting-enablers.

Which again, once you get used to it is quite endearing. Like all languages, natural and computing, there's a learning curve but once you're done it's effortless. At least we don't have macros.

As for stuff like @rabsef-bicrym

ca-abet:ca-prep:ca-read:ca-rite:ca-this:ca-that:(ca-abel:calk mar vaz)

Yes I do think it's ugly. Very. I'm personally not a fan of nested cores, they feel like an OOP-ish kludge in a functional language.

But they're here to stay, and the kernel uses them heavily. So given that we could at least have a nicer syntax sugar to do nested core calls. Pipes would be nice. If Hoon is to be a painting language we might as well make sure all our paintings are pretty.

One good idea would be for Hoon School to start lessons with only the basic runes, zero sugar. I only really started grokking subject-oriented programming once I made a point of doing that myself.

ajlamarc commented 1 year ago

I think it's worth considering that Urbit devs are currently way more competent than an average programmer, so our tolerance for "number of keywords" is a lot higher.

We write Hoon so we can use Urbit's networking + auth stack, not because of the language itself. So looking at successful languages (Python) implies that nonessential keywords (runes) should start being removed from the lexicon, and eventually the remaining representable in human-readable words. (Have floated the idea before of a CoffeeScript that compiles to Hoon.)

Understandably current "Hooners" will fight against this. While @rabsef-bicrym's code is surely art, I can barely understand it.

bacwyls commented 1 year ago

Keywords over hoon have already been implemented and abandoned. Can anyone surface some of the old reasoning behind that? Seems pertinent.

IMO more would be accomplished with just a VSCode extension that describes a rune onhover and provides a link to docs for that rune.

nonessential keywords (runes) should start being removed from the lexicon

Code style is very complicated. Hard and fast rules don't work in every situation. IMO the common "vernacular" for userspace hoon will naturally include fewer runes as new devs start shipping code without having known every rune, and newer devs mimic that code style. This is naturally balanced by the need to clean up long, strung out programs. Experienced devs don't need to take part in that process.

This thread by @philipcmonk is relevant

intermediate hoon programmers use =/ not at all, contorting the code to avoid it. Sometimes it's the clearest technique.

It's very difficult to create "optimally styled" hoon code making full use of the language. There's a perfectionist atmosphere in urbit which comes from the kernel work. Thats an OK attitude for the kernel, but not for userspace. It's unreasonable to expect people to read and write "optimally styled" hoon when they're creating their first urbit app. Although no one is really bullying noobs about that, it could probably be made more clear that "unoptimal" hoon is perfectly OK in most cases. There are pretty good local maxima that newer devs are free to use without forcing anything on experienced devs.

dr-frmr commented 1 year ago

I think it's worth considering that Urbit devs are currently way more competent than an average programmer

Hard disagree, for any fair measure of our non-Urbit peers!

We write Hoon so we can use Urbit's networking + auth stack, not because of the language itself.

This is also not true for "we", though maybe it is for you -- lots of people are interested in Urbit as a purely functional programming environment. The "Nock VM" is going to be used for smart contract writing and hopefully many more things in the future, some of which may not even touch the event loop or auth stack of Urbit. If you want to create a more prescriptive language for a specific varietal of Urbit app -- the genre of social app / messaging app that doesn't need Urbit for much more than the p2p network and ID system -- that's a good idea, though I think your work with tome DB basically already handles that case. But Hoon is valuable as an existing, socially and compiler-ly agreed upon set of macros over Nock, and broad sweeping suggestions to alter the social side of this consensus seem harmful.

rabsef-bicrym commented 1 year ago

I believe there might be 3 projects here. I will conclude this thought with a request:

  1. Naming Conventions - in user space it is reasonable to suggest that people use human-legible kebab case, descriptive faces for anything that has a face. I am fine with someone suggesting to new users that they, e.g., eschew "mar" for mark and "vaz" for vase (a common convention in my work, and yours AJ).

  2. Highlighting "Easy" Runes - I think it is reasonable to give new Hooners a delimited, functional list of runes that will let them get started without memorizing everything. I believe @Fang- and @bacwyls (and others) spoke to that above. It strikes me that this might already be done in Hoon School as it is now taught (and has been explained above).

  3. Suggesting a strict style for Userspace based on (1) and (2) - I take @bacwyls's contention that this will naturally occur and then dissolve as programmers start, become more familiar with the language, improve their programs and utilize additional runes to clean up style. I don't think this is a necessary activity.

Request: If we want to continue to use my code as an exemplar of "styled but illegible", I would ask only that the person making the contention submit one PR clarifying portions of my code in any of my applications, before attempting the Rabsef Gambit as I will now refer to it.

sigilante commented 1 year ago

Hoon grew organically for the authors to serve the needs which naturally arose in systems programming for Urbit. This means that we can argue about rune usage in three ways:

  1. Whether a rune does what it is intended to do in a useful way. The existence of a long tail of Urbit rune occurrence reflects the utility of many of the rare runes: they do one useful thing well that was needed at some point in time for Urbit to work correctly and expressively. ~| sigbar should not be used indiscriminately, but it should be used in certain cases—perhaps it should only be recommended in kernel and middleware (/lib) code instead!

  2. Whether a rune does what it is intended to do in a correct way. Most of them do, but there are some known exceptions. ;< micgal needed to be sanitized. ?= wuttis should detect list.

  3. Whether the use of a rune unnecessarily obfuscates or increases code legibility. =+ tislus can absolutely be the correct rune in certain cases. +* lustar is controversial but most userspace developers find it compelling within the door context as boilerplate.

Any style guide, including the current one, would be much more compelling to me if it not only expressed strong opinions—which I am fine with whether I personally hold those opinions or not—but demonstrated in production code the given discipline. (@ajlamarc does refer to tome-db at the end.)

In fact, a long guide which discusses and illustrates WHEN each rune IS preferable and useful would be amazing. When and how to use =- tishep, for instance? Another useful way to surface this kind of discussion would be a series of "How I Work" blog posts, wherein opinionated arguments can be made and justified, then used or not as individual developers and teams prefer. (I would welcome any contributions in this vein.) Style guides for particular dev teams also make sense, e.g. Assembly Capital or Holium or Quartus.

@ajlamarc you are probably working on documentation for TomeDB as well. I would welcome an App Workbook entry discussing how and why a version of it does what it does, and such a tutorial would be a fine place to include arguments for a particular style.

App mark and structure styling is more in flux, and while I have hewed to a discipline of action/update in my more recent code, I think there is a case for effect or others for different kinds of peer actions, reserving action for generator-driven pokes.

A style guide is a good learning tool, and a case can be made for company-level production code. Ultimately tho: Rules are boring. Embrace digital anarchism.

Before enlightenment, chop wood and carry water. After enlightenment, chop wood and carry water.

ajlamarc commented 1 year ago

Hoon grew organically for the authors to serve the needs which naturally arose in systems programming for Urbit. This means that we can argue about rune usage in three ways:

1. Whether a rune does what it is intended to do in a useful way.  The existence of [a long tail of Urbit rune occurrence](https://developers.urbit.org/blog/rune-frequency-202212) reflects the utility of many of the rare runes:  they do one useful thing well that was needed at some point in time for Urbit to work correctly and expressively.  `~|` sigbar should not be used indiscriminately, but it should be used in certain cases—perhaps it should only be recommended in kernel and middleware (`/lib`) code instead!

2. Whether a rune does what it is intended to do in a correct way.  Most of them do, but there are some known exceptions.  `;<` micgal needed to be sanitized.  `?=` wuttis should detect `list`.

3. Whether the use of a rune unnecessarily obfuscates or increases code legibility.  `=+` tislus can absolutely be the correct rune in certain cases.  `+*` lustar is controversial but most userspace developers find it compelling within the door context as boilerplate.

Any style guide, including the current one, would be much more compelling to me if it not only expressed strong opinions—which I am fine with whether I personally hold those opinions or not—but demonstrated in production code the given discipline. (@ajlamarc does refer to tome-db at the end.)

In fact, a long guide which discusses and illustrates WHEN each rune IS preferable and useful would be amazing. When and how to use =- tishep, for instance? Another useful way to surface this kind of discussion would be a series of "How I Work" blog posts, wherein opinionated arguments can be made and justified, then used or not as individual developers and teams prefer. (I would welcome any contributions in this vein.) Style guides for particular dev teams also make sense, e.g. Assembly Capital or Holium or Quartus.

@ajlamarc you are probably working on documentation for TomeDB as well. I would welcome an App Workbook entry discussing how and why a version of it does what it does, and such a tutorial would be a fine place to include arguments for a particular style.

App mark and structure styling is more in flux, and while I have hewed to a discipline of action/update in my more recent code, I think there is a case for effect or others for different kinds of peer actions, reserving action for generator-driven pokes.

A style guide is a good learning tool, and a case can be made for company-level production code. Ultimately tho: Rules are boring. Embrace digital anarchism.

Before enlightenment, chop wood and carry water. After enlightenment, chop wood and carry water.

I've enjoyed reading all these comments. My trite response to Rules are boring. Embrace digital anarchism would perhaps be Code itself is not art. What the code builds is.

I think a series of different opinions on Hoon style would enlighten developers on what a good strategy to follow might be. Style guides for dev teams will become more important as those teams grow.

sigilante commented 1 year ago

Well obviously I'm an irredeemable troll there... :)

sigilante commented 1 year ago

I've been thinking about revisiting this. While I'm not willing to go as far as redesigning Hoon for the time being, I think that defining a subset of runes and limited sugar syntax that is present in the docs (outside of kernel stuff) and official userspace apps and generators would be a good thing to build for.

sigilante commented 1 year ago

I'm going to post a full gist on this soon, but right now here's what I'm thinking rune-wise for Hoon Prime:

Runes

The first concerns are to limit the scope of runes that must be learned to about the top 25 most important ones, with a few context-specific runes included for particular needs.

The following are allowed in specific contexts or forms:

The following should be specifically avoided in Hoon Prime:

To reiterate, these are not claims about Hoon generally—Hoon Prime is a pedagogical code discipline, not the future of Hoon.

bacwyls commented 1 year ago

I think a hoon-prime guide would have: =. presented as: "edit a variable", ?. : "if not", =| : "declare a variable without initializing", and maybe :_ and irregular form since it's so common.

%= and %~ are probably better presented as sugar.

;: can be safely ignored imo.

It would be cool if docs for each rune showed how important it is to initially learn based on frequency data. Or some natural way to communicate "You (hobbyist) are over the learning curve once you know these few minimum-viable-runes." and "A ton of this documentation is for onboarding and supporting full time system devs, you can write good code much sooner than it may seem."

More broadly speaking, hobbyist onboarding would benefit from a clear path to a "meaningful" program in <1 weekend. Something that might help here is for existing urbit apps to create more scripting opportunities and documented CLI flows to accomplish little things.

sigilante commented 1 year ago

;: shows up in unit tests—they become awkward without that rune.

sigilante commented 1 year ago

Thank you all for your contributions to this important discussion on conventions.

I am going to close this issue on the repo and move the discussion to the nature of a userspace code discipline, Hoon Prime.

Comment on the first version of the Hoon Prime proposal here: https://gist.github.com/sigilante/57109dafa344631f55d72bf5c7fd2fcd