a_e_k

Joined 13 years ago

Karma
2,650
Submissions
740
Member since
Sep 22
http://eastfarthing.com/blog/

andrew at $DOMAIN

View on Hacker News

Recent submissions

Comment · 2 days ago
⬑ Xenodium created agent-shell, in case anyone missed the joke.
Comment · 2 days ago
Comment · 3 days ago
If you've read Pratchett's Discworld, I like to think of Emacs as an Igor: it's a loyal servant that can swap out its own parts, exchange them with other individuals, and rebuild itself on the fly.

But to answer your question, It's not just elisp itself, but rather that Emacs is basically a live elisp interpreter process with an editor UI on top, and the design is something of a ball-of-mud with few boundaries.

With typical systems you have plugins and they have fairly narrow interfaces. If you want to do something that's not covered by the plugin API, you're pretty much out of luck.

With Emacs, everything is open as a free-for-all to extend or redefine, so you can monkey-patch pretty much anything. Here's an example from my init.el:

    (define-key global-map [remap move-beginning-of-line] 'move-beginning-of-line-dwim)
    (defun move-beginning-of-line-dwim ()
      "Cycles between the beginning of text on the line, the actual
    beginning of the line, and the beginning of the body of a comment
    on the line.  If not in one of those three places, it starts at
    the beginning of the text.  Basically, it's a smarter HOME
    command."
      (interactive "^")
      (comment-normalize-vars t)
      (unless (and (bolp) (comment-search-forward (pos-eol) t))
        (let ((cur (point)))
          (beginning-of-line-text)
          (if (= cur (point))
              (beginning-of-line)))))
By default, the HOME key and Ctrl-a are bound to the `move-beginning-of-line` (defined in `simple.el`, one of the elisp source files that comprises vanilla Emacs). That `define-key` with the `remap` tells Emacs that everywhere in the global keymap that it sees the default `move-beginning-of-line`, it should replace it with my custom `move-beginning-of-line-dwim`.

Alternatively, I could have just done `(defun move-beginning-of-line ...)` and simply redefined `move-beginning-of-line` wholesale and it would probably have worked fine. But this is a little cleaner, IMO. Either way, now when I hit HOME key it cycles between column 0, the first non-whitespace character, and the first character in the body of a trailing comment.

On top of that, I don't need to have a formal plugin or anything. I can take the above code, paste it into an elisp buffer somewhere, put the cursor somewhere in or after the `(defun ...), hit Ctrl-x Ctrl-e and now that function is defined within Emacs (and callable by other functions). Same thing with the `(define-key ...)`: put the cursor on it, Ctrl-x Ctrl-e, and the binding is updated. No ceremony.

And for testing, I can edit the function freely, hit Ctrl-x Ctrl-e and now my edited version is the live one in the running Emacs process. It's a lot like a scripting language REPL except within the editor UI.

And in addition, Ctrl-h Ctrl-f tells you about any function that Emacs knows, defaulting to whatever function name the cursor is on. So if I put the cursor on `move-beginning-of-line-dwim` and hit Ctrl-h Ctrl-f RETURN, I get:

    <home> runs the command move-beginning-of-line-dwim (found in global-map),
    which is an interactive interpreted-function.

    It is bound to C-a and <home>.

    (move-beginning-of-line-dwim)

    Cycles between the beginning of text on the line, the actual
    beginning of the line, and the beginning of the body of a comment
    on the line.  If not in one of those three places, it starts at
    the beginning of the text.  Basically, it’s a smarter HOME
    command.

    [back]
Same thing for Ctrl-h Ctrl-v for variables and settings. The documentation that it shows is generated directly from the doc strings and live editor state. Ctrl-h Ctrl-k will prompt for a key and show me a key binding, so Ctrl-h Ctrl-k HOME will give me the above documentation now too. Ctrl-h Ctrl-b shows all applicable keybindings, etc.

Now I'd mentioned that you can monkey-patch anything. In practice that could cause chaos if you don't take care. A pretty common idiom in Emacs to do this more cooperatively are "hooks". These are just variables that some package, internal or external, defines to hold a list of functions to callback. The package iterates the list and calls them whenever the given event happens and you can add or remove your own function to the list to get that call. Think signals and slots, if you seen that design before. And these are pretty ubiquitous. As an example from my init.el:

    (add-hook 'font-lock-mode-hook 'font-lock-mode-setup)
    (defun font-lock-mode-setup ()
      "Make fixme tags standout."
      (unless (derived-mode-p 'special-mode)                      ; Don't break list-{faces,colors}-display
        (font-lock-add-keywords nil
         '(("\\<\\(?:AEK\\|NOTE\\|FIXME\\|TODO\\|XXX\\)\\>\\(?:([a-z]+)\\)?:?" 0 'font-lock-warning-face prepend)))))
