Hacker Newsnew | past | comments | ask | show | jobs | submit | undecidabot's commentslogin

Trusted publishing is a thing now for many package registries, including npm: https://github.blog/changelog/2025-07-31-npm-trusted-publish...


Also worth reading: Compiling with Continuations, Continued (2007) [1]

[1] https://www.microsoft.com/en-us/research/wp-content/uploads/...


And Andrew Kennedy gave a very nice lecture on this recently as part of Xavier Leroy's seminar on control structures:

https://www.college-de-france.fr/fr/agenda/seminaire/structu...


There is also the counterpoint: Compiling without continuations (2017) [1]

[1] https://www.microsoft.com/en-us/research/wp-content/uploads/...


System programming languages also used to refer to non-scripting languages. See this paper by John Ousterhout (creator of Tcl) written in 1997: https://users.ece.utexas.edu/~adnan/top/ousterhout-scripting...


Ullman's book is really accessible and what introduced me to SML as well, but for those looking for something that goes a little deeper, do read "ML for the Working Programmer" by Lawrence Paulson (author of Isabelle). It has one of the best introductions to ML's module system and even covers building a (toy) tactical theorem prover. Oh, and it's now available online for free as well [1].

Another great book on FP is "The Functional Approach to Programming" [2], which is a bit like SICP but using Caml (OCaml without the O) instead of Scheme.

[1] https://www.cl.cam.ac.uk/~lp15/MLbook/pub-details.html

[2] http://pauillac.inria.fr/cousineau-mauny/main.html


Brian Kernighan (the K in K&R and AWK) also wrote a similar book with P. J. Plauger called "The Elements of Programming Style" [1]. There's even a talk by him about it online (2009) [2].

Kernighan also co-authored a (imo) really great book with Rob Pike (once an assistant of Penn & Teller [3]) called "The Practice of Programming" [4]. Unfortunately, this one is a bit over the 200 page limit.

[1] https://en.wikipedia.org/wiki/The_Elements_of_Programming_St...

[2] https://www.youtube.com/watch?v=8SUkrR7ZfTA

[3] https://youtu.be/z4iVAcYyWN0?t=180

[4] https://en.wikipedia.org/wiki/The_Practice_of_Programming



You can configure ssh-agent to ask for confirmation if you set the `-c` flag in ssh-add or by setting `AddKeysToAgent` to `confirm` in your ssh config [1].

Once set, authentication will require confirmation via a GUI dialog provided by the ssh-askpass command. However, it does not mention the command or process requesting for authentication.

It works great on Linux, but I couldn't get it to work on macOS with the system keychain.

[1] https://man.openbsd.org/ssh_config.5#AddKeysToAgent


Recent macOS versions don't have `ssh-askpass`, and it's weirdly hard to add one. Since agent confirmation depends on askpass, I don't think there's an easy way to get this work on macOS.

Aside from the missing context you mentioned, the other bigger problem with this approach is that agent confirmation is all-or-nothing: it turns on confirmation for local SSH connections in addition to forwarded connections. If you're using SSH a lot, having to confirm every connection is very annoying.


Slides: https://www.slideshare.net/cloudinarymarketing/imagecon-2019...

Background: JPEG XL is a combination of Cloudinary's FUIF [1] (successor of FLIF [2]) and Google's Pik [3].

Committee Draft (Aug 2019): https://arxiv.org/abs/1908.03565

Technical Details: https://www.spiedigitallibrary.org/conference-proceedings-of...

Features / Goals:

- high quality compression (> 60% over JPEG-1)

- royalty-free with open source implementations available from the start

- versatile: supports alpha transparency, high bit depth (16-bit), lossless compression, animations

- progressive decoding / "responsive by design"

- legacy-friendly: reversible transcoding of JPEGs with 22% size reduction (demo available [4])

Comparisons:

- JPEG 2000, JPEG XR: only marginal compression improvements

