开发者
What a Language Needs Before It Can Compile Itself
Code: Megapixel99/lambda-language lm is a small low-level language I wrote: static types, explicit memory, no closures, no garbage collector, and four independent backends that emit C, WebAssembly, ARM64 and bytecode for a VM. Its compiler is about 4,400 lines of JavaScript. The obvious next question is whether the language can compile itself, and the obvious first step is the lexer, which is 129 lines. In lm the same lexer is 355 lines. That ratio is the finding, because almost none of it is lm being a verbose language. Six specific absences account for nearly all of it, and writing them down was a planned milestone rather than an afterthought: the point of porting the lexer first was to find out what the language could not do while the port was still small enough to abandon. The one that cost the most src/lexer.js has a single advance(n) that moves pos , line and col together, called from 14 places. lm had no way to take the address of a scalar local, so a function could not mutate a caller's variable, and a function returning three values would need a struct allocated on every call. So advance does not exist. All 14 sites write pos += 1; col += 1; inline, and the newline case writes the three-line variant. That is the single largest source of the size difference, and it also caused the only correctness bug in the port. Column counting inside a string literal has to skip UTF-8 continuation bytes, and because the logic is inlined rather than centralised there is no one place to fix it. The two comment scanners over-count a column in exactly the same way. They get away with it only because a comment always ends at a newline, which resets the column before anything reads it. That is worth sitting with. A centralised advance would have been fixed once and been right in all three places. Instead the code is right in one place by correction and in two others by luck, and the luck is load-bearing: change what terminates a comment and two latent bugs become live ones. Dup
AI 资讯
Bir Ev Ağı Aslında Nasıl Çalışıyor? LAN/WAN’dan WISP, VLAN ve VPN’e
Ev Ağı Nasıl Çalışır? Bir ev ağını en basit haliyle şöyle düşünebiliriz: Internet │ ISP ağı │ Ev Router'ı │ ┌─────────────┼─────────────┐ │ │ │ Laptop Telefon NAS Ev router'ı burada iki farklı dünyayı birbirine bağlar: ISP üzerinden ulaştığı dış ağ ve evdeki cihazların bulunduğu yerel ağ. Bu basit topolojinin arkasında LAN, WAN, subnet, DHCP, routing, NAT, firewall, bridge ve VLAN gibi kavramlar birlikte çalışır. 1. Ev ağı, ISP ve internet tarafı LAN ve WAN LAN — Local Area Network , router'ın yerel ağ tarafıdır. Evdeki laptop, telefon, NAS, televizyon gibi cihazlar genellikle bu tarafta bulunur. Örneğin router'ın LAN adresi: 192.168.1.1/24 olsun. Cihazlar da: Laptop 192.168.1.20 Telefon 192.168.1.30 NAS 192.168.1.50 adreslerini kullanabilir. Bunların tamamı aynı: 192.168.1.0/24 yerel IP ağına aittir. WAN — Wide Area Network ise router'ın kendi yerel ağı dışındaki bir upstream ağa bağlandığı taraftır. Tipik bir evde: Internet / ISP │ WAN │ Router │ LAN │ Ev cihazları şeklinde görünür. LAN ve WAN, Ethernet kablosunun fiziksel türünü tanımlamaz. Aynı standart Ethernet bağlantısı bir router için LAN, başka bir router için WAN rolünde olabilir. Örneğin: Internet │ Upstream Router LAN: 192.168.1.1 │ │ Ethernet ▼ Downstream Router WAN: 192.168.1.50 LAN: 192.168.10.1 Buradaki 192.168.1.0/24 ağı: upstream router açısından LAN, downstream router açısından WAN tarafıdır. Dolayısıyla LAN ve WAN kavramları hangi router açısından baktığımıza göre anlam kazanır . Upstream ve downstream Ağda internet veya daha üstteki ağa doğru olan yön upstream , son kullanıcı cihazlarına doğru olan yön ise downstream olarak adlandırılır. Internet │ Upstream Router │ Downstream Router │ Laptop Downstream router'ın internete doğru bağlandığı router onun upstream router'ıdır. Bu terminoloji özellikle evde bir modem/router arkasına ikinci bir router bağlandığında kullanışlı hale gelir. ISP'nin rolü ISP — Internet Service Provider , ev ağını daha büyük internet altyapısına bağlayan servis sağlayıcıdı
科技前沿
The 6 Best Monitors That Actually Work Well With Macs
Macs are fantastic computers, but you’ll need one of these great displays to complete your work-from-home setup.
AI 资讯
Three Years of Starting Over: How I Landed on Cybersecurity
I've been a die-hard Computer Science fan for as long as I can remember. Right after my 10th standard, I picked up C — that was four years ago. Around the same time, GitHub pulled me in before I even understood what was happening there. I couldn't parse a single line of what people were building, but I could tell something big was going on. That curiosity eventually pulled me into web development, and from there, into almost every corner of tech over the next few years — AI included. Diploma: The Real Lessons Weren't in the Syllabus I just finished a 3-year Diploma in Computer Engineering. Looking back, the biggest lessons weren't in the coursework. They were in hallway conversations — friends and teachers talking about where technology and the market are headed, instead of the usual teenage small talk. Watching how an organization actually runs, what really happens day to day — that taught me more than most subjects did. A Habit I Used to See as a Flaw Here's a pattern about how I work: everything I start, I start from zero — and I don't always go deep. I finish with the basics, then move on. For a long time I saw that as a bad habit. Three years and almost every major technology later, I've changed my mind — it was the fastest way to find out that "a little bit of everything" isn't who I am. What I actually need is to dig into a system until I find the reason it works. Until I do, I can't let it go. Where That Instinct Pointed Me: Cybersecurity That same need to dig eventually pointed me toward something equal parts fun and dangerous — cybersecurity. I'm about three months into this path now, and I'm moving slowly. Not because it's too hard, but because I won't move to the next topic until every dot is connected. Loose ends don't let me sleep. What I've Learned So Far This is still the floor, not the ceiling, but it's real and hands-on: Web authentication attacks — 2FA bypass, broken password-reset logic, username enumeration through timing differences, account lo
AI 资讯
Lenovo’s Project AeroBlade Fanless Laptop Takes Thin and Light to the Extreme
Using Frore’s air-cooling technology, Lenovo’s Project AeroBlade Concept is an ultralightweight laptop with efficient heat management.
AI 资讯
Nvidia RTX Spark ‘Superchip’: The First AI PCs Are Here
At IFA 2026, Nvidia and its partners showed off the first RTX Spark-powered laptops and mini PCs, designed to run AI models right on your computer.
开发者
Zstandard einfach erklärt in 2 Episoden — Episode 1
Episode 1: Was in einer ZST-Datei passiertEpisode 1: Was in einer ZST-Datei passiertZST-Dateien begegnen uns immer häufiger bei großen Downloads, Softwarepaketen, Backups und Serverdaten. Sie sind oft deutlich kleiner als die ursprünglichen Dateien und lassen sich trotzdem sehr schnell wieder entpacken. Doch wie funktioniert das? Warum werden Dateien komprimiert? Eine Datei besteht aus Daten. Je mehr Daten sie enthält, desto mehr Speicherplatz wird benötigt und desto länger dauert ihre Übertragung. Kompression versucht, dieselben Informationen mit weniger Daten darzustellen. Beim späteren Entpacken muss daraus wieder exakt die ursprüngliche Datei entstehen. Nach dem Entpacken ist die Datei Bit für Bit identisch mit dem Original. Es wird nichts weggelassen und nichts vereinfacht. Wiederholungen benötigen unnötig viel Platz Betrachten wir diesen Satz: Kleine Katzen kuscheln auf kleinen Kissen, junge Katzen kuscheln auf bunten Kissen und alte Katzen kuscheln auf weichen Kissen.Die folgenden Teile kommen mehrfach vor: A = Katzen kuscheln auf B = KissenWenn wir die wiederkehrenden Textteile durch die Variablen A und B ersetzen, können wir den Satz kürzer darstellen: Kleine A kleinen B, junge A bunten B und alte A weichen B.Damit ist der Text noch nicht vollständig. Zusätzlich müssen wir speichern, wofür A und B stehen: A = Katzen kuscheln auf B = KissenAus diesen Informationen lässt sich der ursprüngliche Satz wiederherstellen. Jedes A wird durch Katzen kuscheln auf und jedes B durch Kissen ersetzt. Das ist bereits die grundlegende Idee der verlustfreien Kompression: Wiederkehrende Daten werden nicht jedes Mal vollständig gespeichert. Stattdessen werden sie einmal gespeichert und anschließend durch kürzere Verweise ersetzt. ### Zstandard verwendet keine Variablen Unsere Variablen A und B dienen nur dazu, das Prinzip verständlich zu machen. Zstandard versteht weder Wörter noch Sätze. Es weiß nicht, was Katzen oder Kissen sind. Für das Programm besteht eine Datei lediglich
科技前沿
Asus ProArt 27 QD-OLED (PA279cdv) Review: HDR for All
I wouldn’t call it cheap, but this monitor from Asus brings proper HDR-capable video editing to creators who couldn’t previously afford an OLED display.
AI 资讯
Interpreters and Compilers: How Your Code Actually Becomes a Running Program
Every developer writes code that "just works" thousands of times without thinking about what happens between hitting save and seeing output on screen. This article pulls back that curtain. We're going to walk through, in real depth, how source code — plain text you typed — becomes a running program, covering lexing, parsing, abstract syntax trees, semantic analysis, and the actual difference between interpretation and compilation (including why that difference is far blurrier than most explanations make it sound). This is one of those topics where understanding the fundamentals pays off across your entire career — it changes how you read error messages, how you reason about performance, and how you evaluate new languages and tools. 1. The Big Picture: Two Broad Strategies At the highest level, there are two strategies for running code: Compilation — translate the entire source program into another form (often machine code, but not always) before running it. The translation and the execution are separate steps. Interpretation — read and execute the source program directly, translating and running it (roughly) simultaneously, statement by statement. In practice, almost no real system is purely one or the other. Python "compiles" your source to bytecode before interpreting the bytecode. Java compiles to bytecode, then a JIT (Just-In-Time) compiler compiles hot paths of that bytecode to native machine code while the program runs . JavaScript engines like V8 do something similar. The clean binary of "compiled vs. interpreted" that gets taught early on is really a spectrum, and most production language runtimes today live somewhere in the middle. But to understand any point on that spectrum, you need to understand the pipeline every one of these systems shares. Let's build it up stage by stage. 2. Stage One: Lexical Analysis (Lexing / Tokenizing) The first thing that has to happen to your source code is the least glamorous: it gets chopped into pieces. Source code, to a c
AI 资讯
I Built My Own Fail-Fast HashMap — Here's Why a Boolean Flag Wasn't Enough
If you've done LeetCode's Design HashMap , you've implemented put , get , and remove . What that exercise usually skips is the part that actually breaks in production: what happens when someone mutates the map while another piece of code is iterating over it. I ran into this directly while building MyHashMap , a from-scratch single-threaded HashMap (separate chaining, resize on load factor). Getting put / get / remove right was the easy 80%. Getting entrySet().iterator() to correctly detect concurrent mutation — including the case where a second, completely separate iterator is the one that should notice — took three wrong turns before landing on the pattern the JDK actually uses. The problem, concretely Iterator < Entry < K , V >> it = map . entrySet (). iterator (); it . next (); map . put ( someNewKey , someValue ); // structural change, mid-iteration it . next (); // ??? — undefined behavior if we don't guard against this Without a guard, next() might return a stale entry, skip entries entirely, or throw an unrelated exception depending on internal bucket-array state. Java's real collections handle this with ConcurrentModificationException (CME) — but the interesting part isn't the exception, it's the mechanism that detects when to throw it. First idea: a boolean "dirty" flag Obvious first attempt: a boolean modified field on the map, flipped to true on any put / remove , checked by the iterator. This works for exactly one iterator. It falls apart the moment two iterators are alive at once: Iterator A calls next() , sees modified == false , proceeds. Something else mutates the map. modified flips to true . Iterator B — created after that mutation — checks the same shared modified flag, sees true , and incorrectly throws, even though nothing has changed since B was created. A single shared boolean can't represent "changed since this specific iterator was created" for more than one iterator at a time. Resetting it on read doesn't help either — now the other iterat
AI 资讯
CPU, GPU, TPU, NPU, DPU, QPU: six chips, one question
Hello, I'm Maneshwar, and I'm building LiveReview — a blast-radius aware AI code review built for...
AI 资讯
Nine puzzle solvers, one browser tab, zero servers: a tour of classic search algorithms
I recently finished building a small suite of puzzle and game solvers that all run entirely in the browser — no backend, no API calls, no machine-learning models. You paste in a Sudoku, a chess position, or a crossword pattern, and the answer comes back instantly, computed on your own device. The fun part wasn't the UI. It was that each puzzle turned out to be a textbook excuse to reach for a different classic algorithm. Nine solvers, and I got to use constraint propagation, adversarial search, heuristic search, brute-force scanning, and plain old pattern matching — the stuff that shows up in an algorithms course and then, in most day jobs, never again. This is a tour of which algorithm fits which puzzle, and a few of the potholes I hit along the way. Everything here is vanilla JavaScript running in a Web Worker. The one design constraint: no server Before the algorithms, the rule that shaped all of them: it has to run client-side. That's a privacy choice (your puzzle never leaves the tab) and a cost choice (no compute bill), but it's also a fun forcing function. You can't lean on a beefy backend or a hosted model — you get one browser thread (well, a Worker thread) and whatever you can compute in a few hundred milliseconds. That budget is exactly why classic algorithms shine here. They're fast, deterministic, and small enough to ship as a script. Let's group the solvers by the technique each one leans on. Family 1: Constraint propagation Sudoku Sudoku is the poster child for constraint propagation. A cell that can only be one value forces that value; that in turn shrinks its neighbours' options, which forces more cells, and so on. Most "easy" and "medium" boards fall over from propagation alone (naked singles + hidden singles), and only the hard ones need a backtracking search on top. The nice property: the same engine that solves the board also powers the hint feature (find the next forced cell and explain why it's forced) and a uniqueness check — count solutions,
开发者
Alienware AW3926QW Review: 39 Inches of Gaming Glory
Alienware’s latest gaming monitor explores a new size and resolution for ultrawide monitors, and I have a feeling PC gamers are going to love it.
AI 资讯
MEU COMEÇO NA ÁREA DA TECNOLOGIA
Olá, comunidade dev.to! Meu nome é Neto, tenho 17 anos e sou estudante de Ciência da Computação no UNIPÊ, em João Pessoa. Atualmente, estou cursando o segundo semestre da graduação e também estudando design profissional, área que considero importante para a criação de soluções digitais mais úteis, intuitivas e visualmente agradáveis. Minha trajetória na tecnologia ainda está no começo, mas já tem sido marcada por descobertas, aprendizados e desafios. Escolhi Ciência da Computação porque sempre tive curiosidade sobre como aplicativos, sites e sistemas funcionam. Quero aprender não apenas a programar, mas também a compreender todo o processo de desenvolvimento de um produto, desde a identificação de um problema até a construção de uma solução. Durante o curso, tive a oportunidade de desenvolver, com alguns colegas, um projeto relacionado à criação de um aplicativo. Essa experiência foi importante porque me mostrou que desenvolver um produto vai muito além de escrever código. Foi necessário discutir ideias, organizar tarefas, pensar nas necessidades dos usuários e encontrar soluções para os problemas que surgiram durante o processo. Mesmo enfrentando desafios simples, percebi como cada obstáculo pode contribuir para o nosso crescimento. Em alguns momentos, precisamos revisar decisões, corrigir erros e adaptar o projeto. Também aprendemos que uma equipe precisa manter uma boa comunicação, pois cada integrante possui habilidades, responsabilidades e pontos de vista diferentes. O estudo de design profissional complementa minha formação em computação. Estou aprendendo que uma aplicação não deve apenas funcionar corretamente: ela também precisa oferecer uma boa experiência ao usuário. Elementos como cores, tipografia, organização das informações, acessibilidade e facilidade de navegação influenciam a maneira como as pessoas utilizam um produto. Ainda tenho muito a aprender sobre programação, design e desenvolvimento de projetos. Porém, entendo que a evolução acontece aos po
AI 资讯
My Nand2Tetris Journey #2 - Building Basic Chips And ALU
What I Built HalfAdder, FullAdder, Add16, Inc16, And ALU. How I Solved Like when I built logic gates, I started with analyzing truth table of HalfAdder , FullAdder . HalfAdder was really easy. After looking at the truth table, I could map the sum and carry outputs to logic gates pretty quickly. FullAdder was also not hard since it's really similar to HalfAdder except that it can add 3 bits. I realized that I could build it by combining some chips and logic gates I had already made instead of designing everything again from scratch. Once I finished building them, I was also able to build Add16 . At first, I had no idea how to sum all the 16 bits. But I soon realized that I could build a 16-bit adder by combining the smaller adders I had already built and passing carry information to the next bit. It looks not beautiful, but still works. And about Inc16 , it's basically add exactly 1(0000000000000001) . So I could easily build it using Add16 . (But I did something weird at first.. check the Reflection below) ALU was the core part of project 2. Once I realized that Mux can be used as if , I could make proper outputs using logic gates. ALU is also a combination of logic gates and chips, after all. What I Learned How to build basic chips using logic gates and already-built chips Why I should reuse the chips for another chip(check the Reflection section below) Mux can be used like if How to use bit slicing and fan-out in HDL and why it's important Reflection Before I started this part, I didn't know two things: I could use bit slicing and true , false for each bit. So when I first tried to build Inc16 , it looked really weird, since I calculated all the bits one by one. It's not logically wrong. But not beautiful either. I was not sure if it was right or not. Then I realized that I already built Add16 . But I had no idea how I could use it to add exactly 1(0000000000000001) . After googling, I realized that I could use bit slicing like Python's list slicing and construct
AI 资讯
Apple Mac Mini M6 and Mac Studio M5 Ultra: Specs, Price, Release Date
Apple’s Mac Mini and Mac Studio have been tough to buy for months, but updated versions have arrived. Both include new chips optimized for AI, with the M6 Mac Mini getting a $200 price bump.
AI 资讯
Leetcode 31: Next Permutation
Question : Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). The replacement must be in-place and use only constant extra memory. Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. Example : 1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1 Idea : Scan from right to left and find the first element that is less that its previous. eg: 1 6 3 5 -> here it is 3. Let's name it as index. Again scan from right to left and find the first element that is greater than 3 and that's 5. Let's mark it as idx. 3.In this step we swap 3 and 5. Reverse elements from index+1 till the array length. Code: public void nextPermutation(int[] nums) { int index = -1; for(int i=nums.length-1;i>0;i--){ if(nums[i]>nums[i-1]){ index = i-1; break; } } if(index==-1){ reverse(nums,0,nums.length-1); return; } int idx=0; for(int i=nums.length-1;i>=index+1;i--){ if(nums[i]>nums[index]){ idx=i; break; } } swap(nums,index,idx); reverse(nums,index+1,nums.length-1); } void swap(int[] nums,int i,int j){ int temp =nums[i]; nums[i] = nums[j]; nums[j] = temp; } void reverse(int[] nums,int i ,int j){ while(i<j){ swap(nums,i,j); i++; j--; } } Code Explanation : We first initialize index=-1 and traverse backward to find the first one with i that satisfy the condition nums[i]>nums[i-1] . We assign this to index and break out of the loop. for(int i=nums.length-1;i>0;i--){ if(nums[i]>nums[i-1]){ index = i-1; break; } } Next step we are discussing a corner case. For example if the given array is 3,2,1 then we cannot find the element that satisfies the previous condition. So when the array is given in decreasing order we just reverse it and return. if(index==-1){ reverse(nums,0,nums.length-1); return; } Next iteration we are considering another variable idx and traverse backw
科技前沿
Asus ROG Swift RGB Stripe OLED Review: Clarity King
The Asus PG27UCWM brings a new sub-pixel layout to the world of OLED gaming monitors, and in my testing, I appreciated the improvements it brings to the table.
科技前沿
The 6 Best Laptop Docking Stations to Unlock the Full Desktop Experience (2026)
Docking stations expand what your laptop can do, and I’ve been testing the best of the best to see which you should buy.
AI 资讯
LeetCode 3116 (Hard) — binary search + inclusion-exclusion makes it easy
Full walkthrough: https://www.youtube.com/watch?v=vFuFA3ByCs0 LeetCode 3116 — Kth Smallest Amount With Single Denomination Combination. Here’s the trick everyone misses: Brute force (generate all multiples, pick k-th) fails because k can reach 2×10⁹. The real approach: Binary search the answer X Count valid amounts ≤ X using inclusion-exclusion Odd subsets add, even subtract (bitmask over coins) LCM via GCD, break when LCM > X O(n · 2ⁿ · log(k·M)) — passes cleanly. The 26% acceptance rate makes this look harder than it is. Once you see the count(X) monotonic trick, it clicks.