HN user

jclem

127 karma

Principal engineer at GitHub

https://jclem.net

https://twitter.com/_clem

Posts10
Comments66
View on HN
Octobass 1 year ago

For years, a friend of mine (in San Francisco) and I (in New York City) have sent one another an image [1] of one of these being tuned any time we’re doing coast-to-coast software debugging (especially relevant when we were working on a realtime collaborative text editor).

[1] https://www.loc.gov/item/2014714519/

I grew up in the Midwest, and my father, who went to the University of Kentucky, was fraternity brothers with Ben Gish, and so growing up it was a name that I heard often when he’d tell stories from that time. I remember always being aware that a friend of my father had been framed for burning their family newspaper.

I live in New York City, now, and one evening found myself sitting at a bar in Brooklyn where my roommate, the bartender, was closing around 3am (at the time I worked a very late shift at the 24 hour Apple Store). The normal patrons had all gone, and myself, my roommate, and another man I’d never met were locked in having a last couple of beers while my roommate closed up. I had a long conversation with the man I hadn’t met before that eventually turned to where we grew up. It turned out that this man was Ray Gish (also mentioned in this article), the younger brother of Ben. Ray even recognized my father’s name, because Ben had mentioned him before.

Ray invited my roommate (whom he already knew well) and I over to his place for a last drink, and I vividly remember him playing “Street Hassle” by Lou Reed on his record player. It was the first time I’d ever heard that song.

Anyway—wildest coincidence that has ever happened to me. I see and say howdy to Ray every now and then when I find myself in that part of Brooklyn—one of the most genuine people I’ve ever met.

You can reduce with list comprehensions in Elixir, but it's uncommon to see:

    sum_list = fn list ->
      for item <- list,
          reduce: 0,
          do: (sum -> sum + item)
    end

    sum_list.([1,2,3])
Other comments are correct that `Enum.reduce/2` is probably better:
    Enum.reduce(list, &(&1 + &2))
Obviously you don't have the flexibility / mutability you refer to in other comments with either of these, but you can always put more in your accumulator:
    get_sum_and_update_count = fn list, map ->
      for item <- list,
          reduce: {0, map},
          do: ({sum, map} -> {sum + item, Map.update(map, item, 1, &(&1 + 1))})
    end
(A contrived function that returns a list sum and an updated map with the count of the values found in the list)

It seems worth noting that the input of gte-small is limited to 512 tokens. The tokenizers for sure aren’t the same, but I imagine this is significantly less than ada-002, whose input is limited to 8191 tokens. That said, I don’t imagine that embedding huge full documents is necessarily the right approach.

I would love to see a comparison for some typical use cases using various methods of chunking input documents.

Hello from slightly further south on Vanderbilt Ave :) I haven't tried that Indian place yet, but it's on my list, now. The pizza and bagels threw me off (not because "Indian == bad bagels/pizza", but because "somewhat random assortment of foods" is sometimes a red flag).

First, let's replace "gushing" with "discussing", because that's what was happening. I'm not sure "got bad during part of the pandemic, now is improving again" counts as gushing.

In what way is caring about your local food options in your immediate neighborhood, on the street you live, where your friends and acquaintances eat, drink, and work "very Brooklyn"? I guess if you live somewhere that restaurants just appear and have faceless owners with employees you'll never know, this isn't a thing. This is something discussed by really anyone who is interested food and restaurants in their area all over the world. If you like what a person did at one restaurant, you may like what they do with a new one. Or, maybe it's noteworthy when only the first one is great, and the subsequent ones are mediocre.

Maybe you mean Vanderbilt Ave? Vanderbilt St has no commercial zoning.

What many people don't know is that 3 of the pricier restaurants on Vanderbilt Ave are all actually the same restaurant group. Their background is partially the 3-Michelin star Alinea in Chicago via chef Greg Baxtrom. Olmsted was first, then came Maison Yaki, and then Patti Ann's.

Olmsted is mostly very good (started great, then got bad during part of the pandemic, now is improving again), but you can still joke about being sold $8 vinegar from them for sure, haha. However, since "midwestern" cuisine is now becoming somewhat trendy, jokes about expensive port wine cheese balls at Patti Ann's ($12) may be more appropriate.

An LWW register is most certainly a CRDT, it just has limited use. I think you’re making a good point about how one must be careful applying CRDTs, but I don’t think it’s accurate to say that a suboptimal merge strategy in terms of user experience means that something does not meet the definition of a CRDT.

In other words, the “conflict-free” part of the term refers to the fact that all replicas converge on the same value when all updates have been exchanged. What you’re discussing seems to have more to do with concerns around intention preservation when using CRDTs. In other words, an LWW register on a text field is still a CRDT, but in many applications it is potentially a poor choice in terms of preserving the intent of user-generated operations, but determining this is something done in a case-by-case basis.

If the content is a long document which users collaborate on over time, then a register is most certainly a poor choice. If it is a short text field akin to a label, an LWW register isn’t necessarily bad, because user intent is likely to replace the entire value, rather than to perform minute edits on the value.

