HNHacker News
TopNewBestAskShowJobs

grayrest

1,959 karma · joined May 10, 2009

front end guy
submissionscomments
grayrest··on Kotlin for JavaScript
> Can Rust replace C or C++ yet, atleast for green field projects?

Mozilla has been replacing parts of Firefox C++ with Rust for a decade. They recently celebrated Rust hitting 25% of the LoC in the main repo. More broadly, serious code at large companies is written in Rust: A chunk of Google's Fuchsia OS, Dropbox's storage engine, Amazon's VM manager, etc. There are niches where C/C++ are better suited but in general Rust is good for whatever if the team wants to use it.

grayrest··on Kotlin for JavaScript
> What about Svelte?

Svelte apps aren't written in JS but in Svelte's own component syntax files. It's "HTML" but all the parts are extended (JS -> reactive, HTML -> directives, CSS -> scoping) and it needs its own compiler to transform the source to something everything else understands.

grayrest··on Humans did not evolve to ride bicycles (2017)
I think it's interesting that the online recumbent community as I've encountered it is in general agreement that most styles of recumbent climb worse than a diamond frame. I say most styles because recumbent bicycle design covers a much wider range of options than upright bicycles. The consensus is that a good climbing recumbent loses 5-10% power on the climbs but is generally faster over a course due to aerodynamic advantage (lower frontal area, better CdA due to the body not being shaped like a parachute). You can, of course, have a recumbent that doesn't climb well. I have one (my casual recumbent) where my hip angle is really bad at producing power for some reason so I get like 2/3 the climbing speed at full perceived power but my other (my fast recumbent) doesn't have an issue.

I like recumbents in general from a tech perspective because there's no obvious correct way to design them. The most efficient chain line for a rear wheel drive bike runs through the rider's body for lowracer through highracer designs which usually means idlers. Long wheelbase (LWB) design moves the cranks down to below the rider's seat which works for some people and not for others. Driving the front wheel works but creates traction problems going uphill and requires deciding whether the bottom bracket moves as part of the steering (Moving Bottom Bracket, MBB) or the chain twists (not consistently named, I've seen 3-4 designs). There's also weird designs like the python where the pivot is in the frame itself below the rider. It's a fun thing to explore and think about.

grayrest··on Humans did not evolve to ride bicycles (2017)
The usual study/reference for this is someone biking at ~10mph. Bicycles become progressively less efficient at higher speeds due to air resistance.

Fairings and reduced frontal area (recumbent/supine positioning) can help this considerably. The combination is commercially sold as velomobiles and they're not especially popular but they do work. As an example, dedicated amateur enthusiasts do 3 hour century rides in commercial velomobiles regularly.

grayrest··on Hooks Considered Harmful
I have not adopted hooks and have argued against it for others on the team. My primary objection is that the paradigm is not clean.

Class based components are fairly straightforward. The entire render function is run on every change.

Solid/Svelte are fairly straightforward. The component is run once and then only the reactive parts change.

Hooks run the function on every change but there are islands of non-running code inside the constantly rendering body where only run when their dependencies change. This strikes me as an obviously intermediate solution and I don't want to spend time porting/developing something that's going to be obsoleted in a year or two.

The next framework generation is underway and the time for early adopters to move on is in the next year or so. The main reason to hold off is that the handling of SSR/hydration/etc is in flux and I believe the primary benefit of the upcoming generation is going to be ability to avoid shipping most component code over the wire.

I have a lot of respect/love for React. I've seen quite a bit of criticism that the vdom idea is inherently inefficient but the important thing about it was that it was reliable. Lots of JS used to do all sorts of crazy stuff with the dom underneath you but React has basically cleared the field of most of that which allows more fine grained approaches to work consistently.

grayrest··on Ace, CodeMirror, and Monaco: A comparison of browser code editors (2021)
The size is going to depend on the set of features enabled and I expect that build has everything turned on so that it can be used for all the demos.

I did a quick check of a CM6 project (customizing the JS lexer) with the base options and a JS-derived lexer and it came out to 405k / 124k gzip. I wouldn't consider it especially lightweight but I think the size is reasonable for the feature set.

grayrest··on Vue 3 as the New Default
The ecosystem largely settled out in 2014 when everybody was "javascript fatigue" complaining. The developments since have mostly been refinements on details of the development setup or state management. There's new stuff but I'm pretty sure anybody who wrote React at the time would be comfortable with the slight modifications in the patterns of how things fit together.

We're kind of into the next generation of frameworks (Solid, Svelte 3, Vue 3) and that's more about how much JS is getting delivered to the client. The current area of exploration is "partial hydration" where the goal is to write stuff using the component model but do server rendering and only send JS for the parts of the page that'll change client side. For quite a few classes of application this would substantially reduce the size of JS over the wire. All this is less of a benefit than the state control React brought so I expect slower/partial adoption.

More broadly, there's been a resurgence of the render everything on the server and send html diffs approach in the form of alpine and htmx. The other potential area for change on the horizon is web assembly getting host bindings support so it doesn't have to bridge through JS to affect the DOM and other browser APIs.

grayrest··on Kakoune Code Editor
Doing the motion first lets you visually confirm the range before invoking the command. You also have the opportunity to adjust the range if you didn't get it quite right.

Mnemonically the vim order works better for English but in practice I find the visual feedback from selection better for anything even moderately complex. An example would b `f` or `t` since I tend to hit the letter I was aiming for earlier than I was expecting.

> In case were `wd` deletes a word - there should be some lag, no?

There's no animation or forced latency. For a short motion that's predictable like `w`, you're typing the d before you actually check the result and it's just as fast as vim but in the opposite order.

grayrest··on Kakoune Code Editor
I've gone for several week long stretches of using it but never fully converted. What winds up happening is that I get to a point in a project where I really need to focus on the code and not the editor, switch back to vim, and don't get around to switching back for another few months. The editing model is better than Vim's and if I didn't have 20 years of vim muscle memory I probably would have switched over by now.
grayrest··on Kakoune Code Editor
There is a Kakoune-inspired VSCode extension. [1]

[1] https://github.com/71/dance

grayrest··on Heroes of Might and Magic
HoMM3 was also my main experience with the series. I tend to pick it up once every few years with the last time in early 2020. My problem with the game is that I know the AI exploits so it's never THAT much of a challenge.

If you're picking it up again, the HD plus mod lets you play on higher resolution screens and adds keyboard shortcuts for things like splitting a creature stack in half. Highly recommended.

grayrest··on There's never been a better time to build websites
Tailwind is a design system. It's not the same as inline styles because the options are constrained and are picked to fit on a coherent scale. I consider the inability to do this natively to be a longstanding gap in CSS itself and have been doing my own variations of the tailwind utilities with sass mixins since 2009.

I'll point out that CSS has no semantic component in itself. It's just a way to apply styles. If you want to keep semantic class names then you can apply the tailwind design language using the postCSS `@apply` in the body. There's a tradeoff between the value of semantics against the value of greater code locality and elimination of specificity as a concern. In practice most people seem to prefer the latter.

grayrest··on Supersonic Trebuchet
The idea of using whip cracks for acceleration features fairly prominently in Neal Stephenson's Seveneves. None of the instances in the books are sized for orbital launch but that was the first time I encountered the idea.
grayrest··on Django, HTMX and Alpine.js: Modern websites, JavaScript optional
Keeping all state server side is a completely reasonable approach. The 37Signals guys have been advocating for it since 2006 or so and as long as you have a low latency connection to the server then it usually works great.

What doesn't work well (and what tended to happen with jQuery apps) is having state both on the client and on the server and having to coordinate between the two. My personal preference is for client side state with a lighter setup than React (i.e. Svelte). I like the predictable latency and I feel you don't run into a complexity barrier (e.g. multi-step forms) as the app grows.

grayrest··on Goodbye CSS Modules, Hello TailwindCSS
The restrictions are a feature, not a bug.
grayrest··on An oral history of Bank Python
This took me a while to figure out but K/APL code is built on a different value system than most software. Specifically, the goal is to be able to see and operate on the entire program at once. Obviously this only works for programs up to a certain size but that size is larger than you'd expect when abstractions, variable names, and general legibility are sacrificed. I wouldn't write code this way but I can see how someone would find it valuable.
grayrest··on 55 GiB/s FizzBuzz
> an Advent of Code sized example will not be anywhere close in complexity to your typical CRUD application

Advent of Code size problems is the best case scenario for Python. The difference in implementation time goes down as program size increases because you spend a larger fraction of the time figuring out what you're implementing.

The reason it's not done is mainly social and not technical. Ecosystems matter and this is particularly the case in graphical desktop environments where massive amounts of time and effort are required to re-implement features matching users' expectations (e.g. Flutter).

If we're talking a server side http app server then the library requirements are significantly lower and the libraries are generally there in almost any language. To keep the language comparison the same, it's not significantly slower to implement a CRUD backend in Rust than it is in Python. Depending on your specific setup and how much pre-prep is involved it can be faster. I'm not aware of any framework in a dynamic language that can produce production grade endpoint handlers that are as terse as a Rocket app heavily leveraging request guards. The guards handle validation, conversion, session context and db connection based on the endpoint parameter types so you just write the happy path which is 1-2 lines of code for CRUD.

