Секция за въпроси относно Ruby, които не сме се сетили да зададем на лекции или не е стигнало времето.
Ruby Q/A
Искам да знам дали има reverse arr.each , тоест да итерирам от зад напред с each ?
Намерих го първо си обръщаме масива array.reverse.each
Отваряме документацията на
Array
, търсим reverse и намираме три неща.Четейки какво пише разбираме, че
Array#reverse
ни дава обърнато копие на оригиналия масив,Array#reverse!
го обръща на място,Array#reverse_each
итерира в обратен ред.Имам въпрос, реших че искам да знам в кой клас се намирам и с тази цел докато тествах реших да принтирам класа тоест
puts self което съответно доведе до грешка
в последствие установих че
p self обаче работи
Въпроса ми е защо?
Друг въпрос който имам е как точно работи array.sort това което разбрах е че използва оператора <=> за сравнение, следователно предполагам че ако си предефинирам този оператор в конкретния за мен клас би трябвало да да мога да направя нещо от сорта на arr.sort!{|x, y| x <=> y}
направих си тест който обаче хвърля грешка
class Test def initialize(x) @x = x end def x x end def <=>(other) if @x > other.x then return 1 end if @x < other.x then return -1 end if @x == other.x then return 0 end end end t1 = Test.new(5) t2 = Test.new(6) arr = [Test.new(9) , Test.new(45), Test.new(5), Test.new(8)] arr.sort!{|x, y| x <=> y}
@Николай, каква грешка ти даде това със селф?
[11] pry(main)> p self main => main [12] pry(main)> puts self main => nil [13] pry(main)> class Slon [13] pry(main)* p self [13] pry(main)* puts self [13] pry(main)* end Slon Slon => nil [14] pry(main)> class Slon [14] pry(main)* def initialize [14] pry(main)* p self [14] pry(main)* puts self [14] pry(main)* end [14] pry(main)* end => nil [15] pry(main)> Slon.new #<Slon:0x007fefb3a9cef0> #<Slon:0x007fefb3a9cef0> => #<Slon:0x007fefb3a9cef0>
Форматирай кода на другото - не може да се прочете така. Използвай 3 пъти ` този символ, с нови редове над него.
Работещ пример за Test класа:
[18] pry(main)> class Test [18] pry(main)* attr_accessor :x [18] pry(main)* def initialize(x) [18] pry(main)* @x = x [18] pry(main)* end [18] pry(main)* [18] pry(main)* def <=>(other) [18] pry(main)* @x <=> other.x # numbers already have <=> - just use it [18] pry(main)* end [18] pry(main)* end => nil [19] pry(main)> tests = (1..10).map { |x| Test.new(x) }.shuffle => [#<Test:0x007fefb1e2cef0 @x=8>, #<Test:0x007fefb1e2cea0 @x=9>, #<Test:0x007fefb1e2cf90 @x=4>, #<Test:0x007fefb1e2ce78 @x=10>, #<Test:0x007fefb1e2cf40 @x=6>, #<Test:0x007fefb1e2cf18 @x=7>, #<Test:0x007fefb1e2cf68 @x=5>, #<Test:0x007fefb1e2cfe0 @x=3>, #<Test:0x007fefb1e2d030 @x=2>, #<Test:0x007fefb1e2d058 @x=1>] [20] pry(main)> tests.sort => [#<Test:0x007fefb1e2d058 @x=1>, #<Test:0x007fefb1e2d030 @x=2>, #<Test:0x007fefb1e2cfe0 @x=3>, #<Test:0x007fefb1e2cf90 @x=4>, #<Test:0x007fefb1e2cf68 @x=5>, #<Test:0x007fefb1e2cf40 @x=6>, #<Test:0x007fefb1e2cf18 @x=7>, #<Test:0x007fefb1e2cef0 @x=8>, #<Test:0x007fefb1e2cea0 @x=9>, #<Test:0x007fefb1e2ce78 @x=10>]
Идеята да предефинираш <=> метода е да избегнеш подаването на блок при сортиране на масив от
Test
инстанции. Без дефиниран<=>
метод заTest
класа примера би изглеждал така:[24] pry(main)> class Test [24] pry(main)* attr_accessor :x [24] pry(main)* def initialize(x) [24] pry(main)* @x = x [24] pry(main)* end [24] pry(main)* end => nil [25] pry(main)> tests = (1..10).map { |x| Test.new(x) }.shuffle => [#<Test:0x007fefb3b54910 @x=9>, #<Test:0x007fefb3b54870 @x=5>, #<Test:0x007fefb3b54848 @x=4>, #<Test:0x007fefb3b548c0 @x=7>, #<Test:0x007fefb3b547d0 @x=1>, #<Test:0x007fefb3b547f8 @x=2>, #<Test:0x007fefb3b54938 @x=10>, #<Test:0x007fefb3b54898 @x=6>, #<Test:0x007fefb3b54820 @x=3>, #<Test:0x007fefb3b548e8 @x=8>] [26] pry(main)> tests.sort { |first, second| first.x <=> second.x } => [#<Test:0x007fefb3b547d0 @x=1>, #<Test:0x007fefb3b547f8 @x=2>, #<Test:0x007fefb3b54820 @x=3>, #<Test:0x007fefb3b54848 @x=4>, #<Test:0x007fefb3b54870 @x=5>, #<Test:0x007fefb3b54898 @x=6>, #<Test:0x007fefb3b548c0 @x=7>, #<Test:0x007fefb3b548e8 @x=8>, #<Test:0x007fefb3b54910 @x=9>, #<Test:0x007fefb3b54938 @x=10>]
Идеята е да енкапсулираш логиката за сравняване на сложни класове вътре в самите класове. Не е нужно тези, които ги иползват да знаят по какъв начин се сравняват. А и ако решиш
Test
обектите да ги сортираш по друго трябва да го промениш на 1 място, а не на всички, на които ги сортираш. Освен това, винаги можеш да използвашsort
с блок и да направиш къстъм сортиране ако ти трябва.@Николай, дай "Редактирай" на поста си и виж как съм ти го форматирал. Без това форматиране, някои специални символи не се показват в поста ти и това пречи на другите да разберат какво питаш.
Конкретно за примера ти, той дава следната грешка:
SystemStackError: stack level too deep
И причината за нея е дефиницията ти на метода
Test#x
:def x x end
В нея ти реално правиш рекурсия, като
x
викаx
и така безкрай. Вероятно си искал да напишеш това:def x @x end
Освен тази грешка, няма други. Примерът ти работи.
Когато пускам тестовете те файлват което се очаква, но после забелязах че се тества дали Card.new(10, :spades).to_s дава 10 of Spades което като го проверих при мен е така , но rspec връща че теста е файлнал с грешка :
Failures: 1) Card can be converted to a string Failure/Error: expect(Card.new(10, :spades).to_s).to eq '10 of Spades' NoMethodError: undefined method `expect' for #<RSpec::ExampleGroups::Card:0x268a088> # ./test_cards.rb:3:in `block (2 levels) in <top (required)>'
Въпроса ми е дали проблема е в rspec, защото този проблем NoMetgodError ми го връща на всички тестове
П.С. пробвах ръчно още няколко теста, отново дава че са файлнали докато като ги тествам ръчно връща това което се очаква.
С коя версия на
rspec
си? Може да провериш с тази команда:rspec --version
Трябва ти 3+.
3.3.2
Имам интересн въпрос, така имам клас
class Child < Parent attr_accessor :field end
Child наследява някакви работи и се случва следното ако не съм инициализирал :field обекта от този тип си е Child със всичките му методи и т.н. обаче ако сетна :field на нещо целия обект става от тип символ, защо ?
Как го сетваш? Липсва достатъчно код за да се отговори. : /
@Ники, няколко неща:
- Дай редакция на поста си и виж как съм ти форматирал кода, за да се чете. Спри да ползваш
<code>
тагове, не се ползват за форматиране на Markdown. Погледни тук за повече информация. - Направих примера ти по-общ, за да не споделяш код от задачата. Прави така занапред.
- И аз, както и Влад, не разбирам обяснението, което даваш. Трябва цялостен пример (но "анонимизиран", без неща от задачата). Или ни изпрати на имейла на курса кода от задачата, с въпрос.
- Дай редакция на поста си и виж как съм ти форматирал кода, за да се чете. Спри да ползваш
Трябва да сте влезли в системата, за да може да отговаряте на теми.