Hacker News new | past | comments | ask | show | jobs | submit | nfrmatk's comments login

In truth, that's exactly what it is. My point in writing this wasn't to say "Ooh, look at Rust being so much better". The original PHP is wonderful and there is definitely something lost in a Rust translation. Other things gained as well. ¯\_(ツ)_/¯

This blog post is just a personal journey winding through the thought process it took to replicate that PHP in Rust, something I did because I thought I might learn something.


https://tuckersiemens.com Just a log of my personal journey through tech. I don't post much, maybe once a year, but I have fun maintaining it.


I think Gary Bernhardt's corresponding Boundaries conference talk [1] is quite good, particularly because of how pragmatic he is in introducing the topic.

I have been thinking about and trying to work with this paradigm for a few years now. To be honest, it's been a struggle. Partly because it requires unlearning some habits and partly because there's limited opportunity to practice in my $DAYJOB where I'm working in codebases heavily invested in other paradigms.

I've seen and read many, many videos, blog posts, etc. on this topic. Everyone loves to introduce the concept with a contrived example and then stop there. What I would love to see more of are complete examples for everything from simple to complex applications.

I think there's potentially a lot of value in thinking this way (or at least taking as much from it as you can), but it's hard to learn and then to teach others without more examples to draw on.

[1]: https://www.destroyallsoftware.com/talks/boundaries


I've used this for many real applications that I would characterise as small (biggest being ~10KLOC excluding tests, types, etc.). I've applied the pattern across entire codebases and to specific components within much larger codebases which follow other patterns. I tend to combine it with some of the ideas in Mitchell Hashimoto's talk Advanced Testing with Go[0] - particularly small interfaces and defining test stubs alongside real implementations.

In practice my imperative shell tends to have two layers. The inner layer is responsible for executing the imperative logic, while the outer layer is responsible for initialising configuration and dependencies, invoking the inner layer, and adhering to any sort of external interface that it may need to satisfy. Everything from the inner layer down through the functional core can be comprehensively tested using stub objects only -- no need to patch anything.

Unfortunately everything I've applied this pattern to is proprietary, so I can't share any code examples.

[0] https://www.youtube.com/watch?v=yszygk1cpEc


I also did it for a Go app recently exactly like that.

It was mostly about putting the "imperative" part closer to main.go and putting business rules and things like that in the other files: Routing, serialization, validation, business rules, data transformation, command line argument parsing, configuration parsing, they all go in the "functional" part. Instantiating the HTTP server, reading argv, files and reading/writing to the database goes in the "imperative" part.

The major hurdle for me is frameworks and libraries that often want to be used in an imperative way. Some routers, for, instance could be purely functional, but they often want to instantiate the HTTP server themselves. Not a big issue in practice in Golang, though.

Also: the database. To keep purity in a simple way, you gotta wrap the imperative parts and use callback-ish structures. This part is often where I cheat. But with a proper abstraction it's great. I hate to say the forbidden word here, but a "monadic" abstraction you can have your cake and eat it. I never did it in Golang and I have no idea whether it would work, but, I did it in C# and it was a breeze.

I agree with your assessment about testing. In the end it was incredibly easy for me to get 100% coverage on the functional part.


Would love to see an example of your monadic database abstraction


If you're familiar with Node.js promises, you already know how it works. I just pass a hollow "DB" object to my controllers that can perform queries and commands, but instead of returning data imperatively, I use JS-like "promises" to chain the next steps. On the "success" callback you have the result of queries. At the end I will just return this "chain of statements" that wasn't executed yet. I only really run everything at the "imperative" layer, within a database transaction.

  return DB.Query(...).ThenCommand(res => ...).ThenHttpSuccess(res => ...);
That's also similar to how Haskell IO works. If you desugar the "do" syntax, you get something like this. Of course I said "monadic" between quotes above because it doesn't follow the functor/monad laws, it's just a Fluent interface promise-thing tailor-made for that very small app.

A big issue is that this was in very small project. Promises are not exactly pretty, and the code is not the easiest to maintain if you don't know how they work, which is why I "cheated" on the Golang app. I think someone else smarter might be able to figure this problem out too, though :)


> In practice my imperative shell tends to have two layers.

Doesn't that boil down to a hexagonal design, ports & adapters, that is also mentioned at the end of the Boundaries video?


In case you haven't seen it already, Cliff Biffle's "Learn Rust the Dangerous Way" might be of interest to you.

https://cliffle.com/p/dangerust/


https://tuckersiemens.com

