CINXE.COM

Scala extension methods vs implicits - beware of precendence

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Scala extension methods vs implicits - beware of precendence</title> <meta name="viewport" content="width=device-width"> <link href="/assets/css/style.css" rel="stylesheet" /> <!-- favicon code start, by https://favicon.io/favicon-generator --> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> <link rel="manifest" href="/site.webmanifest"> <!-- favicon code end --> </head> <body> <div id="header-outer"> <header id="header"> <h1><a href="/">Michael Pollmeier ~ dev blog</a></h1> <nav> <ul> <li><a href="/">blog posts</a></li> <li><a href="/presentations">presentations</a></li> <li><a href="https://mastodontech.de/@mpollmeier">mastodon</a></li> <li><a href="/feed.xml">blog rss</a></li> <li><a href="/about">about me</a></li> </ul> </nav> </header> </div> <div id="page"> <div id="content"> <article class="post"> <h1><a href="/2024/01/scala-extension-methods-precedence">Scala extension methods vs implicits - beware of precendence</a></h1> <p class="meta"> Posted on <span class="postdate">Jan 25, 2024</span><br/> tags: <!-- <a href="/tags.html#scala">scala</a> --> scala </p> <div class="post-content"><p>Scala extension methods vs implicits: beware of precendence</p> <p>I just noticed one important difference between extension methods and old school implicits in Scala 3: the former have a higher precedence. If that鈥檚 not what you wanted, you be better off with plain old implicits. Canonical example for the scala repl:</p> <div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="kt">A</span> <span class="k">object</span> <span class="nc">Foo</span> <span class="o">{</span> <span class="nf">extension</span> <span class="o">(</span><span class="n">a</span><span class="k">:</span> <span class="kt">A</span><span class="o">)</span> <span class="o">{</span> <span class="k">def</span> <span class="nf">hello</span> <span class="k">=</span> <span class="s">"in extension"</span> <span class="o">}</span> <span class="o">}</span> <span class="k">import</span> <span class="nn">Foo.</span><span class="o">*</span> <span class="k">val</span> <span class="nv">hello</span> <span class="k">=</span> <span class="s">"pure value"</span> <span class="c1">// &lt;evaluate the above, and then:</span> <span class="n">hello</span> <span class="c1">// val res0: A =&gt; String = Lambda$1367/0x0000000800571c08@71eff6a3</span> <span class="c1">// ^ extension method takes precedence over value</span> </code></pre></div></div> <p>Using old school implicits:</p> <div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="kt">A</span> <span class="k">object</span> <span class="nc">Foo</span> <span class="o">{</span> <span class="k">class</span> <span class="nc">Ext</span><span class="o">(</span><span class="n">a</span><span class="k">:</span> <span class="kt">A</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">AnyVal</span> <span class="o">{</span> <span class="k">def</span> <span class="nf">hello</span> <span class="k">=</span> <span class="s">"in extension"</span> <span class="o">}</span> <span class="k">implicit</span> <span class="k">def</span> <span class="nf">toExt</span><span class="o">(</span><span class="n">a</span><span class="k">:</span> <span class="kt">A</span><span class="o">)</span><span class="k">:</span> <span class="kt">Ext</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Ext</span><span class="o">(</span><span class="n">a</span><span class="o">)</span> <span class="o">}</span> <span class="k">import</span> <span class="nn">Foo.</span><span class="o">*</span> <span class="k">val</span> <span class="nv">hello</span> <span class="k">=</span> <span class="s">"pure value"</span> <span class="c1">// &lt;evaluate the above, and then:</span> <span class="n">hello</span> <span class="c1">// val res0: String = pure value</span> <span class="c1">// ^ pure value takes precedence over implicit</span> </code></pre></div></div> <p>Note: without the surrounding <code class="language-plaintext highlighter-rouge">object Foo</code> and the import, the pure value has precedence even with extension methods</p> <div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="kt">A</span> <span class="nf">extension</span> <span class="o">(</span><span class="n">a</span><span class="k">:</span> <span class="kt">A</span><span class="o">)</span> <span class="o">{</span> <span class="k">def</span> <span class="nf">hello</span> <span class="k">=</span> <span class="s">"in extension"</span> <span class="o">}</span> <span class="k">val</span> <span class="nv">hello</span> <span class="k">=</span> <span class="s">"pure value"</span> <span class="c1">// &lt;evaluate the above, and then:</span> <span class="n">hello</span> <span class="c1">// val res0: String = pure value</span> <span class="c1">// ^ pure value takes precedence over implicit</span> </code></pre></div></div> </div> <hr /> <div class="footer"> If you liked this post you may want to follow me on <a href="https://mastodontech.de/@mpollmeier">mastodon</a> and subscribe to the <a href="/feed.xml">RSS feed</a>. </div> </article> </div> </div> <script src="/assets/js/jquery.min.js"></script> <script src="/assets/js/jquery.mobilemenu.min.js"></script> <script> $(document).ready(function(){ $('#sidebar nav ul').mobileMenu({'topOptionText': 'Menu', 'prependTo': '#sidebar nav'}); }); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10