TryRuby raises undefined method `[]=' for String - ruby

I am working to replace a character in a string, changing "cat" into "hat".
Here's my code:
str = "cat"
str[0] = 'h'
puts str
But when I run this code in TryRuby I get this error:
NoMethodError: undefined method `[]=' for "cat"

l am using Try ruby's editor
ruby.github.io/TryRuby uses Opal (a Ruby-to-JavaScript compiler) to evaluate the code in the browser. Opal provides its own String class which doesn't implement []=.
This seems to be a known limitation (among others). From the documentation: (emphasis added)
For performance and ease of runtime features, all strings in Opal are immutable, i.e. #<<, #gsub!, etc. do not exist.

You can use the gsub method and do it like this:
str = 'cat'
puts str.gsub(str[0], 'h')

Related

Why does Ruby string formatting with hashes behave inconsistently across versions?

I wrote some code that used a "dynamic hash" to return values for keys, where the values were calculated. I tested it under irb (RUBY_VERSION 2.3.3) and everything seemed good. Below is a trivial example demonstrating the idea.
PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS # => "Foo: foo! Bar: bar!"
PROPS[:xyzzy] # => "xyzzy!"
But then deploying my code into the environment where it used (a plugin for the modeling tool Sketchup) which apparently has Ruby 2.2.4 the string formatting example above yields a KeyError: key{foo} not found.
PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS # KeyError: key{foo} not found
PROPS[:xyzzy] # => "xyzzy!"
But accessing the hash with any key works fine... Reading at http://ruby-doc.org/core-2.2.4/Kernel.html#method-i-sprintf doesn't provided much in the way of specifying why hash defaults would not behave as expected.
Obviously I can do different things, like invent my own replacement functions and variable syntax. As an aside, apparently the "hashes" passed to "%" or sprintf must actually BE Hash objects, violating Ruby's supposed duck-typing flexibility.
I can confirm that it does not work in Ruby 2.1.5 .
I will give some hints on how you could find out which ruby code to define to get the stuff going without reading C or Ruby code from MRI.
I know, this is not a full answer, but the text is too long to give in a comment.
Following is an irb session
>> detector = Object.new
=> #<Object:0x00000002257900>
>> def detector.method_missing m
>> puts m.to_s
>> end
=> :method_missing
>> "Foo: %{fnoo} Bar: %{bar}" % detector
to_ary
to_hash
ArgumentError: one hash required
from (irb):37:in `%'
from (irb):37
from /home/felix/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
This tells us that during interpolation methods were called that are not implemented by our dummy "detector" Object (to_hash to be precisely; through other tests I know that to_ary is also called if given object is a Hash, so we can ignore that one).
It does however not tell us whether already something like detector.class or detector is_a Hash? etcpp. were called.
Now I await the downvotes ;)
Btw, if you want to dive in via C - and I came to believe that this is probably needed in this case - you can start digging here: https://github.com/ruby/ruby/blob/6d728bdae9de565ad9d0b2fee2d4c2a33c6f4eac/sprintf.c#L579 (more or less "sprintf" on ruby 2.1).

Ruby - cannot convert individual chars in string to ASCII

I am trying to run the following code on http://repl.it/languages/Ruby/, but I am encountering a NoMethodError:
a = "string"
a.each_char do |c|
puts c.ord
end
The error details are as follows:
(eval):1: undefined method `ord' for "s":String (NoMethodError)
from (eval):0:in `each_char'
from (eval):0
Please could somebody explain to me why my code does not work?
The each_char method of String yields each character as a separate String.
The Ruby version running on repl.it is quite old (1.8.7). The String class in that version of Ruby doesn't define an ord method, so your code fails to run with a NoMethodError.
ord was added to String in Ruby 1.9, so your code will run on newer versions of Ruby.
On Ruby 1.8.7 (and repl.it), you could use one of the following alternatives instead:
a = "string"
a.each_char do |c|
puts c[0]
end
a = "string"
a.each_byte do |c|
puts c
end
However, please note that these examples won't behave identically to your original code if your string uses a multi-byte encoding. The ord method returns a Unicode code point. The Ruby 1.8.7 examples will give you individual bytes.
The code as is will print the ascii code of each letter. Perhaps you're looking at the return value which would be the original string "string"?

What is the # (sharp, number, pound, hash) sign used for in Ruby?

What are the various meanings of the Ruby sharp/number sign/pound/hash(#) symbol
How many contexts does the symbol # in Ruby have ?
I know that #` represents comment
# a comment
or 'convert to the value':
i = 1
print "#{i}" # simple example
However I also see some Ruby docs describe built-in methods like these:
Array#fill
File::file?
Why do they describe the same thing using 2 different symbols ?
I am new in Ruby. Thanks
This is how instance method described:
Array#fill
So you can:
a = Array.new(2)
=> [nil, nil]
a.fill(42)
=> [42, 42]
This is how class method described:
String::new
s = String.new('abc')
=> "abc"
In Perl, # is used for commenting, and since Perl is an 'ancestor' of Ruby, the role was carried over.
The "#{}" syntax is called 'interpolation' and the pound was picked most likely because interpolation is similar in a sense to commenting, because you are changing the context of your code (in this case to another context for execution)
The # following a Class name is just meant to indicate the following identifier is a method of that Class, and is just a convention. Read more about it here: Why are methods in Ruby documentation preceded by a hash sign?
The :: is interesting, it acts similarly to the . in that you can call methods via both
Car::is_hybrid?
and
car.is_hybrid?
As you will see in most code though . is preferred for methods.
One case where :: is often preferred is where you have constant in the class and you will see this in system calls such as Math::PI or ones you create, e.g. ThePentagon::NUMBER_OF_BUILDING_SIDES
Just to show you as an example,that Ruby shows instance method preceded with the symbol # and class methods preceded with the symbol ..
class Foo
def self.foo;end
def bar;end
end
p Foo.method(:foo) # => #<Method: Foo.foo>
p Foo.new.method(:bar) # => #<Method: Foo#bar>