I try to keep it simple, HTML, Sass (but really just vanilla CSS), and no JS. I generate the site with Zola (https://www.getzola.org/), which has been fantastic. Nothing fancy here, probably write a post once a year, but I have fun doing so.


Congrats to the release team! I'm really excited to work with the new structural pattern matching. This feels like the biggest language change since the addition of async/await.


Personally, I'd say it's worth it now. I've been dabbling in Rust for a few years and while I still don't get to use it at $DAYJOB it's been a huge benefit to me. Those "esoteric" concepts have bled into other languages and my usage of them, making me a better programmer overall. Read a chapter of "The Book" once a month or so over the next 3 years and I wager you'll find yourself in a better place than had you waited 3 years to start.


After doing a couple of projects with it, I have found that learning Rust is an exercise in futility. I wish I had never heard of Rust. What will happen is you'll immediately recognize it as the greatest language ever invented and you'll want everyone else to know about it. You will try to convey what it is about Rust that makes all other languages obsolete, but they will look at you like you're a crazy person. You will be ostracized and considered a lunatic. You will lose all your friends. They will say you are part of a cult now and you will eat your lunch at a separate table. You have seen nirvana and will never be satisfied again with doing your old Python or JavaScript job. After doing a few projects in Rust, yet unable to convince your non-programmer managers why they should convert to it, doing your old job no longer brings the joy it once did. You will stop shaving and grow a long beard. Because using non-Rust languages is basically the same as living in the past. The world has lost all its color. The future is Rust, and yet the business world is too conservative, or too afraid, or too incurious to make the leap. This is how I feel about learning Rust right now.


Sounds like everyone I've known that learned Lisp or Erlang or Haskell.....


I can relate, i learned React in tandem with ReasonML. The first job working with TypeScript felt like watching paint dry. Awesome languages can spoil you.


This is my life as a Svelte developer.


Nice advice!! Would definitely start learning it from this year itself.


Personally, I reserve "clickbait" for links with no substance or value on the other side of the click, but I understand what you mean.

Yes, the intent of the title is to get your attention, but I'm not trying to get you to buy anything, collecting or selling user data, etc.

I really just wrote the post to share a debugging experience I had this year. It doesn't have to do with IPv{4,6} addresses themselves or any specification thereof, but it does relate to the Python 2 `ipaddress` library's handling of them and a pitfall you can accidentally find yourself in.

A dry, but more accurate title might have been

> Python 2's ipaddress library considers "node.example.com" an IPv6 Address


Is this an intentional troll? The post explains why those results are meaningless in this context.


I generally agree that the web could be simpler. A lot can be accomplished with just plain ol' HTML/CSS nowadays. I think there's a kernel of truth in what you're saying about apps vs. websites.

That said, how would you propose to do syntax highlighting instead of

> just a wall of <div>s and <span>s, for every single visible character

? Rather than being a wall, it looks to me like it's actually a tree of <divs> and <span>s for every line and every _token_.

I think the author has used Prism[1], so I assume the highlighting was done client-side, but even if you were to do the task server-side I think you'd end up with similar HTML/CSS, no?

What would be a better approach to solving the same problem?

[1]: https://prismjs.com/


From the WhatCMS, author uses Gatsby, assume no trace of Prismjs is used.


Gatsby doesn't offer a syntax highlighter out of the box. It has markdown (and MDX) components that generate pages, and those in turn can have syntax highlighting plugins. AFAICT prismjs indeed is the predominant one used by Gatsby sites (at least, in mine). But thanks to SSR prismjs will typically run at compile time.


Hey, OP/author here, I do use prismJS under the hood, a flavor of it: prism-react-renderer, so it might indeed remove the traces of Prism.

Agree that it's a mess of div and spans, but it does the job.


> how would you propose to do syntax highlighting

Of course you'd use spans to do syntax highlighting, just like you'd use JavaScript to do interactivity. You know what the commenter means–using these in places where they aren't necessary at all.


The commenter specifically used that tree of spans as an example of the horrible mess that is modern HTML. So it is necessary here to deliver the feature, and I think the broader point is that we might see a mess in the DOM inspector, but it is a requirement to deliver certain modern features in a productive way.


Like normal text on a page? No. For one very specific thing that it's useful for? Of course. If it wasn't useful for something it wouldn't exist, the issue is using it for things that it has no reason to be used for.


The code snippet seems like the only part where individual words are wrapped in their own divs or spans. It's not true that the whole article is like that. It seems like the article has reasonably semantic html elements present, just with minified CSS classnames and maybe a couple extra wrapping divs at the top.


I'm not the one who called out this site, and this one "OK" with its semantic HTML for the article content (though outside of that it has a bit more soup than it probably needs). It does render a bunch of stuff with JavaScript though so that's not great :(


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: