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

Singleton monoid instances #4314

Merged
merged 3 commits into from
Oct 9, 2022

Conversation

TimWSpence
Copy link
Member

@TimWSpence TimWSpence commented Oct 5, 2022

Prompted by http4s/http4s#6712, which locally caches a particular Monoid[List[*]] instance - the issue is a generic one so it seems better to apply this optimisation here.

There are other cases where this kind of change could be made too but I wanted to get feedback before doing any more work on it.

Carries on the work done in #4309. Many thanks to @bplommer for doing most of the work!


object LazyListMonoid {
@nowarn("msg=deprecated")
private[this] val singleton: Monoid[LazyList[Any]] = new LazyListMonoid[Any]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps, in the light of Scala3 and future migrations we should avoid using private [this] modifier:
https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html

I think just private would be private enough :)

Copy link
Member

@armanbilge armanbilge Oct 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for the record, here's the difference.

//> using scala "2.13.8"

object Foo {
  private val bar: String = "bar"
  private[this] val baz: String = "baz"

  def publicBar = bar
  def publicBaz = baz
}
/*
 * Decompiled with CFR 0.152.
 */
public final class Foo$ {
    public static final Foo$ MODULE$ = new Foo$();
    private static final String bar = "bar";
    private static final String baz = "baz";

    private String bar() {
        return bar;
    }

    public String publicBar() {
        return this.bar();
    }

    public String publicBaz() {
        return baz;
    }

    private Foo$() {
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, optimizations and portability are often a trade off :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the conclusion here sorry? In general we seem to use private[this] absolutely everywhere so personally I don't see the harm in adding one more to the mountain but am happy to go with whatever the concensus is!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, when scala 3 actually deprecates/removes it we can replace private[this] with private but there seems no harm using it in the meantime

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally fine with private[this] too, I don't think it is that important for now.


I personally prefer to avoid using private [this] on project that are supposed to be migrated to Scala3 eventually. But since the majority of projects are still using Scala2, they may benefit from such optimization.

Btw, I've just checked the @armanbilge's example with Scala 3.2.0 (just out of curiosity :) ) and looks like Scala3 does a great job on optimizing private fields indeed:

/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  scala.runtime.ModuleSerializationProxy
 */
import java.io.Serializable;
import scala.runtime.ModuleSerializationProxy;

public final class Foo$
implements Serializable {
    private static final String bar;
    private static final String baz;
    public static final Foo$ MODULE$;

    private Foo$() {
    }

    static {
        MODULE$ = new Foo$();
        bar = "bar";
        baz = "baz";
    }

    private Object writeReplace() {
        return new ModuleSerializationProxy(Foo$.class);
    }

    public String publicBar() {
        return bar;
    }

    public String publicBaz() {
        return baz;
    }
}

Copy link
Member

@armanbilge armanbilge Oct 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer to avoid using private [this] on project that are supposed to be migrated to Scala3 eventually.

I am 💯 % confident that find/replace private[this] to private will be the fastest and easiest part of Scala 3 migration in Cats :)

@TimWSpence TimWSpence closed this Oct 6, 2022
@TimWSpence TimWSpence reopened this Oct 6, 2022
Copy link
Contributor

@satorg satorg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@armanbilge armanbilge added this to the 2.9.0 milestone Oct 7, 2022
@armanbilge armanbilge merged commit 409ee7e into typelevel:main Oct 9, 2022
@TimWSpence TimWSpence deleted the singleton-monoid-instances branch October 10, 2022 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants