<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: uryga</title><link>https://news.ycombinator.com/user?id=uryga</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Thu, 16 Apr 2026 18:19:02 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=uryga" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by uryga in "Learn how modern JavaScript frameworks work by building one"]]></title><description><![CDATA[
<p>> AFAIK there's no magic to React.memo. It's basically a shorthand for useMemo that takes the props as the dependency.<p>Pedantic note: this isn't quite true. memo() also allows a second `arePropsEqual` argument that useMemo doesn't have. Also, memo() compares individual prop values, while useMemo() can only look at the whole props object (which would be "fresh" on every render -- it's a diffferent object, even if it has the same values). So it's not like you can easily reimplement memo() via useMemo(). But of course, conceptually they are pretty close :)</p>
]]></description><pubDate>Mon, 04 Dec 2023 11:34:19 +0000</pubDate><link>https://news.ycombinator.com/item?id=38516030</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=38516030</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=38516030</guid></item><item><title><![CDATA[New comment by uryga in "Making sense of React Server Components"]]></title><description><![CDATA[
<p>how exactly is there "money to be made" here for the React team?</p>
]]></description><pubDate>Fri, 08 Sep 2023 18:47:02 +0000</pubDate><link>https://news.ycombinator.com/item?id=37437709</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37437709</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37437709</guid></item><item><title><![CDATA[New comment by uryga in "Making sense of React Server Components"]]></title><description><![CDATA[
<p>> Why did they not include other companies<p>AFAIK: the initial stages of the project involved Vercel and Shopify [edit: and Gatsby]. these companies maintain frameworks and hosting solutions for them, which makes them good partners to work on full-stack features like this. notably, the convention ("use client") came about based on early feedback from Shopify.<p>the reason to work with framework authors first is that RSC requires a high degree of coordination/wiring across client code, server code, and the bundler. React itself only implements a couple of low-level primitives that need to be wired together by something like a framework to actually do anything useful<p>> expecting all third-party packages, React-related or not, to buy into the "use client" directive<p>AFAIK: non-react code has no reason to care about this directive. and on the react side, couldn't you make the same complaint about most breaking changes?</p>
]]></description><pubDate>Fri, 08 Sep 2023 17:30:48 +0000</pubDate><link>https://news.ycombinator.com/item?id=37436655</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37436655</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37436655</guid></item><item><title><![CDATA[New comment by uryga in "Making sense of React Server Components"]]></title><description><![CDATA[
<p>> But their routing things locks you into NextJS as a framework.<p>I'm confused by this -- how is a framework supposed to offer routing in a way that <i>doesn't</i> "lock you in"? are you "locked into" React Router if you use that? what's the alternative?<p>> RSC locks you into [Vercel's] hosting solution<p>how? you can self-host it if you want.</p>
]]></description><pubDate>Fri, 08 Sep 2023 17:13:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=37436392</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37436392</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37436392</guid></item><item><title><![CDATA[New comment by uryga in "Making sense of React Server Components"]]></title><description><![CDATA[
<p>> I would like to write a component, not have to think about where it is running in most cases<p>you can keep doing this, just put "use client" in the file, Next will SSR them just like it used to. (SSR is an "emulated client" in this model. admittedly, the naming is a bit confusing)<p>but for some things, you want a guarantee that it <i>only</i> runs on the server, and then you can use server components :) i believe this is also why useState & friends are disallowed there -- they fundamentally don't make sense for stuff that'll only ever run server-side.</p>
]]></description><pubDate>Fri, 08 Sep 2023 17:07:05 +0000</pubDate><link>https://news.ycombinator.com/item?id=37436314</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37436314</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37436314</guid></item><item><title><![CDATA[New comment by uryga in "Making sense of React Server Components"]]></title><description><![CDATA[
<p>> zero functionality has been removed from class components<p>yes, exactly!<p>> They use them because they are idiomatic React<p>right, and do you think it'd be easy for a feature to become idiomatic if it wasn't an improvement over the previous patterns?</p>
]]></description><pubDate>Fri, 08 Sep 2023 16:53:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=37436133</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37436133</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37436133</guid></item><item><title><![CDATA[New comment by uryga in "Waku: The Minimalist React Framework with Server Components"]]></title><description><![CDATA[
<p>have you seen <a href="https://vite-plugin-ssr.com/" rel="nofollow noreferrer">https://vite-plugin-ssr.com/</a> ? i've only browsed their docs, but AFAICT the pitch is that it's a more DIY approach to a framework, where you keep a lot of control over how things are wired together.</p>
]]></description><pubDate>Mon, 28 Aug 2023 02:03:53 +0000</pubDate><link>https://news.ycombinator.com/item?id=37288817</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37288817</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37288817</guid></item><item><title><![CDATA[New comment by uryga in "Waku: The Minimalist React Framework with Server Components"]]></title><description><![CDATA[
<p>> Apps (as in, mobile apps) cannot be rendered on the sever<p>yes and no. sure, you can't do standard SSR like for websites. but i've seen a number of spins[1] on "Server-driven UI", meaning "server defines the app views as a big blob of JSON". usually, it's payload looking something like this:<p><pre><code>  [
    { "type": "Heading", "text": "Our cool products" },
    { "type": "List", "children": [
      { "type": "ProductCard", "id": 123, },
      { "type": "ProductCard", "id": 456, }
      ...
    ] }
  ]
</code></pre>
the app "interprets" this and displays the corresponding components in the specified arrangement.<p>the kicker is that, in a sense, RSC is just a less ad-hoc way to do this kind of thing! instead of `type` tags you get "client references", React handles the relevant parsing/serialization, and a lot of other good stuff on top. it's also quite seamless w.r.t writing components -- react does a very good job of abstracting away all the serialization business. and importantly, you can have an actual ecosystem of RSC packages around it, which a bespoke in-house method of doing this won't have.<p>now, RSC for react native has barely even been <i>teased</i>, but i'll bet good money that they have at least a prototype somewhere. and yeah, of course this would require your app to be in React Native. but that's the selling point -- IF all your stuff is in react, you get a bunch of power and some good DX.<p>---<p>[1] some examples off the top of my head:<p>- Facebook (not public, described by an employee): <a href="https://twitter.com/acdlite/status/1632217463772393473" rel="nofollow noreferrer">https://twitter.com/acdlite/status/1632217463772393473</a><p>- AirBnb: <a href="https://medium.com/airbnb-engineering/a-deep-dive-into-airbnbs-server-driven-ui-system-842244c5f5" rel="nofollow noreferrer">https://medium.com/airbnb-engineering/a-deep-dive-into-airbn...</a><p>- a Polish site called allegro.pl, though I can't find the conf talk about it right now...</p>
]]></description><pubDate>Mon, 28 Aug 2023 01:44:38 +0000</pubDate><link>https://news.ycombinator.com/item?id=37288691</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=37288691</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37288691</guid></item><item><title><![CDATA[New comment by uryga in "Idris 2 0.6.0 is now available for the JVM"]]></title><description><![CDATA[
<p>> TypeScript is a little unique in that its core type system is much more structural than nominal (<i>even more so than Haskell</i>)<p>I'm a bit confused by the point about Haskell here -- IME Haskell's type system is pretty strictly nominal, not a lot of structural typing there</p>
]]></description><pubDate>Mon, 27 Feb 2023 12:33:48 +0000</pubDate><link>https://news.ycombinator.com/item?id=34955655</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=34955655</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=34955655</guid></item><item><title><![CDATA[New comment by uryga in "Oxide builds servers as they should be [audio]"]]></title><description><![CDATA[
<p>thats what the rack is for duh</p>
]]></description><pubDate>Sun, 10 Jul 2022 06:22:33 +0000</pubDate><link>https://news.ycombinator.com/item?id=32042314</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=32042314</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=32042314</guid></item><item><title><![CDATA[New comment by uryga in "Revisiting the principles of data-oriented programming"]]></title><description><![CDATA[
<p>good luck! it's quite fun :)<p>another term that might be useful is "GADT" - it's kinda like a weaker form of DT, more easily expressible in, uh, normal languages. the C# one i linked is really more like a GADT, bc it all stays at the type level w/o bringing "normal" values into it. another way to do it would be a sealed class with a private constructor + static methods:<p><pre><code>  class Foo<T> {
    private Foo(...)
    static Foo<int> Bar() { ... }
    static Foo<string> Zap() { ... }
  }