- WebP: limited (8-bit, 4:2:0), no progressive decoding

- BPG/HEIF (HEVC): patent-encumbered (not royalty-free), no progressive decoding, complex

- AVIF (AV1): no progressive decoding, complex, slow?

[1] https://cloudinary.com/blog/introducing_fuif_responsive_imag...

[2] http://flif.info/

[3] https://github.com/google/pik

[4] https://google.github.io/brunsli/


From the video I was expecting even higher compression than HEIF, but > 60% over JPEG-1 seems to be about the same as HEIF.

And what are the downside? Whenever something sounds too good to be true it often means we are overlooking something.


There is a Japanese independent (simple) comparison between av1, bpg, WebP and pik for use in photo compression. Pik won it. JPEG XL is an improved from pik.

https://qiita.com/fg11894


I apologize for going off topic, but if the author is reading this (perhaps I should email him instead), please be informed that your work has been plagiarized on Amazon, by a book called "Python Programming: A Step By Step Guide From Beginner To Expert" [1]. Read the first few pages of the print book's "Look inside" and you'll see a word for word copy of the book.

Not only did they plagiarize your work, but they did a really poor job of it too. The print is full of formatting issues. The code blocks are not properly indented, which is not only poor style but also broken given that python is white-space sensitive. And bizarrely enough the letter "q" is continuously in bold throughout the whole book. You can easily verify this from the pictures by the reviewers. I don't actually own a copy of the book myself.

To make matters worse (or better?), they only decided to include the first four chapters, ending at "Conditional Execution". Yes, the plagiarized book claims to be a guide "from beginner to expert", yet it didn't reach the chapters on loops and functions!

If you read the reviews, you'll quickly notice that it's full of fake five-star reviews with very vague sentences, some of which don't even make sense. You'll also (now) see a lot of real one-star review, which means that quite a number of people have fallen for this scam.

Surprisingly, one of the fake reviewers even got in Amazon's top 100 reviewer list. Check the profile of "Kip Krenz" [2], who is currently at rank #53. Somehow he managed to review two to four books on a near daily basis for maybe a year or more, mostly five-stars (the rest are four-stars) and full of generic sentences. The books reviewed are most likely "fake" as well. They often fall under one of the following: a beginner book, a self-help book, a cookbook, a trading book, or a book on one of the latest fads.

This book is unfortunately just one of the many fake books (not the jazzy kind) that have proliferated on Amazon. If you look at the other recommendations, you'll probably find another one of these books (Python seems to be one of those profitable topics).

A common technique used by these books is to put themselves under some niche category in order to get a high rank. For example, this book categorized itself under "Microsoft C & C++ Windows Programming" [3], and is currently at #9 there (it used to be #1, but thankfully the real reviews probably dragged it down). For a more peculiar example of this, take a look at what's #1 under "Windows XP Guides" [4].

Sorry for going on a tangent with such a long wall of text. I spent a night "investigating" this whole thing a few weeks ago, and after seeing this post, thought that it would be best to spread awareness of the issue here.

[1] https://www.amazon.com/Python-Programming-Beginner-Intermedi...

[2] https://www.amazon.com/gp/profile/amzn1.account.AGXMOOP4UKWV...

[3] https://www.amazon.com/gp/bestsellers/books/3967

[4] https://www.amazon.com/gp/bestsellers/books/6134002011


Original author here. Someone else discovered this and notified me about three weeks ago. Amazon has a site for reporting infringement, so I submitted my claim of ownership. I received an immediate automated response promising a follow up, but I have yet to hear anything more.

In the book's front matter I grant permission for anyone to use the book freely and to make as many copies as they like as long as the original copyright notice remains intact. It started out as my small way of helping my students who are facing escalating higher education costs. Over the years, I've received feedback from other instructors at both the university and high school level who appreciate having this option available for their students.


