You are viewing archived messages.
Go here to search the history.

Felix Kohlgrüber 2025-04-02 12:59:52

Hi!

it's been a long time since I posted in this group (almost 5 years, wow!). Life changed on my side (working full-time jobs, having kids, ...) but I still tried to follow what's going on occasionally. Thanks a lot to Mariano Guerra for the newsletter, it's the perfect digest for me to read whenever I have some spare time.

I've recently started using Obsidian and it's working great for me to collect and organize all kinds of thoughts. I've used quite a few tools for this over the years, but Obsidian is my new favorite. I'm sure it's been discussed here already, but here's what I love about it:

  • based on markdown files instead of some proprietary formats
  • great apps for desktop and mobile
  • effortless e2e-encrypted sync between devices
  • linking between files / pages and following those links is easy. I'm using a variation of a Zettelkasten (this link can be useful as a starting point; I can write about my approach if there's interest in it)

I'm currently trying to collect my FoC ideas, projects and thoughts into my Obsidian and therefore wanted to see my contributions to this community. I used the Archive tool by Kartik Agaram and it's been working great. A simple long webpage and Ctrl-F worked beautifully, probably better than what Slack Pro could have given me. Thanks a lot for creating the archive, Kartik!

Going back in time was very interesting. One thing I noticed though was that quite a few links that we discussed at the time sadly don't work anymore. With the help of the wayback machine, I was able to still access all the info though. This made me once again appreciate the wayback machine and its importance for the internet. Feels like a donation to the project is overdue.

That's all I wanted to share. Have a great day folks :)

Kartik Agaram 2025-04-02 14:53:46

I've been thinking about color, and I don't know anything about it.

I'd really like my hypertext browser to allow people to adjust color, but without ever compromising contrast. Is there some color space/model like rgb/hsl/CIELAB/Lch that allows you to adjust an author foreground color relative to an author background color, yielding new reader foreground and background colors that maintain the original level of contrast? Ideally I want a single spectrum/dimension/knob that I can adjust to change the hues of one element (say the background color), automatically adjusting the colors of other elements around it.

For example, say the background color is white. I reflect it to get a text color of black. Then I get 3 other foreground colors that are rotated by 120 degrees along the color wheel. Now I could adjust the hue to rotate around the color wheel. Or I could reflect to get dark mode. But is there a way that supports both without going all the way to a 2D color space? For example, if you set the background color to medium grey now no foreground color can give you the desired level of contrast. So I'd like to not even represent such a background color as an option.

Scott 2025-04-02 15:08:00

I don't know if this is exactly what you're looking for, but it reminded me of this demo of the color contrast tool in Figma I just saw: x.com/billy_sweeney/status/1905640393045409923

🐦 Billy Sweeney (@billy_sweeney) on X: Color contrast accessibility tools are now available in the @figma color picker! Grateful for the chance to design this, and I hope it helps contribute to more design in the world being made more inclusive. Let us know what you think!

Tweet Thumbnail

Marek Rogalski 2025-04-02 15:34:40

I really like the brightness as defined by HSLuv hsluv.org. The transform betweeen RGB is not super straightforward but there is a lot of sample code and it produces really nice feeling colors.

📝 HSLuv - Human-friendly HSL

HSLuv - An alternative to HSL for programmatic color generation

Marek Rogalski 2025-04-02 15:36:52

Also it kind of depends if you're designing for color-blind people. Assuming the most pessimistic accessibility scenario (total color blindness), the only factor in foreground / background contrast is the difference in brightness but for folks that see color the whole UI could have the same effective brightness and still be legible (maybe even could still look nice).

Marek Rogalski 2025-04-02 15:37:33

(see Ishihara tests)

Kartik Agaram 2025-04-02 15:39:43

Yeah, I don't really know what I'm doing regarding color blindness, mostly I just try to avoid red on green, or using red and green foregrounds on the same background.

I'm not intending this for extremely colorful things like you make, @Marek Rogalski or something professional quality that designers will make @Scott. I'm imagining there's mostly a single background, a single body color, couple of accent colors say for syntax highlighting. So I don't need to support every possible point in a scale. The goal is more to exclude bad points in a predictable, opinionated way.

