For example, I want to make Object#rescue another name so I can use in my code like:
def dangerous
something_dangerous!
dont_worry # instead of rescue here
false
end
I tried
class ::Object
alias :dont_worry :rescue
end
But cannot find the rescue method on Object:
`<class:Object>': undefined method `rescue' for class `Object' (NameError)
Another example is I would like to have when in the language to replace:
if cond
# eval when cond is truthy
end
to
when cond
# eval when cond is truthy
end
Is it possible to give a Ruby keyword alias done in Ruby?
Or I need to hack on Ruby C source code?
Thanks!
This is not possible without some deep changes to the Ruby language itself. The things you describe are not methods but keywords of the language, i.e. the actual core of what is Ruby. As such, these things are not user-changeable at all.
If you still want to change the names of the keywords, you would at least have to adapt the language parser. If you don't change semantics at all, this might do it as is. But if you want to change what these keywords represent, things get messy really quick.
Also note that Ruby in itself is sometimes quite ambiguous (e.g. with regards to parenthesis, dots, spacing) and goes to great length to resolve this in a mostly consistent way. If you change keywords, you would have to ensure that things won't get any more ambiguous. This could e.g. happen with your change of if to when. when is used as a keywords is case statements already and would thus could be a source of ambiguity when used as an if.
Related
foo = ''
begin
foo = 'hi there'
rescue
end
puts foo
if I don't delcare foo = '' at the top before the begin it still works. But I see a lot of people do this. And it feels better. But is it best practice?
This is part paranoia, and part clarity. In this trivial example there's unlikely to be an issue, but what if you had this?
begin
foo = complicated_method_call(with: lots_of_arguments, and: another_call(with: args))
rescue
end
A whole bunch of stuff could go wrong there, and if that's the case you end up with foo being nil.
Now, using a blind rescue is generally bad form, you ideally want to scope down to just the ones your code might trigger.
Remember Ruby variables are defined at the method level, any instance of them in the method makes them defined, but they will have a default of nil which can be undesirable.
As you already know, for Ruby the variable exists whenever you assign a value/object to it, making it a weakly/loosely-typed (as opposed to "strongly typed") language. Why? The focus of the language's designer was simplicity and easy of use -- see the statement in the manual :). Remember also that there isn't a need to write 'return' inside methods to return values nor write parenthesis when calling functions if there isn't confusion. Why? Simplicity, ease of use. Hard to tell if these things are better or not as a general answer. Do we have to rely always upon the compiler checks? Are we pro? Really? But generally speaking, we can hardly find ruby programmers declaring variables always unless instance/global ones, and at the end we'll getting ourselves rushing in the mainstream. Yay! General answer to determine the type of a variable: https://en.wikipedia.org/wiki/Duck_test Have fun!
I'd like to avoid my method:
def page_cover
return cover_title unless cover_title.match(/#{ capitalised_acronyms }/).present?
cover_title.gsub(/#{ capitalised_acronyms }/, $&.upcase)
end
because it looks Perly, and I heard of a news that it might be deprecated in the future. From the book:
Prefer String#match to String#=~. The former returns all the match information in a MatchData object instead of several special global variables.
Use the longer, more descriptive global variable aliases as opposed to their short cryptic names (e.g., $LOAD_PATH instead of $:). Most of the longer names are only available after loading the English library.
Avoid methods that implicitly read from, or write to, the $_ global variable (e.g., Kernel#print, Regexp#~, etc.).
I think I violated #3 in:
$&.upcase
Any suggestions are welcome.
While I neither agree nor disagree with a general principle of avoiding "Perlisms," I do agree that avoiding $+punctuation variables is a good way to improve the readability of your code.
There is no in-place substitute for $& (which holds the last regex match). You can, however, access the matched string using the MatchData object returned by String#match.
def page_cover
if matchdata = cover_title.match(/#{capitalised_acronyms}/)
cover_title.gsub(/#{capitalised_acronyms}/, matchdata[0].upcase)
else
cover_title
end
end
NOTE:
As written, this method (like your example method) will replace all matched lowercase acronyms with an uppercase version of only the first acronym matched: i.e. "I love the nfl and nba" becomes "I love the NFL and NFL". If that is unintentional, there is a much simpler way to write this method:
def page_cover
cover_title.gsub(/#{capitalised_acronyms}/, &:upcase)
end
This uses the & operator (which is completely unrelated to $&) to convert the symbol :upcase into the block {|x| x.upcase } behind the scenes.
I'm just getting into Ruby and come from the Java and C/C++ environment.
While coding a first little project in Ruby, I somehow got used to let all local variables start with an underscore. I guess my main motivation for this was a better readability and distinction from method calls.
As in principle there are only three types of variables ($global, #instance and local), the vast majority of variables start with an underscore. I'm not really sure, whether this is good or bad. Besides, in a lot other languages, the underscore would be substituted to some other character.
Is there somehow a best practice concerning variable naming beside the usual CamelCase and/or underscore separated? What are the habits of the professional "rubyists"? Have I overlooked some general Ruby conventions, when I chose the leading underscore?
edit
Thanks to all answers and suggestions. It helped me a lot.
Short Summary of Answers and Comments below
(for the short-on-time visitor)
Leading underscores go with:
method arguments: def my_method(_my_arg)
block arguments: e.g. my_array.each { |_x| puts _x}
All other local variables without leading underscores, as programmers coming from e.g. JavaScript might get confused about intended behaviour of the variables.
For visual separation between variable names and method calls, forcing oneself to use "(" brackets ")" with all method calls might increase readability significantly.
Existing answers to this question are now a few years old, and conventions have changed. You should only ever use a leading underscore (_some_param), or a standalone underscore (_), to indicate that you don't care about the value. The rubocop style linting tool will carp about a "useless assignment" if you assign a variable but don't use it, but it will ignore variables with a leading underscore. This allows you to expressly indicate that you don't care about the value and don't intend to use it.
Here's a somewhat-contrived example use-case in an RSpec context:
describe 'login' do
let(:user) { FactoryGirl.create(:user, login: 'bob') }
it 'must be unique' do
_user1 = user
user2 = User.new login: 'bob'
expect(user2.valid?).to be_false
end
end
Here we're indicating that our user helper has a side-effect and returns something, but we don't care about it. You could also just skip the assignment entirely, but seeing a bare user on a line by itself looks odd and doesn't reveal the intention as clearly:
describe 'login' do
let(:user) { FactoryGirl.create(:user, login: 'bob') }
it 'must be unique' do
user
user2 = User.new login: 'bob'
expect(user2.valid?).to be_false
end
end
Other scenarios include ignoring values in iterators, or overriding a method where you want to keep the original method signature but don't care about some of the values:
def greet(name, _title)
puts "Hi, #{name}!"
end
In my experience, underscore-prefixed variables in Ruby are much like underscore-prefixed variables in JavaScript: a "don't touch" flag. More specifically, they are used when the implementer is doing something that really is not supposed to be understood as a part of the object, or shouldn't be thought of as the conceptual interface of the object.
This is more clear in the JavaScript world, where somebody is emulating "private" by prefixing a variable with an underscore. They are encoding that there's part of the object that's under the hood and can be ignored when looking at the object from the outside.
In Ruby, I've only really seen this with things like a cache or a singleton instance - the kind of thing that should be invisible to consumers of your object. Non-underscored variables are things that people using your object might be interested to know are there.
In any case, they seem fairly rare, and I would avoid them unless you want to send a signal to the next guy that's coming along that there's some extra magic or voodoo happening.
As far as making a distinction for method calls, if you're worried that there can be confusion between a method and a local variable, I would call the method on self to clarify. For instance:
def foo
...
end
def some_method
foo # method
bar # variable
end
If this seems unclear for whatever reason, you can clarify with
def some_method
self.foo
bar
end
Nothing wrong with your idea. But if I was having trouble distinguishing local vars from method calls, I would probably just force myself to always use ()'s on methods. (My team at work has discussed making this part of our coding standards).
a = thing # var
b = thing() # method
The possible advantage to this is readability to others. Someone may wonder at your leading _'s, but using ()'s on all method calls should be clear to everyone.
Seeing as how instance variables have the # sign in front of them, and global variables have the $ sign in front of them already in ruby, it is probably unnecessary to put an underscore character in front of the variable names. That being said, I don't think it is a bad practice necessarily. If it helps you to read or write your code in Ruby, then you should use it.
I have sometimes seen Ruby code where an argument for an instance method on a class has an underscore in front of it. Such as:
def my_method(_argument1)
# do something
end
And I think that when you are dealing with a class that may have it's own attributes, like a model file in rails, for instance, this can be helpful so that you know you are dealing with a variable that has been passed into the method as opposed to one of the attributes that belongs to the class/model.
I am trying to create instances of objects of various types by iterating and checking for validity. I need an array of types so I can do something like this:
def tryClasses(in)
types = [Foo::A, Foo::B, Foo::C]
types.each do |type|
a = type.new(in)
return a != null
end
end
How do I create and array of class types?
Doing it this way I am getting a NoMethodError (undefined method 'A' for Foo)
Apart from the obvious syntactic errors (e.g. in is a reseved word, and null is spelled nil in Ruby), the code you showed should work just fine as it is, and indeed it does when I copy&paste it into my Ruby installation. This assumes, of course, that the classes Foo::A, Foo::B and Foo::C actually exist. If they don't, then the code obviously cannot possibly work.
It is, however, completely un-Rubyish and violates just about every coding convention in the book:
indentation is 2 spaces
method names are snake_case, not camelCase
explicitly checking for equality to nil is a no-no, simply calling #nil? is much preferred
try_classes isn't exactly an intention-revealing method name
and WTF does in mean?
Rubyists much prefer higher-order methods over explicit looping
Here's a more Rubyish version of the code you wrote:
def can_create_object?(*args)
[Foo::A, Foo::B, Foo::C].none? do |klass|
klass.new(*args).nil?
end
end
However, note that I am pretty convinced that the whole idea is fundamentally flawed.
"Is 'eval' supposed to be nasty?" inspired this one:
Mostly everybody agrees that eval is bad, and in most cases there is more elegant/safer replacement.
So I wanted to ask: if eval is misused that often, is it really needed as a language feature? Is it doing more evil than good?
Personally, the only place I find it useful is to interpolate strings provided in config file.
Edit: The intention of this question is to get as many real-life cases as possible when eval is the only or the best solution. So please, don't go into "should a language limit a programmer's creativity" direction.
Edit2: And when I say eval, of course I refer to evaling string, not passing ruby block to instance_eval or class_eval.
The only case I know of (other than "I have this string and I want to execute it") is dynamically dealing with local and global variables. Ruby has methods to get the names of local and global variables, but it lacks methods to get or set their values based on these names. The only way to do AFAIK is with eval.
Any other use is almost certainly wrong. I'm no guru and can't state categorically that there are no others, but every other use case I've ever seen where somebody said "You need eval for this," I've found a solution that didn't.
Note that I'm talking about string eval here, by the way. Ruby also has instance_eval, which can take either a string or a block to execute in the context of the receiver. The block form of this method is fast, safe and very useful.
When is it justified? I'd say when there's no reasonable alternative. I was able to think of one use where I can't think of an alternative: irb, which, if you dig deep enough (to workspace.rb, around line 80 in my copy if you're interested) uses eval to execute your input:
def evaluate(context, statements, file = __FILE__, line = __LINE__)
eval(statements, #binding, file, line)
end
That seems pretty reasonable to me - a situation where you specifically don't know what code you're going to have to execute until the very moment that you're asked to do so. Something dynamic and interactive seems to fit the bill.
The reason eval is there is because when you need it, when you really need it, there are no substitutes. There's only so much you can do with creative method dispatching, after all, and at some point you need to execute arbitrary code.
Just because a language has a feature that might be dangerous doesn't mean it's inherently a bad thing. When a language presumes to know more than its user, that's when there's trouble.
I'd argue that when you find a programming language devoid of danger, you've found one that's not very useful.
When is eval justified? In pragmatic terms, when you say it is. If it's your program and you're the programmer, you set the parameters.
There is one very important use-case for eval() which cannot (AFAIK) be achieved using anything else, and that is to find the corresponding object reference for a binding.
Say you have been passed a block but (for some reason) you need access to object context of the binding, you would do the following:
obj = eval('self', block.binding)
It is also useful to define the following:
class Proc
def __context__
eval('self', self.binding)
end
end
IMO mostly for Domain Specific Languages.
"Evaluation Options in Ruby" is an article by Jay Fields about it on InfoQ.
eval is a tool, it is neither inherently good nor evil. It is justified whenever you are certain it is the right tool for what you are trying to accomplish.
A tool like eval is about evaluating code at runtime vs. "compile" time. Do you know what the code is when you launch Ruby? Then you probably don't need eval. Is your code generating code during runtime? then you probably need to eval it.
For example, the methods/functions needed in a recursive decent parser depend on the language being parsed. If your application builds such a parser on-the-fly, then it might make sense to use eval. You could write a generalized parser, but it might not be as elegant a solution.
"Programatically filling in a letrec in Scheme. Macros or eval?" is a question I posted about eval in Scheme, where its use is mostly unavoidable.
In general eval is a useful language feature when you want to run arbitrary code. This should be a rare thing but maybe you are making your own REPL or you want to expose the ruby run-time to the end user for some reason. It could happen and that is why the feature exists. If you are using it to work around some part of the language (e.g. global variables) then either the language is flawed or your understanding of the language is flawed. The solution is typically not to use eval but to either better understand the language or pick a different language.
It's worth noting that in ruby particulary instance_eval and class_eval have other uses.
You very likely use eval on a regular basis without even realizing it; it's how rubygems loads the contents of a Gemspec. Via rubygems/lib/specification.rb:
# Note: I've removed some lines from that listing to illustrate the core concept
def self.load(file)
code = File.read(file)
begin
_spec = eval code, binding, file # <-------- EVAL HAPPENS HERE
if Gem::Specification === _spec
return _spec
end
warn "[#{file}] isn't a Gem::Specification (#{_spec.class} instead)."
rescue SignalException, SystemExit
raise
rescue SyntaxError, Exception => e
warn "Invalid gemspec in [#{file}]: #{e}"
end
nil
end
Typically, a gem specification would look like this:
Gem::Specification.new do |s|
s.name = 'example'
s.version = '0.1.0'
s.licenses = ['MIT']
s.summary = "This is an example!"
s.description = "Much longer explanation of the example!"
s.authors = ["Ruby Coder"]
s.email = 'rubycoder#example.com'
s.files = ["lib/example.rb"]
s.homepage = 'https://rubygems.org/gems/example'
s.metadata = { "source_code_uri" => "https://github.com/example/example" }
end
Note that the gemspec file simply creates a new object but does not assign it nor send it anywhere.
Trying to load or require this file (or even executing it with Ruby) will not return the Gem::Specification value. eval is the only way to extract the value defined by an external ruby file.
One use of eval is compiling another language to ruby:
ruby_code = "(def foo (f a b) (mapv f (cons a b)))".compile_to_ruby
# "foo_proc = ->(f a b) { mapv_proc.call(f, (cons_proc.call(a, b)) }"
eval ruby_code
I use a 3D modeling software that implemented Ruby for writing custom text macros. In that software we are given access to model data in the form of name:value pairs accessed using the following format:
owner.name
#=> value
So for a 36 inch tall cabinet, I could access the height and convert its value to feet like so:
owner.height.to_f / 12
The main problem is that objects in that software have no unique identifiers aside from something called their schedule_number. If I want to name a variable using the schedule_number in the variable name so that I can call and use that value elsewhere, the only possible way I know to do that is by using eval:
eval "#{owner.schedule_number} = owner.height"