Thanks for writing this book. As a someone who has had some starts and stops with Python I look forward to giving this oen a shot.

It might be worth calling up Amazon customer service. They are usually very helpful and might be able to route you to the correct person.


I appreciate your research here. I've clicked the "report abuse" option for a few of the sketchy reviews on Amazon, and submitted my own review pointing to your post here, and the original PDF. Perhaps that will prompt Amazon review, or at least save a few potential buyers.


Don't apologise for this; your dissection, even if only a comment, was a tremendously enjoyable read. Well done for putting in the effort to research this!


Apparently someone thought it valuable enough to "pirate", so you can see it yourself here, unfortunately minus the bolded 'q' and bad paper quality:

https://bookflare.org/python-programming-a-step-by-step-guid...

It's perplexing why someone would copy only the first 4 chapters --- and do it poorly --- but I suppose it's enough to sell; maybe they're not as rational as me, since if I were to plagiarize and sell books, a search/replace of the author's name would've been sufficient. No doubt whoever is doing this is expending more effort for an inferior product.


Looks like another biased comparison to me. You could easily rewrite the TypeScript reducer example (which fails to compile btw) to be similarly concise while being as safe.

  interface State {
    movies: string[]
  }

  // you may also use { tag: "Action", payload: string }
  // if you prefer something more structured
  type Action =
    | ["AddMovie", string]
    | ["RemoveMovie", string]
    | ["Reset"]

  const defaultState: State = { movies: [] }

  const reducer = (state: State, action: Action): State => {
    switch (action[0]) {
      case "AddMovie": return { movies: [action[1], ...state.movies] }
      case "RemoveMovie": return { movies: state.movies.filter(m => m !== action[1]) }
      case "Reset": return defaultState
    }
  }

  const someAction: Action = ["AddMovie", "The End of Evangelion"]
TypesScript's type system is actually very flexible and advanced [1] compared to most type systems since it had to adapt to the very "dynamic" structuring of JavaScript in the wild.

[1] https://www.typescriptlang.org/docs/handbook/advanced-types....


ReasonML variants are type constructors. Your example completely eliminated all action creators (constructors). Once you add those functions back, most of the type bloat reappears.

I wouldn't want to work on a project where everyone was creating object literals and passing them to dispatch everywhere.


Yes, I eliminated the action creators. I don't see why they're necessary (maybe there's something about redux I'm missing?). The type constructors of ReasonML cannot be used as functions, so I think my rewrite is fair.

If you insist on having the action creators, they can easily be written as one liners each, which is a lot less bloated than the original example.

  export const addMovie = (movie: string): Action => ({ tag: "AddMovie", movie });
What's the issue with passing object literals? I know it looks a bit hacky and messy, but if it's typesafe (which it is) then it doesn't seem like a real issue.


No action creator is a serious refactor concern.

Let's say you need to update your function signature with an additional, optional parameter with a default value. You can go to the definition of the action creator and change it. Since you've defined an interface for the action object, finding reducers that use it will be reliable and easy.

If such a creator doesn't exist, you must grep your codebase for every instance of the object and ensure they deal with the optional bit. Murphy's Law guarantees that someone will have decided to procedurally generate the object making finding every instance very hard. Next, you have that reducer lookup, but you don't have a shared interface, so you're stuck in grep land once again to find all the reducers.

Finally, copy-pasting an object literal all over generally results in a larger bundle than reusing an action creator which is smaller and also minifies better.


If the lack of action creators is a serious concern, then the one-liner-each action creator I suggested should be sufficient without adding much bloat. How would the ReasonML example deal with that change though? Can the variant constructors take in optional parameters?

Using Murphy's Law is not very convincing. Even with action creators Murphy's Law guarantees someone would have just constructed the objects manually anyways. Having to grep the tag is not ideal, but it's not likely to be a problem in practice.

I doubt that the bundle would be significantly larger (especially after compression). Using actions creators introduces additional (function call) overhead too (and that would be insignificant as well).


