proj-oot-ootNotes24

haspok 2 days ago [-]

One thing that is completely missing from the Erlang side of the article are the OOB monitoring and operating capabilities.

An Erlang VM is a living system that has a shell which you can connect to, and control both the VM and the applications running in it. You can also remotely connect to another VM, execute arbitrary code, debug, stop processes, start processes etc. It really is an operating system in itself, that was _designed_ to be that way.

And the best part is that you get all this for free. Whether that is a good thing depends entirely on your needs. You probably wouldn't want to replace your bash scripts with Erlang programs :)

What Erlang is not really suited for is where you need multiple levels of abstraction, such as when implementing complex business logic. You would think that the functional nature of the language lends itself to that, but then you quickly realize that because the primary concern of an Erlang engineer is to keep the system alive, and for that reason you must be able to reason and follow the code as it is running on the system, all kinds of abstractions are very much discouraged and considered bad practice (look up "parameterized modules" for an example of a feature that was _almost_ added to the language but was discarded in the end).

I think that from this perspective Erlang and Go are actually very similar - both prefer simplicity over abstractions.

reply

julienmarie 2 days ago [-]

Totally agree. Erlang is quite against "magic" which improves greatly readability. Debugging is really straightforward 99.9% of the time.

reply

---

"Error handling is really the least of it. Attempting to replicate some of Erlang's high-level design principles at a quickly lead to roadblocks. For example, goroutines cannot be killed; this means it's impossible to fully implement supervisor trees in Go. It's possible that the runtime could support this at some point, but it's a big can of worms."

---

a Scala guy's complaints on Golang, excerpted from https://news.ycombinator.com/item?id=13485953 :

extempore 4 days ago [-]

Paul Phillips here. I searched my tweet archive for my tweets about Go. Draw your own conclusions.

---

 _Codemonkeyism 5 days ago [-]

Maintaining a Scala code base for some years, I've learned a lot. I would not go back to a language that does not support Option/Maybe and map/flatMap. These really changed my coding style.

My largest problems [1] are all still there after years, developers only payed lip service and that killed Scala I think.

The largest bad design decision was to support inheritance which leads to it's own problems with type inference. Sad that after Java devs already recognized how bad inheritance is that Scala also got inheritance.

The sticking out problems is how very very very slow Scala compiles. This makes web development (even with Play) and unit testing a huge pain (and the complicated syntax + implicits + type inference makes IntellJ? as an IDE very very slow on detecting problems in your code)

Concerning the article I do think Futures are a more powerful (and higher) concept compared to coroutines. They are easier to combine IMHO [2]

Now trying Kotlin for the faster IDE and compilation speed, sadly the Kotlin developers think Option is only about nullable Types (it's not and something differen!) and don't embrace it.

[1] http://codemonkeyism.com/scala-unfit-development/

[2] http://codemonkeyism.com/a-little-guide-on-using-futures-for-web-developers/

reply

adriaanm 5 days ago [-]

The only thing on your list on your blog [1] that's still true is that we care about PL research. Since 2.10, we've worked really hard on improving the migration between major versions, and the feedback has been very positive. We'll keep working on finding the right balance between ease of migration and fixing issues in the libraries. Scala 2.13 will be a library release, with further modularisation of the library (towards a core that we can evolve much more slowly, and modules that can move more quickly, but where you can opt to stay with older versions as you prefer).

We've also invested heavily in incremental compilation in sbt. Sbt is meant for use as a shell, and it's super powerful when used like that. When I'm hacking the compiler in IntelliJ?, recompiles of some of the biggest source files in the compiler (Typers.scala, say) take just a few seconds. I rarely have time for office chair sword fights anymore.

With Scala 2.13, half of my team at Lightbend is dedicated to compiler performance. We'll have some graphs to show you soon, but our internal benchmarking shows our performance has steadily improved since 2.10.

reply

---

some complaints about Golang:

 waps 676 days ago | parent | favorite | on: “Go’s design is a disservice to intelligent progra...

I don't get where people get the idea that Go is simple.

1) go has generic functions : http://golang.org/pkg/builtin/, they're just not accessible to you

2) go has generic types : slices, maps, and channels, all of which have slightly differing behaviour, including some highly counter intuitive and contradictory behaviour (example: slices are pass-by-reference, arrays are pass-by-value. In other words []int and [5]int behave entirely differently)

3) go has overloaded functions : http://golang.org/pkg/builtin/, they're just not accessible to you

4) go has exceptions (panic/recover), negating all the advantages of Go error checking, and providing zero fixes for the problems it introduces (finding the source line where an error happened and if/how multiple errors are related. Easy in Java/C++/..., hard in Go) (in C++ you have to be aware of whether any external code you use throws exceptions ... in Go you have to be aware if any external code you use panics. And if you say I haven't dealt with it, that means that you quite literally haven't dealt with it. Same as in C++. External libraries throwing exceptions is perfectly fine ... as long as they never actually throw an exception. Panicing standard library is fine ... as long as it doesn't panic ... If you're looking for correct code, it is of course not fine)

5) Go's "simple" threading and panics. Try crashing a Go program with shared data with a null-pointer derefence in the shared data. Someone please explain to me how the resulting output is simple.

6) golang's own compiler and standard library are not in fact idiomatic Go. This goes from small problems (like total lack of unit tests in quite a few places), to larger ones, like not using interfaces for logging.

7) interface{}. I just grepped a reasonable, thoroughly reviewed codebase I've written, of several tens of thousands lines of Go. Result: 2.7 uses of interface{} per 1000 lines of code.

Is this what people here call simple to think about code ? I would argue that you don't understand a codebase until you've read it. That's a certainty. So can we at least agree there's a point where verbosity no longer increases readability ? I hope you can see Go is far past that point.

Go's type system : riddled with exceptional behaviour. Literally it says "type system applies unless it's doing <-, cap, len, copy, new, append or delete calls", in which case we do something custom. The resulting behaviour, of course, is inconsistent with Go's type system (which is really the point of the code of course, unfortunately, there's surprises buried in there, and those calls are inconsistent with eachother as well).

---

to summarize "What PHP Deployment Gets Right" by Ian Bicking, Jan 12 2008 [1]

...

---

The JVM is not that heavy (opensourcery.co.za)

https://news.ycombinator.com/item?id=13543233

---

nikcub 7 hours ago [-]

Microsoft seem to have learned a lot from Java in designing their new .NET Core CLR. It has gotten almost everything right:

Java may have missed the window for fixing some of these issues in their platform - I feel that if Android were being developed today, they'd almost certainly take .NET Core as the runtime.

I've yet to commit to using .NET Core anywhere, but from what I know about it so far it is impressive.

[0] https://github.com/dotnet/coreclr

[1] https://raw.githubusercontent.com/dotnet/coreclr/master/PATE...

reply

---

rspeer 13 hours ago [-]

Another wart (in a separate post from my other wart so that replies are coherent):

I understand why &str and String are different, but why do they act like they've never heard of each other? Why do they implement such different sets of methods? Why can't they be compared for equality, so I don't always have to type "literal".to_string()?

Haskell has problems with too many string types as well (worse than Rust, because the type of their default string literals is best avoided entirely), but they fix much of the problem with the OverloadedStrings? extension, which uses the type checker as something that helps you coerce string literals, instead of arguing with you.

reply

dbaupp 12 hours ago [-]

String == &str works. Maybe you were encountering some other problem.

reply

rspeer 12 hours ago [-]

Oh, I guess the case of this I encountered most recently was actually Option<String> == Option<&str>.

I get why that's different, but it would be great if the type system could figure that out, so that the literal Some("foo") could be an Option<String> if necessary. Maybe I'm still being spoiled by Haskell's OverloadedStrings?.

reply

---

pjungwir 7 hours ago [-]

So I'm only a Rust amateur (I mean I don't get paid to use it), but I'm on my third round trying to build something with it, and I feel like I'm finally starting to get it. A couple warts I've encountered:

If the next push is going to be for ease-of-use, those would be two nice things to fix.

reply

---

in Rust:

kibwen 15 hours ago [-]

> I always joke String should have been called StrBuf?

Agreed, and Vec should just be Buf! Let's fork the language. :)

reply

---

zyxzkz 16 hours ago [-]

Man, if developing programming languages was this easy, we should have done it years ago!

reply

lmm 15 hours ago [-]

We did. The ML family has been around for about 4 decades now. Not sure why they never caught on until Rust.

reply

jeffdavis 8 hours ago [-]

It's about the runtime. I think that's probably the most important reason, even more so than memory management or performance.

If you need to write a library to implement the latest protocol, or render the latest image format, or parse the latest serialization format, then Haskell seems great. Unfortunately, the resulting library will be useless except to other Haskell programmers. Nobody wants to link in libXYZ.a and get the entire Haskell runtime, starting threads and doing GC and sending and catching signals.

I tried implementing a handler in postgresql so that you could write user-defined functions in Haskell. I made little progress, even with help on IRC and elsewhere. Any non-trivial function would need to define its own types and use some libraries, but it was far from clear how to do that and the best advice I got was to dig into ghci and try to use some ideas from that. I started down that path, ran into runtime issues, and that was the last straw and I ran out of steam. And that was only to get the most basic functionality: call into haskell to do some computation and return.

reply

---

" What's missing is help. A great command line needs to reach out and hug you in every way it can. It needs to assume you don't know anything at all about the system. It's there for you to solve your problems, but also to help you explore.

There's actually one exotic Unix shell that does it right: fish. fish jumps through some pretty amazing hoops, like parsing manpages, to give you context and completion. "

" How should it actually work? Let's say you're trying to put Urbit in control of your Twitter feed. That means you're creating a Twitter gateway on Urbit, which you can control with a

twitter command.

Before you type a character, Urbit offers you

(any command with side effects). (You could also add a ! prefix, which is like sudo -- it lets you do something dangerous.) Once you type , you can page through a list of commands. Once you type t, that list is much shorter. Once it can tab complete to twitter, it prompts you with that.

And once you get to

twitter, you're in a "meta-generator" that's helping you build the correct command line. At least in a browser, you'll be stepping through a form with rich entry. But the command line will show you the text of the command you're building, so next time you can just type it.

Building a command is just a case of data entry. In a command-line world, data entry is always serial. You answer questions serially, one at a time. The only navigation is forward and back.

A great Urbit console also has to be accessible both from a browser and a Unix terminal. That means a prompt needs to tell the console if it could be a radio button, even though a terminal can't have a radio button. We'll improve the interactivity of our terminal a little, but we're not rewriting Lynx. "

---

"Three of the four languages most often used at Google (Python, C++, Go) do not allow multiple versions of a library to be linked into a single process due to symbol conflicts. This is a limitation of those languages, "

---

https://fsharpforfunandprofit.com/posts/is-your-language-unreasonable/

---

" There are ~38 HTTP response codes. Below is a complete list. I’ve shortened a few titles in the interest of space: Method Method 200 OK 201 Created 202 Accepted 203 Not authorized 204 No content 205 Reset content 206 Partial content 300 Multiple choice 301 Moved permanently 302 Found 303 See other 304 Not modified 306 (unused) 307 Temporary redirect 400 Bad request 401 Unauthorized 402 Payment required 403 Forbidden 404 Not found 405 Method not allowed 406 Not acceptable 407 Proxy auth required 408 Timeout 409 Conflict 410 Gone 411 Length required 412 Preconditions failed 413 Request entity too large 414 Requested URI too long 415 Unsupported media 416 Bad request range 417 Expectation failed 500 Server error 501 Not implemented 502 Bad gateway 503 Service unavailable 504 Gateway timeout 505 Bad HTTP version "

" Consider, for example, when we might use the 200 OK response code. Should we use it to indicate the successful update of a record, or should we use 201 Created? It seems we really should use a code like 250 Updated but that code doesn’t exist. And can anyone out there explained to me what 417 Expectation failed really means? I mean besides Roy? "

" The REST vocabulary of methods and response codes is simply too limited to effectively communicate the wide variety of requests and responses required across all applications. Imagine we create an application where we want to send a “render complete” response back to an HTTP client. But we can’t do that using an HTTP response code, because (a) one doesn’t exist and (b) HTTP is not extensible " [2]

" int_19h 1 day ago [-]

What we really need is a set of verbs that allow to reliably distinguish between these three types of operations:

1. Pure read.

2. Impure (stateful) read.

3. Idempotent write.

4. Any other write.

There's no particular reason to separate inserts, updates, deletes etc as part of the protocol - they're all just different kinds of writes, and middleware doesn't derive any benefit from being able to distinguish them. Thus, this can be a part of the payload.

On the other hand, the difference between reads and writes, and the two subdivisions within each, do matter for purposes such as caching and automated error recovery (e.g. a proxy can repeat an idempotent write a few times before returning the error to the originator of the request).

In REST, we have GET for #1 and #2, PUT and DELETE for #3, and POST for #4. In practice, this is often simplified to just POST used for both #3 and #4, but that loses a valuable distinction (but is unfortunately often necessary because of the lack of support for other methods). On the other hand, the PUT/DELETE distinction is largely pointless.

reply "


" Waterluvian 21 hours ago [-]

When I was given the task of defining how our multi-robot server would interface with our user interfaces, I eventually settled on REST. Most of what I knew about REST had been obtained that week. I implemented something pretty vanilla with Django and it all felt pretty elegant. I didn't have to worry about defining a protocol, there was pretty much already one for me:

It was all nice and worked great (and still does, years later).

But over time numerous people started told me that no it's actually all wrong for one reason or another. I've heard that I should never use anything except GET and POST. That I should ALWAYS return a 200 and provide error metadata as a response if there actually was an error. That POST is actually meant for updates and PUT is meant for new entities. That the opposite is true. That neither is true and I should always use POST for any mutation of state. etc.

I feel like I had success because I approached it from a position of ignorance, meaning I just implemented a simple, sane REST API and was none the wiser that I was doing it wrong.

reply "

"

stymaar 18 hours ago [-]

> If it's independent of HATEOAS what is in REST?

Using GET/POST/PUT/DELETE with a defined semantic, the confidence that GET is idempotent, and the proper use of HTTP status codes.

Back in 2005, it was really common to have only GET routes even for update of deletion, or worst: to have a single url: http://example.org/action which concentrated all the API surface, different behavior being triggered by the type of the payload (JSON or even XML). Also, all the errors where `200 OK` but with a payload which contained the error. It was all done on top of HTTP but nothing was really using the HTTP tools (route + method + status code). "

---

legulere 1 hour ago [-]

> YAML is so much more complicated and harder to parse.

YAML has more complexity in syntax, but a data model that fits to data structures in programming languages (records/maps, arrays/lists, integers, floats, boolean, bytes, strings). As long as you do not implement a YAML parser yourself (why would you do that?) you should have easy times with YAML.

XML on the other hand is relatively easy to parse, but has a complex data model that maps well just to a DOM. For anything but markup text, you do not have a direct mapping to/from XML.

> Developers write hundreds of lines of XML all the time... its called HTML

There it makes sense, because it is marked up text you are writing and it is the right tool for the job.

reply

---

bad_user 6 hours ago [-]

You're missing the forest from the trees. Java libraries and frameworks are complicated because Java the language is not expressive enough.

As I like saying, the status quo in Java land is Spring and Hibernate and people bemoaning Scala's implicit parameters never wonder why such monstrosities like Spring or Hibernate happened. Sure, blame the culture, but that's only half the story.

The same thing happens with other inexpressive languages. One of them is Python. And here we disagree again, as I think Python is chock full of ugly parts.

It started with refusing powerful and multi-purpose language features, like multi-line anonymous functions. As a result Python has been patched repeatedly with multiple non-orthogonal features to supplant the need for multi-line anonymous functions and/or to make up for its statement oriented nature. Oh, now Python 3 got await/async as well, but somehow I don't think this will stop people from monkey patching the socket module. I'm going to make the claim that in fact Python is not a TOOWTDI platform, in spite of its much touted "spirit" and anybody making that claim never tried working with Gevent or Eventlet, trying to make it work with MySQL?'s client and being forced to use the native client because Django wasn't compatible with the pure one. Or with an N-th iteration of Ruby inspired libraries that hack into its meta programming features to make it smell like the DSLs in Ruby, but with limitations and leaks. I don't even want to talk about the build and dependency management tools in Python's land, because it should be self-evident how broken the Python ecosystem has been.

Another language in this category is Go. It's still young enough that people haven't used it much outside the niche it was created for and doesn't have much reuse going on in libraries. Give it time, you'll see the same pattern, same mistakes repeated again and again. Java was also a pioneer in dealing with concurrency, Java introduced generics really late and it was also built by famous engineers working for a sexy company, designed to appeal to beginners and managers.

reply

JustSomeNobody? 5 hours ago [-]

No. It's not the Java language. It is the developers. They are the ones who have to have 35 levels of abstraction. Why? Because for some reason they think this will make modifying the software they write easier. In reality, no, it doesn't because everyone gets frustrated wading through the abstractions. If I can hold ten items in my brain's working memory and all ten are taken up by keeping track of how many levels deep I'm in, then it is really hard to make any real changes to the code.

reply

dlwdlw 20 minutes ago [-]

I agree that there is a Java culture, but I also think that it developed into the way it is because it was so popular during a time when there werent very good engineering practices by non-technical people. The movement towards wanting managers with a technical background I think is fairly recent. The majority mass of java developers now probably "grew up" in the jaded horror story environments we seek to avoid.

Also, i think new grads tend to only know how to make things dry via abstraction (not considering the trade offs) and b/c of javas popularity and oop as a buzzword, always did it via inheritance.

reply

---

cle 2 hours ago [-]

The problem with Java+XML isn't XML itself, it's that the Java community for a long time was pushing more and more critical code into XML, because doing non-trivial dynamic things in Java itself can be a huge pain. And so over time, enterprise Java apps became giant balls of XML+Java that would break at runtime if you missed an XML parameter or had a stray character somewhere. At that point, what benefit are you getting from Java's static typing? You lose much of the benefits of Java, and suffer twice as much from its drawbacks.

This is slightly better with the push away from XML and toward annotations, but it's not much better. Your program's behavior still depends on tagging the right language constructs with the right magic tags, which is a horrible way to program IMO.

reply

sreque 40 minutes ago [-]

I agree with cle, and I care enough to give examples of painful XML coding in Java:

Java is not a dynamic language, sorry. The JVM bytecode is fairly dynamic, but the language certainly isn't.

Also, I think Java would have been better off never introducing annotations. They have their uses, but they've been so over-abused that I would consider them a net negative on the language as a whole. I've been thinking about starting a blog, and one of my initial blog posts may be why annotations are bad for Java.

reply

---

TheCondor?