Здравствуйте, FDSC, Вы писали:
FDS>>>Остался вопрос, как написать aBlock так, что бы blockResult получил значение
EB>>
EB>>aBlock := [123].
EB>>
EB>>Т.е. просто без выхода из метода.
FDS>Это я догадался. А если бы мне нужно было написать настоящую функцию?
Это и есть настоящая функция. Значением блока (т.е. объектом, который возвращается после выполнения метода "value") является результат последней операции в блоке.
startingMethod
|aBlock blockResult val1 val2| "прописываем локальные переменные aBlock, blockResult, val1 и val2"
aBlock := [val1 + val2]. "1.1. присваиваем переменной aBlock объект класса блок со значением [val1 + val2]"
val1 := 1. "1.2. присваиваем переменной val1 значение 1"
val2 := 2. "1.3. присваиваем переменной val2 значение 2"
blockResult := self methodThatWorksWithBlock: aBlock. "1.4. вызываем у самого себя метод
methodThatWorksWithBlock: с параметром aBlock
и записываем результат в переменную blockResult"
blockResult printSomewhere. "1.5. каким-то образов выводим значение переменной blockResult"
methodThatWorksWithBlock: aBlock
|blockResult| "приписываем локальную переменную blockResult"
blockResult := aBlock value. "2.1. выполняем блок aBlock и записываем результат в blockResult"
^blockResult "2.2. Возвращаем blockResult"
Порядок выполнения и значения переменных: 1.1. val1 = nil; val2 = nil; aBlock до выполнения операции — nil, после выполнения операции — блок [val1 + val2].
1.2. val1 = 1
1.3. val2 = 2
1.4. вызываем метод "methodThatWorksWithBlock:" с параметром aBlock.
2.1. вызываем метод "value" у объекта aBlock
1.1. исполняем блок. val1 = 1; val2 = 2; aBlock = блок [val1 + val2]; значение блока после выполнения = 3
2.1. присваиваем переменной blockResult значение 3
2.2. выходим из метода, возвращая значение 3
1.4. присваиваем переменной blockResult значение 3
1.5.
Разумеется, в блоке может быть сколько угодно операций (разделяемых стандартно — точкой), кроме того в нём можно определять локальные переменные блока (тоже стандартно — перечислив в начале блока их имена и заключив их между символами "|"), а также изменять значения переменных контекста — как локальные так и любые другие.
Здравствуйте, Sinclair, Вы писали:
ГВ>>Есть. Ты забываешь про лес и выделяешь деревья. Win2K очень много дельного говорит (как и камрад Kolhoz). Не знаю, зачем это ему нужно. Может быть, его тоже достал "майнстрим" со своими амбициями? Я вот ничего оскорбительного в его словах не вижу S>а ты сходи постинги его почитай. Квалификация у чувака есть, но от так тщательно маскирует ее за ведрами помоев, что трудно разглядеть.
Почему я никакой маскировки не заметил? Что я сделал не так?
S>И уж успешность его в жизни — не знаю, личной там или профессиональной, — вызывает обоснованные сомнения.
В контексте программистского форума мне его личная жизнь совсем не интересна. И твои (а также Влада и остальных) догадки о ней — тем паче.
S>Влад верно заметил — те, кто чувствует себя комфортно и достиг успеха, не бегают на форумы собеседников в умственной отсталости обвинять.
Уф-ф-ф... Тяжела она, форумная жизнь. Не успели с личной жизнью оппонента разобраться, так ещё и его целеполагание определять надо. Не позавидуешь!
<< Под музыку: Rammstein — Fever Frei! >>
<< При помощи Януса: 1.2.0 alpha rev. 650 >>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Eugene Beschastnov, Вы писали:
VD>>>В функциональных языках return то не приветствуется, а тут вольный выход из любой точки выражения. По-моему, то чистой воды грабли. EB>>Ну блин %-). А ТЫ как относишься к exception-ам? WH>А как исключения относятся к выходу черт знает куда?
Ну, во-первых, не чёрт знает куда, а в контекст, находящийся в стеке непосредственно перед контекстом, в котором был определён блок. А во-вторых "вольный выход из любой точки выражения" — это несколько о другом (даже если закрыть глаза, что это устверждение неверно, и выход может быть отнюдь не из любой точки выражения
).
WH>Да и что получится если блоки кода сложить в коллекцию, потом выдти из функции где были созданны эти блоки, и после этого повызывать эти блоки?
Предположу, что бросится какой-то exception, но всё равно интересно
worksWithCollectionOfBlocks: aCollection
aCollection do: "3.1. метод do: осуществляет обход по коллекции и для каждого элемента выполняет блок,
передаваемый в качестве параметра"
[ :aBlock | "здесь мы описываем, что блок требует один параметр,
в качестве которого поочерёдно будут переданы все элементы коллекции"
aBlock value "3.2. выполняем каждый блок, лежащий в коллекции"
]
Исполняем
SomeClass startingMethod
Порядок исполнения: 1.1 — вызываем
2.1
2.2
2.3
2.4
2.5
1.1 — присваиваем
1.2
3.1
3.2 (aBlock = [^val1])
2.3
возникает exception "BlockCannotReturn: Block cannot return"
Как и ожидалось
Здравствуйте, Eugene Beschastnov, Вы писали:
VD>>>>В функциональных языках return то не приветствуется, а тут вольный выход из любой точки выражения. По-моему, то чистой воды грабли. EB>>>Ну блин %-). А ТЫ как относишься к exception-ам? WH>>А как исключения относятся к выходу черт знает куда? EB>Ну, во-первых, не чёрт знает куда, а в контекст, находящийся в стеке непосредственно перед контекстом, в котором был определён блок. А во-вторых "вольный выход из любой точки выражения" — это несколько о другом (даже если закрыть глаза, что это устверждение неверно, и выход может быть отнюдь не из любой точки выражения
).
Забыл добавить — и, собственно, unchecked exception-ы в плане "вольного выхода из любой точки выражения" значительно более "опасны" — они могут возникнуть в любом месте, а отнюдь не только в value*-методах.
T>Да фактически каждый новичок отмечает эту особенность синтаксиса смоллтока. Просто некоторые привыкают и не замечают некоторых неудобств (кажущихся?), а некоторым это кажется неуклюжим и они не могут это принять и привыкнуть. T>Что-то в этом духе.
Как уже говорили вопрос привычки. "новички" обычно уже знают другой язык. Чтобы сделать чистый экперемент нужны настоящие новички без знаний языков програмирования. Насколько я знаю школьники легко осваивают смаллток.
Здравствуйте, FDSC, Вы писали:
VD>>Я думаю дело не в алгоритмах, а в том как человек видит эти алгоритмы. В общем-то, да, любой алгоритм написанный императивно можно перенести в ФЯ. И для этого можно применитиь некие формальные правила. Но вот не будеш же ты каждый раз в голове делать преобразования? Тебе нужно думать. Причем думать по другому. Вот это и есть ломка сознания.
FDS>Если честно, то я всегда считал своим успехом то, что мои мысли стали относительно слабо зависить от языка программирования. И код стал лучше после этого. Что ж там за ломка то такая? Может эти языки, действительно, лучше на помойку выбросить, если там такая ломка
Ломка на уровне повыше чем использование языка программрования (конструирования по макконеллу), притом стадия конструирования тоже меняется целиком. Влад прав надо попробовать, непередаваемые очущения
Здравствуйте, VladD2, Вы писали:
ANS>> и на ST там всё написано кроме ВМ и виндовых контролов.
VD>Спай четко показывает, что все окна написаны на MFC или еще чем-то там (давно дело было). То есть сама среда написана на С++ или с нехилым его применением.
То что там окна MFC'шные не обязательно значит что среда написана на C++. Как пример есть биндинг MFC на питон, и на питоне можно писать используя MFC. И даже есть IDE написаное на питоне используя MFC — PythonWin.
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, FDSC, Вы писали:
FDS>>Здравствуйте, minorlogic, Вы писали:
M>>>Известно , что счет удобнее вести в 12 рмчной системе исчесления , но пользуемся мы 10 ричной ..
FDS>>Это откуда это известно. Мне вот говорили, что лучшая система исчисления — с основанием с числом e , так и не знаю почему
M>Были такие исследования, источник не помню. но вкратце таблица умножения намного проще.
M>12 делится без остатка на 2 , 3, 4, 6, в отличие от 10 который делится на 2 и 5. Помните как легко делить на 2 и на 5 различные числа в 10 ричной системе .
Самая удобная для устного счета (притом сама древняя из известных) Шумерская, если сводить к нашим понятиям получается что используется 60-ричная система
Здравствуйте, Eugene Beschastnov, Вы писали:
EB> возникает exception "BlockCannotReturn: Block cannot return"
Кстати, замечу, что этот exception бросается, только если именно нельзя вернуться. При этом контекст, где был определён блок, не теряется и, если в блоке нет оператора "^", то он замечательно и корректно выполняется.
Здравствуйте, Sinclair, Вы писали:
ANS>>Вместо пугающей "крышечки" я написал слово "return". Так вот, "возврат" выполняется не в контексте блока, а в контексте где блок определён. S>Ой! Ужасть, как интересно. Чего-то я здесь не понимаю. S>Вопрос №1: что еще "интересного", т.е. контекстно-специфичного, можно сделать, помимо return? Ну там: break, continue, goto?
В Smalltalk нет break, continue и goto . А отвечая на вопрос — насколько я знаю Smalltalk, больше ничего такого нельзя сделать. Ну, за исключением прямых операций с контекстом и стеком исполнения, которые хотя и возможны (доступ до контекста есть, контекст — это тоже объект, следовательно с ним тоже можно что-то поделать), но вот они точно являются грязным хаком и никогда не используются.
ANS>> То есть выполнение команды "return" из анонимной функции в C#, или метода анонимного класса в Java возвращают управление в код, вызвавший эту функцию. А в ST происходит возврат из того метода, где был блок определён. S>Вопрос №2: а как это работает вместе с присвоением блока кода в переменную с последующей ее передачей за пределы контекста. S>Подробнее: допустим, у нас есть переменная absent. Мы в нее присвоили значение в контексте одного метода. А вызвали в рамках совсем другого. Куда вернется управление? http://www.rsdn.ru/Forum/Message.aspx?mid=2094926&only=1
ANS>>Отсутсвие этой фичи делает невозможным реализацию аналога at:ifAbsent: в Java и C#. S>Угу, причем не вполне ясно, нужен ли этот аналог.
Нужен или нет — вопрос спорный, но в Java мне этой возможности иногда не хватает.
VD>Еще раз. Это не лябда! Это эдакий вариант континюэшона, а еще точнее замена дальнего goto. За такое в приличных программистских конторах по пальцем железной линейкой были во времена С. Код может получиться столь не предсказуемым, что его отладка и изучение может стать пыткой.
Ну не получается . Ни у меня, ни у кого другого, использующего Smalltalk (замечу — именно использующего). Что мы не так делаем?
Здравствуйте, FR, Вы писали:
FR>Как уже говорили вопрос привычки. "новички" обычно уже знают другой язык. Чтобы сделать чистый экперемент нужны настоящие новички без знаний языков програмирования. Насколько я знаю школьники легко осваивают смаллток.
FR>Самая удобная для устного счета (притом сама древняя из известных) Шумерская, если сводить к нашим понятиям получается что используется 60-ричная система
Здравствуйте, VladD2, Вы писали:
VD>Пугает вот этот исходный пример. Управление из середины выражения уходит по непредсказуемому пути. Это конечно может оказаться очень удобным при кодировании в некоторых случаях, но это будет создавать головную боль у любого кто изучает этот код.
Блин, реально не пойму о каком непредсказуемом пути идёт реч. Если в блоке есть нелокальный возврат, то выход проискодит из места определения блока. То есть код работает так же как и код, который ты привёл. Это указано в спецификации метода. Если тебя пугает то, что метод делает не то, что должен делать, то не стоит пользоваться ни одним ЯП вообще.
Здравствуйте, Курилка, Вы писали:
К>К примеру, что будет если блок вернуть из метода? А в блоке будет возврат из этого метода (который уже завершился)?
Здравствуйте, VladD2, Вы писали:
VD>В функциональных языках return то не приветствуется, а тут вольный выход из любой точки выражения. По-моему, то чистой воды грабли.
В ST которые реализовывали для JVM и .Net ВМ нелокальный возврат реализовывали через механизм исключений. То есть, этот код эквивалентен созданию своего уникального класса исключения, определению блока try..catch, который ловит это уникальное исключение _перед_ вызовом метода с блоком, и бросанию этого исключения при активации блока. Плюс ошибка при попытке бросить исключение, если управление уже вышло из нашего уникального try..catch.
Здравствуйте, Eugene Beschastnov, Вы писали:
EB> Ну, за исключением прямых операций с контекстом и стеком исполнения, которые хотя и возможны (доступ до контекста есть, контекст — это тоже объект, следовательно с ним тоже можно что-то поделать), но вот они точно являются грязным хаком и никогда не используются.
Так прям и никогда. В Seaside first-class continuation реализованы путём манипуляции цепочкой контекстов активации, в VW — исключения (хотя может и есть какие-то ускорения в ВМ, не знаю, проверить не могу).
S>>Вопрос №2: а как это работает вместе с присвоением блока кода в переменную с последующей ее передачей за пределы контекста.
можно делать нелокальный возврат, можно просто вернуть значение. Блок с нелокальным возвратом бросает исключение если контекст выполнения уже уничтожен (управление вышло из него назад). С блоком, возвращающим значение, и так всё понятно.
Здравствуйте, Sinclair, Вы писали:
S>Во-вторых, мне не нравится сам подход. Это что же, я буду изобретать по методу на каждую мыслимую транзакцию??? Имхо, лучше дать пользователю возможность явно обозначать границы:
Эти коллекции специально введены для того, чтобы не использовать синхронизацию. Я так понимаю, в C# такого не предвидится по синтаксическим причинам?
ANS>>Короче — проперти и индексеры — сакс S>О да. Удивляюсь, как еще джава решилась применить встроенные value-типы. А то ведь можно же было обойтись одними классами.
это бага, которую они специфицировали и она стала фичей
S>>>2. Джава sux: а если в словаре хранятся значения примитивного типа, то мы что будем возвращать? А что делать, если мы хотим намеренно сохранить null? ANS>>В джава нельзя положить в словарь примитивный тип, так что со вторым пунктом всё впорядке S>Точнее, это третий пункт: джава suxx, потому что в ее коллекции нельзя положить примитивный тип. Кстати, теперь вроде можно. Или генерики в джаве так и не заработали?
При чем тут дженерики? Если нужно, использую (авто)боксинг. А в .Net value в коллекции без боксинга ложатся?
S>А, ну вот это уже интереснее, хотя скорее всего читаться будет хуже, чем то же самое в виде try/catch.
Ну я пример кода привёл. Он действительно выглядит хуже чем с try/catch, но, как я указал, он неэквивалентен этому способу а лучше его (хотя бы потому, что исключение KeyNotFound может выбросить какаято внутренняя часть мапы, и эта ошибка будет замаскирована).