How can I make a custom Ruby type behave like a string?

If I have a custom Ruby class representing some string type, as in
class MyString
end
Which functions should I implement in order to make the following use cases possible:
Passing a Ruby string whenever a MyString is expected
Passing a MyString whenever a Ruby string is expected
Comparing a Ruby string with a MyString value (it shouldn't matter whether I use s == t or t == s).
I saw various interesting functions like to_s, cmp, == and eq already, but it's not clear to me when each of them is called.
My concrete use case is that I'm writing a Ruby extension using the C API which exposes functions taking (and returning) values of a custom string type (QString, to be precise) which my extension also registers. However, I'd like to make those custom strings behave as intuitive as possible. Unfortunately I can't just return Ruby strings from my C code since it should be possible to call Qt methods on the strings.
There are at least three approaches:
class MyString < String; ...; end
Define #to_s
Define #to_str
Doing both #2 and #3 will make the object act very much like a real String even if it isn't a subclass.
#to_s is an explicit converter, meaning it must appear in Ruby code to work.
#to_str is an implicit converter, meaning the Ruby interpreter will attempt to call it when it wants a String but is given something else.
Update:
Here is an example of some fun you can have with to_str:
begin
open 1, 'r'
rescue TypeError => e
p e
end
class Fixnum
def to_str; to_s; end
end
open 1, 'r'
When run, the first open fails with TypeError but the second proceeds to looking for 1.
#<TypeError: can't convert Fixnum into String>
fun.rb:9:in `initialize': No such file or directory - 1 (Errno::ENOENT)
from fun.rb:9:in `open'
Although it's tempting to sub-class String to give it a new initialize method that will import these QString-type strings, you may just want to tack on an extension to String that helps with the conversion so you don't have to re-implement a version of String itself.
For instance, with two methods you could pretty much have this done:
class String
def self.from_qstring(qstring)
new(...)
end
def to_qstring
# ...
end
end
Having multiple storage types for String is not going to be a problem until you start comparing them, but given that Ruby's String is quite robust, writing a work-alike is difficult.
It's not generally a good idea to subclass classes that were built by someone else in Ruby, because too many things can go wrong. (You might, for example, override an internal method without knowing it.)
1) define Mystring.to_s to get automatic conversion from a Mystring to a String.
2) Not sure what you mean by this. If you want a String method that returns a Mystring, you will have to monkey-patch String:
Class String
def to_mystring
return Mystring.new(self)
end
end
3) to get t == s (assuming s is an instance of String and t an instance of Mystring) define <=>. To get s == t you will have to monkey patch String again, though.
Since I was looking for something similar, but none of the other answers worked for me, I'll post what did work for me.
Found in this blog post which discourage the use of inheriting String and instead use simple delegator.
Inheriting from SimpleDelegator create an object which delegate everything to a string of your choice but on which you add behavior as you see fit.
class ChunkyBacon < SimpleDelegator
def initialize(content)
#content = content
super #content
end
def chunky_bacon?
#content == 'chunky_bacon'
end
end
test = ChunkyBacon.new('choco pizza') # => 'choco pizza'
test.chunky_bacon? # => false

Ruby - equivalent of Python __str__() method?

In Ruby, is there the equivalent of the __str__() method that you can define on Python classes?
You could use to_s.
http://briancarper.net/2006/09/26/ruby-to_s-vs-to_str/
FWIW, inspect is probably more like __repr__() than __str__()
from the library reference...
repr( self)
Called by the repr() built-in function and by string conversions (reverse quotes) to compute the ``official'' string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form "<...some useful description...>" should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an ``informal'' string representation of instances of that class is required.
On the core classes it is typically 'inspect'.
Eg:
irb(main):001:0> puts "array is: #{[1,2,3].inspect}"
array is: [1, 2, 3]
=> nil
irb(main):002:0> puts "array is: #{[1,2,3]}"
array is: 123
=> nil
irb(main):003:0>

Resources