标签归档:ruby

从Ruby学习Python;异同

问题:从Ruby学习Python;异同

我非常了解Ruby。我认为目前可能需要学习Python。对于既了解这两个概念的人,两者之间哪些概念相似,又有什么不同?

我正在寻找与我为《面向JavaScripters的学习Lua》写的入门读物相似的列表:诸如空格含义和循环构造之类的简单内容;nilPython中的名称,以及哪些值被认为是“真实的”;是惯用的使用相当于mapeach,或者是咕哝 somethingaboutlistcomprehensions MUMBLE常态?

如果我得到各种各样的答案,我很乐意将它们汇总到社区Wiki中。否则,大家可以互相搏斗,尝试创建一个真正的综合清单。

编辑:明确地说,我的目标是“适当的”和惯用的Python。如果有Python的等价物inject,但没有人使用它,因为有一种更好/不同的方法来实现迭代列表和沿途累积结果的通用功能,我想知道您的工作方式。也许我会用一个共同的目标列表来更新这个问题,这些目标是如何在Ruby中实现的,并询问在Python中等效的目标。

I know Ruby very well. I believe that I may need to learn Python presently. For those who know both, what concepts are similar between the two, and what are different?

I’m looking for a list similar to a primer I wrote for Learning Lua for JavaScripters: simple things like whitespace significance and looping constructs; the name of nil in Python, and what values are considered “truthy”; is it idiomatic to use the equivalent of map and each, or are mumble somethingaboutlistcomprehensions mumble the norm?

If I get a good variety of answers I’m happy to aggregate them into a community wiki. Or else you all can fight and crib from each other to try to create the one true comprehensive list.

Edit: To be clear, my goal is “proper” and idiomatic Python. If there is a Python equivalent of inject, but nobody uses it because there is a better/different way to achieve the common functionality of iterating a list and accumulating a result along the way, I want to know how you do things. Perhaps I’ll update this question with a list of common goals, how you achieve them in Ruby, and ask what the equivalent is in Python.


回答 0

这是我的一些主要区别:

  1. Ruby有块;Python没有。

  2. Python具有功能;Ruby没有。在Python中,您可以采用任何函数或方法并将其传递给另一个函数。在Ruby中,一切都是方法,不能直接传递方法。相反,您必须将它们包装在Proc中才能通过。

  3. Ruby和Python都支持闭包,但是方式不同。在Python中,您可以在另一个函数中定义一个函数。内部函数对外部函数的变量具有读访问权限,但对写函数没有访问权限。在Ruby中,您可以使用块定义闭包。闭包对外部作用域的变量具有完全的读取和写入访问权限。

  4. Python具有列表表达能力,非常具有表现力。例如,如果您有一个数字列表,则可以写

    [x*x for x in values if x > 15]

    要获得所有大于15的平方的新列表,在Ruby中,您必须编写以下代码:

    values.select {|v| v > 15}.map {|v| v * v}

    Ruby代码并不那么紧凑。由于它首先将values数组转换为包含值大于15的较短的中间数组,因此效率也不高。然后,它获取中间数组并生成包含中间平方的最终数组。然后将中间数组扔掉。因此,Ruby在计算过程中最终在内存中存储了3个数组。Python仅需要输入列表和结果列表。

    Python还提供了类似的地图理解。

  5. Python支持元组;露比没有 在Ruby中,您必须使用数组来模拟元组。

  6. Ruby支持switch / case语句;Python没有。

  7. Ruby支持标准的expr ? val1 : val2三元运算符。Python没有。

  8. Ruby仅支持单继承。如果您需要模拟多重继承,则可以定义模块并使用混入将模块方法拉入类。Python支持多重继承,而不是模块混合。

  9. Python仅支持单行lambda函数。Ruby块是lambda函数的一种/种类,可以任意大。因此,Ruby代码通常以比Python代码更实用的方式编写。例如,要遍历Ruby中的列表,通常

    collection.each do |value|
      ...
    end

    该块的工作原理非常类似于传递给的函数collection.each。如果要在Python中执行相同的操作,则必须定义一个命名的内部函数,然后将其传递给每个方法的集合(如果列表支持此方法):

    def some_operation(value):
      ...
    
    collection.each(some_operation)

    那不是很好。因此,通常在Python中使用以下非功能性方法:

    for value in collection:
      ...
  10. 两种语言之间以安全的方式使用资源是完全不同的。在这里,问题在于您想要分配一些资源(打开文件,获取数据库游标等),对其进行一些任意操作,然后即使发生异常也以安全的方式关闭它。

    在Ruby中,由于块非常易于使用(请参阅#9),因此通常将这种模式编码为一种方法,该方法采用块来对资源执行任意操作。

    在Python中,为任意动作传递函数会比较麻烦,因为您必须编写一个命名的内部函数(请参阅#9)。相反,Python使用with语句来安全地处理资源。请参阅如何正确清理Python对象?更多细节。

Here are some key differences to me:

  1. Ruby has blocks; Python does not.

  2. Python has functions; Ruby does not. In Python, you can take any function or method and pass it to another function. In Ruby, everything is a method, and methods can’t be directly passed. Instead, you have to wrap them in Proc’s to pass them.

  3. Ruby and Python both support closures, but in different ways. In Python, you can define a function inside another function. The inner function has read access to variables from the outer function, but not write access. In Ruby, you define closures using blocks. The closures have full read and write access to variables from the outer scope.

  4. Python has list comprehensions, which are pretty expressive. For example, if you have a list of numbers, you can write

    [x*x for x in values if x > 15]
    

    to get a new list of the squares of all values greater than 15. In Ruby, you’d have to write the following:

    values.select {|v| v > 15}.map {|v| v * v}
    

    The Ruby code doesn’t feel as compact. It’s also not as efficient since it first converts the values array into a shorter intermediate array containing the values greater than 15. Then, it takes the intermediate array and generates a final array containing the squares of the intermediates. The intermediate array is then thrown out. So, Ruby ends up with 3 arrays in memory during the computation; Python only needs the input list and the resulting list.

    Python also supplies similar map comprehensions.

  5. Python supports tuples; Ruby doesn’t. In Ruby, you have to use arrays to simulate tuples.

  6. Ruby supports switch/case statements; Python does not.

  7. Ruby supports the standard expr ? val1 : val2 ternary operator; Python does not.

  8. Ruby supports only single inheritance. If you need to mimic multiple inheritance, you can define modules and use mix-ins to pull the module methods into classes. Python supports multiple inheritance rather than module mix-ins.

  9. Python supports only single-line lambda functions. Ruby blocks, which are kind of/sort of lambda functions, can be arbitrarily big. Because of this, Ruby code is typically written in a more functional style than Python code. For example, to loop over a list in Ruby, you typically do

    collection.each do |value|
      ...
    end
    

    The block works very much like a function being passed to collection.each. If you were to do the same thing in Python, you’d have to define a named inner function and then pass that to the collection each method (if list supported this method):

    def some_operation(value):
      ...
    
    collection.each(some_operation)
    

    That doesn’t flow very nicely. So, typically the following non-functional approach would be used in Python:

    for value in collection:
      ...
    
  10. Using resources in a safe way is quite different between the two languages. Here, the problem is that you want to allocate some resource (open a file, obtain a database cursor, etc), perform some arbitrary operation on it, and then close it in a safe manner even if an exception occurs.

    In Ruby, because blocks are so easy to use (see #9), you would typically code this pattern as a method that takes a block for the arbitrary operation to perform on the resource.

    In Python, passing in a function for the arbitrary action is a little clunkier since you have to write a named, inner function (see #9). Instead, Python uses a with statement for safe resource handling. See How do I correctly clean up a Python object? for more details.


回答 1

经过6年的Ruby,我花了几个月的时间学习Python。对于这两种语言,确实没有很好的比较,所以我决定亲自写一个。现在,它主要关注的函数式编程,但既然你提到了Ruby的inject方法,我猜我们是在相同的波长。

我希望这会有所帮助:Python的“丑陋”

有几点可以使您朝正确的方向前进:

  • 您在Ruby中使用的所有函数式编程优势都在Python中,并且更加容易。例如,您可以完全按预期映射功能:

    def f(x):
        return x + 1
    
    map(f, [1, 2, 3]) # => [2, 3, 4]
  • Python没有类似的方法each。由于您仅each用于副作用,因此Python中的等效方法是for循环:

    for n in [1, 2, 3]:
        print n
  • 当a)您必须同时处理函数和对象集合,以及b)需要使用多个索引进行迭代时,列表的理解非常有用。例如,要查找字符串中的所有回文(假设您有一个p()对回文返回true 的函数),那么您只需要一个列表即可:

    s = 'string-with-palindromes-like-abbalabba'
    l = len(s)
    [s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]

I’ve just spent a couple of months learning Python after 6 years of Ruby. There really was no great comparison out there for the two languages, so I decided to man up and write one myself. Now, it is mainly concerned with functional programming, but since you mention Ruby’s inject method, I’m guessing we’re on the same wavelength.

I hope this helps: The ‘ugliness’ of Python

A couple of points that will get you moving in the right direction:

  • All the functional programming goodness you use in Ruby is in Python, and it’s even easier. For example, you can map over functions exactly as you’d expect:

    def f(x):
        return x + 1
    
    map(f, [1, 2, 3]) # => [2, 3, 4]
    
  • Python doesn’t have a method that acts like each. Since you only use each for side effects, the equivalent in Python is the for loop:

    for n in [1, 2, 3]:
        print n
    
  • List comprehensions are great when a) you have to deal with functions and object collections together and b) when you need to iterate using multiple indexes. For example, to find all the palindromes in a string (assuming you have a function p() that returns true for palindromes), all you need is a single list comprehension:

    s = 'string-with-palindromes-like-abbalabba'
    l = len(s)
    [s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]
    

回答 2

我的建议:不要尝试去学习差异。了解如何使用Python解决问题。就像有一个针对每种问题的Ruby方法(考虑到语言的局限性和优势,这种方法非常有效),也有一种针对该问题的Python方法。他们都是不同的。为了充分利用每种语言,您确实应该学习语言本身,而不仅仅是学习一种语言到另一种语言的“翻译”。

如此说来,两者之间的区别将帮助您更快地适应和对Python程序进行一次修改。刚开始写作就很好。但是尝试从其他项目中了解架构和设计决策背后的原因,而不是语言语义背后的原因…

My suggestion: Don’t try to learn the differences. Learn how to approach the problem in Python. Just like there’s a Ruby approach to each problem (that works very well givin the limitations and strengths of the language), there’s a Python approach to the problem. they are both different. To get the best out of each language, you really should learn the language itself, and not just the “translation” from one to the other.

Now, with that said, the difference will help you adapt faster and make 1 off modifications to a Python program. And that’s fine for a start to get writing. But try to learn from other projects the why behind the architecture and design decisions rather than the how behind the semantics of the language…


回答 3

我几乎不了解Ruby,但是这里有一些关于您提到的内容的要点:

  • nil,表示缺少值的值将是None(请注意,您可以像x is None或那样检查它x is not None,而不用==-或通过强制布尔值检查它,请参阅下一点)。
  • None零式的数字(00.00j(复数))和空集([]{}set(),空字符串"",等等)被认为falsy,一切被认为是truthy。
  • 对于副作用,(for-)显式循环。要生成一堆没有副作用的新东西,请使用列表推导(或它们的亲戚-懒惰的一次性迭代器的生成器表达式,所述集合的dict / set推导)。

关于循环:您具有for,它以可迭代(!不计算在内)进行操作,而while,它可以实现预期的效果。得益于对迭代器的广泛支持,源代码的功能要强大得多。不仅几乎所有可以成为迭代器而不是列表的东西都是迭代器(至少在Python 3中-在Python 2中,您同时拥有了这两个,默认情况下,列表是一个列表)。有很多使用迭代器的工具- zip并行迭代任意数量的可迭代对象,enumerate为您(index, item)(在任何可迭代对象上,不仅在列表中)提供切片,甚至切片可迭代对象(可能很大或无限)!我发现这些使许多循环任务变得更加简单。不用说,它们可以很好地与列表推导,生成器表达式等集成。

I know little Ruby, but here are a few bullet points about the things you mentioned:

  • nil, the value indicating lack of a value, would be None (note that you check for it like x is None or x is not None, not with == – or by coercion to boolean, see next point).
  • None, zero-esque numbers (0, 0.0, 0j (complex number)) and empty collections ([], {}, set(), the empty string "", etc.) are considered falsy, everything else is considered truthy.
  • For side effects, (for-)loop explicitly. For generating a new bunch of stuff without side-effects, use list comprehensions (or their relatives – generator expressions for lazy one-time iterators, dict/set comprehensions for the said collections).

Concerning looping: You have for, which operates on an iterable(! no counting), and while, which does what you would expect. The fromer is far more powerful, thanks to the extensive support for iterators. Not only nearly everything that can be an iterator instead of a list is an iterator (at least in Python 3 – in Python 2, you have both and the default is a list, sadly). The are numerous tools for working with iterators – zip iterates any number of iterables in parallel, enumerate gives you (index, item) (on any iterable, not just on lists), even slicing abritary (possibly large or infinite) iterables! I found that these make many many looping tasks much simpler. Needless to say, they integrate just fine with list comprehensions, generator expressions, etc.


回答 4

在Ruby中,实例变量和方法是完全不相关的,除非您将它们与attr_accessor或类似的东西显式关联。

在Python中,方法只是一种特殊的属性类:一种可执行的属性。

因此,例如:

>>> class foo:
...     x = 5
...     def y(): pass
... 
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>

这种差异具有很多含义,例如,引用fx引用方法对象而不是调用它。另外,如您所见,fx默认情况下是公共的,而在Ruby中,实例变量默认情况下是私有的。

In Ruby, instance variables and methods are completely unrelated, except when you explicitly relate them with attr_accessor or something like that.

In Python, methods are just a special class of attribute: one that is executable.

So for example:

>>> class foo:
...     x = 5
...     def y(): pass
... 
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>

That difference has a lot of implications, like for example that referring to f.x refers to the method object, rather than calling it. Also, as you can see, f.x is public by default, whereas in Ruby, instance variables are private by default.


相当于Ruby中的`if __name__ ==’__main __’`

问题:相当于Ruby中的`if __name__ ==’__main __’`

我是Ruby的新手。我正在从包含要继续单独使用的工具的模块中导入函数。在Python中,我只需执行以下操作:

def a():
    ...
def b():
    ...
if __name__ == '__main__':
    a()
    b()

这使我可以运行程序或将其导入为模块使用a()和/或b()单独使用。Ruby中的等效范例是什么?

I am new to Ruby. I’m looking to import functions from a module that contains a tool I want to continue using separately. In Python I would simply do this:

def a():
    ...
def b():
    ...
if __name__ == '__main__':
    a()
    b()

This allows me to run the program or import it as a module to use a() and/or b() separately. What’s the equivalent paradigm in Ruby?


回答 0

从我在野外看到的Ruby(当然,不是一吨)来看,这不是标准的Ruby设计模式。模块和脚本应该保持独立,因此,如果没有真正好的清洁方法,我也不会感到惊讶。

编辑: 找到了。

if __FILE__ == $0
    foo()
    bar()
end

但这绝对不常见。

From the Ruby I’ve seen out in the wild (granted, not a ton), this is not a standard Ruby design pattern. Modules and scripts are supposed to stay separate, so I wouldn’t be surprised if there isn’t really a good, clean way of doing this.

EDIT: Found it.

if __FILE__ == $0
    foo()
    bar()
end

But it’s definitely not common.


回答 1

如果堆栈跟踪为空,我们可以从左右开始执行。我不知道这是常规使用还是非常规使用,因为我进入Ruby大约一周了。

if caller.length == 0
  # do stuff
end

概念证明:

文件:test.rb

#!/usr/bin/ruby                                                                 

if caller.length == 0
  puts "Main script"
end

puts "Test"

文件:shmest.rb

#!/usr/bin/ruby -I .                                                            

require 'test.rb'

puts "Shmest"

用法:

$ ./shmest.rb 
Test
Shmest

$ ./test.rb
Main script
Test

If stack trace is empty, we can start executing to the right and left. I don’t know if that’s used conventionally or unconventionally since I’m into Ruby for about a week.

if caller.length == 0
  # do stuff
end

Proof of concept:

file: test.rb

#!/usr/bin/ruby                                                                 

if caller.length == 0
  puts "Main script"
end

puts "Test"

file: shmest.rb

#!/usr/bin/ruby -I .                                                            

require 'test.rb'

puts "Shmest"

Usage:

$ ./shmest.rb 
Test
Shmest

$ ./test.rb
Main script
Test

回答 2

if $PROGRAM_NAME == __FILE__
  foo()
  bar()
end 

Rubocop首选:

if __FILE__ == $0
    foo()
    bar()
end
if $PROGRAM_NAME == __FILE__
  foo()
  bar()
end 

is preferred by Rubocop over this:

if __FILE__ == $0
    foo()
    bar()
end

Ruby相当于virtualenv吗?

问题:Ruby相当于virtualenv吗?

是否有类似于Python实用程序virtualenv的东西?

基本上,它允许您将Python软件包安装到沙盒环境中,因此easy_install django它不会进入系统范围的site-packages目录中,而是会进入virtualenv创建的目录中。

例如:

$ virtualenv test
New python executable in test/bin/python
Installing setuptools...cd .........done.
$ cd test/
$ source bin/activate
(test)$ easy_install tvnamer
Searching for tvnamer
Best match: tvnamer 0.5.1
Processing tvnamer-0.5.1-py2.5.egg
Adding tvnamer 0.5.1 to easy-install.pth file
Installing tvnamer script to /Users/dbr/test/bin

Using /Library/Python/2.5/site-packages/tvnamer-0.5.1-py2.5.egg
Processing dependencies for tvnamer
Finished processing dependencies for tvnamer
(test)$ which tvnamer 
/Users/dbr/test/bin/tvnamer

RubyGems是否有类似的东西?

Is there something similar to the Python utility virtualenv?

Basically it allows you to install Python packages into a sandboxed environment, so easy_install django doesn’t go in your system-wide site-packages directory, it would go in the virtualenv-created directory.

For example:

$ virtualenv test
New python executable in test/bin/python
Installing setuptools...cd .........done.
$ cd test/
$ source bin/activate
(test)$ easy_install tvnamer
Searching for tvnamer
Best match: tvnamer 0.5.1
Processing tvnamer-0.5.1-py2.5.egg
Adding tvnamer 0.5.1 to easy-install.pth file
Installing tvnamer script to /Users/dbr/test/bin

Using /Library/Python/2.5/site-packages/tvnamer-0.5.1-py2.5.egg
Processing dependencies for tvnamer
Finished processing dependencies for tvnamer
(test)$ which tvnamer 
/Users/dbr/test/bin/tvnamer

Is there something like this for RubyGems?


回答 0

RVM的工作方式与virtualenv的工作方式更为接近,因为它可以让您沙盒化不同的红宝石版本及其宝石等。

RVM works closer to how virtualenv works since it lets you sandbox different ruby versions and their gems, etc.


回答 1

沙箱,RVM和rbenv都不管理应用程序的gem依赖项的版本。该工具是bundler

  • 使用Gemfile作为应用程序的依赖项声明
  • 用于bundle install将这些依赖项的显式版本安装到隔离的位置
  • 用于bundle exec运行您的应用程序

Neither sandbox, RVM, nor rbenv manage the versions of your app’s gem dependencies. The tool for that is bundler.

  • use a Gemfile as your application’s dependency declaration
  • use bundle install to install explicit versions of these dependencies into an isolated location
  • use bundle exec to run your application

回答 2

似乎没有人提到rbenv

No one seems to have mentioned rbenv.


回答 3

我想您会喜欢沙盒

I think you’ll like sandbox.


回答 4

我将提到使用Bundler进行此操作的方式(我将其与RVM一起使用-RVM用于管理红宝石和一组默认的全局宝石,Bundler则用于处理项目特定的宝石)

bundler install --binstubs --path vendor

在项目的根目录中运行此命令将安装Gemfile中列出的gems,将libs放入中./vendor./bin并且所有requires 中的所有可执行文件(如果使用bundle console或Bundler要求)将引用这些exes和libs。

为我工作。

I’ll mention the way I do this with Bundler (which I use with RVM – RVM to manage the rubies and a default set of global gems, Bundler to handle project specific gems)

bundler install --binstubs --path vendor

Running this command in the root of a project will install the gems listed from your Gemfile, put the libs in ./vendor, and any executables in ./bin and all requires (if you use bundle console or the Bundler requires) will reference these exes and libs.

Works for me.


回答 5

如果仅需要以非root用户身份安装gem,请尝试设置GEM_HOME环境变量。然后运行gem

例如:

$ export GEM_HOME=$HOME/local/gems
$ gem install rhc

If you only need to install gems as non-root, try setting the GEM_HOME environment variable. Then just run gem.

For example:

$ export GEM_HOME=$HOME/local/gems
$ gem install rhc

回答 6

我推荐direnv。它是外壳的环境切换器。

在每个提示之前,它会检查当前目录和父目录中是否存在“ .envrc”文件。如果文件存在(并已授权),则将其加载到bash子shell中,然后所有导出的变量都由direnv捕获,然后使当前shell可用。

这是如何在 ruby-install中使用direnv

+红宝石安装

将此添加到 ~/.direnvrc

use_ruby() {
  local ruby_root=$HOME/.rubies/$1
  load_prefix "$ruby_root"
  layout_ruby
}

安装ruby-install(brew install ruby-install)并安装一堆Ruby 。

ruby-install ruby 1.9.3
ruby-install ruby 2.0.0
ruby-install ruby 2.2.0

为了方便起见,然后进行几个符号链接:

ln -s .rubies/1.9 ruby-1.9.3-p*
ln -s .rubies/2.0 ruby-2.0.0
ln -s .rubies/2.2 ruby-2.2.0

最后在任何项目中.envrc

use ruby 2.0

这会将所有gem放置在项目.direnv/ruby目录下(使打开gem更加容易)。捆绑程序将放入包装二进制文件 .direnv/bin(不再bundle exec!)。

+ rbenv

也可以通过use rbenv在任何.envrc文件中添加命令来使用rbenv 。这将激活rbenv,从而将红宝石包装器放入PATH中。

请注意,不必在.bashrc或.zshrc中安装rbenv即可起作用。

+ RVM

这是我在ruby项目上使用的最复杂的.envrc:

rvm use 1.8.7
layout ruby
PATH_add .direnv/bundler-bin

rvm用于为您选择正确的红宝石版本

布局命令会自动设置一些常用的环境变量。目前仅存在红宝石布局。它的作用是设置GEM_HOME环境变量,并将它放在bin目录中。因为它取决于Ruby版本,所以请确保在“ rvm”之后调用它。由于每个ruby布局目录都有其自己的GEM_HOME,因此您无需使用rvm的gemset。

PATH_add前置并扩展给定的相对路径。在这种情况下,我使用它来将捆绑程序binstub与我自己的bin脚本隔离,bundle install --binstubs .direnv/bundler-bin

如果您想了解这些命令的确切功能,现在:cat direnv stdlib| 减

I recommend direnv. It is an environment switcher for the shell.

Before each prompt it checks for the existence of an “.envrc” file in the current and parent directories. If the file exists (and authorized), it is loaded into a bash sub-shell and all exported variables are then captured by direnv and then made available the current shell.

Here is how to use direnv with ruby-install

+ ruby-install

Add this to the ~/.direnvrc

use_ruby() {
  local ruby_root=$HOME/.rubies/$1
  load_prefix "$ruby_root"
  layout_ruby
}

Install ruby-install (brew install ruby-install) and install a bunch of rubies.

ruby-install ruby 1.9.3
ruby-install ruby 2.0.0
ruby-install ruby 2.2.0

And then make a couple of symlinks for convenience:

ln -s .rubies/1.9 ruby-1.9.3-p*
ln -s .rubies/2.0 ruby-2.0.0
ln -s .rubies/2.2 ruby-2.2.0

And finally in any project’s .envrc:

use ruby 2.0

This will put all gems under the project’s .direnv/ruby directory (makes opening gems easier). bundler will put wrapper binaries in .direnv/bin (no more bundle exec!).

+ rbenv

It’s also possible to use rbenv by adding the use rbenv command in any .envrc file. This will activate rbenv which in turn will put the ruby wrappers in the PATH.

Note that it’s not necessary to install rbenv in the .bashrc or .zshrc for this to work.

+ RVM

Here is the most complicated .envrc that I use on ruby projects:

rvm use 1.8.7
layout ruby
PATH_add .direnv/bundler-bin

rvm is used to select the right ruby version for you

layout commands automatically set some of the usual environment variables. For now only the ruby layout exists. What it does is set the GEM_HOME environment variable and it’s bin directory to your path. Because it depends on the ruby version, make sure to call it after “rvm”. Since each ruby layout directories have their own GEM_HOME, you don’t need to use rvm’s gemsets.

PATH_add prepends and expands the given relative path. In that case, I use this to segregate the bundler binstubs from my own bin scripts with bundle install --binstubs .direnv/bundler-bin

If you want to find out what those commands exactly do, for now: cat direnv stdlib | less


回答 7

Mineshaft是一个我已经从事了一段时间的项目,并将继续进行开发工作。

它提供了创建类似于virtualenv工作原理的虚拟环境的能力,并且还可以全局安装Ruby。

Mineshaft is a project that I’ve been working on for some time and am continuing development work on.

It offers the ability to both create virtual environments akin to how virtualenv works and can also install Ruby globally as well.


Ruby相当于Python的`s =“你好,%s。%s在哪里?” %(“ John”,“ Mary”)`

问题:Ruby相当于Python的`s =“你好,%s。%s在哪里?” %(“ John”,“ Mary”)`

在Python中,这种用于字符串格式化的习惯很普遍

s = "hello, %s. Where is %s?" % ("John","Mary")

Ruby中的等效功能是什么?

In Python, this idiom for string formatting is quite common

s = "hello, %s. Where is %s?" % ("John","Mary")

What is the equivalent in Ruby?


回答 0

最简单的方法是字符串插值。您可以将少量Ruby代码直接注入您的字符串中。

name1 = "John"
name2 = "Mary"
"hello, #{name1}.  Where is #{name2}?"

您也可以在Ruby中格式化字符串。

"hello, %s.  Where is %s?" % ["John", "Mary"]

请记住在此处使用方括号。Ruby没有元组,只有数组,并且使用方括号。

The easiest way is string interpolation. You can inject little pieces of Ruby code directly into your strings.

name1 = "John"
name2 = "Mary"
"hello, #{name1}.  Where is #{name2}?"

You can also do format strings in Ruby.

"hello, %s.  Where is %s?" % ["John", "Mary"]

Remember to use square brackets there. Ruby doesn’t have tuples, just arrays, and those use square brackets.


回答 1

在Ruby> 1.9中,您可以执行以下操作:

s =  'hello, %{name1}. Where is %{name2}?' % { name1: 'John', name2: 'Mary' }

查看文件

In Ruby > 1.9 you can do this:

s =  'hello, %{name1}. Where is %{name2}?' % { name1: 'John', name2: 'Mary' }

See the docs


回答 2

几乎相同的方式:

irb(main):003:0> "hello, %s. Where is %s?" % ["John","Mary"]
=> "hello, John. Where is Mary?"

Almost the same way:

irb(main):003:0> "hello, %s. Where is %s?" % ["John","Mary"]
=> "hello, John. Where is Mary?"

回答 3

其实差不多

s = "hello, %s. Where is %s?" % ["John","Mary"]

Actually almost the same

s = "hello, %s. Where is %s?" % ["John","Mary"]

Awesomo 很酷的开源项目列表

A.W.E.S.O.M.O是用各种语言编写的有趣的开放源码项目的广泛列表。

如果您有兴趣Open Source并且正在考虑加入开源开发人员社区,那么在这里您可能会找到一个适合您的项目

Subscribe

我们有一个电报频道,我们每天在那里发布新闻,宣布和我们找到的所有开源的好东西,所以订阅我们:@the_art_of_development

语言

想要添加一个有趣的项目吗?

  • 简单地说fork此存储库
  • 使用与其他项目类似的格式将项目添加到列表中
  • 打开new pull request

☝️不过,请记住,我们不接受猛犸象的屎只有具有良好文档的活动和有趣的项目才会被添加。废弃和废弃的项目将被拆除

想支持我们吗?

只需将此列表与您的朋友分享到TwitterFacebookMedium或者其他地方

许可证

awesomo通过@lk-geimfari

在法律允许的范围内,将CC0与awesomo已放弃所有版权以及与以下内容相关或相邻的权利awesomo

您应该已经收到了这项工作附带的CC0法律代码的副本。如果没有,请参见https://creativecommons.org/publicdomain/zero/1.0/

Ruby有Python没有的,反之亦然?

问题:Ruby有Python没有的,反之亦然?

关于Python与Ruby的讨论很多,我都发现它们完全无济于事,因为它们都绕开了为什么功能X吸收了语言Y或声称语言Y没有X的事实,尽管实际上确实如此。我也确切地知道为什么我偏爱Python,但这也是主观的,并且不会帮助任何人选择,因为他们在开发中的品味可能不如我。

因此,客观列出差异是很有趣的。因此,没有“ Python的lambdas很烂”。相反,请解释Ruby的lambda可以做什么,而Python则不能。没有主观性。示例代码很好!

请在一个答案中没有几个差异。并投票支持您所知道的正确和不正确(或主观)的投票。同样,语法上的差异也不是很有趣。我们知道Python用缩进来做,而Ruby用括号来做,而@在Python中被称为self。

更新:这是现在的社区Wiki,因此我们可以在此处添加较大的差异。

Ruby在类主体中有一个类引用

在Ruby中,您已经在类主体中引用了该类(自身)。在Python中,直到类构造完成后,您才可以引用该类。

一个例子:

class Kaka
  puts self
end

在这种情况下,self是类,并且此代码将打印出“ Kaka”。无法打印出类名称,也无法通过其他方式从Python中的类定义主体(外部方法定义)访问该类。

所有类在Ruby中都是可变的

这使您可以开发核心类的扩展。这是rails扩展的示例:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python(假设没有''.startswith方法):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

您可以在任何序列上使用它(不仅是字符串)。为了使用它,您应该显式导入它,例如from some_module import starts_with

Ruby具有类似Perl的脚本功能

Ruby具有一流的正则表达式,$变量,awk / perl逐行输入循环以及其他功能,使其更适合于编写小型shell脚本,这些脚本会压缩文本文件或充当其他程序的粘合代码。

Ruby具有一流的延续性

感谢callcc声明。在Python中,您可以通过各种技术来创建延续,但是该语言没有内置支持。

红宝石有块

使用“ do”语句,您可以在Ruby中创建一个多行匿名函数,该函数将作为参数传递给do前面的方法,然后从那里调用。在Python中,您可以通过传递方法或使用生成器来实现。

红宝石:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python(Ruby块对应于Python中的不同构造):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

要么

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

要么

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

有趣的是,Ruby中用于调用块的便捷性语句称为“ yield”,在Python中将创建一个生成器。

红宝石:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

尽管原理不同,但结果却非常相似。

Ruby更轻松地支持功能样式(类似管道)的编程

myList.map(&:description).reject(&:empty?).join("\n")

Python:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python具有内置的生成器(如上所述,它们像Ruby块一样使用)

Python支持该语言的生成器。在Ruby 1.8中,您可以使用generator模块,该模块使用延续从一个块中创建一个generator。或者,您可以只使用block / proc / lambda!此外,在Ruby 1.9中,光纤是并且可以用作生成器,而Enumerator类是内置的生成器4

docs.python.org包含以下生成器示例:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

将此与上面的块示例进行对比。

Python具有灵活的命名空间处理

在Ruby中,当您使用导入文件时require,该文件中定义的所有内容都将最终存储在全局命名空间中。这会导致命名空间污染。解决方案是Rubys模块。但是,如果使用模块创建命名空间,则必须使用该命名空间来访问所包含的类。

在Python中,该文件是一个模块,您可以使用导入其包含的名称from themodule import *,从而根据需要污染命名空间。但是,您也可以使用导入刚刚选择的名称,from themodule import aname, another也可以简单地使用导入import themodule名称themodule.aname。如果要在命名空间中使用更多级别,则可以有包,包是带有模块和__init__.py文件的目录。

Python具有文档字符串

文档字符串是附加到模块,函数和方法的字符串,可以在运行时自省。这有助于创建诸如help命令和自动文档之类的东西。

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Ruby的等效项类似于javadocs,并且位于方法上方而不是其中。可以使用1.9的Method#source_location 示例use在运行时从文件中检索它们。

Python具有多重继承

Ruby不会(“故意”-请访问Ruby的网站,在这里查看它是如何在Ruby中完成的)。它确实将模块概念作为一种抽象类重用。

Python具有列表/字典理解

Python:

res = [x*x for x in range(1, 10)]

红宝石:

res = (0..9).map { |x| x * x }

Python:

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

红宝石:

p = proc { |x| x * x }
(0..9).map(&p)

Python 2.7+

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

红宝石:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Python有装饰器

类似于装饰器的东西也可以在Ruby中创建,也可以说它们没有Python中的必要。

语法差异

Ruby需要使用“ end”或“}”来关闭其所有作用域,而Python仅使用空格。最近在Ruby中尝试了仅允许空格缩进http://github.com/michaeledgar/seamless

There is a lot of discussions of Python vs Ruby, and I all find them completely unhelpful, because they all turn around why feature X sucks in language Y, or that claim language Y doesn’t have X, although in fact it does. I also know exactly why I prefer Python, but that’s also subjective, and wouldn’t help anybody choosing, as they might not have the same tastes in development as I do.

It would therefore be interesting to list the differences, objectively. So no “Python’s lambdas sucks”. Instead explain what Ruby’s lambdas can do that Python’s can’t. No subjectivity. Example code is good!

Don’t have several differences in one answer, please. And vote up the ones you know are correct, and down those you know are incorrect (or are subjective). Also, differences in syntax is not interesting. We know Python does with indentation what Ruby does with brackets and ends, and that @ is called self in Python.

UPDATE: This is now a community wiki, so we can add the big differences here.

Ruby has a class reference in the class body

In Ruby you have a reference to the class (self) already in the class body. In Python you don’t have a reference to the class until after the class construction is finished.

An example:

class Kaka
  puts self
end

self in this case is the class, and this code would print out “Kaka”. There is no way to print out the class name or in other ways access the class from the class definition body in Python (outside method definitions).

All classes are mutable in Ruby

This lets you develop extensions to core classes. Here’s an example of a rails extension:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python (imagine there were no ''.startswith method):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

You could use it on any sequence (not just strings). In order to use it you should import it explicitly e.g., from some_module import starts_with.

Ruby has Perl-like scripting features

Ruby has first class regexps, $-variables, the awk/perl line by line input loop and other features that make it more suited to writing small shell scripts that munge text files or act as glue code for other programs.

Ruby has first class continuations

Thanks to the callcc statement. In Python you can create continuations by various techniques, but there is no support built in to the language.

Ruby has blocks

With the “do” statement you can create a multi-line anonymous function in Ruby, which will be passed in as an argument into the method in front of do, and called from there. In Python you would instead do this either by passing a method or with generators.

Ruby:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (Ruby blocks correspond to different constructs in Python):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

Or

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

Or

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

Interestingly, the convenience statement in Ruby for calling a block is called “yield”, which in Python will create a generator.

Ruby:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

Although the principles are different, the result is strikingly similar.

Ruby supports functional style (pipe-like) programming more easily

myList.map(&:description).reject(&:empty?).join("\n")

Python:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python has built-in generators (which are used like Ruby blocks, as noted above)

Python has support for generators in the language. In Ruby 1.8 you can use the generator module which uses continuations to create a generator from a block. Or, you could just use a block/proc/lambda! Moreover, in Ruby 1.9 Fibers are, and can be used as, generators, and the Enumerator class is a built-in generator 4

