HNHacker News
TopNewBestAskShowJobs

kilink

104 karma · joined August 13, 2011

submissionscomments
kilink··on Java 27
That's less of a thing nowadays if you use the newer APIs that accept Charset instances instead of the charset name as a String.
kilink··on Dismissing Python Garbage Collection at Instagram
They mentioned msgpack was calling gc.enable(), but it looks like that issue was fixed quite a while ago in version 0.2.2:

https://github.com/msgpack/msgpack-python/blob/2481c64cf162d...

kilink··on Kotlin in Production – What Works, Whats Broken
Maybe they mean data class inheritance, instead of subclassing? That's the only thing I know of that is planned for Kotlin 1.1 [1], and it's primarily useful for sealed classes (I've wanted this).

[1] https://github.com/Kotlin/KEEP/blob/master/proposals/data-cl...

kilink··on Why bad scientific code beats code following “best practices” (2014)
I think the advice is more relevant in the context of the specific language; it's not universal.

In python you can go from attribute access to using a property (getter/setter) without breaking anything.

The same is not true in a language like Java where obj.foo is always a direct field access distinct from calling a method like obj.getFoo(), so going from public fields to getters is not backwards compatible and can be painful.

kilink··on Python Lists vs. Tuples
...Or can you?

  import ctypes

  def tuple_setitem(t, index, item):
      obj = ctypes.py_object(t)
      item = ctypes.py_object(item)
      ref_count = ctypes.c_long.from_address(id(t))
      original_count = ref_count.value
      if original_count != 1:
          ref_count.value = 1
      ctypes.pythonapi.Py_IncRef(item)
      ctypes.pythonapi.PyTuple_SetItem(obj, ctypes.c_ssize_t(index), item)
      ref_count.value = original_count

  >>> x = (1, 2, 3,)
  >>> tuple_setitem(x, 1, "foo")
  >>> x
  (1, "foo", 3)
Disclaimer: for entertainment purposes only, do not try this at home!
kilink··on Python Lists vs. Tuples
I'm not sure if you are asking about Python, or Ruby.

Anyway, both languages use value-based hashing for dictionaries. I am not a Rubyist, but I guess you are just expected to not mutate the keys? Ruby's dictionary implementation also has a rehash method to deal with this case [1], if for some reason you are purposely mutating the keys I suppose...

[1] http://docs.ruby-lang.org/en/2.0.0/Hash.html#method-i-rehash

kilink··on Python Lists vs. Tuples
This is a Python specific restriction. Ruby for example allows mutable keys in dictionaries.
kilink··on Functional Programming Isn't the Answer (2014)
What about null?
kilink··on Java Exception Handling
I'm not sure what you mean by error values being dropped on the floor by default. In Go or languages with ADTs you would have to consciously ignore an exception. Languages where pattern matching is prevalent force you to deal with the exceptional case to unpack anything useful from an Either for instance.

And if the study is to be believed, checked exception are almost always dropped on the floor, just with more boilerplate and ceremony.

kilink··on Java Exception Handling
I was addressing your specific assertion with regard to encoding error conditions as reserved values in your return type's codomain, which I agree is ugly.

One benefit of not throwing an exception is that you can maintain referential transparency, which exceptions generally break. You can't substitute a function call with its value because throwing an exception will have different effects depending on the context, which consequently hinders the composability of such functions.

Exceptions are also generally not type-safe, e.g. the return type of a function tells you nothing about what exceptions it may throw. If you go the checked exception route like Java, you do get some degree of type safety, but you do so at the expense of higher-order functions, which can't reasonably be expected to know about the specific exception types its arguments may throw.

On the other hand, ADTs are composable. They work for functions that aren't defined for some inputs (maybe an input type that can't be constrained by the type system). They avoid bugs because they force the caller to deal with the exceptional case (unlike returning null, a sentinel value, or throwing a RuntimeException), but without the boilerplate of exceptions, particularly in languages with pattern matching. The caller gets to decide when, if, and how to handle the exceptional case.

kilink··on Java Exception Handling
> The problem usually is: What is the error code if your return type is int? Sure, you can define all negative ints as errors, or you provide a reference which is set when an error is encountered and so on, but that ends up being just another type of "very ugly".

Many languages support multiple return values, algebraic data types, or box types, allowing you to return an error value out of band.

kilink··on Amazon open-sources Ion – a binary and text interchangable, typed JSON-superset
Things I dislike about Ion, having used it while at Amazon:

- IonValues are mutable by default. I saw bugs where cached IonValues were accidentally changed, which is easy to do: IonSequence.extract clears the sequence [1], adding an IonValue to a container mutates the value (!) [2], etc.

- IonValues are not thread-safe [3]. You can call makeReadOnly() to make them immutable, but then you'll be calling clone since doing anything useful (like adding it to a list) will need to mutate the value. While it says IonValues are not even thread-safe for reading, I believe this is not strictly true. There was an internal implementation that would lazily materialize values on read, but it doesn't look like it's included in the open source version.

- IonStruct can have multiple fields with the same name, which means it can't implement Map. I've never seen anyone use this (mis)feature in practice, and I don't know where it would be useful.

- Since IonStruct can't implement Map, you don't get the Java 8 default methods like forEach, getOrDefault, etc.

- IonStruct doesn't implement keySet, values, spliterator, or stream, and thus doesn't play well with the Java 8 Stream API.

- Calling get(fieldName) on an IonStruct returns null if the field isn't present. But the value might also be there and be null, so you end up having to do a null check AND call isNullValue(). I'm not convinced it's a worthwhile distinction, and would have preferred a single way of doing it. You can already call containsKey to check for the presence of a field.

- In practice most code that dealt with Ion was nearly as tedious and verbose as pulling values out of an old-school JSONObject. Every project seemed to have a slightly different IonUtils class for doing mundane things like pulling values out of structs, doing all the null checks, casting, etc. There was some kind of adapter for Jackson that would allow you to deserialize to a POJO, but it didn't seem like it was widely used.

[1] https://github.com/amznlabs/ion-java/blob/master/src/softwar...

[2] https://github.com/amznlabs/ion-java/blob/master/src/softwar...

[3] https://github.com/amznlabs/ion-java/blob/master/src/softwar...

kilink··on How to reduce the cognitive load of your code
That also wouldn't even compile. I also write in multiple languages, and for languages for which this is an issue I use a linter. This isn't even an issue in C if you compile everything with the appropriate flags (-Wall or -Wparentheses).
kilink··on How to reduce the cognitive load of your code
Sorry, it's just not practical to keep lines under 80 characters in some languages.
kilink··on How to reduce the cognitive load of your code
For me it's not that it's confusing, it's annoying to read because it indicates that the programmer didn't actually take the time to learn the language, and is instead writing it as C/PHP something else where expressions in if statements don't need to be explicitly boolean (the examples in the article are Java). If they wrote that, what else do they not understand about the language?
kilink··on How to reduce the cognitive load of your code
Java if statements only allow boolean expressions, so the thing that the Yoda condition is supposed to protect against isn't even possible. I think this is precisely what the author is talking about, as this style is a totally unnecessary holdover from C.
kilink··on Kill Your Dependencies
That may true for Go, a language which still does not have a great dependency management story. I'm not sure this proverb is universal though.
kilink··on Records: Python library for making raw SQL queries to Postgres databases
The parent was talking about namedtuple.

    >>> collections.namedtuple("test", "$")
    Traceback (most recent call last):
    ...
    ValueError: Type names and field names can only contain alphanumeric characters and underscores: '$'
kilink··on Records: Python library for making raw SQL queries to Postgres databases
If this were a big deal, it could be optimized using something like a key-sharing dict implementation [1]. You can keep the dict interface to accommodate column names that aren't valid identifiers, and avoid most of the memory overhead.

[1] https://www.python.org/dev/peps/pep-0412/

kilink··on Comparing Java GC Collectors
There are so many other factors that ultimately determine GC performance. The GC must be tuned based on the workload. For instance, the out of the box defaults for things like newRatio [1] are not ideal for web services with lots of short-lived objects.

[1] https://blogs.oracle.com/jonthecollector/entry/the_second_mo...

kilink··on Design Patterns in Clojure
I like Clojure quite a bit more than Java, but some of these are unfair if you are comparing against modern Java.

For instance, the sorting example can be simplified:

    Comparator<User> userOrdering = Comparator.comparing(User::isSubscription).thenComparing(User::getName);
    // forward sort
    Collections.sort(users, userOrdering);
    // reverse sort
    Collections.sort(users, userOrdering.reversed());
A lot less verbose than it's made out to be.
kilink··on Why Go Is Not Good (2014)
Too bad you can't just call functional interfaces in Java 8, or you could just do something like this:

BiFunction<BigDecimal, BigDecimal, BigDecimal> add = BigDecimal::add; add(x, y);

Unfortunately you have to do:

add.apply(x, y);

Which is kind of cumbersome.

kilink··on Metabase: Why we picked Clojure
Isn't that what Python Wheels are for though?

http://pythonwheels.com/

kilink··on Modern Java – A Guide to Java 8
CompletableFuture implements Future, so the get method is an implementation of Future.get [1].

Anyway, the major difference is that Future.get throws 2 checked exceptions, InterruptedException and ExecutionException, while CompletableFuture.join does not throw any checked exception. Instead, it wraps any exceptions in CompletionException.

[1] https://docs.oracle.com/javase/7/docs/api/java/util/concurre...

kilink··on Modern Java – A Guide to Java 8
Smalltalk.
kilink··on Better Java – Resources for Writing Modern Java
Also, if you look at the Javadocs for some of the creation methods, they explicitly state that they are for Java 6 and earlier, and that modern code should just use the constructor with the diamond syntax.

http://docs.guava-libraries.googlecode.com/git/javadoc/com/g...

kilink··on Better Java – Resources for Writing Modern Java
I realize he mentions Lombok, but he specifically bemoans the extra boilerplate with writing builders and data classes, but does not mention the @Data or @Builder annotations...
kilink··on Better Java – Resources for Writing Modern Java
> First: constructor calling is not readable because Java misses named parameters. It's fine when there are 2-3 dependencies, but not more.

If you have more than 2-3 dependencies, it might be time to refactor things, as your class may be doing too many things.

> Second: circular dependency is not possible.

Circular dependencies are possible with constructor injection when using a DI framework (e.g., using a Provider in Guice [1], or the equivalent in Dagger).

[1] https://github.com/google/guice/wiki/CyclicDependencies

kilink··on Better Java – Resources for Writing Modern Java
I'm also not a fan of passing Optionals into methods. Most of the time it's easier and cleaner just to write an additional method without that optional parameter.
kilink··on Better Java – Resources for Writing Modern Java
I'm surprised he didn't mention AutoValue [1] or Lombok (using @Data and @Builder) in his section about data objects and builders. I prefer AutoValue, but both approaches cut down on a lot of the boilerplate (and they also generate sensible equals(), hashCode(), toString(), etc).

It's also kind of a nitpick, but I disagree with his preference for Guava's Maps.newHashMap() vs new HashMap<>(). I'm pretty sure the only reason those static methods exist is because pre-Java 7 didn't have the diamond operator.

[1] https://github.com/google/auto/tree/master/value

Page 1 of 2Next →