Re[10]: Где у ФЯ матчасть?
От: Gaperton http://gaperton.livejournal.com
Дата: 03.09.04 11:38
Оценка: :)
Здравствуйте, Mink, Вы писали:

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


G>>{ Колесо, МашинаБезКолеса } = снятьПереднееКолесо( Машина, Ключ ).

G>>Так лучше?

M>Нет. Лучше:

M>машина.СнятьПереднееКолесо(ключ);
Кто снимает колесо? Умная машина, так выходит? Мне ей только надо отправить сообщение — "снять переднее колесо", и приложить к нему ключ. Машины они такие, все с первого слова понимают.

Согласен, так лучше, зачем самому корячиться

А если серьезно, то абсолютно пофигу, как писать. Разница между ФЯ и не ФЯ будет только в результате операции. Если она вернет измененный объект как часть результата, не тронув предыдущий — это функциональный стиль. Вот и весь пафос.
Re[12]: Где у ФЯ матчасть?
От: Кодт Россия  
Дата: 03.09.04 11:46
Оценка: 4 (1)
Здравствуйте, Mink, Вы писали:

M>Во первых, такое элементарно реализуется на ИЯ.

M>Во вторых, с точки зрения читабельности кода первый вариант мне больше нравится.

Кому-то нужны пошаговые инструкции, а кому-то — образ результата.

К примеру с колесом:

1.1)
Приезжает дама на сервис, и говорит мастеру: "возьми ключ 19, поставь домкрат, поочерёдно отверни 4 болта с колеса, подними машину, сними колесо, .............., получи деньги, конец".
Что сделает мастер? Спросит "За кого ты меня держишь, *****?".
1.2)
... и говорит: "Проколото левое заднее колесо. Вот деньги, вот машина, почините плиз."

2.1)
Мастер принял заказ и передаёт машину подмастерью со словами "Вот машина, вот инструменты, вот ремкомплект, вперёд".
Подмастерье спрашивает: "Как, чёрт побери?"

2.2)
со словами "возьми ключ 19, ........., а деньги я тебе в конце смены отдам, конец".

2.3)
со словами "Чтобы починить колесо, нужно его снять, диагностировать, заклеить..... Чтобы его снять, нужно отвинтить болты и поддомкратить машину....."
Перекуём баги на фичи!
Re[12]: Где у ФЯ матчасть?
От: Gaperton http://gaperton.livejournal.com
Дата: 03.09.04 11:51
Оценка:
Здравствуйте, Mink, Вы писали:

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


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


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


G>>>>{ Колесо, МашинаБезКолеса } = снятьПереднееКолесо( Машина, Ключ ).

G>>>>Так лучше?

M>>>Нет. Лучше:


M>>>машина.СнятьПереднееКолесо(ключ);


N_>>А теперь сравните:


N_>>машина.СнятьКолесо();

N_>>машина.Починить();
N_>>машина.ОдетьКолесо();

N_>>и


N_>>ОдетьКолесо(Починить(СнятьКолесо(машина)))


M>Во первых, такое элементарно реализуется на ИЯ.

M>Во вторых, с точки зрения читабельности кода первый вариант мне больше нравится.

починитьМашину( МашинаСПробитымКолесом ) ->
  Ключ = чешемРепуИВыбираемКлюч( МашинаСПробитымКолесом ),
  { ПлохоеПробитоеКолесо, МашинаБезКолесаЕхатьНеМожет } = снятьПереднееКолесо( МашинаСПробитымКолесом, Ключ ),
  ХорошееОтремонтированноеКолесо = Отремонтировать( ПлохоеПробитоеКолесо ),
  МашинаГотоваДавайДеньги = одетьПереднееКолесо( МашинаБезКолесаЕхатьНеМожет, Ключ, ХорошееОтремонтированноеКолесо ),
  { МашинаГотоваДавайДеньги, вотСколькоТыМнеДолжен( МашинаСПробитымКолесом, МашинаГотоваДавайДеньги ) }


Так лучше?

Вообще такие вещи совершенно одинаково выглядят на ФЯ и ИЯ. Здесь различия только косметические.
Re[11]: Где у ФЯ матчасть?
От: Mink Россия  
Дата: 03.09.04 12:23
Оценка: +6
Здравствуйте, Gaperton, Вы писали:

G>А если серьезно, то абсолютно пофигу, как писать. Разница между ФЯ и не ФЯ будет только в результате операции. Если она вернет измененный объект как часть результата, не тронув предыдущий — это функциональный стиль. Вот и весь пафос.


Насчет пофиг я, пожалуй, не соглашусь
Вообще, насчет легкости восприятия языковых конструкций по момему лучше всего сказал Элджер:

«Простые и последовательные» языки никогда не пользовались особым успехом за стенками академий, а языки с блочной структурой овладели массами. Стоит ли этому удивляться? Ведь компьютерные языки приходится изучать и запоминать, а для этого используется то же серое вещество, с помощью которого мы изучаем и запоминаем естественные языки. Попробуйте-ка назвать хотя бы один естественный язык без существительных, глаголов и скобок! Я бы не рискнул. Все наши познания в лингвистике говорят о том, что эти «плохие» особенности только ускоряют изучение компьютерного языка и делают его более понятным. i++ во всех отношениях действительно понятнее, чем i:=i+1, а x=17+29 читается лучше, нежели (setq(x(+17, 29)). Речь идет не о строении компьютерного языка, а скорее о нашем собственном строении.

Сила, она в ньютонах
Re[23]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 03.09.04 15:41
Оценка:
DG>>Как об этом узнает модуль-визуализатор?

N_>Если "ссылка" внешняя для программы, то работать с ней надо так же как с вводом-выводом.

N_>Если эта "ссылка" для программы внутренняя, то один модуль просто передает обновленные данные другому по значению. И уже дело компилятора как передать его на самом деле. По ссылке или как-то по другому.

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

Допустим у нас распределенная система — есть что-то (объект, функция — не важно)-сервер, и есть что-то клиенты.

Клиенты могут независимо менять сервер, при этом все остальные клиенты должны работать уже с измененным состоянием.

И вот не понятно, как это будет выглядить на ФЯ.

ps
На объектах это выглядит просто:

class Server
{
  public int Value;
}

class Client
{
  public Client(Server server) {this.server = server;}
  Server server;
  public void OnTick()
  {
    if (new Random().Next(2) == 0)
       server.Value++;
    Out.Write(server.Value);
  }
}

void Main()
{
  Server server =new Server();
  Timer timer = new Timer();
  timer.Interval = 10;
  timer.Start();
  for (int i = 0; i < 10; ++i)
  {
    Client client = new Client(server);
    timer.Tick += server.OnTick;
  }
}
Re[24]: Сферы применения
От: Кодт Россия  
Дата: 03.09.04 15:55
Оценка:
Здравствуйте, DarkGray, Вы писали:

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


Фактически, передача чего-то по ссылке — это передача не данных, а функции доступа.
Говоря на C++,
void foo(int& bar)
{
  x = bar; sleep();
  y = bar; sleep();
  z = bar; sleep();
  bar = t;
}

////////////////////

void foo(/*byval*/ int(*get)(), /*byval*/ void(*put)(int))
{
  x = get(); sleep();
  y = get(); sleep();
  z = get(); sleep();
  put(t);
}
Перекуём баги на фичи!
Re[24]: Сферы применения
От: Gaperton http://gaperton.livejournal.com
Дата: 03.09.04 16:37
Оценка: 5 (1)
Здравствуйте, DarkGray, Вы писали:

DG>>>Как об этом узнает модуль-визуализатор?


N_>>Если "ссылка" внешняя для программы, то работать с ней надо так же как с вводом-выводом.

N_>>Если эта "ссылка" для программы внутренняя, то один модуль просто передает обновленные данные другому по значению. И уже дело компилятора как передать его на самом деле. По ссылке или как-то по другому.

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


DG>Допустим у нас распределенная система — есть что-то (объект, функция — не важно)-сервер, и есть что-то клиенты.


DG>Клиенты могут независимо менять сервер, при этом все остальные клиенты должны работать уже с измененным состоянием.


DG>И вот не понятно, как это будет выглядить на ФЯ.

По другому. Вот чисто функциональный вариант, когда все происходит одном процессе.
Главная функция — менеджер событий. Из нее вызывается сервер, и все клиенты. Elrang.

eventCycle( { Server, Clients } ) ->
   receive
   after 1000
      eventCycle( processEvent( fun OnTick/2, Clients, Server, [] ) )
   end.

processEvent( EventHandler, [ Client | Clients ], Server, UpdatedClients ) ->
    { UpdatedClient, UpdatedServer } = EventHandler( Client, Server ),
    processEvent( Clients, UpdatedServer, [ UpdatedClient | UpdatedClients ] ) ];
processEvent( [], Server, UpdatedClients ) -> { Server, UpdatedClients }.

OnTick( Client, Server ) ->
   %% do something, for example
   { Client, Server + 1 }.


Я надеюсь, принцип понятен — это можно обобщить до произвольных событий и реализовать подписку.

Если приложение будет распределенным, то решение на Erlang будет отчасти императивным. Мы запустим по одному процессу на сервер и каждого клиента, и они будут обмениваться сообщениями. Каждый процесс реализуется бесконечно рекурсивной функцией, содержащей обработчик сообщений. Логика внутри процессов будет сделана на чистых функциях.
Re[12]: Где у ФЯ матчасть?
От: Gaperton http://gaperton.livejournal.com
Дата: 03.09.04 17:11
Оценка:
Здравствуйте, Mink, Вы писали:

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


G>>А если серьезно, то абсолютно пофигу, как писать. Разница между ФЯ и не ФЯ будет только в результате операции. Если она вернет измененный объект как часть результата, не тронув предыдущий — это функциональный стиль. Вот и весь пафос.


M>Насчет пофиг я, пожалуй, не соглашусь

Имелось в виду Obj.Method( Parm ) или Method( Obj, Parm ).
Re[25]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 03.09.04 17:54
Оценка:
К>Фактически, передача чего-то по ссылке — это передача не данных, а функции доступа.

Согласен. Но функция опять же откуда должна брать меняющиеся данные...
Re[25]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 03.09.04 17:57
Оценка:
G>Я надеюсь, принцип понятен — это можно обобщить до произвольных событий и реализовать подписку.

А где работа с данными? т.е. где видно, что каждый из клиентов получает обновленные данные с сервера?
Re[9]: Где у ФЯ матчасть?
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 03.09.04 18:05
Оценка: +2
G>{ Колесо, МашинаБезКолеса } = снятьПереднееКолесо( Машина, Ключ ).
G>Так лучше?

Меня смущает идентификатор "МашинаБезКолеса".
Это же получается, что также будут идентификаторы "МашинаБезДвухКолес", "МашинаБезКолесаИБампера", "МашинаСКолесамиНоБезЗапаски" и т.д., т.е. на лицо комбинаторный взрыв, причем не понятно, как этого можно будет избежать в реальном проекте.
Re[26]: Сферы применения
От: Nick_ Россия  
Дата: 04.09.04 04:05
Оценка:
Здравствуйте, DarkGray, Вы писали:


К>>Фактически, передача чего-то по ссылке — это передача не данных, а функции доступа.


DG>Согласен. Но функция опять же откуда должна брать меняющиеся данные...


Если вы будуте хранить изменяющиеся данные в общей памяти, то ваша программа будет работать только в одном потоке.
Либо вам придется расставлять критические секции где попало. При этом не факт, что вы правильно с первого раза расставите критические секции и избежите взаимных блокировок.
Да, в функциональных языках для вас будет немного необычно написать то, что хотите. Зато компилятор сможет ее автоматически распараллелить.
Re[10]: Где у ФЯ матчасть?
От: Nick_ Россия  
Дата: 04.09.04 04:07
Оценка:
Здравствуйте, DarkGray, Вы писали:


G>>{ Колесо, МашинаБезКолеса } = снятьПереднееКолесо( Машина, Ключ ).

G>>Так лучше?

DG>Меня смущает идентификатор "МашинаБезКолеса".

DG>Это же получается, что также будут идентификаторы "МашинаБезДвухКолес", "МашинаБезКолесаИБампера", "МашинаСКолесамиНоБезЗапаски" и т.д., т.е. на лицо комбинаторный взрыв, причем не понятно, как этого можно будет избежать в реальном проекте.

Я уже писал.
новая_машина = одеть(починить(снять(машина)))
Re[27]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 04.09.04 07:25
Оценка:
DG>>Согласен. Но функция опять же откуда должна брать меняющиеся данные...

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


Вы ушли от вопроса.
На данный момент мне пофигу на блокировки, синхронизацию и т.д.
Сейчас мне интересно видеть, как две независимых части программы получают меняющиеся данные.
От Вас я услышал пока только одни общие слова "ФЯ — крутая парадигма, и там таких проблем нет", и не увидел ни одного конкретного примера.
Создается ощущение, что Вы не понимаете о чем Вас спрашивают, а только повторяете заученные слова.
Re[28]: Сферы применения
От: Nick_ Россия  
Дата: 04.09.04 08:16
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>>>Согласен. Но функция опять же откуда должна брать меняющиеся данные...


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


DG>Вы ушли от вопроса.

DG>На данный момент мне пофигу на блокировки, синхронизацию и т.д.
DG>Сейчас мне интересно видеть, как две независимых части программы получают меняющиеся данные.
DG>От Вас я услышал пока только одни общие слова "ФЯ — крутая парадигма, и там таких проблем нет", и не увидел ни одного конкретного примера.
DG>Создается ощущение, что Вы не понимаете о чем Вас спрашивают, а только повторяете заученные слова.

Чесно говоря, я не понимаю вопроса.
если есть глобальные для программы данные, которые могут меняться обоими модулями, то модули должны их передавать друг другу по очереди. Если меняет один модуль, а другой только доступается, то первый модуль вызывает второй и передает ему данные, либо второй модуль вызывает первый что бы тот вернул ему эти данные. Я не понимаю в чем тут трудность?
Если бы вы привели пример кода на каком-нибудь императивном псевдоязыке, то я бы смог привести анологичный пример на функциональном языке.
Re[29]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 04.09.04 08:55
Оценка:
N_>Чесно говоря, я не понимаю вопроса.
N_>если есть глобальные для программы данные, которые могут меняться обоими модулями, то модули должны их передавать друг другу по очереди.

Есть глобальные данные, которые меняются и читаются несколькими независимыми модулями.

ps
Независимые означает, что модули друг о друге не знают

N_>Если бы вы привели пример кода на каком-нибудь императивном псевдоязыке, то я бы смог привести анологичный пример на функциональном языке.


http://www.rsdn.ru/Forum/Message.aspx?mid=793251&amp;only=1
Автор: DarkGray
Дата: 03.09.04
Re[30]: Сферы применения
От: Nick_ Россия  
Дата: 04.09.04 09:50
Оценка:
ЗDG>Есть глобальные данные, которые меняются и читаются несколькими независимыми модулями.

DG>ps

DG>Независимые означает, что модули друг о друге не знают

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

N_>>Если бы вы привели пример кода на каком-нибудь императивном псевдоязыке, то я бы смог привести анологичный пример на функциональном языке.


DG>http://www.rsdn.ru/Forum/Message.aspx?mid=793251&amp;only=1
Автор: DarkGray
Дата: 03.09.04


Не совсем понятный пример. У вас там что, Client.OnTick вызывается из какого-то другого потока?
Re[31]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 04.09.04 10:28
Оценка:
N_>Не совсем понятный пример. У вас там что, Client.OnTick вызывается из какого-то другого потока?

В данном примере из одного (считается, что в потоке всегда есть очередь сообщения).

ps
Можно также сделать, чтобы OnTick вызывался из нескольких потоков.
Re[31]: Сферы применения
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 04.09.04 10:34
Оценка:
N_>Глобальных данных в функциональном программировании не существует.

Нет, не только глобальных данные — нет, вообще, общих данных.

N_>Придется передавать эти данные клиенту и серверу явно.


Для больших программ — это подобно смерти, т.к. получается что каждый модуль должен знать обо всех остальных модулях.
Получается, что обязательно должен быть человек, которые будет держать в голове все зависимости между всеми модулями.

т.е. фактически не получается модульного программирования
Re[28]: Сферы применения
От: INTP_mihoshi Россия  
Дата: 04.09.04 11:08
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>Вы ушли от вопроса.

DG>На данный момент мне пофигу на блокировки, синхронизацию и т.д.
DG>Сейчас мне интересно видеть, как две независимых части программы получают меняющиеся данные.
DG>От Вас я услышал пока только одни общие слова "ФЯ — крутая парадигма, и там таких проблем нет", и не увидел ни одного конкретного примера.
DG>Создается ощущение, что Вы не понимаете о чем Вас спрашивают, а только повторяете заученные слова.

Ну, ФЯ — крутая парадигма, и там таких проблем нет

С отходом от функционального стиля в OCaml это делается так

let my_inc_thread r iv () = 
    for i=1 to 10 do 
        r := !r + iv; 
        Printf.printf "(%d)" !r; 
        flush stdout 
    done in

let x = ref 3 in (* Императивная переменная, меняющая значения *)
let t1 = Thread.create (my_inc_thread x 1) () in
let t2 = Thread.create (my_inc_thread x 100) () in
Thread.join t1;
Thread.join t2


Два треда инкрементят одну переменную.

В чисто функциональном стиле это тоже делается. Даже более изящно. Как всегда, через монады. Т.е. в треде есть функция, которая принимает аргументом старое состояние, ждет сигнала, на основе его и старого состояние делает новое и вызывает (или не вызывает) саму себя уже с новым состоянием. Если интересно — могу набросать код. А лучше почитай O'Reillyвскую книжку — там все это есть.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.