docs.python.org has this generator example:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

Contrast this with the above block examples.

Python has flexible name space handling

In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace. This causes namespace pollution. The solution to that is Rubys modules. But if you create a namespace with a module, then you have to use that namespace to access the contained classes.

In Python, the file is a module, and you can import its contained names with from themodule import *, thereby polluting the namespace if you want. But you can also import just selected names with from themodule import aname, another or you can simply import themodule and then access the names with themodule.aname. If you want more levels in your namespace you can have packages, which are directories with modules and an __init__.py file.

Python has docstrings

Docstrings are strings that are attached to modules, functions and methods and can be introspected at runtime. This helps for creating such things as the help command and automatic documentation.

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Ruby’s equivalent are similar to javadocs, and located above the method instead of within it. They can be retrieved at runtime from the files by using 1.9’s Method#source_location example use

Python has multiple inheritance

Ruby does not (“on purpose” — see Ruby’s website, see here how it’s done in Ruby). It does reuse the module concept as a type of abstract classes.

Python has list/dict comprehensions

Python:

res = [x*x for x in range(1, 10)]

Ruby:

res = (0..9).map { |x| x * x }

Python:

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Ruby:

p = proc { |x| x * x }
(0..9).map(&p)

Python 2.7+:

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

Ruby:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Python has decorators

Things similar to decorators can also be created in Ruby, and it can also be argued that they aren’t as necessary as in Python.

Syntax differences

Ruby requires “end” or “}” to close all of its scopes, while Python uses white-space only. There have been recent attempts in Ruby to allow for whitespace only indentation http://github.com/michaeledgar/seamless


回答 0

Ruby具有的概念,它们实际上是围绕一段代码的语法糖。它们是创建闭包并将其传递给可能使用也可能不使用该块的另一种方法。稍后可以通过一条yield语句调用一个块。

例如,对each方法的简单定义Array可能类似于:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

然后,您可以像这样调用它:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

Python具有匿名函数/闭包/ lambdas,但由于缺少一些有用的语法糖,因此它没有块。但是,至少有一种方法可以临时获得它。例如,请参阅此处

Ruby has the concepts of blocks, which are essentially syntactic sugar around a section of code; they are a way to create closures and pass them to another method which may or may not use the block. A block can be invoked later on through a yield statement.

For example, a simple definition of an each method on Array might be something like:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Then you can invoke this like so:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

Python has anonymous functions/closures/lambdas, but it doesn’t quite have blocks since it’s missing some of the useful syntactic sugar. However, there’s at least one way to get it in an ad-hoc fashion. See, for example, here.


回答 1

Python范例

函数是Python中的一类变量。您可以声明一个函数,将其作为对象传递,然后覆盖它:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

这是现代脚本语言的基本特征。JavaScript和Lua也这样做。Ruby并不以这种方式对待函数。给函数命名会调用它。

当然,有很多方法可以在Ruby中完成这些操作,但它们不是一流的操作。例如,您可以使用Proc.new包装函数以将其视为变量,但是它不再是函数;它是带有“调用”方法的对象。

Ruby的功能不是一流的对象

Ruby函数不是一流的对象。必须将函数包装在一个对象中以将它们传递给对象。结果对象不能像函数一样对待。不能以一流的方式分配功能;相反,必须调用其容器对象中的函数以对其进行修改。

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

Python Example

Functions are first-class variables in Python. You can declare a function, pass it around as an object, and overwrite it:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

This is a fundamental feature of modern scripting languages. JavaScript and Lua do this, too. Ruby doesn’t treat functions this way; naming a function calls it.

Of course, there are ways to do these things in Ruby, but they’re not first-class operations. For example, you can wrap a function with Proc.new to treat it as a variable–but then it’s no longer a function; it’s an object with a “call” method.

Ruby’s functions aren’t first-class objects

Ruby functions aren’t first-class objects. Functions must be wrapped in an object to pass them around; the resulting object can’t be treated like a function. Functions can’t be assigned in a first-class manner; instead, a function in its container object must be called to modify them.

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

回答 2

最终,所有答案都将在一定程度上是主观的,到目前为止发布的答案几乎证明,您无法以同样不错的方式(如果不是相似的方式)指向其他语言无法实现的任何功能,因为这两种语言都很简洁明了。

我喜欢Python的语法。但是,您必须比语法更深入一点,才能找到Ruby的真正魅力。Ruby的一致性具有禅宗般的美。虽然没有任何简单的示例可以完全解释这一点,但我将在此处尝试提出一个示例以解释我的意思。

反转此字符串中的单词:

sentence = "backwards is sentence This"

在考虑如何做时,请执行以下操作:

  1. 把句子分成单词
  2. 反转字
  3. 重新将单词重新组合成字符串

在Ruby中,您可以这样做:

sentence.split.reverse.join ' '

正如您所想的那样,以相同的顺序依次调用一个方法。

在python中,它将看起来像这样:

" ".join(reversed(sentence.split()))

这不难理解,但流程不尽相同。主题(句子)埋在中间。这些操作是功能和对象方法的混合。这是一个简单的示例,但是在真正使用和理解Ruby时,尤其是在非琐碎的任务上,人们发现了许多不同的示例。

Ultimately all answers are going to be subjective at some level, and the answers posted so far pretty much prove that you can’t point to any one feature that isn’t doable in the other language in an equally nice (if not similar) way, since both languages are very concise and expressive.

I like Python’s syntax. However, you have to dig a bit deeper than syntax to find the true beauty of Ruby. There is zenlike beauty in Ruby’s consistency. While no trivial example can possibly explain this completely, I’ll try to come up with one here just to explain what I mean.

Reverse the words in this string:

sentence = "backwards is sentence This"

When you think about how you would do it, you’d do the following:

  1. Split the sentence up into words
  2. Reverse the words
  3. Re-join the words back into a string

In Ruby, you’d do this:

sentence.split.reverse.join ' '

Exactly as you think about it, in the same sequence, one method call after another.

In python, it would look more like this:

" ".join(reversed(sentence.split()))

It’s not hard to understand, but it doesn’t quite have the same flow. The subject (sentence) is buried in the middle. The operations are a mix of functions and object methods. This is a trivial example, but one discovers many different examples when really working with and understanding Ruby, especially on non-trivial tasks.


回答 3

Python具有“我们都在这里成年”的心态。因此,您会发现Ruby具有类似常量的功能,而Python没有(尽管Ruby的常量只会发出警告)。Python的思维方式是,如果您想使某些内容不变,则应将变量名全部大写,而不要更改它。

例如,Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

Python has a “we’re all adults here” mentality. Thus, you’ll find that Ruby has things like constants while Python doesn’t (although Ruby’s constants only raise a warning). The Python way of thinking is that if you want to make something constant, you should put the variable names in all caps and not change it.

For example, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

回答 4

您只能从Python中的模块导入特定功能。在Ruby中,您将导入整个方法列表。您可以在Ruby中“取消导入”它们,但这不是全部。

编辑:

让我们来看看这个Ruby模块:


module Whatever
  def method1
  end

  def method2
  end
end

如果您将其包含在代码中:


include Whatever

您会看到method1method2都已添加到您的命名空间中。您不能仅导入method1。您要么同时导入它们,要么根本不导入它们。在Python中,您只能导入您选择的方法。如果有这个名字,也许会叫做选择性导入?

You can import only specific functions from a module in Python. In Ruby, you import the whole list of methods. You could “unimport” them in Ruby, but it’s not what it’s all about.

EDIT:

let’s take this Ruby module :


module Whatever
  def method1
  end

  def method2
  end
end

if you include it in your code :


include Whatever

you’ll see that both method1 and method2 have been added to your namespace. You can’t import only method1. You either import them both or you don’t import them at all. In Python you can import only the methods of your choosing. If this would have a name maybe it would be called selective importing?


回答 5

从Ruby的网站

与Python相似,在Ruby中,…

  • 有一个交互式提示(称为irb)。
  • 您可以在命令行上阅读docs(使用ri命令而不是pydoc)。
  • 没有特殊的行终止符(通常的换行符除外)。
  • 字符串文字可以跨越多行,例如Python的三引号字符串。
  • 方括号用于列表,大括号用于字典(在Ruby中称为“哈希”)。
  • 数组的工作原理相同(添加它们会构成一个长数组,但是像这样组成它们 a3 = [ a1, a2 ]得到一个数组数组)。
  • 对象是强类型和动态类型的。
  • 一切都是对象,变量只是对象的引用。
  • 尽管关键字有些不同,但是exceptions的作用大致相同。
  • 您已经拥有嵌入式doc工具(Ruby称为rdoc)。

与Python不同,在Ruby中,…

  • 字符串是可变的。
  • 您可以创建常量(不希望更改其值的变量)。
  • 有一些强制的大小写约定(例如,类名以大写字母开头,变量以小写字母开头)。
  • 列表容器只有一种(数组),并且是可变的。
  • 双引号字符串允许转义序列(如\ t)和特殊的“表达式替换”语法(可让您将Ruby表达式的结果直接插入其他字符串中,而不必“添加” +“字符串” +“在一起”) 。单引号字符串类似于Python的r“原始字符串”。
  • 没有“新样式”和“旧样式”类。只是一种。
  • 您永远不会直接访问属性。使用Ruby,这就是所有方法调用。
  • 方法调用的括号通常是可选的。
  • 有公共的,私有的和受保护的用于强制访问,而不是Python的_voluntary_ underscore __convention__
  • 使用“ mixin’s”代替多重继承。
  • 您可以添加或修改内置类的方法。两种语言都可以让您随时打开和修改类,但是Python阻止了对内置函数的修改,而Ruby则不允许。
  • 您将获得true和false而不是True和False(并且使用nil代替None)。
  • 在测试真相时,只有false和nil会得出错误值。其他所有内容均正确(包括0、0.0,“”和[])。
  • 它是elsif而不是elif。
  • 这是必需的,而不是导入。否则,用法是相同的。
  • 事物上方的一行(而不是它们下方的文档字符串)上的常用注释用于生成文档。
  • 尽管有许多捷径可让您记住,但仍有许多捷径可让您快速学习。它们往往使Ruby变得有趣且非常有生产力。

From Ruby’s website:

Similarities As with Python, in Ruby,…

  • There’s an interactive prompt (called irb).
  • You can read docs on the command line (with the ri command instead of pydoc).
  • There are no special line terminators (except the usual newline).
  • String literals can span multiple lines like Python’s triple-quoted strings.
  • Brackets are for lists, and braces are for dicts (which, in Ruby, are called “hashes”).
  • Arrays work the same (adding them makes one long array, but composing them like this a3 = [ a1, a2 ] gives you an array of arrays).
  • Objects are strongly and dynamically typed.
  • Everything is an object, and variables are just references to objects.
  • Although the keywords are a bit different, exceptions work about the same.
  • You’ve got embedded doc tools (Ruby’s is called rdoc).

Differences Unlike Python, in Ruby,…

  • Strings are mutable.
  • You can make constants (variables whose value you don’t intend to change).
  • There are some enforced case-conventions (ex. class names start with a capital letter, variables start with a lowercase letter).
  • There’s only one kind of list container (an Array), and it’s mutable.
  • Double-quoted strings allow escape sequences (like \t) and a special “expression substitution” syntax (which allows you to insert the results of Ruby expressions directly into other strings without having to “add ” + “strings ” + “together”). Single-quoted strings are like Python’s r”raw strings”.
  • There are no “new style” and “old style” classes. Just one kind.
  • You never directly access attributes. With Ruby, it’s all method calls.
  • Parentheses for method calls are usually optional.
  • There’s public, private, and protected to enforce access, instead of Python’s _voluntary_ underscore __convention__.
  • “mixin’s” are used instead of multiple inheritance.
  • You can add or modify the methods of built-in classes. Both languages let you open up and modify classes at any point, but Python prevents modification of built-ins — Ruby does not.
  • You’ve got true and false instead of True and False (and nil instead of None).
  • When tested for truth, only false and nil evaluate to a false value. Everything else is true (including 0, 0.0, “”, and []).
  • It’s elsif instead of elif.
  • It’s require instead of import. Otherwise though, usage is the same.
  • The usual-style comments on the line(s) above things (instead of docstrings below them) are used for generating docs.
  • There are a number of shortcuts that, although give you more to remember, you quickly learn. They tend to make Ruby fun and very productive.

回答 6

Ruby比Python具有的脚本语言功能。在这种情况下,脚本语言意味着用于Shell脚本和常规文本操作中的“胶水代码”。

这些大多与Perl共享。一流的内置正则表达式,$-Variables,有用的命令行选项(如Perl(-a,-e)等)。

连同其简洁而优美的语法,它非常适合此类任务。

对我而言,Python更像是一种动态类型化的业务语言,它非常易于学习并且语法简洁。不像Ruby那样“酷”,但很简洁。Python对Ruby而言,对我来说,是其他库的大量绑定。绑定到Qt和其他GUI库,许多游戏支持库以及和和。Ruby少得多。尽管经常使用的绑定(例如与数据库的绑定)具有良好的质量,但我发现利基库在Python中得到了更好的支持,即使对于同一库也有Ruby绑定。

因此,我想说这两种语言都有其用途,这是定义要使用哪种语言的任务。两者都很容易学习。我并排使用它们。Ruby用于脚本编写,Python用于独立应用程序。

What Ruby has over Python are its scripting language capabilities. Scripting language in this context meaning to be used for “glue code” in shell scripts and general text manipulation.

These are mostly shared with Perl. First-class built-in regular expressions, $-Variables, useful command line options like Perl (-a, -e) etc.

Together with its terse yet epxressive syntax it is perfect for these kind of tasks.

Python to me is more of a dynamically typed business language that is very easy to learn and has a neat syntax. Not as “cool” as Ruby but neat. What Python has over Ruby to me is the vast number of bindings for other libs. Bindings to Qt and other GUI libs, many game support libraries and and and. Ruby has much less. While much used bindings e.g. to Databases are of good quality I found niche libs to be better supported in Python even if for the same library there is also a Ruby binding.

So, I’d say both languages have its use and it is the task that defines which one to use. Both are easy enough to learn. I use them side-by-side. Ruby for scripting and Python for stand-alone apps.


回答 7

我不认为“ Ruby具有X而Python没有,而Python具有Y而Ruby没有”是查看它的最有用的方法。它们是非常相似的语言,具有许多共享功能。

在很大程度上,区别在于该语言使语言更加优雅和可读。使用您提出的示例,理论上两者都具有lambda,但是Python程序员倾向于避免使用lambda,并且使用它们构造的构造看起来不像Ruby那样易读或惯用。因此,在Python中,优秀的程序员将希望采用与Ruby中不同的方法来解决问题,只是因为这实际上解决问题的更好方法。

I don’t think “Ruby has X and Python doesn’t, while Python has Y and Ruby doesn’t” is the most useful way to look at it. They’re quite similar languages, with many shared abilities.

To a large degree, the difference is what the language makes elegant and readable. To use an example you brought up, both do theoretically have lambdas, but Python programmers tend to avoid them, and constructs made using them do not look anywhere near as readable or idiomatic as in Ruby. So in Python, a good programmer will want to take a different route to solving the problem than he would in Ruby, just because it actually is the better way to do it.


回答 8

我想提出一个原始问题的变体:“ Ruby有哪些Python没有的,反之亦然?” 它承认了令人失望的答案:“那么,用Intercal无法做到的Ruby或Python可以做什么?” 在这个级别上什么都没有,因为Python和Ruby都是庞大的皇室家族的一部分,坐在图灵近似的宝座上。

但是呢:

在Python中,优雅而良好的工作可以做得很好,而在Ruby中却不能做到如此美丽和出色的工程,反之亦然?

这可能比单纯的功能比较有趣。

I’d like to suggest a variant of the original question, “What does Ruby have that Python doesn’t, and vice versa?” which admits the disappointing answer, “Well, what can you do with either Ruby or Python that can’t be done in Intercal?” Nothing on that level, because Python and Ruby are both part of the vast royal family sitting on the throne of being Turing approximant.

But what about this:

What can be done gracefully and well in Python that can’t be done in Ruby with such beauty and good engineering, or vice versa?

That may be much more interesting than mere feature comparison.


回答 9

Python具有用于列表推导和生成器的显式内置语法,而在Ruby中,您将使用映射和代码块。

比较

list = [ x*x for x in range(1, 10) ]

res = (1..10).map{ |x| x*x }

Python has an explicit, builtin syntax for list-comprehenions and generators whereas in Ruby you would use map and code blocks.

Compare

list = [ x*x for x in range(1, 10) ]

to

res = (1..10).map{ |x| x*x }

回答 10

“以大写字母开头的变量将成为常量,无法修改”

错误。他们能。

您只会收到警告。

“Variables that start with a capital letter becomes constants and can’t be modified”

Wrong. They can.

You only get a warning if you do.


回答 11

基础设施方面:

  • 与Ruby相比,Python与C ++的集成要好得多(通过Boost.PythonSIPPy ++之类的东西),而Ruby似乎可以直接针对Ruby解释器API进行编写(当然,您也可以使用Python做到这一点,但是在这两种情况下,这样做都是低级,乏味且容易出错的)或使用SWIG(虽然它可以工作,并且如果您想支持多种语言,绝对是个好主意),但它不如Boost.Python或SIP好您特别希望绑定C ++)。

  • Python有许多Web应用程序环境(Django,Pylons / Turbogears,web.py,可能至少还有六种),而Ruby(有效地)有一个:Rails。(确实存在其他Ruby Web框架,但是似乎很难在Rails上获得很多吸引力)。这方面是好是坏?很难说,可能很主观;我可以很容易地想到这样的论点:Python情况更好,而Ruby情况更好。

  • 在文化上,Python和Ruby社区似乎有所不同,但是我只能暗示这一点,因为我没有与Ruby社区进行交互的丰富经验。我主要是为了补充这一点,希望对两者都有丰富经验的人可以放大(或拒绝)此声明。

