Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

Allow anonymous implicit values #9

Closed
puffnfresh opened this issue Sep 4, 2014 · 19 comments
Closed

Allow anonymous implicit values #9

puffnfresh opened this issue Sep 4, 2014 · 19 comments

Comments

@puffnfresh
Copy link

Provide support for the following syntax for introducing a new implicit val without assigning a name to it.

implicit val _ = ...

and

implicit val _: TypeClass[Foo] = ...

Incidentally, I just realized that you can currently write:

implicit val _ = foo

as long as you're not at the top-level in the REPL, and you've not already bound something to _. As desired, you've got no way of referring to it by name afterwards, but it's not a solution because you only get one implicit per scope.

@propensive
Copy link

My addendum about there being no way to refer to it subsequently is false. You can always refer to using backticks, e.g.

QualifiedScope.`_`

@paulp
Copy link

paulp commented Sep 5, 2014

The "clever" trick of actually having a name called _ in the namespace has already shown its limits. Give the poor users a gensym.

@propensive
Copy link

I'm in no way advocating it.

@puffnfresh
Copy link
Author

It's a good point though, if we're preserving backwards compat, then we need to continue exposing _ as a val - right?

@paulp
Copy link

paulp commented Sep 5, 2014

Classic.

object o {
  val _ = 1
  val b = 2
}
object p extends App {
  { import o.`_` ; println(b)   } // ok (!)
  { import o.`_` ; println(`_`) } // ok
  { import o._   ; println(b)   } // ok
  { import o._   ; println(`_`) } // error: not found: value _
}

@puffnfresh
Copy link
Author

@paulp wow, what?

@propensive
Copy link

I don't even want to contemplate how ALL of those examples are true.

@paulp
Copy link

paulp commented Sep 5, 2014

I'll give you a hint:

final val WILDCARD: NameType = "_"
% ack --nogroup --no-filename --no-color  'name\.toString' src/ | wc -l
      85

85 occurrences of the literal character sequence "name.toString". Just imagine if sometimes the name isn't in a variable called "name", or if it's "" + name or s"$name". No that's crazy, probably just the 85.

@gigamonkey
Copy link

Wow. Are there legitimate uses where you peer through the anonymity of _? I always thought/hoped it was truly totally anonymous, i.e. caused a fresh, unnamable symbol to be used or some such. (Is that what you meant by "give the poor users a gensym", paulp?)

@paulp
Copy link

paulp commented Sep 5, 2014

@gigamonkey no, it is essentially the opposite. _ is much like any other name. No, there are no legitimate uses for it, nor are there any intentional uses for it. It's just an incredibly leaky "abstraction", not that it even rises to the level of abstraction.

However it's still like that because (here we go again) I tried to fix it and that was reverted, because I forgot about java. https://issues.scala-lang.org/browse/SI-6426

Yes, that's what I meant about gensym.

@paulp
Copy link

paulp commented Sep 5, 2014

See also https://issues.scala-lang.org/browse/SI-7691 for more fun with underscores.

@gigamonkey
Copy link

Hmmm. It seems like Scala could compile each _ used as a pseudo-identifier as a gensym but still allow _ (bah, markdown: that's an underscore in backticks) to refer to the variable named "_" for Java interop. Or am I missing something? (Totally likely.)

@paulp
Copy link

paulp commented Sep 5, 2014

@gigamonkey No, you're not missing anything. That's what it should do. With scala the difficulty is always concentrated around making the implementation do what you want.

@som-snytt
Copy link

This is tangential, but I was going to mention that at least this is no longer true:

$ scala210
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.7.0_65).
Type in expressions to have them evaluated.
Type :help for more information.

scala> (1 to 9).toList match { case List(`_`*) => true }
res0: Boolean = true

But instead it's become:

$ scala
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> (1 to 9).toList match { case List(`_`*) => true }
<console>:8: error: unsupported pattern: Star / p3: List[Int] @ (`_`)* (this is a scalac bug.)
              (1 to 9).toList match { case List(`_`*) => true }
                                                   ^

So I have to revisit a previous conjecture and propose unsupported pattern as the new nosymbol has no owner.

aloiscochard pushed a commit to aloiscochard/scala that referenced this issue Sep 5, 2014
@propensive
Copy link

p3? That's a new one for me...

@milessabin
Copy link
Member

I think exposing something gensym-like is probably the safest option ... though can we call it freshName please? (I lean towards ML rather than Lisp ;-). That's also what it's called in the reflection API.

@aryairani
Copy link

Is there a Java program that uses _ as a "perfectly valid identifier" anyway? :-\

@som-snytt
Copy link

Someone used _ as an enum element. I noticed because compiling with Java 8.

puffnfresh pushed a commit to puffnfresh/scala that referenced this issue Jul 30, 2015
folone pushed a commit that referenced this issue Aug 14, 2015
Calls to synthetic case class apply methods are inlined to the
underlying constructor invocation in refchecks.

However, this can lead to accessibility errors if the constructor
is private.

This commit ensures that the constructor is at least as accessible
as the apply method before performing this tranform.

I've manually checked that other the optimization still works in other
cases:

scala> class CaseApply { Some(42)  }
defined class CaseApply

    scala> :javap -c CaseApply
    Compiled from "<console>"
    public class CaseApply {
      public CaseApply();
        Code:
           0: aload_0
           1: invokespecial #9                  // Method java/lang/Object."<init>":()V
           4: new           #11                 // class scala/Some
           7: dup
           8: bipush        42
          10: invokestatic  #17                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
          13: invokespecial #20                 // Method scala/Some."<init>":(Ljava/lang/Object;)V
          16: pop
          17: return
    }
@milessabin
Copy link
Member

To resurrect this issue, please rework it as an issue/PR against Lightbend Scala (ie. scala/scala).

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

No branches or pull requests

7 participants