weird Socket.getaddrinfo result for localhost - ruby

I have a problem with a ruby application connecting to a data base. After some hours of poking around, my problem boiled down to Socket.getaddrinfo 'localhost', nil returns unexpected addresses:
ruby -e "require \"socket\"; puts Socket.getaddrinfo('localhost', nil).inspect"
[["AF_INET", nil, "10.10.1.37", "10.10.1.37", 2, 2, 17],
["AF_INET", nil, "10.10.1.37", "10.10.1.37", 2, 1, 6],
["AF_INET", nil, "fe80:0:0:0:5e96:9dff:fe94:fce3%5", "fe80:0:0:0:5e96:9dff:fe94:fce3%5", 2, 2, 17],
["AF_INET", nil, "fe80:0:0:0:5e96:9dff:fe94:fce3%5", "fe80:0:0:0:5e96:9dff:fe94:fce3%5", 2, 1, 6]]
10.10.1.37 is the address of the network adapter.
I'm using rvm and this strange behavior just happens, when I use a jruby. If I use a regular ruby version, the result is what I expect ('127.0.0.1' for example).
According to wikipedia, localhost should refer to the local loop back interface. What could cause this behavior, it this a Java thingy?
JRuby versions I've tried are: 1.7.2, 1.7.4 and 1.7.9
The more expected output (when using a regular ruby-1.9.3) is:
ruby -e "require \"socket\"; puts Socket.getaddrinfo('localhost', nil).inspect"
[["AF_INET6", 0, "::1", "::1", 30, 2, 17],
["AF_INET6", 0, "::1", "::1", 30, 1, 6],
["AF_INET", 0, "127.0.0.1", "127.0.0.1", 2, 2, 17],
["AF_INET", 0, "127.0.0.1", "127.0.0.1", 2, 1, 6],
["AF_INET6", 0, "fe80::1%lo0", "fe80::1%lo0", 30, 2, 17],
["AF_INET6", 0, "fe80::1%lo0", "fe80::1%lo0", 30, 1, 6]]

This looks like a bug in jruby. They try to maintain compatibility with MRI as much as possible, and when that doesn't happen, it is considered a bug unless otherwise noted. You should open an issue with them over at Github
EDIT
I was not able to reproduce this on Linux running jruby 1.7.10 or on OS X using 1.7.8, but it still seems like a bug to me.

Related

Passing arguments to Ruby methods

It seems that arguments can be passed to certain Ruby methods by appending the arguments after the method, and separating the two by a space. I'm trying to understand the mechanism that makes this happen. This is how arguments are passed to scripts in the command line. Why does the following statement work in Ruby?
item = 'orange'
fruits = ['orange', 'grapefruit', 'apple']
x = fruits.include? item
puts x
And why does the following statement not work?
item = 'orange'
fruits = ['orange', 'grapefruit', 'apple']
x = fruits.include? item ? 'You picked a fruit' : 'You did not pick a fruit'
puts x
Examine the AST with Ripper
In Ruby, parentheses are largely optional except when needed to avoid ambiguity, such as when passing arguments to methods that take a block. Under the hood, mainline Ruby has a lot of moving parts that tokenize and parse the code you write. One of the most useful is the Ripper module (documented here) which enables you to see the abstract syntax tree that Ruby produces from your code.
Here are two versions of your code as Ruby sees them. You can see from the S-expressions that the failing version is different from the non-failing version. In irb:
Ripper.sexp %q{x = fruits.include?(item) ? 'You picked a fruit' : 'You did not pick a fru
it'}
#=>
[:program,
[[:assign,
[:var_field, [:#ident, "x", [1, 0]]],
[:ifop,
[:method_add_arg,
[:call,
[:vcall, [:#ident, "fruits", [1, 4]]],
[:#period, ".", [1, 10]],
[:#ident, "include?", [1, 11]]],
[:arg_paren, [:args_add_block, [[:vcall, [:#ident, "item", [1, 20]]]], false]]],
[:string_literal, [:string_content, [:#tstring_content, "You picked a fruit", [1, 29]]]],
[:string_literal, [:string_content, [:#tstring_content, "You did not pick a fruit", [1, 52]]]]]]]]
Ripper.sexp %q{x = fruits.include? item ? 'You picked a fruit' : 'You did not pick a frui
t'}
#=>
[:program,
[[:assign,
[:var_field, [:#ident, "x", [1, 0]]],
[:command_call,
[:vcall, [:#ident, "fruits", [1, 4]]],
[:#period, ".", [1, 10]],
[:#ident, "include?", [1, 11]],
[:args_add_block,
[[:ifop,
[:vcall, [:#ident, "item", [1, 20]]],
[:string_literal, [:string_content, [:#tstring_content, "You picked a fruit", [1, 28]]]],
[:string_literal, [:string_content, [:#tstring_content, "You did not pick a fruit", [1, 51]]]]]],
false]]]]]
Since Ruby treats almost everything as an expression that returns a value, the order of operations can affect how the parser forms expressions. The ternary operator must ultimately evaluate as three expressions, and if you use what the parser considers ambiguous syntax it will cause problems.
See Also
parse.y

What is `&method` called? How to pass multiple arguments in it? [duplicate]

You're probably familiar with the following Ruby shorthand (a is an array):
a.map(&:method)
For example, try the following in irb:
>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]
The syntax a.map(&:class) is a shorthand for a.map {|x| x.class}.
Read more about this syntax in "What does map(&:name) mean in Ruby?".
Through the syntax &:class, you're making a method call class for each array element.
My question is: can you supply arguments to the method call? And if so, how?
For example, how do you convert the following syntax
a = [1,3,5,7,9]
a.map {|x| x + 2}
to the &: syntax?
I'm not suggesting that the &: syntax is better.
I'm merely interested in the mechanics of using the &: syntax with arguments.
I assume you know that + is a method on Integer class. You can try the following in irb:
>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2
You can create a simple patch on Symbol like this:
class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
Which will enable you to do not only this:
a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]
But also a lot of other cool stuff, like passing multiple parameters:
arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]
And even work with inject, which passes two arguments to the block:
%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"
Or something super cool as passing [shorthand] blocks to the shorthand block:
[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
Here is a conversation I had with #ArupRakshit explaining it further:
Can you supply arguments to the map(&:method) syntax in Ruby?
As #amcaplan suggested in the comment below, you could create a shorter syntax, if you rename the with method to call. In this case, ruby has a built in shortcut for this special method .().
So you could use the above like this:
class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
Here is a version using Refinements (which is less hacky than globally monkey patching Symbol):
module AmpWithArguments
refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
end
using AmpWithArguments
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
For your example can be done a.map(&2.method(:+)).
Arup-iMac:$ pry
[1] pry(main)> a = [1,3,5,7,9]
=> [1, 3, 5, 7, 9]
[2] pry(main)> a.map(&2.method(:+))
=> [3, 5, 7, 9, 11]
[3] pry(main)>
Here is how it works :-
[3] pry(main)> 2.method(:+)
=> #<Method: Fixnum#+>
[4] pry(main)> 2.method(:+).to_proc
=> #<Proc:0x000001030cb990 (lambda)>
[5] pry(main)> 2.method(:+).to_proc.call(1)
=> 3
2.method(:+) gives a Method object. Then &, on 2.method(:+), actually a call #to_proc method, which is making it a Proc object. Then follow What do you call the &: operator in Ruby?.
As the post you linked to confirms, a.map(&:class) is not a shorthand for a.map {|x| x.class} but for a.map(&:class.to_proc).
This means that to_proc is called on whatever follows the & operator.
So you could give it directly a Proc instead:
a.map(&(Proc.new {|x| x+2}))
I know that most probably this defeats the purpose of your question but I can't see any other way around it - it's not that you specify which method to be called, you just pass it something that responds to to_proc.
There is another native option for enumerables which is pretty only for two arguments in my opinion. the class Enumerable has the method with_object which then returns another Enumerable.
So you can call the & operator for a method with each item and the object as arguments.
Example:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+) # => [3, 5, 7, 9, 11]
In the case you want more arguments you should repeat the proccess but it's ugly in my opinion:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+).to_enum.with_object(5).map(&:+) # => [8, 10, 12, 14, 16]
Short answer: No.
Following #rkon's answer, you could also do this:
a = [1,3,5,7,9]
a.map &->(_) { _ + 2 } # => [3, 5, 7, 9, 11]
if all your method needs as argument is an element from the array, this is probably the simplest way to do it:
def double(x)
x * 2
end
[1, 2, 3].map(&method(:double))
=> [2, 4, 6]
Instead of patching core classes yourself, as in the accepted answer, it's shorter and cleaner to use the functionality of the Facets gem:
require 'facets'
a = [1,3,5,7,9]
a.map &:+.(2)
I'm surprised no one mentioned using curry yet, which has been in Ruby since Ruby 2.2.9. Here's how it can be done in the way OP wants using the standard Ruby library:
[1,3,5,7,9].map(&:+.to_proc.curry(2).call(11))
# => [12, 14, 16, 18, 20]
You need to supply an arity to curry that matches the call, though. This is because the interpreter doesn't know which object the + method refers to yet. This also means you can only use this when all the objects in map have the same arity. But that's probably not an issue if you're trying to use it this way.
I'm not sure about the Symbol#with already posted, I simplified it quite a bit and it works well:
class Symbol
def with(*args, &block)
lambda { |object| object.public_send(self, *args, &block) }
end
end
(also uses public_send instead of send to prevent calling private methods, also caller is already used by ruby so this was confusing)

Can you supply arguments to the map(&:method) syntax in Ruby?

You're probably familiar with the following Ruby shorthand (a is an array):
a.map(&:method)
For example, try the following in irb:
>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]
The syntax a.map(&:class) is a shorthand for a.map {|x| x.class}.
Read more about this syntax in "What does map(&:name) mean in Ruby?".
Through the syntax &:class, you're making a method call class for each array element.
My question is: can you supply arguments to the method call? And if so, how?
For example, how do you convert the following syntax
a = [1,3,5,7,9]
a.map {|x| x + 2}
to the &: syntax?
I'm not suggesting that the &: syntax is better.
I'm merely interested in the mechanics of using the &: syntax with arguments.
I assume you know that + is a method on Integer class. You can try the following in irb:
>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2
You can create a simple patch on Symbol like this:
class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
Which will enable you to do not only this:
a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]
But also a lot of other cool stuff, like passing multiple parameters:
arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]
And even work with inject, which passes two arguments to the block:
%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"
Or something super cool as passing [shorthand] blocks to the shorthand block:
[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
Here is a conversation I had with #ArupRakshit explaining it further:
Can you supply arguments to the map(&:method) syntax in Ruby?
As #amcaplan suggested in the comment below, you could create a shorter syntax, if you rename the with method to call. In this case, ruby has a built in shortcut for this special method .().
So you could use the above like this:
class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
Here is a version using Refinements (which is less hacky than globally monkey patching Symbol):
module AmpWithArguments
refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
end
using AmpWithArguments
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
For your example can be done a.map(&2.method(:+)).
Arup-iMac:$ pry
[1] pry(main)> a = [1,3,5,7,9]
=> [1, 3, 5, 7, 9]
[2] pry(main)> a.map(&2.method(:+))
=> [3, 5, 7, 9, 11]
[3] pry(main)>
Here is how it works :-
[3] pry(main)> 2.method(:+)
=> #<Method: Fixnum#+>
[4] pry(main)> 2.method(:+).to_proc
=> #<Proc:0x000001030cb990 (lambda)>
[5] pry(main)> 2.method(:+).to_proc.call(1)
=> 3
2.method(:+) gives a Method object. Then &, on 2.method(:+), actually a call #to_proc method, which is making it a Proc object. Then follow What do you call the &: operator in Ruby?.
As the post you linked to confirms, a.map(&:class) is not a shorthand for a.map {|x| x.class} but for a.map(&:class.to_proc).
This means that to_proc is called on whatever follows the & operator.
So you could give it directly a Proc instead:
a.map(&(Proc.new {|x| x+2}))
I know that most probably this defeats the purpose of your question but I can't see any other way around it - it's not that you specify which method to be called, you just pass it something that responds to to_proc.
There is another native option for enumerables which is pretty only for two arguments in my opinion. the class Enumerable has the method with_object which then returns another Enumerable.
So you can call the & operator for a method with each item and the object as arguments.
Example:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+) # => [3, 5, 7, 9, 11]
In the case you want more arguments you should repeat the proccess but it's ugly in my opinion:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+).to_enum.with_object(5).map(&:+) # => [8, 10, 12, 14, 16]
Short answer: No.
Following #rkon's answer, you could also do this:
a = [1,3,5,7,9]
a.map &->(_) { _ + 2 } # => [3, 5, 7, 9, 11]
if all your method needs as argument is an element from the array, this is probably the simplest way to do it:
def double(x)
x * 2
end
[1, 2, 3].map(&method(:double))
=> [2, 4, 6]
Instead of patching core classes yourself, as in the accepted answer, it's shorter and cleaner to use the functionality of the Facets gem:
require 'facets'
a = [1,3,5,7,9]
a.map &:+.(2)
I'm surprised no one mentioned using curry yet, which has been in Ruby since Ruby 2.2.9. Here's how it can be done in the way OP wants using the standard Ruby library:
[1,3,5,7,9].map(&:+.to_proc.curry(2).call(11))
# => [12, 14, 16, 18, 20]
You need to supply an arity to curry that matches the call, though. This is because the interpreter doesn't know which object the + method refers to yet. This also means you can only use this when all the objects in map have the same arity. But that's probably not an issue if you're trying to use it this way.
I'm not sure about the Symbol#with already posted, I simplified it quite a bit and it works well:
class Symbol
def with(*args, &block)
lambda { |object| object.public_send(self, *args, &block) }
end
end
(also uses public_send instead of send to prevent calling private methods, also caller is already used by ruby so this was confusing)

Ruby remove nil values from array with .reject

I have an array:
scores = [1, 2, 3, "", 4]
And I want to remove all blank values. But when I run this:
puts scores.reject(&:empty?)
I get an error:
undefined method `empty' for 1:Fixnum
How can I remove values that are not integers from my array in a one step process? I am using Ruby 1.9.3.
To reject only nil would be:
array.compact
If you want to remove blank values, you should use blank?: (requires Rails / ActiveSupport)
scores.reject(&:blank?)
#=> [1, 2, 3, 4]
"", " ", false, nil, [], and {} are blank.
It is as simple as:
scores.grep(Integer)
Note that if you plan to map the values, you can do that in a block after:
scores.grep(Integer){|x| x+1 }
Bonus if you want to do the same thing, but your numbers are strings:
scores.grep(/\d+/){|x|x.to_i}
Try this :
scores.select{|e| e.is_a? Integer}
# => [1, 2, 3, 4]
If you really need reject nil only, so it can be done like this:
scores.reject(&:nil?)
scores = [1, 2, 3, "", 4, nil]
scores.reject{|s| s.to_s == ''}
# => [1, 2, 3, 4]
This Worked for me
scores.reject!{|x| x.to_s.empty?}
scores.select{|score| score.is_a? Fixnum}
or, as Fixnum inherits from Integer, you can also go for
scores.select{|score| score.is_a? Integer)
...if that seems more descriptive.
Array and Enumerable tend to offer many ways of doing the same thing.
&:empty? will work for hashes, arrays, and strings, but not numbers. The method you use in reject must be valid for all items in a list. &:blank? will work fine for this reason.

accessing variables in loaded source while in irb

Say I have a file named test1.rb with the following code:
my_array = [1, 2, 3, 4 5]
Then I run irb and get an irb prompt and run "require 'test1'. At this point I am expecting to be able to access my_array. But if I try to do something like...
puts my_array
irb tells me "my_array" is undefined. Is there a way to access "my_array"
like this:
def my_array
[1, 2, 3, 4, 5]
end
You can also require your script and access that data in a few other ways. A local variable cannot be accessed, but these other three data types can be accessed within the scope, similar to the method definition.
MY_ARRAY = [1, 2, 3, 4 5] #constant
#my_array = [1, 2, 3, 4 5] #instance variable
##my_array = [1, 2, 3, 4 5] #class variable
def my_array # method definition
[1, 2, 3, 4 5]
end
No, there isn't. Local variables are always local to the scope they are defined in. That's why they are called local variables, after all.
In irb:
eval(File.read('myarray.rb'),binding)
Or you could drop to irb

Resources