Using .tupled method when companion object is in class

10,644

Solution 1

You can also write

(Person.apply _).tupled

to avoid repeating the types.

Solution 2

This is very similar to what Alexey Romanov said, but in order to avoid lifting apply whenever you need tupled, we just add it to our companion objects.

object Person {
  def something = "rawr"
  def tupled = (Person.apply _).tupled
}

Now you can call Person.tupled just like you would have if it didn't have a companion object.

Solution 3

One workaround is define a companion object as follows:

object Person extends((String,String) => Person) {
    ...
}

See. https://groups.google.com/d/msg/scala-user/jyWBMz5Qslw/Bryv4ftzRLgJ

Solution 4

To build on some of the other comments you could do the following as well since tuple is calling the generated default apply method for the case class.

object Person {
  ...
  def tupled = (this.apply _).tupled
}
Share:
10,644

Related videos on Youtube

mdedetrich
Author by

mdedetrich

Updated on January 10, 2021

Comments

  • mdedetrich
    mdedetrich over 3 years

    I am in the process of migrating from Slick to Slick 2, and in Slick 2 you are meant to use the tupled method when projecting onto a case class (as shown here http://slick.typesafe.com/doc/2.0.0-RC1/migration.html)

    The problem is when the case class has a companion object, i.e. if you have something like this

    case class Person(firstName:String, lastName:String) {
    
    }
    

    Along with a companion object

    object Person {
      def something = "rawr"
    }
    

    In the same scope, the tupled method no longer works, because its trying to run tupled on the object, instead of the case class.

    Is there a way to retrieve the case class of Person rather than the object, so you can call tupled properly?

    • Erik Kaplun
      Erik Kaplun about 10 years
      do you absolutely need the companion object? also, I think this is a general Scala question not really Slick related.
    • mdedetrich
      mdedetrich about 10 years
      Yes I do, unless I want to refactor like half of my project (the companion object has a lot of helper methods for the case class in question) And yes you are right, its not directly related to slick, just mentioned it because Slick may have its own workaround
    • Erik Kaplun
      Erik Kaplun about 10 years
      You can't just rename the companion object and import the renamed object's contents directly to the case class? Alternatively, you can just make your custom companion object look like an autogenerated one manually.
    • mdedetrich
      mdedetrich about 10 years
      Is what I am asking something impossible to do? I mean I can do that (amongst various other options), but that object is used in hundreds of places, so it would be a pretty painful refactor
    • Erik Kaplun
      Erik Kaplun about 10 years
      I've proposed a workaround, so no, it's not impossible, but it's ugly... overriding case class companion objects isn't really intended, otherwise what's the point of using the case class in the first place? case classes are afaik just syntactic sugar over regular classes + autogenerated companions with apply and unapply... if you override the autogen. companion, you're by definition defeating the purpose of case classes.
    • mdedetrich
      mdedetrich about 10 years
      Well it was a design choice, you override the case class with an object for the same reason you use static final in java, that is, you want to attach helper methods onto a namespace In this case I want to attach helper methods to the Person namespace, things like apply and unapply are just for creating an instance of Person (which case classes generate), however it doesn't have anything to do with the other methods that are attached to the Person type
    • Erik Kaplun
      Erik Kaplun about 10 years
      As I said, you can put the helper functions in any object and import them to Person; it doesn't have to be a companion object.
    • mdedetrich
      mdedetrich about 10 years
      Yes, but idiomatically speaking, if you have global functions that deal with Person, they should work on the Person namespace, thats the whole purpose of the Singleton Pattern There is a reason when have global methods with BigDecimal (as an example), the methods are attached to BigDecimal, and not BigDecimalHelpers or something like that
    • Erik Kaplun
      Erik Kaplun about 10 years
      It's hardly idiomatic to override and then re-implement the gist of case classes.
    • mdedetrich
      mdedetrich about 10 years
      The intention to use an object with the same namespace as its case class is not to override the case class, the intention is to add methods/values from the object into the same namespace of the case class. This practice is done in almost every mainstream OOP language (including Java,Scala and others). You are not overriding or reimplementing the case classes (unless you are defining apply, unapply in your object), you are adding ontop of the namespace. Whether a class is a case class or a normal class is irrelevant, case classes just add an apply/unapply methods.
    • Erik Kaplun
      Erik Kaplun about 10 years
      OK, I see, but when why did the tupled method disappear?
    • mdedetrich
      mdedetrich about 10 years
      Actually they don't disappear, have a look at this answer stackoverflow.com/a/22368413/1519631. As to why the tupled method "disappears", I have no clue. After some quick reading, it may be down to how its brought into scopes by implicits (this is done internally). Remember that you can still use case classes fine, even if there is a companion object. This issue only cropped up because I specifically needed to use the tupled method
  • mdedetrich
    mdedetrich about 10 years
    Thanks, that actually works (I assume there isn't any workaround for the boilerplate that is (String,String) )
  • AHonarmand
    AHonarmand almost 6 years
    What if the companion object has its own apply method (an overloaded constructor)? Compiler cannot resolve the apply...
  • AHonarmand
    AHonarmand almost 6 years
  • WestCoastProjects
    WestCoastProjects over 5 years
    this is not compiling: apply not found
  • Alexey Romanov
    Alexey Romanov over 5 years
    @javadba Yes, it is: scalafiddle.io/sf/a5rsgke/0. Are you sure you have a case class?