Задача 2: Въпроси

  1. Последно за Proxy-то, няма нужда да трием всички му вградени методи, понеже ми се вижда доста варварско :D ?

    Публикувано преди повече от 4 години
  2. аз пък да питам по 3-та задача (Object#&)

    в теста се проверява:
    assert_equal nil, list.&.reverse.&.i.&.tend.&.to.&.get.&.carried.&.away

    което разбира се не сработва защото i не е дефиниран метод за класа Array

    Ако правилно съм разбрала, в условието на задачата се иска метода & да работи по същия начин като && , т.е.
    list.&.reverse.&.i
    да върне същото като
    list && list.reverse && list.reverse.i

    и съответно:
    irb(main):055:0* list = [-1, -2, -3, nil, -4]
    => [-1, -2, -3, nil, -4]
    irb(main):056:0> list && list.reverse && list.reverse.i
    NoMethodError: undefined method `i’ for [-4, nil, -3, -2, -1]:Array
    from (irb):56
    from :0
    irb(main):057:0>

    .. аз ли не го разбирам както трябва или има грешка в теста ?

    Публикувано преди повече от 4 години
  3. “Мислете за foo.&.bar като “върни nil ако foo е nil или foo няма метод bar; иначе върни foo.bar””.gsub(“foo”, “list”).gsub(“bar”, “i”)
    По-ясно от условието едва ли може да се каже.

    Публикувано преди повече от 4 години
  4. За 5. Object#swap_methods: Трябва ли да работи ако някой метод, или и двата метода ги няма? Тоест
    str = “Stringophilia”
    str.swap_methods :upcase, :shazam
    puts str.shazam
    Извежда ли “STRINGOPHILIA” или хвърля NoMethodError?

    Редакция: И относно 10. Object#expose_all:
    Ако вече има дефиниран accessor, да се предефинира ли?

    Публикувано преди повече от 4 години
  5. @Матей:

    Триенето на всички методи без object_id, __id__ и __send__ е практиката за такива неща. Не е варварско, налага се, освен ако не ползваш и Ruby 1.9 и имаш BasicObject.

    @Евгения: Прочети коментара на Ясен.

    @Димитър:

    Направи Object#swap_methods да работи при дефинирани методи. В другите случаи не ни интересува как се държи. За expose_all не ни интересува също (аз бих го предефинирал).

    Публикувано преди повече от 4 години
  6. По хак 3:
    Не разбирам. Каквото и да напиша тук:

    class Object
    def &(*args)


    1. end
      end

    на питанката

    list = [1, 2, 3]
    list.&.reverse

    Ruby отговаря:

    ArgumentError: wrong number of arguments (0 for 1)

    Мисля, че това е защото в класа Array операторът & е предефиниран и си иска единия аргумент. Т.е. до извикване на моя метод от Object така и не се стига. Някой може ли да ми каже какво пропускам?

    Публикувано преди повече от 4 години
  7. ами става следното (псевдокод)

    class Array < Object
      def &(other)
        return []
      end
    end

    никъде не се вика super (надявам се да имаш представа какво се опитвам да кажа, т.е. дано си програмирал на Java или C++ с класове)

    не се вика super 100%, т.к. Object няма &

    P.S. леле как го бях набрал текста преди…

    Публикувано преди повече от 4 години
  8. Това ми е ясно :) Въпроса ми е дали няма малко по-умно решение от това да пренаписвам оператора & за всички класове, които го дефинират.
    Най-елементарното, което ми идва на ум е просто да сменя името на въпросния метод, но в този случай, определено няма да мина тестовете :)

    Публикувано преди повече от 4 години
  9. Миналия път беше казано нещо за извикване на блок от метод, предефиниран чрез around_method. Примерно, да можем да around-нем метод each. Проблемът е, че не мога да измисля смислен начин да накарам това да работи правилно :) Тъй като не пишеше нищо за това в условието, трябва ли around_method да има тази функционалност?

    Публикувано преди повече от 4 години
  10. Ами да задавам и аз:

    3.(&)

     
    p nil.&.class # nil

    - не ни интересува x.& обекта

    4.(around) & 7.(proxy)
    трябва ли да имат достъп ограждащите функции до евентуалния блок подаден от външния свят на оградения обект
    e.g.

    Array.around_method do |obj, orig, *args|
      # access { |x| x>1 }
    end
    [1,2].select { |x| x>1 }

    8. (Array#==)
    работи стандартно, e.g.

    [1,2] < [1,2] # false
    [1,2] > [1,2] # false

    Публикувано преди повече от 4 години
  11. Mен също ме интересува отговорът на въпроса на Радан.

    Публикувано преди повече от 4 години
  12. @Радан: В условието си пише че трябва да накараш & да работи едновременно за [1, 2, 3].&.size и [1, 2, 3] & [2, 3, 4], така че явно ще се наложи да предефинираш метода за всички класове които го дефинират. Хубавото е че това може да стане по по-готин начин от очевидното ръчно предефиниране за всеки такъв клас.

    @Ивайло: И аз попаднах на бездънна рекурсия в хак#4, може би и при теб проблема е бил същия. При мен се получаваше от stack`нати around методи, може би тестовия ми код ще хвърли повече светлина на въпроса:

    def change_addition_6
    self.send(:alias_method, :old_plus, :+)

    new_addition = lambda do |other| self == 6 ? 6 : self.old_plus(other) end self.send(:define_method, :+, new_addition)

    end

    def change_addition_5
    self.send(:alias_method, :old_plus, :+)

    new_addition = lambda do |other| self == 5 ? 5 : self.old_plus(other) end self.send(:define_method, :+, new_addition)

    end

    class Fixnum
    change_addition_6
    change_addition_5
    end

    6 + 2 и 5 + 2 минават, но 7 + 2 предизвиква безкрайна рекурсия от извиквания на old_plus. Единственото обяснение което ми хрумва е че old_plus в change_addition_5 се дефинира чрез old_plus в change_selection_6 който започва да вика себе си. Явно при “създаването” на метод методите които той вика се “пазят” като имена а не като обекти, което е доста lame обяснение но не съм достатъчно навътре с езика:) Иначе като преименуваш old_plus на old_plus5 и old_plus6 съответно в change_addition_5 и change_addition_6 всичко тръгва без проблеми. Някой да има идея какво точно се случва под капака?

    Редакция: интересно, “:+” в поста излиза само като “:” :) Какъв таг използвате за ограждането на код в отговорите си?

    Публикувано преди повече от 4 години
  13. Сравнението на масиви трябва ли да работи за масиви от символи? Или за нещо различно от числа и низове?

    Публикувано преди повече от 4 години
  14. Въпроса на Точо, е изключително животрептющ. Т.е.

    nil.&()

    Интересува ли ни какво връща ?

    Публикувано преди повече от 4 години
  15. Може ли да одължите времето за задачата до към края на тази семица примерно ?

    Публикувано преди повече от 4 години
  16. На мен и до края на седмицата не би ми стигнало. Отказах се.

    Публикувано преди повече от 4 години
  17. Здрасти. Когато ни показахте 1вия хак, аз ви казах, че няма да работи. Не го казах просто ей така, ами щото аз го бях направил точно по същия начин и (не) знам защо, но юнит теста за Proxy-то не минаваше. След като ви минаха всички тестове, аз останах още по оциклен. Той даже Емил Станчев ви пита точно за същото нещо, а именно:

    Ако го напишем така:

    class Symbol
      def to_proc()
        Proc.new {|var, *vars| var.send(self, *vars)}
      end
    end

    Това при мен връща:

    [[]].reject(&:nil?) # =>[]

    Което е турбо нелогично, но такъв е живота. Въпроса ми това с какво е по-различно от :

    class Symbol
      def to_proc()
        Proc.new {|*vars| vars.first.send(self, *vars[1..-1])}
      end
    end

    Което връща това което очакваме:

    [[]].reject(&:nil?) # =>[[]]

    Публикувано преди повече от 4 години
  18. Мда, определено поведението е доста особено:

    def f
      yiled [1]
    end
    
    f { |var| p var } # резултат: [1] -- ОК
    f { |*vars| p vars } # резултат: [[1]] -- ОК
    f { |var, *vars| p var; p vars } # резултат: 1 и [] -- ?!

    Нямам идея защо се получава така :)

    Публикувано преди повече от 4 години
  19. не виждам нищо нередно в {|var, *vars|}

    просто не го викате правилно – по-точно че го викате така че той да не се държи както искате…

    yield има синтаксис в който му се подава списък и то го подава нататък като *args към функцията в зависимост от това какво тя очаква, като се старае да напасне максимално аргументите. Също така например ако функцията очаква 1 параметър x, а има yield a,b,c,d подава x=[a,b,c,d].

    The code speaks for itself:

    def a() yield *[[1]] end # the right way to call yield
    a { |var| p var } # [1] 
    a { |*vars| p vars } # [[1]]
    a { |var, *vars| p var; p vars } #  [1] , [] 
    a { |v1, v2| p v1, v2 } # [1] , nil
    p '-----'
    def b() yield [1] end
    b { |var| p var } # [1] 
    b { |*vars| p vars } # [[1]]
    b { |var, *vars| p var; p vars } #  1 , [] 
    b { |v1, v2| p v1, v2 } # 1 , nil
    p '-----'
    def c() yield [1,2] end
    c { |var| p var } # [1,2]
    c { |*vars| p vars } # [[1,2]]
    c { |var, *vars| p var; p vars } #  1 , [2] 
    c { |v1, v2| p v1, v2 } # 1 , 2
    p '-----'
    def d() yield Array[1,2] end
    d { |v1, v2| p v1, v2 } # 1 , 2
    def e() yield 1,2 end
    e { |var| p var } # [1,2]
    e { |*vars| p vars } # [1,2]
    e { |var, *vars| p var; p vars } #  1 , [2] 
    e { |v1, v2| p v1, v2 } # 1 , 2

    т.е., за да работи както искате – yield *[], block[] или block.call

    (Ако някой се чуди това държанието на yield е подвърдено под 1.8.6 и 1.9.0 :) )

    Публикувано преди повече от 4 години
  20. Намерих и къде съм го чел това…

    Programming Ruby
    The Pragmatic Programmer’s Guide
    (1st Edition, поради някаква причина не мога до го намеря в pdf-а на 2nd еdition…)

    """
    What happens if a block has a different number of parameters than are given to the yield? By a staggering coincidence, the rules we discuss under parallel assignment come into play (with a slight twist: multiple parameters passed to a yield are converted to an array if the block has just one argument).
    """

    ако някой има желание да чете – http://www.rubycentral.com/book/

    Публикувано преди повече от 4 години

Нов отговор

Трябва да сте вътре за да отговаряте.