it-swarm-ko.tech

Ruby의 숨겨진 기능

"숨겨진 기능 ..."meme을 계속하면서 Ruby 프로그래밍 언어의 덜 알려지지 만 유용한 기능을 공유해 봅시다.

Ruby에 Rails 자료없이 핵심 Ruby로이 토론을 제한하십시오.

또한보십시오:

(답변 당 one 숨겨진 기능 만)하십시오.

감사합니다

160
squadette

From Ruby 1.9 Proc # ===는 Proc # call의 별칭입니다. 즉 Proc 객체는 다음과 같은 경우에 사용할 수 있습니다.

def multiple_of(factor)
  Proc.new{|product| product.modulo(factor).zero?}
end

case number
  when multiple_of(3)
    puts "Multiple of 3"
  when multiple_of(7)
    puts "Multiple of 7"
end
80
Farrel

Peter Cooper는 좋은 목록 of Ruby 트릭입니다. 아마도 내가 가장 좋아하는 것은 단일 항목과 컬렉션을 모두 열거하는 것입니다. 해당 개체 만 포함하는 컬렉션으로 컬렉션 개체). 다음과 같습니다.

[*items].each do |item|
  # ...
end
76
James A. Rosen

이것이 어떻게 숨겨져 있는지 모르지만 1 차원 배열에서 해시를 만들어야 할 때 유용하다는 것을 알았습니다.

fruit = ["Apple","red","banana","yellow"]
=> ["Apple", "red", "banana", "yellow"]

Hash[*fruit]    
=> {"Apple"=>"red", "banana"=>"yellow"}
64
astronautism

내가 좋아하는 트릭은 splat (*) 배열 이외의 객체의 확장기. 정규식 일치에 대한 예는 다음과 같습니다.

match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)

다른 예는 다음과 같습니다.

a, b, c = *('A'..'Z')

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
54
tomafro

와우, 플립 플롭 연산자를 언급 한 사람은 없습니다.

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end
52
Konstantin Haase

Ruby의 멋진 점 중 하나는 메소드 또는 클래스 정의와 같이 다른 언어가 찌그러 질 곳에서 메소드를 호출하고 코드를 실행할 수 있다는 것입니다.

예를 들어, 런타임까지 알 수없는 수퍼 클래스가있는 클래스를 만들려면 (예 : 임의) 다음을 수행 할 수 있습니다.

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.

이것은 1.9 Array#sample 방법 (1.8.7 만 해당, Array#choice), 예제는 꽤 고안되었지만 여기에서 힘을 볼 수 있습니다.

또 다른 멋진 예는 고정되지 않은 기본 매개 변수 값을 넣는 기능입니다 (다른 언어가 자주 요구하는 것처럼).

def do_something_at(something, at = Time.now)
   # ...
end

물론 첫 번째 예제의 문제점은 호출 시간이 아니라 정의 시간에 평가된다는 것입니다. 따라서 수퍼 클래스가 선택되면 나머지 프로그램의 수퍼 클래스가 유지됩니다.

그러나 두 번째 예에서는 do_something_at, at 변수는 메소드가 호출 된 시간입니다 (매우 매우 근접 함).

49
Bo Jeanes

또 다른 작은 기능-Fixnum를 최대 36까지의 기본으로 변환하십시오.

>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"

>> 1234567890.to_s(8)
=> "11145401322"

>> 1234567890.to_s(16)
=> "499602d2"

>> 1234567890.to_s(24)
=> "6b1230i"

>> 1234567890.to_s(36)
=> "kf12oi"

Huw Walters가 언급했듯이 다른 방법으로 변환하는 것은 간단합니다.

>> "kf12oi".to_i(36)
=> 1234567890
47
tomafro

기본값으로 해시! 이 경우 배열입니다.

parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []

parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"

메타 프로그래밍에 매우 유용합니다.

40
August Lilleaas

Ruby 1.9 소스 다운로드 및 make golf, 그러면 다음과 같이 할 수 있습니다 :

make golf

./goruby -e 'h'
# => Hello, world!

./goruby -e 'p St'
# => StandardError

./goruby -e 'p 1.tf'
# => 1.0

./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/Ruby-svn/src/trunk"

읽기 golf_prelude.c 더 깔끔한 것들이 숨겨져 있습니다.

39
manveru

1.9 Proc 기능의 또 다른 재미있는 추가 기능은 Proc # curry입니다.이 매개 변수는 n 개의 인수를 수락하는 Proc를 n 개의 수락하는 n-1로 바꿀 수 있습니다. 여기에 위에서 언급 한 Proc # === 팁과 결합됩니다.

it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]

case Time.now
when it_is_saturday
  puts "Saturday!"
when it_is_sunday
  puts "Sunday!"
else
  puts "Not the weekend"
end
38
Farrel

부울이 아닌 값에 대한 부울 연산자.

&&||

둘 다 마지막으로 평가 된 식의 값을 반환합니다.

||=는 변수가 정의되지 않은 경우 오른쪽에 반환 된 값으로 변수를 업데이트합니다. 이것은 명시 적으로 문서화되어 있지는 않지만 일반적인 지식입니다.

그러나, 그 &&=은 널리 알려져 있지 않습니다.

string &&= string + "suffix"

에 해당

if string
  string = string + "suffix"
end

변수가 정의되지 않은 경우 진행되지 않아야하는 파괴적인 작업에 매우 편리합니다.

35
EmFi

Rails 제공하는 Symbol # to_proc 함수는 정말 멋집니다.

대신에

Employee.collect { |emp| emp.name }

당신은 쓸 수 있습니다:

Employee.collect(&:name)
29
hoyhoy

마지막 하나-in Ruby 문자열을 구분하려는 모든 문자를 사용할 수 있습니다. 다음 코드를 사용하십시오.

message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"

문자열 내에서 큰 따옴표를 이스케이프하지 않으려면 다른 구분 기호를 사용하면됩니다.

contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]

구분 기호를 이스케이프 처리하지 않아도 될뿐만 아니라 다음 구분 기호를 사용하여 더 나은 여러 줄 문자열을 사용할 수 있습니다.

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}
28
tomafro

define_method 명령을 사용하여 메소드를 동적으로 생성하여 흥미롭고 잘 알려지지 않은 것을 발견했습니다. 예를 들면 다음과 같습니다.

((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end

위 코드는 'define_method'명령을 사용하여 "press1"~ "press9"메소드를 동적으로 작성합니다. essentailly가 동일한 코드를 포함하는 10 개의 메소드를 모두 입력하는 대신 define 메소드 명령을 사용하여 필요에 따라 이러한 메소드를 즉시 생성합니다.

26

Range 개체를 무한한 지연 목록으로 사용하십시오.

Inf = 1.0 / 0

(1..Inf).take(5) #=> [1, 2, 3, 4, 5]

자세한 정보는 여기 : http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-Ruby/

26
horseyguy

module_function

module_function 으로 선언 된 모듈 메소드는 모듈을 포함하는 클래스에서 private 인스턴스 메소드로 자신의 사본을 작성합니다.

module M
  def not!
    'not!'
  end
  module_function :not!
end

class C
  include M

  def fun
    not!
  end
end

M.not!     # => 'not!
C.new.fun  # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>

인수없이 module_function 을 사용하면 module_function 문 다음에 오는 모든 모듈 메소드가 자동으로 module_functions 자체가됩니다.

module M
  module_function

  def not!
    'not!'
  end

  def yea!
    'yea!'
  end
end


class C
  include M

  def fun
    not! + ' ' + yea!
  end
end
M.not!     # => 'not!'
M.yea!     # => 'yea!'
C.new.fun  # => 'not! yea!'
23
newtonapple

다음과 같은 짧은 주사 :

범위의 합 :

(1..10).inject(:+)
=> 55
23
user130730

경고 :이 항목은 # 1 Most Horrendous Hack of 2008으로 선정되었습니다. 실제로, 전염병처럼 피하십시오. 그러나 가장 확실한 것은 숨겨진 루비입니다.

수퍼 레이터는 Ruby에 새로운 연산자 추가

코드에서 일부 고유 한 작업을위한 초 비밀 핸드 셰이크 연산자를 원하십니까? 코드 골프를하는 것처럼? -~ + ~-또는 <---와 같은 연산자를 사용하십시오. 마지막 연산자는 예제에서 항목의 순서를 반대로하는 데 사용됩니다.

Superators Project 와는 아무런 관련이 없습니다.

21
Captain Hammer

나는 파티에 늦었지만

두 개의 동일한 길이의 배열을 쉽게 가져 와서 하나의 배열로 키를 제공하고 다른 하나는 값을 해시로 전환 할 수 있습니다.

a = [:x, :y, :z]
b = [123, 456, 789]

Hash[a.Zip(b)]
# => { :x => 123, :y => 456, :z => 789 }

(이것은 Array # Zip이 두 배열의 값을 "zip으로 압축"하기 때문에 작동합니다.

a.Zip(b)  # => [[:x, 123], [:y, 456], [:z, 789]]

그리고 Hash []는 그러한 배열을 취할 수 있습니다. 사람들이 이것을하는 것을 보았습니다.

Hash[*a.Zip(b).flatten]  # unnecessary!

어느 결과가 같은 결과를 낼지 모르지만, 스 플랫과 플래 튼은 전적으로 불필요합니다. 아마도 과거에는 없었을까요?

19
Jordan Running

루비의 자동 활성화 해시

def cnh # silly name "create nested hash"
  Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }

이것은 단지 편리 할 수 ​​있습니다.

19
Trevoke

배열 파괴

(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]

어디:

a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]

이 기법을 사용하면 간단한 할당을 사용하여 원하는 깊이의 중첩 배열에서 원하는 정확한 값을 얻을 수 있습니다.

16
horseyguy

Class.new()

런타임에 새 클래스를 작성하십시오. 인수는 파생 클래스가 될 수 있으며 블록은 클래스 본문입니다. const_set/const_get/const_defined? 새 클래스를 제대로 등록하려면 inspect에서 숫자 대신 이름을 인쇄하십시오.

매일 필요한 것은 아니지만 할 때 매우 편리합니다.

15
Justin Love

연속적인 숫자의 배열을 만듭니다.

x = [*0..5]

x를 [0, 1, 2, 3, 4, 5]로 설정

13
horseyguy

Rubyland에서 볼 수있는 많은 마술은 메타 프로그래밍과 관련이 있습니다. 메타 프로그래밍은 단순히 코드를 작성하는 코드를 작성하는 것입니다. Ruby의 attr_accessor, attr_readerattr_writer는 표준 패턴에 따라 한 줄에 두 개의 메소드를 작성한다는 점에서 간단한 메타 프로그래밍입니다. Rails has_onebelongs_to와 같은 관계 관리 방법을 사용하여 많은 메타 프로그래밍을 수행합니다.

그러나 동적으로 작성된 코드를 실행하기 위해 class_eval를 사용하여 자체 메타 프로그래밍 트릭을 만드는 것은 매우 간단합니다.

다음 예제는 랩퍼 오브젝트가 특정 메소드를 내부 오브젝트로 전달할 수 있도록합니다.

class Wrapper
  attr_accessor :internal

  def self.forwards(*methods)
    methods.each do |method|
      define_method method do |*arguments, &block|
        internal.send method, *arguments, &block
      end
    end
  end

  forwards :to_i, :length, :split
end

w = Wrapper.new
w.internal = "12 13 14"
w.to_i        # => 12
w.length      # => 8
w.split('1')  # => ["", "2 ", "3 ", "4"]

Wrapper.forwards 메소드는 메소드 이름의 기호를 가져 와서 methods 배열에 저장합니다. 그런 다음 주어진 각각에 대해 define_method를 사용하여 모든 인수와 블록을 포함하여 메시지를 전송하는 새 메소드를 작성합니다.

메타 프로그래밍 문제에 대한 훌륭한 리소스는 Lucky Stiff의 "메타 프로그래밍을 분명히 보는 이유" 입니다.

13
TALlama

"Ruby"바이너리 (적어도 MRI)는 Perl one-liner를 매우 대중적으로 만든 많은 스위치를 지원합니다.

중요한 것들 :

  • -n "gets"만으로 외부 루프를 설정합니다.이 파일은 주어진 파일 이름 또는 STDIN과 마술처럼 작동하여 $ _에 각 읽기 행을 설정합니다.
  • -p -n과 유사하지만 각 루프 반복의 끝에 자동 puts
  • -a $ F에 저장된 각 입력 라인에서 .split에 대한 자동 호출
  • -i 내부 편집 입력 파일
  • -l 입력시 .chomp에 대한 자동 호출
  • -e 코드를 실행
  • -c 소스 코드 확인
  • -w 경고와 함께

몇 가지 예 :

# Print each line with its number:
Ruby -ne 'print($., ": ", $_)' < /etc/irbrc

# Print each line reversed:
Ruby -lne 'puts $_.reverse' < /etc/irbrc

# Print the second column from an input CSV (dumb - no balanced quote support etc):
Ruby -F, -ane 'puts $F[1]' < /etc/irbrc

# Print lines that contain "eat"
Ruby -ne 'puts $_ if /eat/i' < /etc/irbrc

# Same as above:
Ruby -pe 'next unless /eat/i' < /etc/irbrc

# Pass-through (like cat, but with possible line-end munging):
Ruby -p -e '' < /etc/irbrc

# Uppercase all input:
Ruby -p -e '$_.upcase!' < /etc/irbrc

# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
Ruby -i.bak -p -e '$_.upcase!' /etc/irbrc

더 유용하고 실용적인 톤을 얻으려면 Google "루비 원 라이너"및 "펄 원 라이너"를 자유롭게 사용하십시오. 기본적으로 Ruby을 awk와 sed의 상당히 강력한 대체물로 사용할 수 있습니다.

11
minaguib

send () 메소드는 Ruby의 모든 클래스 또는 객체에서 사용할 수있는 범용 메소드입니다. 재정의되지 않은 경우 send ()는 문자열을 허용하고 문자열이 전달 된 메서드의 이름을 호출합니다. 예를 들어 사용자가 'Clr'버튼을 클릭하면 'press_clear'문자열이 send () 메소드로 전송되고 'press_clear'메소드가 호출됩니다. send () 메소드를 사용하면 Ruby에서 함수를 재미 있고 동적으로 호출 할 수 있습니다.

 %w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
    button btn, :width => 46, :height => 46 do
      method = case btn
        when /[0-9]/: 'press_'+btn
        when 'Clr': 'press_clear'
        when '=': 'press_equals'
        when '+': 'press_add'
        when '-': 'press_sub'
        when '*': 'press_times'
        when '/': 'press_div'
      end

      number.send(method)
      number_field.replace strong(number)
    end
  end

이 기능에 대해 블로그 신발 : 간단한 계산기 응용 프로그램

10
private unless Rails.env == 'test'
# e.g. a bundle of methods you want to test directly

멋지고 유용한 (일부 경우) 루비의 유용한 해킹/기능처럼 보입니다.

9
Szymon Jeż

Fixnum#to_s(base)은 어떤 경우에는 정말 유용 할 수 있습니다. 이러한 경우 중 하나는 36의 밑을 사용하여 난수를 문자열로 변환하여 난수 (의사) 고유 토큰을 생성하는 것입니다.

길이 8의 토큰 :

Rand(36**8).to_s(36) => "fmhpjfao"
Rand(36**8).to_s(36) => "gcer9ecu"
Rand(36**8).to_s(36) => "krpm0h9r"

길이 6의 토큰 :

Rand(36**6).to_s(36) => "bvhl8d"
Rand(36**6).to_s(36) => "lb7tis"
Rand(36**6).to_s(36) => "ibwgeh"
9
sickill

실제로 필요하지 않은 것이 필요하다고 말하는 클래스 나 모듈을 속이십시오.

$" << "something"

이것은 예를 들어 A를 요구할 때 유용하지만 B에는 필요하지만 코드에는 B가 필요하지 않으며 A는 코드를 통해 어느 것도 사용하지 않습니다.

예를 들어, Backgroundrb 's bdrb_test_helper requires'test/spec',하지만 전혀 사용하지 않으므로 코드에서 :

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
9
olegueret

여러 개의 매개 변수를 허용하고 모든 매개 변수를 버리는 메소드 정의

def hello(*)
    super
    puts "hello!"
end

위의 hello 메소드는 puts"hello" 화면에서 super을 호출합니다. 그러나 수퍼 클래스 hello은 (는) 매개 변수도 정의하지만 실제로는 매개 변수 자체를 사용할 필요가 없기 때문에 필요하지 않습니다. 그들에게 이름을 주어야합니다.

9
horseyguy

여러 정규 표현식을 |, 당신이 사용할 수있는

Regexp.union /Ruby\d/, /test/i, "cheat"

다음과 비슷한 Regexp를 작성하십시오.

/(Ruby\d|[tT][eE][sS][tT]|cheat)/
8
J-_-L

일부 스크립트에서이 기능이 유용하다는 것을 알았습니다. Shell 스크립트 및 Makefile과 같이 환경 변수를 직접 사용할 수 있습니다. 환경 변수는 정의되지 않은 Ruby 상수에 대한 대체로 사용됩니다.

>> class <<Object
>>  alias :old_const_missing :const_missing
>>  def const_missing(sym)
>>   ENV[sym.to_s] || old_const_missing(sym)
>>  end
>> end
=> nil

>> puts Shell
/bin/zsh
=> nil
>> TERM == 'xterm'
=> true
8
Ropez

ARGV [0]에 기초하여 파일을 여는 것은 어떻습니까?

readfile.rb:

$<.each_line{|l| puts l}

Ruby readfile.rb testfile.txt

일회성 스크립트 작성을위한 훌륭한 지름길입니다. 대부분의 사람들이 알지 못하는 사전 정의 된 변수가 엉망입니다. 그것들을 현명하게 사용하십시오 (읽기 : 그들과 함께 유지할 코드베이스를 깔지 마십시오. 지저분해질 수 있습니다).

8
Scott Holden

나는 팬입니다 :

%w{An Array of strings} #=> ["An", "Array", "of", "Strings"]

얼마나 유용한 지 재미 있네요.

5
Judson

James A. Rosen의 팁은 멋지지만 ([* items] .each) 해시를 파괴한다는 것을 알았습니다.

irb(main):001:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):002:0> [*h]
=> [[:name, "Bob"]]

처리 할 항목 목록을 수락하지만 관대하며 발신자가 하나를 제공 할 수 있도록 허용하는 경우이 방식을 처리하는 것이 좋습니다.

irb(main):003:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):004:0> [h].flatten
=> [{:name=>"Bob"}]

이것은 다음과 같이 메소드 서명과 결합 될 수 있습니다.

def process(*entries)
  [entries].flatten.each do |e|
    # do something with e
  end
end
4
minaguib

인라인 키워드 rescue처럼 love
편집 된 예 :

@user #=> nil (but I did't know)
@user.name rescue "Unknown"
link_to( d.user.name, url_user( d.user.id, d.user.name)) rescue 'Account removed'

이렇게하면 내 앱이 깨지지 않으며 Rails . try ()

4
Fabiano Soriani

재정의 된 경우에도 상속 체인의 어느 곳에서나 정의 된 메소드 호출

ActiveSupport의 객체는 내장 객체로 가장하기도합니다.

 'active_support'
 days = 5.days 
 days.class # => Fixnum 
 days.is_a? (Fixnum) # => true [.____ 필요 .] Fixnum === 일 # => 거짓 (응? 실제로 무엇입니까?) 
 Object.instance_method (: class) .bind (days) .call # => ActiveSupport :: Duration (aha!) 
 ActiveSupport :: Duration === 일 # => true 

물론 위의 내용은 active_support가 Object # instance_method를 재정의하지 않는다는 사실에 의존합니다.이 경우 실제로 우리는 개울에 빠질 것입니다. 그런 다음 타사 라이브러리가로드되기 전에 항상 Object.instance_method (: class)의 반환 값을 저장할 수 있습니다.

Object.instance_method (...)는 해당 클래스의 인스턴스에 바인딩 할 수있는 UnboundMethod를 반환합니다. 이 경우 Object의 모든 인스턴스 (서브 클래스 포함)에 바인딩 할 수 있습니다.

객체의 클래스에 모듈이 포함 된 경우 해당 모듈에서 UnboundMethod를 사용할 수도 있습니다.

 모듈 Mod 
 def var_add (more); @ var + more; end 
 end 
 class Cla 
 include Mod 
 def initialize (var); @ var = var; end 
 # override 
 def var_add (more); @ var + more + more; end 
 end 
 cla = Cla.new ( 'abcdef') 
 cla.var_add ( 'ghi') # => "abcdefghighi"
 Mod.instance_method ( : var_add) .bind (cla) .call ( 'ghi') # => "abcdefghi"

심지어 객체가 속한 클래스의 인스턴스 메소드를 재정의하는 싱글 톤 메소드에서도 작동합니다.

 class Foo 
 def mymethod; '기발한'; end 
 end 
 foo = Foo.new 
 foo.mymethod # => 'original'
 def foo.mymethod; '하나씩 일어나는 것'; end 
 foo.mymethod # => 'singleton'
 Foo.instance_method (: mymethod) .bind (foo) .call # => 'original'
 
 # 싱글 톤 클래스에서 #instance 메소드를 호출 할 수도 있습니다. 
 class << foo; 본인; end.instance_method (: mymethod) .bind (foo) .call # => 'singleton'
4
Kelvin

사람들이 알아야 할 기호 리터럴에는 몇 가지 측면이 있습니다. 특수 기호 리터럴로 해결되는 한 가지 경우는 일반적인 기호 리터럴 구문을 사용하여 어떤 이유로 이름에 구문 오류가 발생하는 기호를 작성해야하는 경우입니다.

:'class'

심볼 보간을 수행 할 수도 있습니다. 접근 자의 맥락에서, 예를 들어 :

define_method :"#{name}=" do |value|
  instance_variable_set :"@#{name}", value
end
3
Tom

each_with_index 열거 가능한 객체 (배열, 해시 등)에 대한 메소드?

myarray = ["la", "li", "lu"]
myarray.each_with_index{|v,idx| puts "#{idx} -> #{v}"}

#result:
#0 -> la
#1 -> li
#2 -> lu

어쩌면 다른 답변보다 잘 알려져 있지만 모든 Ruby programmers :)

3
mhd
class A

  private

  def my_private_method
    puts 'private method called'
  end
end

a = A.new
a.my_private_method # Raises exception saying private method was called
a.send :my_private_method # Calls my_private_method and prints private method called'
2
Chirantan

루비에는 call/cc 메카니즘이있어 스택을 자유롭게 올리거나 내릴 수 있습니다.

간단한 예는 다음과 같습니다. 이것은 루비에서 시퀀스를 곱하는 방법은 아니지만, call/cc를 사용하여 스택을 도달하여 알고리즘을 단락시키는 방법을 보여줍니다. 이 경우 우리는 모든 숫자를 보거나 0을 볼 때까지 숫자 목록을 재귀 적으로 곱합니다 (두 가지 경우에 답을 알고 있습니다). 제로의 경우, 우리는 목록에서 임의로 깊게 빠져 나갈 수 있습니다.

#!/usr/bin/env Ruby

def rprod(k, rv, current, *nums)
  puts "#{rv} * #{current}"
  k.call(0) if current == 0 || rv == 0
  nums.empty? ? (rv * current) : rprod(k, rv * current, *nums)
end

def prod(first, *rest)
  callcc { |k| rprod(k, first, *rest) }
end

puts "Seq 1:  #{prod(1, 2, 3, 4, 5, 6)}"
puts ""
puts "Seq 2:  #{prod(1, 2, 0, 3, 4, 5, 6)}"

당신은 여기에 출력을 볼 수 있습니다 :

http://codepad.org/Oh8ddh9e

스택에서 다른 방향으로 계속 이동하는 더 복잡한 예제를 보려면 소스를 Generator 로 읽으십시오.

2
Dustin

방금 모든 답변을 읽었습니다 ... 주목할만한 누락은 할당을 파괴하는 것이 었습니다.

> (a,b),c = [[1,2],3]
=> [[1,2],3]
> a
=> 1

블록 매개 변수에도 작동합니다. 이것은 배열이 중첩되어있을 때 유용하며 각 요소는 고유 한 것을 나타냅니다. "array [0] [1]"과 같은 코드를 작성하는 대신 중첩 배열을 세분화하고 한 줄의 코드로 각 요소에 설명적인 이름을 지정할 수 있습니다.

2
Alex D
@user #=> nil (but I did't know)
@user.name rescue "Unknown"
2
haoqi

스프린트 단축키

내가 가장 좋아하는 Ruby 기능입니다. 구문은 format_string % argument

"%04d"  % 1         # => "0001"
"%0.2f" % Math::PI  # => "3.14"

배열 (format_string % array_of_arguments)

"%.2f %.3f %.4f" % ([Math::PI]*3) 
# => "3.14 3.142 3.1416"
1
iblue