Ruby로 JavaScript의 Template literals 따라하기

15334 단어 Ruby
이 글은 Okinawa.rb Advent Calendar 2018 13일째 되는 글이다.
어제@hanachin_선생님경로에 따라Turnip에 쓰인feature에 다른 유형을 추가하는 방법입니다.
내일은 @hanachin_씨의 줄을 설 시간이 필요 없다for입니다.

javascript_template_literals gem


Ruby의 `동작을 변경하는 자바스크립트의 Template literals를 모방한gem입니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
소스 코드.
https://github.com/hanachin/javascript_template_literals

사용법


설치 방법
% gem i javascript_template_literals
리퀘스트 후 using으로 사용할 수 있습니다.편하네.
require "javascript_template_literals"

using JavaScriptTemplateLiterals

a = 5
b = 10
puts `Fifteen is ${a + b} and
not ${2 * a + b}.`
# Fifteen is 15 and
# not 20.

def my_tag((strings, person_exp, age_exp))
  str0 = strings[0]
  str1 = strings[1]

  if age_exp > 99
    age_str = "centenarian"
  else
    age_str = "youngster"
  end

  `${str0}${person_exp}${str1}${age_str}`
end

person = "Mike"
age = 28
puts my_tag`That ${ person } is a ${ age }`
# That Mike is a youngster

설치 방법


루비의 방법.


루비에서 `는 단지 하나의 방법일 뿐이다.Kernel에 자라고 있어요.
https://docs.ruby-lang.org/ja/latest/class/Kernel.html#M_--60
일반적으로 외부 명령을 실행합니다.
Refinements로 덮어쓰면 마음대로 움직일 수 있기 때문에 여기에 실복을 적으세요.
module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      # ここでJavaScriptのTemplate literals風の動作をさせる
      "bar"
    end
  end
end

using JavaScriptTemplateLiterals

puts `foo`
# bar

호출 변수 보기


JavaScript의 Template literals에서는 변수${}를 참조할 수 있습니다.
Rubby에서 호출된 소스의 변수binding_of_caller를 참조하고 호출된 소스의 Binding에서 eval 변수를 참조합니다.
require "binding_of_caller"

module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      binding.of_caller(1).eval('x')
    end
  end
end

using JavaScriptTemplateLiterals

x = "foo"
puts `bar`
# foo

방정식 확장 시 호출 소스 변수 참조


정규 표현식에서 좋은 공식을 선택하고 gsub로 바꿀 때 bindingof_콜러를 사용하여 원본 Binding eval을 호출합니다.
require "binding_of_caller"

module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      b = binding.of_caller(1)
      str.gsub(/\$\{([^\}]*)\}/) { b.eval($1) }
    end
  end
end

using JavaScriptTemplateLiterals

foo = "bar"
puts `${foo}`
# bar

Tagged templates와 같은 행동거지의 설치 방법


처음에 방법이 tag에 전달된다면 배열을 되돌려 tag 방법에 전달하기 전에 전개해야 한다.
module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      # もしここで返した値がtagっぽいメソッドに渡るなら配列を返す
      [["foo"], 1, 2]
    end
  end
end

using JavaScriptTemplateLiterals

def bar(strings, exp1, exp2)
  "bar"
end

puts bar(*`${foo}`)
# bar
하지만 태그 방법で返した文字列が渡るのか渡らないのか에서는 방법에서 판단할 수 없습니다(좋은 방법을 아는 사람이 있으면 알려주세요).
그리고 * 필요한 건 자바스크립트가 아니에요, 보기 싫어요.
module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      # ここで返した値がtagっぽいメソッドに渡るかどうか、判断がつかない...
      [["foo"], 1, 2]
    end
  end
end

using JavaScriptTemplateLiterals

def bar(strings, exp1, exp2)
  "bar"
end

#    これ↓がいけてない
puts bar(*`${foo}`)
# bar
참고로 Rubby의 매개 변수()는 그룹을 분리할 수 있다.
def foo((a, b, c))
  a + b + c
end

puts foo([1, 2, 3])
# 6
'배열'이라고 쓰여 있지만 배열로 변환할 수 있다면 분해할 수 있다.
수조로 변환할 때 to_ary 방법이라고 한다.to_ary로 배열로 바꿀 수 있다면 배열이 아니어도 전달할 수 있다.
def foo((a, b, c))
  a + b + c
end

obj = Object.new

def obj.to_ary
  [1, 2, 3]
end

puts foo(obj)
# 6
이 방법을 이용하여tag방법의 매개 변수는 ()로 수신합니다...!
def my_tag((strings), exp1, exp2)
  # ...
end

a = 44
b = 23
my_tag`a + b = ${a + b}, a * b = ${a * b}`
방법은 드파인.singleton_method를 사용한 문자열을 되돌려줍니다ary 방법을 정의합니다.
이렇게 하면 일반적인 문자열로 사용할 때 일반적인 문자열로 사용할 수 있고 tag 방법으로 전달된 후에 tag 방법의 매개 변수에 좋은 전개값을 되돌릴 수 있습니다!이예리!
module JavaScriptTemplateLiterals
  refine(Object) do
    def `(str)
      # 普通は文字列として振る舞う
      ret = "foo2000bar"
      # to_aryメソッドがあるため
      # tagメソッドに渡されたときはタグっぽく振る舞う
      ret.define_singleton_method(:to_ary) do
        [["foo", "bar"], 2000]
      end
      ret
    end
  end
end

using JavaScriptTemplateLiterals

def my_tag((strings, exp))
  "#{strings.join}#{exp}"
end

puts `foo${1000 * 2}`
# foo2000bar

puts my_tag `foo${1000 * 2}`
# foobar2000

총결산

  • 루비의 ` 단지 방법일 뿐 Refinements로 덮어쓸 수 있다
  • 방법의 매개 변수는 ()로 묶으면 분해된다
  • 방법의 매개 변수가 ()에 둘러싸일 때 우리의 매개 변수to_ary 방법은 호출되어 진열로 변환되고 분해된다
  • 루비라면 뭐든 방법이니까 레파인먼트에 아무거나 쓰면 돼

    좋은 웹페이지 즐겨찾기