HN user

lilactown

849 karma
Posts2
Comments260
View on HN

I believe Borkdude showed it was possible by first implementing async/await in Squint, his alternative* implementation of ClojureScript, and then took those learnings to the core CLJS compiler.

If your inbox is as big as mine, you won’t be able to load all the text content into a prompt even with SotA cloud hosted models.

Instead you should give it tools to search over the mailbox for terms, labels, addresses, etc. so that the model can do fine grained filters based on the query, read the relevant emails it finds, then answer the question.

Pebble Round 2 7 months ago

Would buy this in a heartbeat (pun intended) if it came with a heart rate monitor.

I had the first Pebble Time Round and it's my favorite smart watch I've ever owned, but these days the things I want from a watch are to tell the time and collect biometrics. Taking a step back in biometrics feels like a bummer. I also totally buy that it would increase the foot print in a way that would feel way less slim.

I think it's as much about familiarity than anything else. I've programmed full time in Clojure for the last 6 years, and I find it just as easy to read than other languages I'm familiar with (JavaScript, Java) and way less easy to read than other languages like Haskell or OCaml that have their own syntax lineage. I'm sure if I spent an amount of time becoming familiar with them, I'd find them just as easy as I do Lisp.

There are certain things that languages can do that make syntax easier; for instance, Clojure's default constructs reduce a lot of parens compared to CL by using brackets [] and removing nesting. For instance

    ;; clojure
    (defn sum-and-square [a b]
      (let [sum (+ a b)]
        (* sum sum)))

    ;; common lisp
    (defun sum-and-squaer (a b)
      (let ((sum (+ a b))
        (* sum sum)))
This leads some people to assert (with other reasons too) that Clojure is not in fact a "lisp."

AFAICT after the first write, the inner promise is resolved and will return the same value it was resolved with even if subsequent writes are made. This is totally different than Go-like channels which can receive multiple writes, often handling buffering them until they are consumed.

I also didn't think to look in the "language extensions" section of the manual, instead going to the API docs and clicking on the "Effect" module.

This looks much more interesting, on a skim. Thanks!

Is there a guide on how to use the new constructs? The link to the 5.0 docs was broken on the site, and after manually fixing the URL all I found was some type annotations in the `Effects` module.

Yes, an outpouring of sympathy, empathy, etc combined with the same unilateral decision making that technologists make would be terrible. I would call continuing to do that unempathetic.

Technologists acting like technocrats and expecting everyone to give them sympathy, empathy and identification is laughably rude and insulting.

The Twitter Files 4 years ago

Twitter's now owned by Elon, who is making friends with right wing reactionaries in public.

Fox News is the most watched news channel on the continent.

All tech companies at the very least are pro-capitalist, it's often a choice of whether they're outwardly more pro-market or more technocratic, which has nothing to do with political lefts and rights.

IMO this is one of the main benefits of Clojure from a lisp-er perspective: it actually takes multithreading seriously in its design. It basically chose the "yes add the machinery" option, but built the machinery into the design of the language.

For instance, vars (i.e. global bindings) are mutable storage containers that can be bound on a per-thread basis. `(def foo "bar")` creates a new var and interns it in the current namespace, binding a root value "bar". Using it in code looks up the current value of it, either in thread-local storage or in the root binding. Any thread looking up the root binding of the var will see a newly bound value immediately.

However! Data in Clojure is immutable, which means that even if a running program started by looking up the current value of a var (or any of the other concurrency-safe containers in Clojure), once it has that value it is guaranteed not to change underneath you.

e.g. if you have a process that looks up the current value of a var and does some work with it for 5s, an in-flight process will not be altered if the var is redefined in the middle of the work. Other processes could even be kicked off that would alter the var, and it will have no affect on each other unless you explicitly synchronize, since the data inside the var is immutable.

That's a reasonable hypothesis. My experience was mbsync would hang for many minutes, and eventually when I revisited the terminal it was in it had failed with a nondescript error.

I tried using a combo of mbsync, notmuch, and notmuch-emacs to start migrating away from Gmail's UI (and eventually moving away from their service).

I found, though, that mbsync failed to download updates after the initial bulk load.

Has anyone else run into this, and/or found a good way to use notmuch with gmail?

AFAIK (maybe someone else will correct me) there are two things that people run into when implementing interpreters:

1. You can't write a JIT because you need to be able to dynamically allocate executable memory, which is typically not allowed

2. The App Store needs to know up front what native methods & behavior your app accesses so that it can allow users to observe and control what your app can access. Accessing new native methods by downloading random code over the internet is not allowed

There are ways to get around (2) by ensuring you request access to everything your app could possibly access up front, but that could also lead to rejections for asking for permission for things your app doesn't actually need. It's a bit of a dice roll.

There was talk that ability to do (1) might be coming in an update a couple years ago, but no official policy change ever came of it.

The "Optimized B-Trees" section I _think_ is suggesting to get rid of datoms, which I 100% agree with. I do not think they add anything at all; IME you can have a collection of all attributes indexed by entity ID and then have additional indexes on top of that collection.

My stupid question is: why even bother with B-Trees? I believe asami[0] stores everything in memory using Clojure maps & sets.

[0] https://github.com/quoll/asami

The germ theory of disease is sprang up in many places of the world throughout history.

Setting that aside, cultural appropriation is something that just happens; it's not a moral good or bad, despite the way that it often gets talked about in culture war rants. It's an emergent phenomenon of different cultures mingling.

There are negative aspects of appropriation, such as decontextualizing something to the point of erasing its original meaning, or using it as window dressing to be "exotic," or to make fun of people. These things can feel especially crass to people when they're present in a system that denigrates or oppresses the people that they are appropriating those things from.

I can't speak for everyone, but to me it makes sense that the issue people have against appropriation of sacred customs or ornamentation of some cultures is that it seems disrespectful to the people who hold it sacred. I'm not even sure that's what the original article is saying, though.

STM, atomics and channels are all different things that can be use to build different kinds of systems, so I think it's good to disambiguate them when talking about concurrency problems and their tradeoffs.

Clojure' STM is basically unused. It's a suite of functions and a container type `ref` that allows you to do transactions in memory and keep everything consistent within the view of a transaction. The overhead required to do the book keeping for these transactions is often not worth it for most use cases in practice.

Clojure also, as an alternative, gives you `atom` which is a type that implements a simple thread safe compare-and-swap. This ends up being sufficient for many cases of sharing state between threads. When combined with Clojure's immutable data structures, one can often use them as a simple in memory database.

Those two things are about sharing memory, but has nothing to do with what the article talks about: green threads.

clojure.core.async, as the article succinctly explains, allows you to create "goroutines" or green threads which are then multiplexed across some number of OS threads. This can allow you to create many more threads for computation than you have OS threads, and combined with thread locals and atoms can allow one to build large scale systems.

Clojure's STM and atomics are sort of a non-sequitur from what the article is talking about

Now as for downsides of Clojure, there are plenty of gotchas in practice that can lead people to issues with the three things above:

* STM is slow and rarely useful compared to regular atomics

* atoms CAS assumes you are using immutable data structures

* core.async has a lot of sharp edges, including lack of first-class error handling and the fact that doing synchronous I/O on a go routine can end up starving the thread pool they are running on

I've never built a high performance web server, but I imagine it's possible with Clojure; it would probably require you to probably eschew immutable data structures within the plumbing (for performance) and use an async I/O framework along with core.async to get competitive with a language like go. For shared memory, you probably would end up eschewing compare-and-swap for something more bare bones like locks, which you have access to via Java interop. At that point, you may wonder why you even chose Clojure in the first place instead of using Java directly. :D

Project Loom really only helps solve the problem that core.async is trying to solve, and applications would still make use of atomics like `atom` and basic Java atomic values. My hope is that it makes it easier to do I/O, since it sounds like along with loom fibers the project is adding first class support for suspending and resuming on fundamental I/O operations. Time will tell.

The difference is that it's not "fools" that will accept USD, but people who are taxed by the US government. That's what keeps the USD from being worth nothing; even if you do all your transactions in crypto (which you shouldn't), you need to convert it to USD at some point to pay your taxes.

This is why actual currency and cryptocoins are not equivalent; there's no one forcing someone to eventually convert into cryptocoins, so the value of any individual coin can go quickly to 0 based purely on whims - or someone rug pulls and freezes sales, making off with all the money from people who have bought in.

In order for the USD to go to 0, the US Government would have to collapse. We might argue about how likely that is, but I think we can all agree that it's less likely than a cryptocoin staying at the top of the hype cycle.

Another difference between cryptocoins and currency is the deflationary nature of cryptocoins, which encourages holding, which (if used as a currency) slows the velocity of money in the system, which leads to all sorts of macroeconomic problems like shortages - because no one wants to buy things, people stop making things.

Stablecoins and every other crypto scheme are just speed running the lessons the financial crashes should have taught us over the last 20 years. It shows there's a large swathe of people who saw the crash and thought that they want to be the ones who get rich and then bailed out, rather than preventing them from happening in the first place.

I think the article comes off to many here as anti-technology because it doesn't continue past the thesis: Apple's vast amount of unilateral control over devices and software gives it the ability to surveil the population in ways that were not possible before. It then goes on to suggest a very consumer-centric way of addressing this, through a special iPhone that's more privacy-centric.

This ignores two big things we have to address when thinking about mass data collection.

1. The ability to collect data at scale unlocks capabilities that simply weren't possible before. There are lots of positive outcomes that can come out of this. Focusing on only the negative can lead one to a sort of primitivist mindset, and it convinces no one who feels the positive effects of it.

2. Apple could very well offer a phone with no facial recognition, rock solid encryption, an easily coverable camera, and it would affect close to nothing. The entire point of mass data collection is the "mass" part of it, and as long as people observe the benefits of being tracked (i.e. using maps, social media, finding their lost things, getting notified when their heart rate is up, counting their steps, tracking their sleep, getting notifications, seamlessly backing up their contacts and photos, dictating messages, etc.) then they will continue to be able to collect mass amounts of information regardless if some individuals choose to abdicate completely.

Other people are pointing these things out in the comments because it's the natural antithesis to what the article offers.

Salome Viljoen[0] talks about this thesis/antithesis in her research on data privacy and ways to treat data from a legal perspective. She explores an alternative to the "I'll just take my data elsewhere" and "I'll just not let my data be collected at all" approaches: democratic data governance[1].

One path forward reconceives data about people as a democratic resource. Such proposals view data not as an expression of an inner self subject to private ordering and the individual will, but as a collective resource subject to democratic ordering. Democratic data governance schemes consider the relational nature of data: information about one individual is useful (or harmful) precisely because it can be used to infer features about—and thus make decisions affecting—others.

The problem is not necessarily that Apple (or Google, or anyone else) is collecting data. The problem is that we have very little say in what data they collect, or what they do with it afterwards, because the data is captured by corporations that act as data fiefdoms without any sort of democratic control.

Unfortunately, the massive valuations of these companies are essentially based on the amount of control they have over the data they collected, because it gives them incredible abilities to extract more value out of it. Any loss of unilateral control would be seen as a threat to the value of the companies, which in America makes it very politically distasteful right now. Perhaps that can change.

0: https://scholar.google.com/citations?user=rH63p3sAAAAJ&hl=en 1: https://phenomenalworld.org/analysis/data-as-property

Project Loom is both about the JVM and the language Java. Most of the work for Loom AFAICT is at the JVM level, and the benefits are that all Java code will Just Work(TM) with the new primitives underneath them at the end.

Scala’s varied async/concurrency libraries are implemented in user land, and still use threads underneath. Mechanically, you must opt in to these and have to work to interop with code that might use other primitives. Scala can handle a lot of this complexity at compile time w/ types, but it’s not perfect, and certain runtime behaviors will always be out of scope.

Loom improves this by allowing any language that runs on the JVM (Java, Scala, Clojure) to opaquely use virtual threads to run their existing synchronous, scheduler-unaware code on the new Loom concurrency primitives implemented in the JVM. That’s powerful!