• 谢谢解答

  • 明白了,谢谢各位大神的解答。

  • JIT for MRI 开始开发了 at June 15, 2020

    确实,这个 JIT 有点粗糙了,JVM 的 JIT,V8 的 JIT 等等这些 JIT 可是直接内存生成不依赖其他编译器 (GCC,LLVM 等),希望 Ruby 以后可以慢慢改进吧,毕竟人手有限,直接生成 JIT 没那么简单做出来

  • 谢谢,明白了

  • 你这个是运行啊,我说的是在 cmd 中直接输入 ruby 不加任何东西,似乎会进入到一个输入界面,但我尝试输入任何东西都没有反应,然后你输入 end 就报错推出了,我想问的是这个输入界面有什么用 有人知道吗?

  • 你没懂我的意思,我的意思是可以在某些设计上统一,只是不愿这样做罢了,|x|看上去不是一个很好的选择,完全可以用 lambda 代替

  • 关键字多少与语言看不看得懂没有直接关系,关键字只要够用就可以,其实能不能统一只是现在的结果已经不统一了,然而设计之初如果统一了现在来看也没有什么不妥

  • 我可没转移话题,是你说他们是虾兵蟹将的,这些语言正是因为是多范式的所以也更加灵活,他们不是完全面向对象,但包含了面向对象的思想,那么 ruby 为什么不能反过来在面向对象的基础上加入一些函数式特性呢,目前官方已经这样做了,但还不够好,首先 define_method 和你外面的 def 的语法就不一致,|*args|看起来也不够好,call 也有点多此一举,如果 ruby 能改成以下写法你看会不会更好呢?

    def self.log m
      def method *args
        p "输入是:#{args}"
        m(*args)
      end
      return method
    end
    
    log def foo x, y
      x + y
    end
    
    result = foo(2,3)
    puts result
    

    但是这是不可能的,看看就好

  • 你看用 ruby 写的话可能就需要|x|,define_method 这种东西了,我下面的 python 代码没有用到类,纯方法级别的装饰器

    #Aop-用于输出日志
    def log(fn):
        def method(*param):
            print("输入是:" + str(param))
            return fn(*param)
        return method
    
    @log
    def foo(x,y):
        return x + y
    
    result = foo(2,3)
    print(result)
    

    大家是和平讨论,你在这里贬低 JavaScript,Python 这些语言说是虾兵蟹将,这些语言难道就没有学习 smalltalk 语言吗,纯粹的面向对象是不存在的,因为任何一个通用语言都有例外的时候,除非你是 DSL。我说的一切不是来引战,我非常喜欢 ruby,写起来很优美,但有时又不够优美,这让人很纠结

  • 是的,你可以说所有的东西我都可以自己实现,从你开始自己写元编程实现装饰器的时候已经“不够简洁了”,但有总比没有好,“所以我说如果能加一个方法级别的装饰器语法糖之类的会更好”。

  • 不不不,你没理解我说的,你这叫语法的二义性,你如果明白我说的方法其实是一个变量就自然理解了(但问题是在 ruby 中 def 定义的方法不是一个变量),归根到底还是 def 定义的方法没有类型,而 proc,lambda 或者 method :xxxx 返回的是一个对象,这是设计上的问题,因为 ruby 语言历史悠久现在改已经不可能了,也就是 matz 说的 lisp-2 语义 如果大家都是方法那么调用格式应该统一,这样你说的所谓的多态其实只会增加复杂度,官方已经回复了,基本不可能改了。

  • sig 是由 sorbetrb 提供的一个元编程产物,但 python 的@是语言内置的,而且他们在行为上也有一些区别。

  • 你犯了一个最根本的原则性错误,那就是循环内使用 break 必须在当前作用域,如果你在方法内使用 break 属于语法错误。一般 python 和 javascript 都没有你这样的写法,一般也不会遇到这种需求

  • 对比一下 python 就好了,在 python 中装饰器有一个语法糖那就是@,在任意方法上面@xxxx就 OK 了还有比这更简洁的吗,当然我不是要拿其他语言来 ruby-china 这里引战,大家和平讨论,互相借鉴互相学习,谢谢

  • "那么我说的这个方法级别的装饰器需求可能会麻烦一点,但依然可以实现" 我没说不可以实现,麻烦看完再评论好吗,“所以我说如果能加一个方法级别的装饰器语法糖之类的会更好”,自己实现是可以,但不够简洁。

  • 你说的是以类为基础 prepend 之后在子类里 extend,这样确实可以做到装饰器,但我说的是类似 python 里面的方法级别的装饰器,但 ruby 是面向对象的,也就是说类是一等公民,那么我说的这个方法级别的装饰器需求可能会麻烦一点,但依然可以实现,所以我说如果能加一个方法级别的装饰器语法糖之类的会更好

  • 你说的没错,但我一开始也提到了统一函数或方法的调用格式,[] 这东西你可以理解为取数组元素,但在某些情况下又是调用方法 (或函数),这就是设计的不一致性,如果一个 def 方法通过 method1 = method :xxxxx 取引用后,其实它还是该方法本身,就不应该造成语义分歧,应该依然可以采取 method1 的方式调用方法,所以在这里 method1 其实就是一个变量,那么 def 定义的方法应该也是一个变量,但实际上不是。

  • 我觉得 |x| 这个东西看上去就不够优雅

  • 确实是你的原话,但我也没说一定要 ruby 引入纯函数式编程,是借鉴了函数式思想的允许副作用的函数式编程,官方的那个提案我看过了,取消的原因是官方认为似乎用到的地方很少,管道运算符其实反向的调用过程,把前面的函数或值的执行结果给后面的函数当作参数。

    #如果是这样的方法嵌套要写很多括号,很不方便,引入了管道运算符就可以简化
    method3(method2(method1(1)))
    #functional pipeline call
    1 |> method1 |> method2 |> method3
    

    看看官方以后怎么决定吧

  • 官方已经回复我了,大家可以继续讨论,原因就是历史原因,现在更改会导致不兼容以前的语法或语义,matz 不希望 ruby 跟 python2 -> python3 一样出现大版本更新不兼容以前版本的情况发生,现在只能希望官方能找到一个更好的办法来完善函数式编程了。谢谢大家

  • 不好意思,虽然我 ruby 学习时间不长,但不代表我不可以发表我的看法,如果你有什么建议可以提出来

  • 比如你说的 block 和 proc 其实“我认为”都是可以写成 def 定义的方法 proc 返回的是一个对象,lambda 也返回的是一个对象,他们可以被一个变量接受,那么 def 定义的方法为什么不能被一个变量接受呢,导致 def 定义的方法要用方法名调用,而 proc 或者 lambda 被变量接受后,甚至一个 def 方法用 method :symbol 返回后要用 call 或者.(xxx) 或者 [xxx] 来调用,其实他们都是方法不是吗?那么设计可以简化一下,简化之后其实就是函数式编程了,传递方法,闭包,甚至回调函数

  • 装饰器可以对原方法进行修饰,返回一个修改之后的方法,在打印日志,切面编程中运用广泛,你说 ruby 开放那你可以试一下在不改变函数名的情况下对原函数进行修改,第二 javascript 只是我用来举例,可能你没懂我在说什么,第三纯函数式语言是写不出复杂的系统的,或者说是不容易写出复杂的系统,所以这里的函数式编程就是一个概念,允许方法有副作用,第四这不是装不装的问题,而是真的很用心在和大家讨论,第五你可能说我学习 ruby 没多少时间,但是 ruby 的所谓的 proc 和 lambda 和 def 方法也就是 method 和 function 其实本质上就是一种东西,那么为什么不能简化一下呢。可能我说的还是有点笼统,希望能理解

  • 在方法中定义方法是编程语言的一个进步,更加灵活,闭包也更加方便,而且“要不然我新建一个函数还得检查一下之前做过什么……” ,其实并不需要,你既然要新建一个函数那么就只用你用到的部分就好,其他的不用管,再来说一下你最后那一段代码,JavaScript就可以轻松做到,其他的语言java,C#都可以,python自己写一个类也是可以做到的,当然还有很多我就不一一列举了,问题是我们似乎在讨论的不是同一个东西,我想说的是保持方法定义以及调用的一致性是很重要的。最后附上JavaScript版的同样功能的代码

    [1,2,3].map(x => x % 2 == 0).filter(x => x).length
    

    同理 python 支持传递函数,函数是一个变量名,在函数式编程中,或者说是高阶方法就很简单,你完全可以自己写一个链式调用的函数式方法,其实 ruby block 本质上也是一个方法,但是当时不知道为什么跟 def 定义的方法做了区分,在性能上又不讨好,在语法上又很奇怪。下面是 python 元编程版的实现。

    class Demo:
    
        array = None
    
        def __init__(self,tempArr):
            self.array = tempArr
    
        def map(self,fn):
            self.array = list(map(fn,self.array))
            return self
    
        def select(self,fn):
            self.array = list(filter(fn,self.array))
            return self
    
        def count(self):
            return len(self.array)
    
    #这里仿了Ruby的函数名方便你的理解
    result = Demo([1,2,3]).map(lambda x:x % 2 == 0).select(lambda x:x).count()
    print(result)
    

    我认为 ruby block 的 |x| 语法声明参数不是一个好主意,相比于JavaScript,C#的x => block,python 的 lambda x: block,该 | 字符不仅输入不方便而且过于丑陋,我在我的提案里提到了修改 block,lambda 的语法

    [1,2,3].map(x -> x.even?).select(x -> x).count
    

    这样是不是更好一点呢? 至于 Perl 这个语言连函数的参数都没有,居然用@_代替,我就不管他了,我只是希望 ruby 能更加好,我很喜欢 ruby,Do you understand?

  • def 定义的方法作用域与 proc,lambda,define_method 不同,这个其实只需要扩展 def 的作用域就可以完美解决,而 ruby 是把简单的问题弄的复杂了,最后一点是 你既然用了动态语言就别想隐藏变量,静态的 java 都甚至都可以通过反射强行拿出隐藏的变量,所以你这个问题严格来说不是问题

  • 谢谢你的回复,同时该提案确实是我发起的,我想说的是如果方法也是一个变量的话,而她的类型是 Method,那么不会出现你所说的重复定义的问题,当方法和变量可以同名才是最大的隐患,任意时刻应该只能有一个唯一的标识符,而不是 f 是一个变量而 f[3] 是一个函数调用,同时编译器在判断你这是变量还是方法的时候效率不高,也就是你所说的性能问题,我们真的需要一个方法名和一个变量名同名的情况存在吗?答案是否定的,没有人会这样做。

    def method1(x)
        puts "method1"
        puts x
    end
    #method1 的类型是Method 而且她是一个变量(我假设的)
    #调用method1
    method1 10  #或method(10)
    #重复定义可被覆盖(我假设的)
    method1 = []
    #此时method1是一个数组,原来的method1被覆盖了,这时调用method1
    method1 10 #报错,method1不是一个方法
    

    那再来看看通过 define_method 定义的方法,我们真的需要 define_method 这种定义方法的方式吗,你说是为了元编程,我同意,但 define_method 真正的目的是为了扁平化作用域,让这个特殊的方法可以访问到父方法的局部变量,这在很多时候其实就是一个闭包,但这种实现方式过于丑陋,|x|这种方式定义参数不如 def method1(x) 好看,也导致了方法定义的不一致性。

    define_method :method1 do |x|
        puts "method1"
        puts x
    end
    #目前调用method1
    (method :method1).call 10  #或(method :method1)[10]
    #如果method1 的类型是Method 而且她是一个变量,跟调用def定义的方法没有任何区别
    method1 10  #或method(10)
    

    消除歧义/保持语法设计统一是很重要的,既然大家都是方法,就应该遵循一个调用规则,而不是什么 call 或 [] 这种奇怪的东西,为什么 javascript 或者 python 能够流行,因为他们在设计上来说是高度一致的,而 ruby 更像是一个有很多花式语法糖来遮盖丑陋的设计 (这都是恨铁不成钢没有任何其他意思),我认为 ruby 还有很长的路要走

  • 首先谢谢你的回复,但有一点我想要说明,ruby 很多设计我认为是过度设计,如果能修改掉,就能让这个语言更加好,比如你说的 block 和 proc 其实都是可以写成 def 定义的方法,而现在 def 的方法,define_method 出来的方法,proc 和 lambda 调用形式也不统一,说白了就是 def xxx 的方法可以 xxx() 调用,而 lambda 或 define_method 需要用 call 或者 [] 调用,其实他们都是方法不是吗?这就是设计上的问题了,而 proc 不支持返回值,lambda 是一个特殊的 proc,我是不是也可以理解为,lambda 是一个方法,而 proc 只是一个没有返回值的方法,def 定义的也是一个方法,那都是方法为什么要有区别呢?看看 JavaScript 的高阶函数就知道多好用了,而在 ruby 中很变扭的传递方法要传递一个 symbol 或者 method (:symbol),虽然可能大家用 block 习惯了,但更加灵活的传递任意 def 定义的方法返回方法这种高阶函数,面向对象的语言以后的发展方向肯定是融入函数式编程思想,所以为了以后 ruby 的更好发展,我认为有必要统一设计,虽然可能不会被官方支持或者 ruby china 的朋友们支持,但是我是真的很喜欢 ruby 语言,希望她能够更好

  • 好的,谢谢

  • 谢谢,学习了,xxx.call(10) 可以写成 xxx.(10) 这是什么语法

  • 好的,谢谢,似乎 ruby 中 def 定义的方法不能直接访问其他作用域中的局部变量