天道酬勤,学无止境

将 self 应用于 proc 的方法(A method that applies self to a proc)

问题

我想在Object上定义一个方法,该方法接受一个块并将接收器应用于该块。 一个实现将如下所示:

class Object
    def apply ≺ pr.call(self) end
end

2.apply{|x| x * 3} # => 6

是否已经有一种标准方法可以做到这一点,或者有一个具有类似用途的方法的知名库? 如果是这样,我不想重新发明轮子。

我经常遇到这样的情况,我有一个方法需要一个可选块,当没有块时,我想返回一些在方法中计算的return_value ,但是当有一个块时,我想返回返回值应用于块的return_value 。 现在,我有很多行,例如:

def method ..., &pr
  ...
  pr ? pr.call(return_value) : return_value
end

但我想一直写

def method ..., &pr
  ...
  pr ? return_value.apply(&pr) : return_value
end

甚至更好,稍微修改一下apply定义,

def method ..., &pr
  ...
  return_value.apply(&pr)
end
回答1

我猜Object.tap是你要找的:

"Abc".tap do |str|
  puts str
end
回答2

这与def apply; yield self; end不一样吗def apply; yield self; end def apply; yield self; end def apply; yield self; end ? – 斯廷斯拉格

@steenslag 是的。 这是。 我想以self作为接收器来实现这种效果。 – 萨瓦

你是这个意思吗?

2.instance_eval { * 3 }
# => 6

不幸的是,这行不通。 instance_eval只是简单地运行代码,就好像接收者是self 。 操作员不会假定self是接收者,所以你实际上必须这样写:

2.instance_eval { self * 3 }
# => 6

但是,作为概念证明,这是可能的:

Numeric.send(:define_method, :plus) { |x| self + x }
2.instance_eval { plus 3 }
# => 5
回答3

(Aftwer 阅读 OP 的编辑)AFAIK 写这个的规范方法是:

def purpose(*args)  #no &bl or &pr
  res = 42 #huge calculation
  return res unless block_given?
  yield res
end

p purpose(1,2)
purpose{|n| puts "from the block: #{n}"}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 多重处理:如何在类中定义的函数上使用Pool.map?(Multiprocessing: How to use Pool.map on a function defined in a class?)
    问题 当我运行类似的东西时: from multiprocessing import Pool p = Pool(5) def f(x): return x*x p.map(f, [1,2,3]) 它工作正常。 但是,将其作为类的函数: class calculate(object): def run(self): def f(x): return x*x p = Pool() return p.map(f, [1,2,3]) cl = calculate() print cl.run() 给我以下错误: Exception in thread Thread-1: Traceback (most recent call last): File "/sw/lib/python2.6/threading.py", line 532, in __bootstrap_inner self.run() File "/sw/lib/python2.6/threading.py", line 484, in run self.__target(*self.__args, **self.__kwargs) File "/sw/lib/python2.6/multiprocessing/pool.py", line 225, in _handle_tasks put(task)
  • to_proc方法是什么意思?(What does to_proc method mean?)
    问题 我正在学习Rails并遵循此主题。 我陷入to_proc方法。 我仅将符号视为字符串的替代方法(它们类似于字符串,但在内存方面更便宜)。 如果我还有其他缺少的符号,请告诉我。 请以简单的方式说明to_proc含义及其用途。 回答1 某些方法占用一个块,这种模式经常出现在一个块上: {|x| x.foo} 人们想以一种更简洁的方式写出来。 为此,他们使用以下各项的组合:符号,方法Symbol#to_proc ,隐式类转换和&运算符。 如果在参数位置将&放在Proc实例的前面,它将被解释为一个块。 如果将Proc实例之外的其他内容与& ,则隐式类转换将尝试使用在该对象上定义的to_proc方法(如果有)将其转换为Proc实例。 在Symbol实例的情况下, to_proc以这种方式工作: :foo.to_proc # => ->x{x.foo} 例如,假设您编写: bar(&:foo) &运算符与不是Proc实例的:foo结合使用,因此隐式类Symbol#to_proc转换对其应用Symbol#to_proc ,从而得到->x{x.foo} 。 &现在适用于此,并被解释为一个块,它给出: bar{|x| x.foo} 回答2 解释此问题的最简单方法是使用一些示例。 (1..3).collect(&:to_s) #=> ["1", "2", "3"] 是相同的: (1..3)
  • map(&:name)在Ruby中是什么意思?(What does map(&:name) mean in Ruby?)
    问题 我在RailsCast中找到了以下代码: def tag_names @tag_names || tags.map(&:name).join(' ') end 什么是(&:name)在map(&:name)是什么意思? 回答1 这是tags.map(&:name.to_proc).join(' ')的简写 如果foo是具有to_proc方法的对象,则可以将其作为&foo传递给方法,该方法将调用foo.to_proc并将其用作方法的块。 Symbol#to_proc方法最初是由ActiveSupport添加的,但已集成到Ruby 1.8.7中。 这是它的实现: class Symbol def to_proc Proc.new do |obj, *args| obj.send self, *args end end end 回答2 许多人不知道的另一个很酷的速记是 array.each(&method(:foo)) 这是的简写 array.each { |element| foo(element) } 通过调用method(:foo)我们从self那里获取了一个Method对象,该对象代表其foo方法,并使用&表示它具有to_proc方法,可将其转换为Proc 。 当您想做无指向性的样式时,这非常有用。 一个示例是检查数组中是否有任何与字符串"foo"相等的字符串。 有常规方法
  • Ruby:将proc转换为lambda吗?(Ruby: convert proc to lambda?)
    问题 是否可以将proc风味的Proc转换为lambda风味的Proc? 有点惊讶,这至少在1.9.2中不起作用: my_proc = proc {|x| x} my_lambda = lambda &p my_lambda.lambda? # => false! 回答1 要追踪这个问题有些棘手。 在寻找Proc#lambda的文档? 对于1.9,关于proc和lamdba的区别进行了相当长的讨论。 结果是, lambda强制使用了正确数量的参数,而proc没有。 从该文档中,此示例显示了将proc转换为lambda的唯一方法: 即使给出了非lambda Proc对象, define_method始终定义没有技巧的方法。 这是不保留技巧的唯一例外。 class C define_method(:e, &proc {}) end C.new.e(1,2) => ArgumentError C.new.method(:e).to_proc.lambda? => true 如果要避免污染任何类,可以只在匿名对象上定义单例方法,以将proc强制为lambda : def convert_to_lambda &block obj = Object.new obj.define_singleton_method(:_, &block) return obj.method(:_).to_proc
  • 将特定对象的方法作为 Tcl 中的输入参数传递(Pass a method of a specific object as an input argument in Tcl)
    问题 我正在编写一个 EDA 实用程序,依赖于符合 TCL 8.6 的 API。 我的挑战如下: 我的实用程序在数据库中的晶体管模型上运行,并使用 EDA 供应商的 TCL API 命令进行一些分析。 我可以将 TCL 过程名称/指针传递给 TCL 命令,并且分析将依赖于我的代码,而不是 EDA 供应商的代码。 内部编写的 proc 接受一个指向 EDA 供应商数据库中特定晶体管实例的指针作为参数。 现在,EDA 供应商允许使用 TCL 8.6,这意味着我想要传递而不是全局 proc 名称或命名空间 proc 名称,即特定对象名称的名称/指针。 我怎么做? 在代码示例中: oo:class create foo { constructor {} { variable numy 2 } method fooshta { mos_pointer } { puts "now in mosy [get name $mos_pointer ]" } destructor {} } foo create bar analyse_tx -proc < how do I refer to bar's method fooshta?> 在非 OOP 上下文中,代码如下所示: proc fooshta { mos_pointer } { puts "now in mosy [get name $mos
  • 在没有/ proc / self / exe的情况下查找当前可执行文件的路径(Finding current executable's path without /proc/self/exe)
    问题 在我看来,Linux可以通过/ proc / self / exe轻松实现。 但是我想知道是否有一种方便的方法可以通过跨平台接口在C / C ++中找到当前应用程序的目录。 我已经看到一些项目与argv [0]混为一谈,但它似乎并不完全可靠。 例如,如果您必须支持没有/ proc /的Mac OS X,您会怎么做? 使用#ifdefs隔离特定于平台的代码(例如,NSBundle)? 还是尝试从argv [0],$ PATH和诸如此类的东西推断出可执行文件的路径,冒着在边缘情况下发现错误的风险? 回答1 一些特定于OS的界面: Mac OS X:_NSGetExecutablePath()(man 3 dyld) Linux:readlink / proc / self / exe Solaris:getexecname() FreeBSD:sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1 FreeBSD如果具有procfs: readlink /proc/curproc/file (默认情况下,FreeBSD没有procfs) NetBSD: readlink /proc/curproc/exe DragonFly BSD: readlink /proc/curproc/file Windows: hModule = NULL
  • 如何恢复传递给multiprocessing.Process的函数的返回值?(How can I recover the return value of a function passed to multiprocessing.Process?)
    问题 在下面的示例代码中,我想恢复函数worker的返回值。 我该怎么做呢? 此值存储在哪里? 示例代码: import multiprocessing def worker(procnum): '''worker function''' print str(procnum) + ' represent!' return procnum if __name__ == '__main__': jobs = [] for i in range(5): p = multiprocessing.Process(target=worker, args=(i,)) jobs.append(p) p.start() for proc in jobs: proc.join() print jobs 输出: 0 represent! 1 represent! 2 represent! 3 represent! 4 represent! [<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>] 我似乎无法找到存储在对象的相关属性jobs 。 回答1
  • 影响大量云服务厂商的严重漏洞:runC容器逃逸漏洞分析(CVE-2019-5736)
    41yf1sh 嘶吼专业版 一、概述以下漏洞研究的灵感来源于35C3 CTF的namespaces任务,由_tsuro创建。在进行这一挑战的过程中,我们发现,从安全角度来看,要创建基于命名空间的沙箱并通过外部进程加入是一项非常具有挑战性的任务。我们在CTF比赛结束后,发现Docker具有“docker exec”功能(实际上是由opencontainers的runc实现的)具有类似的模型,于是我们决定挑战这种漏洞实现。二、目标及结果我们的目标是在默认配置或加固后配置下的Docker容器内部攻陷宿主机环境(例如:获得有限的功能和系统调用可用性)。我们考虑了以下两个***维度:1、恶意Docker镜像;2、容器内的恶意进程(例如:攻陷以root身份运行的Docker化服务)。最终的结果,我们已经在宿主机上实现了完整意义的代码执行,具有所有功能(获得管理员“root”访问权限),该过程可以由以下任一方式触发:1、在被攻陷的Docker容器上,从宿主机运行“docker exec”;2、启动恶意Docker镜像。该漏洞被分配CVE编号CVE-2019-5736,并在这里正式公布:https://seclists.org/oss-sec/2019/q1/119三、默认Docker安全设置尽管Docker并没有作为沙盒软件发行,但它的默认设置会保护宿主机资源不被容器内的进程访问
  • 如何恢复传递给 multiprocessing.Process 的函数的返回值?(How can I recover the return value of a function passed to multiprocessing.Process?)
    问题 在下面的示例代码中,我想恢复函数worker的返回值。 我该怎么做呢? 这个值存储在哪里? 示例代码: import multiprocessing def worker(procnum): '''worker function''' print str(procnum) + ' represent!' return procnum if __name__ == '__main__': jobs = [] for i in range(5): p = multiprocessing.Process(target=worker, args=(i,)) jobs.append(p) p.start() for proc in jobs: proc.join() print jobs 输出: 0 represent! 1 represent! 2 represent! 3 represent! 4 represent! [<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>] 我似乎无法在存储在jobs的对象中找到相关属性。 回答1
  • [源码解析] 并行分布式任务队列 Celery 之 多进程模型
    Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度。因为 Celery 通过多进程来提高执行效率,所以本文将带领大家初步了解 Celery 之 多进程架构和模型。[源码解析] 并行分布式任务队列 Celery 之 多进程模型目录[源码解析] 并行分布式任务队列 Celery 之 多进程模型3.1 实例化3.2 建立通讯机制 queues3.3 进程池基类构造方法3.5 配置file 到 queue 的关系3.6 AsynPool 总体结果3.2.1 _SimpleQueue3.2.2 Pipe3.2.3 Connection3.3.1.1 子进程工作代码3.3.1.2 子进程抽象封装 --- WorkerProcess3.3.1.3 fork 过程3.3.1.2.1 WorkerProcess 具体执行3.3.1.2.2 基类 BaseProcess3.3.1.2.3 加入进程列表3.3.1 建立子进程3.4.2 辅助管理 Supervisor3.3.3 给子进程分配任务 ---- TaskHandler3.4.3 处理子进程返回 --- ResultHandler2.1 进程池初始化2.2 进程池启动 start1.1 bootsteps0x00 摘要0x01 Consumer 组件 Pool bootstep0x02
  • 子流程命令的实时输出(live output from subprocess command)
    问题 我正在使用python脚本作为流体力学代码的驱动程序。 当需要运行模拟时,我使用subprocess.Popen运行代码,将stdout和stderr的输出收集到subprocess.PIPE ---然后,我可以打印(并保存到日志文件中)输出信息,并检查是否有任何错误。 问题是,我不知道代码是如何进行的。 如果我直接从命令行运行它,它会给我输出有关它在什么迭代,什么时间,下一个时间步长等的输出。 有没有办法既存储输出(用于日志记录和错误检查),又产生实时流输出? 我的代码的相关部分: ret_val = subprocess.Popen( run_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True ) output, errors = ret_val.communicate() log_file.write(output) print output if( ret_val.returncode ): print "RUN failed\n\n%s\n\n" % (errors) success = False if( errors ): log_file.write("\n\n%s\n\n" % errors) 最初,我是通过tee run_command ,以便将副本直接发送到日志文件
  • POSIX API调用以列出进程中运行的所有pthread(POSIX API call to list all the pthreads running in a process)
    问题 我在POSIX / Linux环境中有一个多线程应用程序-我无法控制创建pthread的代码。 在某个时候,进程(pthread的所有者)接收到信号。 该信号的处理程序应中止,取消或停止所有pthread,并记录正在运行的pthread数。 我的问题是我找不到如何列出正在运行的所有pthread。 回答1 似乎没有任何可移植的方式枚举进程中的线程。 Linux具有pthread_kill_other_threads_np ,它看起来像是原始的纯用户级pthreads实现的遗留物,该实现可能不如今天所述。 它不会告诉您有多少个线程。 通过查看/proc/self (或者对于其他进程,是/proc/123 ),可以获得有关进程的大量信息。 尽管许多unice都有一个具有该名称的文件或目录,但是布局是完全不同的,因此任何使用/proc代码都是特定于Linux的。 /proc的Documentation/filesystems/proc.txt位于内核源代码的Documentation/filesystems/proc.txt中。 特别是, /proc/self/task对每个线程都有一个子目录。 子目录的名称是LWP id。 不幸的是,[1] [2] [3]似乎没有一种方法可以将LWP ID与pthread ID关联起来(但是如果您使用它,可以将自己的线程ID与gettid(2)
  • Ruby on Rails 3:通过Rails将数据流传输到客户端(Ruby on Rails 3: Streaming data through Rails to client)
    问题 我正在研究与RackSpace云文件(类似于Amazon S3,但缺少一些功能)进行通信的Ruby on Rails应用程序。 由于缺乏按对象访问权限和查询字符串身份验证的可用性,必须通过应用程序来介导对用户的下载。 在Rails 2.3中,看起来您可以动态构建一个响应,如下所示: # Streams about 180 MB of generated data to the browser. render :text => proc { |response, output| 10_000_000.times do |i| output.write("This is line #{i}\n") end } (来自http://api.rubyonrails.org/classes/ActionController/Base.html#M000464) 而不是10_000_000.times...我可以在其中转储我的cloudfiles流生成代码。 麻烦的是,这是我在Rails 3中尝试使用此技术时得到的输出。 #<Proc:0x000000010989a6e8@/Users/jderiksen/lt/lt-uber/site/app/controllers/prospect_uploads_controller.rb:75> 看起来proc对象的call方法可能没有被调用?
  • Delphi:如何在虚方法上调用继承的继承祖先?(Delphi: How to call inherited inherited ancestor on a virtual method?)
    问题 我覆盖了一个虚方法,我想调用继承的。 但是我不想调用直系祖先,我想调用之前的那个。 TObject TDatabaseObject TADODatabaseObject <---call this guy TCustomer <---skip this guy TVIP <---from this guy 我尝试将self为祖先,并在其上调用该方法,但导致递归堆栈溢出: procedure TVip.SetProperties(doc: IXMLDOMDocument); begin TADODatabaseObject(Self).SetProperties(doc); //skip over TCustomer ancestor ... end; 我尝试添加inherited关键字,但不能编译: procedure TVip.SetProperties(doc: IXMLDOMDocument); begin inherited TADODatabaseObject(Self).SetProperties(doc); //skip over TCustomer ancestor ... end; 可能的? 回答1 你不能以常规语言的方式,因为这会破坏语言的面向对象方面。 你可以摆弄指针和聪明的演员来做到这一点,但在开始回答之前:这真的是你想要的吗? 正如其他人提到的
  • Ruby中的proc和lambda有什么区别?(What's the difference between a proc and a lambda in Ruby?)
    问题 您什么时候会使用一个而不是另一个? 回答1 一种区别是它们处理参数的方式。 使用proc {}和Proc.new {}创建proc是等效的。 但是,使用lambda {}为您提供了一个过程,可以检查传递给它的参数数量。 来自ri Kernel#lambda : 与Proc.new等效,除了生成的Proc对象检查调用时传递的参数数量。 一个例子: p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28@(irb):1> p.call 1, 2 # => 5 p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass p.call 1, 2, 3 # => 5 l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c@(irb):5 (lambda)> l.call 1, 2 # => 5 l.call 1 # => ArgumentError: wrong number of arguments (1 for 2) l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2) 此外,正如Ken所指出的那样
  • Ruby Object 中是否有将自身传递给块或过程的方法?(Is there a method in Ruby Object to pass itself to a block or proc?)
    问题 我认为在 Ruby 中有这样的东西是很自然的: class Object def yield_self yield(self) end end 是否存在这样的方法? (我还没有找到。)有没有其他人认为拥有它会很好? 回答1 yield_self已于一个月前添加到 ruby​​ 核心,截至 2017 年 6 月。 https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/58528 它在修订号 58528 之后的 ruby​​ 2.5.0 中,尽管我还不确定如何获得该代码。 也许如果有人知道如何编辑这个答案 回答2 我不明白你为什么想要复杂的: Object.new.yield_self do |foo| ... end 当以下几乎完全等效时: foo = Object.new ... 回答3 确实有tap方法几乎可以完全满足您的要求: x = [].tap do |array| array << 'foo' array << 9 end p x #=> ["foo", 9] 正如 Rob Davis 所指出的, tap和您的方法之间存在微妙但重要的区别。 tap的返回值是接收者(即我例子中的匿名数组),而你的方法的返回值是块的返回值。 您可以在 tap 方法的源代码中看到这一点: VALUE rb
  • 将模块“子进程”与超时一起使用(Using module 'subprocess' with timeout)
    问题 这是运行任意命令以返回其stdout数据或在非零退出代码上引发异常的Python代码: proc = subprocess.Popen( cmd, stderr=subprocess.STDOUT, # Merge stdout and stderr stdout=subprocess.PIPE, shell=True) communicate用于等待进程退出: stdoutdata, stderrdata = proc.communicate() subprocess进程模块不支持超时-杀死运行时间超过X秒的进程的能力-因此, communicate可能要花很长时间才能运行。 在打算在Windows和Linux上运行的Python程序中,实现超时的最简单方法是什么? 回答1 在Python 3.3+中: from subprocess import STDOUT, check_output output = check_output(cmd, stderr=STDOUT, timeout=seconds) output是一个字节字符串,其中包含命令的合并标准输出,标准错误数据。 与proc.communicate()方法不同, proc.communicate()在问题文本中指定的非零退出状态下引发CalledProcessError 。 我删除了shell
  • 可以在Ruby中为map(&:method)语法提供参数吗?(Can you supply arguments to the map(&:method) syntax in Ruby?)
    问题 您可能熟悉以下Ruby速记( a是一个数组): a.map(&:method) 例如,在irb中尝试以下操作: >> a=[:a, 'a', 1, 1.0] => [:a, "a", 1, 1.0] >> a.map(&:class) => [Symbol, String, Fixnum, Float] 语法a.map(&:class)是a.map {|x| x.class}的简写。 a.map {|x| x.class} 。 在“ Ruby中的map(&:name)意味着什么?”中阅读有关此语法的更多信息。 通过&:class语法,您将为每个数组元素创建一个方法调用class 。 我的问题是:您可以为方法调用提供参数吗? 如果是这样,怎么办? 例如,如何转换以下语法 a = [1,3,5,7,9] a.map {|x| x + 2} 到&:语法? 我不建议&:语法更好。 我仅对将&:语法与参数一起使用的机制感兴趣。 我假设您知道+是Integer类的方法。 您可以在irb中尝试以下操作: >> a=1 => 1 >> a+(1) => 2 >> a.send(:+, 1) => 2 回答1 您可以在Symbol上创建一个简单的补丁,如下所示: class Symbol def with(*args, &block) ->(caller, *rest) { caller
  • 将方法传递给迭代器方法时发生了什么(what happened when pass a method to iterator method)
    问题 众所周知,wo可以通过&:前缀将方法传递给迭代器方法。 例如: ["a", "b"].map(&:upcase) #=> ["A", "B"] def rettwo 2 end ["a", "b"].map(&:rettwo) #=> [2, 2] 这是问题所在,当我编写一个方法时,将一个带有&:前缀的方法传递给它,我收到一条错误消息:“ ArgumentError:未指定接收者”。 让我显示代码: def a_simple_method &proc puts proc.class # it shows `Proc` proc.call end def a_iterator_method puts yield end a_simple_method &:rettwo #=> ArgumentError: no receiver given a_iterator_method &:rettwo #=> ArgumentError: no receiver given 我缺少什么,像Array方法的map如何处理它 回答1 这是有效的方法。 解释如下。 class String def rettwo self + self end end def a_simple_method &proc proc.call('a') end def a_iterator_method
  • Ruby 的代码块是否与 C# 的 lambda 表达式相同?(Is Ruby's code block same as C#'s lambda expression?)
    问题 这两者本质上是一回事吗? 他们看起来和我非常相似。 lambda 表达式是否从 Ruby 借用了它的想法? 回答1 Ruby 实际上有 4 个非常相似的结构 街区 块背后的想法是一种实现真正轻量级策略模式的方法。 一个块将在函数上定义一个协程,函数可以使用 yield 关键字将控制委托给它。 我们用块只是一切的宝石,其中包括几乎所有的循环结构或任何你会使用using在C#。 块外的任何东西都在块的范围内,但反之则不然,除了在块内返回将返回外部作用域。 他们看起来像这样 def foo yield 'called foo' end #usage foo {|msg| puts msg} #idiomatic for one liners foo do |msg| #idiomatic for multiline blocks puts msg end 进程 proc 基本上是获取一个块并将其作为参数传递。 一个非常有趣的用法是你可以传递一个 proc 来代替另一种方法中的块。 Ruby 有一个特殊的 proc 强制转换字符是 &,还有一个特殊规则,如果方法签名中的最后一个参数以 & 开头,它将是方法调用块的 proc 表示。 最后,有一个名为block_given?的内置方法block_given? ,如果当前方法定义了块,则返回 true。 看起来像这样 def foo(