Здравствуйте, AVC, Вы писали:
AVC>Очень интересно, как можно опечататься с ":=", так чтобы компилятор этого не заметил?
Аналогично что и сказал ПК.
var
a:boolean;
b:boolean;
begin
if (a:=b)then
.....
end;
С уважением, Gleb.
Re[16]: Лекция Вирта в политехническом - впечатления
Здравствуйте, GlebZ, Вы писали:
AVC>>Очень интересно, как можно опечататься с ":=", так чтобы компилятор этого не заметил? GZ>Аналогично что и сказал ПК.
GZ>var
GZ>a:boolean;
GZ>b:boolean;
GZ>begin
GZ> if (a:=b)then
GZ>.....
GZ>end;
Не аналогично, однако. В Паскале операция присваивания возвращает void.
В Сях же она возвращает ссылку на приёмник — это и бонус, и грабли одновременно.
Перекуём баги на фичи!
Re[17]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Кодт, Вы писали:
К>Не аналогично, однако. В Паскале операция присваивания возвращает void. К>В Сях же она возвращает ссылку на приёмник — это и бонус, и грабли одновременно.
Oops
С уважением, Gleb.
Re[17]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Кодт, Вы писали:
AVC>>>Очень интересно, как можно опечататься с ":=", так чтобы компилятор этого не заметил? GZ>>Аналогично что и сказал ПК. К>
GZ>>var
GZ>>a:boolean;
GZ>>b:boolean;
GZ>>begin
GZ>> if (a:=b)then
GZ>>.....
GZ>>end;
К>
К>Не аналогично, однако. В Паскале операция присваивания возвращает void. К>В Сях же она возвращает ссылку на приёмник — это и бонус, и грабли одновременно.
ИМХО, если есть "грабли", "бонус" кажется уже не таким притягательным.
(Конечно, точки зрения могут быть разные.)
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Хоар
Re[17]: Лекция Вирта в политехническом - впечатления
К>Не аналогично, однако. В Паскале операция присваивания возвращает void.
Если я правильно помню грамматику Паскаля, там, вообще, присваивание не является expression, а является statement — т.е. о возвращаемом значении вообще говорить вообще бессмысленно, так же как о возвращаемом значении for или while (в Паскале — в некоторых других языках это вполне может иметь смысл). Внутри if, естественно, statement быть не может, только expression...
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, eao197, Вы писали:
E>Я что-то пропустил?
typedef float a[ 3 ];
Переменную-массив из 3 элементов Вы создать конечно сможете, о чем я и говорил. Но вот типа нового тут не создается, вот смотрите:
#include"stdafx.h"typedef int Vector2D[2];
typedef int Vector3D[3];
void f2D(Vector2D v)
{
for(int i = 0; i < 2; i++) v[i] = i;
}
void f3D(Vector3D v)
{
for(int i = 0; i < 3; i++) v[i] = i;
}
int _tmain()
{
int v2d[2];
int v3d[3];
f2D(v3d);
f3D(v2d);
return 0;
}
этот код прекрасно компилируется, но во время выполнения случается непонятная ошибка, связанная с порчей памяти ведь я случайно перепутал v2d и v3d: f2D(v3d); f3D(v2d); а для компилятора это не заметно, ведь typedef — не создает нового типа.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Переменную-массив из 3 элементов Вы создать конечно сможете, о чем я и говорил. Но вот типа нового тут не создается, СГ> вот смотрите: СГ>
СГ>#include"stdafx.h"
СГ>typedef int Vector2D[2];
СГ>typedef int Vector3D[3];
СГ>void f2D(Vector2D v)
СГ>{
СГ> for(int i = 0; i < 2; i++) v[i] = i;
СГ>}
СГ>void f3D(Vector3D v)
СГ>{
СГ> for(int i = 0; i < 3; i++) v[i] = i;
СГ>}
СГ>int _tmain()
СГ>{
СГ> int v2d[2];
СГ> int v3d[3];
СГ> f2D(v3d);
СГ> f3D(v2d);
СГ> return 0;
СГ>}
СГ>
СГ>этот код прекрасно компилируется, но во время выполнения случается непонятная ошибка, связанная с порчей памяти ведь я случайно перепутал v2d и v3d: f2D(v3d); f3D(v2d); а для компилятора это не заметно, ведь typedef — не создает нового типа.
Не знание языка не освобождает от ответственности
Тебя кстати, не смутило, что в f2D и f3D вектора передаются не по значению (как это было бы, если бы Vector?D был не агрегатом, а, скажем, классом), а по ссылке? Точнее говоря, декларация функции f( int p[3] ) в C++ эквивалентна f( int * p ).
На самом деле Vector2D действительно вводит тип, и чтобы в этом убедится нужно всего лишь изменить декларации f?D функций:
void f2D(Vector2D & v)
{
for(int i = 0; i < 2; i++) v[i] = i;
}
void f3D(Vector3D & v)
{
for(int i = 0; i < 3; i++) v[i] = i;
}
Попробуй теперь свой пример скомпилировать.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Так гораздо лучше — теперь хоть тот бред не компилируется.
А теперь наивный такой вопросик: А как же передать переменную типа Vector3D не по ссылке, а по значению, т.е. так как можно передать обычную переменную value-типа?
Кстати, можно продолжить языковое соревнование. Как на счет такого кода:
TYPE
A = ARRAY 3 OF BYTE;
B = ARRAY 3 OF BYTE;
PROCEDURE fa(u: A);
BEGIN
END fa;
PROCEDURE fb(u: B);
BEGIN
END fb;
PROCEDURE Test;
VAR a: A; b: B;
BEGIN
fa(b); (* ERROR: incopatible assignment *)
fb(a); (* ERROR: incopatible assignment *)END Test;
typedef int A[3];
typedef int B[3];
void fa(A & v)
{
}
void fb(B & v)
{
}
int _tmain()
{
A a;
B b;
fa(b); /* компилятору по барабану */
fb(a); /* компилятору по барабану */return 0;
}
Здравствуйте, Сергей Губанов, Вы писали:
СГ>А теперь наивный такой вопросик: А как же передать переменную типа Vector3D не по ссылке, а по значению, т.е. так как можно передать обычную переменную value-типа?
Встречный наивный ответик: а нафига.
Массивы потому и называются массивами, что могут иметь очень большой размер.
Передача их по значению
— во-первых, требует размещения копии где-то в памяти (в каком хранилище? стек же не резиновый)
— во-вторых, медленная
Разумеется, всегда можно изыскать способ выполнить глубокое копирование — начиная с простейшего заворачивания в структуру (boost::array, например) и кончая умными указателями-на-массивы (std::vector).
Но тут уже программист сам себе злобный буратино.
Обработка массивов не является задачей первостепенной важности ни в Обероне, ни в С++ — поэтому большая часть инструментария выносится в библиотеки (которые можно тюнинговать как хочется).
А вот для языков, принципиально заточенных под массивы и списки (ФЯ) — работа с ними как со значениями (включая стратегии владения и копирования) на уровне языка всячески приветствуется.
Исключение составляют строки — многие языки поддерживают работу с ними как со значениями. Во-первых, это часто встречающаяся задача, а во-вторых, можно надеяться на разумную длину строк.
Но опять же, степень поддержки языком варьируется:
— примитивные операции (конкатенация там...)
— форматирование и подстановка
— регулярные выражения
Почему конкатенация в паскале есть, а регекспов нет, хотя в перле регекспы встроены в язык? Потому что цели у языков разные.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Кстати, можно продолжить языковое соревнование. Как на счет такого кода:
C++ хорош тем что если в нем чегото нету то очень часто это можно сделать довольно легко
Описываем вот такой шаблон
class ArrayDefaultTag{};
template<class T, int N, class Tag = ArrayDefaultTag>
struct Array
{
T& operator[](int i)
{
return arr[i];
}
T const& operator[](int i)const
{
return arr[i];
}
int Length()const
{
return N;
}
private:
T arr[N];
};
Теперь если написать так то все компилируется
typedef Array<int, 3> A;
typedef Array<int, 3> B;
void fa(A & v)
{
}
void fb(B & v)
{
}
int main()
{
A a;
B b;
fa(b);
fb(a);
}
А если нам надо чтобы не компилировалось пишем так
class ArrayATag{};
class ArrayBTag{};
typedef Array<int, 3, ArrayATag> A;
typedef Array<int, 3, ArrayBTag> B;
Теперь A и B разные типы.
Кстати этот массив вполне себе копируется как значение
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Сергей Губанов, Вы писали:
СГ>>Переменную-массив из 3 элементов Вы создать конечно сможете, о чем я и говорил. Но вот типа нового тут не создается,
E>Не знание языка не освобождает от ответственности E>Тебя кстати, не смутило, что в f2D и f3D вектора передаются не по значению (как это было бы, если бы Vector?D был не агрегатом, а, скажем, классом), а по ссылке? Точнее говоря, декларация функции f( int p[3] ) в C++ эквивалентна f( int * p ).
E>На самом деле Vector2D действительно вводит тип, и чтобы в этом убедится нужно всего лишь изменить декларации f?D функций:
Формально г-н Губанов прав, typedef действительно не вводит новый тип, лишь определяет синоним для существующего:
Стандарт 7.3.1/1
... A typedefname is thus a synonym for another type. A typedefname does not introduce a new type the way a class declaration (9.1) or enum declaration does...
Но я не случайно сделал оговорку "определяет синоним для существующего". Тип для массива есть, просто получиь к нему доступ мы можем лишь через определение для него синонима с помощью typedef.
А теперь коммент для г-на Губанова.
Несмотря на всё вышесказанное, ваш пример в корне не правилен. Он ни как не демонстрирует тот факт, что typedef не определяет новый тип. Вы продемонстрировали лишь то, что массивы одной размерности неявно преобразуются друг в друга и в указатели... Если вы хотели продемонстрировать, что typedef не вводит новый тип, вы должны были привести такой пример:
typedef int Vector2D[2];
void fun(Vector2D var)
{
}
int main()
{
Vector2D var1;
int var2[2];
func(var1);
func(var2);
return 0;
}
Так что не лезли бы вы туда, в чём разбираетесь не достаточно хорошо...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Mr. None, Вы писали:
СГ>>>Переменную-массив из 3 элементов Вы создать конечно сможете, о чем я и говорил. Но вот типа нового тут не создается,
E>>Не знание языка не освобождает от ответственности E>>Тебя кстати, не смутило, что в f2D и f3D вектора передаются не по значению (как это было бы, если бы Vector?D был не агрегатом, а, скажем, классом), а по ссылке? Точнее говоря, декларация функции f( int p[3] ) в C++ эквивалентна f( int * p ).
E>>На самом деле Vector2D действительно вводит тип, и чтобы в этом убедится нужно всего лишь изменить декларации f?D функций:
MN>Формально г-н Губанов прав, typedef действительно не вводит новый тип, лишь определяет синоним для существующего: MN>
MN>Стандарт 7.3.1/1
MN>... A typedefname is thus a synonym for another type. A typedefname does not introduce a new type the way a class declaration (9.1) or enum declaration does...
MN>Но я не случайно сделал оговорку "определяет синоним для существующего". Тип для массива есть, просто получиь к нему доступ мы можем лишь через определение для него синонима с помощью typedef.
Именно это я и имел в виду.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Mr. None,
> Тип для массива есть, просто получиь к нему доступ мы можем лишь через определение для него синонима с помощью typedef.
Не вполне понял, что здесь говорится... Все конструкции, где используется имя типа массива, введенное с помощью typedef, можно заменить на эквивалентные без использования оного.
> Вы продемонстрировали лишь то, что массивы одной размерности неявно преобразуются друг в друга и в указатели...
Не (с)только это. В примере Сергея иллюстрируется специальное правило C++, сводящееся к тому, что объявления вида f(T[N]) преобразуется в f(T*).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[12]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Mr. None,
>> Тип для массива есть, просто получиь к нему доступ мы можем лишь через определение для него синонима с помощью typedef.
ПК>Не вполне понял, что здесь говорится... Все конструкции, где используется имя типа массива, введенное с помощью typedef, можно заменить на эквивалентные без использования оного.
Примерно это я и хотел сказать . Думаю Сергей меня понял .
[offtop_mode = on]
Практика показывает: обладая большими знаниями по предмету перестаёшь понимать простейшее объяснение основанное на аналогиях и схожести объектов. Так, например, когда моя жена (прочитав в моей диссертации фразу) попросила меня обяъяснить, что такое фрактальная или дробная размерность я очень долго думал, как бы это сделать по проще и додумался. Вот если взять противокомаринную сетку, которой окна затянуты — она вроде бы 2-ух мерная, но с другой стороны настолько дырявая, что как бы и 2-ух мерной её назвать сложно... Но с другой стороны она точно не 1-но мерная... поэтому про неё можно сказать, что она обладает некой дробной размерностью, значение которой лежит между 1 и 2... Когда же в шутку я рассказал это объяснение своему НР, он меня чуть с г@%#ом не съел!
[offtop_mode = off]
>> Вы продемонстрировали лишь то, что массивы одной размерности неявно преобразуются друг в друга и в указатели...
ПК>Не (с)только это. В примере Сергея иллюстрируется специальное правило C++, сводящееся к тому, что объявления вида f(T[N]) преобразуется в f(T*).
Вы правы... Я не столько хотел объяснить что демонстрирует пример Сергея, сколько хотел объяснить, что он не демонстирует того, чего Сергей хотел продемонстрировать — эквивалентность типа и синонима получаемого с помощью typedef`а .
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[9]: Лекция Вирта в политехническом - впечатления
Здравствуйте, mormat, Вы писали:
C>>А на чем еще писать ОСы?
M>http://bluebottle.ethz.ch/
M>Ведет проект один человек.
Кстати, Гуткнехт собирается Zonnon на нее перенести (потом). А то под .Net активные абъекты Zonnon-а уж очень не эффективно реализуются, под BlueBottle же всё "летать" будет.
Re[13]: Лекция Вирта в политехническом - впечатления