It’s hard to get a sense from the site or from the actual idea pages what the goal is. Removing the BQE (https://transformyour.city/vision/new-york-city/the-bqe ) would affect millions of people and businesses, and simply saying “transform it into a linear park” comes across as incredibly naïve. I would feel foolish signing this petition because…what’s the actual plan?

Sure, maybe there is some way to do it with a multi-decade effort, an enormous cost, and a fundamental shift in NYC’s layout and even economy, but something about how MASSIVELY oversimplified the statement “Remove the BQE” is makes it hard to take this seriously.

I applaud the sentiment, though! And I hate the BQE.

Edit: Also just to be even clearer for anyone not familiar with NYC geography: the BQE is a stretch of interstate highway 278 that connects Brooklyn and Queens.

This isn’t the High Line, built from a disused rail line. It’s proposing removing a stretch of interstate and putting a park in its place.

Edit 2: Ok, apparently the goal is to gather signatures and then show elected officials. The minimum bar appears to be 100 signatures. I have a hard time understanding what outcome is expected when an elected official in NYC is shown a petition in which 100 people say we should rip out part of the interstate (and one of NYC’s most important stretches of road) and put in a park.

While “Arcadia” is likely of greatest interest to HN readers of all of Tom Stoppard’s plays, I also highly recommend “Jumpers” and “The Hard Problem.”

Also worth noting the many excellent films he wrote, like “Brazil” and “Empire of the Sun.”

Disclaimer: I like Railway.

Heroku VMs had the kitchen sink, and I miss that with Railway. A pretty standard Phoenix app with Phoenix’s built-in auth doesn’t build and the user is presented with build errors about nixpacks. Now there’s a good deal I have to learn just to get bcrypt to build.

1Password “forces” (strongly suggests to) you to physically print a recovery kit with both your master password and secret key on it. I keep mine in a safe deposit box in another part of the city. Of course, losing access to this box is a concern, but ¯\_(ツ)_/¯ I suppose I could also bury it somewhere remote too without the QR code or my identifiable information in it, or mail a copy to a family member.

Layout and paint.

I don’t think using the term “rendering” for interpolating data into a template is anything new, though, nor is it bad or even confusing that it means one thing in the context of computer graphics and another in the context of programming language templates. ¯\_(ツ)_/¯

I am curious what the difference is in property value and general perceived desirability between external-facing and internal-facing apartments in these superblocks in Barcelona.

Ah, one of the bugs with Slate was with spell-checking. On mobile Safari, at least, its text nodes aren’t marked by spell check unless they’re interacted with by the user after they’ve been typed.

As I’d said, they all have bugs, including ProseMirror. I just found that PM solved most of the ones I cared about relatively well.

Last I evaluated them, they had some bugs that wouldn’t work for my use case. For example, Quill has the annoying bug on mobile Safari of blocking the native behavior of capitalizing the first letter of a new line.

I don’t remember what I found in Slate, however, and it’s possible it may be much better now.

One light-microsecond is about 300 meters, this must be milliseconds.

Edit: Just saw that this was already pointed out. Apologies, didn’t mean to pile on.

Seconding ProseMirror [1] as the least buggy editor implementation on top of contenteditable I’ve seen yet. It also supports JSON serialization and has plenty of support for complex custom pieces of content in the document.

The ProseMirror API is quite low-level-feeling for many use cases, however, and TipTap [2] is doing a good job of building a friendlier wrapper around it.

That said, neither of these are perfect and there are bugs here and there, especially on mobile devices, but they’re better than any other solution I’ve seen so far.

[1] https://prosemirror.net/

[2] https://tiptap.dev/

Music Grid 6 years ago

This is neat! Cool to encode the state in the URL, but it’s better to use replaceState rather than pushState for this. I don’t typically want every single change I make to add an entry to my browser history.

This is against a Heroku hobby server. Latency is very low, as I’m on the East coast where I believe this server is.

Using LiveView, of course, requires taking round trip latency for your users into account. It currently won’t work well for some use cases where optimistic UI updates may help hide some latency. I think I read something about there being some optimistic updating in the works for LiveView, though, long-term, but I’m not sure how it’ll be done.

There’s more than one field here, it’s just not discussed in the post. The title is a separate form field that is validated and updates live on every change event. `phx-change` gives me the whole form state, which is what I wanted.

Thanks!

It’s parsing the entire Markdown content on each key press right now, which is definitely suboptimal for a product but fine for my needs.

It should certainly be possible to make this more efficient by either doing some smarter diffing of the in-progress document or using an operation-based update mechanism.

LiveView doesn’t yet have event debouncing built in, but it’s in the works, I believe, and that would help, as well.

That said, it’s currently fast enough writing a post of this length that while writing, I notice no significant lag in the live updates. By the time I stop typing and look at the preview, it’s up to date.

I have always wanted to be able to write Alfred workflows exclusively in a text editor. In order to do that, I built Alpaca, a compiler for Alfred workflows.

Instead of using the Alfred GUI for authoring workflows, an Alpaca project defines the workflow in an "alpaca.yml" file, and then the Alpaca command line interface is used to compile the project to a working Alfred workflow.

Only a tiny bit of Alfred functionality is implemented at this point, but I wanted to release something simple for v1.

From what I remember, we did look at it some, but I can't remember many specifics, unfortunately. Looking at it now, I think that it wouldn't give us some of the flexibility that we want—for example, TOML arrays can only contain values of a single type, and for the sake of brevity, there were places in our configuration where we wanted to allow you to, for example, pass either a shorthand string or an object.