</code></pre>
(or sth like that, i don't really do C#!)<p>so that way you can have the type param and use it to track something, but limit what can be put there - in this case, only int or string. type-safe syntax trees are a common case for sth like this (though in that case you'd probably go for an abstract base + subclasses, like in the link).</p>
]]></description><pubDate>Sun, 26 Jun 2022 18:07:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=31886311</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=31886311</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=31886311</guid></item><item><title><![CDATA[New comment by uryga in "Revisiting the principles of data-oriented programming"]]></title><description><![CDATA[
<p>i haven't used scala, but from the looks of it, yeah, "path-dependent types" are a narrow subset of full dependent types, intended for stuff like this exact use case :D<p>there's things you can do to track list length at the type level, but it usually involves putting your data in a special-purpose linked-list thingy: <a href="https://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#vectors" rel="nofollow">https://docs.idris-lang.org/en/latest/tutorial/typesfuns.htm...</a><p>(the `S` and `Z` refer to peano-style natural numbers)<p>although if you go that way, you can actually get a lot of that without dependent types! here's an example i found of someone doing a similar construction in C#: <a href="http://www.javawenti.com/?post=631496" rel="nofollow">http://www.javawenti.com/?post=631496</a><p>last but not least, in TS you can use the builtin support for arrays as tuples and just do:<p><pre><code>  type AtLeastTwo<T> = [_1: T, _2: T, ...rest: T[]]
</code></pre>
which looks very nice, but it's pretty much only doable because the type system has specific support for array stuff like this, so not a really general solution.</p>
]]></description><pubDate>Sun, 26 Jun 2022 13:10:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=31883569</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=31883569</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=31883569</guid></item><item><title><![CDATA[New comment by uryga in "Revisiting the principles of data-oriented programming"]]></title><description><![CDATA[
<p>while you probably <i>can</i> do this with dependent types, i'd imagine GP means something along the lines of typescript's structural typing, i.e.<p><pre><code>  const post = {
    id: 123,
    content: "...",
    published: true,
  }
  // TS infers the type of `post` to be an unnamed "map-ish" type: 
  // { id: number, content: string, published: boolean }
</code></pre>
JS objects are map-like, and this one is "heterogenous" in that the values are of different types (unlike most maps in statically typed langs, which need to be uniform). this just "structural typing", the easier way to do stuff like this.<p>now, dependent types allow you to express pretty much arbitrary shapes of data, so you can do heterogenous collections as well. i haven't read about it enough to do a map, but a list of tuples (equivalent if you squint) is "easy" enough:<p><pre><code>  [
    ("id", 123),
    ("content", "..."),
    ("published", True),
  ]
</code></pre>
in Idris, you could type it as something like this:<p><pre><code>  -- a function describing what type the values of each key are
  postKeyValue : String -> Type
  postKeyValue k =
    case k of
      "id" -> Int
      "content" -> String
      "published" -> Bool
      _ -> Void  -- i.e. "no other keys allowed"
  
  -- now we're gonna use postKeyValue *at the type level*.

  type Post = List (k : String ** postKeyValue k)

  -- "a Post is a list of pairs `(key, val)` where the type of each `val` is given by applying `postKeyValue` to `key`.
  -- (read `**` like a weird comma, indicating that this is a "dependent pair")
</code></pre>
more on dependent pairs:
<a href="https://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#dependent-pairs" rel="nofollow">https://docs.idris-lang.org/en/latest/tutorial/typesfuns.htm...</a><p>in general if you want to learn more about DT's, i'd probably recommend looking at a language like Idris with "native support" for them. backporting DT's onto an existing typesystem usually makes them much harder to read/understand that they actually are (and don't get me wrong, they're mindbending enough on their own).<p>if you don't want to bother with that, i'd look at Typescript - it's combination of "literal types", "type guards" and "function overloads" can get you some of the power of DT's. see this article for some examples: <a href="https://www.javiercasas.com/articles/typescript-dependent-types" rel="nofollow">https://www.javiercasas.com/articles/typescript-dependent-ty...</a></p>
]]></description><pubDate>Sun, 26 Jun 2022 11:16:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=31882896</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=31882896</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=31882896</guid></item><item><title><![CDATA[New comment by uryga in "Revisiting the principles of data-oriented programming"]]></title><description><![CDATA[
<p>they allow as many operations as you need, just pass in a "method name" :)<p><pre><code>  const p = Point(3, 5)
  p('getX') // 3
  p('up', 11)('toString') // "Point(3, 16)"


  const Point = (x, y) => (method, ...args) => {
    switch (method) {
      case 'getX': return x;
      case 'getY': return y;
      case 'toString': return `Point(${x}, ${y})`
      case 'up': return Point(x, y+args[0]);
      // ...
    }
  }
</code></pre>
(unfortunately statically typing this statically requires... some work, either sth like [typescript overloads + literal types] or full on dependent types)</p>
]]></description><pubDate>Sun, 26 Jun 2022 10:23:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=31882603</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=31882603</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=31882603</guid></item><item><title><![CDATA[New comment by uryga in "RFC: Intent to Ship React 18"]]></title><description><![CDATA[
<p>> 'useSyncExternalStore()' -- Gack!<p>> Now...that "little" it's-not-a-framework-it's-a-library whose scope is supposed to be confined to just the "view" part of MVC (by which I mean: "React") is inserting it's tentacles [...] into the _model_.<p>useSyncExternalStore doesn't care about what you do in your model. it's for connecting your view to your model in a way that doesn't give you inconsistent states when concurrent-rendering-funkiness happens.<p>you could even say that useSyncExternalStore exists <i>because</i> React maintainers want people to be able to use whatever state-manager they want (instead of useState/useReducer/whatever) -- uSES was necessary to enable that in 18.</p>
]]></description><pubDate>Thu, 24 Mar 2022 21:26:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=30795540</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30795540</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30795540</guid></item><item><title><![CDATA[New comment by uryga in "Go 1.18"]]></title><description><![CDATA[
<p>are there any languages that do this? Rust's `?` is similar but the propagation is explicit</p>
]]></description><pubDate>Wed, 16 Mar 2022 09:16:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=30696765</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30696765</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30696765</guid></item><item><title><![CDATA[New comment by uryga in "Go 1.18"]]></title><description><![CDATA[
<p>> But where they really shine, like in the mapping example, isn't possible in Go.<p>oh yeah, definitely! Go's version of EaV with multiple returns is pretty lackluster compared to a proper Result type. afaict it's kind of "the worst of both worlds" -- all of the boilerplate of plumbing errors manually w/ none of the benefits.</p>
]]></description><pubDate>Wed, 16 Mar 2022 09:09:49 +0000</pubDate><link>https://news.ycombinator.com/item?id=30696727</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30696727</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30696727</guid></item><item><title><![CDATA[New comment by uryga in "Go 1.18"]]></title><description><![CDATA[
<p>> But I also don't know any languages where errors _aren't_ values<p>(look, i know you understand how exceptions work, please bear with me)<p>yes, Exception objects are technically values, but you don't return them to the caller; you throw them to the, uh, catcher. basically, you get a special, second way of returning something that bypasses the normal one! but in the EaV approach, errors just are returned like every other thing.<p>the uniformity of EaV comes in handy when doing generic things like mapping a function over a collection - don't have to worry if something will throw, because it's just a value! and that lets you go to some pretty powerful places w.r.t abstraction: see e.g. haskells `traverse`.<p>but yeah, EaV needs some syntactic sugar to reach ergonomic par with exceptions, otherwise you get if-err-not-nil soup :P</p>
]]></description><pubDate>Wed, 16 Mar 2022 00:19:38 +0000</pubDate><link>https://news.ycombinator.com/item?id=30693693</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30693693</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30693693</guid></item><item><title><![CDATA[New comment by uryga in "Go 1.18"]]></title><description><![CDATA[
<p><a href="https://en.m.wikibooks.org/wiki/Haskell/do_notation" rel="nofollow">https://en.m.wikibooks.org/wiki/Haskell/do_notation</a><p>rough analogy: `await` replaces `.then()`, do-notation replaces `.flatMap()`</p>
]]></description><pubDate>Tue, 15 Mar 2022 23:32:19 +0000</pubDate><link>https://news.ycombinator.com/item?id=30693349</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30693349</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30693349</guid></item><item><title><![CDATA[New comment by uryga in "Go 1.18"]]></title><description><![CDATA[
<p>distinguishing `Some(null)` and `None` is often considered a <i>feature</i> of Optional ;)<p>to use a tired example: when getting a value out of a map via some `myMap.get(key)`, you may want to distinguish
"not present" = `None`
and
"present, with value null" = `Some(null)`<p>the right solution is to just not have nulls in the first place, then there's no problem ;)</p>
]]></description><pubDate>Tue, 15 Mar 2022 23:22:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=30693267</link><dc:creator>uryga</dc:creator><comments>https://news.ycombinator.com/item?id=30693267</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=30693267</guid></item></channel></rss>