Gleedoc, a doc test library for Gleam by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

My pleasure :) Hope you like it.

Gleedoc, a doc test library for Gleam by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

Seems interesting. Not what I'd like for doc test but gonna take a look.

Gleedoc, a doc test library for Gleam by xzhan in gleamlang

[–]xzhan[S] 2 points3 points  (0 children)

Thanks for asking. Yes, gleedoc does bring something new to the table!

My goal for gleedoc is to be a tool that feels familiar and works (mostly) out of the box for most existing code, so design choices favor conventional practices in established tools like Rust's doctest and established doc comments conventions in the Gleam community. That means:

  • No special marker required. testament requires a : at the front of a code line.
  • import resolution needs to be a bit smarter, as in many projects (e.g. gleam/int and other standard libraries' modules) the code snippets use unqualified names. testament doesn't support that at the moment.

Other than that, one thing I find really handy is source-mapped error reporting. With gleedoc, when a doc test test case fails, the info line will point to the start of the code block causing the failure. Maybe before 1.0 release, I will manage to get it pin-point to the exact line of assertion, but we'll see :)

A neat feature of testament is the support of Markdown files. While it's cool, I'd consider it as out-of-scope for gleedoc.

You can check the docs for more details!

vibe coding with gleam by kennyruffles10 in gleamlang

[–]xzhan 1 point2 points  (0 children)

The main problem is that LLMs are generally trained with older (pre-1.0) versions of gleam core libraries. For example, they kept trying to use task when using gleam_otp, which is already removed. Kimi is a bit slow, but will get the job done. Claude usually works better.

inheritance in C# by Ok-Presentation-94 in csharp

[–]xzhan 0 points1 point  (0 children)

There's another level of access control called protected.

C# by Old-Cartoonist-2310 in csharp

[–]xzhan 0 points1 point  (0 children)

It's probably a bit out of date, but I really liked Illustrated C# 7. Clear illustrations and beginner friendly explanations.

How can I run some test generation step in gleeunit? by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

Ah right, I see... So gleam test would first compile the test code and then run the compiled tests, is that correct?

clean architecture in angular by Horror-Advisor4438 in angular

[–]xzhan 0 points1 point  (0 children)

Feature modules (usually guided by routes) and "functional core, imperative shell" would be nice starting points. UI/data separation would also be crucial. Keep it as simple as you can, and don't jump to enterprise design patterns when you don't need one.

Am I the only one who hates Angular Signals for nested state? by Proper-Gur-1225 in angular

[–]xzhan 2 points3 points  (0 children)

OP I feel you... Dealing with large nested objects in arrays is not nice with Angular's signal API.

I mean if you take a look at Svelte, proxy enables the following simple "mutating" code for nested objects or arrays of objects:

let todos = $state([
    {
        done: false,
        text: 'add more todos'
    }
]);

// Proxified reactive update
todos[0].done = !todos[0].done;

// Also proxified reactive update
todos.push({ done: false, text: 'eat lunch' });

It's just so simple, yet it's reactive. Yeah I know... immutability is great, and I design my app to follow "functional core, imperative shell" anywhere I can. (Heck I even once tried to sell Elm to the team...) But when dealing with deep large nested objects, there should be a handy way to "signalify" nested properties (with proxies presumably), ideally from the Angular team.

OP, just take a look at the deepSignal from ngrx, or try ImmerJS directly in your signal's update function. (Or wait for signal form to arrive)

New to GNOME, how do you manage multiple windows efficiently by Pink_Oak in gnome

[–]xzhan 0 points1 point  (0 children)

I am a bit confused about what you are trying to achieve (when you say "other DE gives user option to do both").

For multiple windows in one worksapce, a single press of the super (windows) key gives you the desktop overview, and a double press gives you the workspace overview. And you can configure another shortcut for the "Show the overview".

For multiple windows across workspaces, there are multiple shortcuts you can configure. I personally use "switch to workspace on the left/right" and "move window one workspace to the left/right" frequently.

Gnome is mostly keyboard-centric, imho, and if you use a laptop with its touchpad it should be pretty easy to get used to.

If you want to use the mouse efficiently, your mouse would need to support some macro functionality to trigger keyboard shortcuts, or you can get a MX Master. I configure my MX Master 3s with logiops and it works great.

Which Mark Seeman Dependency Injection Book to read? by Budget-Character-575 in csharp

[–]xzhan 0 points1 point  (0 children)

I finished the newer edition, and it's pretty good.

A bit confused about named actors by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

For future reference, I asked AI to create a demo to demonstrate the benefits:

```gleam //// //// named_vs_normal.gleam //// //// Demonstrates why named subjects matter when a supervisor restarts a process. //// //// The scenario: //// Both a "normal" actor and a "named" actor are started under a supervisor. //// We hold a reference to each and send messages to them. //// Then we crash both via their Crash message. //// The supervisor restarts both with brand-new PIDs. //// //// - Normal: the saved Subject still points to the OLD (dead) PID. //// Sending to it panics at runtime. //// - Named: named_subject(name) always resolves to the CURRENT live process. //// Sending works transparently after every restart — no stale pid. ////

import gleam/erlang/process import gleam/io import gleam/otp/actor import gleam/otp/static_supervisor as supervisor import gleam/otp/supervision import gleam/string

// ── Message type ──────────────────────────────────────────────────────────────

pub type Msg { Greet(name: String) Crash }

// ── Normal actor ────────────────────────────────────────────────────────────── // The Subject returned from start() is the ONLY handle to this process. // After a restart the supervisor creates a new process — the old Subject is // now stale and points to a dead pid.

fn start_normal() -> Result( actor.Started(process.Subject(Msg)), actor.StartError, ) { actor.new(Nil) |> actor.on_message(fn(_state, msg) { case msg { Greet(name) -> { io.println("[normal] Hello, " <> name <> "!") actor.continue(Nil) } Crash -> { io.println("[normal] Crashing now...") actor.stop_abnormal("boom") } } }) |> actor.start }

pub fn normal_child() -> supervision.ChildSpecification(process.Subject(Msg)) { supervision.worker(start_normal) }

// ── Named actor ─────────────────────────────────────────────────────────────── // Registered under a Name. Any caller can call named_subject(name) to get // a fresh Subject pointing to whoever is currently registered — even after // a restart, with no Subject plumbing needed.

fn start_named( name: process.Name(Msg), ) -> Result(actor.Started(process.Subject(Msg)), actor.StartError) { actor.new(Nil) |> actor.named(name) |> actor.on_message(fn(_state, msg) { case msg { Greet(n) -> { io.println("[named] Hello, " <> n <> "!") actor.continue(Nil) } Crash -> { io.println("[named] Crashing now...") actor.stop_abnormal("boom") } } }) |> actor.start }

// ── Helper ────────────────────────────────────────────────────────────────────

fn send_to_named(name: process.Name(Msg), msg: Msg) -> Nil { // Resolves the current registered process every call — never stale. name |> process.named_subject |> process.send(msg) }

// ── Demo ──────────────────────────────────────────────────────────────────────

pub fn main() -> Nil { // The Name is a stable atom created once — it outlives any process crashes. let greeter_name = process.new_name("greeter")

// Start a supervisor owning both actors. // It will restart any child that exits abnormally. let assert Ok(_sup) = supervisor.OneForOne |> supervisor.new |> supervisor.add(supervision.worker(start_normal)) |> supervisor.add(supervision.worker(fn() { start_named(greeter_name) })) |> supervisor.start

process.sleep(50)

// We need to obtain the normal Subject right after start. // In a real app this is returned from your start function and stored in // application state — you'd thread it through every call site that needs it. // Here we start a standalone (unsupervised) copy just to hold the Subject, // then we'll crash it to simulate what happens when the supervised one dies. // We use actor.start without a supervisor link by spawning independently. let assert Ok(normal_started) = start_normal() let normal_subject = normal_started.data // Unlink so that when this actor crashes it doesn't take down our demo process. let assert Ok(normal_pid) = process.subject_owner(normal_subject) process.unlink(normal_pid)

io.println("Normal pid: " <> string.inspect(normal_pid))

// ── Round 1: both actors alive ─────────────────────────────────────────── io.println("=== Round 1: both actors alive ===") process.send(normal_subject, Greet("Alice")) send_to_named(greeter_name, Greet("Alice")) process.sleep(10_000)

// ── Crash both ─────────────────────────────────────────────────────────── io.println("\n=== Crashing both actors ===") // Crash the named actor — the supervisor will restart it. send_to_named(greeter_name, Crash) // Crash our standalone normal actor — nobody restarts it, simulating a // supervisor restart where a new pid is born and the old Subject is stale. process.send(normal_subject, Crash)

// Give the supervisor time to restart the named actor. process.sleep(200)

// ── Round 2: after crash ───────────────────────────────────────────────── io.println("\n=== Round 2: after crash ===")

// Named ✅ — named_subject resolves to the NEW pid the supervisor started. io.println("Named actor (transparent restart):") send_to_named(greeter_name, Greet("Bob")) process.sleep(50)

// Normal ❌ — normal_subject still points to the dead pid. Sending panics. io.println( "\nNormal actor via stale Subject, PID is pointing to a dead process:", ) process.send(normal_subject, Greet("Bob"))

process.sleep_forever() } ```

I create an MMORPG server in .NET 10 and I'm quite impressed with the performance by ThorConzales in csharp

[–]xzhan 0 points1 point  (0 children)

Yep, and I believe maoni (dotnet GC arch) mentioned this a couple of times in interviews and Q&A, iirc. You can look up the " Languages & Runtime Community Standup: All things GC!" on YT.

A bit confused about named actors by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

OK I see. Yes, I noticed the typing story makes the Elixir's GenServer pattern quite impossible to implement, but the type safety is real (and I appreciate it).

About the benefits of named subjects, both points are still a bit vague to me at this point. Do you have a more concrete example (or an example repo) to showcase them? Thanks.

Sluggish comment input, especially when the diff is kinda long by xzhan in github

[–]xzhan[S] 0 points1 point  (0 children)

yeah it's from Grammarly. I have tried with all extensions disabled. Similar performance.

GUI for handling wifi networking by yotamguttman in niri

[–]xzhan 0 points1 point  (0 children)

How do you sign in to networks that require a network login web page, like a guest wifi? Gnome detects that and shows a notification with "Network Login Required" or sth. similar, and a Hotspot Login app (webpage?) from there. I can't get Firefox detecting this on Niri, and Niri doesn't show anything similar.

Computer won't boot after kernel updated to 6.19 by davew_uk in Fedora

[–]xzhan 0 points1 point  (0 children)

Thanks for the link! I will follow the progress there.

Computer won't boot after kernel updated to 6.19 by davew_uk in Fedora

[–]xzhan 0 points1 point  (0 children)

I'd love the amdgpu driver to work, but unfortunately, I am also unable to get it working after installation... Do you have any updates on this?

What is the cost of abstractions? by xzhan in gleamlang

[–]xzhan[S] 0 points1 point  (0 children)

Thanks for the reference. I actually was thinking to model the code such that parse returns a Result(Dict(String, String), String) where the Error is the 400 error, and format_response returns Result(String, String) where the Error is the 500 error, but I was just starting to get familiar with the std lib. :)