This is what my redux stuff looks like with TypeScript:

    const constants = {
      addMovie: 'movies/addMovie',
    }

    export const addMovie = createAction<string>(constants.addMovie)

    export const reducer = createReducer(initialState, {
      [constants.addMovie]: (state, action: ReturnType<typeof addMovie>) => ({
        ...state,
      })
    })
But this forgoes applying any constraints to `dispatch` / the ability to have one giant union of all possible action types your app supports.


I'm fairly new to both TypeScript and ReasonML (both within the past month). The author's reducer example closely matches that of the official Redux documentation [0], so I'm not really sure it's biased. But, I could buy that it's not a best practice. Absent anything else, I've been using the patterns demonstrated in the docs. Is there a better resource I should be following?

[0] -- https://redux.js.org/recipes/usage-with-typescript


The question is as much how exhaustive you want your Redux usage typed, and also how much you want to stick to the "action creator" pattern. A lot of the action creator ceremony is to avoid throwing the wrong types of data to Redux dispatch and make it easier to refactor things when the data requirements for an action change. Typescript handles a lot of that no matter what, and you can lean on the Typescript type system more and the "action creator" pattern less, but it won't look "Redux enough" to more JS-focused developers and that may or may not be a source of friction.

Which is a long way around to: the pattern in that recipe is a good one, it's quite exhaustive in making sure everything is typed, and it's quite familiar to almost any Redux dev you will meet whether they come from JS or TS. You can get away with other patterns/recipes if you want looser typing or "looser redux", based on the compromises you are willing to take, but currently there's no strong recommendation for any such alternative pattern because the common recipe is "good enough", even if it has lots of little bits of extra "ceremony". (Ceremony isn't necessarily a bad thing, sometimes those rituals are helpful in getting your thoughts down and making sure you have everything you need planned out.)

But that's also part of why the example in the author's post is unfair to Typescript. It's as strict on types as the Typescript pattern, but it's "looser redux". It sort of has action creators, but those aren't proper functions from a JS perspective because they are type constructors that don't properly exist in JS. They also don't exactly correspond to/produce the usual sort of "plain JS objects" that Redux expects when dispatching ({ type: "DISCRIMINATOR_STRING", … }), which will worsen and even in some cases may break Redux debug tools/experiences.

(Semi-related, there is a Stage 1 proposal for pattern matching in front of TC39 that would also help reduce the switch case that TS needs to pattern matching closer to the ReasonML example. TS sticking to Stage 3+ proposals now means that it won't get some of these sort of nice to have things until JS does.)


Okay, thanks for elaborating. I think the part I had overlooked was the variant constructor not being a function. I had mentally mapped that as a `dispatch` call with the variant being the payload. But, yeah, it looks like the author either made a mistake or took a shortcut there.


BuckleScript (ReasonML's-to-JavaScript compiler) has an annotation that automatically creates functions from variant constructors. E.g.:

    [@bs.deriving {accessors}]
    type msg =
    | Increment
    | Decrement
    | Reset
    | Set(int);

    let action = set(2);


I don't have experience with Redux so I cannot comment on that, but I do believe my rewrite is equivalent to the ReasonML example (it should express the same thing and still be typesafe).

While I'm sure the author did not intentionally try to make TypeScript look bad, (imo) they didn't put enough effort to make it look good either. There's a lot more to TypeScript that this post fails to mention. ReasonML is a good language (I think OCaml was just fine though), but TypeScript is good too.

The author says "ReasonML is everything TypeScript tries to be (and a bit more) without all that JavaScript weirdness.", but I strongly disagree. Embracing "all that JS weirdness" is the whole point of TypeScript, and what makes it so successful. Unlike most typed languages, TypeScript (for better or for worse) adapts its type system to the developer's code, not the other way around. This is why its type system is much more expressive than many other type systems including ReasonML's.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: