• midori 百日记 at 2016年12月17日

    #6 楼 @embbnux 对,对于单个请求的响应时间确实是有好处的

  • midori 百日记 at 2016年12月17日

    #4 楼 @embbnux 事实上,Promise.all 这样的特性在语言层面上是很高效的,但在运行上,特别是 Web 服务器上并没有想象中的优势。因为 Web 服务器主要都是碎片式的 CGI,这意味着,我 CPU 一旦有空闲的时间我只要去处理别的请求就行,而不必通过压榨一个请求内的时间。本质上说,如果我们能将一个线程的 Idle 率降到 0,那么无论我们采取何种策略,他们的整体效率应该都是接近的。

  • #2 楼 @Rei 哈哈哈哈哈哈哈,我也不相信裸写 Lisp,纯 Lisp 更像是在写语法树而不是在写程序。但是我相信基于 Lambda 演算模型做出更好的语法设计,从而又具备 Lisp 那样高度灵活性和高度抽象性的动态语言,但又能让编程有更好的可读性和工程性的东西。这两年 Lisp 社区其实发展得也很迷,不是很懂。

  • 任何 C 或 Fortran 程序复杂到一定程度之后,都会包含一个临时开发的、不合规范的、充满程序错误的、运行速度很慢的、只有一半功能的 Common Lisp 实现。—— 格林斯潘第十定律

    Paul Graham 后来给这个格言加了一个推论。

    包括 Common Lisp。

    包括 Erlang、Ruby、JavaScript 在内的高度灵活的动态语言,不免和 Lisp 的设计有很多相似之处。在这些语言的虚拟机上支持 Lisp 本身的语法其实相对来说并不麻烦。

  • 其实用特殊字符写代码有个比较常见的用途是在 Android 开发中使用一本非 ASCII 字符的字典,比如中文甚至 emoji 来做混淆。。。而反编译工具遇到这些字符变量名会触发异常导致无法反编译成功😆

  • 几个月前买了原版书还没怎么看。。。下了一单中文版。。。

  • 惊了,我才知道搭建 gem 原来也是有脚手架工具了,每次都是手动一个个文件建出来的 0.0

  • Crystal 随便玩玩 at 2016年11月10日

    感觉对显式定义 Type,然后对函数进行重载这种方法确实挺冗余的。虽然说静态类型是能提高代码分析质量的好方法,对提升性能能有很大的帮助。但在这上面还是很难和优雅之间找到一个平衡。比如

    class TestClass
      getter :value
    
      def initialize(str : String)
        initialize(str.to_i)
      end
    
      def initialize(@value : Int32)
      end
    
      def initialize(mixedA : Int32 | String, mixedB : Int32 | String)
        initialize(initialize(mixedA) + initialize(mixedB))
      end
    
    end
    

    用 Ruby 来实现的话可以写成

    class TestClass
      attr_reader :value
      def initialize(*args)
        @value = args.map { |v| v.to_i }.reduce(:+)
      end
    end
    

    更新: 我错了,没想到 Crystal 完全支持这种写法。。。

    class TestClass
      getter :value
      def initialize(*args)
        @value = args.map { |v| v.to_i }.reduce(:+)
      end
    end
    

    只是说性能没有完全定义全那么好。。。我觉得 Crystal 符合 matz 想在 Ruby 3 中实现的 Soft Type。也就是能类型推断的就推,不能推断的就不推。Crystal 里还是保留了 *args 这种写法的兼容,我要收回之前的批评。

  • #4 楼 @mizuhashi 其实还有些类似的框架,甚至有支持 SSR 啊什么的

  • #4 楼 @mizuhashi youchan/menilite

  • Opal 作者今年已经写了个类似 React 的东西了,今年 RubyKaigi 的 Keynote 之一。

  • #5 楼 @mizuhashi

    其实比如说

    class Demo
      def initialize(n)
        @secret = n
      end
      def get_binding
        binding
      end
    end
    
    k1 = Demo.new(99)
    b1 = k1.get_binding
    eval("@secret", b1) #=> 99
    

    可以写成

    class Demo
      def initialize(n)
        @secret = n
      end
    end
    
    k1 = Demo.new(99)
    k1.instance_variable_get('@secret') #=> 99
    

    还可以写成

    class Demo
      def initialize(n)
        @secret = n
      end
    end
    
    k1 = Demo.new(99)
    k1.instance_exec(&lambda { @secret })
    

    其实除了 eval 以外的所有的元编程方法,都可以被认为是对 eval 大杀器的约束,限制其的一些行为。

  • #3 楼 @glz1992 不是。"2+2 is #{2+2}" 只是模板字符串。能被一次性解析开来,而不会执行一次解析一次。

  • 因为 LeetCode 往你函数里输入的并不是 ['X..X','...X','...X'] 而是 [["X", ".", ".", "X"], [".", ".", ".", "X"], [".", ".", ".", "X"]]

    那个 Run Code Result 里会自动把 Input 的多维数组的第二维开始全部展开,非常迷。

    count_battleships(%w(X..X ...X ...X)) # => 2
    count_battleships([%w(X . . X), %w(. . . X), %w(. . . X)]) # => 4
    

    在一开始 LeetCode 打给你的样例函数里

    # @param {Character[][]} board
    # @return {Integer}
    def count_battleships(board)
    
    end
    

    就在注释里给你描述了参数是单字符组成的二维数组了。


    另外被题主高超的数组下标加减法能力给搞晕了,一开始还没看懂代码到底在干什么。。。其实只要把 s.to_s 改成 s.join 就行了。

    这个算法复杂度是 O(n) 的,理论上应该非常快,但是实测 109ms,比平均速度还要慢一些。因为为了能在一个字符串里操作,你把整个 board 重新生成了一遍。

    花了五分钟,写了个 O(n) 的 DFS 解决方案,好久不写算法了,跑出来 75ms, beats 100.00% of ruby submissions。

    # @param {Character[][]} board
    # @return {Integer}
    def count_battleships(board)
      @board = board # Make it class visible for dfs to modify
    
      @size_y = board.length
      return 0 if @size_y == 0
      @size_x = board[0].length
      return 0 if @size_x == 0
    
      count = 0
      @size_y.times do |y|
        @size_x.times do |x|
          if @board[y][x] == 'X'
            count += 1
            dfs(x, y)
          end
        end
      end
      count
    end
    
    # Depth-first Search
    def dfs(x, y)
      return unless @board[y][x] == 'X'
      @board[y][x] = '.' # Delete the pixel if searched
    
      # Corner detection
      dfs(x+1, y) unless x == @size_x - 1
      dfs(x, y+1) unless y == @size_y - 1
    end
    

    不过其实可以不 DFS,按楼主扫一遍的思路的话,不操作数组也可以写,代码如下,

    # @param {Character[][]} board
    # @return {Integer}
    def count_battleships(board)
      board = board
    
      size_y = board.length
      return 0 if size_y == 0
      size_x = board[0].length
      return 0 if size_x == 0
    
      count = 0
      size_y.times do |y|
        size_x.times do |x|
          count += 1 if board[y][x] == 'X' && board[y][x+1] != 'X' && (board[y+1].nil? || board[y+1][x] != 'X')
        end
      end
      count
    end
    

    跑出来也是 75ms, beats 100.00% of ruby submissions。复杂度一样的两个算法,DFS 那个会多写入和反复扫描几下,但会少判断几下,所以时间上总的来说是一样。

  • 早上装 JRuby 的时候报了一屏幕的证书错误,我还以为是临时性抽风。。。结果下午试了一下还是这样,暂时先改 http 用了。。。但翻了苹果的公告,只查到对 StartCom 的一个 Free SSL 失去信任的公告,StartCom Class 1 DV Server CA 应该是不受影响的,暂时没有搞懂原因。

  • 勾起来我对用过的一些日本企业的网站的回忆。。。这个前端的界面非常有。。。日本公司的感觉。

  • #22 楼 @huacnlee 说实话,我现在感到压力巨大,因为这项目的进度还不是很完善,就已经被那么多人盯着给我做 code review 了。这几天都没怎么好好睡好都。。。

  • #22 楼 @xiaoronglv 是啊,上海有一段时间没搞 Ruby Tuesday 了,正好看到杭州在搞,就坐火车过来了。

  • #19 楼 @gwotzehsing Sinatra 用 thin 的话就已经相当于包了一层异步了。sinatra-synchrony 又不维护了。。。其实裸跑 hello world EM 本身倒是有性能限制。。。不过加上一些别的东西就不算限制了。之后会把数据库驱动都做一遍。。。至少会把我平时用到的东西尽可能都搞一下。

  • 感谢诸位如此慷慨的 Star,人生第一次上 GitHub Trending 了。。。

    以及感谢各位的意见 Benchmark 跟踪和路由匹配的重构都将会尽快

    突然发现成为了过去 24 小时加 Star 最多的 Ruby 项目。。。受宠若惊。。。

  • #8 楼 @jasl 现在这东西还是有很多地方值得性能优化的。特别是路由匹配的部分,Ruby 的正则是一个 NFA 的实现,如果徒手写一个 DFA 的实现的话,足够完成现在的需求,但匹配的算法复杂度可以降到线性。但现在功能还不是很全,暂时还没有考虑这么多。

  • 👍

  • #2 楼 @steven_yue

    #\ -s puma
    

    必须要加在 config.ru 文件的第一行才有效,其目的是让 rackup 命令变成 rackup -s puma。。。加在第 15 行是没有用的。。。

  • #1 楼 @hlcfan 肯定不是杀进程的问题。。。我 lsof -i:9292 确认过的。。。log 的话。。。是哪一部分的 log?404 它并不像 500 服务器的错误,并不会把出错的栈打印下来啊。。。。

  • #44 楼 @derekyxie 一般用非线性视频剪辑工具分分钟想黑苹果。。。

  • @jasl http://rubyconfchina.org 因为备案问题被挂了。。。但 http://2016.rubyconfchina.org 还可以用。。。

  • 讲道理的话,Ruby 作为 Lisp 的方言,闭包是非常重要和基础的东西,否则就变成写了一手 Java 了。。。

  • #61 楼 @ericguo 我还打算先黑 Xamarin 的其实 (逃)

  • #58 楼 @danjiang 感觉我提交的话题能带到这个题目。。。虽然不知道能不能选上。。。