So whenever syntax highlighting is started up in a buffer, it calls the font-lock-mode-hook callbacks, and that runs my code to register a regexp to highlight my initials and other fixme tags.

And if all that's not enough, Emacs also has an "advice" system which lets you register code to run before, after, around, etc., any existing function. (And then later unregister it if you wish.) There's also a built-in elisp debugger to break into a function and step through it.

So basically, the key I'd say is that there's no real privileged code in Emacs. You can redefine pretty much anything to taste, and do so without even having to reload Emacs. The downside is that it's up to you to decide what to trust. It's on you to avoid breaking it, and you probably want to be choosy about the packages you run.

Comment · 3 days ago
`(insert (format-time-string "%c"))` should do the trick, though you might need to change the format string to taste.
Comment · 6 days ago
Saw it with my family last last night and we all loved it. I was amazed at how much Laika has upped their game with crowds and FX. That, and I definitely noticed things like the subsurface on the skin and smoother motion in general.

I previously worked at Pixar for 11 years on the RenderMan team and would sometimes talk to some of your CGI folks. I'm crossing my fingers that this is Laika's year at the Oscars.

Comment · 23 days ago
For the float stuff, beware of `-ffinite-math-only`. If enabled, `isfinite()` and may compile out as assumed true (with similar assumptions around `isnan()` and `isinf()`).

And `-ffinite-math-only` is enabled by `-ffast-math` which in turn is enabled by `-Ofast`.

Comment · 25 days ago
Blue. No, yel--
Comment · 1 month ago
Comment · 1 month ago
Yes, and back when hand-writing vectorized kernels via intrinsics, one learned to do the equivalent of (pseudocode here - picture SSE, AltiVec, NEON, etc.):

    vector conditionmask = <some computation...>; // E.g., 11111111 00000000 00000000 11111111
    vector truebranch = <some computation...>;
    vector falsebranch = <some computation...>;
    vector result = (truebranch & conditionmask) | (falsebranch & ~conditionmask);
where each lane of the conditionmask has either all bits set or all bits clear, depending on the outcome of the conditional test for that lane.

The processor obviously does execute both branches here, so there's going to be wasted work. But since it's just a linear sequence of operations it can often schedule them independently and run them out-of-order and in parallel. And of course, if there's any shared computation between the two branches, the compiler can do common subexpression elimination.

That said, that sort of approach where you go ahead and do both and then blend them was definitely the kind of optimization where you'd want to profile rather than doing it blindly. But it was a pretty common thing to do when hand-vectorizing code. (Thankfully, auto-vectorizers are pretty good at doing this sort of optimization for you these days. It's been a very long time now since I've had to hand-write vector intrinsics.)

Comment · 1 month ago
$2000!

I really don't get why people spend so much on flagship phones! I tend to aim for $200 Motos for me and my family, and it feels like it's a 90%+ solution at a tenth of the price. I can still browse the web, text with people, make calls, listen to music, and take pictures. They still last for years, and if they get dropped and the screen cracks, it just means its time to upgrade. What am I missing here?

Comment · 1 month ago
That's the the difference between a low-discrepancy sequence and low-discrepancy set. The first can generate an infinite number of points, the later targets exactly a specific number. You can often get lower discrepancy if you know up front exactly how many points you'll want.

All that said, there's definitely been research into samplers that combine low-discrepancy with blue noise properties (often including retaining those properties even in lower-dimensional projections produced by dropping axis).

Comment · 2 months ago
Comment · 2 months ago
NEW Reddit has recently started blocking logged-out access too. Stupid modal popup with "Join the most real place on the internet" (yeah, right) banner that appears after about 20 seconds.

I'm not logging in to my private account from a work machine that's MITMd for "security", just to browse search results or take a short break!

(I've been a user for nearly 21 years, but using it less and less with each stupid choice - these days I post a comment maybe once a week there. I think I may finally be done with Reddit, sadly. It was good while it lasted.)

Comment · 2 months ago
"Usually". The case when they say it's not:

> The study finds annual mileage thresholds below which the replacement EV’s manufacturing emissions are not recovered: about 7,054 kilometers for cars, 6,837 kilometers for SUVs and 10,794 kilometers for trucks. Those are well below the roughly 20,000 kilometers in the researchers’ average case, but very lightly driven vehicles clearly exist and can be better left in service.

("Kilometerage threshold"? Anyway, for those using miles, that's 4383 mi for cars, 4248 mi for SUVs, and 6706 mi for trucks.)

Still, I like my old ICE car partly because it's from the offline vehicle era and completely lacks any kind of remote telemetry. Perhaps if I didn't have to choose between EVs and lack of telemetry, I might be more inclined to upgrade sooner. (That, plus it's still nice to be able to just completely refuel in a couple of minutes on long road trips through areas where services are very sparse.)

Comment · 2 months ago
Like the old proverb: "The marvel is not that the bear dances well, but that the bear dances at all."

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton