How to return from Scala method with generics












0















I have two trait



trait TResponseData extends Serializable {} //all response data
trait TRequestData extends Serializable {} //all request


Now I have Response class, which contains data and request



case class Response[A <: TResponseData, B <: TRequestData](data: A, request: B = null){}


While instance of case class Response must have data, request is not mandatory. So I declared its default to null in case class constructor. From Scala console, I am able to create its instance like



Response(null, null)
Response(null)


To generate instance of Response, I have created helper method:



def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] = {
if (passRequestInResponse)
return Response(data, request)
return Response(data, null)
}


Based on boolean passRequestInResponse, I am setting request in Response.
On compiling same, I am getting follow error:



error: type mismatch;
found : Null(null)
required: B
return Response(data, null)


How can I achieve same (making request optional in generateResponse method)










share|improve this question



























    0















    I have two trait



    trait TResponseData extends Serializable {} //all response data
    trait TRequestData extends Serializable {} //all request


    Now I have Response class, which contains data and request



    case class Response[A <: TResponseData, B <: TRequestData](data: A, request: B = null){}


    While instance of case class Response must have data, request is not mandatory. So I declared its default to null in case class constructor. From Scala console, I am able to create its instance like



    Response(null, null)
    Response(null)


    To generate instance of Response, I have created helper method:



    def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] = {
    if (passRequestInResponse)
    return Response(data, request)
    return Response(data, null)
    }


    Based on boolean passRequestInResponse, I am setting request in Response.
    On compiling same, I am getting follow error:



    error: type mismatch;
    found : Null(null)
    required: B
    return Response(data, null)


    How can I achieve same (making request optional in generateResponse method)










    share|improve this question

























      0












      0








      0








      I have two trait



      trait TResponseData extends Serializable {} //all response data
      trait TRequestData extends Serializable {} //all request


      Now I have Response class, which contains data and request



      case class Response[A <: TResponseData, B <: TRequestData](data: A, request: B = null){}


      While instance of case class Response must have data, request is not mandatory. So I declared its default to null in case class constructor. From Scala console, I am able to create its instance like



      Response(null, null)
      Response(null)


      To generate instance of Response, I have created helper method:



      def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] = {
      if (passRequestInResponse)
      return Response(data, request)
      return Response(data, null)
      }


      Based on boolean passRequestInResponse, I am setting request in Response.
      On compiling same, I am getting follow error:



      error: type mismatch;
      found : Null(null)
      required: B
      return Response(data, null)


      How can I achieve same (making request optional in generateResponse method)










      share|improve this question














      I have two trait



      trait TResponseData extends Serializable {} //all response data
      trait TRequestData extends Serializable {} //all request


      Now I have Response class, which contains data and request



      case class Response[A <: TResponseData, B <: TRequestData](data: A, request: B = null){}


      While instance of case class Response must have data, request is not mandatory. So I declared its default to null in case class constructor. From Scala console, I am able to create its instance like



      Response(null, null)
      Response(null)


      To generate instance of Response, I have created helper method:



      def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] = {
      if (passRequestInResponse)
      return Response(data, request)
      return Response(data, null)
      }


      Based on boolean passRequestInResponse, I am setting request in Response.
      On compiling same, I am getting follow error:



      error: type mismatch;
      found : Null(null)
      required: B
      return Response(data, null)


      How can I achieve same (making request optional in generateResponse method)







      scala






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 1 at 10:17









      user811602user811602

      5471828




      5471828
























          3 Answers
          3






          active

          oldest

          votes


















          2














          Using null is a bad idea (as is return) so it is better to use Option:



          trait TResponseData extends Serializable //all response data
          trait TRequestData extends Serializable //all request

          case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

          def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
          if (passRequestInResponse) {
          Response(data, Some(request))
          } else {
          Response(data)
          }


          You can also do some Option magic like this:



          def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
          Response(
          data,
          Some(request).filter(_ => passRequestInResponse)
          )


          The advantage of this formulation is that it will work if request is null, and will treat this case as if passRequestInResponse was false



          Update



          As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. If you don't like that Some in the first version, then create a class object with a custom apply method:



          object Response {
          def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
          = Response(data, Option(request))
          }


          Then you can just use Response(data, request). This will work correctly if request is null.






          share|improve this answer


























          • thanks. I am using option magic now :)

            – user811602
            Jan 1 at 14:02



















          2














          You can either modify the generateResponse() return type...



          def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
          ,request: B
          ,passRequestInResponse: Boolean
          ): Response[A, _] =
          if (passRequestInResponse) Response(data, request)
          else Response(data, null)


          ... or you can cast the null to the required type.



          def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
          ,request: B
          ,passRequestInResponse: Boolean
          ): Response[A, B] =
          if (passRequestInResponse) Response(data, request)
          else Response(data, null.asInstanceOf[B])


          (But don't use return. It's not idiomatic Scala.)



          In general, I don't really see why you need generateResponse() at all. The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None. (Idiomatic Scala avoids null.)






          share|improve this answer


























          • thanks for reply. I will be using generateResponse because I am doing some more operation in it.

            – user811602
            Jan 1 at 14:00



















          1














          The reason for the error is that all types in Scala have a bottom type of Nothing. Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing.



          To solve this you can add a lower bound:



           def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
          passRequestInResponse: Boolean): Response[A, B] = {


          this will mean that Nothing is an illegal type for B as the minimum allowed in Null.



          The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better.



          P.S. you shouldn't be using return. As you can see in other answers you can do:



          if (passRequestInResponse) {
          Response(data, Some(request))
          } else {
          Response(data)
          }


          as this will give the value. Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994658%2fhow-to-return-from-scala-method-with-generics%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            Using null is a bad idea (as is return) so it is better to use Option:



            trait TResponseData extends Serializable //all response data
            trait TRequestData extends Serializable //all request

            case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            if (passRequestInResponse) {
            Response(data, Some(request))
            } else {
            Response(data)
            }


            You can also do some Option magic like this:



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            Response(
            data,
            Some(request).filter(_ => passRequestInResponse)
            )


            The advantage of this formulation is that it will work if request is null, and will treat this case as if passRequestInResponse was false



            Update



            As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. If you don't like that Some in the first version, then create a class object with a custom apply method:



            object Response {
            def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
            = Response(data, Option(request))
            }


            Then you can just use Response(data, request). This will work correctly if request is null.






            share|improve this answer


























            • thanks. I am using option magic now :)

              – user811602
              Jan 1 at 14:02
















            2














            Using null is a bad idea (as is return) so it is better to use Option:



            trait TResponseData extends Serializable //all response data
            trait TRequestData extends Serializable //all request

            case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            if (passRequestInResponse) {
            Response(data, Some(request))
            } else {
            Response(data)
            }


            You can also do some Option magic like this:



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            Response(
            data,
            Some(request).filter(_ => passRequestInResponse)
            )


            The advantage of this formulation is that it will work if request is null, and will treat this case as if passRequestInResponse was false



            Update



            As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. If you don't like that Some in the first version, then create a class object with a custom apply method:



            object Response {
            def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
            = Response(data, Option(request))
            }


            Then you can just use Response(data, request). This will work correctly if request is null.






            share|improve this answer


























            • thanks. I am using option magic now :)

              – user811602
              Jan 1 at 14:02














            2












            2








            2







            Using null is a bad idea (as is return) so it is better to use Option:



            trait TResponseData extends Serializable //all response data
            trait TRequestData extends Serializable //all request

            case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            if (passRequestInResponse) {
            Response(data, Some(request))
            } else {
            Response(data)
            }


            You can also do some Option magic like this:



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            Response(
            data,
            Some(request).filter(_ => passRequestInResponse)
            )


            The advantage of this formulation is that it will work if request is null, and will treat this case as if passRequestInResponse was false



            Update



            As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. If you don't like that Some in the first version, then create a class object with a custom apply method:



            object Response {
            def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
            = Response(data, Option(request))
            }


            Then you can just use Response(data, request). This will work correctly if request is null.






            share|improve this answer















            Using null is a bad idea (as is return) so it is better to use Option:



            trait TResponseData extends Serializable //all response data
            trait TRequestData extends Serializable //all request

            case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            if (passRequestInResponse) {
            Response(data, Some(request))
            } else {
            Response(data)
            }


            You can also do some Option magic like this:



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
            Response(
            data,
            Some(request).filter(_ => passRequestInResponse)
            )


            The advantage of this formulation is that it will work if request is null, and will treat this case as if passRequestInResponse was false



            Update



            As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. If you don't like that Some in the first version, then create a class object with a custom apply method:



            object Response {
            def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
            = Response(data, Option(request))
            }


            Then you can just use Response(data, request). This will work correctly if request is null.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 1 at 11:15

























            answered Jan 1 at 10:54









            TimTim

            6,3811819




            6,3811819













            • thanks. I am using option magic now :)

              – user811602
              Jan 1 at 14:02



















            • thanks. I am using option magic now :)

              – user811602
              Jan 1 at 14:02

















            thanks. I am using option magic now :)

            – user811602
            Jan 1 at 14:02





            thanks. I am using option magic now :)

            – user811602
            Jan 1 at 14:02













            2














            You can either modify the generateResponse() return type...



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, _] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null)


            ... or you can cast the null to the required type.



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, B] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null.asInstanceOf[B])


            (But don't use return. It's not idiomatic Scala.)



            In general, I don't really see why you need generateResponse() at all. The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None. (Idiomatic Scala avoids null.)






            share|improve this answer


























            • thanks for reply. I will be using generateResponse because I am doing some more operation in it.

              – user811602
              Jan 1 at 14:00
















            2














            You can either modify the generateResponse() return type...



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, _] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null)


            ... or you can cast the null to the required type.



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, B] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null.asInstanceOf[B])


            (But don't use return. It's not idiomatic Scala.)



            In general, I don't really see why you need generateResponse() at all. The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None. (Idiomatic Scala avoids null.)






            share|improve this answer


























            • thanks for reply. I will be using generateResponse because I am doing some more operation in it.

              – user811602
              Jan 1 at 14:00














            2












            2








            2







            You can either modify the generateResponse() return type...



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, _] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null)


            ... or you can cast the null to the required type.



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, B] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null.asInstanceOf[B])


            (But don't use return. It's not idiomatic Scala.)



            In general, I don't really see why you need generateResponse() at all. The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None. (Idiomatic Scala avoids null.)






            share|improve this answer















            You can either modify the generateResponse() return type...



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, _] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null)


            ... or you can cast the null to the required type.



            def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
            ,request: B
            ,passRequestInResponse: Boolean
            ): Response[A, B] =
            if (passRequestInResponse) Response(data, request)
            else Response(data, null.asInstanceOf[B])


            (But don't use return. It's not idiomatic Scala.)



            In general, I don't really see why you need generateResponse() at all. The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None. (Idiomatic Scala avoids null.)







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 1 at 10:56

























            answered Jan 1 at 10:47









            jwvhjwvh

            27.5k52140




            27.5k52140













            • thanks for reply. I will be using generateResponse because I am doing some more operation in it.

              – user811602
              Jan 1 at 14:00



















            • thanks for reply. I will be using generateResponse because I am doing some more operation in it.

              – user811602
              Jan 1 at 14:00

















            thanks for reply. I will be using generateResponse because I am doing some more operation in it.

            – user811602
            Jan 1 at 14:00





            thanks for reply. I will be using generateResponse because I am doing some more operation in it.

            – user811602
            Jan 1 at 14:00











            1














            The reason for the error is that all types in Scala have a bottom type of Nothing. Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing.



            To solve this you can add a lower bound:



             def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
            passRequestInResponse: Boolean): Response[A, B] = {


            this will mean that Nothing is an illegal type for B as the minimum allowed in Null.



            The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better.



            P.S. you shouldn't be using return. As you can see in other answers you can do:



            if (passRequestInResponse) {
            Response(data, Some(request))
            } else {
            Response(data)
            }


            as this will give the value. Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/






            share|improve this answer




























              1














              The reason for the error is that all types in Scala have a bottom type of Nothing. Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing.



              To solve this you can add a lower bound:



               def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
              passRequestInResponse: Boolean): Response[A, B] = {


              this will mean that Nothing is an illegal type for B as the minimum allowed in Null.



              The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better.



              P.S. you shouldn't be using return. As you can see in other answers you can do:



              if (passRequestInResponse) {
              Response(data, Some(request))
              } else {
              Response(data)
              }


              as this will give the value. Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/






              share|improve this answer


























                1












                1








                1







                The reason for the error is that all types in Scala have a bottom type of Nothing. Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing.



                To solve this you can add a lower bound:



                 def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
                passRequestInResponse: Boolean): Response[A, B] = {


                this will mean that Nothing is an illegal type for B as the minimum allowed in Null.



                The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better.



                P.S. you shouldn't be using return. As you can see in other answers you can do:



                if (passRequestInResponse) {
                Response(data, Some(request))
                } else {
                Response(data)
                }


                as this will give the value. Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/






                share|improve this answer













                The reason for the error is that all types in Scala have a bottom type of Nothing. Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing.



                To solve this you can add a lower bound:



                 def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
                passRequestInResponse: Boolean): Response[A, B] = {


                this will mean that Nothing is an illegal type for B as the minimum allowed in Null.



                The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better.



                P.S. you shouldn't be using return. As you can see in other answers you can do:



                if (passRequestInResponse) {
                Response(data, Some(request))
                } else {
                Response(data)
                }


                as this will give the value. Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 1 at 12:00









                Assaf MendelsonAssaf Mendelson

                7,39511932




                7,39511932






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994658%2fhow-to-return-from-scala-method-with-generics%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith