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...
HN user
[ my public key: https://keybase.io/kilink; my proof: https://keybase.io/kilink/sigs/L2bIjKsfXWgHQPYbsXCntTq3nM0DKnxZ_9R819KAA8k ]
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...
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...
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.
...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!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
This is a Python specific restriction. Ruby for example allows mutable keys in dictionaries.
What about null?
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.
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.
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.
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...
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).
Sorry, it's just not practical to keep lines under 80 characters in some languages.
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?
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.
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.
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: '$'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.
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...
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.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.
Isn't that what Python Wheels are for though?
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...
Smalltalk.
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...
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...
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).
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.
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.
I think the Map interface should have been composed of two interfaces, ReadableMap and WriteableMap. Then APIs could return ReadableMap, which would lack the mutator methods altogether.