HN user

heartofgold

262 karma
Posts0
Comments21
View on HN
No posts found.

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.

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.

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.

A Little Clojure 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.

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.

Why Clojure? 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.

Why Clojure? 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','john.smith@email.org')"])
    [#:next.jdbc{:update-count 1}]
    user=> (jdbc/execute! ds ["select * from address"])
    [#:ADDRESS{:ID 1, :NAME "John Smith", :EMAIL "john.smith@email.org"}]

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.

Why Clojure? 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.
Why Clojure? 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.
Why Clojure? 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.

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.

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?

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.

A lot of people want to trash Musk and Tesla, but I look at it this way:

- Sure the CEO might be too active on twitter and at times say or do things typically considered inappropriate CEO behavior.

- Musk often makes bold claims and sometimes misses his projected dates.

However:

- Musk also is often right.

- He delivered amazing things with the model s. The Audi e-tron looks quite nice and I think competition is nice, but it still doesn't match the 2012 model s specs.

- He wanted the model 3 entry price to be $35k. Lots of peopple doubted he could do it, and many projected it wouldn't be available until 2020 or later. It looks like the base model 3 I can order is about $39k and with tax credit brings you downt to $35k and change.

- He promised autonomous driving 2 years from 2016, and honestly many people thought he was nuts. And his prediction was overly optimistic here, but there have been a steady stream of amazing incremental improvements to auto-pilot. On freeways, the tesla can now determine when to change lanes and does it. It can follow navigation within freeways, and it can warn you if a stoplight or stopsign is approaching. They demoed true autonomy, and I believe it's actually getting quite close. Given 1 or 2 more years of incremental improvements, your tesla would be capable of driving you most places I would think. He didn't make his 2 year prediction, but his team at tesla is still doing amazing innovation in this space.

- Part of what makes a great innovator is being able to fail sometimes. Musk will continue to make bold claims, sometimes he will fail to fulfill it, but many times he will deliver.

What he's doing is nothing short of amazing. He's doing things people keep saying can't be done. Re-usable rockets that land? Electric cars? Cars that drive themselves? I'm willing to tolerate a little shenanigans in exchange for this kind of innovation.

If you want to look at it that way, you also should include the emissions/environment impact included in acquiring the oil, building refineries, the emissions during the refinery process, and the shipment of the fuel around the country.

https://cleantechnica.com/2018/02/19/electric-car-well-to-wh...

And with electric cars, the ongoing CO2 emissions can be limited by where you get your charge. If you have solar for example, your not contributing any additional emissions beyond what it took to produce your solar setup. With an internal combustion engine, you don't really have much choice on how your fuel is produced.

For me personally: - I started out just learning navigation. How to move around within buffers, how to open multiple buffers and move around between buffers.

Then I learned several built in commands.

Years later I learned clojure, a lisp dialect. After learning it, and then looking back at emacs lisp (elisp), and a light bulb went on for me. You can write any elisp function you want, which has functions to manipulate text within buffers and much more. Using it you can create any kind of specialized editor function you can dream of, and you can call that function with "M-x function-name". If use use the function lots, then you can bind that function to a keystroke. (For example, if you wanted a completely custom function... to delete the current block of code, you could write an elisp function to go to move the point to the blocks beginning brace, set the mark, move to the matching brace, and then delete the region.)

There are several "modes" that define how buffers behave. A clojure mode will know how to highlight code and navigate around parenthesis. Magit-mode knows all kinds of commands for operating a git project, and org-mode knows commands to help facilitate note-taking.