Somewhat more on the infrastructure side:

  • Python has much better integration with C++ (via things like Boost.Python, SIP, and Py++) than Ruby, where the options seem to be either write directly against the Ruby interpreter API (which you can do with Python as well, of course, but in both cases doing so is low level, tedious, and error prone) or use SWIG (which, while it works and definitely is great if you want to support many languages, isn’t nearly as nice as Boost.Python or SIP if you are specifically looking to bind C++).

  • Python has a number of web application environments (Django, Pylons/Turbogears, web.py, probably at least half a dozen others), whereas Ruby (effectively) has one: Rails. (Other Ruby web frameworks do exist, but seemingly have a hard time getting much traction against Rails). Is this aspect good or bad? Hard to say, and probably quite subjective; I can easily imagine arguments that the Python situation is better and that the Ruby situation is better.

  • Culturally, the Python and Ruby communities seem somewhat different, but I can only hint at this as I don’t have that much experience interacting with the Ruby community. I’m adding this mostly in the hopes that someone who has a lot of experience with both can amplify (or reject) this statement.


回答 12

无耻地复制/粘贴自:Alex Martellicomp.lang.python邮件列表中回答了Ruby比Python有什么更好的线程。

2003年8月18日,上午10:50 Erik Max Francis写道:

“布兰登·范·凡·布朗”写道:

Ruby比Python有什么更好的选择?我确定有事 它是什么?

向Ruby人员(而不是Python人员)问这个不是更有意义吗?

可能(也可能不会)取决于一个人的目的-例如,如果一个人的目的包括对Python社区的“社会学研究”,那么向该社区提出问题很可能会证明有关该信息的揭示更多,而不是放在其他地方:-)。

我个人很高兴借此机会在上次OSCON上关注Dave Thomas的为期一天的Ruby教程。在语法差异的明显变化之下,我发现Ruby和Python惊人地相似-如果我正在计算几乎所有语言集中的最小生成树,我很确定Python和Ruby将成为合并的前两叶中间节点:-)。

当然,在Ruby中,我确实会在每个块的末尾键入愚蠢的“ end”(而不是不缩进)而感到疲倦-但是,我确实避免输入Python要求的同样愚蠢的’:’。每个块的 开始,所以几乎可以洗了:-)。其他语法差异,例如’@foo’与’self.foo’,或者Ruby vs Python中case的较高重要性,实际上与我无关。

毫无疑问,其他人只是基于这样的问题来选择编程语言,并且引发了最激烈的辩论-但对我而言,这只是帕金森定律中一个行动的例子(关于某个问题的辩论数量与该问题的数量成反比实际重要性)。

编辑(2010年6月19日,上午11:45之前):这也称为“为自行车棚涂漆”(或简称为“自行车棚涂漆”)-再次提及诺斯科特·帕金森,他提出了“辩论”作为“关于琐碎话题的热门辩论”的典型示例。(编辑结束)。

我确实发现语法上的差异很重要,并且对Python有利-但其他人无疑会认为相反-是“如何调用不带参数的函数”。在Python中(就像在C中一样),要调用函数,您总是要应用“调用运算符”-括号紧跟在您要调用的对象之后(在这些括号内是您在调用中传递的args,如果您没有传递参数,则括号为空)。这仅提及 任何对象,不涉及运算符,在任何上下文中都意味着仅是对对象的引用,没有特殊情况,异常,即席规则等。在Ruby中(例如在Pascal中),要调用带有WITH参数的函数,您需要传递args(通常在括号中,尽管并非总是如此)-但是,如果该函数没有args,则只需简单地提及该函数即可。这可能会满足许多人的期望(至少,毫无疑问,至少那些以前仅有编程经验的人是使用Pascal或其他具有类似“隐式调用”的语言(例如Visual Basic)的人)-但对我而言,这意味着仅提及对象可能意味着对对象的引用或对对象的调用,具体取决于对象的类型-在某些情况下,我可以 仅仅通过提及它就不能得到对对象的引用,我将需要使用明确的“给我一个对此的引用,不要称呼它!” 否则不需要的运算符。我觉得这会影响函数(或方法或其他可调用对象)的“一流”,并影响对象平滑交换的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。函数(或方法或其他可调用对象)的功能,以及顺利交换对象的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。函数(或方法或其他可调用对象)的功能,以及顺利交换对象的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。

在语法下方,我们发现了基本语义上的一些重要差异-例如,Ruby中的字符串是可变对象(例如在C ++中),而在Python中则不可改变(例如在Java中,或者我相信C#)。同样,主要根据已经熟悉的知识进行判断的人可能会认为这对Ruby有利(除非他们熟悉Java或C#,当然:-)。我,我认为不可变字符串是一个好主意(我不认为Java独立地重新发明了Python中已经存在的那个想法),尽管我也不介意具有“可变字符串缓冲区”类型(理想情况下,它比Java自己的“字符串缓冲区”具有更好的易用性);而且由于熟悉程度,我不作这样的判断-在学习Java之前, 所有数据都是不可变的,我所知道的所有语言都具有可变的字符串-但是,当我第一次看到Java中的不可变字符串的想法(我在学习Python之前就学得很好)时,它立即使我震惊,非常适合顶级编程语言的参考语义(与最适合于距离机器更近,距离应用程序更远的语言,例如C)最合适的值语义,将字符串作为一流的,内置的(漂亮的)关键)数据类型。

Ruby在基本语义上确实具有一些优势-例如,删除Python的“列表与元组”极其微妙的区别。但是大多数情况下,分数(就我而言,保持简单,是一个很大的加和微妙的,聪明的区别,是一个显着的减号)与Ruby相对(例如,同时具有封闭和半开放间隔,用符号a..b和a。表示)。 .b [任何人都想声称哪个是显而易见的?-)],这很愚蠢-当然,恕我直言!)。同样,考虑到在语言的核心上有很多相似但又细微不同的事物的人,加号(而不是减号)当然会按照我的计算方式来反加这些:-)。

这些比较不会误导您认为这两种语言是 非常不一样,请注意。他们不是。但是,如果我被要求将“ capelli d’angelo”与“ spaghettini”进行比较,然后指出这两种意大利面几乎对任何人都没有区别,并且可以在您可能要准备的任何菜肴中互换使用,那么我将不可避免地拥有进入显微镜检查长度和直径如何明显地不同,在一种情况下而不是在另一种情况下股线的末端如何逐渐变细等等,以尝试解释为什么我个人更愿意’angelo作为任何一种汤中的意大利面食,但更喜欢将意大利面条作为Pastasciutta来搭配适用于此类长而细的意大利面食形式的调味料(橄榄油,蒜末,剁碎的红辣椒和细碎的凤尾鱼,例如-但是,如果您将大蒜和胡椒切成薄片而不是切碎,那么您应该选择意大利面更健康的面条,而不是意大利面条稀薄的消失,并且建议您不要食用凤尾鱼,而应添加一些新鲜的春季罗勒[甚至-我是一个异端…!-薄荷糖…]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)-薄荷糖…]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)-薄荷糖…]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)

因此,回到Python和Ruby,我们来谈谈两个大问题(就适当的语言而言-离开了库以及其他重要辅助工具(如工具和环境,如何嵌入/扩展每种语言等),现在-它们将无法应用于每种语言的所有实现,例如,Jython与Classic Python是Python语言的两种实现!):

  1. Ruby的迭代器和代码块与Python的迭代器和生成器;

  2. Ruby的TOTAL不受限制的“动态性”,包括
    “重新打开”任何现有类(包括所有内置类)并在运行时更改其行为的能力-相对于Python庞大但 有限的 动态性,它从未改变现有的行为内置类及其实例。

就我个人而言,我认为1是一次洗礼(差异是如此之深,以至于我很容易看到人们讨厌这两种方法中的任何一种,但从我个人的角度来看,它们的优缺点几乎相同);还有2个至关重要的问题-一个使Ruby更适合“修补”的问题,但Python同样更适合用于大型生产应用程序。从某种程度上讲,这很有趣,因为两种语言都比大多数其他语言更具动态性,以至于最终它们与我的POV之间的关键区别应该取决于这一点-Ruby在这方面“达到11种”(参考当然是“ Spinal Tap”。在Ruby中我能做到!即,我可以动态地更改内置的字符串类,以便如果a == b打印“等于!\ n”,则a =“ Hello World” b =“ hello world”,否则打印“ different!\ n”,最后将打印“等于”。在python中,我无法做到这一点。出于元编程,实现实验框架等目的,Ruby的这种惊人的动态功能非常强大。 吸引人。但是-如果我们谈论的是大型应用程序,它是由许多人开发并由更多人维护的,包括来自不同来源的各种库,并且需要在客户站点上投入生产…那么,我不想一种非常动态的语言,非常感谢。我讨厌这样的想法:某些库不知不觉地打破了那些依赖于那些不同字符串的其他不相关的库-这是一种深层和深层的“通道”,在LOOK分离和应该分离的代码段之间,这意味着死亡。大规模编程。通过让任何模块“隐蔽地”影响任何其他模块的行为,对内置类型的语义进行变异的能力只是生产应用程序编程的一个坏主意,

如果我必须将Ruby用于如此大的应用程序,那么我将尝试依赖于编码样式的限制,大量的测试(只要有任何更改,都将重新运行-甚至应该完全不相关…),等等。禁止使用此语言功能。但是,我认为不首先具有该功能会更好,就像Python本身可以成为应用程序编程的一种更好的语言一样,如果可以“固定”一定数量的内置程序,那么我知道,例如len(“ ciao”)为4(而不必担心是否有人在内置模块中更改了名称“ len”的绑定…)。我确实希望Python最终能够“钉牢”其内置组件。

但是问题不大,因为重新绑定内置函数在Python中已被弃用,也是一种罕见的做法。在Ruby中,它让我感到很专业-就像 其他语言(例如Dylan)的功能过于强大一样,在我看来也存在类似的风险(我希望Python永远不会获得如此强大的宏系统, “让人们定义自己的语言中嵌入的他们自己的特定于领域的小语言”的诱惑力很重要-恕我直言,这会通过向可能的修补匠提供“有吸引力的麻烦”来削弱Python对应用程序编程的出色用处。潜伏在每个程序员的心中…)。

亚历克斯

Shamelessly copy/pasted from: Alex Martelli answer on What’s better about Ruby than Python thread from comp.lang.python mailing list.

Aug 18 2003, 10:50 am Erik Max Francis wrote:

“Brandon J. Van Every” wrote:

What’s better about Ruby than Python? I’m sure there’s something. What is it?

Wouldn’t it make much more sense to ask Ruby people this, rather than Python people?

Might, or might not, depending on one’s purposes — for example, if one’s purposes include a “sociological study” of the Python community, then putting questions to that community is likely to prove more revealing of information about it, than putting them elsewhere:-).

Personally, I gladly took the opportunity to follow Dave Thomas’ one-day Ruby tutorial at last OSCON. Below a thin veneer of syntax differences, I find Ruby and Python amazingly similar — if I was computing the minimum spanning tree among just about any set of languages, I’m pretty sure Python and Ruby would be the first two leaves to coalesce into an intermediate node:-).

Sure, I do get weary, in Ruby, of typing the silly “end” at the end of each block (rather than just unindenting) — but then I do get to avoid typing the equally-silly ‘:’ which Python requires at the start of each block, so that’s almost a wash:-). Other syntax differences such as ‘@foo’ versus ‘self.foo’, or the higher significance of case in Ruby vs Python, are really just about as irrelevant to me.

Others no doubt base their choice of programming languages on just such issues, and they generate the hottest debates — but to me that’s just an example of one of Parkinson’s Laws in action (the amount on debate on an issue is inversely proportional to the issue’s actual importance).

Edit (by AM 6/19/2010 11:45): this is also known as “painting the bikeshed” (or, for short, “bikeshedding”) — the reference is, again, to Northcote Parkinson, who gave “debates on what color to paint the bikeshed” as a typical example of “hot debates on trivial topics”. (end-of-Edit).

One syntax difference that I do find important, and in Python’s favor — but other people will no doubt think just the reverse — is “how do you call a function which takes no parameters”. In Python (like in C), to call a function you always apply the “call operator” — trailing parentheses just after the object you’re calling (inside those trailing parentheses go the args you’re passing in the call — if you’re passing no args, then the parentheses are empty). This leaves the mere mention of any object, with no operator involved, as meaning just a reference to the object — in any context, without special cases, exceptions, ad-hoc rules, and the like. In Ruby (like in Pascal), to call a function WITH arguments you pass the args (normally in parentheses, though that is not invariably the case) — BUT if the function takes no args then simply mentioning the function implicitly calls it. This may meet the expectations of many people (at least, no doubt, those whose only previous experience of programming was with Pascal, or other languages with similar “implicit calling”, such as Visual Basic) — but to me, it means the mere mention of an object may EITHER mean a reference to the object, OR a call to the object, depending on the object’s type — and in those cases where I can’t get a reference to the object by merely mentioning it I will need to use explicit “give me a reference to this, DON’T call it!” operators that aren’t needed otherwise. I feel this impacts the “first-classness” of functions (or methods, or other callable objects) and the possibility of interchanging objects smoothly. Therefore, to me, this specific syntax difference is a serious black mark against Ruby — but I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-).

Below the syntax, we get into some important differences in elementary semantics — for example, strings in Ruby are mutable objects (like in C++), while in Python they are not mutable (like in Java, or I believe C#). Again, people who judge primarily by what they’re already familiar with may think this is a plus for Ruby (unless they’re familiar with Java or C#, of course:-). Me, I think immutable strings are an excellent idea (and I’m not surprised that Java, independently I think, reinvented that idea which was already in Python), though I wouldn’t mind having a “mutable string buffer” type as well (and ideally one with better ease-of-use than Java’s own “string buffers”); and I don’t give this judgment because of familiarity — before studying Java, apart from functional programming languages where all data are immutable, all the languages I knew had mutable strings — yet when I first saw the immutable-string idea in Java (which I learned well before I learned Python), it immediately struck me as excellent, a very good fit for the reference-semantics of a higher level programming language (as opposed to the value-semantics that fit best with languages closer to the machine and farther from applications, such as C) with strings as a first-class, built-in (and pretty crucial) data type.

Ruby does have some advantages in elementary semantics — for example, the removal of Python’s “lists vs tuples” exceedingly subtle distinction. But mostly the score (as I keep it, with simplicity a big plus and subtle, clever distinctions a notable minus) is against Ruby (e.g., having both closed and half-open intervals, with the notations a..b and a…b [anybody wants to claim that it’s obvious which is which?-)], is silly — IMHO, of course!). Again, people who consider having a lot of similar but subtly different things at the core of a language a PLUS, rather than a MINUS, will of course count these “the other way around” from how I count them:-).

Don’t be misled by these comparisons into thinking the two languages are very different, mind you. They aren’t. But if I’m asked to compare “capelli d’angelo” to “spaghettini”, after pointing out that these two kinds of pasta are just about undistinguishable to anybody and interchangeable in any dish you might want to prepare, I would then inevitably have to move into microscopic examination of how the lengths and diameters imperceptibly differ, how the ends of the strands are tapered in one case and not in the other, and so on — to try and explain why I, personally, would rather have capelli d’angelo as the pasta in any kind of broth, but would prefer spaghettini as the pastasciutta to go with suitable sauces for such long thin pasta forms (olive oil, minced garlic, minced red peppers, and finely ground anchovies, for example – but if you sliced the garlic and peppers instead of mincing them, then you should choose the sounder body of spaghetti rather than the thinner evanescence of spaghettini, and would be well advised to forego the achovies and add instead some fresh spring basil [or even — I’m a heretic…! — light mint…] leaves — at the very last moment before serving the dish). Ooops, sorry, it shows that I’m traveling abroad and haven’t had pasta for a while, I guess. But the analogy is still pretty good!-)

So, back to Python and Ruby, we come to the two biggies (in terms of language proper — leaving the libraries, and other important ancillaries such as tools and environments, how to embed/extend each language, etc, etc, out of it for now — they wouldn’t apply to all IMPLEMENTATIONS of each language anyway, e.g., Jython vs Classic Python being two implementations of the Python language!):

  1. Ruby’s iterators and codeblocks vs Python’s iterators and generators;

  2. Ruby’s TOTAL, unbridled “dynamicity”, including the ability
    to “reopen” any existing class, including all built-in ones, and change its behavior at run-time — vs Python’s vast but bounded dynamicity, which never changes the behavior of existing built-in classes and their instances.

Personally, I consider 1 a wash (the differences are so deep that I could easily see people hating either approach and revering the other, but on MY personal scales the pluses and minuses just about even up); and 2 a crucial issue — one that makes Ruby much more suitable for “tinkering”, BUT Python equally more suitable for use in large production applications. It’s funny, in a way, because both languages are so MUCH more dynamic than most others, that in the end the key difference between them from my POV should hinge on that — that Ruby “goes to eleven” in this regard (the reference here is to “Spinal Tap”, of course). In Ruby, there are no limits to my creativity — if I decide that all string comparisons must become case-insensitive, I CAN DO THAT! I.e., I can dynamically alter the built-in string class so that a = “Hello World” b = “hello world” if a == b print “equal!\n” else print “different!\n” end WILL print “equal”. In python, there is NO way I can do that. For the purposes of metaprogramming, implementing experimental frameworks, and the like, this amazing dynamic ability of Ruby is extremely appealing. BUT — if we’re talking about large applications, developed by many people and maintained by even more, including all kinds of libraries from diverse sources, and needing to go into production in client sites… well, I don’t WANT a language that is QUITE so dynamic, thank you very much. I loathe the very idea of some library unwittingly breaking other unrelated ones that rely on those strings being different — that’s the kind of deep and deeply hidden “channel”, between pieces of code that LOOK separate and SHOULD BE separate, that spells d-e-a-t-h in large-scale programming. By letting any module affect the behavior of any other “covertly”, the ability to mutate the semantics of built-in types is just a BAD idea for production application programming, just as it’s cool for tinkering.

If I had to use Ruby for such a large application, I would try to rely on coding-style restrictions, lots of tests (to be rerun whenever ANYTHING changes — even what should be totally unrelated…), and the like, to prohibit use of this language feature. But NOT having the feature in the first place is even better, in my opinion — just as Python itself would be an even better language for application programming if a certain number of built-ins could be “nailed down”, so I KNEW that, e.g., len(“ciao”) is 4 (rather than having to worry subliminally about whether somebody’s changed the binding of name ‘len’ in the builtins module…). I do hope that eventually Python does “nail down” its built-ins.

But the problem’s minor, since rebinding built-ins is quite a deprecated as well as a rare practice in Python. In Ruby, it strikes me as major — just like the too powerful macro facilities of other languages (such as, say, Dylan) present similar risks in my own opinion (I do hope that Python never gets such a powerful macro system, no matter the allure of “letting people define their own domain-specific little languages embedded in the language itself” — it would, IMHO, impair Python’s wonderful usefulness for application programming, by presenting an “attractive nuisance” to the would-be tinkerer who lurks in every programmer’s heart…).

Alex


回答 13

其他人来自:

http://www.ruby-lang.org/zh-CN/documentation/ruby-from-other-languages/to-ruby-from-python/

(如果自该页面更新以来,我误解了任何东西,或者其中的任何一个在Ruby方面已更改,则可以随时进行编辑…)

字符串在Ruby中是可变的,而不是在Python中(通过“ changes”创建新字符串)是可变的。

Ruby有一些强制的大小写约定,而Python没有。

Python同时具有列表和元组(不可变列表)。Ruby具有与Python列表相对应的数组,但它们没有不变的变体。

在Python中,您可以直接访问对象属性。在Ruby中,总是通过方法。

在Ruby中,方法调用的括号通常是可选的,但在Python中则不是。

Ruby具有公共,私有和受保护的强制访问权限,而不是Python使用下划线和名称修饰的约定。

Python具有多重继承。Ruby具有“ mixins”。

另一个非常相关的链接:

http://c2.com/cgi/wiki?PythonVsRuby

特别是与Alex Martelli的另一个好链接的链接,Alex Martelli在SO上也发布了很多很棒的东西:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283

Some others from:

http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/

(If I have misintrepreted anything or any of these have changed on the Ruby side since that page was updated, someone feel free to edit…)

Strings are mutable in Ruby, not in Python (where new strings are created by “changes”).

Ruby has some enforced case conventions, Python does not.

Python has both lists and tuples (immutable lists). Ruby has arrays corresponding to Python lists, but no immutable variant of them.

In Python, you can directly access object attributes. In Ruby, it’s always via methods.

In Ruby, parentheses for method calls are usually optional, but not in Python.

Ruby has public, private, and protected to enforce access, instead of Python’s convention of using underscores and name mangling.

Python has multiple inheritance. Ruby has “mixins.”

And another very relevant link:

http://c2.com/cgi/wiki?PythonVsRuby

Which, in particular, links to another good one by Alex Martelli, who’s been also posting a lot of great stuff here on SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


回答 14

我不确定,因此我首先将其添加为答案。

Python将未绑定方法视为函数

这意味着您可以通过theobject.themethod()或调用方法TheClass.themethod(anobject)

编辑:尽管方法和函数之间的差异在Python中很小,在Python 3中不存在,但是在Ruby中也不存在,仅因为Ruby没有函数。定义函数时,实际上是在Object上定义方法。

但是您仍然不能采用一个类的方法并将其作为函数调用,您将不得不将其重新绑定到要调用的对象上,这更加令人费解。

I’m unsure of this, so I add it as an answer first.

Python treats unbound methods as functions

That means you can call a method either like theobject.themethod() or by TheClass.themethod(anobject).

Edit: Although the difference between methods and functions is small in Python, and non-existant in Python 3, it also doesn’t exist in Ruby, simply because Ruby doesn’t have functions. When you define functions, you are actually defining methods on Object.

But you still can’t take the method of one class and call it as a function, you would have to rebind it to the object you want to call on, which is much more obstuse.


回答 15

我想提到Python描述符API,该API允许一个自定义对象到属性的“通信”。还值得注意的是,在Python中,可以通过覆盖通过方法的默认实现提供的默认值来自由实现另一种协议__getattribute__。让我提供有关上述内容的更多详细信息。描述是在普通类__get____set__和/或__delete__方法。当解释器遇到类似的内容时anObj.anAttr,将执行以下操作:

  • __getattribute__的方法anObj被调用
  • __getattribute__ 从类字典中检索anAttr对象
  • 它检查abAttr对象是否具有__get____set____delete__可调用对象
  • 上下文(即调用方对象或类,以及值,而不是后者,如果有设置器的话)被传递给可调用对象
  • 返回结果。

如前所述,这是默认行为。可以通过重新实现自由更改协议__getattribute__

该技术比装饰器功能强大得多。

I would like to mention Python descriptor API that allows one customize object-to-attribute “communication”. It is also noteworthy that, in Python, one is free to implement an alternative protocol via overriding the default given through the default implementation of the __getattribute__ method. Let me give more details about the aforementioned. Descriptors are regular classes with __get__, __set__ and/or __delete__ methods. When interpreter encounters something like anObj.anAttr, the following is performed:

  • __getattribute__ method of anObj is invoked
  • __getattribute__ retrieves anAttr object from the class dict
  • it checks whether abAttr object has __get__, __set__ or __delete__ callable objects
  • the context (i.e., caller object or class, and value, instead of the latter, if we have setter) is passed to the callable object
  • the result is returned.

As was mentioned, this is the default behavior. One is free to change the protocol by re-implementing __getattribute__.

This technique is lot more powerful than decorators.


回答 16

Ruby使用内置了延续支持callcc

因此,您可以实施酷的东西,例如amb-operator

Ruby has builtin continuation support using callcc.

Hence you can implement cool things like the amb-operator


回答 17

在此阶段,Python仍具有更好的unicode支持

At this stage, Python still has better unicode support


回答 18

Python具有文档字符串,而ruby没有…或者,如果没有,则无法像在python中那样容易地访问它们。

附言 如果我错了,请留下一个例子?我有一个解决方法,可以很容易地将其Monkey类拼凑到类中,但是我想以“本机方式”使用文档字符串有点功能。

Python has docstrings and ruby doesn’t… Or if it doesn’t, they are not accessible as easily as in python.

Ps. If im wrong, pretty please, leave an example? I have a workaround that i could monkeypatch into classes quite easily but i’d like to have docstring kinda of a feature in “native way”.


回答 19

Ruby在命令行中逐行循环输入文件(’-n’标志),因此可以像AWK一样使用。这个Ruby一线:

ruby -ne 'END {puts $.}'

将计数像AWK一线式的行:

awk 'END{print NR}'

Ruby通过Perl获得了此功能,Perl从AWK那里获得了它,这是使系统管理员可以使用Perl的一种方式,而不必更改他们的工作方式。

Ruby has a line by line loop over input files (the ‘-n’ flag) from the commandline so it can be used like AWK. This Ruby one-liner:

ruby -ne 'END {puts $.}'

will count lines like the AWK one-liner:

awk 'END{print NR}'

Ruby gets feature this through Perl, which took it from AWK as a way of getting sysadmins on board with Perl without having to change the way they do things.


回答 20

Ruby有Sigils和Twigils,Python没有。

编辑:这是我忘记的一个非常重要的事情(毕竟,前一个只是发火了一点:-p):

Python具有JIT编译器(Psyco),一种用于编写更快的代码的低级语言(Pyrex)和添加内联C ++代码(Weave)的能力。

Ruby has sigils and twigils, Python doesn’t.

Edit: And one very important thing that I forgot (after all, the previous was just to flame a little bit :-p):

Python has a JIT compiler (Psyco), a sightly lower level language for writing faster code (Pyrex) and the ability to add inline C++ code (Weave).


回答 21

我的python生锈了,所以其中一些可能在python中,我只是一开始就不记得/从未学过,但是这里是我想到的前几个:

空格

Ruby处理空白完全不同。对于初学者,您不需要缩进任何内容(这意味着使用4个空格或1个制表符都没有关系)。它还执行智能线路连续,因此以下内容有效:

def foo(bar,
        cow)

基本上,如果您以运算符结尾,它将找出正在发生的事情。

混合蛋白

Ruby具有可以扩展实例而不是完整类的mixin:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

枚举

我不确定这是否与生成器相同,但是从Ruby 1.9 ruby​​开始,作为枚举,所以

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

参考:http : //blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

“关键字参数”

尽管您不能跳过这样的默认值,但Ruby中支持其中列出的两个项目。你可以按顺序去

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

请注意,c = 5实际上为调用范围内的变量c分配了值5,并将参数b设置为了值5。

或者您也可以使用散列来解决第二个问题

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

参考:《 Ruby实用程序员指南》

My python’s rusty, so some of these may be in python and i just don’t remember/never learned in the first place, but here are the first few that I thought of:

Whitespace

Ruby handles whitespace completely different. For starters, you don’t need to indent anything (which means it doesn’t matter if you use 4 spaces or 1 tab). It also does smart line continuation, so the following is valid:

def foo(bar,
        cow)

Basically, if you end with an operator, it figures out what is going on.

Mixins

Ruby has mixins which can extend instances instead of full classes:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Enums

I’m not sure if this is the same as generators, but as of Ruby 1.9 ruby as enums, so

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Reference: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

“Keyword Arguments”

Both of the items listed there are supported in Ruby, although you can’t skip default values like that. You can either go in order

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Note that c=5 actually assigns the variable c in the calling scope the value 5, and sets the parameter b the value 5.

or you can do it with hashes, which address the second issue

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Reference: The Pragmatic Progammer’s Guide to Ruby


回答 22

您可以在Ruby和Python的类定义中都包含代码。但是,在Ruby中,您有对类(自身)的引用。在Python中,您没有对该类的引用,因为该类尚未定义。

一个例子:

class Kaka
  puts self
end

在这种情况下,self是类,并且此代码将打印出“ Kaka”。无法打印出类名,也无法通过其他方式从Python中的类定义主体访问该类。

You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don’t have a reference to the class, as the class isn’t defined yet.

An example:

class Kaka
  puts self
end

self in this case is the class, and this code would print out “Kaka”. There is no way to print out the class name or in other ways access the class from the class definition body in Python.


回答 23

语法不是一件小事,它直接影响我们的思维方式。它也直接影响我们为使用的系统创建的规则。例如,由于我们编写数学方程式或句子的方式,我们具有运算顺序。数学的标准表示法允许人们以多种方式阅读它,并在给定相同方程的情况下得出不同的答案。如果我们使用前缀或后缀表示法,那么我们将创建规则以区分要操纵的数字,而不是仅具有计算值顺序的规则。

标准表示法清楚地表明了我们在谈论什么数字,同时使它们的计算顺序不明确。前缀和后缀表示法在使数字含糊不清的同时,使计算明文的顺序变得容易。如果不是因为语法空白引起的困难,Python就已经有了多行lambda。(确实存在一些建议,无需添加显式的块定界符就可以拉出此类内容。)

我发现在条件为的情况下编写条件(如果条件为假)要比在Ruby或其他语言中用语义上等效的“ if-not”构造容易得多,而用Ruby语句中的else语句更容易编写条件。如果当今人们使用的大多数语言的力量相等,那么如何将每种语言的语法视为琐碎的事情呢?在诸如块和继承机制等特定功能之后,语法是语言最重要的部分,这并不是肤浅的事情。

肤浅的是我们赋予句法的美的美学特质。美学与我们的认知如何运作,语法无关。

Syntax is not a minor thing, it has a direct impact on how we think. It also has a direct effect on the rules we create for the systems we use. As an example we have the order of operations because of the way we write mathematical equations or sentences. The standard notation for mathematics allows people to read it more than one way and arrive at different answers given the same equation. If we had used prefix or postfix notation we would have created rules to distinguish what the numbers to be manipulated were rather than only having rules for the order in which to compute values.

The standard notation makes it plain what numbers we are talking about while making the order in which to compute them ambiguous. Prefix and postfix notation make the order in which to compute plain while making the numbers ambiguous. Python would already have multiline lambdas if it were not for the difficulties caused by the syntactic whitespace. (Proposals do exist for pulling this kind of thing off without necessarily adding explicit block delimiters.)

I find it easier to write conditions where I want something to occur if a condition is false much easier to write with the unless statement in Ruby than the semantically equivalent “if-not” construction in Ruby or other languages for example. If most of the languages that people are using today are equal in power, how can the syntax of each language be considered a trivial thing? After specific features like blocks and inheritance mechanisms etc. syntax is the most important part of a language,hardly a superficial thing.

What is superficial are the aesthetic qualities of beauty that we ascribe to syntax. Aesthetics have nothing to do with how our cognition works, syntax does.


回答 24

惊讶地发现红宝石的“方法缺失”机制一无所获。我将提供Rails中find_by _…方法的示例,作为该语言功能强大功能的示例。我的猜测是可以在Python中实现类似的功能,但据我所知它本身并不存在。

Surprised to see nothing mentioned of ruby’s “method missing” mechanism. I’d give examples of the find_by_… methods in Rails, as an example of the power of that language feature. My guess is that something similar could be implemented in Python, but to my knowledge it isn’t there natively.


回答 25

Paul Graham的累加器生成器问题证明了Python和Ruby在lambda上的另一个区别。转载在这里:

编写一个具有数字n的函数foo,并返回一个具有数字i的函数,并返回以i递增的n。注意:(a)是数字而不是整数,(b)是递增而不是加号。

在Ruby中,您可以执行以下操作:

def foo(n)
  lambda {|i| n += i }
end

在Python中,您将创建一个对象来保存n的状态:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

有些人可能更喜欢显式Python方法,因为它在概念上更加清晰,即使它有些冗长。您可以像存储其他任何内容一样存储状态。您只需要围绕可调用对象的想法就可以了。但是,无论人们从审美角度偏爱哪种方法,它的确表明了一个方面,即Ruby lambda比Python更强大。

Another difference in lambdas between Python and Ruby is demonstrated by Paul Graham’s Accumulator Generator problem. Reprinted here:

Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i. Note: (a) that’s number, not integer, (b) that’s incremented by, not plus.

In Ruby, you can do this:

def foo(n)
  lambda {|i| n += i }
end

In Python, you’d create an object to hold the state of n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

Some folks might prefer the explicit Python approach as being clearer conceptually, even if it’s a bit more verbose. You store state like you do for anything else. You just need to wrap your head around the idea of callable objects. But regardless of which approach one prefers aesthetically, it does show one respect in which Ruby lambdas are more powerful constructs than Python’s.


回答 26

python已命名可选参数

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby仅定位参数,因为函数声明中的b = 2是始终附加的影响。

python has named optional arguments

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby has only positioned arguments because b=2 in the function declaration is an affectation that always append.


回答 27

Ruby嵌入了文档:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

Ruby has embedded documentation:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

回答 28


回答 29

在Ruby中,当您导入带有require的文件时,该文件中定义的所有内容都将最终存储在全局命名空间中。

使用Cargo,您可以“在不干扰命名空间的情况下要求提供库 ”。

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = import(“ foo-1.0.0”)
>> Foo2 = import(“ foo-2.0.0”)
>> Foo1 :: VERSION
=>“ 1.0.0”
>> Foo2 :: VERSION
=>“ 2.0.0”

In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace.

With Cargo you can “require libraries without cluttering your namespace“.

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = import("foo-1.0.0")
>> Foo2 = import("foo-2.0.0")
>> Foo1::VERSION
=> "1.0.0"
>> Foo2::VERSION
=> "2.0.0"

是什么阻碍了Ruby,Python获得Javascript V8速度?[关闭]

问题:是什么阻碍了Ruby,Python获得Javascript V8速度?[关闭]

V8引擎是否有任何阻止优化实现(例如内联缓存)的Ruby / Python功能?

Python由Google家伙共同开发,因此不应被软件专利所阻止。

还是这与Google投入V8项目的资源有关。

Are there any Ruby / Python features that are blocking implementation of optimizations (e.g. inline caching) V8 engine has?

Python is co-developed by Google guys so it shouldn’t be blocked by software patents.

Or this is rather matter of resources put into the V8 project by Google.


回答 0

是什么阻碍了Ruby,Python获得Javascript V8速度?

没有。

好吧,好的:钱。(还有时间,人员,资源,但是如果您有钱,就可以购买。)

V8拥有一支由精明,高度专业,经验丰富(因此薪资很高)的工程师组成的团队,他们在创建高性能执行方面拥有数十年的经验(我个人是在讲话,而集体而言更像是几个世纪)动态OO语言的引擎。他们基本上都是创建Sun HotSpot JVM的人(还有许多其他人)。

首席开发人员Lars Bak实际上从事VM已有25年的历史(并且所有这些VM都达到了V8版本),这基本上就是他的整个(职业)生涯。有些编写Ruby VM的人甚至不到25岁。

是否有任何Ruby / Python功能阻止V8引擎执行优化(例如,内联缓存)?

至少考虑到IronRuby,JRuby,MagLev,MacRuby和Rubinius具有单态(IronRuby)或多态内联缓存,答案显然不是。

现代Ruby实现已经进行了大量优化。例如,对于某些操作,Rubinius的Hash类比YARV的类要快。现在,这听起来并不令人兴奋,直到您意识到Rubinius的Hash类是在100%纯Ruby中实现的,而YARV的类是在100%手动优化的C中实现的。

因此,至少在某些情况下,Rubinius可以生成比GCC更好的代码!

还是这与Google投入V8项目的资源有关。

是。不只是谷歌。V8的源代码沿袭至今已有25年的历史了。使用V8的人还创建了Self VM(迄今为止,这是迄今为止创建的最快的动态OO语言执行引擎之一),Animorphic Smalltalk VM(迄今为止,是迄今为止创建的最快的Smalltalk执行引擎之一),HotSpot JVM(有史以来最快的JVM,可能是最快的VM周期)和OOVM(有史以来最高效的Smalltalk VM之一)。

实际上,V8的首席开发人员Lars Bak致力于其中每一个,以及其他一些人。

What blocks Ruby, Python to get Javascript V8 speed?

Nothing.

Well, okay: money. (And time, people, resources, but if you have money, you can buy those.)

V8 has a team of brilliant, highly-specialized, highly-experienced (and thus highly-paid) engineers working on it, that have decades of experience (I’m talking individually – collectively it’s more like centuries) in creating high-performance execution engines for dynamic OO languages. They are basically the same people who also created the Sun HotSpot JVM (among many others).

Lars Bak, the lead developer, has been literally working on VMs for 25 years (and all of those VMs have lead up to V8), which is basically his entire (professional) life. Some of the people writing Ruby VMs aren’t even 25 years old.

Are there any Ruby / Python features that are blocking implementation of optimizations (e.g. inline caching) V8 engine has?

Given that at least IronRuby, JRuby, MagLev, MacRuby and Rubinius have either monomorphic (IronRuby) or polymorphic inline caching, the answer is obviously no.

Modern Ruby implementations already do a great deal of optimizations. For example, for certain operations, Rubinius’s Hash class is faster than YARV’s. Now, this doesn’t sound terribly exciting until you realize that Rubinius’s Hash class is implemented in 100% pure Ruby, while YARV’s is implemented in 100% hand-optimized C.

So, at least in some cases, Rubinius can generate better code than GCC!

Or this is rather matter of resources put into the V8 project by Google.

Yes. Not just Google. The lineage of V8’s source code is 25 years old now. The people who are working on V8 also created the Self VM (to this day one of the fastest dynamic OO language execution engines ever created), the Animorphic Smalltalk VM (to this day one of the fastest Smalltalk execution engines ever created), the HotSpot JVM (the fastest JVM ever created, probably the fastest VM period) and OOVM (one of the most efficient Smalltalk VMs ever created).

In fact, Lars Bak, the lead developer of V8, worked on every single one of those, plus a few others.


回答 1

高度优化JavaScript解释器的动力更大,这就是为什么我们看到Mozilla,Google和Microsoft之间投入了大量资源的原因。JavaScript必须在(通常是不耐烦的)人在等待时进行下载,解析,编译和实时运行,它必须在有人与之交互时运行,并且它是在不受控制的客户端中进行的可以是计算机,电话或烤面包机的环境。为了有效地在这些条件下运行,它必须高效。

Python和Ruby在开发人员/部署者控制的环境中运行。通常,功能强大的服务器或台式机系统的限制因素将是诸如内存或磁盘I / O之类的因素,而不是执行时间。或者在可以利用非引擎优化(例如缓存)的地方。对于这些语言,将重点放在语言和库功能集而不是速度优化上可能更有意义。

这样做的附带好处是,我们有两个出色的高性能开源JavaScript引擎,这些引擎可以并且正在重新用于所有类型的应用程序,例如Node.js。

There’s a lot more impetus to highly optimize JavaScript interpretors which is why we see so many resources being put into them between Mozilla, Google, and Microsoft. JavaScript has to be downloaded, parsed, compiled, and run in real time while a (usually impatient) human being is waiting for it, it has to run WHILE a person is interacting with it, and it’s doing this in an uncontrolled client-end environment that could be a computer, a phone, or a toaster. It HAS to be efficient in order to run under these conditions effectively.

Python and Ruby are run in an environment controlled by the developer/deployer. A beefy server or desktop system generally where the limiting factor will be things like memory or disk I/O and not execution time. Or where non-engine optimizations like caching can be utilized. For these languages it probably does make more sense to focus on language and library feature set over speed optimization.

The side benefit of this is that we have two great high performance open source JavaScript engines that can and are being re-purposed for all manner of applications such as Node.js.


回答 2

其中很大一部分与社区有关。大多数情况下,Python和Ruby没有公司的支持。没有人获得全职从事Python和Ruby工作的报酬(尤其是他们没有获得始终从事CPython或MRI工作的报酬)。另一方面,V8得到了世界上最强大的IT公司的支持。

此外,V8可以更快,因为对V8员工唯一重要的是解释器-他们没有标准的库可以使用,也无需担心语言设计。他们只是写翻译。而已。

它与知识产权法无关。Python也不是由Google伙计共同开发的(它的创建者与其他一些提交者在那儿一起工作,但是在Python上工作他们没有得到报酬)。

Python 3的另一个障碍是Python3。它的采用似乎是语言开发人员的主要关注点,以至于他们冻结了新语言功能的开发,直到其他实现赶上来。

关于技术细节,我对Ruby不太了解,但是Python在很多地方都可以使用优化功能(Google项目Unladen Swallow在开始努力之前就开始实现这些功能)。这是他们计划的一些优化。如果为CPython实现JIT la PyPy,我可以看到Python在将来获得V8的速度,但这在未来几年似乎不太可能(目前的重点是采用Python 3,而不是JIT)。

许多人还认为Ruby和Python可以从删除各自的全局解释器锁中受益匪浅。

您还必须了解Python和Ruby都是比JS重得多的语言-它们以标准库,语言功能和结构的方式提供了更多内容。单独的面向对象的类系统增加了很多权重(我认为这是一种很好的方式)。我几乎认为Javascript是一种旨在嵌入的语言,例如Lua(在许多方面,它们是相似的)。Ruby和Python具有更丰富的功能集,而表现力通常是以速度为代价的。

A good part of it has to do with community. Python and Ruby for the most part have no corporate backing. No one gets paid to work on Python and Ruby full-time (and they especially don’t get paid to work on CPython or MRI the whole time). V8, on the other hand, is backed by the most powerful IT company in the world.

Furthermore, V8 can be faster because the only thing that matters to the V8 people is the interpreter — they have no standard library to work on, no concerns about language design. They just write the interpreter. That’s it.

It has nothing to do with intellectual property law. Nor is Python co-developed by Google guys (its creator works there along with a few other committers, but they don’t get paid to work on Python).

Another obstacle to Python speed is Python 3. Its adoption seems to be the main concern of the language developers — to the point that they have frozen development of new language features until other implementations catch up.

On to the technical details, I don’t know much about Ruby, but Python has a number of places where optimizations could be used (and Unladen Swallow, a Google project, started to implement these before biting the dust). Here are some of the optimizations that they planned. I could see Python gaining V8 speed in the future if a JIT a la PyPy gets implemented for CPython, but that does not seem likely for the coming years (the focus right now is Python 3 adoption, not a JIT).

Many also feel that Ruby and Python could benefit immensely from removing their respective global interpreter locks.

You also have to understand that Python and Ruby are both much heavier languages than JS — they provide far more in the way of standard library, language features, and structure. The class system of object-orientation alone adds a great deal of weight (in a good way, I think). I almost think of Javascript as a language designed to be embedded, like Lua (and in many ways, they are similar). Ruby and Python have a much richer set of features, and that expressiveness is usually going to come at the cost of speed.


回答 3

性能似乎并不是核心Python开发人员的主要关注点,他们似乎认为“足够快”足够好,并且帮助程序员提高生产率的功能比帮助计算机更快地运行代码的功能更为重要。

但是,确实的确有一个Google项目(现在已被废弃),未满载吞咽,用于生成与标准解释器兼容的更快的Python解释器。PyPy是另一个旨在产生更快的Python的项目。还有PsyPy的先驱PsycoCython,它们可以在不更改整个解释器的情况下提高许多Python脚本的性能,而Cython则可以让您使用非常类似于Python语法的方式为Python编写高性能的C库。

Performance doesn’t seem to be a major focus of the core Python developers, who seem to feel that “fast enough” is good enough, and that features that help programmers be more productive are more important than features that help computers run code faster.

Indeed, however, there was a (now abandoned) Google project, unladen-swallow, to produce a faster Python interpreter compatible with the standard interpreter. PyPy is another project that intends to produce a faster Python. There is also Psyco, the forerunner of PyPy, which can provide performance boosts to many Python scripts without changing out the whole interpreter, and Cython, which lets you write high-performance C libraries for Python using something very much like Python syntax.


回答 4

误导性的问题。V8是JavaScript的JIT(即时编译器)实现,在其最流行的非浏览器实现Node.js中,它是围绕事件循环构建的。CPython不是JIT,也不是事件。但是这些在PyPy项目中最普遍地存在于Python中-一个兼容CPython 2.7(不久将成为3.0+)的JIT。并且有大量事件服务器库,例如Tornado。在运行Tornado与Node.js的PyPy之间存在真实的测试,并且性能差异很小。

Misleading question. V8 is a JIT (a just in time compiler) implementation of JavaScript and in its most popular non-browser implementation Node.js it is constructed around an event loop. CPython is not a JIT & not evented. But these exist in Python most commonly in the PyPy project – a CPython 2.7 (and soon to be 3.0+) compatible JIT. And there are loads of evented server libraries like Tornado for example. Real world tests exist between PyPy running Tornado vs Node.js and the performance differences are slight.


回答 5

我只是遇到了这个问题,而性能差异也有一个未提及的重大技术原因。Python拥有功能强大的软件扩展的庞大生态系统,但是其中大多数扩展都是用C或其他低级语言编写的,以提高性能,并且与CPython API紧密相关。

有许多众所周知的技术(JIT,现代垃圾收集器等)可用于加速CPython实现,但是所有这些都需要对API进行实质性更改,从而破坏了该过程中的大多数扩展。CPython会更快,但是很多使Python如此吸引人的东西(广泛的软件堆栈)将会丢失。恰当的例子是,那里有几种更快的Python实现,但是与CPython相比,它们几乎没有吸引力。

I just ran across this question and there is also a big technical reason for the performance difference that wasn’t mentioned. Python has a very large ecosystem of powerful software extensions, but most of these extensions are written in C or other low-level languages for performance and are heavily tied to the CPython API.

There are lots of well-known techniques (JIT, modern garbage collector, etc) that could be used to speed up the CPython implementation but all would require substantial changes to the API, breaking most of the extensions in the process. CPython would be faster, but a lot of what makes Python so attractive (the extensive software stack) would be lost. Case in point, there are several faster Python implementations out there but they have little traction compared to CPython.


回答 6

由于不同的设计优先级和用例目标,我相信。

通常,脚本(aka动态)语言的主要目的是成为本机函数调用之间的“胶水”。这些本机功能应a)覆盖最关键/经常使用的区域,并且b)尽可能有效。

这是一个示例: 导致iOS Safari冻结jQuery排序冻结是由于过度使用了按选择器调用而引起的。如果按选择器获取将以本机代码实现并且有效,那么根本就不会出现这样的问题。

考虑ray-tracer演示,它是V8演示的常用演示。在Python世界中,由于Python提供了本机扩展的所有功能,因此可以用本机代码实现。但是在V8领域(客户端沙箱)中,您没有其他选择,只能使VM发挥更大的作用。因此,唯一的选择是使用脚本代码来查看ray-tracer的实现。

因此有不同的优先事项和动机。

Sciter中,我通过本地实现几乎完整的jQurey核心进行了测试。在诸如ScIDE(由HTML / CSS / Script制成的IDE)之类的实际任务上,我相信这种解决方案比任何VM优化都有效。

Because of different design priorities and use case goals I believe.

In general main purpose of scripting (a.k.a. dynamic) languages is to be a “glue” between calls of native functions. And these native functions shall a) cover most critical/frequently used areas and b) be as effective as possible.

Here is an example: jQuery sort causing iOS Safari to freeze The freeze there is caused by excessive use of get-by-selector calls. If get-by-selector would be implemented in native code and effectively it will be no such problem at all.

Consider ray-tracer demo that is frequently used demo for V8 demonstration. In Python world it can be implemented in native code as Python provides all facilities for native extensions. But in V8 realm (client side sandbox) you have no other options rather than making VM to be [sub]effective as possible. And so the only option see ray-tracer implementation there is by using script code.

So different priorities and motivations.

In Sciter I’ve made a test by implementing pretty much full jQurey core natively. On practical tasks like ScIDE (IDE made of HTML/CSS/Script) I believe such solution works significantly better then any VM optimizations.


回答 7

正如其他人所提到的,Python具有PyPy形式的高性能JIT编译器。

进行有意义的基准测试总是很微妙的,但是我碰巧有一个用不同语言编写的K均值的简单基准测试-您可以在这里找到。约束之一是,各种语言都应实现相同的算法,并应努力做到简单和惯用(相对于速度优化而言)。我已经编写了所有实现,所以我知道我没有被欺骗,尽管我不能对所有语言都声称我所写的东西是惯用的(我只对其中的一些有所了解)。

我没有任何明确的结论,但是PyPy是我得到的最快的实现之一,远胜于Node。相反,CPython是排名最慢的一端。

As other people have mentioned, Python has a performant JIT compiler in the form of PyPy.

Making meaningful benchmarks is always subtle, but I happen to have a simple benchmark of K-means written in different languages – you can find it here. One of the constraints was that the various languages should all implement the same algorithm and should strive to be simple and idiomatic (as opposed to optimized for speed). I have written all the implementations, so I know I have not cheated, although I cannot claim for all languages that what I have written is idiomatic (I only have a passing knowledge of some of those).

I do not claim any definitive conclusion, but PyPy was among the fastest implementations I got, far better than Node. CPython, instead, was at the slowest end of the ranking.


回答 8

该说法不完全正确

就像V8只是JS的实现一样,CPython也是Python的一种实现。Pypy具有与V8匹配的性能

此外,还存在可感知的性能问题:由于V8本质上是非阻塞的,因此Web开发人员可以节省更多的IO等待,从而导致性能更高的项目。V8主要用于以IO为关键的dev Web,因此他们将其与类似项目进行了比较。但是您可以在Web开发人员之外的许多其他领域中使用Python。您甚至可以使用C扩展来完成许多任务,例如科学计算或加密,并以出色的性能处理数据。

但是在网络上,最流行的Python和Ruby项目正在阻止。尤其是Python,它具有同步WSGI标准的遗产,像著名的Django之类的框架都基于它。

您可以编写异步Python(例如Twisted,Tornado,gevent或asyncio)或Ruby。但是它并不经常执行。最好的工具仍在阻塞。

但是,这是为什么Ruby和Python中的默认实现没有V8这么快的一些原因。

经验

就像JörgW Mittag指出的那样,从事V8工作的人都是VM天才。Python是一群热情的开发人员,在很多领域都非常擅长,但并不擅长VM调优。

资源资源

Python软件基金会的资金很少:一年不到40K的资金来投资Python。当您认为像Google,Facebook或Apple这样的大公司都在使用Python时,这有点疯狂,但这是一个丑陋的事实:大多数工作都是免费完成的。自愿者在Java手工制作之前为Youtube提供支持的语言。

他们是聪明而敬业的志愿者,但是当他们确定自己在田间需要更多果汁时,就无法要求30万聘请该领域的顶尖专家。他们必须四处寻找免费提供服务的人。

在此有效的同时,这意味着您必须非常注意自己的优先事项。因此,现在我们需要查看:

目标

即使具有最新的现代功能,编写Java脚本也很糟糕。您遇到范围问题,集合极少,可怕的字符串和数组操作,几乎没有日期,数学和正则表达式之外的stdlist,甚至对于非常常见的操作也没有语法糖。

但是在V8中,您已经有了速度。

这是因为,速度是Google的主要目标,因为它是Chrome浏览器页面渲染的瓶颈。

在Python中,可用性是主要目标。因为这几乎从来不是项目的瓶颈。这里的稀缺资源是开发人员时间。针对开发人员进行了优化。

The statement is not exactly true

Just like V8 is just an implementation for JS, CPython is just one implementation for Python. Pypy has performances matching V8’s.

Also, there the problem of perceived performance : since V8 is natively non blocking, Web dev leads to more performant projects because you save the IO wait. And V8 is mainly used for dev Web where IO is key, so they compare it to similar projects. But you can use Python in many, many other areas than web dev. And you can even use C extensions for a lot of tasks, such as scientific computations or encryption, and crunch data with blazing perfs.

But on the web, most popular Python and Ruby projects are blocking. Python, especially, has the legacy of the synchronous WSGI standard, and frameworks like the famous Django are based on it.

You can write asynchronous Python (like with Twisted, Tornado, gevent or asyncio) or Ruby. But it’s not done often. The best tools are still blocking.

However, they are some reasons for why the default implementations in Ruby and Python are not as speedy as V8.

Experience

Like Jörg W Mittag pointed out, the guys working on V8 are VM geniuses. Python is dev by a bunch a passionate people, very good in a lot of domains, but are not as specialized in VM tuning.

Resources

The Python Software foundation has very little money : less than 40k in a year to invest in Python. This is kinda crazy when you think big players such as Google, Facebook or Apple are all using Python, but it’s the ugly truth : most work is done for free. The language that powers Youtube and existed before Java has been handcrafted by volunteers.

They are smart and dedicated volunteers, but when they identify they need more juice in a field, they can’t ask for 300k to hire a top notch specialist for this area of expertise. They have to look around for somebody who would do it for free.

While this works, it means you have to be very a careful about your priorities. Hence, now we need to look at :

Objectives

Even with the latest modern features, writing Javascript is terrible. You have scoping issues, very few collections, terrible string and array manipulation, almost no stdlist apart from date, maths and regexes, and no syntactic sugar even for very common operations.

But in V8, you’ve got speed.

This is because, speed was the main objective for Google, since it’s a bottleneck for page rendering in Chrome.

In Python, usability is the main objective. Because it’s almost never the bottleneck on the project. The scarce resource here is developer time. It’s optimized for the developer.


回答 9

因为JavaScript实现不需要关心其绑定的向后兼容性。

直到最近,JavaScript实现的唯一用户还是Web浏览器。由于安全性要求,仅Web浏览器供应商有权通过向运行时编写绑定来扩展功能。因此,无需保持绑定的C API向后兼容,可以允许Web浏览器开发人员随着JavaScript运行时的发展来更新其源代码。他们反正一起工作。甚至是V8,它是游戏的后来者,也是由一个非常有经验的开发人员领导的,随着它变得越来越好,它也改变了API。

OTOH Ruby(主要)用于服务器端。许多流行的ruby扩展都被编写为C绑定(考虑RDBMS驱动程序)。换句话说,如果不保持兼容性,Ruby永远不会成功。

今天,这种差异在一定程度上仍然存在。使用node.js的开发人员抱怨说,随着V8随着时间的推移更改API,很难保持其本机扩展向后兼容(这是node.js被派生的原因之一)。在这方面,IIRC红宝石仍采取更为保守的方法。

Because JavaScript implementations need not care about backwards compatibility of their bindings.

Until recently the only users of the JavaScript implementations have been web browsers. Due to security requirements, only the web browser vendors had the privilege to extend the functionality by writing bindings to the runtimes. Thus there was no need keep the C API of the bindings backwards compatible, it was permissible to request the web browser developers update their source code as the JavaScript runtimes evolved; they were working together anyways. Even V8, which was a latecomer to the game, and also lead by a very very experienced developer, have changed the API as it became better.

OTOH Ruby is used (mainly) on the server-side. Many popular ruby extensions are written as C bindings (consider an RDBMS driver). In other words, Ruby would have never succeeded without maintaining the compatibility.

Today, the difference still exist to some extent. Developers using node.js are complaining that it is hard to keep their native extensions backwards compatible, as V8 changes the API over time (and that is one of the reasons node.js has been forked). IIRC ruby is still taking a much more conservative approach in this respect.


回答 10

由于JIT,曲轴,类型推断器和数据优化代码,V8速度很快。标记指针,NaN标记双打。当然,它在中间进行常规的编译器优化。

普通的ruby,python和perl引擎都不会做这些,而只是进行一些基本的优化。

唯一接近的主要虚拟机是luajit,它甚至不进行类型推断,常量折叠,NaN标记或整数,但是使用类似的小代码和数据结构,不如不良语言那么胖。我的原型动态语言potion和p2具有与luajit类似的功能,并且胜过v8。使用可选的类型系统“渐进式键入”,您可以轻松超越v8,因为您可以绕过曲轴。参见飞镖。

已知的优化后端(如pypy或jruby)仍然遭受各种过度设计技术的困扰。

V8 is fast due to the JIT, Crankshaft, the type inferencer and data-optimized code. Tagged pointers, NaN-tagging of doubles. And of course it does normal compiler optimizations in the middle.

The plain ruby, python and perl engines don’t do neither of the those, just minor basic optimizations.

The only major vm which comes close is luajit, which doesn’t even do type inference, constant folding, NaN-tagging nor integers, but uses similar small code and data structures, not as fat as the bad languages. And my prototype dynamic languages, potion and p2 have similar features as luajit, and outperform v8. With an optional type system, “gradual typing”, you could easily outperform v8, as you can bypass crankshaft. See dart.

The known optimized backends, like pypy or jruby still suffer from various over-engineering techniques.


Mal-MAL-做一个Lisp

MAL-做一个Lisp

描述

1.Mal是一个受Clojure启发的Lisp解释器

2.MAL是一种学习工具

MAL的每个实现被分成11个增量的、自包含的(且可测试的)步骤,这些步骤演示了Lisp的核心概念。最后一步是能够自托管(运行mal的错误实现)。请参阅make-a-lisp process
guide

Make-a-LISP步骤包括:

每个Make-a-LISP步骤都有一个关联的架构图。该步骤的新元素以红色高亮显示。以下是step A

如果您对创建mal实现感兴趣(或者只是对使用mal做某事感兴趣),欢迎您加入我们的Discord或加入#mal onlibera.chat除了make-a-lisp
process guide
还有一个mal/make-a-lisp
FAQ
在这里我试图回答一些常见的问题

3.MAL用86种语言实现(91种不同实现,113种运行模式)

语言 创建者
Ada Chris Moore
Ada #2 Nicolas Boulenguez
GNU Awk Miutsuru Kariya
Bash 4 Joel Martin
BASIC(C64和QBASIC) Joel Martin
BBC BASIC V Ben Harris
C Joel Martin
C #2 Duncan Watts
C++ Stephen Thirlwall
C# Joel Martin
ChucK Vasilij Schneidermann
Clojure(Clojure和ClojureScript) Joel Martin
CoffeeScript Joel Martin
Common Lisp Iqbal Ansari
Crystal Linda_pp
D Dov Murik
Dart Harry Terkelsen
Elixir Martin Ek
Elm Jos van Bakel
Emacs Lisp Vasilij Schneidermann
Erlang Nathan Fiedler
ES6(ECMAScript 2015) Joel Martin
F# Peter Stephens
Factor Jordan Lewis
Fantom Dov Murik
Fennel sogaiu
Forth Chris Houser
GNU Guile Mu Lei
GNU Smalltalk Vasilij Schneidermann
Go Joel Martin
Groovy Joel Martin
Haskell Joel Martin
Haxe(Neko、Python、C++和JS) Joel Martin
Hy Joel Martin
Io Dov Murik
Janet sogaiu
Java Joel Martin
Java(松露/GraalVM) Matt McGill
JavaScript(Demo) Joel Martin
jq Ali MohammadPur
Julia Joel Martin
Kotlin Javier Fernandez-Ivern
LiveScript Jos van Bakel
Logo Dov Murik
Lua Joel Martin
GNU Make Joel Martin
mal itself Joel Martin
MATLAB(GNU Octave&MATLAB) Joel Martin
miniMAL(RepoDemo) Joel Martin
NASM Ben Dudson
Nim Dennis Felsing
Object Pascal Joel Martin
Objective C Joel Martin
OCaml Chris Houser
Perl Joel Martin
Perl 6 Hinrik Örn Sigurðsson
PHP Joel Martin
Picolisp Vasilij Schneidermann
Pike Dov Murik
PL/pgSQL(PostgreSQL) Joel Martin
PL/SQL(Oracle) Joel Martin
PostScript Joel Martin
PowerShell Joel Martin
Prolog Nicolas Boulenguez
Python(2.x和3.x) Joel Martin
Python #2(3.x) Gavin Lewis
RPython Joel Martin
R Joel Martin
Racket Joel Martin
Rexx Dov Murik
Ruby Joel Martin
Rust Joel Martin
Scala Joel Martin
Scheme (R7RS) Vasilij Schneidermann
Skew Dov Murik
Standard ML Fabian Bergström
Swift 2 Keith Rollin
Swift 3 Joel Martin
Swift 4 陆遥
Swift 5 Oleg Montak
Tcl Dov Murik
TypeScript Masahiro Wakame
Vala Simon Tatham
VHDL Dov Murik
Vimscript Dov Murik
Visual Basic.NET Joel Martin
WebAssembly(WASM) Joel Martin
Wren Dov Murik
XSLT Ali MohammadPur
Yorick Dov Murik
Zig Josh Tobin

演示文稿

Mal第一次出现在2014年Clojure West的闪电演讲中(不幸的是没有视频)。参见Examples/clojurewest2014.mal了解会议上的演示文稿(是的,该演示文稿是一个MALL程序)

在Midwest.io 2015上,乔尔·马丁(Joel Martin)就MAL做了题为“解锁的成就:一条更好的语言学习之路”的演讲VideoSlides

最近,乔尔在LambdaConf 2016大会上发表了题为“用10个增量步骤打造自己的Lisp解释器”的演讲:Part 1Part 2Part 3Part 4Slides

构建/运行实现

运行任何给定实现的最简单方法是使用docker。每个实现都有一个预先构建的停靠器映像,其中安装了语言依赖项。您可以在顶层Makefile中使用一个方便的目标启动REPL(其中impl是实现目录名,stepX是要运行的步骤):

make DOCKERIZE=1 "repl^IMPL^stepX"
    # OR stepA is the default step:
make DOCKERIZE=1 "repl^IMPL"

外部实现

以下实施作为单独的项目进行维护:

HolyC

生锈

  • by Tim Morgan
  • by vi-使用Pest语法,不使用典型的MAL基础设施(货币化步骤和内置的转换测试)

问:

  • by Ali Mohammad Pur-Q实现运行良好,但它需要专有的手动下载,不能Docker化(或集成到mal CI管道中),因此目前它仍然是一个单独的项目

其他MAL项目

  • malc详细说明:MAL(Make A Lisp)编译器。将MAL程序编译成LLVM汇编语言,然后编译成二进制
  • malcc-malcc是MAL语言的增量编译器实现。它使用微型C编译器作为编译器后端,并且完全支持MAL语言,包括宏、尾部调用消除,甚至运行时求值。“I Built a Lisp Compiler”发布有关该过程的帖子
  • frock+Clojure风格的PHP。使用mal/php运行程序
  • flk-无论Bash在哪里都可以运行的LISP
  • glisp详细说明:基于Lisp的自引导图形设计工具。Live Demo

实施详情

Ada

Ada实现是在Debian上使用GNAT4.9开发的。如果您有git、gnat和make(可选)的windows版本,它也可以在windows上编译而不变。没有外部依赖项(未实现ReadLine)

cd impls/ada
make
./stepX_YYY

Ada.2

第二个Ada实现是使用GNAT 8开发的,并与GNU读取线库链接

cd impls/ada
make
./stepX_YYY

GNU awk

Mal的GNU awk实现已经使用GNU awk 4.1.1进行了测试

cd impls/gawk
gawk -O -f stepX_YYY.awk

BASH 4

cd impls/bash
bash stepX_YYY.sh

基本(C64和QBasic)

Basic实现使用一个预处理器,该预处理器可以生成与C64 Basic(CBMv2)和QBasic兼容的Basic代码。C64模式已经过测试cbmbasic(当前需要打补丁的版本来修复线路输入问题),并且QBasic模式已经过测试qb64

生成C64代码并使用cbmbasic运行:

cd impls/basic
make stepX_YYY.bas
STEP=stepX_YYY ./run

生成QBasic代码并加载到qb64中:

cd impls/basic
make MODE=qbasic stepX_YYY.bas
./qb64 stepX_YYY.bas

感谢Steven Syrek有关此实现的原始灵感,请参阅

BBC Basic V

BBC Basic V实现可以在Brandy解释器中运行:

cd impls/bbc-basic
brandy -quit stepX_YYY.bbc

或在RISC OS 3或更高版本下的ARM BBC Basic V中:

*Dir bbc-basic.riscos
*Run setup
*Run stepX_YYY

C

mal的C实现需要以下库(lib和头包):glib、libffi6、libgc以及libedit或GNU readline库

cd impls/c
make
./stepX_YYY

C.2

mal的第二个C实现需要以下库(lib和头包):libedit、libgc、libdl和libffi

cd impls/c.2
make
./stepX_YYY

C++

构建mal的C++实现需要g++-4.9或clang++-3.5和readline兼容库。请参阅cpp/README.md有关更多详细信息,请执行以下操作:

cd impls/cpp
make
    # OR
make CXX=clang++-3.5
./stepX_YYY

C#

mal的C#实现已经在Linux上使用Mono C#编译器(MCS)和Mono运行时(2.10.8.1版)进行了测试。两者都是构建和运行C#实现所必需的

cd impls/cs
make
mono ./stepX_YYY.exe

卡盘

Chuck实现已经使用Chuck 1.3.5.2进行了测试

cd impls/chuck
./run

封闭式

在很大程度上,Clojure实现需要Clojure 1.5,然而,要通过所有测试,则需要Clojure 1.8.0-RC4

cd impls/clojure
lein with-profile +stepX trampoline run

CoffeeScript

sudo npm install -g coffee-script
cd impls/coffee
coffee ./stepX_YYY

通用Lisp

该实现已经在Ubuntu 16.04和Ubuntu 12.04上使用SBCL、CCL、CMUCL、GNU CLISP、ECL和Allegro CL进行了测试,请参阅README了解更多详细信息。如果您安装了上述依赖项,请执行以下操作来运行实现

cd impls/common-lisp
make
./run

水晶

MAL的晶体实现已经用Crystal 0.26.1进行了测试

cd impls/crystal
crystal run ./stepX_YYY.cr
    # OR
make   # needed to run tests
./stepX_YYY

D

使用GDC4.8对MAL的D实现进行了测试。它需要GNU读取线库

cd impls/d
make
./stepX_YYY

省道

DART实施已使用DART 1.20进行了测试

cd impls/dart
dart ./stepX_YYY

Emacs Lisp

Emacs Lisp的MAL实现已经使用Emacs 24.3和24.5进行了测试。虽然有非常基本的读数行编辑(<backspace>C-d工作,C-c取消进程),建议使用rlwrap

cd impls/elisp
emacs -Q --batch --load stepX_YYY.el
# with full readline support
rlwrap emacs -Q --batch --load stepX_YYY.el

灵丹妙药

MAL的长生不老的实现已经在长生不老的长生不老的1.0.5中进行了测试

cd impls/elixir
mix stepX_YYY
# Or with readline/line editing functionality:
iex -S mix stepX_YYY

榆树

MAL的ELM实现已经用ELM 0.18.0进行了测试

cd impls/elm
make stepX_YYY.js
STEP=stepX_YYY ./run

二郎

Mal的Erlang实现需要Erlang/OTP R17rebar要建造

cd impls/erlang
make
    # OR
MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
./stepX_YYY

ES6(ECMAScript 2015)

ES6/ECMAScript 2015实施使用babel用于生成ES5兼容JavaScript的编译器。生成的代码已经在Node 0.12.4上进行了测试

cd impls/es6
make
node build/stepX_YYY.js

F#

mal的F#实现已经在Linux上使用Mono F#编译器(Fsharpc)和Mono运行时(版本3.12.1)进行了测试。单C#编译器(MCS)也是编译readline依赖项所必需的。所有这些都是构建和运行F#实现所必需的

cd impls/fsharp
make
mono ./stepX_YYY.exe

因素

MAL的因子实现已通过因子0.97(factorcode.org)

cd impls/factor
FACTOR_ROOTS=. factor -run=stepX_YYY

幻影

MAL的幻象实现已经用幻象1.0.70进行了测试

cd impls/fantom
make lib/fan/stepX_YYY.pod
STEP=stepX_YYY ./run

茴香

Mal的Fennel实现已经在Lua5.4上使用Fennel版本0.9.1进行了测试

cd impls/fennel
fennel ./stepX_YYY.fnl

第四

cd impls/forth
gforth stepX_YYY.fs

GNU Guile 2.1+

cd impls/guile
guile -L ./ stepX_YYY.scm

GNU Smalltalk

MALL的Smalltalk实现已经在GNU Smalltalk 3.2.91上进行了测试

cd impls/gnu-smalltalk
./run

MALL的GO实现要求在路径上安装GO。该实现已经在GO 1.3.1上进行了测试

cd impls/go
make
./stepX_YYY

时髦的

mal的Groovy实现需要Groovy才能运行,并且已经使用Groovy 1.8.6进行了测试

cd impls/groovy
make
groovy ./stepX_YYY.groovy

哈斯克尔

Haskell实现需要GHC编译器版本7.10.1或更高版本以及Haskell parsec和readline(或editline)包

cd impls/haskell
make
./stepX_YYY

Haxe(Neko、Python、C++和JavaScript)

Mal的Haxe实现需要编译Haxe3.2版。支持四种不同的Haxe目标:neko、Python、C++和JavaScript

cd impls/haxe
# Neko
make all-neko
neko ./stepX_YYY.n
# Python
make all-python
python3 ./stepX_YYY.py
# C++
make all-cpp
./cpp/stepX_YYY
# JavaScript
make all-js
node ./stepX_YYY.js

干草

MAL的Hy实现已经用Hy 0.13.0进行了测试

cd impls/hy
./stepX_YYY.hy

IO

已使用IO版本20110905测试了MAL的IO实现

cd impls/io
io ./stepX_YYY.io

珍妮特

MAIL的Janet实现已经使用Janet版本1.12.2进行了测试

cd impls/janet
janet ./stepX_YYY.janet

Java 1.7

mal的Java实现需要maven2来构建

cd impls/java
mvn compile
mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
    # OR
mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"

Java,将Truffle用于GraalVM

这个Java实现可以在OpenJDK上运行,但是多亏了Truffle框架,它在GraalVM上的运行速度可以提高30倍。它已经在OpenJDK 11、GraalVM CE 20.1.0和GraalVM CE 21.1.0上进行了测试

cd impls/java-truffle
./gradlew build
STEP=stepX_YYY ./run

JavaScript/节点

cd impls/js
npm install
node stepX_YYY.js

朱莉娅

Mal的Julia实现需要Julia 0.4

cd impls/julia
julia stepX_YYY.jl

JQ

针对1.6版进行了测试,IO部门存在大量作弊行为

cd impls/jq
STEP=stepA_YYY ./run
    # with Debug
DEBUG=true STEP=stepA_YYY ./run

科特林

MAL的Kotlin实现已经使用Kotlin 1.0进行了测试

cd impls/kotlin
make
java -jar stepX_YYY.jar

LiveScript

已使用LiveScript 1.5测试了mal的LiveScript实现

cd impls/livescript
make
node_modules/.bin/lsc stepX_YYY.ls

徽标

MAL的Logo实现已经用UCBLogo 6.0进行了测试

cd impls/logo
logo stepX_YYY.lg

路亚

Mal的Lua实现已经使用Lua 5.3.5进行了测试。该实现需要安装luarock

cd impls/lua
make  # to build and link linenoise.so and rex_pcre.so
./stepX_YYY.lua

男性

运行mal的错误实现包括运行其他实现之一的STEPA,并传递作为命令行参数运行的mal步骤

cd impls/IMPL
IMPL_STEPA_CMD ../mal/stepX_YYY.mal

GNU Make 3.81

cd impls/make
make -f stepX_YYY.mk

NASM

MAL的NASM实现是为x86-64 Linux编写的,并且已经在Linux 3.16.0-4-AMD64和NASM版本2.11.05上进行了测试

cd impls/nasm
make
./stepX_YYY

NIM 1.0.4

MAL的NIM实现已经使用NIM 1.0.4进行了测试

cd impls/nim
make
  # OR
nimble build
./stepX_YYY

对象PASCAL

MAL的对象Pascal实现已经使用Free Pascal编译器版本2.6.2和2.6.4在Linux上构建和测试

cd impls/objpascal
make
./stepX_YYY

目标C

Mal的Objective C实现已经在Linux上使用CLANG/LLVM3.6进行了构建和测试。它还使用XCode7在OS X上进行了构建和测试

cd impls/objc
make
./stepX_YYY

OCaml 4.01.0

cd impls/ocaml
make
./stepX_YYY

MATLAB(GNU倍频程和MATLAB)

MATLAB实现已经在GNU Octave 4.2.1上进行了测试。它还在Linux上用MATLAB版本R2014a进行了测试。请注意,matlab是一个商业产品。

cd impls/matlab
./stepX_YYY
octave -q --no-gui --no-history --eval "stepX_YYY();quit;"
matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
    # OR with command line arguments
octave -q --no-gui --no-history --eval "stepX_YYY('arg1','arg2');quit;"
matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"

极小值

miniMAL是用不到1024字节的JavaScript实现的小型Lisp解释器。要运行mal的最小实现,您需要下载/安装最小解释器(这需要Node.js)

cd impls/miniMAL
# Download miniMAL and dependencies
npm install
export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
# Now run mal implementation in miniMAL
miniMAL ./stepX_YYY

Perl 5

Perl 5实现应该使用Perl 5.19.3和更高版本

要获得读取行编辑支持,请从CPAN安装Term::ReadLine::Perl或Term::ReadLine::GNU

cd impls/perl
perl stepX_YYY.pl

Perl 6

Perl6实现在Rakudo Perl6 2016.04上进行了测试

cd impls/perl6
perl6 stepX_YYY.pl

PHP 5.3

mal的PHP实现需要php命令行界面才能运行

cd impls/php
php stepX_YYY.php

皮奥利普

Picolisp实现需要libreadline和Picolisp 3.1.11或更高版本

cd impls/picolisp
./run

派克

Pike实现在Pike8.0上进行了测试

cd impls/pike
pike stepX_YYY.pike

pl/pgSQL(PostgreSQL SQL过程语言)

mal的PL/pgSQL实现需要一个正在运行的PostgreSQL服务器(“kanaka/mal-test-plpgsql”docker映像自动启动PostgreSQL服务器)。该实现连接到PostgreSQL服务器并创建名为“mal”的数据库来存储表和存储过程。包装器脚本使用psql命令连接到服务器,并默认为用户“postgres”,但可以使用PSQL_USER环境变量覆盖该值。可以使用PGPASSWORD环境变量指定密码。该实现已使用PostgreSQL 9.4进行了测试

cd impls/plpgsql
./wrap.sh stepX_YYY.sql
    # OR
PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql

PL/SQL(Oracle SQL过程语言)

mal的PL/SQL实现需要一个正在运行的Oracle DB服务器(“kanaka/mal-test-plsql”docker映像自动启动Oracle Express服务器)。该实现连接到Oracle服务器以创建类型、表和存储过程。默认的SQL*Plus登录值(用户名/口令@CONNECT_IDENTIFIER)是“SYSTEM/ORACLE”,但是可以用ORACLE_LOGON环境变量覆盖该值。该实施已使用Oracle Express Edition 11g Release 2进行了测试。请注意,任何SQL*Plus连接警告(用户密码过期等)都会干扰包装脚本与数据库通信的能力

cd impls/plsql
./wrap.sh stepX_YYY.sql
    # OR
ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql

PostScript Level 2/3

mal的PostScript实现需要运行Ghostscript。它已经使用Ghostscript 9.10进行了测试

cd impls/ps
gs -q -dNODISPLAY -I./ stepX_YYY.ps

PowerShell

Mal的PowerShell实现需要PowerShell脚本语言。它已经在Linux上使用PowerShell 6.0.0 Alpha 9进行了测试

cd impls/powershell
powershell ./stepX_YYY.ps1

序言

Prolog实现使用了一些特定于SWI-Prolog的结构,包括READLINE支持,并且已经在8.2.1版的Debian GNU/Linux上进行了测试

cd impls/prolog
swipl stepX_YYY

Python(2.x和3.x)

cd impls/python
python stepX_YYY.py

Python2(3.x)

第二个Python实现大量使用类型注释并使用Arpeggio解析器库

# Recommended: do these steps in a Python virtual environment.
pip3 install Arpeggio==1.9.0
python3 stepX_YYY.py

RPython

你一定是rpython在您的路径上(随附pypy)

cd impls/rpython
make        # this takes a very long time
./stepX_YYY

R

MALL R实现需要R(r-base-core)来运行

cd impls/r
make libs  # to download and build rdyncall
Rscript stepX_YYY.r

球拍(5.3)

Mal的racket实现需要运行racket编译器/解释器

cd impls/racket
./stepX_YYY.rkt

雷克斯

Mal的Rexx实现已经使用Regina Rexx 3.6进行了测试

cd impls/rexx
make
rexx -a ./stepX_YYY.rexxpp

拼音(1.9+)

cd impls/ruby
ruby stepX_YYY.rb

生锈(1.38+)

Mal的Rust实现需要使用Rust编译器和构建工具(Cargo)来构建

cd impls/rust
cargo run --release --bin stepX_YYY

缩放比例

安装Scala和SBT(http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):

cd impls/scala
sbt 'run-main stepX_YYY'
    # OR
sbt compile
scala -classpath target/scala*/classes stepX_YYY

方案(R7RS)

MAL的方案实施已在赤壁-方案0.7.3、卡瓦2.4、高车0.9.5、鸡肉4.11.0、人马座0.8.3、气旋0.6.3(Git版本)和Foment 0.4(Git版本)上进行了测试。在弄清库是如何加载的并调整了R7RS实现的基础上,您应该能够让它在其他符合R7RS标准的实现上运行Makefilerun相应地编写脚本

cd impls/scheme
make symlinks
# chibi
scheme_MODE=chibi ./run
# kawa
make kawa
scheme_MODE=kawa ./run
# gauche
scheme_MODE=gauche ./run
# chicken
make chicken
scheme_MODE=chicken ./run
# sagittarius
scheme_MODE=sagittarius ./run
# cyclone
make cyclone
scheme_MODE=cyclone ./run
# foment
scheme_MODE=foment ./run

歪斜

MAL的不对称实现已经使用不对称0.7.42进行了测试

cd impls/skew
make
node stepX_YYY.js

标准ML(Poly/ML、MLton、莫斯科ML)

Mal的标准ML实现需要一个SML97实施。Makefile支持POLY/ML、MLTON、MOVICO ML,并已在POLY/ML 5.8.1、MLTON 20210117和MOSSIONS ML版本2.10上进行了测试

cd impls/sml
# Poly/ML
make sml_MODE=polyml
./stepX_YYY
# MLton
make sml_MODE=mlton
./stepX_YYY
# Moscow ML
make sml_MODE=mosml
./stepX_YYY

斯威夫特

MALL的SWIFT实施需要SWIFT 2.0编译器(XCode 7.0)来构建。由于语言和标准库中的更改,旧版本将无法运行

cd impls/swift
make
./stepX_YYY

斯威夫特3

MALL的SWIFT 3实施需要SWIFT 3.0编译器。它已经在SWIFT 3预览版3上进行了测试

cd impls/swift3
make
./stepX_YYY

斯威夫特4

MALL的SWIFT 4实施需要SWIFT 4.0编译器。它已在SWIFT 4.2.3版本中进行了测试

cd impls/swift4
make
./stepX_YYY

SWIFT 5

MALL的SWIFT 5实施需要SWIFT 5.0编译器。它已在SWIFT 5.1.1版本中进行了测试

cd impls/swift5
swift run stepX_YYY

TCL 8.6

Mal的Tcl实现需要运行Tcl 8.6。要获得readline行编辑支持,请安装tclreadline

cd impls/tcl
tclsh ./stepX_YYY.tcl

打字稿

mal的TypeScript实现需要TypeScript 2.2编译器。它已经在Node.js V6上进行了测试

cd impls/ts
make
node ./stepX_YYY.js

瓦拉

MALL的VALA实现已经用VALA0.40.8编译器进行了测试。您将需要安装valaclibreadline-dev或同等的

cd impls/vala
make
./stepX_YYY

VHDL

用GHDL0.29对mal的vhdl实现进行了测试。

cd impls/vhdl
make
./run_vhdl.sh ./stepX_YYY

Vimscript

Mal的Vimscript实现需要运行Vim 8.0

cd impls/vimscript
./run_vimscript.sh ./stepX_YYY.vim

Visual Basic.NET

Mal的VB.NET实现已经在Linux上使用Mono VB编译器(Vbnc)和Mono运行时(2.10.8.1版)进行了测试。构建和运行VB.NET实现需要两者

cd impls/vb
make
mono ./stepX_YYY.exe

WebAssembly(Wasm)

WebAssembly实现是用Wam(WebAssembly宏语言),并在几种不同的非Web嵌入(运行时)下运行:nodewasmtimewasmerlucetwaxwacewarpy

cd impls/wasm
# node
make wasm_MODE=node
./run.js ./stepX_YYY.wasm
# wasmtime
make wasm_MODE=wasmtime
wasmtime --dir=./ --dir=../ --dir=/ ./stepX_YYY.wasm
# wasmer
make wasm_MODE=wasmer
wasmer run --dir=./ --dir=../ --dir=/ ./stepX_YYY.wasm
# lucet
make wasm_MODE=lucet
lucet-wasi --dir=./:./ --dir=../:../ --dir=/:/ ./stepX_YYY.so
# wax
make wasm_MODE=wax
wax ./stepX_YYY.wasm
# wace
make wasm_MODE=wace_libc
wace ./stepX_YYY.wasm
# warpy
make wasm_MODE=warpy
warpy --argv --memory-pages 256 ./stepX_YYY.wasm

XSLT

mal的XSLT实现是用XSLT3编写的,并在Saxon 9.9.1.6家庭版上进行了测试

cd impls/xslt
STEP=stepX_YY ./run

雷恩

MAL的WREN实现在WREN 0.2.0上进行了测试

cd impls/wren
wren ./stepX_YYY.wren

约里克

MAL的Yorick实现在Yorick 2.2.04上进行了测试

cd impls/yorick
yorick -batch ./stepX_YYY.i

之字形

MAL的Zig实现在Zig0.5上进行了测试

cd impls/zig
zig build stepX_YYY

运行测试

顶层Makefile有许多有用的目标来协助实现、开发和测试。这个helpTarget提供目标和选项的列表:

make help

功能测试

中几乎有800个通用功能测试(针对所有实现)。tests/目录。每个步骤都有相应的测试文件,其中包含特定于该步骤的测试。这个runtest.py测试工具启动MAL步骤实现,然后将测试一次一个提供给实现,并将输出/返回值与预期的输出/返回值进行比较

  • 要在所有实现中运行所有测试(请准备等待):
make test
  • 要针对单个实施运行所有测试,请执行以下操作:
make "test^IMPL"

# e.g.
make "test^clojure"
make "test^js"
  • 要对所有实施运行单个步骤的测试,请执行以下操作:
make "test^stepX"

# e.g.
make "test^step2"
make "test^step7"
  • 要针对单个实施运行特定步骤的测试,请执行以下操作:
make "test^IMPL^stepX"

# e.g
make "test^ruby^step3"
make "test^ps^step4"

自托管功能测试

  • 若要在自托管模式下运行功能测试,请指定mal作为测试实现,并使用MAL_IMPLMake Variable以更改基础主机语言(默认值为JavaScript):
make MAL_IMPL=IMPL "test^mal^step2"

# e.g.
make "test^mal^step2"   # js is default
make MAL_IMPL=ruby "test^mal^step2"
make MAL_IMPL=python "test^mal^step2"

启动REPL

  • 要在特定步骤中启动实施的REPL,请执行以下操作:
make "repl^IMPL^stepX"

# e.g
make "repl^ruby^step3"
make "repl^ps^step4"
  • 如果您省略了这一步,那么stepA使用的是:
make "repl^IMPL"

# e.g
make "repl^ruby"
make "repl^ps"
  • 若要启动自托管实现的REPL,请指定mal作为REPL实现,并使用MAL_IMPLMake Variable以更改基础主机语言(默认值为JavaScript):
make MAL_IMPL=IMPL "repl^mal^stepX"

# e.g.
make "repl^mal^step2"   # js is default
make MAL_IMPL=ruby "repl^mal^step2"
make MAL_IMPL=python "repl^mal"

性能测试

警告:这些性能测试在统计上既不有效,也不全面;运行时性能不是mal的主要目标。如果你从这些性能测试中得出任何严肃的结论,那么请联系我,了解堪萨斯州一些令人惊叹的海滨房产,我愿意以低价卖给你

  • 要针对单个实施运行性能测试,请执行以下操作:
make "perf^IMPL"

# e.g.
make "perf^js"
  • 要对所有实施运行性能测试,请执行以下操作:
make "perf"

正在生成语言统计信息

  • 要报告单个实施的行和字节统计信息,请执行以下操作:
make "stats^IMPL"

# e.g.
make "stats^js"

对接测试

每个实现目录都包含一个Dockerfile,用于创建包含该实现的所有依赖项的docker映像。此外,顶级Makefile还支持在停靠器容器中通过传递以下参数来运行测试目标(以及perf、stats、repl等“DOCKERIZE=1”在make命令行上。例如:

make DOCKERIZE=1 "test^js^step3"

现有实现已经构建了坞站映像,并将其推送到坞站注册表。但是,如果您希望在本地构建或重建坞站映像,TopLevel Makefile提供了构建坞站映像的规则:

make "docker-build^IMPL"

注意事项

  • Docker镜像被命名为“Kanaka/mal-test-iml”
  • 基于JVM的语言实现(Groovy、Java、Clojure、Scala):您可能需要首先手动运行此命令一次make DOCKERIZE=1 "repl^IMPL"然后才能运行测试,因为需要下载运行时依赖项以避免测试超时。这些依赖项被下载到/mal目录中的点文件中,因此它们将在两次运行之间保持不变

许可证

MAL(make-a-lisp)是根据MPL 2.0(Mozilla Public License 2.0)许可的。有关更多详细信息,请参阅LICENSE.txt

Pyroscope-🔥连续性能分析平台🔥调试性能问题可归结为一行代码

Pyroscope是一个开源的连续性能剖析平台。它将帮助您:

  • 查找代码中的性能问题
  • 解决CPU利用率高的问题
  • 了解应用程序的调用树
  • 跟踪随时间变化的情况

🔥Pyroscope Live Demo🔥

功能

  • 可以存储来自多个应用程序的多年性能分析数据
  • 您可以一次查看多年数据,也可以放大特定事件
  • 低CPU开销
  • 高效压缩、低磁盘空间需求
  • 时髦的用户界面
  • 支持Go、Ruby和Python

分3步在本地试用Pyroscope:

# install pyroscope
brew install pyroscope-io/brew/pyroscope

# start pyroscope server:
pyroscope server

# in a separate tab, start profiling your app:
pyroscope exec python manage.py runserver # If using Python
pyroscope exec rails server               # If using Ruby

# If using Pyroscope cloud add flags for server address and auth token
# pyroscope exec -server-address "https://your_company.pyroscope.cloud" -auth-token "ps-key-1234567890" python manage.py runserver

文档

有关如何将Pyroscope与其他编程语言配合使用、在Linux上安装或在生产环境中使用的更多信息,请查看我们的文档:

下载次数

您可以从我们的网站下载适用于MacOS、Linux和Docker的最新版本的PyroscopeDownloads page

支持的集成

  • 红宝石(通过rbspy)
  • Python(通过py-spy)
  • 前往(途经pprof)
  • Linux eBPF(VIAprofile.py从…bcc-tools)
  • PHP(通过phpspy)
  • .NET(通过dotnet trace)
  • Java(即将推出)

请让我们知道您希望在our issues或在our slack

学分

高温镜之所以成为可能,要归功于许多人的出色工作,包括但不限于:

  • 布兰登·格雷格(Brendan Gregg)-火焰图的发明者
  • Julia Evans-Ruby的rbspy采样剖析器的创建者
  • 弗拉基米尔·阿加方金(Vladimir Agafonkin)-火焰手的创建者-快速火焰图形渲染器
  • Ben Frederickson-Python的py-spy采样分析器的创建者
  • Adam Saponara-PHP采样剖析器的创建者
  • Alexei Starovoitov、Brendan Gregg和其他许多使Linux内核中基于BPF的分析成为可能的人

贡献

要开始投稿,请查看我们的Contributing Guide

感谢Pyroscope的贡献者!

Graal-GraalVM:在🚀任何地方更快地运行程序

GraalVM是一个通用虚拟机,用于运行以JavaScript、Python、Ruby、R、基于JVM的语言(如Java、Scala、Clojure、Kotlin)以及基于LLVM的语言(如C和C++)编写的应用程序

项目网站为https://www.graalvm.org描述如何get started,如何stay connected,以及如何contribute

存储库结构

GraalVM主源存储库包括下面列出的组件。每个组件的文档都包括该组件的开发人员说明

  • GraalVM SDK包含长期支持的GraalVM API
  • GraalVM compiler用JAVA编写,支持动态编译和静电编译,可以与JAVA HotSpot VM集成,也可以独立运行
  • Truffle用于创建GraalVM的语言和工具的语言实现框架
  • Tools包含一组使用规范框架实现的GraalVM语言的工具
  • Substrate VM允许在封闭假设下提前(AOT)将Java应用程序编译为可执行映像或共享对象的框架
  • Sulong是用于在GraalVM上运行LLVM位码的引擎
  • GraalWasm是一个用于在GraalVM上运行WebAssembly程序的引擎
  • TRegex是正则表达式的实现,它利用GraalVM高效编译自动机
  • VM包括构建模块化GraalVM映像的组件
  • VS Code提供对Visual Studio代码的扩展,以支持使用GraalVM开发多语言应用程序

获得支持

相关存储库

GraalVM允许使用Truffle和GraalVM编译器在使用GraalVM内核的相关存储库中开发和测试的以下语言运行。这些是:

许可证

每个GraalVM组件均获得许可: