Ruby was initially designed to be a successor of the Perl programming language, which also means that it inherited a lot of Perl's expressiveness. To celebrate this, the TRIC¹ contest was invented: Write the most Transcendental, Imbroglio Ruby program! Illustrate some of the subtleties (and design issues) of Ruby! Show the robustness and portability of Ruby interpreters! Stabilize the spec of Ruby…
Have you ever been confused by the __underscores__ required by some of __RUBY__ 's features? You can get it right with this overview of all of "super snake" keywords and methods. There are three different types of underscore-wrapped syntaxes in the Ruby core language: keywords Object methods and Kernel methods. Let us take a look at each of them, and understand the motivations behind. Or directly…
The Ruby core team cares a lot about Unicode, and this is why we have pretty good Unicode support in the language. Even though the Unicode standard evolves constantly - it gets updated at least once a year - Ruby's Unicode support is often only a little bit behind the current version of Unicode. The following tables list which Ruby version supports which version of Unicode / Emoji: Ruby / Unicode…
Recent Ruby versions allow you to choose from a wide-range of uppercase letters - beyond just ASCII - to start a constant / class name: class Österreich # 00D6 ├─ Ö ├─ LATIN CAPITAL LETTER O WITH DIAERESIS end # Syntax OK However, it is not possible to use just any Unicode character: class ℻ # 213B ├─ ℻ ├─ FACSIMILE SIGN end # SyntaxError Only characters of the categories Uppercase_Letter or…
Ruby's mode of operation can be altered with some --enable-* / --disable-* command-line switches. By default, all of the following features are activated, except for the frozen strings and the JIT: Feature CLI Option to Change Description RubyGems --disable-gems RubyGems is the package manager of Ruby, which is required to load 3rd party Ruby libraries¹. RUBYOPT --disable-rubyopt The RUBYOPT ENV…
What is your wild guess: How many different ways does Ruby provide for inserting a NULL byte into a double-quoted string? There are exactly 43 options¹! Here is the list, put together with some ideas from Episode 61: Meta Escape Control : Directly embedded NULL byte # => "\u0000" "\0" # => "\u0000" "\x00" # => "\u0000" "\x0" # => "\u0000" "\u0000" # => "\u0000" "\u{0000}" # => "\u0000" "\u{000}" #…
The introduction of pattern matching in Ruby 2.7 brought us a new style of multi-assigning local variables: The pattern assignment , or, how you could also call it, the assignment in-style . After you have deactivated the warnings for experimental features , try the following piece of code: [1, 2, 3, 4] in [first, second, *other] Think: Put [1, 2, 3, 4] into [first, second, *other] first # => 1…
Ruby's Warning module learned some new tricks in Ruby 2.7: Support for muting different categories of compile warnings has been introduced. This is a mechanism on top of the warning level reflected by the $VERBOSE variable . You can now silence deprecation warnings: These are aspects of the language which will be removed or changed in a future version of Ruby. One example is the infamous: warning:…
Ruby comes with good support for Unicode-related features. Read on if you want to learn more about important Unicode fundamentals and how to use them in Ruby… …or just watch my talk from RubyConf 2017: ⑩ Unicode Characters You Should Know About as a 👩💻 Ruby ♡ Unicode Characters in Unicode Codepoints & Encodings Grapheme Clusters Normalization Confusables Case-Mapping Case-Folding Regex Unicode…
Starting with Ruby 2.5¹ it is possible to customize the behavior of Kernel#warn through the Warning module . Here is how: def Warning.warn(w) # super calls the original behavior, which is printing to $stderr super "\e[31;1mRUBY WARNING: \e[22m#{w.sub(/warning: /, '')}\e[0m" end # # # # examples warn "test" # => RUBY WARNING: test { a: 1, a: 2 } # => RUBY WARNING: (irb):4: key :a is duplicated and…
Regexes, the go-to-mechanism for string matching, must not only be written, but also need to be applied. This episode acts as a reference with some style advice for working with regular expressions in Ruby. If you are looking for resources on writing the actual regexes, take a look at the link collection at the bottom . What do you Want to Achieve? 1 - Task: Check if Regex Matches 2 - Task: Find…
When you get farther upwards the steep hill that is Ruby mastery, you will come across some powerful, yet slightly evil methods: instance_eval and class_eval ¹. They allow you to execute code and define methods tied to a specific class, at the same time giving you access to outer scope variables through the Ruby block syntax. Their exact behavior varies, depending on the context they are used in.…
Ruby was created in 1993 and has come a long way. The preferred style of coding has changed quite a lot and solid best practice has emerged (though, as always, one size does not fit all ). At the same time, Ruby's tool support could be better , the language is still too complex. Maybe, the time has come to remove some features from Ruby. Which is always hard, because it will break existing code.¹…
Double-quoted strings can not only be used with interpolation, #{} , they also support various escape sequences, which are initiated with \ . Escape sequences allow you to embed raw byte and codepoint values. Furthermore, there are shortcuts for common formatting and control characters. Byte Sequences There are two basic ways in which you can specify raw bytes to embed: \x00 (hexadecimal) or \000…
Ruby has more than one way to access additional information about the most recent regex match, like captured groups. One way is using the special variables $` , $& , $' , $1 - $9 , $+ , and also in the MatchData object $~ . They become available after using a method that matched a regex, or when the method supports a block, they are already available in the block. However, there is also a special…
Ruby's big DATA constant does more than you might expect! Everything after the __END__ keyword (at the beginning of the line) is not interpreted as Ruby, but can be retrieved with the big¹ DATA constant.² This is an example big-data.rb script: p DATA.read __END__ big data Big DATA is a File object, which you can read . The example will output "big data" . An example of real-world usage is inline…
Ruby supports magic comments (interpreter instructions) at the top of the source file, mostly known for setting a source files' Encoding . This is the most common use case, but there is more you can do. Source File Encoding The default encoding of string literals in a Ruby file is UTF-8: p "".encoding # => #<Encoding:UTF-8> You can change it like this # encoding: big5 p "".encoding # =>…
%a %A %b %B %c %C %d %D %e %F %g %G %h %H %I %j %k %l %L %m %M %n %N %p %P %Q %r %R %s %S %t %T %u %U %v %V %w %W %x %X %y %Y %z %Z %+ %% - _ 0 ^ # : Date and time formatting is traditionally done with strftime . Not any different in Ruby, which includes a public domain based strftime implementation accessible via Time#strftime . Ruby would not be Ruby if it would not add some confusion: There is…
How come that Ruby has two ASCII encodings? Encoding.name_list.grep(/ASCII/) # => ["ASCII-8BIT", "US-ASCII"] Which one is the normal one you should use for ASCII? Aliases ASCII-8BIT US-ASCII BINARY ASCII ANSI_X3.4-1968 646 So, US-ASCII is aliased to ASCII , but then what is ASCII-8BIT for? Encodings' RDoc has some help: Encoding::ASCII_8BIT is a special encoding that is usually used for a byte…
Another of Ruby's idiosyncrasies is equalness. It's not too complicated, but naming is an issue here. Four Concepts of Equalness equal? Object Identity Comparison This one is easy. Two objects should be considered identical. Think: x.object_id == y.object_id == Equality Equality This is the usual method to care about. Two objects should be treated the same. If the class supports the <=> spaceship…
Similar to metaprogramming , Ruby's type conversion system has evolved over time. While the result functions, it is also a little inconsistent and suffers from poor naming. Let's put things in perspective: Implicit and Explicit Conversion Ruby objects are usually converted to other classes/types using to_* functions. For example, converting the String "42" to a Float is done with to_f : "42".to_f…
It is less common, but similar to methods, constants have a visibility attached to them. You have the choice between private and public , and you can also mark a constant deprecated ! Like with methods, the default visibility of a constant is public . Unlike methods, which have a lot of associated methods for metaprogramming , working with constants is easier: Module.methods.grep /const/ =>…
How many bytes (= ASCII characters) of Ruby code does it take to generate a SHA 256 hash sum of STDIN? 500 Bytes¹ q,z=[3,2].map{|t|i=l=1;(2..330).select{i-1<(l*=i)%i+=1}.map{|e|(e**t**-1*X=2**32).to_i&X-=1}} s=proc{|n,*m|a=0 m.map{|e|a^=n>>e|n<<32-e} a} i=$<.read.b<<128 (i+"\0"*(56.-(w=i.size)%64)+[~-w*8].pack('Q>')).gsub(/.{64}/m){w=$&.unpack'N*' y=z…
Some words should not be chosen as identifiers for variables, parameters and methods in Ruby, because they clash with core methods or keywords. As long as you do not define a method with the name of a keyword, Ruby will not complain. Still, it is often better to avoid naming things like existing methods. It carries potential for future bugs and also confuses newcomers. You might change the name in…
%a %A %b %B %c %d %e %E %f %g %G %i %o %p %s %u %x %X %% 0 $ # + - * space Ruby comes with a structured alternative to classic string interpolation: This episode will explore format strings , also known as the sprintf syntax. Recall the normal way of interpolating variables into a string: v = 42 "--> #{v} <--" # => "--> 42 <--" Format strings are different in that they use a string template and…
Ruby was initially designed to be a successor of the Perl programming language, which also means that it inherited a lot of Perl's expressiveness. To celebrate this, the TRIC¹ contest was invented: Write the most Transcendental, Imbroglio Ruby program! Illustrate some of the subtleties (and design issues) of Ruby! Show the robustness and portability of Ruby interpreters! Stabilize the spec of Ruby…
Ruby was initially designed to be a successor of the Perl programming language, which also means that it inherited a lot of Perl's expressiveness. To celebrate this, the TRIC¹ contest was invented: Write the most Transcendental, Imbroglio Ruby program! Illustrate some of the subtleties (and design issues) of Ruby! Show the robustness and portability of Ruby interpreters! Stabilize the spec of Ruby…
There is nothing easier than parsing the command-line arguments given to your Ruby program: It is an array found in the special variable $* : $ ruby -e 'p $*' -- some command line --arguments ["some", "command", "line", "--arguments"] That is Too Easy! The trouble begins with supporting common arguments conventions, like GNU's , and combining it with Ruby DSLs. This has lead to hundreds of Ruby…
Today, another snippet from the category don't try at home, might have unforeseeable consequences! Constant assignment¹ is not permanent in Ruby, so it is perfectly valid to do this: module A end class B def initialize p 42 end end A, B = B, A # warning: already initialized constant A # warning: previous definition of A was here # warning: already initialized constant B # warning: previous…
In case you have wondered, what this top-level constant TOPLEVEL_BINDING is all about: It is, as its name suggest, the Binding of your script's main scope: a = 42 p binding.local_variable_defined?(:a) # => true p TOPLEVEL_BINDING.local_variable_defined?(:a) # => true def example_method p binding.local_variable_defined?(:a) # => false p TOPLEVEL_BINDING.local_variable_defined?(:a) # => true end…
What happens when you invoke the Ruby interpreter, even before it executes your first line of code? Actually a lot! A few observations: Initial Load Path These are all locations you can Kernel#require from: $ ruby --disable-all -e 'puts $LOAD_PATH.map{ |path| "- #{path}" }' …/ruby-3.2.0/lib/ruby/site_ruby/3.2.0 …/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/x86_64-linux …/ruby-3.2.0/lib/ruby/site_ruby…
At some point when working with Ruby, you come across this mysterious RbConfig constant. A typical scenario is that you want to check which operating system your current program is executed on. You can do this with RbConfig::CONFIG['host_os'] or RbConfig::CONFIG['arch'] , see the RubyGems source for an advanced example! The Ruby Configuration is a collection of low-level information about your…
Ruby's Regexp engine has a powerful feature built in: It can match for Unicode character properties . But what exactly are properties you can match for? The Unicode consortium not only assigns all codepoints , it also publishes additional data about their assigned characters. When searching through a string, Ruby allows you to utilize some of this extra knowledge. Property Regexp Syntax Within a…
When exactly don't you have to :"escape" a Ruby symbol? Because this question is somehow related to the Ruby interpreter's internal usage of symbols, the rules are not the most obvious ones: : + Identifier¹, optionally appended by ! , ? , or = (→ methods) :@ + Identifier¹ (→ instance variables) :@@ + Identifier¹ (→ class variables) :$ + Identifier¹ (→ global variables) :$ + Single identifier¹…
A quick reminder that number literals in Ruby can be pretty fancy! Example Evaluates To Class Purpose 0x10 16 Integer Integers in hexadecimal (0-16) format 0o10 ¹ 8 Integer Integers in octal (0-8) format 0b10 2 Integer Integers in binary (0-1) format 1e1000 Float::INFINITY Float Floats in exponential notation 1i (0+1i) ² Complex Shorthand for creating complex numbers 3/6r (1/2) ² Rational…
In general, Ruby's reflection capabilities are pretty powerful, although not always logical . However, when reflecting on a method's (or proc's) usage, you are sometimes stuck with sad methods . Sad methods only work for code, that is written in Ruby itself. And Ruby itself (official MRI) is written in C, which limits such methods' usefulness quite a lot. This is an implementation specific…
Programming languages have been, and will always be categorized by their typing system . Naturally, large parts of the Ruby community (including myself) have some kind of aversion against static typing. But while Ruby goes down the route of being dynamically typed that does not mean that you are not allowed to use some form of types! 2020 update: Ruby 3.0 introduced types Put differently, nothing…
ERB stands for <%# Embedded Ruby %> and is the templating engine included in the Ruby Standard Library. While there are more recent gems that provide a better templating experience (see tilt for an abstraction, and erubis / erbse for an updated ERB), it is also convenient to have basic support directly in the standard library. However, it does not directly support rendering data from a Hash , but…
Is it a hash? Or is it a hash? hash = {"Idiosyncratic" => "Ruby"} hash["Idiosyncratic"] # => "Ruby" hash.compare_by_identity idiosyncratic_in_variable = "Idiosyncratic" hash[idiosyncratic_in_variable] # => nil hash["Idiosyncratic"] # => "Ruby" Hash#compare_by_identity changes the semantics of what is equal in a hash and what not. Only if exact the same object is passed in, the value will be…
RubyGems is bundled with core Ruby since 1.9, which was first released in 2007. As long as you do not run Ruby with the $ ruby --disable-gems flag, it is available to you without having to install anything. This also means that you can use some of RubyGems' support utilities for free! 1) Current Platform Info Gem::Platform.local.os # => "linux" Gem::Platform.local.cpu # => "x86_64" The value is…
Ruby's syntax is so expressive — it utilizes every printable, non-alphanumeric ASCII character as much as it cans. Sometimes, this can be confusing for beginners. The next sections show 4+ different meanings of every portrayed single character (not counting different meaning as custom string delimiter or meaning within a regex): Question Mark (4 Syntactical Meanings) The question mark is a sure…
If you don't like errors in your code, you will have to fix them. This handy list of Ruby's errors will hopefully help you do so! (And welcome back for the second season of Idiosyncratic Ruby !) Built-in Exceptions Exception Thrown by core Ruby when Remarks NoMemoryError The Ruby interpreter could not allocate the required memory "Idiosyncratic" * 100_000_000_000 ScriptError - Not thrown directly…
This is a summary of reasons why you should still use Ruby: It is a language with a terrific community (welcoming and always questioning itself) and ecosystem (a lot of problems already solved ), which is beautiful (focus on productivity), a little conservative (in the sense that it is easy to work with), and general purpose (a good choice in most cases). For a deeper understanding of Ruby's…
Ruby's regex engine defines a lot of shortcut character classes. Besides the common meta characters ( \w , etc.), there is also the POSIX style expressions and the unicode property syntax. This is an overview of all character classes: Meta Chars Char Negation ASCII Unicode . - ¹ Any ¹ Any \X - Any Grapheme clusters ( \P{M}\p{M}* ) \d \D [0-9] ² ASCII plus Decimal_Number ( Nd ) \h \H [0-9a-fA-F]…
If you take a closer look, you'll notice that Ruby's grammar has quite a few edge-case where its syntax is inconsistent or ambiguous: Binary Minus vs Minus taken as Unary Method Argument >> [1,3,4,5].size - 1 # => 3 >> [1,3,4,5].size -1 # wrong number of arguments(1 for 0) No Simple Rule, if a Symbol can be Displayed Without the Explicit :"" Syntax >> {:< => 0} # => {:<=>0} >> {:<=>0} # syntax…
There is an operator in Ruby, that does nothing: The unary plus operator . It is part of the language for keeping symmetry with the unary minus operator ! This is awesome, an operator for free! How can we utilize it? Update: In Ruby 2.3, the plus operator got its first purpose: Create an unfrozen copy of a string string = "frozen string".freeze string.object_id # => 19066860 string.frozen? # =>…
Code Golf is the art of writing the shortest program possible. The less bytes the better. And the competition is just ridiculously strong! Head over to Anarchy Golf if you want to see more! A good beginner's problem is printing out Pascal's Triangle : Spend a few days to get to 45 bytes. Spend a few months to get to 43 bytes! Attention: A new golf course has opened at code.golf . Why not give it a…
Ruby has three default encodings . One of them is the default source encoding , which can be set using a magic comment in the file's first line, or in the second line if the first line is taken by a shebang . Default source encoding (UTF-8): p "".encoding #=> #<Encoding:UTF-8> With encoding comment ( file_with_magic_comment.rb ): # coding: cp1252 p "".encoding #=> #<Encoding:Windows-1252> See…