programing

루비의 블록 및 수율

skycolor 2023. 7. 21. 21:29
반응형

루비의 블록 및 수율

과 나는블을록이고노려있력고고하해하▁andstand▁blocks,있고,yield그리고 루비에서 어떻게 작동하는지.

어떻게 있다.yield 중 이 었까습니용? 제가 살펴본 많은 레일즈 애플리케이션은yield이상한 방법으로

누가 나에게 설명을 해주거나 그들을 이해하기 위해 어디로 가야 하는지 보여줄 수 있습니까?

네, 처음에는 좀 헷갈립니다.

Ruby에서 메서드는 코드의 임의 세그먼트를 수행하기 위해 코드 블록을 수신할 수 있습니다.

메서드가 블록을 예상할 때, 다음을 호출하여 블록을 호출할 수 있습니다.yield기능.

예:

가지고 가다Personname및 속과ado_with_name전달됩니다.name블록에 대한 속성입니다.

class Person 
    def initialize( name ) 
         @name = name
    end

    def do_with_name   # expects a block
        yield( @name ) # invoke the block and pass the `@name` attribute
    end
end

이제 이 메서드를 호출하여 임의 코드 블록을 전달할 수 있습니다.

person = Person.new("Oscar")

# Invoking the method passing a block to print the value
person.do_with_name do |value|
    puts "Got: #{value}"
end

인쇄 대상:

Got: Oscar

로 블이매변수수변신수같다습다라는 변수를 합니다.value가 코가호출때될드를 할 때yield은 인수로 됩니다.@name.

yield( @name )

다른 블록으로 동일한 메서드를 호출할 수 있습니다.

예를 들어 이름을 반대로 설정하는 경우:

reversed_name = ""

# Invoke the method passing a different block
person.do_with_name do |value| 
    reversed_name = value.reverse
end

puts reversed_name

=> "racsO"

다른 더 흥미로운 실생활 사례들:

배열에서 요소 필터링:

 days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]  

 # Select those which start with 'T' 
 days.select do | item |
     item.match /^T/
 end

=> ["Tuesday", "Thursday"]

또는 이름 길이별로 정렬:

 days.sort do |x,y|
    x.size <=> y.size
 end

=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]

블록이 선택 사항인 경우 다음을 사용할 수 있습니다.

yield(value) if block_given?

이 옵션이 아닌 경우 이 옵션을 호출합니다.

컴퓨터에서 다음 예제를 사용하여 사용할 수 있습니다.irb(인터랙티브 루비 쉘)

다음은 복사/붙여넣기 준비 형식의 모든 예입니다.

class Person 
    def initialize( name ) 
         @name = name
    end

    def do_with_name   # expects a block
        yield( @name ) # invoke the block and pass the `@name` attribute
    end
end


person = Person.new("Oscar")

# Invoking the method passing a block to print the value
person.do_with_name do |value|
    puts "Got: #{value}"
end


reversed_name = ""

# Invoke the method passing a different block
person.do_with_name do |value| 
    reversed_name = value.reverse
end

puts reversed_name



# Filter elements in an array:    
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]  

# Select those which start with 'T' 
days.select do | item |
    item.match /^T/
end



# Sort by name length:     
days.sort do |x,y|
   x.size <=> y.size
end

Ruby에서 메소드는 일반 인수 외에 블록이 제공되는 방식으로 호출되었는지 확인할 수 있습니다.일반적으로 이 작업은 다음을 사용하여 수행됩니다.block_given?.&)을를) 입력합니다을(를) 입력합니다.

블록을 사용하여 메서드를 호출하면 메서드는yield필요한 경우 몇 가지 인수를 사용하여 블록에 대한 제어(블록 호출).다음을 보여주는 이 예제 방법을 생각해 보십시오.

def foo(x)
  puts "OK: called as foo(#{x.inspect})"
  yield("A gift from foo!") if block_given?
end

foo(10)
# OK: called as foo(10)
foo(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as foo(123)
# BLOCK: A gift from foo! How nice =)

또는 특수 블록 인수 구문을 사용합니다.

def bar(x, &block)
  puts "OK: called as bar(#{x.inspect})"
  block.call("A gift from bar!") if block
end

bar(10)
# OK: called as bar(10)
bar(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as bar(123)
# BLOCK: A gift from bar! How nice =)

누군가가 여기서 진정으로 상세한 답변을 제공할 가능성이 꽤 있지만, 저는 항상 로버트 소신스키의 이 게시물이 블록, 프록스, 람다 사이의 미묘함에 대한 훌륭한 설명이라고 생각했습니다.

제가 링크하고 있는 게시물은 루비 1.8에 한정되어 있다고 생각합니다.루비 1.9에서 블록 변수가 블록에 로컬인 것과 같은 일부 사항이 변경되었습니다.1.8에서는 다음과 같은 결과를 얻을 수 있습니다.

>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Goodbye"

1.9는 다음을 제공합니다.

>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Hello"

저는 이 기계에 1.9가 없어서 위에 오류가 있을 수 있습니다.

는 이 기사가 매우 유용하다는 것을 알았습니다.특히 다음 예는 다음과 같습니다.

#!/usr/bin/ruby

def test
  yield 5
  puts "You are in the method test"
  yield 100
end

test {|i| puts "You are in the block #{i}"}

test do |i|
    puts "You are in the block #{i}"
end

다음과 같은 출력을 제공해야 합니다.

You are in the block 5
You are in the method test
You are in the block 100
You are in the block 5
You are in the method test
You are in the block 100

가 올 마다 그래서본매전걸려때올가화마다번질으.yield▁the의 입니다.do 내부{}를 변매수제경우는되공에 yield 그면이것이매변제것입공니다될수로개러▁▁the에 대한 매개 입니다.do블록으로 막다

나에게 있어서, 이것은 내가 진정으로 이해한 첫 번째였습니다.do블록들이 하고 있었습니다.이는 기본적으로 함수가 내부 데이터 구조에 액세스할 수 있도록 하는 방법으로, 반복을 위한 것이든 함수의 구성을 위한 것이든 상관없습니다.

레일에서 다음과 같이 기록합니다.

respond_to do |format|
  format.html { render template: "my/view", layout: 'my_layout' }
end

이렇게 하면 실행됩니다.respond_to을 하는 함수do (으)로 합니다.format매개 변수그런 다음 전화를 합니다..html하여 이내변 함다수실음코로행산다블드니출록을 합니다.render참고:.html요청한 파일 형식인 경우에만 반환됩니다.(기술: 이 함수들은 실제로 사용합니다.block.call것은 아니다.yield소스에서 볼 수 있지만 기능은 기본적으로 동일합니다. 자세한 내용은 이 질문을 참조하십시오.)이를 통해 기능이 초기화를 수행한 다음 호출 코드에서 입력을 가져온 다음 필요한 경우 처리를 계속할 수 있습니다.

즉, 함수가 익명 함수를 인수로 사용하여 javascript로 호출하는 것과 비슷합니다.

저는 왜 당신이 이미 훌륭한 답변들에 그런 식으로 일을 하는지를 덧붙이고 싶었습니다.

여러분이 어떤 언어에서 왔는지는 모르지만, 정적인 언어라고 가정하면, 이런 종류의 것은 친숙해 보일 것입니다.이것이 당신이 자바로 파일을 읽는 방법입니다.

public class FileInput {

  public static void main(String[] args) {

    File file = new File("C:\\MyFile.txt");
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    DataInputStream dis = null;

    try {
      fis = new FileInputStream(file);

      // Here BufferedInputStream is added for fast reading.
      bis = new BufferedInputStream(fis);
      dis = new DataInputStream(bis);

      // dis.available() returns 0 if the file does not have more lines.
      while (dis.available() != 0) {

      // this statement reads the line from the file and print it to
        // the console.
        System.out.println(dis.readLine());
      }

      // dispose all the resources after using them.
      fis.close();
      bis.close();
      dis.close();

    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

모든 스트림 체인을 무시하고, 아이디어는 이것입니다.

  1. 정리해야 하는 리소스 초기화
  2. 자원을 사용합니다.
  3. 그것을 반드시 치웁니다.

루비로 하는 방법은 이렇습니다.

File.open("readfile.rb", "r") do |infile|
    while (line = infile.gets)
        puts "#{counter}: #{line}"
        counter = counter + 1
    end
end

완전히 다릅니다.이것을 부수는 것.

  1. 파일 클래스에 리소스를 초기화하는 방법을 알려줍니다.
  2. 파일 클래스에 사용할 작업을 지정합니다.
  3. 아직 타이핑 중인 자바 남자들을 비웃습니다 ;-)

여기서는 1단계와 2단계를 처리하는 대신 기본적으로 다른 클래스로 위임합니다.보시다시피, 이렇게 하면 작성해야 하는 코드의 양이 크게 줄어들어 내용을 읽기가 더 쉬워지고 메모리 누수나 파일 잠금이 지워지지 않을 가능성이 줄어듭니다.

자, 여러분이 자바에서 비슷한 것을 할 수 없는 것은 아닙니다. 사실, 사람들은 수십 년 동안 그것을 해왔습니다.그것은 전략 패턴이라고 불립니다.차이점은 블록이 없으면 파일 예제와 같은 단순한 경우에는 작성해야 하는 클래스와 메서드의 양으로 인해 전략이 과도하게 실행된다는 것입니다.블록을 사용하는 것은 매우 간단하고 우아한 방법이기 때문에 코드를 그런 식으로 구성하지 않는 것은 말이 되지 않습니다.

블록이 사용되는 유일한 방법은 아니지만, 다른 방법(레일의 api에 대한_for api 형식에서 볼 수 있는 Builder 패턴 등)도 충분히 유사하므로 이를 머리에 감으면 무슨 일이 일어나고 있는지 분명하게 알 수 있습니다.블록이 표시되면 일반적으로 메서드 호출이 원하는 작업이며 블록이 원하는 작업 방식을 설명하고 있다고 가정하는 것이 좋습니다.

루비에서 블록은 기본적으로 어떤 방식으로든 전달되고 실행될 수 있는 코드 덩어리입니다.블록은 항상 메서드와 함께 사용되며 일반적으로 데이터를 제공합니다(인수로).

블록은 루비 보석(레일 포함) 및 잘 작성된 루비 코드에서 널리 사용됩니다.개체가 아니므로 변수에 할당할 수 없습니다.

기본 구문

블록은 {} 또는 do로 둘러싸인 코드 조각입니다.curly brace 구문은 일반적으로 한 줄 블록과 do에 사용해야 합니다.다중 줄 블록에는 끝 구문을 사용해야 합니다.

{ # This is a single line block }

do
  # This is a multi-line block
end 

모든 메서드는 블록을 암시적 인수로 수신할 수 있습니다.블록은 메소드 내의 수율 문에 의해 실행됩니다.기본 구문은 다음과 같습니다.

def meditate
  print "Today we will practice zazen"
  yield # This indicates the method is expecting a block
end 

# We are passing a block as an argument to the meditate method
meditate { print " for 40 minutes." }

Output:
Today we will practice zazen for 40 minutes.

수율 문에 도달하면, 명상 방법은 블록에 제어권을 부여하고, 블록 내의 코드가 실행되고 제어권이 메서드로 반환되며, 수율 문 직후에 실행을 재개합니다.

메소드에 수율 문이 포함되어 있으면 호출 시 블럭을 수신해야 합니다.블록이 제공되지 않으면 수율 문에 도달하면 예외가 발생합니다.블록을 선택적으로 설정하고 예외 발생을 방지할 수 있습니다.

def meditate
  puts "Today we will practice zazen."
  yield if block_given? 
end meditate

Output:
Today we will practice zazen. 

여러 블럭을 메서드에 전달할 수 없습니다.각 메서드는 하나의 블록만 수신할 수 있습니다.

자세한 내용은 http://www.zenruby.info/2016/04/introduction-to-blocks-in-ruby.html 에서 확인하십시오.

저는 가끔 다음과 같은 "수익률"을 사용합니다.

def add_to_http
   "http://#{yield}"
end

puts add_to_http { "www.example.com" }
puts add_to_http { "www.victim.com"}

간단히 말해, 생성한 메서드가 블록을 가져오고 호출할 수 있도록 허용합니다.수율 키워드는 구체적으로 블록의 'stuff'가 수행될 지점입니다.

여기서 수익률에 대해 두 가지 요점을 말씀드리고 싶습니다.먼저, 여기서는 수율을 사용하는 방법으로 블록을 전달하는 다양한 방법에 대해 많은 답변을 제공하지만, 제어 흐름에 대해서도 이야기해 보겠습니다.한 블록에 여러 번 양보할 수 있기 때문에 특히 중요합니다.예를 들어 보겠습니다.

class Fruit
  attr_accessor :kinds

  def initialize 
    @kinds = %w(orange apple pear banana)
  end

  def each 
    puts 'inside each'
    3.times { yield (@kinds.tap {|kinds| puts "selecting from #{kinds}"} ).sample }
  end  
end

f = Fruit.new
f.each do |kind|
  puts 'inside block'
end    

=> inside each
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block

각 메서드가 호출되면 한 줄씩 실행됩니다.이제 3.times 블록에 도달하면 이 블록은 3번 호출됩니다.수익률을 호출할 때마다.이 산출량은 각 방법을 호출한 방법과 연결된 블럭과 연결됩니다.수율이 호출될 때마다 클라이언트 코드에서 각 메서드의 블록으로 제어를 되돌립니다.블록 실행이 완료되면 3.times 블록으로 돌아갑니다.그리고 이것은 3번 발생합니다.따라서 클라이언트 코드의 블록은 수율을 3개의 개별 시간이라고 명시적으로 부르기 때문에 3개의 개별 시간에 호출됩니다.

저의 두 번째 요점은 enum_for와 yield에 관한 것입니다.enum_for는 Enumerator 클래스를 인스턴스화하며 이 Enumerator 개체도 수율에 응답합니다.

class Fruit
  def initialize
    @kinds = %w(orange apple)
  end

  def kinds
    yield @kinds.shift
    yield @kinds.shift
  end
end

f = Fruit.new
enum = f.to_enum(:kinds)
enum.next
 => "orange" 
enum.next
 => "apple" 

외부 반복기를 사용하여 종류를 호출할 때마다 한 번만 수율을 호출합니다.다음 번에 호출하면 다음 수율 등이 호출됩니다.

enum_for에 관한 흥미로운 소식이 있습니다.온라인 설명서에는 다음과 같은 내용이 나와 있습니다.

enum_for(method = :each, *args) → enum
Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.

str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }    
# => 120
# => 121
# => 122

enum_for 인수로 기호를 지정하지 않으면 루비는 열거자를 수신자의 각 메서드에 연결합니다.String 클래스와 같이 일부 클래스에는 각 메서드가 없습니다.

str = "I like fruit"
enum = str.to_enum
enum.next
=> NoMethodError: undefined method `each' for "I like fruit":String

따라서 enum_for로 호출된 일부 개체의 경우 열거 방법이 무엇인지 명시적으로 지정해야 합니다.

수율을 이름 없는 블럭으로 사용하여 메서드의 값을 반환할 수 있습니다.다음 코드를 고려합니다.

Def Up(anarg)
  yield(anarg)
end

하나의 인수가 할당된 메서드 "Up"을 생성할 수 있습니다.이제 이 인수를 할당하여 관련 블록을 호출하고 실행할 수 있습니다.매개 변수 목록 뒤에 블록을 할당할 수 있습니다.

Up("Here is a string"){|x| x.reverse!; puts(x)}

Up 메서드가 인수를 사용하여 항복을 호출하면 요청을 처리하기 위해 블록 변수로 전달됩니다.

언급URL : https://stackoverflow.com/questions/3066703/blocks-and-yields-in-ruby

반응형