> speed of refactors and maintainability

Dynamic languages are significantly worse for maintainability and refactoring. I say this as someone who generally gets paid to be a frontend developer and spent years writing both Python and Clojure professionally. Despite my arguments, I do not write server side Rust for work because team coherence is more important for doing my actual job (solving a customer's problem) than programming language and I'm the only person in my company who writes Rust. I've been doing this long enough that I accept the worse solution as the cost of doing business. My personal projects don't have this constraint so perf is orders of magnitude better in exchange for a lot more knowledge and a bit more design work.

grayrest··on 55 GiB/s FizzBuzz
> The overwhelming majority of slow code isn't slow because it's failed to do this kind of microoptimization, it's slow because it used the wrong algorithm.

I disagree. I believe the majority of code is slow because it's written without any consideration at all to performance. I like Casey Muratori's philosophy of non-pessimization where true optmization (measuring, working hot spots) is rare and rarely necessary but massive speedups compared to the general state of the art are achievable by simply not writing code using patterns that are inherently slow. This isn't deep algorithmic stuff it's just avoiding copies and/or pointer chasing.

Edit: https://www.youtube.com/watch?v=pgoetgxecw8 <- Casey's most recent intro to non-pessimization

> For a realistic-sized problem, if you write solutions in C and Python with the same amount of effort from equally skilled programmers, the Python version will almost certainly be faster

The Advent of Code runs every year and I'm not sure about C (not something I track) but there are plenty of Rust submissions and while the Rust submissions take longer to come in, it's not THAT much longer. From memory it's like 2x on a timescale of minutes. The Python programs are not faster.

grayrest··on Egui: An easy-to-use immediate mode GUI
> It isn't really much different than calling them "radio buttons" even though they have nothing to do with radios.

The button set on the face of many dashboard radios would physically pop out the previously pressed button when you pushed a different one in so only one in the set would be selected. The name is pretty obvious if you've used the physical version but I haven't seen one since the 90s.

grayrest··on F# is the best coding language today
> If you’re co-workers aren’t able to work with the types, how can they receive any benefits?

There's plenty of distance between unable to work with types at all and knowing the full breadth of the TS type system. I've worked with plenty of people who weren't enthusiastic about types and this is my way of handling those objections. Even someone who doesn't know/care about types gets the IDE features from the types.

I have yet to have someone persist in sending me lots of any types past two weeks because having your work constantly corrected is embarrassing. I don't expect everybody to care about the type system past generics so if someone wants to write a basic index type instead of the more correct keyof or opts for any over figuring out a conditional intersection type, I'll take care of it in code review. I'd rather have them writing code than reading TS documentation to wrangle advanced types and people do look at the commits when they go in and learn the tricks over time.

grayrest··on Coming to Terms with Tailwind
When I talk about cross-cutting I'm very specifically referring to restricting the values of properties to the ones matching the design system at the CSS language level and not the can I arrange the page to be styled level.

I haven't explained my biases. Perhaps a technicality but I don't consider the reset styles to really be a consideration. They're something set up at the start of a project and not really touched day to day. With the rise of component-based development, I strongly prefer my styling to not be context dependent and so I avoid relying on styles cascading from outside the component aside from the reset styles. Neither of these is required but I think this is relatively common. This leaves the utility/mixin layer in your taxonomy and thus my focus on it.

> existing preprocessors have had such widespread adoption for most of the last decade

I'd mentioned using Sass mixins as my workaround in my initial post. The compile-to-CSS languages have solved the problem but that doesn't mean it's not a weakness in CSS itself.

Despite having the tools to solve the problem, I'm quite confident very few people have. Virtually all Sass/Less use I've encountered outside the Sass online community has been nested selectors and variables.

> most of Tailwind's fans are people who hadn't found themselves working with these concepts before they picked it up.

Yes, this is the primary advantage for most. Most developers do not have a design system let alone come up with the idea to design something to enforce it. I had to derive mine from Bringhurst's Elements of Typographic style, adapt it to every designer I worked with (they're generally familiar with the overall concept, it just doesn't make it to the popular frontend body of knowledge) and then sell the approach to every team I worked with. I ran into utility CSS much later and then only in online articles until Tailwind.

Since you're familiar with the concepts, you won't encounter a lot of new material here but might find some of the details interesting (I mention some specifics below).

> Or maybe there's something else I don't understand about it yet?

Tailwind's scattered/duplicative nature is a good match for people with the biases matching my own. It's largely competing with inline styles, CSS-in-JS, or scoped CSS. The redundancy of setting styles without relying on the cascade is a feature for component-focused uses where they're desired to stand alone for use in multiple places. The comprehensive (i.e. scattered) nature of the utilities allows for a nothing-but-utilities approach. This avoids class name conflicts and specificity issues, which competing approaches were specifically created to address. Psychologically it also keeps people focused on finding utilities (and thus staying in the design system) instead of hacking in their own CSS.

There's less duplication than I thought at first. Recommended coding style uses component-local cascade for things like font or text color and parent shortcut utilities like space, divide, and gap cut down on the really painful duplication.

I do think Tailwind takes their utilities too far. I think the transition/animation, gradient, and transform utilities are ridiculous even if I do respect the effort. Going the other way, the layout options are underwhelming (grid is anemic) and there really isn't anything around handling images. I consider these relatively minor, nit-picking concerns and simply define custom utilities has solved all the issues I've had here.

In my mind, the more substantive argument against it is an only-utility approach completely tramples on the idea of separating markup from presentation. This leads to a lot of edits and workarounds when trying to use a single component in multiple design contexts, which is a general problem for the component-local approaches. Straightforward css-var things like color are easily handled by making custom utilities with css vars in them. There's also a straightforward general solution in the form of @apply in a named class.

Tailwind is gaining popularity because it's a pretty good fit for the space. My current project is my first professional one on Tailwind but I expect to be using it over my own system going forward simply because it largely does the same thing and is an easier sell.

grayrest··on F# is the best coding language today
I'm happy it's working for you well. The map changes were more in the line of changing core maps and then having to update every place they were used. IDEs are amenable to this as long as they can figure out the references. Cursive helped some but most of the work was still manual.

My point of reference between typed and untyped code is primarily with Typescript and Javascript since that's 99% of what separates the two. For what it's worth, I do have 21 years of experience and have been lead on my projects for a number of years. As the lead, I get enough benefit from the type annotations that I've told co-workers to just any type anything they can't get working immediately and I'll fix it in code review. It's enough of an overall team velocity increase and easier code reviews that it's a win.

I'm not trying to argue with your experience. Dynamic languages work fine for building products and Clojure is my favorite dynamic language by a significant margin. I'm sure I'll write more Clojure in the future. I'm just trying to explain the benefits since I had the same mindset 15 years ago and now prefer static types. I'll mention that don't particularly like C# or Java and their type systems are not expressive enough for me to prefer over dynamic language.

grayrest··on F# is the best coding language today
If you're on a project every day and familiar with all the pieces, there's not a large advantage to static typing. Static typing allows people unfamiliar with the program to make changes and have a reasonably high degree of confidence that they got them right. This can be junior devs, people new to the project, you after 5 years away, or a project that's grown to the point where nobody knows all the pieces.

I'm not saying this as a die-hard static typing fan. I wrote Python for years, have written JS professionally most of my career, and spent 2 years writing Clojure professionally. I'm comfortable with dynamic languages. The Clojure codebase was the most stable I've been on (including typed languages) largely due to the senior team and excellent QA. The only problem I had with it was when business shifted from a subscription model to an a-la-carte model, which required manually reworking a LOT of maps to match the new requirements. This is considerably more painful in a dynamic language than it is in a static one.

There IS a downside to static typing in terms of verbosity. I've seen Java codebases where half the code was there basically because of the static typing. More advanced type systems do not suffer from that problem. I'm fine with OCaml / F# / Rust / Typescript.

grayrest··on Coming to Terms with Tailwind
> the only thing I can think of is that what people are complaining about is too many ways to define cross-cutting abstraction

I meant exactly what I wrote. The primary axis for styling is applying a set of properties using a selector. The cross-axis abstraction for providing restrictions on what values the properties contain has not been part of the language for the vast majority of its existence.

> variables and mixins / other apply boosters and even css classes themselves

The only options here that are actually CSS are variables (which are relatively new to the language) and utility classes, which work against the general desire for semantic class names and separating structure from presentation. I'm familiar with the proposals for the others but I'm not aware of them being standardized and I know they aren't supported in any browsers.

There are plenty of reasons to not like Tailwind but I expect most people who do like Tailwind aren't coming off a project with an established design system and method for applying it. I have some complaints about Tailwind's choices but it's a fine set of defaults and has enough customization for me to disable or replace the utilities I don't like.

grayrest··on Are we GUI Yet? The state of building user interfaces in Rust
There are a lot more options but nothing that's clearly winning. The first projects I'd check for building a GUI today are Microsoft exposing the Windows UI toolkit and the Rust+Flutter integration. I know that the GTK crowd were engaged with the Rust core team years ago but I don't know if anything came from that.

I'm still on the DOM-as-the-main-platform train (since 2001, I believe in the Mozilla vision) so I haven't been tracking the details that carefully.

grayrest··on Coming to Terms with Tailwind
> I'm curious if there are Tailwind users out there that could teach me if Tailwind solves other problems I'm not seeing.

I'm building a RAD platform (I hate the term low code) and just pushed through Tailwind as the only method for styling apps and banned custom CSS.

The primary value Tailwind provides is a reasonably well considered design system. I believe CSS' primary weakness is the general inability to define cross-cutting abstractions. I think of the style of an object as a composition of concerns: spacing, position, size, typography, color, decoration, etc. Programming languages have interfaces or traits or protocols to handle this sort of thing but there's no equivalent in CSS. The addition of CSS variables provides limited ability to do this like you can set up a primary color and use that everywhere but CSS variables alone don't let you set up type or spacing scales. I realized this in 2009 and switched over to defining these abstractions as sass mixins that basically boil down @apply with Tailwind utilities where my mixins were the first part of the utility name and the argument(s) the last part. Having a design system simplifies the job of both the designers and developers. There's no guessing on whether it's a 5px or 6px margin, it's a `margin(2)`. Further, if you pick cooperating scales, the page tends to fall into a vertical rhythm, which is tough to do ad-hoc.

Tailwind is an improvement over my self-designed sass mixins mostly because it has more effort behind it and enough people banging on it that it's been expanded to cover a majority of the CSS you need to implement apps. I add a set of CSS-variable based color names to handle theming (`pri` for primary, `sec` for secondary, `ter` for teritary, and `acc` for accent, with `-dark` and `-light` variations) and allow custom utilities for the project. The latter provides an unsupported escape hatch but is enough friction that I'm hoping people won't abuse it excessively.

For my specific use case there are other benefits:

* No specificity issues

* Having to come up with a name for elements is a significant source of friction in a graphical interface

* Naming CSS classes well requires some concept of the overall system and how the element being targeted fits into it. I do not expect my users to have this knowledge.

* I only allow modification of specific points in a component that have a data- attribute containing component-unique names. This will allow me to change the underlying markup and have a fighting chance at successfully migrating custom styles.

* By breaking the link between styling intent and page structure I have the potential to translate apps into non-browser programming environments.

I find Tailwind markup to be quite ugly and think it doesn't have as much advantage in other situations but it fits my specific problem well.

grayrest··on Folk wisdom on visual programming
> So presumably we could learn to distinguish closely packed shapes if we were familiar enough with the conventions.

The data visualization people have already demonstrated this with sparklines and small multiples. There are fewer preattentive attributes than most people would assume so I expect increasingly dense visual representations to approach text (e.g. logograms).

I'll also point out that data viz people have also come up with reasonable solutions to problems mentioned like wire bundling. I haven't seen an auto-layout algorithm I like but I've found a reasonable guess followed by manual manipulation with automatic wire routing to be okay for visualizations and the circuit drawing and VLSI I did 20 years ago in college.

grayrest··on Rally, a novel privacy-first data sharing platform
Is this Mozilla Test Pilot with data sharing with outside researchers?
grayrest··on Ask HN: How to get back in employment market after working on side projects?
I have a tendency to take 6 months or a year off between jobs and the uncertainty around Covid pushed my most recent funemployment round to 18 months. It was also the first time I've had trouble finding work. I tried a bunch of different things, applied for ~30 positions, but posting on the HN Who Wants to be Hired thread in May got me 6 good leads within the week and I had two offers within 4 days. If people ask I tell them the truth: I'm busy when I'm working and not working gives me time to investigate all the weird corners of programming that aren't necessarily commercially viable.
grayrest··on Ask HN: Would Spreadsheets with Lisps be much more powerful?
Every time someone mentions extended spreadsheets I like to bring up Resolver One. In the mid 00s it was a spreadsheet interface in .Net that generated python modules under the hood running on IronPython. As a side effect you could import sections of one spreadsheet into another spreadsheet, go behind the scenes and edit the Python to connect to a DB or run arbitrary code, generate GUIs using the .Net facilities, etc. I thought it was neat. Unfortunately they never got traction and as far as I know they were aquihired by a financial company that used it internally.
← PreviousPage 3 of 23Next →