Scott 2025-04-02 15:49:08

Ah got it, yeah I guess I had never seen a visual representation of the available and bad colors at a given contrast level and thought there might be something useful for you there: exclude 90% of color space, set up some basic heuristics, get a pretty decent solution

Arvind Thyagarajan 2025-04-02 16:25:54

i think oklch is the new black

📝 OKLCH in CSS: why we moved from RGB and HSL—Martian Chronicles, Evil Martians’ team blog

CSS Color Module 4 adds oklch(), and we gain P3 wide-gamut support, boost code readability, and improve developer-designer communication.

Karl Toby Rosenberg 2025-04-02 23:20:13

I’ve been thinking about how languages taught at the intro level are usually taught with lots of white lies about how they work, out of necessity. For example, Python’s actual underlying memory model (how everything’s a reference and isn’t copied around) is confusing (arguably), so we avoid teaching that part and oftentimes make all these distinctions between references and primitives (even though everything’s an object). Teaching something more accurate (everything’s an object with references, and oh sometimes values are even referenced via referenced counting) would actually lead to confusion when trying to translate some of this in other languages like C, where everything’s actually a value (pointers are just ints purposed for addressing things).

Java is also confusing with all the GC stuff and opinions it has about memory and memory behavior.

I would like a first-learner’s language that has the arguably-more-consistent semantics of something like C (“everything’s a value”), but is closer to Python. So I can feel like I’m not “lying” so much. I think the closest thing is C itself, unfortunately, or C++ with a custom allocator thing.

Or maybe a hot-take: objective C / ARC are the closest.

But really I’d just like a Python with less obfuscation and inconsistency, so it looks more like C with safety on-top and better file imports.

Essentially, Python with proper value types for everything, even if a little more challenging. The most explainable language closest to hardware, but easier to use.

Just thinking out-loud. I think a Python 3 subset preprocessor that outputs raw C would look close to the language I have in-mind. (I’d like end for blocks too).

Kartik Agaram 2025-04-03 00:56:56

Could you elaborate on where beginners might get tripped up by memory model gotchas in these languages? Basically I'm wondering how to build up to a worldview that this is a major issue. For example, if you had a list of gotcha programs in Python that would be very interesting to go through. I can think of one gotcha in Python (appending to a default arg that is initialized to an empty list, or something like that). Is it a jungle out there, or is it just a couple of things like that in each language that people hit and learn to avoid?

Karl Toby Rosenberg 2025-04-03 04:45:20

e.g. “Why you can modify a list passed to a function and not a non-container type” ; “Why does setting a variable equal to a list / object type make for a reference to the list / object type, whereas ints/floats/strs don’t have this behavior?

In general you explain this in intro by describing copying of values and treating container/object types as references, but in Python that’s not actually how it works. These are not SUPER major issues, but any attempt to explain correctly leads to more complexity than an intro student can normally handle. Python’s a bit messy unless you just suspend disbelief and pretend things work a certain way without explaining why.

I’d like a language that doesn’t hide things like that quite as much, even if arguably it’s not a huge issue for intro.

I do think a simplified C is slightly better because the copying semantics is pretty well-defined vs Python’s reference counting stuff.

Good talk and page on how Python variables work

Marek Rogalski 2025-04-03 07:01:36

