Is There a 'Pipe' Equivalent in Ruby

Is there a `pipe` equivalent in ruby?

This abstraction doesn't exist in the core. I usually call it as, it's short and declarative:

class Object
def as
yield(self)
end
end

"3".to_i.as { |x| x*x } #=> 9

Raganwald usually mentions that abstraction in his posts, he calls it into.

So, summing it up, some names: pipe, as, into, peg, thru.

What are those pipe symbols for in Ruby?

They are the variables yielded to the block.

def this_method_takes_a_block
yield(5)
end

this_method_takes_a_block do |num|
puts num
end

Which outputs "5". A more arcane example:

def this_silly_method_too(num)
yield(num + 5)
end

this_silly_method_too(3) do |wtf|
puts wtf + 1
end

The output is "9".

Is there a shorthand equivalent for the double pipe operator which treats empty strings as falsy?

Use the "nullifier" Object#presence:

config.uh_product_name = ENV['UH_PRODUCT_NAME'].presence || 'Unicorn Hunt'

Can someone explain Ruby's use of pipe characters in a block?

Braces define an anonymous function, called a block. Tokens between the pipe are the arguments of this block. The number of arguments required depends on how the block is used. Each time the block is evaluated, the method requiring the block will pass a value based on the object calling it.

It's the same as defining a method, only it's not stored beyond the method that accepts a block.

For example:

def my_print(i) 
puts i
end

will do the same as this when executed:

{|i| puts i}

the only difference is the block is defined on the fly and not stored.

Example 2:
The following statements are equivalent

25.times &method(:my_print)

25.times {|i| puts i}

We use anonymous blocks because the majority of functions passed as a block are usually specific to your situation and not worth defining for reuse.

So what happens when a method accepts a block? That depends on the method. Methods that accept a block will call it by passing values from their calling object in a well defined manner. What's returned depends on the method requiring the block.

For example: In 25.times {|i| puts i} .times calls the block once for each value between 0 and the value of its caller, passing the value into the block as the temporary variable i. Times returns the value of the calling object. In this case 25.

Let's look at method that accepts a block with two arguments.

{:key1 => "value1", :key2 => "value2"}.each {|key,value| 
puts "This key is: #{key}. Its value is #{value}"
}

In this case each calls the block ones for each key/value pair passing the key as the first argument and the value as the second argument.

What is the meaning of the double pipe in Ruby?

c_enc = opts['encode'] || false

In this line if opts['encode'] is not nil, the value of c_enc will be set to opts['encode'] otherwise it will be false

Case 2

If the opts['encode'] is false, the false on the right side of || will be assigned to c_enc.

Other examples

    1  || false => 1 
false || 1 => 1
false || false => false
true || false => true
"foo" || false => "foo" #because string foo is not false or nil
"foo1" || "foo2" => "foo1" #because foo1 is not false or nil, it short circuits and will not bother to evaluate the right hand side of ||

Basically in your example, opts['encode'] should not either false or nil. If it is other than false or nil, anything that is inside opts['encode'] will be assigned to c_enc

Now as per your question

you are passing a hash in the method call, opts is the receiving the argument. Now come to the first line

c_enc = opts['encode'] || false, now opts['encode'] = nil, opts is as hash. You lookup an entry in hash by hash['key'] So c_env = false

Double Pipe Symbols in Ruby Variable Assignment?

It's a conditional assignment. From here:

 x = find_something() #=>nil
x ||= "default" #=>"default" : value of x will be replaced with "default", but only if x is nil or false
x ||= "other" #=>"default" : value of x is not replaced if it already is other than nil or false

What does ||= (or-equals) mean in Ruby?

This question has been discussed so often on the Ruby mailing-lists and Ruby blogs that there are now even threads on the Ruby mailing-list whose only purpose is to collect links to all the other threads on the Ruby mailing-list that discuss this issue.

Here's one: The definitive list of ||= (OR Equal) threads and pages

If you really want to know what is going on, take a look at Section 11.4.2.3 "Abbreviated assignments" of the Ruby Language Draft Specification.

As a first approximation,

a ||= b

is equivalent to

a || a = b

and not equivalent to

a = a || b

However, that is only a first approximation, especially if a is undefined. The semantics also differ depending on whether it is a simple variable assignment, a method assignment or an indexing assignment:

a    ||= b
a.c ||= b
a[c] ||= b

are all treated differently.

Ruby pipe operator on nil and array

nil is the receiver in your example, and NilClass#| coerces the right-hand side of the expression (the argument) to a boolean value. The expression is the equivalent of nil | !!(["foo", "bar"]), and because nil is always falsey and arrays are never falsey, it reduces to false | true, which will always return true. The same is true for other non-falsey values on the right-hand side:

irb(main):001:0> nil|0
=> true
irb(main):002:0> nil|1
=> true
irb(main):003:0> nil|"foo"
=> true
irb(main):004:0> nil|true
=> true
irb(main):005:0> nil|false
=> false
irb(main):006:0> nil|nil
=> false

You can keep doing what you're doing, but if the receiver might be nil (or really anything other than an array), you should coerce it into an array to get the Array#| behavior you desire. Fortunately, there's a really neat and easy way to do that in Ruby:

[*nil] | ["foo", "bar"]

This "does the right thing" in a variety of cases:

irb(main):001:0> [*nil] | ["foo", "bar"]
=> ["foo", "bar"]
irb(main):002:0> var = "foo"
=> "foo"
irb(main):003:0> [*var] | ["foo", "bar"]
=> ["foo", "bar"]
irb(main):004:0> var = ["bar"]
=> ["bar"]
irb(main):005:0> [*var] | ["foo", "bar"]
=> ["bar", "foo"]
irb(main):006:0> var = []
=> []
irb(main):007:0> [*var] | ["foo", "bar"]
=> ["foo", "bar"]
irb(main):008:0> var = nil
=> nil
irb(main):009:0> [*var] | ["foo", "bar"]
=> ["foo", "bar"]

Pipe symbol before command in open

The Ruby documentation for Kernel#open says:

If path starts with a pipe character ("|"), a subprocess is created,
connected to the caller by a pair of pipes. The returned IO object may
be used to write to the standard input and read from the standard
output of this subprocess.

In your case it is used to log the output of the process spawned by the command /opt/jruby/bin/jruby jasper_pdf.rb to the file log/jasper_pdf.log.

It is roughly equivalent to use the Open3 module like this:

require 'open3'
Open3.popen2e('cd lib && /opt/jruby/bin/jruby jasper_pdf.rb') do |_, output, _|
open('log/jasper_pdf.log', 'w') do |f|
f.write(output.read)
end
end


Related Topics



Leave a reply



Submit