Замыкания
От: BogdanMart Украина  
Дата: 28.01.11 21:58
Оценка:
Както по дебильному немерле генерит замыкания
                  def param = getOmmParameter(Guid($(param.ID.ToString() : string))); // ну тут макрос, но можете счиатать что это строка "66d1a69e-37d2-4569-9c81-3dc0b441d4a5"
                  param.PropertyChanged += fun(_, e)
                  {
                    when (e.PropertyName == "Value")
                      OnPropertyChanged((param.Name : string));
                  }
                  
                  param.Value :> $(param.Type.ToString() : usesite)
                }



и на вызоде получается

    get
    {
        _N_closure_8066 e_ = new _N_closure_8066 {
            _N__N_closurised_this_ptr_8071 = this,
            _N_param_8073 = this.getOmmParameter(new Guid())
        };
        FunctionVoid<object, PropertyChangedEventArgs> @void = new _N__N_lambda__8057__8075(e_);
        e_._N_param_8073.PropertyChanged += new PropertyChangedEventHandler(@void.apply_void);
        return (double) e_._N_param_8073.Value;
    }



Вопроссы
1) зачем Гуид пихать в замыкание? Если он ипсользуеться только в теле метода..
2) Зачем вообще создавать класс _N__N_lambda__8057__8075, C# создает в таком случаае приватный метод с рандомным именем, и подписывает на событие делегат на этот метод.

Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.

Это создавать целый метод для такой тривиальной задачи... а шарп справлялся...
Re: Замыкания
От: BogdanMart Украина  
Дата: 28.01.11 22:12
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>Както по дебильному немерле генерит замыкания

BM>
BM>                  def param = getOmmParameter(Guid($(param.ID.ToString() : string))); // ну тут макрос, но можете счиатать что это строка "66d1a69e-37d2-4569-9c81-3dc0b441d4a5"
BM>                  param.PropertyChanged += fun(_, e)
BM>                  {
BM>                    when (e.PropertyName == "Value")
BM>                      OnPropertyChanged((param.Name : string));
BM>                  }
                  
BM>                  param.Value :> $(param.Type.ToString() : usesite)
BM>                }
BM>



BM>1) зачем Гуид пихать в замыкание? Если он ипсользуеться только в теле метода..



Про замыкание для гуида вопрос снимаеться... забылся поставить $ перед (param.Name : string)
Re: Замыкания
От: hardcase Пират http://nemerle.org
Дата: 28.01.11 22:46
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.


Почему она запросто соберется сборщиком мусора?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 10:29
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, BogdanMart, Вы писали:


BM>>Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.


H>Почему она запросто соберется сборщиком мусора?


мы используем WeakDelegatе, по этому эта строка e_._N_param_8073.PropertyChanged += new PropertyChangedEventHandler(@void.apply_void); не создает ссылку на объект, и после выхода из текущего метода функция за коллектиться, а Шарп в этом случае просто создает метод в текущем классе и его подписывает...

Конечно никто не рассчитывал Немерле на WeakDelegatы, но все ровно не особо оптимально использовать Функцию, если она все ровно конвериться в делегат и скармливается ивенту.

Просто удивляет, что люди доказывают что Функции быстрее делегатов... а под капотом немерле такое вытворяет с замыканиями... что аж страшно.

Чистые функции может и быстрее, но обычные иногда создают лишнее замыкание.
Re: Замыкания
От: catbert  
Дата: 29.01.11 10:43
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>2) Зачем вообще создавать класс _N__N_lambda__8057__8075, C# создает в таком случаае приватный метод с рандомным именем, и подписывает на событие делегат на этот метод.


Делегаты медленные.

BM>Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.


Это почему?

BM>Это создавать целый метод для такой тривиальной задачи... а шарп справлялся...


