/ / Wyłączanie shuffle i sample w klasie Array - ruby

Wyłączanie trybu losowego i próbki w klasie Array - ruby

Załóżmy, że chcemy, aby ktoś napisał własną metodę pseudolosową. Jako ćwiczenie programowania. I chcemy zgłaszać błąd za każdym razem, gdy próbują rozwiązać funkcje wbudowane jako skrót

Do tej pory zrobiłem to:

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed"

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand",
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand",
"Array::shuffle", "Array::shuffle!", "Array::sample"]

methods_to_block.each do |method|
eval
"""
def #{method}
raise ERROR_STRING_FOR_RANDOM
end
"""
end

Blokuje więc Losowo, a to powoduje błąd:

rand
srand
Random.new.rand(18)

ale nie działa z pseudolosowymi metodami tablicowymi. Na przykład

[1,2,3].shuffle!

Nadal działa. Dlaczego tak się dzieje i jak temu zapobiec?

Odpowiedzi:

2 dla odpowiedzi № 1

Możesz otworzyć klasę i zastąpić metody, które chcesz wyłączyć ...

class Array
ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed"
RANDOM_METHODS = [:shuffle, :shuffle!, :select]
def rajarshi_random_error
raise ERROR_STRING_FOR_RANDOM
end
RANDOM_METHODS.each do |m|
define_method(m) {|*args| rajarshi_random_error }
end
end

2 dla odpowiedzi nr 2

Twój kod zawierał błąd

ArgumentError: wrong number of arguments (0 for 1..4)

ale dla innych podobnych funkcji modułu możesz po prostu zdefiniować takie metody

methods_to_block = ["rand", "srand","seed", "sample", "shuffle!", "shuffle!"]

tak powinno wyglądać

 methods_to_block.each do |method|
define_method "#{method}" do
raise ERROR_STRING_FOR_RANDOM
end
end
#=> ["rand", "srand", "Random::rand", "Random::srand", "Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", "Array::shuffle", "Array::shuffle!", "Array::sample"]

Teraz jeśli zadzwonisz

> srand
RuntimeError: Usage of built-in random generators is not allowed

> rand
RuntimeError: Usage of built-in random generators is not allowed

mam nadzieję, że ci to pomoże

Jeśli chcesz się trzymać, pozostań po swojemu

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed"

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand",
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand",
"Array::shuffle", "Array::shuffle!", "Array::sample"]


methods_to_block.each do |method|
if method.split("::").size > 1 && method.split("::").first != "Kernel"
class_name = method.split("::").first
method_name = method.split("::").last
er = <<ER
class #{class_name}
def #{method_name}
raise ERROR_STRING_FOR_RANDOM
end
end
ER
eval(er)
else
define_method "#{method}" do
raise ERROR_STRING_FOR_RANDOM
end
end
end

Teraz możesz dostać wszystko

> srand
RuntimeError: Usage of built-in random generators is not allowed

> rand
RuntimeError: Usage of built-in random generators is not allowed

> [2,3,4,5].shuffle
RuntimeError: Usage of built-in random generators is not allowed

0 dla odpowiedzi № 3

Dobrze. To działa:

class Array
undef_method :sample, :shuffle, :shuffle!
end

Używanie operatorów rozdzielczości zakresu na początku było złym pomysłem. Po prostu tworzą stałe wewnątrz klas zamiast redefiniować metody

Podobnie właściwy sposób wyłączenia rand i srand wygląda następująco:

module Kernel
undef_method :rand, :srand
class << self
undef_method :rand, :srand
end
end

class Random
undef_method :rand, :srand, :seed
class << self
undef_method :rand, :srand, :new
end
end