I think I understand StringIO somewhat as being similar to Java's StringBuffer class, but I don't really understand it fully. How would you define it and its purpose/possible uses in Ruby? Just hoping to clear up my confusion.
no, StringIO is more similar to StringReader/StringWriter than StringBuffer.
In Java StringBuffer is the mutable version of String (since String is immutable).
StringReader/StringWriter are handy classes meant to be used when you want to fake file access . You can read/write in a String with the same stream-oriented interface of Reader/Writer: it is immensely useful in unit testing.
Related
The following code is valid:
(1..5).to_a
(1..5) is a Range. The method to_a appears to convert a range to an array.
However, the documentation for Range does not document. Since this documentation is presumably auto-generated from the source with Yard, I doubt it could not be in the list of methods. Is there auto conversion going on?
How is the above legal Ruby?
The following code is valid ruby:
b = (1..5).to_a
(1..5) is a Range object, and b is an Array object. The official(?) documentation for the Class Range does not document the method to_a, which appears to convert a range to an array.
So, how is the above legal Ruby?
Ruby has something called "inheritance". Inheritance is a method for differential code-reuse that actually does not only exist in Ruby, but is in fact quite popular in many languages such as Java, C♯, C++, Python, PHP, Scala, Kotlin, Ceylon, and so on and so forth.
Inheritance allows you to define methods in one place, and then inherit them in another place, overriding and defining only the methods whose behavior differs. Hence, "differential code re-use".
In this particular case, the method you are looking at is Enumerable#to_a.
Note: Ruby actually has two forms of inheritance, mixin inheritance and class inheritance. Mixin inheritance is like class inheritance where the mixin doesn't know its superclass. (The definitive resource about mixin inheritance is Gilad Bracha's PhD Thesis The Programming Language Jigsaw – Mixins, Modularity, and Multiple Inheritance.)
The official(?) documentation
Actually, ruby-doc is a third-party site. There is no official documentation site. (However, the documentation on ruby-doc is generated from documentation comments in YARV, one of the major Ruby implementations, and one that Yukihiro Matsumoto actively contributes to.)
Since this documentation is presumably autogenerated from the source with Yard,
It is actually autogenerated from the YARV source with RDoc, not YARD.
I'm confused how it could not be in the list of methods,
Note that the explanation I gave is the correct one, but there could be many other explanations. The most simple one: the reason why the method is not in the documentation is that it is not documented. Another reason could be a bug in the documentation generator that prevents the documentation for that method being displayed, a typo in the source code that prevents the documentation generator from recognizing the documentation, and many, many others.
so is there auto conversion going on?
No. Ruby does not have automatic conversions in the language. There are some methods which for reasons of efficiency are implemented in a non-object-oriented manner, and require an object to be an instance of a specific class (as opposed to the object-oriented manner, which would only require the object to conform to a specific protocol). Because it is a severe restriction to require an object to be an instance of a specific class, those methods will usually offer an "escape hatch" to the programmer, by sending a specific message and allowing the object to respond with an object of the required class.
For example, all methods printing something to the console, require an instance of String, but they will try sending to_s first, before rejecting the argument.
These are sometimes called "implicit conversions", but they have nothing to do with implicit conversions as in Scala or implicit casts as in C♯. They are in fact not even part of the language, they are just a convention for library writers.
In Ruby, when you design an embedded DSL a very useful trick is to leverage instance_eval. That way one can offer special statements within a certain block by implementing them as private methods on a special object. This is very nice for contextual stuff.
For an example see: https://robots.thoughtbot.com/writing-a-domain-specific-language-in-ruby
I was wondering what the closest equivalent would be in a Scala EDSL? More specifically how would I offer parts of the syntax only within a certain context that is delimited by a block?
If anybody's wondering: It looks like this is gonna be solve by so-called implicit function types. Here's a good write-up of the idea by Martin Odersky himself: https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html
I understand the other Reader subclasses in java.io, but I can't think of a use case where I'd need a CharArrayReader or a StringReader when I already have data available as String or char[].
Is it because of compatibility? To "feed" a String or char[] into something that expects Reader as parameter?
I would not call it compatibility, it's flexibility.
You are right, some libraries that deal with character based data provide a method accepting a Reader. So the user of that library can choose any mechanism to feed that library.
If you have a file on the harddisk, use a FileReader. If you have an arbitrary InputStream, use an InputStreamReader (with an appropriate encoding). If you already have a simple String in your code, use a StringReader. And so on ...
In addition to what has been answered already, these classes are very handy when you write unit tests for a method that expects a reader.
In the answer to this SO question Jörg W Mittag says:
There is no such thing as a constructor in Ruby.
I didn't think much of that, until I read the Wikipedia article on constructors, which states:
Immutable objects must be initialized in a constructor.
Since symbols are immutable in Ruby, how are they made? Wikipedia would seem to think they must be made with a constructor, yet Jörg says there are no constructors in Ruby.
I'm fairly new to OOP concepts and programming in general, so it possible I am missing something fairly basic, but from my perspective it there is a contradiction between these sources.
When people say
There is no such thing as a constructor in Ruby.
they mean that there is no special method type corresponding to a constructor, the way there is in C++ and Java.
In Ruby, the initialize method is, by convention, used to initialize a new object. However, it is not a special method -- it's a method just like any other method in Ruby.
Symbols are 'initialized' in some dark inside part of the ruby runtime, that you don't need to worry about.
If you make your own immutable class in ruby, it would have to be initialized in it's "constructor", which in ruby means in it's #initialize method. The initialize method may or may not technically be a constructor, but it's the method that is called when the object is instantiated, which is the point the wikipedia article is making -- since an immutable object can't be changed once created, any state has to be set when it's created, not later.
Wikipedia article calls this 'a constructor', but different languages use different terminology or exact constructs, the wikipedia article wasn't written with ruby in mind. For ruby, "place you can set state on object instantiation" is typically initialize method. (I say 'typically', because you can do all kinds of crazy things in ruby if you try). The wikipedia article is still right that if an object is truly immutable, any setting of state happens to happen on object creation, not afterwords -- that's just the meaning of 'immutable', right?
That's for immutable classes implemented by ruby source code. But good luck finding an 'initialize' method for symbols. They don't work that way. They are just provided by ruby itself, by the runtime, and we don't need to worry about the details.
I'm working on a ruby project in which we are planning to do some operations with ruby strings. Some operations are simple (like counting the number of words) and others more complex (like checking if a given string is in the correct language).
A possible way to implement this is by patching the String class with extra methods, without modifying any existing methods, and adding behaviors like "some string".word_count and "some string".cjk?.
Another approach, based on FileUtils is to create a class or module full of methods and always use string as parameters, like OddClassName.word_count("some string") and OddClassName.cjk?("some string"). We like the first better because of readability.
I understand that monkey patching a basic class as described in the first alternative can have name clashes. However, if this is the main application, not a library, should I worry with it at all?
So, the questions are:
Is adding methods to ruby base classes a bad practice? If yes, is that in all cases or only in some cases?
What is the best approach to accomplish this?
What could be the name of 'OddClassName'?
Please suggest any alternatives.
Monkey patching isn't considered to be a bad practice unless you are writing odd methods that do not have PatchedClass-related behavior (for example, String.monkeyPatchForMakingJpegFromString is rather bad, but Jpeg.fromString is good enough.)
But if your project is rather large, the libraries that you use in it may happen to have colliding patches, so you may have one more problem with all these patching stuffs. In Ruby 2.0, refinements come to an aid. They work as follows: you define a module, refine your (even core) class in it, and then use that module where it's necessary. So, in your code it works as:
YourClass.new.refinedMethodFromCoreClass #=> some result
But
CoreClass.refinedMethodFromCoreClass
produces undefined method exception.
That's all monkey patching stuff: monkey patching is useful and convenient, but refinements add some features, that make your code more secure, maintainable and neat.
I'd use a new class, call it Doc or something because getting the word count and checking languages sounds like operations for documents.
Let it take a string as a constructor parameter and have modifications chain to return a new Doc. Also give it a to_s method that returns the string.
class Doc
def initialize(str)
#str = str
end
def to_s
#str
end
define word_count, cjk?, etc.
end
Doc.new("Some document").word_count
# => 2