Details

    • Type: Improvement Improvement
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: JRuby 1.1.2
    • Fix Version/s: None
    • Component/s: Java Integration
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Sometimes it would be nice to permit this:

      public interface MyInterface {
        public void getProperty(String key);
      }
      
      Unable to find source-code formatter for language: ruby. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
      obj.getProperty(:some_key)
      

      Currently this gives me:
      <unknown>:1: #<NameError::Message:0x4f77a035> (NoMethodError)

      To some extent it would be nice if hashes with Symbol keys could also support get() by string from the Java side, but that's probably a different enhancement and somewhat easier to work around in the first place.

        Activity

        Hide
        Bill Dortch added a comment -

        -1. Sorry, and I've been all for simplifying Java-Ruby transitional boundaries (because I believe JRuby's great undiscovered country lies in Java integration, not Rails), but IMO that would be an abuse of the Ruby Symbol type, which (in not-quite-translatable Java terms) is something like an enum, or even an int – it's a memorable primitive. Opinions?

        Show
        Bill Dortch added a comment - -1. Sorry, and I've been all for simplifying Java-Ruby transitional boundaries (because I believe JRuby's great undiscovered country lies in Java integration, not Rails), but IMO that would be an abuse of the Ruby Symbol type, which (in not-quite-translatable Java terms) is something like an enum, or even an int – it's a memorable primitive. Opinions?
        Hide
        Trejkaz added a comment -

        Interesting opinion. The way Symbol has always been described to me is that it's like a string which you know is interned.

        Show
        Trejkaz added a comment - Interesting opinion. The way Symbol has always been described to me is that it's like a string which you know is interned.
        Hide
        Bill Dortch added a comment -

        Re: been described to me is that it's like a string which you know is interned.

        And an integer is a number that hasn't been divided by anything other than a factor – certainly a property, but not the point. Ruby symbols are immutable token-like entities, whose resemblance to Strings is a happy, mnemonically-helpful, not-quite-coincidence contrived by the numerically-challenged. [Sorry, very IMO tonight. Beer Bad.]

        Show
        Bill Dortch added a comment - Re: been described to me is that it's like a string which you know is interned. And an integer is a number that hasn't been divided by anything other than a factor – certainly a property, but not the point. Ruby symbols are immutable token-like entities, whose resemblance to Strings is a happy, mnemonically-helpful, not-quite-coincidence contrived by the numerically-challenged. [Sorry, very IMO tonight. Beer Bad.]
        Hide
        Trejkaz added a comment -

        Contrived analogy detected: Fixnum does get autoconverted to int.

        Show
        Trejkaz added a comment - Contrived analogy detected: Fixnum does get autoconverted to int.
        Hide
        Charles Oliver Nutter added a comment -

        I believe the appropriate way to handle this (and most other such conversions) would be to have Java String-accepting methods follow Ruby String coercion policies. And as far as Ruby is concerned, a Symbol is not coercible to a String:

        &#10132; jruby -e "puts 'foo' + :bar"
        :1: can't convert Symbol into String (TypeError)
        

        There's been endless discussion over this point on the ruby-talk and ruby-core mailing lists. In Ruby 1.9 Symbols are changed to not have an explicit ID, but they're still not coercible to String.

        In general, I feel like coercion rules when passing to Java should not go above and beyond coercion rules common to other Ruby methods. Of course there are exceptions, but this probably should not be one of them. Pass :some_key.to_s as a workaround, or reopen your Java type on the Ruby side and add the behavior yourself:

        import java.lang.System
        
        def System.get_property(x);
          case x;
          when String; getProperty(x)
          when Symbol; getProperty(x.to_s)
          end
        end
        p System.get_property(:'java.home')
        
        Show
        Charles Oliver Nutter added a comment - I believe the appropriate way to handle this (and most other such conversions) would be to have Java String-accepting methods follow Ruby String coercion policies. And as far as Ruby is concerned, a Symbol is not coercible to a String: &#10132; jruby -e "puts 'foo' + :bar" :1: can't convert Symbol into String (TypeError) There's been endless discussion over this point on the ruby-talk and ruby-core mailing lists. In Ruby 1.9 Symbols are changed to not have an explicit ID, but they're still not coercible to String. In general, I feel like coercion rules when passing to Java should not go above and beyond coercion rules common to other Ruby methods. Of course there are exceptions, but this probably should not be one of them. Pass :some_key.to_s as a workaround, or reopen your Java type on the Ruby side and add the behavior yourself: import java.lang. System def System .get_property(x); case x; when String ; getProperty(x) when Symbol; getProperty(x.to_s) end end p System .get_property(:'java.home')
        Hide
        Trejkaz added a comment -

        The problem as I see it, is that my method takes "something like a symbol". I defined it as a String in Java because it was the closest type Java has to a symbol type. I didn't want to actually define it as using RubySymbol as the API is supposed to be script engine neutral.

        To some extent I agree with the earlier comment that symbols are similar to enums. But sadly, symbols aren't coerced to enums either. Otherwise I would switch in a snap, as it means I could properly restrict which values they can use without manually checking.

        Show
        Trejkaz added a comment - The problem as I see it, is that my method takes "something like a symbol". I defined it as a String in Java because it was the closest type Java has to a symbol type. I didn't want to actually define it as using RubySymbol as the API is supposed to be script engine neutral. To some extent I agree with the earlier comment that symbols are similar to enums. But sadly, symbols aren't coerced to enums either. Otherwise I would switch in a snap, as it means I could properly restrict which values they can use without manually checking.
        Hide
        Thomas E Enebo added a comment -

        +1 since RubySymbol is represented internally as an intern'd string. What is downside to this?

        Show
        Thomas E Enebo added a comment - +1 since RubySymbol is represented internally as an intern'd string. What is downside to this?
        Hide
        Charles Oliver Nutter added a comment -

        Enebo: I'm starting to lean that way myself. The downside appears to be mostly that we feel like Ruby Symbol "should not" be a String. However, I think there's two concerns here. I do not believe it's right to automatically coerce Symbol to a Ruby String, since they are very different types. However in this case the coercion is not to a Ruby String, but to a Java String, which is immutable and internable. So really the coercion we'd do in Symbol would only be to unwrap the already-contained interned Java String and pass it along.

        Bill: can you think of any concrete reason why this would be bad, other than conecptually that it's a bit against the idea that "Symbols aren't Strings"?

        Show
        Charles Oliver Nutter added a comment - Enebo: I'm starting to lean that way myself. The downside appears to be mostly that we feel like Ruby Symbol "should not" be a String. However, I think there's two concerns here. I do not believe it's right to automatically coerce Symbol to a Ruby String, since they are very different types. However in this case the coercion is not to a Ruby String, but to a Java String, which is immutable and internable. So really the coercion we'd do in Symbol would only be to unwrap the already-contained interned Java String and pass it along. Bill: can you think of any concrete reason why this would be bad, other than conecptually that it's a bit against the idea that "Symbols aren't Strings"?
        Hide
        Bill Dortch added a comment -

        I once liked the idea myself, but am concerned about blurring the lines too much; if conversion rules are too lax, it could end up masking programming errors. I've thought for a while that the array conversion rules (which I originally, intentionally, made as lax as possible) really need to be tightened up. For example, this will actually "work":

        byte_arr = ['1', :b, Time.new].to_java :byte
        byte_arr[1] = '_2_'

        In the case of RubySymbols as Java strings, what makes me most uneasy is that the conversion only works in one direction; a String returned to Ruby from Java will still become a RubyString, even if it is interned. So here is what will happen:

          map = java.util.HashMap.new
          map[0] = :sym
          map[0]
         => "sym"
        

        I think this will be unexpected and confusing.

        Show
        Bill Dortch added a comment - I once liked the idea myself, but am concerned about blurring the lines too much; if conversion rules are too lax, it could end up masking programming errors. I've thought for a while that the array conversion rules (which I originally, intentionally, made as lax as possible) really need to be tightened up. For example, this will actually "work": byte_arr = ['1', :b, Time.new] .to_java :byte byte_arr [1] = '_ 2 _' In the case of RubySymbols as Java strings, what makes me most uneasy is that the conversion only works in one direction; a String returned to Ruby from Java will still become a RubyString, even if it is interned. So here is what will happen: map = java.util.HashMap.new map[0] = :sym map[0] => "sym" I think this will be unexpected and confusing.
        Hide
        Charles Oliver Nutter added a comment -

        Doesn't the hash case you demonstrate just store the RubySymbol object directly? The signature only takes Object, so there's nothing to coerce to.

        Show
        Charles Oliver Nutter added a comment - Doesn't the hash case you demonstrate just store the RubySymbol object directly? The signature only takes Object, so there's nothing to coerce to.
        Hide
        Bill Dortch added a comment -

        In my example above, that assumes that we always convert Ruby Symbols to Java Strings. If we only did so for String parameters, that might be less bad. Still don't like it, though.

        Show
        Bill Dortch added a comment - In my example above, that assumes that we always convert Ruby Symbols to Java Strings. If we only did so for String parameters, that might be less bad. Still don't like it, though.
        Hide
        Benjamin Bock added a comment -

        This issue is fixed in JRuby 1.4 but it's still marked as open here. I bisected the version which changed that behaviour, it's commit d7e5666becc3d3008f9f388f1e661d160749e402.
        Author: Charles Oliver Nutter <headius@headius.com>
        Date: Fri Oct 30 15:38:16 2009 -0500
        Fix for JRUBY-4189: calling to_java(:string) on a ruby array with a symbol in it now causes java exception

        If the concensus is to convert Ruby Symbols into Java Strings, this issue can be closed. Otherwise we have a new bug which is the opposite of this one.

        Show
        Benjamin Bock added a comment - This issue is fixed in JRuby 1.4 but it's still marked as open here. I bisected the version which changed that behaviour, it's commit d7e5666becc3d3008f9f388f1e661d160749e402. Author: Charles Oliver Nutter <headius@headius.com> Date: Fri Oct 30 15:38:16 2009 -0500 Fix for JRUBY-4189 : calling to_java(:string) on a ruby array with a symbol in it now causes java exception If the concensus is to convert Ruby Symbols into Java Strings, this issue can be closed. Otherwise we have a new bug which is the opposite of this one.
        Hide
        Hiro Asari added a comment -

        Indeed, this appears to be fixed. Thanks, Ben, for pointing it out.

        Show
        Hiro Asari added a comment - Indeed, this appears to be fixed. Thanks, Ben, for pointing it out.

          People

          • Assignee:
            Unassigned
            Reporter:
            Trejkaz
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: