Recent submissions

Comment · 4 years ago
For any older java programmers that may have a bad taste in their mouth when they think of green threads: when Java first came out, it had green threads, and all N threads that were spawned were tied to a single kernel thread. It also required cooperative multithreading, where one green thread may need to yield.

Java upgraded to native threads, and then you could have N java threads bound to N kernel threads. This was way better, but had downsides: You're limited on how many threads you can spawn, you need a threadpool to help manage, and any long-running tasks could effectively deplete your thread-pool.

With Loom, now you have M green threads mapped to N kernel threads. These green threads are way cheaper to spawn, so you could have thousands (millions even?) of green threads. Blocking calls won't tie up a kernel thread. So if you have many long-running IO tasks, they aren't going to waste a kernel thread and have it sit around idle waiting on IO. This is similar to async libraries, but without the mental overhead. You should be able to just code synchronously and the JVM will take care of the rest.

Comment · 5 years ago
> Lisp is not widely used

This is so unfortunate. Lisp has so many good things to teach us.

Comment · 5 years ago
SQS FIFO is like 25-40% more expensive, but you're getting added benefit and additional guarantees in exchange.

For the most expensive tier: 40 cents per million API requests for plain SQS vs 50 cents per million API requests for FIFO SQS.

Like many AWS Services, it started off pretty basic or limited, but gradually and incrementally improved over time.

I started off pretty skeptical, but over time I've grown to be impressed with SQS and SQS FIFO.

Comment · 6 years ago
Not quite _always_. There were some documented caveats... the one I hit before was: Read nonexistent key, followed by a write of that same key, and then a subsequent read could return a stale read saying it didn’t exist. (even though it had just been written for the first time.)

Anyway I am glad to see these gaps and caveats have been closed.

Comment · 6 years ago
I went thru a magnetic pole swap, if you will. I went from growing up as a kid toying in C , later professional development in c++ and java. In college, had a small taste of functional style and found it difficult for my brain to grok. Later in life I took up clojure, and things started to click. Despite years and years imperative development, my personal preference is for the functional style.

I do find languages like Scala and Haskell slightly appealing, but I find many of the deep concepts and rigid type are orthogonal to the problem I am dealing with at hand. I realize for some working thru the type system helps them solve the problem at hand, but for me, it often seems to get in my way.

Comment · 6 years ago
You are citing case fatality rate for MERS and SARS, but not the flu (which is typically 0.1%), and yet in any given year the flu has killed many more people than MERS or SARS. Why? Because millions get the flu whereas MERS and SARS were contained.

Now consider that COVID-19 is much more contagious than the flu and it has a significantly higher case fatality rate than the flu.

Furthermore, people can and do protect themselves against the flu with a vaccine. There is no vaccine for COVID-19. And still further, no one is immune because the disease is new to humans.

So yes, while covid-19 has a 98% survival rate, a widespread outbreak could kill hundreds of thousands of people.

Comment · 7 years ago
I do agree that you should prefer functions over macros. The rule of thumb I’ve heard is only use macros if they are absolutely necessary.

But having that option is better than not having the option at all IMHO.

Comment · 7 years ago
What about JDBC?

Here's a few examples stolen from the doc page for the next.jdbc library (https://github.com/seancorfield/next-jdbc):

    > clj
    Clojure 1.10.1
    user=> (require '[next.jdbc :as jdbc])
    nil
    user=> (def db {:dbtype "h2" :dbname "example"})
    #'user/db
    user=> (def ds (jdbc/get-datasource db))
    #'user/ds
    user=> (jdbc/execute! ds ["
    create table address (
      id int auto_increment primary key,
      name varchar(32),
      email varchar(255)
    )"])
    [#:next.jdbc{:update-count 0}]
    user=> (jdbc/execute! ds ["
    insert into address(name,email)
      values('John Smith','[email protected]')"])
    [#:next.jdbc{:update-count 1}]
    user=> (jdbc/execute! ds ["select * from address"])
    [#:ADDRESS{:ID 1, :NAME "John Smith", :EMAIL "[email protected]"}]

That is an example REPL session to setup the library, setup a datasource, create a table, insert a row into the table, and then select from the table. The "user=>" part is the REPL command prompt. Essentially it's one statement for each SQL query executed, and 1 or 2 statements to setup the JDBC datasource. This is tight.

You can see the return from the select contains clojure native data-structures. It returns a list of rows, where each row is a map of fieldName to fieldValue. You can now go to town and manipulate lists and maps to your hearts content, convert the payload to HTML or JSON or whatever you like.

Comment · 7 years ago
Using the clj-http library in clojure to fetch from a REST webservice:

    (client/get "http://example.com/resources/3" {:accept :json :query-params {"q" "foo, bar"}})
With the response, you can examine response headers, the body, etc.
Comment · 7 years ago
Here is an example to massage/manipulate CSV data.

Stolen from the README page for a clojure CSV parsing library (https://github.com/clojure/data.csv)

    (defn read-column [reader column-index]
      (let [data (read-csv reader)]
        (map #(nth % column-index) data)))
    
    (defn sum-second-column [filename]
      (with-open [reader (io/reader filename)]    ; Read in the CSV file (streaming / lazily)
        (->> (read-column reader 1)               ; Convert to just the first column of data.
             (drop 1)                             ; Drop the first row (the CSV header)
             (map #(Double/parseDouble %))        ; convert each string in this column into double
             (reduce + 0))))                      ; sum the result

Because it's lazy, this code should work regardless of how large the CSV file.
Comment · 7 years ago
Not original poster, but my take is:

- Immutable data-structures with concise literals for lists, vectors, maps, and sets. Having pure functions and immutable data-structures makes code easier to reason about, easier to test, and thread-safe.

(But clojure doesn't "force" you to be pure. The idea is that you write as much of your code in pure functions as you can, and push the IO and impure parts to the extremities. It's very pragmatic in this way, and you can get real work done.)

- Simple syntax:

While the syntax may be intimidating at first and arithmetic looks weird to untrained eye, once you realize that everything is a function (or a special form that also looks just like a function), the very light syntax and consistency feels amazing/refreshing.

- Macro system:

This is tied to the previous point. Since all your code is technically a "list", and you have something akin to a pre-processor where you have the full library of clojure functions to manipulate data. But in this pre-processing phase, your data is the code. (the code is a list). Now you can dynamically re-arrange or re-write code. Lookup homoiconicty and learn about the kinds of things you can do in macros that can't be done in other languages.

- Capabilitis for general programming, abstractions, code re-use etc.

- Performance is quite good. It's often nearly as fast as java, yet your codebase might be 10x smaller because the language is so expressive.

- Concise/expressiveness. Clojure comes with a nice built-in library with generic functions that you re-use again and again. Give a programmer a few dozen of these functions and it's amazing what can be composed to solve many problems succinctly and elegantly.

- There are surely other benefits, but the last one I'll leave with is hard to explain unless you have felt it before. It's REPL driven development.

Clojure comes with some seriously awesome REPLs (i.e. a shell for interactive tinkering with the language). Other languages may have some form of REPL, but no other language in my experience has come close to the feel you get in a clojure REPL. I can best explain it as a freedom of very light-weight experimentation that you use to write your code. It's a playground for writing functions with very quick feedback to see if your code will work or not. One factor that makes the clojure repl experience so nice ties back again to the succinctness and expressiveness of the language. Typing commands in the repl is painless because it's concise, not a lot to type, and then the feedback is so instant.

Somehow when I write code in python, java, javascript, or other languages, I just don't use their REPL or shell as often. It's just not quite the same as the clojure repl experience.

Comment · 7 years ago
I second this. Struggle with each problem and then view other answers to see how elegantly they solved the same problems. This worked wonders for me as well.
Comment · 7 years ago
It seems like go's killer feature, initially, was it's approach to concurrency with goroutines and CSP.

However, race conditions are still quite possible with goroutines, and many experienced go developers seem to eschew goroutines. It seems like for certain niches go works wonderfully, but I'm not convinced it will become THE next enterprise programming language.

In fact, we may not have another language dominate the enterprise landscape the way java did in the 2000s. It likely will end up being a mix of go, rust, python, java, .net, and node, among others.

Comment · 7 years ago
The improvements in autopilot in my friends model 3 is truly astonishing to me versus the first gen auto-pilot in the model s. If the incremental improvements over the last 2 years are any indication of what's possible over the next 2 years, we are going to see amazing things. It may not go everywhere in every condition, but so what? Isn't it still totally mind blowing how far it's already come?
Comment · 7 years ago
Don't get me wrong, I'm not cultist. I agree w/ you that what is going on with the SEC seems reckless, and I don't like it. There are a number of things Musk has done that I definitely don't agree with. (However, I wouldn't call him a serial liar. He may exaggerate or stretch claims as many CEOs do.)

That doesn't change the fact that he's produced a great car and seriously innovated in many areas.

I am rooting for them to succeed because I think what they are doing is important and good for humanity. I am hoping Musk does the right thing, and doesn't get in further trouble with the SEC, etc. And I am hoping that the company is able to survive the tumult of the markets -- that is, the costs associated with electric cars and the supply/demand of the market. Sometimes the best technology doesn't win. It happens often. It would be a huge loss if it didn't work out.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton