HNHacker News
TopNewBestAskShowJobs

yokohummer7

619 karma · joined August 17, 2015

submissionscomments
yokohummer7··on My Livecoding.tv account deletion saga
It is also interesting that only the second line has a plus sign at the end. I'll have to infer the meaning of that.
yokohummer7··on My Livecoding.tv account deletion saga
What on earth is this? Is this something like a joke?
yokohummer7··on Rust-Doom: A Doom renderer in Rust, with no unsafe code
We're all here to exchange each other's opinions. If you don't feel like listening to others' opinions, why are you here in the first place?
yokohummer7··on Rust-Doom: A Doom renderer in Rust, with no unsafe code
Please not this again. The article you mentioned is incorrect in many places, and was heavily criticized in various communities.[1][2] It doesn't qualify as a valid criticism. It is rather a badly written static analyzer promotion.

Also, microbenchmarks are usually not very good at representing the real world characteristics. But then again, please look at the current version of the linked benchmark.[3] Rust now positions itself in the second place, thanks to the recent improvements given to the Rust programs used in the benchmarks. I believe Rust isn't as fast as highly optimized C, but I think it is safe to say that Rust is just as fast as C++, and both Rust and C++ are much faster than GC'ed languages such as Java, Haskell, and Go.

Edit: I would even say that if Rust's performance is comparable to GC'ed languages, there's no point in using Rust in the first place. Rust is paying a lot of complexity to achieve memory safety without relying on garbage collection.

[1] https://news.ycombinator.com/item?id=9531822

[2] https://www.reddit.com/r/cpp/comments/35pn6h/criticizing_the...

[3] http://benchmarksgame.alioth.debian.org/u64q/which-programs-...

yokohummer7··on Problems with Go's design
> The big difference with stuff like GC and re-writing stuff in go slowing the compiler time is that they are not inherent to the language.

Actually, I think GC is inherent to the language, and that's why I listed it as one of the trade-offs that Go made (not the Go implementation made). Almost every language construct depends on GC, e.g. append(), make(), and more. Even the following innocent-looking code:

  func f() *int {
    a := 1
    return &a
  }
is GC-dependent, because it would result in a dangling pointer in non-GC languages. But the code is perfectly fine in Go because GC is inherent to the language. It is not possible to make GC optional in Go, so the performance penalty will stay there forever, only alleviated as the implementation matures (or sometimes regressed, as Go 1.5 shows), unless you use only unsafe.Pointer all the time.
yokohummer7··on Problems with Go's design
This is a typical instance of solving language issues with excessive tooling. I find it uneasy that we will be reproducing all the baggage Java required us in a different language. And even Java didn't have mandatory imports.
yokohummer7··on Problems with Go's design
The reason why I think generics are relevant to point 4 is that generics can be thought as "first-class interfaces" which seem to be wanted by the author. Yes, the author suggests a method that is not acceptable to my taste (implicitly converting []struct to []interface), but if Go had generics he might have not complained about the lack of "first-class interfaces", because generics are in some ways "interfaces on steroids".

As for the core features of Go you mentioned, sorry again for my cynical wording, but I think they are a bit dishonest.

They stress on the performance of the program, yet being slower than C/C++ due to the usage of GC and dynamic dispatch all the time. It was even regressed in Go 1.5[1], because the new GC prefers latency to performance. So, they traded performance for something considered more important.

How about the performance of the compiler? Well, the speed of the Go 1.5 compiler is ~10% worse than the previous one, because they rewrote the compiler in Go (it was previously in C, for those who didn't know yet). Why did they do so? Because it has advantages: reduces the barrier to contribute to the compiler, improves the code quality, etc.. Yet they traded performance for something they consider to be important.

And the performance of the developer... While Go is not very terrible at developer experiences, it isn't very good either. Embracing simplicity led to lack of expressiveness, a typical example being generics. While this isn't entirely a bad thing, it is, again, a trade-off.

So they make trade-offs all the time. Then why are generics not considered to be good enough to make a trade-off? Because they think so. It is their opinion, sure, but claiming generics are impossible because performance isn't very convincing to me.

[1] http://yokohummer7.github.io/blog/2015/09/01/go-1.5-regressi...

yokohummer7··on Problems with Go's design
Sorry to bring up this yet-another-generics-ranty-thing, but actually point 4 is a typical issue that can be nicely solved with generics, by defining a function that works on every type that implements Foo. In this way you can directly pass a slice of Foo to the function and achieve type safety at the same time. As stated by the author, there's a demand for manually constructing an interface-slice in Go, and this shows a good example why generics can be useful.
yokohummer7··on Environment Variables and Path in Windows 10
If you place environment variables in ~/.bashrc, it would work. However, generally they are placed in ~/.profile which is read only when a login shell is launched. (And ~/.bashrc is not even read when you start a GUI session, anyways.) This is especially problematic in the GUI environment because in that case the login shell is the desktop environment itself. So you need to restart the whole environment (close all the windows, logout, and login) to load the new environment variables.

Windows gets over this problem by letting the login shell (explorer.exe) reload the environment variables in place. So, if we are to do the same thing in Linux, we might have to patch bash, zsh, and GNOME etc. to understand the environment variable change events and reload itself appropriately. I'm not sure where to start, but I believe this is the one thing that Windows did right, so I want to see it happen.

yokohummer7··on Environment Variables and Path in Windows 10
That's a neat trick, thanks for pointing me out. I've always wondered how Windows could have accomplished that. It's a shame that Linux doesn't have such an equivalent. If we are to do the same thing in Linux, a login shell (bash or zsh or even GNOME) would be the right place to implement?
yokohummer7··on Environment Variables and Path in Windows 10
What's worse, Linux (or Unix) requires the user to re-login to make the changed environment variables take effect. Whereas in Windows they are applied immediately, so you don't have to re-login after changing PATH.
yokohummer7··on So you're learning OCaml
I feel embarrassed while reading your comment as a Rust proponent... Promoting Rust is great at times, but this particular article doesn't really have anything related to Rust. It is true that Rust was much influenced by OCaml, but the influence is not to a degree of calling it a "dialect". I'd say F# is much more likely a dialect of OCaml.
yokohummer7··on Let's Encrypt is Trusted
Not yet, because Let's Encrypt doesn't provide wildcard certificates as of now. This may change in the near future, though.

Also note that free single domain certificates have been available from StartSSL for a very long time, but this didn't destroy the certificate industry.

yokohummer7··on First chapter of Kernighan and Donovan's new Go book [pdf]
This is exactly the case that the problems of a language are solved by tooling. This attitude can be easily found in the Java ecosystem, where the answer to every question is "to use IDE". Interestingly, Java recently abandoned the idea of feature stagnation and started improving the language. I'm curious when this will happen to Go.
yokohummer7··on First chapter of Kernighan and Donovan's new Go book [pdf]
C is clearly not done, actually. Both C99 and C11 added, deprecated, and even removed many features. You can run C in the 70s not because it didn't change, but because it retained backward compatibility. It will be pretty surprising if Go manages to prohibit even the same level of changes C has taken.
yokohummer7··on First chapter of Kernighan and Donovan's new Go book [pdf]
> no default parameter values

Hearing this leaves a bad taste in my mouth, because one of the (mis)features I've found in Go is its implicit default value in struct initialization. In Go, you don't get a compile error when you miss some fields while initializing a struct. e.g.

  type T struct {
    a int
    b string
    c float64
  }
  
  t := T{c: 1.5}
will happily set `t.a` to 0 and `t.b` to an empty string. While this is useful for maintaining backward compatibility (adding more fields to a struct doesn't break upstream code), it also hinders discovering genuine mistakes at compile time. So typical Go programs end up using 0 or an empty string as a sentinel value. This is probably what made me feel Go's dynamic nature the most. It really is pretty close to a dynamic language.
yokohummer7··on From Python to Go and Back Again
Type systems are a burden because (a) a programmer needs to think of the types he or she should design, (b) a programmer needs to actually utilize those types to write his or her program, (c) they can only act as a safety net.
yokohummer7··on Python wats
I interpret "wat" in the original "wat" presentation as "certain behaviors that can't be predicted by reading the code". In this regard, I don't think many things pointed out in the article can be considered as "wat". I could predict the behavior of many items fairly easily. The same thing could not be applied when I watched the original "wat" presentation.

The only exception I think is the bool coercion. Even though I can predict the behavior, I find it fairly disturbing. I believe that should have been removed when transitioning to Python 3. It is very unfortunate, considering Python is generally reluctant to implicit type conversion.

yokohummer7··on Python wats
If that were the sole reason, it should have been fixed when introducing Python 3. It seems to be much less controversial than other breaking changes in Python 3.

I think the more important reason is that Python doesn't really have an emphasis on the boolean type in general. The `if` statement works for every type, in contrast to other languages allowing only the boolean type in `if`. It is very common to use `if string_or_number_or_anything: blah blah` in Python. While I won't make a stance whether this is a good thing or not, it is still awkward that Python allows implicit conversion between `bool` and `int`.

yokohummer7··on New Perl 6 Homepage
I believe many others feel differently, but personally, I find the Go mascot a bit scary. Dunno the reason, but it's something that I can't easily get used when reading the articles on Go.

FWIW, Russ Cox's GitHub icon[1] is similarly scary to me.

[1] https://github.com/rsc

yokohummer7··on When Rust Makes Sense, or The State of Typed Languages
The page renders well in my browser, and lookup at the generated HTML there doesn't seem to be something suspicious... Maybe one of the fonts doesn't render in your browser?
yokohummer7··on When Rust Makes Sense, or The State of Typed Languages
> which for the most part seem like it wouldn't involve a ton of work

This is probably the reason why our opinions vary. I believe rewriting existing libraries to be safe would be a tremendous amount of work. This estimation comes from my experiences with Rust. Safety guarantee hugely affects the interfaces of the libraries. You cannot "just" gradually increase safety of your library. It is basically a redesign. At least with what Rust currently provides this was my experience. And the method suggested by Herb Sutter seems to be very similar to Rust's. So I expect the same churn to happen in the C++ ecosystem, and it would effectively split the ecosystem into two: safe ones and unsafe ones.

Let me rephrase myself again: if adding safety to C++ in a gradual manner was that easy, Rust would have not been invented in the first place. The Mozilla guys could just use C++. There's a reason why Rust had to exist, despite all the "reinventing the wheel".

yokohummer7··on When Rust Makes Sense, or The State of Typed Languages
Like I said somewhere, a safe subset of C++ sounds wonderful at first, but it also has demerits:

- If you enforce memory safety to all of your code, the number of the libraries that you can use will be severely limited. Imagine if you can only use C++14 libraries. How many C++14 libraries are out there? And I'm not sure if there will be many libraries written in safe C++, at least for the next few years. The adoption rate for newer C++ standards (C++11, C++14) was generally not satisfactory.

- If you only enforce memory safety to your own code, then you could use the existing ecosystem. But in that case, your program will still segfault because of the libraries you're using. Admittedly this is also a concern of Rust when you use C libraries in Rust. The more safe code you use, the safer your program is. The problem is, if you choose this route, there's not much ecosystem-ish advantage in the C++'s side. You will also have to "reinvent the wheel" as you would have to do in Rust.

This problem all boils to this: adding guaranteed memory safety to the unsafe language is a breaking change. And the problems occurred by breaking changes are very hard to solve.

yokohummer7··on When Rust Makes Sense, or The State of Typed Languages
As a Rust proponent, the reasons listed in this article match my sentiment surprisingly well, although the author seems to think Rust isn't ideal for my use cases. I'm also from Python, which I've used for more than 10 years, and chose Rust as my next weapon.

- Haskell: While pervasive laziness does have its merits, I believe it is not the best choice in general, especially for performance-wise. Having to use streaming libraries to do even a simple I/O is just ridiculous. Its syntax was also a big obstacle to me, but thankfully I overcame it. But I'm not sure I can also persuade my colleagues to do the same thing.

- Scala: If I have a JVM requirement, Scala would be a really good fit. (Un)fortunately I don't have such a limit, so what Scala provides are less appealing to me. It also seemed way too gigantic to me at a glance, probably to be interoperable with Java. But I've not tried it deeply.

- F#: I've only heard good things about that, and it was quite a great experience learning through its great IDE. The problem is that even though MS's recent moves I'm still not completely sure if I could retrofit myself to the .NET ecosystem. But the future is bright.

- OCaml: OCaml always felt a bit "obsolete" to me. AFAIK it even didn't have multi-core support until very recently (no parallelism, concurrency only), and they seem to have no resources for a decent Windows support. It has also a funny syntax. I definitely agree Rust's syntax is ugly at best, but OCaml's is... I just can't describe it. Hopefully I can get used to it someday, like I did to Haskell.

And I met Rust and instantly fell in love, even though it requires me to do manual memory management. While manual memory management makes a certain data structure harder to implement, what I realized is that for my daily job, especially for "boring" works (e.g. CRUD apps), it is OK to use manual memory management. If there's a need, I can always borrow libraries from others to accomplish my job. And it is fast by default, less need to optimize the code by myself, as seen in Haskell.

That said, what I have as a "best" language in my mind is, probably a strict version of Haskell. Yeah, that would be Idris, like the author suggests. I really hope that Idris will take off in the near future.

yokohummer7··on Writing a browser extension for three browsers
That's interesting. I've only made some toy extensions for both Chrome and Firefox, and I've got an impression that Firefox's extension model is somehow more "powerful", and Chrome's is a bit limited. But after reading the experiences shown in this thread, it seems that Firefox's model is actually harder to use in practice. Would this be related to the maxim that "less is better"?
yokohummer7··on Analyzing Three Space Leaks in Haskell
> I'm surprised they've not introduced fundamental features to solve or mitigate this problem.

The problem is, to completely solve space leaks, Haskell should abandon pervasive laziness. But laziness is sold as one of the best things about Haskell, and most Haskellers do love laziness because it improves composability.

I myself hate pervasive laziness, and I'm all for removing it from the language. Unfortunately this argument will fail to convince most Haskellers because they're already sold on the bright sides of pervasive laziness.

Ok, this is all good, but from here there's one really annoying aspect of the Haskell community. They try to twist the reality to convince themselves. The typical reaction when these kinds of arguments are brought on the Haskell community is "space leaks are actually rare in the real world applications". Yes, this is the saying from the very community that emphasizes on program correctness. Sure, buffer overflow and memory leaks also rarely happen in other languages? Isn't "exact resource usage" also a part of correctness? At least in a broader sense?

Even SPJ (one of the designers of the language) admits laziness should retire now (it was a good experiment to develop purely functional ways, but now the disadvantages outweigh the advantages), but most Haskellers will never agree with this because laziness does also have advantages, and they love it. I actually gave up waiting for the Haskell community to abandon pervasive laziness, so just moved to other languages.

Sometimes I get a sense that many Haskellers treat hardware as merely implementation details.

yokohummer7··on C++ Core Guidelines
I think you're misinterpreting what pcwalton said. Sure, seeing "use Rust" in every possible place is quite annoying, but what pcwalton described is why "compiles to C++" and "has 2 decades of libraries" don't work for new languages. He didn't say to use Rust, he was just pointing out that your two ideas aren't viable.
yokohummer7··on C++ Core Guidelines
But wouldn't factoring out the obsolete features limit the libraries that are available to use? I thought that was the point of the newly developed systems languages. Even if you follow some "sane" parts of the language, the rest of the ecosystem won't agree with you. Just look at this thread, there are tons of disagreements in what a good C++ code is.
yokohummer7··on 400 days of Go
> it's a smell when a language is so verbose that it effectively requires a machine to help you write it

The funny thing is that this feature also explains what Go is. Go relies heavily on the various tooling just to overcome the deficiencies of the language. It's just that they didn't choose IDE as a primary target, but instead various ad hoc tools.

For example, when I find the unused imports being a hard error inconvenient, a typical suggestion from Gophers is "just use an editor plugin that automatically handles that". This is exactly the same attitude that can be found in the IDE lovers.

And that's why I don't like Go anymore. In the name of the simplicity of the language, they concentrate on building more and more tools, rather than fixing the language. I'm pretty sure if Go acquires generics someday, it will have the form of code generation, which is proven to be awkward. (I heard "go generate" already does a part of that?)

yokohummer7··on Programming in D – Tutorial and Reference
DISCLAIMER: I'm not well-versed in type theory at all, so take my words with a grain of salt.

Unfortunately I haven't seen any comprehensive article that discusses affine types in terms of Rust. So I can't recommend a link to you, instead I'll try to explain them in my own words.

Affine types are those whose values can only be used at most once. They are implemented in Rust as ownership and borrowing. In my example above, `send_header` borrows the `conn` variable, whereas `send_body` takes the ownership of the `conn` variable. As you lost the ownership of `conn`, you cannot use it anymore, thus resulting in a compile error.

This is similar to C++'s move semantics, where you are not permitted to move the same value more than once. It is just that in C++ "move only once" is a convention, whereas in Rust it is enforced by the type system.

In Rust, if you pass an argument by value, you're automatically using affine types. You cannot use the passed variable anymore. To "borrow" instead, you need to opt-out using references. So, the hypothetical API I mentioned above would be written as:

  fn send_header(&self, text: &str) { ... }
  fn send_body(self, text: &str) { ... }
Note the difference of `&`.

Finally, all of these aren't just hypothetical. The exactly same design is used in Hyper[1], which is an HTTP library, and in nickel[2], which is a web framework in Rust. If you look at the API doc you will see there is no '&' in the self parameter. That means it's passed by value, using affine types, and the ownership is transferred, so you cannot use the original variable anymore.

I hope this helps.

[1] http://hyper.rs/hyper/hyper/client/struct.RequestBuilder.htm...

[2] http://docs.nickel.rs/nickel/struct.Response.html#method.sen...

← PreviousPage 4 of 5Next →