Hacker News new | past | comments | ask | show | jobs | submit login

Oh, the lengths people go to avoid OOP. Java:

    users.stream()
        .map(User::getEmail)
        .map(Email::send)
        .map(res -> "Error sending email: " + res)
        .collect(toList())



What's "object-oriented" about that code? I'm suspicious of vague labels like "OOP" and "FP", but even some of the Java docs call Java's streams "functional-style".

https://docs.oracle.com/javase/8/docs/api/java/util/stream/p...


the only issue with java in this context is that you'll need to create a new class/transfer object between each function call that does things.

with elixir (the previous example) you'd likely use simple hashmaps or lists like {email: "mail"} or [:error, "reason for failure"].

That doesn't sound like its amazing, but actually is in practice, because the whole language is written with that in mind (pattern matching to effectively do function/method overloading depending on the value of each argument for example)

its very concise while still being very explicit. The same would be possible with java, but you'll need to create a lot of classes/interfaces/enums/boilerplate to facilitate it.

i'd still prefer java any time at a dayjob though, because boring and dumb is generally better if you need to write code that's gonna be in use for decades... and likely going to be changed by a lot of people with varying levels of experience.


Side note to say that the previous example is actually F#, a static typed language contrary to Elixir (to be fair Elixir was heavily inspired by F# and they look similar when only looking at snippets).


> the only issue with java in this context is that you'll need to create a new class/transfer object between each function call that does things

No, in most cases you don't. The stream interface is mostly designed around simple Lists, Sets and Maps. It also interacts very well with the Collection framework (e.g. myHashmap.entrySet() yielding a set, etc.) which is part of the standard library.

You can extend streams with custom collectors, but rarely if ever you need to define intermediate data structures. You do need to define initial and terminal structures, but I'd argue that's good practice regardless.


> No, in most cases you don't

that lets you pass the result from each function to the next without explicitly stating what form they have, yes.

You'll still be missing the conciseness/explicitness because the language isn't meant to be used like that and is missing necessary features in order to facilitate it such as pattern matching by the passed in values into function.

to make a simple example, you could theoretically write the following pseudo-code

  def sendEmail({email}) do
    // send email
  end
  def sendEmail({id}) do
    // get email address
    sendEmail({email})
  end
  sendEmail({id: 244})
or to make sure your code stops executing if an error occurs (positional return values this time)

    [:ok, msg] = sendEmail(lkajsdf)


    .collect(Collectors.groupingBy(...))


that does something entirely different.

maybe actually learn to program sometimes, then you will figure out what it does.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: