HNHacker News
TopNewBestAskShowJobs

_old_dude_

819 karma · joined January 8, 2017

submissionscomments
_old_dude_··on Scala 3.0
> ML is probably the biggest influence

I disagree.

Java records are from Standard ML but sealed is not, it's from Scala with the improvement that subtypes of a sealed types are sealed too.

Java still not have a real syntax for ADT, Standard ML has datatype, Rust or Scala 3 have enums on steroid [1].

[1] https://dotty.epfl.ch/docs/reference/enums/adts.html

_old_dude_··on Adding ANSI C11 C compiler to D so it can import and compile C files directly
yes, Java is adding jextract [1] as a replacement for JNI (Java Native Interface) which directly consumes header files using clang and produces a jar wrapping the native calls.

It's not bolted in the compiler so less nice than Zig but the jar produced by jextract is not ABI dependent so more portable. The ABI dependent code is generated by the JIT using the the Foreign Linker API (the equivalent of C# DllImport) at runtime.

[1] https://inside.java/2020/10/06/jextract/

_old_dude_··on Teeing, a hidden gem in the Java API
There is a talk from Venkat Subramaniam, if you want to explore Collectors to death,

Here is the part about teeing https://youtu.be/pGroX3gmeP8?t=5499

_old_dude_··on Java's records, Lombok's data, and Kotlin's data classes
I wonder why, unlike a Java record, in Kotlin a data class annotated with @Record can not be local.

Being able to use local records is a useful feature in particular in unit tests.

  @Test
  void testPoints() {
     record Point(int x, int y) {}
     ...
  }
_old_dude_··on I Hacked Google App Engine: Anatomy of a Java Bytecode Exploit
I believe it's JEP 411 [1], good ridance, there is nothing worst than a false sense of security.

[1] https://openjdk.java.net/jeps/411

_old_dude_··on Red and blue functions are a good thing
It's only an issue when you have a C callback that calls a Python code, because you have C code in the middle of your stack thus you can not move the stack frames back and forth (because the C code can reference stack addresses).

I may be wrong but most of the C calls in Python do not have callbacks and you can pin the coroutine to the kernel thread if there is a callback.

_old_dude_··on Red and blue functions are a good thing
You can have exceptions like in Erlang, OCaml, C#, Kotlin which all keep the stacktrace without having checked exceptions.

If you take a look to the history of Java, checked exceptions was there since the beginning but were weaken several times, first by the introduction of generics+inference (a type parameter can not represent an union of exceptions) then by the introduction of lambdas, the type of a lambda (the function interfaces in Java lingo) used by the standard lib, do not declare checked exceptions.

It's so bad that IOException, the king of checked exception, has two unchecked dual defined by default, UncheckedIOException and IOError that are raised randomly by the new APIs like java.nio.file.Files that do not want to deal with the complexity of checked exceptions.

Java has a checked exception problem but it does not want to recognize it.

BTW, there is another coloring in Java which is primitive vs object, but at least this one is recognized as an issue (see OpenJDK project Valhalla).

_old_dude_··on Red and blue functions are a good thing
for sync vs async, yes !

but Java still have checked exceptions which is also a form of coloring.

_old_dude_··on Traversing nested data-structures in various languages
It makes a lot of more sense.

`resetLessonPosition` is not a member of the data structure but a parameter of the function that generates the positions and it has an effect on all sections.

_old_dude_··on Traversing nested data-structures in various languages
I'm not sure the problem reflect anything, while updating a data structure like this is fairly standard, the lesson counter is reset globally, which is not a common operation.

For me the problem is too artificial to be meaningful.

_old_dude_··on Background: how we got the generics we have (2020)
Very cool, it seems to be the best of both worlds, the specialization of the class/fields is done the first time a specialized type is instantiated while the specialization of methods is done by the JIT.

And the VM can specialize on any values, not just types.

_old_dude_··on Java 16
I did, the main issue is that jaotc doesn't do any pruning of the unused methods, so it generates too much assembly code. If i remember correctly, compiling just guava was to close to 1 gig.

GraalVM native image is far better, it "compiles" more slowly but the resulting executable is not too big.

_old_dude_··on Performance comparison: counting words in Python, Go, C++, C, Awk, Forth, Rust
No java ! here is my code golf version

  var map =
      new BufferedReader(new InputStreamReader(in, UTF_8))
          .lines()
          .flatMap(compile(" ")::splitAsStream)
          .collect(groupingBy(w -> w, () -> new TreeMap<>(reverseOrder()), counting()));
It obviously doesn't work without the imports

  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.util.TreeMap;

  import static java.lang.System.in;
  import static java.nio.charset.StandardCharsets.UTF_8;
  import static java.util.Collections.reverseOrder;
  import static java.util.regex.Pattern.compile;
  import static java.util.stream.Collectors.counting;
  import static java.util.stream.Collectors.groupingBy;
_old_dude_··on FizzBuzz – SIMD Style
Thanks, i've overlooked that

    var mask = VectorMask.fromLong(SPECIES, 0b0111_1111);

    var i = 0;
    var upperBound = length - length % 15;
    for(; i < upperBound; i += 15) {
      v1.intoArray(result, i);
      v2.intoArray(result, i + 8, mask);
      ...
_old_dude_··on FizzBuzz – SIMD Style
yes, right, if length is a multiple of 15, there is an issue.

And there is no primitive for masking on AVX2, those are only available on AVX-256.

if we want to minimize the iterations of the post loop, it should be

  var upperBound = length % 15 == 0? length - 15: length - length % 15;
but as you said, i'm not sure the VM will eliminate the bound checks in that case so your solution seems to be the best

  var upperBound = length - 15
_old_dude_··on FizzBuzz – SIMD Style
Your version written in Java

  private static final int[] VALUES = range(0, 16).map(FizzBuzz::fizzbuzz).toArray();
  private static final int[] DELTAS = stream(VALUES).map(v -> v < 0? 0: 15).toArray();

  private static final VectorSpecies<Integer> SPECIES = IntVector.SPECIES_256;

  private static int fizzbuzz(int i) {
    return i % 15 == 0? FIZZ_BUZZ: i % 5 == 0? BUZZ: i % 3 == 0? FIZZ: i;
  }

  public static int[] simdFizzBuzz(int length) {
    var result = new int[length];

    var v1 = IntVector.fromArray(SPECIES, VALUES, 0);
    var v2 = IntVector.fromArray(SPECIES, VALUES, 8);
    var d1 = IntVector.fromArray(SPECIES, DELTAS, 0);
    var d2 = IntVector.fromArray(SPECIES, DELTAS, 8);

    var i = 0;
    var upperBound = length - length % 15;
    for(; i < upperBound; i += 15) {
      v1.intoArray(result, i);
      v2.intoArray(result, i + 8);
      v1 = v1.add(d1);
      v2 = v2.add(d2);
    }
    for(; i < length; i++) {
      result[i] = fizzbuzz(i);
    }
    return result;
  }
quite cool indeed
_old_dude_··on Distribution of JVM Desktop Applications
> although, admittedly, popular Java build tools currently lag in their support for jlink

Just an anecdote. We recently ship a CLI app companion to one of our WebApp that mostly dedup few dozen XLS files before uploading the content to the WebApp using jpackage.

We are using this Maven plugin [1] to generate an exe, a rpm and a dmg. We spent far more time figuring out how to notarize an application on MacOs that using jpackage.

[1] https://github.com/akman/jpackage-maven-plugin

_old_dude_··on The Kotlin Foundation
> JVM can't do dynamic dispatch on multiple arguments

It can since Java 7, the instruction invokedynamic was added for this kind of stuff.

The implementation for Pattern Matching (the project Amber) [1] will use the very same instruction.

[1] https://cr.openjdk.java.net/~briangoetz/amber/pattern-match-...

_old_dude_··on The visitor pattern is essentially the same thing as Church encoding
You can keep the Circle and Rectangle as class (record here) and only see them as Shape when you want to do the double dispatch of the visitor.

  interface Shape {
    record Circle(int x, int w, int r) {}
    record Rectangle(int x, int y, int w, int h) {}

    <T> T apply(Function<Circle, T> _circle, Function<Rectangle, T> _rectangle);

    static <T> Shape shape(Circle circle) {
      return new Shape() {
        @Override
        public <T> T apply(Function<Circle, T> _circle, Function<Rectangle, T> _rectangle) {
          return _circle.apply(circle);
        }
      };
    }
    static <T> Shape shape(Rectangle rectangle) {
      return new Shape() {
        @Override
        public <T> T apply(Function<Circle, T> _circle, Function<Rectangle, T> _rectangle) {
          return _rectangle.apply(rectangle);
        }
      };
    }

    static double area(Shape shape) {
      return shape.apply(
          circle -> Math.PI * circle.r * circle.r,
          rectangle -> 1. * rectangle.w * rectangle.h
      );
    }

    static void main(String[] args) {
      var aCircle = new Circle(2, 1, 4);
      var aRectangle = new Rectangle(1, 3, 10, 7);

      System.out.println(area(shape(aCircle)));
      System.out.println(area(shape(aRectangle)));
    }
  }
_old_dude_··on The visitor pattern is essentially the same thing as Church encoding
> The downside is that Java doesn't let you implement generic methods with lambdas ...

yes, that exactly why i've chosen to make the type parametric and not the method apply, but you're right that the classical visitor pattern uses a polymorphic method (accept) not a polymorphic class.

_old_dude_··on The visitor pattern is essentially the same thing as Church encoding
In Java,

  interface Shape<T> {
    interface _Circle<T> {
      T apply(int x, int y, int r);
    }
    interface _Rectangle<T> {
      T apply(int x, int y, int w, int h);
    }
    T apply(_Circle<T> circle, _Rectangle<T> rectangle);

    static <T> Shape<T> Circle(int x, int y, int r) {
      return (circle, rectangle) -> circle.apply(x, y, r);
    }
    static <T> Shape<T> Rectangle(int x, int y, int w, int h) {
      return (circle, rectangle) -> rectangle.apply(x, y, w, h);
    }

    static double area(Shape<?> shape) {
      var s = (Shape<Double>) shape;
      return s.apply(
          (x, y, r) -> Math.PI * r * r,
          (x, y, w, h) -> 1. * w * h
      );
    }

    static void main(String[] args) {
      var exampleCircle = Circle(2, 1, 4);
      var exampleRectangle = Rectangle(1, 3, 10, 7);

      System.out.println(area(exampleCircle));
      System.out.println(area(exampleRectangle));
    }
  }
BTW, you can use the same encoding when you write a Promise in JS.
_old_dude_··on When Amazon Switched from Sun to Linux
Java on Linux was interpreted until 1.3.1/1.4 when the VM, named ExactVM, was replaced by HotSpot which includes a JIT.

At that time, I remember deciding to prototype a B2B store in Java and then rewrite it in C++ when i will know what i was doing. I never rewrite that soft because Java becomes fast enough overnight.

In a sense, SUN kill itself with Java.

_old_dude_··on A former Uber engineer's disaster story
APK is now more a delivery package format than a real executable format now.

On recent Android devices, the APK wil be recompiled to machine code on the device after a small number of runs (to gather code statistics).

So you are comparing an apple and a robot.

_old_dude_··on David Fincher’s Impossible Eye
I don't think it's that simple.

As an anecdote i've recently seen Extraction with Chris Hemsworth, great movie but in the middle of the first big action scene, the camera goes through the windscreen of the back of the car without the glass being shattered. It was enough to pull me out of the action into a moment of disbelief.

Breaking continuity has a cost

_old_dude_··on Graphics for JVM
The author is an employee of JetBrain. I believe JetBrian is using jlink [1], a tool that let you embed the modules of the JDK you need with your application, for all their products since they have migrated to JDK 11.

[1] https://docs.oracle.com/en/java/javase/11/tools/jlink.html

_old_dude_··on A Case for Properties: Programming Language Design
It's exactly what the JVM does, it's called Class Hierarchy Analysis (CHA). The VM checks if a method is actually overridden or not.

When a new class is loaded, the analysis checks which codes are no longer valid and mark them for deoptimization.

_old_dude_··on Python overtakes Java to become the second-most popular programming language
Java or Kotlin support functors or monads as design patterns, i.e. this is how a map/flatMap works with an Optional or a Stream.

The question is: if this support is enough or should the type system be enhanced so you can abstract over/compose a functor and/or a monad ?

The answer to this question is IMO still open.

_old_dude_··on Go Type Parameters – Draft Design
It's far better than the previous drafts, another couple of drafts and it will be very good.

I think that listing the possible types with "type" inside an interface is a mistake. It means that instead of providing builtin interfaces for existing primitive types, Go asks its users to list the primitive types in user defined interfaces. This will not go well if at some point in a future, the Go team want to add a new primitive type because the user codes will need to be upgraded.

And not providing inference when directly referencing a function is a weird choice (see section Type inference for generic function arguments).

_old_dude_··on Swift Concurrency Roadmap
Implementing async/await is only a compiler change, so it can be implemented rather easily on top of any languages, the compiler transforms the code to a state machine.

co-routine (Java Loom's one, Go one, Scheme one, etc) requires to be able to serialize and deserialize a part of the stack (move the stack on the the heap and vice versa), so it's hard/impossible to implement with non managed runtimes which like in C or objective C.

In C, you can declare an address/pointer to an address on stack (using &), but with a co-routine mechanism, the addresses of parts of the stack are not constant.

If you have a managed runtime, you rewrite those kind of pointers when you copy parts of the stack back and forth.

_old_dude_··on Java Turns 25 – Whats Next? [pdf]
I recommend Effective Java, the third edition is updated for Java 9 I believe and Java Concurrency in Practice for the core parts of the language.

For Spring, Jakarta EE, Micronaut or Quarkus the docs of their respective websites is enough.

← PreviousPage 7 of 11Next →