Объект, вы хотите сказать? Но делегат (который возвращается в C#) тоже объект. А без создания метода в .NET наверное никак.
Re[2]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 10:48
Оценка:
Здравствуйте, catbert, Вы писали:



BM>>Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.


C>Это почему?


На этот вопрос я ответил хардкейсу

BM>>Это создавать целый метод для такой тривиальной задачи... а шарп справлялся...


C>Объект, вы хотите сказать? Но делегат (который возвращается в C#) тоже объект. А без создания метода в .NET наверное никак.


Я имел ввиду создавать метод вручную, когда шарп сам из лямбды создает метод, а не класс-функцию.

Пришлось сделать так

decl:
              private $(event_watcher : name) (_ : object, e : System.ComponentModel.PropertyChangedEventArgs) : void
              {
                when (e.PropertyName == "Value")
                  OnPropertyChanged($(param.Name : string));
              }

                get
                {
                  def param = getOmmParameter(Guid($(param.ID.ToString() : string)));
                  param.PropertyChanged += $(event_watcher : name);
                  
                  param.Value :> $(param.Type.ToString() : usesite)
                }


Казалось бы лишний метод создать, но где автоматизация..
Re[3]: Замыкания
От: hardcase Пират http://nemerle.org
Дата: 29.01.11 11:33
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>Здравствуйте, hardcase, Вы писали:


H>>Здравствуйте, BogdanMart, Вы писали:


BM>>>Я бы не возущался... но есть один нюанс, мы используем WeakDelegatе и по этому _N__N_lambda__8057__8075 запроста уберется сборщиком мусора... очень печально.


H>>Почему она запросто соберется сборщиком мусора?


BM>мы используем WeakDelegatе, по этому эта строка e_._N_param_8073.PropertyChanged += new PropertyChangedEventHandler(@void.apply_void); не создает ссылку на объект, и после выхода из текущего метода функция за коллектиться, а Шарп в этом случае просто создает метод в текущем классе и его подписывает...


Еще раз, для тупых. PropertyChangedEventHandler захватит только адрес apply_void метода без замыкания?
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Замыкания
От: hardcase Пират http://nemerle.org
Дата: 29.01.11 11:37
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>Вопроссы

BM>1) зачем Гуид пихать в замыкание? Если он ипсользуеться только в теле метода..

Это косяк оптимизации замыканий.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 12:04
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Еще раз, для тупых. PropertyChangedEventHandler захватит только адрес apply_void метода без замыкания?


WeakDelegate это объект который хрпнит в себесписок WeakReferenc'ов на объекты и список указателей на методы (не MatdodInfo а згенереный в рантайем динамический метод, который делает вызов) что позволяет объектам которые подпись на событие благополучно убераться сборщикоммусора. (Оно из делегата извлекает MethodInfo и ссылку на объект и преобразовывает их). Удобство Вик деоегато в первую очередь при работе с гуишкой. Например листобкс при устанвке в качестве ItemsSource коллекции подписываеться на событие CollectionChanged. а при уберании колеекции из ItemsSource НЕ ОТПИСЫВАЕТЬСЯ(Майровсойт -- мудаки), но даже еслибы он и отписывался при убирании из ИтемзСоурс, то при закрытии формочки она всеровно не убераеться, потому что делегат CollectionChanged содержыт ссылку на формочку. По этому и розработали ВикДелегаты.

а в этом случи на Слабо связаный ивент подписываеться метод объекта, который сздался локально, и ссылок на него нигде нету. вот он и убереться сборщиком мусора..

Ну как-бы ситуация не очень ординарная, но с другой стороны с этими функциями перемудрили где-то. Можно было и по проще сделать первоклассные функции.
Re[5]: Замыкания
От: Ziaw Россия  
Дата: 29.01.11 16:15
Оценка: 1 (1)
Здравствуйте, BogdanMart, Вы писали:

BM>а в этом случи на Слабо связаный ивент подписываеться метод объекта, который сздался локально, и ссылок на него нигде нету. вот он и убереться сборщиком мусора..


BM>Ну как-бы ситуация не очень ординарная, но с другой стороны с этими функциями перемудрили где-то. Можно было и по проще сделать первоклассные функции.


При работе со слабыми ссылками, ты должен учитывать, что объект на который она ссылается в любой момент просто исчезнет. Я не очень понимаю, в чем собственно проблема способа генерации замыканий в nemerle. Решение очень похоже на неудачный архитектурный костыль.
Re[6]: Замыкания
От: hardcase Пират http://nemerle.org
Дата: 29.01.11 16:26
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>При работе со слабыми ссылками, ты должен учитывать, что объект на который она ссылается в любой момент просто исчезнет.


Объект чей метод подписывается — это экземпляр функции (fun), создался он изза того, что компилятор решил что ссылка на него кудато уходит (подписывается событие).
Понятно что слабая ссылка на этот промежуточный объект функции не учитывается при сборке мусора и функция благополучно собирается сборщиком мусора. В итоге мы имеем то, что основной объект которому нжуно получать уведомления еще существует, но уведомлений он не получает — GC уже собрал экземпляр функции (на него не осталось ссылок).
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 18:15
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z> Решение очень похоже на неудачный архитектурный костыль.


Ну как бы создал метод и на него генерирую делегат.. Просто было лень метод создавать но вообще просто не понятно зачем немерлу генерить замыкание, если можно создать приватный метод и вместо замыкания использовать this
Re[7]: Замыкания
От: Ziaw Россия  
Дата: 29.01.11 18:27
Оценка:
Здравствуйте, hardcase, Вы писали:

Z>>При работе со слабыми ссылками, ты должен учитывать, что объект на который она ссылается в любой момент просто исчезнет.


H>Объект чей метод подписывается — это экземпляр функции (fun), создался он изза того, что компилятор решил что ссылка на него кудато уходит (подписывается событие).

H>Понятно что слабая ссылка на этот промежуточный объект функции не учитывается при сборке мусора и функция благополучно собирается сборщиком мусора. В итоге мы имеем то, что основной объект которому нжуно получать уведомления еще существует, но уведомлений он не получает — GC уже собрал экземпляр функции (на него не осталось ссылок).

В слабой ссылке лежит делегат, как я понял. Ну так это обычное поведение слабой ссылки, этот делегат может стать недоступным в любой момент, вне зависимости от того, какому объекту этот метод принадлежит.
Re[8]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 18:30
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В слабой ссылке лежит делегат, как я понял. Ну так это обычное поведение слабой ссылки, этот делегат может стать недоступным в любой момент, вне зависимости от того, какому объекту этот метод принадлежит.


В слабой ссылке лежит Target делегата
Re[9]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 18:36
Оценка:
BogdanMart писал:

BM>В слабой ссылке лежит Target делегата


часть кода вик делегата
        public void Add(TDelegate @delegate)
        {
            if (@delegate != null)
                lock (dels)
                    foreach (var del in ((Delegate)(object)@delegate).GetInvocationList())
                    {
                        var method = del.Method;
                        if(method.IsStatic)
                            _invk = Delegate.Combine(_invk , del);
                        else
                            dels.Add(new Tuple<WeakReference, Func<object, object[], object>, MethodInfo>(new WeakReference(del.Target), method.GetInvokator(), method));
                    }
        }


Где .GetInvokator()
        public static Func<object, object[], object> GetInvokator(this MethodInfo mi)
        {
            lock (cache)
            {
                Func<object, object[], object> fun;
                if (cache.TryGetValue(mi, out fun))
                    return fun;
                
                var method = new DynamicMethod("_" + r.Next(), typeof(object), _args,
                                               typeof (InvokatorFactory), true);

                var generator = method.GetILGenerator();
                var helper = new EmitHelper(generator);
                var parameters = mi.GetParameters();
                var len = parameters.Length;
                //--------------------
                if (!mi.IsStatic)
                    helper
                        .ldarg_0
                        .castclass(mi.DeclaringType);
                //--------------------
                for (int i = 0; i < len; i++)
                    helper
                        .ldarg_1
                        .ldc_i4_(i)
                        .ldelem_ref
                        .CastFromObject(parameters[i].ParameterType);
                //--------------------
                helper
                    .call(mi)
                    .parseRet(mi.ReturnType)
                    .ret();
                

                fun = (Func<object, object[], object>) method.CreateDelegate(typeof (Func<object, object[], object>));
                cache.Add (mi, fun);

                return fun;
            }
        }


По сути GetInvokator генерирует для метода M функцию (obj, params) => obj.M(params[0],..., params[n])
Re[7]: Замыкания
От: Ziaw Россия  
Дата: 29.01.11 18:41
Оценка:
Здравствуйте, BogdanMart, Вы писали:

Z>> Решение очень похоже на неудачный архитектурный костыль.


BM>Ну как бы создал метод и на него генерирую делегат.. Просто было лень метод создавать но вообще просто не понятно зачем немерлу генерить замыкание, если можно создать приватный метод и вместо замыкания использовать this


Ну если кроме this в замыкании ничего нет, то так и надо делать, но у тебя что-то еще туда пихается. Но главная проблема в использовании WeakReference не по назначению. Баги майкрософта конечно неприятные, но обходятся они без weakreference, который породит в этой ситуации баги похлеще. Можно обойтись спецколлекцией, которая проверяет кто на нее подписался и подписывается на диспоуз листбокса.
Re[8]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 18:43
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Можно обойтись спецколлекцией, которая проверяет кто на нее подписался и подписывается на диспоуз листбокса.


ВО! , хреново.
Re[10]: Замыкания
От: Ziaw Россия  
Дата: 29.01.11 18:54
Оценка: +1
Здравствуйте, BogdanMart, Вы писали:

BM>BogdanMart писал:


BM>>В слабой ссылке лежит Target делегата


Я понял, в дотнете есть штатный механизм, позволяющий гарантировать отсутствие проблем с GC при правильной работе с делегатами и событиями и ты этот механизм ломаешь намеренно. Грабли обеспечены, на одни ты уже наступил, то, что шарп делает сейчас приватным методом, при небольшой модификации кода превратится в объект замыкания, ты даже не поймешь что произошло, когда программа начнет падать в непредсказуемых местах.
Re[11]: Замыкания
От: BogdanMart Украина  
Дата: 29.01.11 19:01
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, BogdanMart, Вы писали:


BM>>BogdanMart писал:


BM>>>В слабой ссылке лежит Target делегата


Z>Я понял, в дотнете есть штатный механизм, позволяющий гарантировать отсутствие проблем с GC при правильной работе с делегатами и событиями.

С этоо места, пожалуйста, по подробнее!

Z> Gри небольшой модификации кода превратится в объект замыкания, ты даже не поймешь что произошло

Я то пойму.. замікания шарю хорошо, да и не надо его менять. (но в целом самому создать метод надежнее, безусловно, так и сделал..)
Re[12]: Замыкания
От: Ziaw Россия  
Дата: 29.01.11 19:12
Оценка: +1
Здравствуйте, BogdanMart, Вы писали:

Z>>Я понял, в дотнете есть штатный механизм, позволяющий гарантировать отсутствие проблем с GC при правильной работе с делегатами и событиями.

BM>С этоо места, пожалуйста, по подробнее!

Да ты сам прекрасно его знаешь, делегат держит ссылку на таргет и не дает сборщику его собрать. Если мы можем как-то обратиться к объекту, значит он не будет собран.

Z>> Gри небольшой модификации кода превратится в объект замыкания, ты даже не поймешь что произошло

BM>Я то пойму.. замікания шарю хорошо, да и не надо его менять. (но в целом самому создать метод надежнее, безусловно, так и сделал..)

Это ты сейчас поймешь, а через год-другой сильно удивишься, ибо падения начнутся совсем не сразу после невинной модификации кода, которую сделаешь, возможно, совсем не ты
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.