代码之家  ›  专栏  ›  技术社区  ›  bastibe

如何在Ruby中只执行一次方法?有静态变量吗?

  •  5
  • bastibe  · 技术社区  · 14 年前

    我编写了一个脚本,其中包含一些方法定义,没有类和一些公共代码。其中一些方法执行一些相当耗时的shell程序。但是,这些shell程序只需要在第一次调用该方法时执行。

    现在在C语言中,我将在每个方法中声明一个静态变量,以确保这些程序只执行一次。我怎么能用红宝石做那个?

    6 回复  |  直到 14 年前
        1
  •  10
  •   Arsen7    14 年前

    Ruby中有一个成语: x ||= y .

    def something
      @something ||= calculate_something
    end
    
    private
    
    def calculate_something
      # some long process
    end
    

    但是,如果您的“长时间运行的实用程序”可能返回一个错误的值(false或nil),则该习惯用法存在问题,因为 ||= 操作员仍将对右侧进行评估。 如果期望值为假,则使用与DigitalRoss建议的方法类似的附加变量:

    def something
      return @something if @something_calculated
      @something = calculate_something
      @something_calculated = true
      return @something
    end
    

    不要试图通过先设置@something\u计算变量,然后再运行calculate\u来保存一行代码。如果您的calculate函数引发异常,您的函数将始终返回nil,并且永远不会再次调用calculate。

    更一般地说,在Ruby中,您使用实例变量。但是请注意,它们在给定对象的所有方法中都是可见的-它们不是该方法的本地方法。 如果需要由所有实例共享的变量,请在类对象和每个实例调用中定义方法。 self.class.something

    class User
      def self.something
        @something ||= calculate_something
      end
    
      def self.calculate_something
        # ....
      end
    
      def something
        self.class.something
      end
    end
    
        2
  •  4
  •   Wayne Conrad    14 年前

    “记忆宝石”在这里可能很好。当您记住一个方法时,它被调用不超过一次:

    require 'memoize'
    
    include Memoize
    
    def thing_that_should_happen_once
      puts "foo"
    end
    memoize :thing_that_should_happen_once
    
    thing_that_should_happen_once    # => foo
    thing_that_should_happen_once    # =>
    
        3
  •  1
  •   DigitalRoss    14 年前
    def f
      system "echo hello" unless @justonce
      @justonce = true
    end
    

    而且,嗯,如果您希望它在调用时运行shell命令 直到成功 ,您可以尝试:

    def f x
      @justonce = system x unless @justonce
    end
    
        4
  •  1
  •   Nicolas Blanco    14 年前
    def my_time_consuming_method
      @result ||= begin
        sleep 5
        true
      end
    end
    
    my_time_consuming_method # true after 5 secs
    my_time_consuming_method # true directly
    
        5
  •  1
  •   horseyguy    14 年前

    与此线程中的其他解决方案不同,此解决方案不要求您保留任何状态:

    获取方法以在调用后移除自身或用空方法覆盖自身:

    def hello
      puts "hello"
      define_singleton_method(:hello) {}
    end
    

    或:

    def hello
      puts "hello"
      singleton_class.send(:undef_method, __method__)
    end
    
        6
  •  0
  •   pjotrp    11 年前

    确保shell命令只运行一次是一种循环模式。我编写的一个解决方案是,在命令行上对输入文件进行校验和,并且仅在shell命令以前未运行时执行该校验和。当输入文件发生更改时,它也会再次执行。见

    https://github.com/pjotrp/once-only

    只需在shell命令前面加一次'only'即可使用它。例如。

    bowtie -t e_coli reads/e_coli_1000.fq e_coli.map

    变成

    once-only bowtie -t e_coli reads/e_coli_1000.fq e_coli.map

    对于PBS,添加--PBS开关。