HN user

ericmoritz

734 karma
Posts6
Comments226
View on HN

Java's verbosity made us all hate type systems in the early 2000s so many of us migrated to dynamic languages such as Python, Ruby in the mid 2000s that allowed us to work fast and loose and get things done.

After about 10 years of coding in a fit of passion we ended up with huge monolithic projects written in dynamic languages that where extremely brittle.

Fortunately languages with type inference (Rust, Golang, OCaml, Scala, etc) started becoming the answer to our problems. (We also collectively decided that Microservivces were another solution to our woes though that cargo cult is being questioned).

So we have a decade of code and packages written in Python and JavaScript that work well for our use cases (Data Science, MVP web apps/services, Database integration, etc) that is hard to give up. Often because alternatives aren't available yet in the statically typed languages (Hurry up Rust!).

There is often a lot of friction to get new languages introduced. I love Rust, but I don't think I can introduce it into our Golang/NodeJS/Javascript environment anytime soon.

I don't know for certain without digging into the code but they are probably using the WebCryptoAPI and doing everything client-side to encrypt the file.

The URL that is shared contains the key for the file. You'll notice that the URL contains a fragment identifier, i.e the #foo part of http://example.com/#foo, this isn't transmitted to the server by the browser and therefore the key isn't exposed beyond who the URL is shared to.

https://www.w3.org/TR/WebCryptoAPI/

We don't need another federated network. Administrators of those nodes are putting themselves into danger. What we need to develop is a purely decentralized p2p network that is resistant to censorship and eavesdropping.

No, usually there's an accept process spawning working processes and passing the connection off to it.

Erlang can have two versions of a module present in memory at a time. At the moment of a code upgrade, the processes working with existing connections continue to use the old code while newly accepted connections are passed to the version of the module that was loaded in between connection accepts.

The comments here describe doom and gloom of the web dying.

I doubt the web is going anywhere. The future is going to hyperlink driven link data services that can power both native and web clients.

I have started to architect such a solution for my employer and let me tell you, it is the freaking future!

This is a fantasy of mine as well. A generic opensource PaaS would be awesome. Now if I just had the ambition... It is quite an undertaking.

this isn't any better than using a live server for testing.

Build a good client library for your applications to use, mock the client library and don't worry about tests failing because of availability problems.

Using generators in Python will get similar laziness in Python:

    from itertools import imap
    map(f, imap(g, imap(h, someList)))
I think Python 3's map built-in is a generator so you no longer have to use the itertools module.

Unfortunately we don't have . or currying in Python so no pointfree python :(.

    from itertools import ifilter
    # ugly python function with a "Maybe dict" return type
    def query(data, date):
        """Return the first dict where date is > x['date'] or None"""
        is_greater = lambda x: date > x['date']
        return next(
           ifilter(
               is_greater,
               data
           ),
           None
        )

If you really want power, use NumPy:

    from numpy import arange

    def squares_numpy(n):
        a = arange(n)
        return a * a

    $ python -m timeit -s "from squares import squares_append" "squares_append(1000)"
    10000 loops, best of 3: 130 usec per loop
    $ python -m timeit -s "from squares import squares_comprehension" "squares_comprehension(1000)"
    10000 loops, best of 3: 95.4 usec per loop
    $ python -m timeit -s "from squares import squares_numpy" "squares_numpy(1000)"
    100000 loops, best of 3: 5.31 usec per loop
Why Use Make 13 years ago

I can't tell you how many projects I've shelved for months and when I returned thought, "Damn it. How do I build this again? Oh look a Makefile. Thank you Past Eric."

Even for projects that use more sophisticated build tools like rebar, leiningen or npm I write a Makefile so I don't have to remember those tools. Make provides a universal interface to those tools.

Yeah, because of cowboy and Erlang's design it is going to out perform a single process evented server hands-down.

  1. The evented servers are bound to one CPU, Erlang will use all CPUs 
  2. any bit of blocking code will stall the other code, even it just for a moment.
It is a little unfair to compare the two approaches.

As far as I know, the one process per dyno is not a restriction that Heroku puts on the application, it is an architectural decision of the application.

Spawn up worker pool if you want > 1 req at a time.

"OTP in Action" is an excellent book for learning OTP.

The following reading will take you a long way with Erlang:

Learn you some Erlang http://learnyousomeerlang.com/

OTP In Action http://www.amazon.com/Erlang-OTP-Action-Martin-Logan/dp/1933...

On Erlang, State and Crashes http://jlouisramblings.blogspot.com/2010/11/on-erlang-state-...

"Making reliable distributed systems in the presence of software errors" http://www.erlang.org/download/armstrong_thesis_2003.pdf

The last two links are "Erlang propaganda" describing the hows and whys of Erlang.

Or Erlang

https://gist.github.com/bb01a85404e6b445dcb3#file_resolve_do...

    % -*- erlang -*-                                                                                                                              
    %%! -smp enable                                                                                                                               
                                                                                                                                                  
    worker(Hostname) ->                                                                                                                           
        {ok, IP} = inet:getaddr(Hostname, inet),                                                                                                  
        io:format(                                                                                                                                
          "~s => ~s~n",                                                                                                                                 
          [ip_to_string(IP)]                                                                                                                      
         ).                                                                                                                                       
                                                                                                                                                  
    ip_to_string({N1,N2,N3,N4}) ->                                                                                                                
        io_lib:format(                                                                                                                            
          "~w.~w.~w.~w",                                                                                                                          
          [N1,N2,N3,N4]                                                                                                                           
         ).                                                                                                                                       
                                                                                                                                                  
    main([DomainFile]) ->                                                                                                                         
        {ok, Bin} = file:read_file(DomainFile),                                                                                                   
        String = binary_to_list(Bin),                                                                                                             
        Domains = string:tokens(String, "\n"),                                                                                                    
        plists:foreach(                                                                                                                           
          fun(Domain) -> worker(Domain) end,                                                                                                      
          Domains                                                                                                                                 
        ).

This uses https://github.com/eveel/plists/