1.Допустим, есть абстрактный класс A, в котором содержится список элементов этого же класса, например, protected con : list[A]. Можно ли указать в классе-наследнике B : A, чтобы этот список con мог содержать только элементы другого класса C : A или производные от него X : C?
2.Когда я программировал на с++, я создавал специальный класс Globals со статическими членами для глобальных переменных и методов. Тут что-то не получается обратиться к статической переменной. Как быть?
Здравствуйте, Niovol, Вы писали:
N>1.Допустим, есть абстрактный класс A, в котором содержится список элементов этого же класса, например, protected con : list[A]. Можно ли указать в классе-наследнике B : A, чтобы этот список con мог содержать только элементы другого класса C : A или производные от него X : C?
Можно в наследнике создать свойство с тем же именем, но другим типом:
using System.Console;
using SCG = System.Collections.Generic;
public class A
{
public Collection : SCG.IList[A] { get { array[A(), A()] } }
}
public class B : A
{
public new Collection : SCG.IList[B] { get { array[B(), B()] } }
}
module Program
{
Main() : void
{
def b = B();
def a = A();
WriteLine(a.Collection[1].GetType().Name);
WriteLine(b.Collection[1].GetType().Name);
_ = ReadLine();
}
}
N>2.Когда я программировал на с++, я создавал специальный класс Globals со статическими членами для глобальных переменных и методов. Тут что-то не получается обратиться к статической переменной. Как быть?
Должно получаться. Можно просто обявить модуль (в нем все члены статические):
module X
{
public Y : int = 1;
}
...
WriteLine(X.Y)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Вот такая еще проблема. Есть классы A, B и C. B — наследник класса А. В классе С есть функция, которая принимает по ссылке элемент класса А. Нужно извне вызвать функцию от ссылки на элемент класса B. При вызове — ошибка. Вопрос касается в принципе не только немерле, но и c#.
Здравствуйте, Niovol, Вы писали:
N>Вот такая еще проблема. Есть классы A, B и C. B — наследник класса А. В классе С есть функция, которая принимает по ссылке элемент класса А. Нужно извне вызвать функцию от ссылки на элемент класса B. При вызове — ошибка. Вопрос касается в принципе не только немерле, но и c#.
Эээ, ошибочный код приведи, плиз. Так ничего не понятно
Здравствуйте, Сергей Туленцев, Вы писали:
СТ>Эээ, ошибочный код приведи, плиз. Так ничего не понятно
public abstract class Element
{
//...
}
public class Perceptron : Element, IBackPropagationInstructable
{
//...
}
public class Instructor
{
//...
public Instruct(Net : ref Element) : void
{
match(Net)
{
| _ is IBackPropagationInstructable =>
{
// Тут операции с переменной Net
}
| _ => {}
}
}
}
Далее код на с#, который использует dll библиотеку классов, написанных на немерле.
Perceptron p = new Perceptron();
Instructor Ins = new Instructor();
//...
Ins.Instruct(ref p);
Error 1 The best overloaded method match for 'NeuroV.Instructor.Instruct(ref NeuroV.Construction.Element)' has some invalid arguments
Error 2 Argument '1': cannot convert from 'ref NeuroV.Models.Perceptron' to 'ref NeuroV.Construction.Element'
Как я понял, немерле основан на функциональном подходе, а всякие циклы описаны макросами через вызовы функций. Если же, к примеру, пускать обычный for(mutable i...), не получится ли время исполнения больше, чем следует ожидать?
У меня, кажется, на немерле программы работают по крайней мере в 2 раза дольше, чем на с++. Не знаю, дело в кривом написании кода, или на .NET жаловаться. Я как бы с .NET недавно столкнулся, до этого на чистом с++ программировал.
Здравствуйте, Niovol, Вы писали:
N>Здравствуйте, Сергей Туленцев, Вы писали:
N>Error 1 The best overloaded method match for 'NeuroV.Instructor.Instruct(ref NeuroV.Construction.Element)' has some invalid arguments N>Error 2 Argument '1': cannot convert from 'ref NeuroV.Models.Perceptron' to 'ref NeuroV.Construction.Element'
ECMA-334, Overload resolution
14.4.2.1 Applicable function member
A function member is said to be an applicable function member with respect to an argument list A when all
of the following are true:
• The number of arguments in A is identical to the number of parameters in the function member
declaration.
• For each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is
identical to the parameter passing mode of the corresponding parameter, and
o for a value parameter or a parameter array, an implicit conversion (§13.1) exists from the type of the
argument to the type of the corresponding parameter, or
o for a ref or out parameter, the type of the argument is identical to the type of the corresponding
parameter. [Note: After all, a ref or out parameter is an alias for the argument passed. end note]
Ок, т.е. по определению типы должны совпадать? А если все-таки нужно передать, передавать просто не по ссылке? Тогда будет производиться копирование экземпляра? Мне же нужно производить манипуляции с любым из переданных наследников конкретного класса.
Помнится, в с++ подобное я передавал указателями. Но в дот нете ведь нет указателей? Как быть в таком случае?
Здравствуйте, Niovol, Вы писали:
N>Ок, т.е. по определению типы должны совпадать? А если все-таки нужно передать, передавать просто не по ссылке? Тогда будет производиться копирование экземпляра? Мне же нужно производить манипуляции с любым из переданных наследников конкретного класса.
N>Помнится, в с++ подобное я передавал указателями. Но в дот нете ведь нет указателей? Как быть в таком случае?
Будет производиться копирование ссылки (по С++ному — указателя). Экземпляр класса копироваться не будет. Копируются только структуры. В общем, почитай что-нибудь основополагающего. Например, вот это
Здравствуйте, Сергей Туленцев, Вы писали:
СТ>Будет производиться копирование ссылки (по С++ному — указателя). Экземпляр класса копироваться не будет. Копируются только структуры. В общем, почитай что-нибудь основополагающего. Например, вот это
Ок, спасибо. Только на ссылку не выходит. Завтра поищу инфу. Плюс еще есть книжка от майкрософта по .NET, правда, 2003 года.
Здравствуйте, Niovol, Вы писали:
N>Здравствуйте, Сергей Туленцев, Вы писали:
СТ>>Будет производиться копирование ссылки (по С++ному — указателя). Экземпляр класса копироваться не будет. Копируются только структуры. В общем, почитай что-нибудь основополагающего. Например, вот это
N>Ок, спасибо. Только на ссылку не выходит. Завтра поищу инфу. Плюс еще есть книжка от майкрософта по .NET, правда, 2003 года.
Здравствуйте, Niovol, Вы писали:
N>Error 1 The best overloaded method match for 'NeuroV.Instructor.Instruct(ref NeuroV.Construction.Element)' has some invalid arguments N>Error 2 Argument '1': cannot convert from 'ref NeuroV.Models.Perceptron' to 'ref NeuroV.Construction.Element'
Просто объяви переменную как Element. Это дотнетные тараканы связанные с передачей ref-параметров.
ЗЫ
Общий совет. В Немерле лучше вообще обходиться без ref-параметров. В нем есть tuple-ы (см. статьи и документацию). Они куда удобнее. Если возвращаемое значение одно, то его тоже имеет смысл возвращать прям из функции, а не делать out/ref.
Кстати, в дотнете большинство объектов ссылочные (не ссылочные только перечисления, структуры и встроенные типы вроде int). Передача из по ссылке только замедлит работу. Ну, и любое изменение состояния объекта будет видно внешней стороне. Единственное что не удастся сделать бещ ref — это изменить ссылку на переменную.
Так что почти на 100% уверен, что ref тебе не нужен.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Niovol, Вы писали:
N>Ок, т.е. по определению типы должны совпадать? А если все-таки нужно передать, передавать просто не по ссылке? Тогда будет производиться копирование экземпляра? Мне же нужно производить манипуляции с любым из переданных наследников конкретного класса.
N>Помнится, в с++ подобное я передавал указателями. Но в дот нете ведь нет указателей? Как быть в таком случае?
C++ более низкоуровневый язык. В C#/Nemerle все типы деляться на два основных подтипа:
1. Ссылочные типы — они всегда передаются по ссылке (как правильно заметил Сергей это почти (по крайней мере по эффективности) соответствует передаче указателя или по ссылке в С++.
2. Value-типы. Вот они всегда передаются по значению (т.е. коприуется память). Вот это аналогично передаче не по ссылке в С++. Вот для изменения их содержимого имеет нужно применять ref. Но оять же это не лучший выход. Лучше иметь вэлью-типы небольшого размера (до 16 байт) и передавать их по значению. Это сделает программы надежнее и не просадит производительность.
А вообще, тебе нужно почитать о семантике объекто в дотнете (о делении объектов на вылью-типы и на ссылочные типы). Очень хорошо об этом написано у Рихтера. В прочем в стеи описаний тоже достаточно. На нашем сайте, например, можно почитать: http://www.rsdn.ru/article/dotnet/values.xml
Здравствуйте, Niovol, Вы писали:
N>Как я понял, немерле основан на функциональном подходе, а всякие циклы описаны макросами через вызовы функций.
Так и есть, но вызовы функций с концевой рекурсии оптимизируются и превращаются в код аналогичный циклам.
N>Если же, к примеру, пускать обычный for(mutable i...), не получится ли время исполнения больше, чем следует ожидать?
По крайней мере разница пренебрежима мала. Так что не забивай себе голову подобной фигней. Потери производительности надо искть не там.
N>У меня, кажется, на немерле программы работают по крайней мере в 2 раза дольше, чем на с++. Не знаю, дело в кривом написании кода, или на .NET жаловаться. Я как бы с .NET недавно столкнулся, до этого на чистом с++ программировал.
Это надо на программы смотреть. В дотете модули грузятся дольше, что часто вызвает впечатление заторможенности.
Лучше расскажи про свои задачи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Лучше расскажи про свои задачи.
Вот, там, где мне как раз критично время — это нейронные сети. Моя корявая программа на с++, на которую я грешил, на некоторых входных данных обучается где-то за 1.5 секунды. На тех же входных данных на немерле обучается секунды 3. Причем, как я думал, один кусок кода, который был не очень быстрым на с++, я на немерле написал по крайней мере лучше. Прога, которую пишу на немерле, не является копией сишной, но по смыслу выполняют все-таки одинаковые операции. Почему тут критично время — основной цикл проходит тысячи итераций, иногда десятки тысяч.
Здравствуйте, Niovol, Вы писали:
N>Вот, там, где мне как раз критично время — это нейронные сети. Моя корявая программа на с++, на которую я грешил, на некоторых входных данных обучается где-то за 1.5 секунды. На тех же входных данных на немерле обучается секунды 3. Причем, как я думал, один кусок кода, который был не очень быстрым на с++, я на немерле написал по крайней мере лучше. Прога, которую пишу на немерле, не является копией сишной, но по смыслу выполняют все-таки одинаковые операции. Почему тут критично время — основной цикл проходит тысячи итераций, иногда десятки тысяч.
В нейронных сетях не ничего не понимаю, так что конретных советов дать не смогу. Тут где-то советовали их описывать не объектами, а чем-то более примитивным.
Кроме того имеет смысл попробовать прогнать профайлер и поглядеть на что он показывает.
Десятки же и даже сотни тысяч проходов не так уж много, если конечно при этом на каждом проходе не выполняется какие-то долгие операции (например, создание объектов). Надо избегать такие опрации (по возможности) и стараться превычислять все что можно предварительно вычислить.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>В нейронных сетях не ничего не понимаю, так что конретных советов дать не смогу. Тут где-то советовали их описывать не объектами, а чем-то более примитивным.
Вот именно это одно из соображений. Саму сеть и слои нейронов описал объектами, а нейроны — массивом чисел в классе слоя.
Только что возник вопрос, сколько времени идет доступ к произвольному элементу класса List[некоторый класс]? При том, что он содержит всего несколько экземпляров класса. VD>Кроме того имеет смысл попробовать прогнать профайлер и поглядеть на что он показывает.
Как раз хотел спросить в предыдущем посте, как пользоваться профайлером, где можно почитать, к примеру. Я пробовал ставить VTune, но так и не разобрался, по инструкции не получалось. VD>Десятки же и даже сотни тысяч проходов не так уж много, если конечно при этом на каждом проходе не выполняется какие-то долгие операции (например, создание объектов). Надо избегать такие опрации (по возможности) и стараться превычислять все что можно предварительно вычислить.
Нет, объекты создаются только в конструкторах. За одну итерацию по нескольку раз проходят вложенные циклы, поэтому, десятки тысяч итераций — уже значительно. А превычислять — это как?
Здравствуйте, Niovol, Вы писали:
VD>>В нейронных сетях не ничего не понимаю, так что конретных советов дать не смогу. Тут где-то советовали их описывать не объектами, а чем-то более примитивным. N>Вот именно это одно из соображений. Саму сеть и слои нейронов описал объектами, а нейроны — массивом чисел в классе слоя. N>Только что возник вопрос, сколько времени идет доступ к произвольному элементу класса List[некоторый класс]? При том, что он содержит всего несколько экземпляров класса.
А распараллеливать List не пробовал ? Воспользуйся прямой выгодой от функционального языка. Вот пример на F#. На Nemerle будет почти тоже самое.
[с#]
#light
namespace EeekSoft.FSharp
open System
open System.Threading
module Utils = begin
/// Same as List.fold_left function, but passes index of item in the list
/// as a first parameter to fold function
let list_fold_lefti (func:int -> 'a -> 'b -> 'a) (acc:'a) (l:'b list) =
let rec fli (func:int -> 'a -> 'b -> 'a) (acc:'a) (l:'b list) (n:int) =
match l with | [] -> acc | (h::t) -> fli func (func n acc h) t (n + 1)
fli func acc l 0;
end
module ParallelList = begin
/// Class that manages threads and executes operations in parallel
type ('a, 'b) ThreadProcessor = class
val threads : Thread array;
val worklist : 'a array;
val results : 'b array;
val result_states : int array;
val operation : 'a -> 'b;
val lock : obj;
val mutable position : int;
val mutable running : bool;
val mutable finished : int;
/// Accepts number of threads, array of input data and
/// mapping function as parameters
new((count:int), (arr:'a array), (func:'a -> 'b)) as t =
{
lock = new obj();
running = true;
worklist = arr;
results = Array.zero_create arr.Length;
result_states = Array.create arr.Length 0;
operation = func;
position = 0;
threads = Array.init count ( fun n -> new Thread(new ThreadStart(t.Process)) );
finished = 0;
}
then
t.threads |> Array.iter ( fun t -> t.Start() );
/// Stop execution and wait for all threads to complete
member t.Stop () =
t.running <- false;
t.threads |> Array.iter ( fun t -> t.Join() );
/// Private method executed by the thread(s)
member t.Process () =
// Get section in worklist that will be processed
let (sf, st) = Idioms.lock t.lock ( fun () ->
let len = t.worklist.Length;
if (t.position = len) then
t.running <- false; (1, 0)
else
let npos = t.position + (len — t.position) / (2*t.threads.Length);
let ret = (t.position, npos);
t.position <- npos + 1;
ret )
// Process section
for n = sf to st do
t.results.[n] <- (t.operation t.worklist.[n]);
done;
// Continue? tail-recursive...
if (t.running) then t.Process();
/// Reads results
/// TODO: it could be better to return Seq<'b>
member t.Results
with get() =
let mutable res = [] in
let max = (t.worklist.Length — 1)
let rec item n =
// TODO: Use Interlocked.Compare...
if (t.result_states.[n] = 0) then Thread.Sleep(10); item n; else t.results.[n];
for n = max downto 0 do
res <- (item n)::res;
done
res;
end
let mutable threadcount = 2
let get_thread_count () = threadcount
let set_thread_count n = threadcount <- n
let filter (func:'a -> bool) (lst:'a list) =
let arr = lst |> List.to_array;
let proc = new ThreadProcessor<'a, bool>(threadcount, arr, func)
let ret = proc.Results |> Utils.list_fold_lefti ( fun i acc v ->
match v with | true -> (arr.[i])::acc | false -> acc ) []
proc.Stop();
ret
let map (func:'a -> 'b) (lst:'a list) =
let arr = lst |> List.to_array;
let proc = new ThreadProcessor<'a, 'b>(threadcount, arr, func)
let ret = proc.Results
proc.Stop();
ret