Make ruby raise an error on duplicate key definition in hash - ruby

Is it possible to make ruby raise an error on a duplicate key definition in a hash. E.g.
{a: 1, b: 2, a: 3}
Currently this just gives a warning like so:
warning: key :a is duplicated and overwritten on line 1
I would rather get an exception
BTW: I'm on ruby 2.7

This is a parse timew warning.
I don't think you can generate an exception:
https://github.com/ruby/ruby/blob/master/parse.y#L12201

Related

The called method `...' is defined here

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.

What dos this Ruby statement mean?

The code below comes from the documentation for the Ruby Gem rroc. I desperately need to calculate the AUC for my AI project. However I have virtually no knowledge of Ruby file I/O, not having had occasion to learn. The documentation says rroc expects an n by 2 array but the first line of code below suggest that the data is in a csv file and it will be formatted into my_data for roc to calculate the auc.
I have tried every conceivable combination of csv data and arrays as both files for the first line to read or direct input into the line calculating auc. At best the code works, without error but gives a useless output of 0. My hope is that if I had a fuller understand of what that line does, I could either fix the problem or give up on the gem since a previous version of this gem was shown to be obsolete and this one's 8 years old. I took the data from the article referenced by the gem author and am pretty sure it's not the problem, but then,...
So, to refine the question: from that statement, can we tell what kind of data should be in 'some_data.cvs'? And what will be done to it to make my_data?
require 'rroc'
my_data = open('some_data.csv').readlines.collect { |l| l.strip.split(",").map(&:to_f) }
auc = ROC.auc(my_data)
puts auc
Below I've copied the output for two runs, the first with array data read in, the second with csv values (each in separate files). I added a line to read out the input file just to be sure.
RoyiMac:ruby $ ruby PDaucT.rb
[[90, 1], [80, 1], [70,-1], [60,1], [55,1], [54,1], [53,-1], [52,-1], [51,1], [50,-1], [40,1], [39,-1], [38,1], [37,-1], [36,-1], [35,-1], [34,1], [33,-1], [30,1], [10,-1]]
0.0
RoyiMac:ruby $ ruby PDaucT.rb
90,1,80,1,70,-1,60,1,55,1,54,1,53,-1,52,-1,51,1,50,-1,40,1,39,-1,38,1,37,-1,36,-1,35,-1,34,1,33,-1,30,1,10,-1
0.0
The explanation of the code:
open('some_data.csv') # open the some_data.csv file
.readlines # returns an array with each element being a line
.collect { |l| # for each line do the following tranformation
l.strip # remove proceeding and trailing whitespace characters
.split(',') # split the line based on the "," character (returning an array)
.map(&:to_f) # call .to_f on each element in the array, converting them to a float value
}
map/collect are aliases of each other.
However, like tadman already said in the comments you're better of using the csv standard library. The same can be achieved with:
require 'csv'
my_data = CSV.read('some_data.csv', converters: :float)
# should output
#=> [[90, 1], [80, 1], [70,-1], [60,1], [55,1], [54,1], [53,-1], [52,-1], [51,1], [50,-1], [40,1], [39,-1], [38,1], [37,-1], [36,-1], [35,-1], [34,1], [33,-1], [30,1], [10,-1]]

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.

Format byebug's output

I've recently done a fresh install of my system and I'm seeing some odd behaviour from byebug. For instance, arrays are listed on element on line instead of having everything on the same line. Here is an example:
(byebug) [1,2,3]
1
2
3
Normally, I would expect:
(byebug) [1,2,3]
[1, 2, 3]
How can I get byebug to display arrays "normally"?
The issue got fixed with the latest versions of byebug: gem 'byebug', '~> 8.0'. Arrays are properly printed now.

How can I parse multiple lines using ruby_parser?

I'm trying to use ruby_parser to parse some multi-lined Ruby code in a file.
Let's say I want to parse the following code:
def foo
2 + 2
end
When I do the following I get an error:
RubyParser.new.parse("def foo")
#=> Racc::ParseError: (string):1 :: parse error on value "$end" ($end)
because the line does not contain an end.
I'm passing lines in one at a time using File.readlines(file).
Ideally I would specify the filename to RubyParser, but I can't seem to figure that out, and there's very little documentation.
You cannot pass line by line. Pass the whole code at once.
RubyParser.new("def foo\n 2 + 2\nend")
or
RubyParser.new(File.read(file))

Resources