Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dropping Down To The Metal™ (2018)

Godfrey Chan
October 06, 2018
80

Dropping Down To The Metal™ (2018)

As much as we love Ruby, when you need to be really close to the metal, you have no choice but to use JavaScript. This is why I developed the javascript gem to help you harness the raw power of your machines. (https://github.com/chancancode/javascript)

In this talk, we will examine the Ruby tricks and black magic hidden behind this ludicrous invention. Along the way, we will learn about how Ruby internally deal with variable lookups, method calls, scoping and bindings. Together, we will push the limits of the Ruby language, taking it to places Matz never ever envisioned!

Godfrey Chan

October 06, 2018
Tweet

Transcript

  1. Dropping
    Down To
    The Metal™

    View Slide

  2. View Slide

  3. Java ☕

    View Slide

  4. Java ☕
    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello world!");
    }
    }
    HelloWorld.java Terminal
    % javac HelloWorld.java
    % java HelloWorld
    Hello world!
    %
    %
    %

    View Slide

  5. Java ☕
    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello world!");
    }
    }
    HelloWorld.java Terminal
    % mv HelloWorld.java hello.rb
    % ruby hello.rb
    ???
    %
    %
    %
    hello.rb
    $ It works™
    ) Syntax Error
    - Runtime Error

    View Slide

  6. Java ☕
    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello world!”);
    }
    }
    HelloWorld.java
    Terminal
    hello.rb
    $ It works™
    ) Syntax Error
    - Runtime Error
    % ruby hello.rb
    hello.rb:2: syntax error, unexpected tIDENTIFIER, expecting ')'
    %
    %

    View Slide

  7. How Ruby Works J
    ???
    hello.rb Output
    Ruby Interpreter
    Compile Evaluate
    ???

    View Slide

  8. How Ruby Works J
    hello.rb Output
    Ruby Interpreter
    Compile Execute
    Syntax Error Runtime Error
    Parse

    View Slide

  9. How Ruby Works J
    I don’t speak Russian.
    NP
    N
    VP
    VP
    V N
    V
    I don’t speak Russian
    S
    $ All Good

    View Slide

  10. How Ruby Works J
    Don’t Russian I speak.
    V N V
    N
    I
    Don’t speak
    Russian
    K Syntax Error
    ???

    View Slide

  11. How Ruby Works J
    Russian doesn’t speak me.
    NP
    N
    VP
    VP
    V N
    V
    me
    doesn’t speak
    Russian
    S
    7 Semantic Error

    View Slide

  12. How Ruby Works J
    hello.rb Output
    Ruby Interpreter
    Compile Execute
    Syntax Error Runtime Error
    Parse

    View Slide

  13. How Ruby Works J
    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello world!”);
    }
    }
    HelloWorld.java
    Terminal
    hello.rb
    $ It works™
    ) Syntax Error
    - Runtime Error
    % ruby hello.rb
    hello.rb:2: syntax error, unexpected tIDENTIFIER, expecting ')'
    %
    %

    View Slide

  14. JavaScript

    View Slide

  15. JavaScript ☕
    console.log("Hello world!");
    hello.js Terminal
    % node hello.js
    Hello world!
    %
    %

    View Slide

  16. console.log("Hello world!");
    hello.js Terminal
    % mv hello.js hello.rb
    % ruby hello.rb
    ???
    %
    %
    %
    $ It works™
    ) Syntax Error
    - Runtime Error
    hello.rb
    JavaScript ☕

    View Slide

  17. console.log("Hello world!");
    HelloWorld.java
    Terminal
    hello.rb
    $ It works™
    ) Syntax Error
    - Runtime Error
    JavaScript ☕
    % ruby hello.rb
    hello.js:1:in `': undefined local variable or method `console’ for main:Object (NameError)
    %
    %

    View Slide

  18. console.log("Hello world!");
    JavaScript ☕

    View Slide

  19. console.log("Hello world!");
    Local variable or method named “console”
    JavaScript ☕

    View Slide

  20. console.log("Hello world!");
    JavaScript ☕
    Call the instance method “log” on “console”

    View Slide

  21. console.log("Hello world!");
    JavaScript ☕
    Optional parenthesis

    View Slide

  22. console.log("Hello world!");
    JavaScript ☕
    Method argument (string literal “Hello world!”)

    View Slide

  23. console.log("Hello world!");
    JavaScript ☕
    Optional semicolon

    View Slide

  24. console.log("Hello world!");
    JavaScript ☕

    View Slide

  25. console.log("Hello world!");
    HelloWorld.java
    Terminal
    % ruby hello.rb
    hello.js:1:in `': undefined local variable or method `console’ for main:Object (NameError)
    %
    %
    hello.rb
    JavaScript ☕

    View Slide

  26. class Console
    def log(*args)
    puts(*args)
    end
    end
    console = Console.new
    # Begin "JavaScript"
    console.log("Hello world!");
    HelloWorld.java
    hello.rb
    JavaScript ☕
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %

    View Slide

  27. View Slide

  28. class Console
    def log(*args)
    puts(*args)
    end
    end
    console = Console.new
    # Begin "JavaScript"
    console.log("Hello world!");
    HelloWorld.java
    hello.rb
    JavaScript ☕
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %
    class Console
    def log(*args)
    puts(*args)
    end
    end
    console = Console.new
    L

    View Slide

  29. require "javascript"
    javascript do
    console.log("Hello world!");
    end
    HelloWorld.java
    hello.rb
    JavaScript ☕
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %

    View Slide

  30. DSL
    Domain-specific Language
    M

    View Slide

  31. def javascript
    yield
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    console.log("Hello world!");
    end
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    hello.rb:4:in `block in ': undefined local variable or method `console' for main:Object (NameError)
    %
    %

    View Slide

  32. class Console
    def log(*args)
    puts(*args)
    end
    end
    def console
    Console.new
    end
    def javascript
    yield
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    console.log("Hello world!");
    end
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %

    View Slide

  33. class Console
    def log(*args)
    puts(*args)
    end
    end
    def console
    Console.new
    end
    def javascript
    yield
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    console.log("Hello world!");
    end
    console.log("Hello world!");
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    Hello world!
    Hello world!
    %
    %
    L

    View Slide

  34. def javascript
    yield
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    self.console.log("Hello world");
    end
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    hello.rb:4:in `block in ': undefined local variable or method `console' for main:Object (NameError)
    %
    %
    Instance of Object

    View Slide

  35. class Console ... end
    class JavaScript
    def console
    Console.new
    end
    end
    def javascript(&block)
    JavaScript.new.instance_exec(&block)
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    console.log("Hello world!");
    end
    console.log("Hello world!");
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    Hello world!
    hello.rb:4:in `block in ': undefined local variable or method `console' for main:Object (NameError)
    %
    %
    N
    self is instance of JavaScript
    O
    self is instance of Object

    View Slide

  36. class Console ... end
    class JavaScript
    def console
    Console.new
    end
    end
    def javascript(&block)
    JavaScript.new.instance_exec(&block)
    end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    console.log("Hello world!");
    end
    hello.rb
    DSL M
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %

    View Slide

  37. View Slide

  38. Variables ℹ

    View Slide

  39. require "javascript"
    javascript do
    let message = "Hello world!";
    console.log(message);
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Variables ℹ

    View Slide

  40. $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    console.log("Hello world!");
    hello.rb
    Terminal
    Variables ℹ
    % ruby hello.rb
    hello.rb:4:in `block in ': undefined method `let' for # (NoMethodError)
    %
    %

    View Slide

  41. let message = "Hello world!";
    Variables ℹ

    View Slide

  42. let(message = "Hello world!");
    Variables ℹ

    View Slide

  43. let(message = "Hello world!");
    Variables ℹ
    Call the method named “let”…

    View Slide

  44. let(message = "Hello world!");
    Variables ℹ
    …with this argument.

    View Slide

  45. let(message = "Hello world!");
    Variables ℹ
    What is it?

    View Slide

  46. let(message = "Hello world!");
    Variables ℹ
    Assignment Expression

    View Slide

  47. let(message = "Hello world!");
    Variables ℹ

    View Slide

  48. let(message = "Hello world!");
    Variables ℹ

    View Slide

  49. message = "Hello world!";
    let(message);
    Variables ℹ

    View Slide

  50. message = "Hello world!";
    let("Hello world!");
    Variables ℹ

    View Slide

  51. class Console ... end
    class JavaScript
    def console ... end
    def let(???)
    ???
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    let message = "Hello world!";
    console.log(message);
    end
    hello.rb
    Terminal
    %
    Variables ℹ

    View Slide

  52. message = "Hello world!";
    let("Hello world!");
    Variables ℹ
    $
    Q

    View Slide

  53. class Console ... end
    class JavaScript
    def console ... end
    def let(*)
    # ¯\_(ϑ)_/¯
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    let message = "Hello world!";
    console.log(message);
    end
    hello.rb
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %
    Variables ℹ

    View Slide

  54. View Slide

  55. wait a second… J

    View Slide

  56. require "javascript"
    javascript do
    let message;
    message = "Hello world!";
    console.log(message);
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Variables ℹ

    View Slide

  57. $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    console.log("Hello world!");
    hello.rb
    Terminal
    Variables ℹ
    % ruby hello.rb
    hello.rb:4:in `block in ': undefined method `message’ for # (NoMethodError)
    %
    %

    View Slide

  58. let message;
    message = "Hello world!";
    console.log(message);
    Variables ℹ

    View Slide

  59. let(message);
    message = "Hello world!";
    console.log(message);
    Variables ℹ

    View Slide

  60. let(message);
    message = "Hello world!";
    console.log(message);
    Variables ℹ
    defined here

    View Slide

  61. let(message);
    message = "Hello world!";
    console.log(message);
    Variables ℹ
    not local variable

    View Slide

  62. let(message);
    message = "Hello world!";
    console.log(message);
    Variables ℹ
    method?

    View Slide

  63. let(message());
    message = "Hello world!";
    console.log(message);
    Variables ℹ

    View Slide

  64. class Console ... end
    class JavaScript
    def console ... end
    def let ... end
    def message
    # ¯\_(ϑ)_/¯
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %
    Variables ℹ
    require "javascript"
    javascript do
    let message;
    message = "Hello world!";
    console.log(message);
    end
    hello.rb

    View Slide

  65. class Console ... end
    class JavaScript
    def console ... end
    def let ... end
    def message
    # ¯\_(ϑ)_/¯
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %
    Variables ℹ
    def message
    # ¯\_(ϑ)_/¯
    end
    L
    require "javascript"
    javascript do
    let message;
    message = "Hello world!";
    console.log(message);
    end
    hello.rb

    View Slide

  66. class Console ... end
    class JavaScript
    def console ... end
    def let ... end
    def method_missing(*)
    # ¯\_(ϑ)_/¯
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    let message;
    message = "Hello world!";
    console.log(message);
    end
    hello.rb
    Terminal
    % ruby hello.rb
    Hello world!
    %
    %
    Variables ℹ

    View Slide

  67. View Slide

  68. Functions ⤵

    View Slide

  69. require "javascript"
    javascript do
    function hello() {
    console.log("Hello world!");
    }
    hello();
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Functions ⤵

    View Slide

  70. require "javascript"
    javascript do
    function hello() {
    console.log("Hello world!");
    }
    hello();
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Functions ⤵

    View Slide

  71. $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    console.log("Hello world!");
    hello.rb
    Terminal
    % ruby hello.rb
    %
    %
    * None of the above
    Functions ⤵

    View Slide

  72. function hello() {
    console.log("Hello world!");
    }
    hello();
    Functions ⤵

    View Slide

  73. function(hello() {
    console.log("Hello world!");
    });
    hello();
    Functions ⤵

    View Slide

  74. function(hello() {
    console.log("Hello world!");
    });
    hello();
    Call the method named “function”…
    Functions ⤵

    View Slide

  75. function(hello() {
    console.log("Hello world!");
    });
    hello();
    …with this argument.
    Functions ⤵

    View Slide

  76. function(hello() {
    console.log("Hello world!");
    });
    hello();
    What is it?
    Functions ⤵

    View Slide

  77. function(hello() {
    console.log("Hello world!");
    });
    hello();
    Call the method named “hello”…
    Functions ⤵

    View Slide

  78. function(hello() {
    console.log("Hello world!");
    });
    hello();
    …but what is this?
    Functions ⤵

    View Slide

  79. function(hello() {
    console.log("Hello world!");
    });
    hello();
    A block argument to the “hello” method.
    Functions ⤵

    View Slide

  80. function(hello() {
    console.log("Hello world!");
    });
    hello();
    Call the method named “hello”.
    Functions ⤵

    View Slide

  81. function(hello() {
    console.log("Hello world!");
    });
    hello();
    Undefined methods!
    Functions ⤵

    View Slide

  82. class Console ... end
    class JavaScript
    def console ... end
    def let ... end
    def method_missing(*)
    # ¯\_(ϑ)_/¯
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    function hello() {
    console.log("Hello world!");
    }
    hello();
    end
    hello.rb
    Terminal
    %
    Functions ⤵

    View Slide

  83. class Console ... end
    class JavaScript
    def ... end
    def function(*); end
    def method_missing(name, *, &block)
    if block_given?
    define_singleton_method(name, block)
    end
    end
    end
    def javascript ... end
    HelloWorld.java
    javascript.rb
    require "javascript"
    javascript do
    function hello() {
    console.log("Hello world!");
    }
    hello();
    end
    hello.rb
    Terminal
    Functions ⤵
    % ruby hello.rb
    Hello world!
    %
    %

    View Slide

  84. View Slide

  85. Arguments S

    View Slide

  86. require "javascript"
    javascript do
    function hello(name) {
    console.log(`Hello ${name}!`);
    }
    hello("world");
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Arguments S
    Arguments

    View Slide

  87. require "javascript"
    javascript do
    function hello(name) {
    console.log(`Hello ${name}!`);
    }
    hello("world");
    end
    hello.rb Terminal
    $ It works™
    ) Syntax Error
    - No Method Error
    ( Name Error
    % ruby hello.rb
    ???
    %
    %
    Arguments S
    Arguments

    View Slide

  88. View Slide

  89. gem install javascript

    View Slide

  90. chancancode/javascript

    View Slide

  91. View Slide

  92. View Slide

  93. Why? T

    View Slide

  94. class Post < ActiveRecord::Base
    before_create &javascript {
    function(post) {
    console.log(`Created ${post.title}`);
    }
    }
    end
    app/models/post.rb
    Why? T

    View Slide

  95. Why not? U

    View Slide

  96. Godfrey Chan
    @chancancode

    View Slide