C++ is value oriented and low level. Passing a container into a function creates a copy of that container (unless it's passed as a pointer). So the "reference vs value" gotcha can be mostly avoided while teaching. There is a sea of other gotchas in the language though.

IMO the value vs reference may not be such a big issue if explained directly through exercises. A couple tasks where the student has to directly experience how values and references behave should be enough to form a correct mental model. May be easier than chosing a different language altogether.

Joshua Horowitz 2025-04-03 07:13:32

does pyret.org check any of your boxes?

Konrad Hinsen 2025-04-03 08:00:57

When I started advocating and teaching Python to scientists, around 1996, I tried to avoid the hard parts indeed. But not for long. After a few years, I covered the memory model in the very first session, to get that out of the way. It worked well, and I think it was helpful in particular for the many participants who grew up with Fortran.

That said, I never covered the more subtle gotchas of Python, such as the messy scoping rules.

I am ambivalent about teaching languages that avoid thorny issues but don't aim to be usable in real life. Whatever language is used for teaching should also permit learners to solve real problems that matter to them (though not necessarily to get a job in the software industry).

Tom Larkworthy 2025-04-03 08:40:10

What isn't a gotcha in Python? lol. Cyclic imports, WTF is a _ _init_ _.py , imports are executing. setup.py is executed. package resolution. Nothing can be trusted due to monkey patching (which I like BTW). from {foo} import vs. import foo import-by-reference vs import-by-value subtleties. module unloading. white space. Forgetting an f in a multi-line f string (I caused a prod outage coz of that, it is also unlintable). Can't put functions in a string interpolation. Single line lambdas only (?!). the GIL. async. multi-processing. the list is endless with that language.

The default value being persistent in args is a steady cause of bugs which we can at least lint around. The memory model is not not my main source of problems though.

Chris Krycho 2025-04-03 12:50:29

You can write C++ in a value-oriented way, but you have to internalize a lot of things about it to know how to do that consistently and effectively, so it’s a poor fit for the pedagogical context here I think… but folks with strong positive experiences using C++ in that value-oriented way as well as a lot of time using Swift (which obviously draws a lot on the “C + ARC” model) are behind Hylo, which might be interesting to poke at here. Caveat emptor : I haven’t used it, just read the docs, and it’s still quite early!

📝 Hylo

The Hylo Programming Language

Konrad Hinsen 2025-04-03 13:51:40

Tom Larkworthy Your list contains mostly features that easily become problems in practice when developing large programs. That's not the same as features that require a precise mental model. It's easy to see why the f matters in f-strings, but that doesn't protect you from forgetting it.

Good language design should of course avoid both types of issues.

Karl Toby Rosenberg 2025-04-03 14:10:58

I’m thinking also in terms of curriculum. Going from python in intro straight to java then C seems like the wrong order because in a way, Python’s more complicated and unique than Java than C in that everything’s a reference, then most things are references / some are values, then everything’s a value in C (and pointers are values that can refer to other values).

It’s not a giant issue if you do handwaving and don’t explain how things work, but if you try to explain Python’s model for names/labels, I think it can cause friction if then trying to learn general-purpose things or other languages. The fact that python is all references/no copying is just a little weird.

I like python for a lot of things, but not for this aspect (and not for its lack of graphics and web support).

For me it’s major because stylistically, I like not to handwave.

Jack Rusher 2025-04-03 16:09:22

Racket is a great teaching language with loads of pedagogical material available. If you hate s-expressions, then Pyret (mentioned above) and Rombus are very good choices. These languages have all been designed by people with decades of teaching programming and researching what works for language learners.

rhombus-lang.org

Karl Toby Rosenberg 2025-04-03 16:59:06

btw I don’t have a way to change the language since I don’t design the university curriculum. It’s more me thinking out-loud. I saw racket before, it’s cool.

xyzzy 2025-04-03 17:00:09

I would still recommend C but without the stdlib ... perhaps an alternate stdlib library.

Karl Toby Rosenberg 2025-04-03 17:00:30

That’s what CS50 does

Karl Toby Rosenberg 2025-04-03 17:01:04

I’d do that and maybe provide wrappers around regular stdlib so people could check the innards if they wanted.

xyzzy 2025-04-03 17:05:36

Perhaps add a defer as well. I like D .... its just that the problem with D is C library people write horrible APIs which abuse the C preprocessor. I hate C preprocessor .... people do some scary stuff with it, which is always intimidating for beginners.

Karl Toby Rosenberg 2025-04-03 17:05:51

Have you seen Odin?

xyzzy 2025-04-03 17:06:23

Yeah all of them have the .... need C to do anything useful problem.

xyzzy 2025-04-03 17:06:30

except go

Karl Toby Rosenberg 2025-04-03 17:06:45

It’s basically what we’re talking about. Better allocator support, better imports, built-in allocator context, defer.

C’s worst offsense to me is the includes and headers

Karl Toby Rosenberg 2025-04-03 17:07:03

Actually I think Odin’s pretty good.

xyzzy 2025-04-03 17:08:35

Zig / Odin change the syntax way too much.

At best I would be happy with just changes in the declaration syntax

main(argc :int, argv :char[]) :: int

but they change a whole lot. D is definitely more consistent.

xyzzy 2025-04-03 17:11:20

objective C is really not a bad deal only issue with it is ... lack of win / linux support

Karl Toby Rosenberg 2025-04-03 17:13:47

I think C’s syntax is okay except the square brackets in declaring an array and the includes / headers are BLA. But yeah. A C with a custom course stdlib would be enough. Even if the allocation / deallocation straegy is not super efficient, having something automatic in-place could help. Just a big arena.

Or a Python with less magic.

xyzzy 2025-04-03 17:16:44

C + Lua is a good combo as the world of warcarft players might pay more a attention in class I guess 😁

Karl Toby Rosenberg 2025-04-03 17:17:13

Realistically just C with classes (barebones C++ with methods and basic templates)

Konrad Hinsen 2025-04-04 06:13:16

Boosting Jack Rusher’s recommendation for Racket. It has not only extensive teaching experience behind it, but it is also very usable in real life. Not for all domains, of course. Nothing is. But it's not just a toy language that you need to move on from rapidly.

Jamie Brandon 2025-04-04 21:36:40

scattered-thoughts.net/writing/a-rough-survey-of-compilation-recompilation-and-compile-time-evaluation

I'm curious if anyone knows of languages that have different approaches to the ones I covered here.

Tom Larkworthy 2025-04-05 10:06:46

The article seems motivated by research around a better version of hot-reloading (?). I think about 1. Erlang (you have in the article), also 2. Vite which manages to bolt on hot reloading by exploiting dynamic imports and adds a layer of indirection there, which does not work reliably but works enough to create value and also 3. Observable runtime, which is a runtime that that first class support for swapping an implementation and recomputing the dependancy graph (it has a compilation process too but its kind of trivial). JS simplifies things in that you can't swap in the middle of a function because its single threaded, Erlang also works by having a higher level runtime scheduler deciding when to swap. I think that runtime support is essential for top recompilation. I keep thinking it be awesome if go was hot-swapable but I think it always feel like you need an actor like system with serializable messages communicating between them, and then its not like go anymore.

Anyway, Observable has the best hot-reload IMHO, aided by a combination of JS affordances (dynamic imports, single threaded, garbage collection), Runtime support (explicit dependancy graph, cell based construction which I feel is basically an actor system).

You don't really explicitly mention actor systems but they are perfect for defining boundaries for partial recompilation. Observable goes a little beyond Erlang in the sense that when a cell is recomputed, all downstream cells are recomputed which can be thought of replaying their messages that were tainted with the old code. There still exists a problem that the final state is non-deterministic based on the message processing order (same as Erlang) which is the manifestation of non-determinism in the schedular. Would be nice to fix that (I have no idea how).

Paul Tarvydas 2025-04-05 12:33:37

... actor systems ... are perfect for defining boundaries for partial recompilation

💯

Function-calling makes hot-reloading more difficult than necessary. Units of software that have, both, input queues and output queues make hot-reloading easier to think about.

.. final state is non-deterministic ... Would be nice to fix that (I have no idea how).

The way to fix this is: don't fix it. Don't hide a fix in the engine, under the hood. Allow Software Architects and Software Engineers to deal with the issue on a custom, per-project basis. Give 'em textbooks filled with suggestions and algorithms. Assume that SW Architects and SW Engineers are smart enough to figure out which option to choose to solve a particular problem. Imagine if Civil Engineers had to use a unified bridge design for every bridge over rivers. All bridges would be the same and none of them would be any good in practice. In the current programming workflow, general purpose programming languages try to solve every problem at once and programmers need to waste time and efficiency playing whack-a-mole. One's programming mindset changes, for the better, when one knows that willy-nilly, blocking function calls are not allowed to cross software unit boundaries.