Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate then remove all unsafe API #192

Open
jbgi opened this issue Sep 11, 2015 · 8 comments
Open

Deprecate then remove all unsafe API #192

jbgi opened this issue Sep 11, 2015 · 8 comments

Comments

@jbgi
Copy link
Member

jbgi commented Sep 11, 2015

or at least move unsafe API under a Unsafe nested class (or better: a separate "unsafe" artefact) with all methods prefixed with unsafe.
eg. List.tail(), List.head() should not be part of List public API.

maybe for functionaljava 5?

@functionaljava WDYT?

@dobesv
Copy link
Contributor

dobesv commented Sep 11, 2015

I do find myself using these regularly because Java lacks a pattern matching mechanism. I think it could be done using the visitor pattern, but List doesn't currently implement the visitor pattern. So I do something like if(x.isNotEmpty()) { ... x.head() ... } else { ... }.

Removing or renaming these methods now would create some headaches for me, and probably others, so some kind of deprecation procedure would be recommended. I'm not sure its worth the pain right now.

@techtangents
Copy link

dobesv mailto:notifications@github.com
12 September 2015 8:19 am

I do find myself using these regularly because Java lacks a pattern
matching mechanism. I think it could be done using the visitor
pattern, but List doesn't currently implement the visitor pattern. So
I do something like |if(x.isNotEmpty()) { ... x.head() ... } else {
... }|.

This is what folds are for.

@tonymorris
Copy link
Contributor

👍

Move unsafe functions out, so that if they are not imported, it is more clear that they are not used.

@jbgi
Copy link
Member Author

jbgi commented Oct 22, 2016

the road block to completely removing those unsafe functions is the lack of TCO. Eg. Implementing listEqual without head() and tail() in a stack safe manner is not totally satisfying: you have to allocate objects (Option or Trampolining) at each iteration, or use some sort of mutable local function.
But well this is Java...

@jbgi
Copy link
Member Author

jbgi commented Oct 22, 2016

To clarify what I meant by "some sort of mutable function", here is how one could implement List.forEach without head() and tail():

public final Unit foreach(final F<A, Unit> f) {
    final class ForEachCons implements F2<A, List<A>, Boolean> {
      List<A> as = List.this;
      @Override
      public Boolean f(A head, List<A> tail) {
        as = tail;
        f.f(head);
        return true;
      }
    }
    ForEachCons forEachCons = new ForEachCons();
    while (forEachCons.as.uncons(forEachCons, false)) {}
    return unit();
}

To be compared with current implementation:

  public final Unit foreach(final F<A, Unit> f) {
    for (List<A> xs = this; xs.isNotEmpty(); xs = xs.tail()) {
      f.f(xs.head());
    }
    return unit();
}

I am personally ok-ish with the former implementation but I am guessing not everyone... @functionaljava WDYT?
or is there alternative I am not seeing?
one of them may be to keep using head/tail for primitive recursive functions...

@dobesv
Copy link
Contributor

dobesv commented Oct 25, 2016

I think it's good to leave the door open to optimization. Maybe just rename
them to have an underscore in front, so people feel a bit uncomfortable
using them?

On Sat, Oct 22, 2016, 4:02 AM JB Giraudeau notifications@github.com wrote:

To clarify what I meant by "some sort of mutable function", here is how
one could implement List.forEach without head() and tail():

public final Unit foreach(final F<A, Unit> f) {
final class ForEachCons implements F2<A, List, Boolean> {
List as = List.this;
@OverRide
public Boolean f(A head, List tail) {
as = tail;
f.f(head);
return true;
}
}
ForEachCons forEachCons = new ForEachCons();
while (forEachCons.as.uncons(forEachCons, false)) {}
return unit();
}

To be compared with current implementation:

public final Unit foreach(final F<A, Unit> f) {
for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) {
f.f(xs.head());
}
return unit();
}

I am personally ok-ish with the former implementation but I am guessing
not everyone... @functionaljava https://github.com/functionaljava WDYT?
or is there alternative I am not seeing?
one of them may be to keep using head/tail for primitive recursive
functions...


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#192 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAUAmZEckchoX-Jfm7OU0J-efXdZWZXZks5q2e1dgaJpZM4F78GX
.

@siro-mateos
Copy link
Contributor

I think it would also be good to give NonEmptyList more prominence (and full List methods)... for instance, List.groupBy should produce TreeMap<B, NonEmptyList<A>>.

@devkat
Copy link

devkat commented Feb 18, 2021

+1 from me for this issue. It is hard for me to sell the library to my coworkers as a safe alternative to the Java standard library if it provides unsafe operations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants