The called method `...' is defined here - ruby

Ruby 2.7 was just released and it comes with these new warnings for "Separation of positional and keyword arguments" (see their Release Post).
I was playing around with it and discovered that there's another warning, which I don't understand.
Example:
def multiply(x:, y:)
x * y
end
args = { x: 2, y: 3 }
multiply(args)
# ./warning.rb:7: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
# ./warning.rb:1: warning: The called method `multiply' is defined here
I think the first warning about the deprecation is clear, but the second warning The called method `multiply' is defined here is confusing to me.
What does the second warning mean? Is it related to the first warning?
Both warnings disappear when adding ** to the call (multiply(**args)).

What does the second warning mean? Is it related to the first warning?
There is a single warning with a text split into two lines. It literally says: args should be converted to **args, here is the call that produced this warning, here is its definition for your convenience.

Related

Can this Ruby error be caught with NeoVim/ALE/RuboCop/Syntastic?

I'm new to Ruby and doing some experimenting with NeoVim/ALE which I'm also new to. I'm coming from Perl using the syntastic plugin and I'm trying to figure out how to best set up NeoVim/ALE/RuboCop. I've never used a delinter before.
My confusion stems from this bit of code:
#!/usr/bin/env ruby
r = Array() # Improper array initialization, should be Array.new()
puts r
When run, I get:
Traceback (most recent call last):
1: from /Users/me/ruby/workshop/dink.rb:3:in `<main>'
/Users/me/ruby/workshop/dink.rb:3:in `Array': wrong number of arguments (given
0, expected 1) (ArgumentError)
RuboCop didn't catch this error. I turned syntastic on and it didn't catch the error either. I assume because it's a runtime error and not a compile time error like I thought it would be. Running ruby -c on the script yields no errors either. But perhaps I'm wrong and aren't using the syntax checking tools properly. Can someone please confirm that this is indeed a runtime error and that it's impossible to catch before executing the script?
I have a second question as well: Do I need syntastic with Ruby? Does it do anything more that RuboCop doesn't?
Thanks.
Both tools are correct, because there is the Array() method defined in Kernel.
That means this is not a syntax but a runtime error because that method expects at least one argument.
From the docs:
Array(arg) → array
Returns arg as an Array.
First tries to call to_ary on arg, then to_a. If arg does not respond to to_ary or to_a, returns an Array of length 1 containing arg.

Ruby Mocha expect the first argument to be a symbol

I'm trying to assert a method call happens where the first argument is a symbol like so:
Foo.bar(:some_key, {})
I don't really care what the second argument is at this stage.
I've tried:
Foo.expects(:bar).with(includes(:some_key))
and other variations found in the documentation here. The test passes when I expect the method call with any arguments.
Any ideas?
Have you tried this :
Foo.expects(:bar).with(:some_key, anything)
If you need to be more specific you can also use a block :
Foo.expects(:bar).with do |first_arg, second_arg|
first_arg == :some_key
end

Compilation error in declaration of method which accepts input as block with variable number of arguments

When I am declaring a method like this:
- (void)doAnythingWithThisBlock:(void(^)(NSString *, ... NS_REQUIRES_NIL_TERMINATION))AnythingBlock;
It is giving compilation error:
Expected ')'
but when I am declaring it like this:
- (void)doAnythingWithThisBlock:(void(^)(NSString *, ...))AnythingBlock;
It compiles fine and works as expected
Cannot we use - NS_REQUIRES_NIL_TERMINATION while declaring a method which accepts input as block with variable number of arguments?
I am trying it in XCode 4.2
I guess NS_REQUIRES_NIL_TERMINATION is only for method declarations 1
However you can try to typedef your block to certain type and pass it as an argument: may be clang will eat it then?

Compiling Ruby Inline C code - resolving errors

I am trying to get this Ruby inline C code http://pastie.org/2825882 to work. The code works in vanilla C, but here I get errors and warnings. What causes this error?
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
Also, why do I get the following error?
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
Inspecting the resulting C code ( http://pastie.org/2826036) I fail to see anything wrong with the arguments. But I do also get the following warnings:
./backtrack_inline.rb:73: warning: passing argument 1 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 2 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 3 of 'backtrack' makes integer from pointer without a cast
Starting with this:
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
If you look at your generated code, the backtrack function is defined on line 29:
static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) { ... }
It has seven arguments, the original six, plus VALUE self as it has been converted into a method on the Scan class.
The call to this function, on line 67 looks like this:
end = backtrack(ss, s, p, mm, ins, del);
It has only six arguments. RubyInline doesn't convert this to a call to a method on the object, it simply copies it verbatim. This is also where the warnings about makes integer from pointer without a cast come from: the function definition has been converted to take VALUEs, but you're calling with the original types.
The error message says that the error is from line 73 in backtrack_inline.rb because of the directive on line 54 of the generated code:
# line 61 "./backtrack_inline.rb"
which basically tells the compiler to "reset" its line and file values for errors, and treat the next line (55) as being line 61 in the file ./backtrack_inline.rb. The actual line is 67, 12 ahead of 55, but the compiler reports it as being 73, 12 ahead of 61 (the value it was reset to) and from a differnt file. This technique doesn't really work in this case as it doesn't take into account the extra lines added by RubyInline. The actual line in the source is 69.
A simple fix for this is to change the definition of the backtrack function to be just a C function rather than add it as a method on the object. Change builder.c to builder.prefix (on line 38 of your Ruby file). This won't work if you want to have backtrack available as a method on the object in Ruby. If that's the case you might need create another function to be the method, which then wraps the "real" backtrack function.
Next, looking at
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
This actually refers to line 61 of the generated code, which looks like:
char* s = StringValuePtr(rb_iv_get(self, "#seq"));
StringValuePtr is a macro which is defined as:
#define StringValue(v) rb_string_value(&(v))
This is where the & in lvalue required as unary '&' operand comes from. You need to add a local variable to be the lvalue:
VALUE seq = rb_iv_get(self, "#seq");
char* s = StringValuePtr(seq);
In my case (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) these two changes made the script run without errors, but gave the warning:
backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value
This actually refers to line 46 of the ruby file:
return (s - ss) - 1;
s and ss are char *, i.e. 64 bit pointers (on this machine), and the return type of the function is int - 32 bits. Adding an explicit cast fixed this:
return (int)((s - ss) - 1);
It now runs cleanly:
ruby-inline $ ruby backtrack_inline.rb
14
ruby-inline $
(I hope 14 is the correct answer!)
Here's a version of the script with these changes.
OK, the question was also answered at Ruby Forum:
http://www.ruby-forum.com/topic/2959614
Ok... thought a bit more about this.
you are calling a variable end. While this isn't a reserved word in C - and ruby shouldn't be looking at it... perhaps ruby is getting confused?
I'd suggest you have a go at renaming it just in case. Worthwhile trying even just to rule it out.

trying to find a file/line for: .(eval):289: warning: don't put space before argument parentheses

So, I get this warning when I'm running my tests in ruby/RoR
.(eval):289: warning: don't put space before argument parentheses
I've checked every where (but obvoiusly not) and I can't find the origin of this error.
The above error just pops up inbetween the unit tests ...
Can someone clue me in onto how to find the location of this error?
The file and line number are contained in the backtrace. However, in your case, the warning is inside a string being evaled at runtime. Which means there is no file. (Actually, the eval method does take optional arguments for the file name and line number that should be displayed in a backtrace, but in this case whoever wrote the code in question unfortunately forgot to pass those arguments.)
I fear that you have no other choice than to manually examine every single call to eval in your entire codebase, and that includes Rails, your testing framework, your entire application, your tests, your plugins, your helpers, the ruby standard library, ...
Of course, you should be aware that the problem might not be obvious as in
eval 'foo (bar, baz)'
It could also be something like
def foo(*args)
puts args.join
end
bar = 'Hello'
baz = 'World'
foostr = 'foo' # in one file
barstr = 'bar' # in another file in a different directory
bazstr = 'baz' # in another file in a different directory
argstr = "(#{barstr}, #{bazstr})" # in yet another file
$, = ' ' # in some third-party plugin
str = [foostr, argstr].join # in a fourth file
eval str # somewhere else entirely
eval str, binding, __FILE__, __LINE__ # this is how it *should* be done
Note the difference between the two warning messages: the first one reads exactly like the one you posted, but the second one has the filename instead of (eval) and the line number inside the file instead of the line number inside the eval string.
By the way: the line number 289 in the warning message is the line number inside the evald string! In other words: somewhere in your application there is a string being evald, which is at least 289 lines long! (Actually, it is more likely that this done not in your application but rather in Rails. The Rails router used to be a particularly bad offender, I don't know if this is still the case.)
It sounds to me that there is a rule which forbids a space between a function name and the parentheses enclosing the arguments of the function.
In many languages this would be considered a permissible stylistic variation.
Is the eval mentioned in the warning message, the 'function' being complained about?
Does the number 289 mean anything as a line number?
Could you search your source files for a parenthesis preceded by a space?
Incidentally, the message says warning. What happens if you ignore it?
If it's happening in between the unit tests it might be in a setup or teardown method. Try searching for eval or try reducing the code you are running until the error goes away. Then you'll know where to look (the code you just removed).

Resources