История изменений
Исправление MOPKOBKA, (текущая версия) :
В Racket cons не базовый тип. Макросы на синтаксических объектах.
Жаль, конечно можно не использовать структурные типы, но попытка писать идиоматичный код видимо приведет к тому что будут разные функции для разных групп типов.
Это проблема многих высокоуровневых языков, например в Java я столкнулся с невозможностью адекватно написать коллекцию, потому что там невозможно написать общий код для Integer и int, и генерики принимают только объекты, а они занимают слишком много памяти по сравнению с примитивами. (А еще там индекс менее 32 бита, что не позволяет создавать массивы byte более 4гб, ну это отдельная тема)
В этом плане С намного более единообразен (а ассемблер на фон-неймановской архитектуре достигает вершины, там не только данные представлены в виде char[], но и код).
И этому есть много реальных применений, вот два интересных:
- В некоторых мультиплеерных играх, сервер хранит предыдущее отправленное игрокам состояние, и текущее вычисленное, когда его нужно отправить, он запускает функцию:
Которая отправляет клиенту данные вида [(offset, byte[]), ...], и клиент этими данными просто патчит свою память кодом вида:
void write_diff(int socket, const void *old_state, const void *new_state);
for (auto chunk : server.read()) memcpy(&my_state[chunk.offset], chunk.data, chunk.data.size());
- Консервативный сборщик мусора, такой как Boehm GC, сканирует память приложения, и ищет указатели, если указатель на память найден, то она считается используемой. Используется за пределами С, например в Guile.
Common Lisp родня Forth’у: пишем программу в REPL, тестируем тут же, проектируем после того, как что-то выросло. Racket родня скорее Java: начинать писать приходится с декомпозиции на модули и описание типов/контрактов.
При низкоуровневой работе, первым делом рекомендуется написать эмулятор устройства, что бы можно было тестировать свой код (мокинг). Работа в образе никогда не отмечается и является побочным эффектом организации Forth-системы. Заплаточное программирование считается вредным. Чарльз Мур против документации в коде, и вообще комментариев.
С другой стороны нету контрактов, в функциях предназначенных для программиста традиционно ноль проверок, что приводит к большой гибкости, но не стоит ее путать с намеренным замыслом, как в случае с словами которые возвращают переменное количество значений.
Я не думаю что способы отладки или ее избегание являются определяющими, я все еще считаю что отладчик в DrRacket удобнее, в CL он неудобен для операций которые мне нужны, а что то переопределять на ходу я никогда не буду, потому что после перезапуска все может оказаться иначе.
Исправление MOPKOBKA, :
В Racket cons не базовый тип. Макросы на синтаксических объектах.
Жаль, конечно можно не использовать структурные типы, но попытка писать идиоматичный код видимо приведет к тому что будут разные функции для разных групп типов.
Это проблема многих высокоуровневых языков, например в Java я столкнулся с невозможностью адекватно написать коллекцию, потому что там невозможно написать общий код для Integer и int, и генерики принимают только объекты, а они занимают слишком много памяти по сравнению с примитивами.
В этом плане С намного более единообразен (а ассемблер на фон-неймановской архитектуре достигает вершины, там не только данные представлены в виде char[], но и код).
И этому есть много реальных применений, вот два интересных:
- В некоторых мультиплеерных играх, сервер хранит предыдущее отправленное игрокам состояние, и текущее вычисленное, когда его нужно отправить, он запускает функцию:
Которая отправляет клиенту данные вида [(offset, byte[]), ...], и клиент этими данными просто патчит свою память кодом вида:
void write_diff(int socket, const void *old_state, const void *new_state);
for (auto chunk : server.read()) memcpy(&my_state[chunk.offset], chunk.data, chunk.data.size());
- Консервативный сборщик мусора, такой как Boehm GC, сканирует память приложения, и ищет указатели, если указатель на память найден, то она считается используемой. Используется за пределами С, например в Guile.
Common Lisp родня Forth’у: пишем программу в REPL, тестируем тут же, проектируем после того, как что-то выросло. Racket родня скорее Java: начинать писать приходится с декомпозиции на модули и описание типов/контрактов.
При низкоуровневой работе, первым делом рекомендуется написать эмулятор устройства, что бы можно было тестировать свой код (мокинг). Работа в образе никогда не отмечается и является побочным эффектом организации Forth-системы. Заплаточное программирование считается вредным. Чарльз Мур против документации в коде, и вообще комментариев.
С другой стороны нету контрактов, в функциях предназначенных для программиста традиционно ноль проверок, что приводит к большой гибкости, но не стоит ее путать с намеренным замыслом, как в случае с словами которые возвращают переменное количество значений.
Я не думаю что способы отладки или ее избегание являются определяющими, я все еще считаю что отладчик в DrRacket удобнее, в CL он неудобен для операций которые мне нужны, а что то переопределять на ходу я никогда не буду, потому что после перезапуска все может оказаться иначе.
Исправление MOPKOBKA, :
В Racket cons не базовый тип. Макросы на синтаксических объектах.
Жаль, конечно можно не использовать структурные типы, но попытка писать идеоматичный код видимо приведет к тому что будут разные функции для разных групп типов.
Это проблема многих высокоуровневых языков, например в Java я столкнулся с невозможностью адекватно написать коллекцию, потому что там невозможно написать общий код для Integer и int, и генерики принимают только объекты, а они занимают слишком много памяти по сравнению с примитивами.
В этом плане С намного более единообразен (а ассемблер на фон-неймановской архитектуре достигает вершины, там не только данные представлены в виде char[], но и код).
И этому есть много реальных применений, вот два интересных:
- В некоторых мультиплеерных играх, сервер хранит предыдущее отправленное игрокам состояние, и текущее вычисленное, когда его нужно отправить, он запускает функцию:
Которая отправляет клиенту данные вида [(offset, byte[]), ...], и клиент этими данными просто патчит свою память кодом вида:
void write_diff(int socket, const void *old_state, const void *new_state);
for (auto chunk : server.read()) memcpy(&my_state[chunk.offset], chunk.data, chunk.data.size());
- Консервативный сборщик мусора, такой как Boehm GC, сканирует память приложения, и ищет указатели, если указатель на память найден, то она считается используемой. Используется за пределами С, например в Guile.
Common Lisp родня Forth’у: пишем программу в REPL, тестируем тут же, проектируем после того, как что-то выросло. Racket родня скорее Java: начинать писать приходится с декомпозиции на модули и описание типов/контрактов.
При низкоуровневой работе, первым делом рекомендуется написать эмулятор устройства, что бы можно было тестировать свой код (мокинг). Работа в образе никогда не отмечается и является побочным эффектом организации Forth-системы. Заплаточное программирование считается вредным. Чарльз Мур против документации в коде, и вообще комментариев.
С другой стороны нету контрактов, в функциях предназначенных для программиста традиционно ноль проверок, что приводит к большой гибкости, но не стоит ее путать с намеренным замыслом, как в случае с словами которые возвращают переменное количество значений.
Я не думаю что способы отладки или ее избегание являются определяющими, я все еще считаю что отладчик в DrRacket удобнее, в CL он неудобен для операций которые мне нужны, а что то переопределять на ходу я никогда не буду, потому что после перезапуска все может оказаться иначе.
Исходная версия MOPKOBKA, :
В Racket cons не базовый тип. Макросы на синтаксических объектах.
Жаль, конечно можно не использовать структурные типы, но попытка писать идеоматичный код видимо приведет к тому что будут разные функции для разных групп типов.
Это проблема многих высокоуровневых языков, например в Java я столкнулся с невозможностью адекватно написать коллекцию, потому что там невозможно написать общий код для Integer и int, и генерики принимают только объекты, а они занимают слишком много памяти по сравнению с примитивами.
В этом плане С намного более единообразен (а ассемблер на фон-неймановской архитектуре достигает вершины, там не только данные представлены в виде char[], но и код).
И этому есть много реальных применений, вот два интересных:
- В некоторых мультиплеерных играх, сервер хранит предыдущее отправленное игрокам состояние, и текущее вычисленное, когда его нужно отправить, он запускает функцию:
Которая отправляет клиенту данные вида [(offset, byte[]), ...], и клиент этими данными просто патчит свою память кодом вида:
void write_diff(int socket, const void *old_state, const void *new_state);
for (auto chunk : server.read()) memcpy(&my_state[chunk.offset], chunk.data, chunk.data.size());
- Консервативный сборщик мусора, такой как Boehm GC, сканирует память приложения, и ищет указатели, если указатель на память найден, то она считается используемой. Используется за пределами С, например в Guile.
Common Lisp родня Forth’у: пишем программу в REPL, тестируем тут же, проектируем после того, как что-то выросло. Racket родня скорее Java: начинать писать приходится с декомпозиции на модули и описание типов/контрактов.
При низкоуровневой работе, первым делом рекомендуется написать эмулятор устройства, что бы можно было тестировать свой код (мокинг). Работа в образе никогда не отмечается и является побочным эффектом организации Forth-системы. Заплаточное программирование считается вредным. Чарльз Мур против документации в коде, и вообще комментариев.
С другой стороны нету контрактов, в функциях предназначенных для программиста традиционно ноль проверок, что приводит к большой гибкости, но не стоит ее путать с намеренным замыслом, как в случае с словами которые возвращают переменное количество значений.