LINUX.ORG.RU

KISS языки


1

1

Кроме ближайших родственников Оберона. С тривиальным синтаксисом, интуитивной и формально определенной семантикой. Есть такие?

PS Брейнфак не предлагать.

PPS Желающие предложить СИ отправляются учить стандарт в целом, и лютое количество таких выкрутасов в частности.

★★★★★
Ответ на: комментарий от tailgunner

> Если не хочешь неоправданных предположений оптимизатора - не исполльзуй оптимизацию.

как мне убедиться, что та хрень при -О0 действительно не использует «неоправданных предположений оптимизатора», которые ему разрешил использовать стандарт си в *любых* случаях?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> ты мне сможешь гарантировать, что та жцц-шная хрень при переполнении целых выдаст тот же результат, что очевидный код mov ... idiv ... sub ... ?

Нет. А должен? В свою очередь, ты можешь мне привести пример разных результатов кода gcc и твоего гипотетического?

а если не сможешь, то исполняет ли си роль кроссплатформенного ассемблера даже с -О0?

А сможешь определить понятие «кроссплатформенного ассемблера»? А то ты размахиваешь этой метафорой так, будто это не метафора, а определение.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Пока ты не предъявишь реальных претензий к коду, с моим здравым смыслом всё нормально.

Не-не, это *ты*, сказал, что можно опираться на здравый смысл и плюнуть на стандарт с его UB; ты и щас так же считаешь? Та простыня тебя не пугает?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> *ты*, сказал, что можно опираться на здравый смысл и плюнуть на стандарт с его UB; ты и щас так же считаешь?

Да.

Та простыня тебя не пугает?

Нет.

Впрочем, меня вообще не пугает ситуация с усечениями и переполнениями в Си. Причем совсем не пугает.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Нет. А должен? В свою очередь, ты можешь мне привести пример разных результатов кода gcc и твоего гипотетического?

да, должен ты, а не я, т.к. ты заявил о приорите здавого смысла с -О0 над стандартом.

А сможешь определить понятие «кроссплатформенного ассемблера»? А то ты размахиваешь этой метафорой так, будто это не метафора, а определение.

Тут я уже вспомню здравый смысл; точное определение требует обдумывания, вот версия:

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> ты заявил о приорите здавого смысла с -О0 над стандартом.

Ты не мог бы меня процитировать?

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

А поведение при переполнении ты считаешь «накладными расходами»?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Впрочем, меня вообще не пугает ситуация с усечениями и переполнениями в Си. Причем совсем не пугает.

я вполне возможно потестю эту фигню на совпадение с нормальным кодом, но даже и без этого полагаться на -О0 в таком коде — мягко говоря неблагоразумно.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Впрочем, меня вообще не пугает ситуация с усечениями и переполнениями в Си. Причем совсем не пугает.

1. в стандарте переполнение — это UB, причем про связь UB с оптимизацией ни слова

2. попытка сделать без оптимизации через -О0 наталкивается на оптимизацию (а как ты иначе назовешь замену команды idiv на какую-то последовательность команд?)

Получается типа «Он вас пока не убил? Не убил. А вот когда убьет, обращайтесь.»

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> А сможешь определить понятие «кроссплатформенного ассемблера»? А то ты размахиваешь этой метафорой так, будто это не метафора, а определение.

можно однозначно определить то, что НЕ является кроссплатформенным ассемблером:

это язык, который не предоставляет сравнительно простые и эффективные возможности, имеющиеся в подавляющем большинстве железа

например, сложение знаковых чисел по модулю 2**М делается почти везде эффективно и одной командой, и если его в языке нет, это не кроссплатформенный ассемблер

а вообще это хорошая тема подумать

предложи свое определение

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

>> ты заявил о приорите здавого смысла с -О0 над стандартом.

Ты не мог бы меня процитировать?

могу: http://www.linux.org.ru/jump-message.jsp?msgid=5163288&cid=5165615

Если тебе нужен ассемблер вместо оптимизирующего компилятора, используй -O0.

Подтвердить эти слова стандартом, я так понимаю, ты не собираешься?

Нет, конечно. Я и так чувствую себя Капитаном Очевидность.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Получается типа «Он вас пока не убил? Не убил. А вот когда убьет, обращайтесь.»

Он меня за 20 лет не убил.

Вообще, обсуждаемая проблема яйца выеденного не стоит. Настоящие проблемы Си совсем в другом.

сложение знаковых чисел по модулю 2**М делается почти везде эффективно и одной командой, и если его в языке нет, это не кроссплатформенный ассемблер

Ну что тут скажешь... сейчас, например, почти везде есть инструкция вроде compare-and-swap. Она тоже должна быть в языке? На многих процах есть MMU - это тоже тащим в язык?

предложи свое определение

Если бы я пытался дать такое определение, оно бы включало в себя возможность использовать сырую память, предсказуемое расположение структур в памяти, и манипуляцию битами. Но, в общем, мне пофиг. И арифметику по модулю хоть чего-нибудь я бы туда не включал - по-моему, она тупо бесполезна в переносимых программах (а при желании ее можно эмулировать).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Он меня за 20 лет не убил.

Видимо, ты 20 лет программировал в другой области.

Кстати, это подтверждает и то, что когда-то вполне очевидное битовое выражение ты назвал «ужоснах».

Вообще, обсуждаемая проблема яйца выеденного не стоит.

см. выше.

Настоящие проблемы Си совсем в другом.

так расскажи, очень интересно

Ну что тут скажешь... сейчас, например, почти везде есть инструкция вроде compare-and-swap. Она тоже должна быть в языке? На многих процах есть MMU - это тоже тащим в язык?

compare-and-swap очевидно да, да емнип она и есть де-факто в жцц

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

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

в си вроде до сих пор нет константы mystruct::&myfield ?

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

И арифметику по модулю хоть чего-нибудь я бы туда не включал - по-моему, она тупо бесполезна в переносимых программах (а при желании ее можно эмулировать).

отсюда поподробнее

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

(хотя для более правильного, и более модульного, чем обычно, компилятора это может быть и не так, но то особый случай; было бы хорошо запустить многие числовые оптимизации для оптимизации матриц)

www_linux_org_ru ★★★★★
()

может, форт? там извращений тоже накручено масса, но можно юзать ограниченное подмножество команд

amomymous ★★★
()
Ответ на: комментарий от tailgunner

> Вообще, обсуждаемая проблема яйца выеденного не стоит.

она может рассматриваться как небольшая, но в этой области все должно быть вылизано до блеска, в т.ч. и такое

кроме того, легко найти недостатки типа «а вот в си нет ...» (например, нет деструкторов), а вот недостатки типа «си делает неправильно» сложнее

и наконец, эта проблема очень похожа на проблемы с++ в миниатюре

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от amomymous

Мне вот интересно, кто из советующих тут форт написал на нем хоть одну не-хелло-ворлд программу?

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> Видимо, ты 20 лет программировал в другой области.

В основном системное программирование, для которого Си и создавался. А в какой области нужна арифметика над машинными словами с точно определенной семантикой переполнения?

Ну что тут скажешь... сейчас, например, почти везде есть инструкция вроде compare-and-swap. Она тоже должна быть в языке? На многих процах есть MMU - это тоже тащим в язык?

compare-and-swap очевидно да, да емнип она и есть де-факто в жцц

Где именно? А так, в gcc много полезного есть: __typeof__, ({}).

Настоящие проблемы Си совсем в другом.

так расскажи, очень интересно

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Нахрена замыкания и исключения в таком низкоуровневом языке? Как оно будет на каких-нибудь встраиваемых системах работать?

Love5an
()
Ответ на: комментарий от tailgunner

> А в какой области нужна арифметика над машинными словами с точно определенной семантикой переполнения?

я уклонюсь от доказательства, что оно дотягивает до «области», но пример с pi(x) я привел

основной пойнт в том, что в асме это легко, а в си это UB — и это не нормально

compare-and-swap очевидно да, да емнип она и есть де-факто в жцц

Где именно? А так, в gcc много полезного есть: __typeof__, ({}).

TYPE __sync_val_compare_and_swap (TYPE *ptr, TYPE oldval TYPE newval, ...)

__typeof__ вообще не проблема, т.к. времени компиляции, а ({}) на мой не очень просвещенный взгляд тоже никаких проблем не создает

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

это все правильно, но в стиле «этого нет»

сюда в стиле «этого нет» надо добавить: нет знаковых целых по модулю (со знанием оптимизатора о них), нет допустим оператора >> на байтах, (есть только на целых)

а вот в стиле «си делает неправильно» —

1. нафига оно продвигает незнаковые операнды до знакового инта?

2. и нафига оно вообще продвигает? (этот вопрос уже спорный, хотя случай 32 bit int && 32 bit char одновременно тоже интересен)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Love5an

> Нахрена замыкания и исключения в таком низкоуровневом языке? Как оно будет на каких-нибудь встраиваемых системах работать?

они оба не требуют сборки мусора, а замыкания так вообще в современом си активно юзаются в виде f(bla-bla-bla, void* data)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> А в какой области нужна арифметика над машинными словами с точно определенной семантикой переполнения?

я уклонюсь от доказательства, что оно дотягивает до «области», но пример с pi(x) я привел

Вычисление числа pi в целочисленной арифметике? Это не пример.

TYPE __sync_val_compare_and_swap (TYPE *ptr, TYPE oldval TYPE newval, ...)

ну блин, тогда можно сказать, что GCC и MMX поддерживает.

__typeof__ вообще не проблема

Я и не говорил, что это проблема.

а вот в стиле «си делает неправильно» --

Меня то, что есть в Си, вполне устраивает. Но в нем слишком мало есть.

нафига оно вообще продвигает?

Думаю, непродвижение потянуло бы за собой runtime-поддержку (избавление от UB с переполнениями - тоже).

tailgunner ★★★★★
()
Ответ на: комментарий от Love5an

> Нахрена замыкания и исключения в таком низкоуровневом языке?

Затем же, зачем и в Лиспе.

Как оно будет на каких-нибудь встраиваемых системах работать?

Так же, как Ада.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Вычисление числа pi в целочисленной арифметике? Это не пример.

это вовсе не число 3.14, а функция; и ты опустил самое главное — в любом асме поддержка есть — и мне пофиг, если с твоей точки зрения это не область и даже не пример; эта тему по-моему уже пошла по кругу

ну блин, тогда можно сказать, что GCC и MMX поддерживает

1. а умеет ли он их оптимизировать?

2. ММХ вообще-то не лежит в пересечении асмов

Думаю, непродвижение потянуло бы за собой runtime-поддержку (избавление от UB с переполнениями - тоже).

Несколько шаблонов асма для сдвига байтов (типа как деление на 15 заменяется на умножение на 0х88888889 и сдвиг) это максимум что потребуется?

Что же касается рантайм-поддержки исключений при переполнении — то это *надо*, т.к. в любом асме флаги переполнения есть — извольте предоставить к этому интерфейс.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Вычисление числа pi в целочисленной арифметике? Это не пример.

это вовсе не число 3.14, а функция;

Я сказал, что примером хоть какой-нибудь предметной области это не является.

2. ММХ вообще-то не лежит в пересечении асмов

Почти в любом современном асме есть свой аналог MMX.

Что же касается рантайм-поддержки исключений при переполнении — то это *надо*, т.к. в любом асме флаги переполнения есть — извольте предоставить к этому интерфейс.

Да неужели? И какой же флаг взводится при переполнении 16-бит целого на ia32?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Меня то, что есть в Си, вполне устраивает. Но в нем слишком мало есть.

Меня — почти устраивает, и насчет «слишком мало есть» тоже полное согласие, так что тут и обсуждать нечего.

Практический аспект этой дискуссии о целой арифметике — если транслировать свой код прямо в си, то не слишком он его попортит своими продвижениями? или все-таки в llvm/gimple? (да, еще есть как-бы «нетехнический» аспект, из-за которого у си преимущества)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Да неужели? И какой же флаг взводится при переполнении 16-бит целого на ia32?

я не утверждал, что надо ловить переполнения любых целых — а утверждал, что у каждого проца есть целый тип, где оно флагуется

З.Ы. а разве add ax,bx не выставит нужный флаг?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> а разве add ax,bx не выставит нужный флаг?

ХЗ, лень смотреть учебник. Кроме того, даже если он выставлен - что с ним делать?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Затем же, зачем и в Лиспе.
Не понял.
Лисп, ну CL, низкоуровневым языком, заточенным под системное программирование, не является.

Так же, как Ада.

Ада это, все-таки, редкость. Она только в определенных кругах более-менее широко используется(т.е. военные, и все такое), с определенным железом(точнее, оные определенные круги могут позволить себе разрабатывать железо с учетом определенного языка программирования).
А вот как на какую-нибудь сраную кофеварку воткнуть рантайм с исключениями и замыканиями?

Love5an
()
Ответ на: комментарий от Love5an

> Лисп, ну CL, низкоуровневым языком, заточенным под системное программирование, не является.

Эээ... и что? На Си тоже не только ядра пишут. Более того, одно время в GNU C были вполне полноценные вложенные функции (с доступом к параметрам объемлющей фугкции). Понятно, что full-blown замыканий без сборки мусора сделать нельзя, но даже ограниченные замыкания лучше, чем их отсуствие.

Ада это, все-таки, редкость.

Да не в этом дело... Ада доказала, что даже в реализации глубоко встроенных систем исключения полезны и применимы. В конце концов, можно сделать и для Си профили, как для Ады.

А вот как на какую-нибудь сраную кофеварку воткнуть рантайм с исключениями и замыканиями?

У современной кофеварки мозгов больше, чем у ракеты 30-летней давности, для которой придумали Аду с поддержкой исключений.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ХЗ, лень смотреть учебник.

как будто мне не лень вспоминать, кто это из OCS

оказалось О

Кроме того, даже если он выставлен - что с ним делать?

вообще не понял вопрос, юзать конечно!

например так:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char** argv)
{
    if(argc!=3) return 1;
    short arg1=atoi(argv[1]);
    short arg2=atoi(argv[2]);
    short sum=0, over;

    asm(
        "movw   $0,   %%bx ; "
        "movw   $1,   %%cx ; "
        "movw   %2,   %%ax ; "
        "addw   %3,   %%ax ; "
        "cmovOw %%cx, %%bx ; "
        "movw   %%ax, %0   ; "
        "movw   %%bx, %1   ; "

        : "=m"(sum), "=m"(over) : "m"(arg1), "m"(arg2) : "%ax", "%bx", "%cx"
    );

    printf("arg1=%d arg2=%d sum=%d over=%d\n", (int)arg1, (int)arg2, (int)sum, (int)over );
    return 0;
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Кроме того, даже если он выставлен - что с ним делать?

вообще не понял вопрос, юзать конечно!

Каким образом? Сигнал послать? Неприемлемо для ядер. Исключение? Их нет в Си. Взвести глобальный флаг? Бесполезно, никто проверять не будет.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

без исключений конечно хреново, но все равно можно было сделать конструкцию «кроссплатформенного ассемблера с оптимизатором», например

int x;
ensure {
  x=a-8+b-f(a)*g(b);
  for( i=0; i<n; i++ )
    x+=a%i;
}
on_overflow {
  /* тут можно писать свой код и даже дернуть longjmp */
}

on_overflow выполняется только если произошло переполнение в блоке ensure, при этом переполнения внутри f или g не рассматриваются — это лично дело этих функций, в частности они тоже могут дернуть longjmp

на ассемблере это просто несколько jo on_oveflow_001 после каждого сложения/вычитания

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

если f или g дернут longjmp, даже из-за overflow внутри них, то показанный в коде on_overflow верхнего уровня, очевидно, не выполнится — просто будет longjmp

дешево и сердито, в стиле си

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Понятно, что full-blown замыканий без сборки мусора сделать нельзя,

а это с чего вдруг?

да, в худшем случае куча потребуется, но куча != сборщик_мусора

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Love5an

> Замыкания требуют динамической памяти,

в худшем случае да

и, более того, GC.

обоснуй

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

обоснуй

Ну вот я сделаю сделаю себе вложенные списки на замыканиях:

-- foo <args> ≡ <term>
-- это сахар для
-- foo ≡ λ <args> . <term>

-- Ну а λ <args> . <term>
-- сахар для
-- λ <a1> . λ <a2> ... λ <an> . <term>

true a b  ≡ a
false a b ≡ b

pair a b  ≡ λ f . f a b
first x   ≡ x true
second x  ≡ x false

nil       ≡ pair true true
cons a b  ≡ pair false (pair a b)
head x    ≡ first (second x)
tail x    ≡ second (second x)

list x::List ≡ foldr cons nil x

tail (tail (list 1 2 3))
=> 3

И начну создавать их, вопрос - кто будет очищать мусор? Причём очищать нужно не только функциональные объекты (это просто то же что и обычный free), но и все копии окружений которые связываются с (каждым) замыканием - заставлять пользователя помимо обычной free (для вложенных структур) заниматься освобождением функциональных окружений (для них же)? - это мало кому нужно.

А если речь идёт о локальных окружениях на стеке, то они и в Си есть:

#include <stdio.h>

/* any & λ */

typedef void* any;

typedef any(*lambda1)(any);
typedef any(*lambda2)(any, any);
typedef any(*lambda1_2)(lambda2);
typedef any(*lambda4)(any, any, any, any);
typedef any(*lambda1_4)(lambda4);

/* simple local closure */

lambda2 foo (any c) {
  any true (any a, any b) { printf("in `true' c = %c\n", (int)c); return a; }
  printf("in `foo' true = %c\n", true((any)'t', (any)'f'));
  return &true;
}

/* try pairs with non-local closure */

lambda1_2 pair (any a, any b) {
  any lambda (lambda2 f) { return (f)(a, b); }
  return λ
}

any print_pair (any a, any b) {
  printf("(%i . %i)\n", (int)a, (int)b);
  return NULL;
}

/* try qua */

lambda1_4 qua (any a, any b, any c, any d) {
  any lambda (lambda4 f) { return (f)(a, b, c, d); }
  return λ
}

any print_qua (any a, any b, any c, any d) {
  printf("(%i . %i . %i . %i)\n", (int)a, (int)b, (int)c, (int)d);
  return NULL;
}

/* and then */

int main() {
  // not static scoping:
  any c = (int*)'m';
  // ok, local closures:
  lambda2 fun = foo((any)'c');
  // not dynamic scoping and is no full-closures:
  int result  = (int)(fun)((any)'t', (any)'f');
  printf("in `true' throu `main' true = %c\n", result);

  // try to make pair adt on lambdas/closures
  // but lost something in a closure:
  lambda1_2 pair_lambda = pair((any)17, (any)19);
  (pair_lambda)(&print_pair);

  // something saved because it saved on stack:
  lambda1_4 qua_lambda = qua((any)2, (any)3, (any)5, (any)7);
  (qua_lambda)(&print_qua);
  // ^ seg. fault ! but... its ok ;-)

  return 0;
}

/*
 * So, local closures works,
 * non-local closures make garbage and seg. faults.
 */

Такие вот замыкания - казалось бы их можно немного поправить, но это заставит перенести действия со стека в кучу и обязательно потребует хоть какого-то GC (хотя бы подсчёта ссылок).

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

кто-то там &\lambda; поменял, так что

s/return λ/return &\lambda;/g

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

> lambda1_4 qua_lambda = qua((any)2, (any)3, (any)5, (any)7);

афтор, пеши есчо!

(void*)2 это напрямую сегфолт, и локальность-нелокальность здесь пофиг

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

сегфолт, естественно, после того, как кто-то в конце-концов попытается это разыменовать чтобы использовать

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от quasimoto

> И начну создавать их, вопрос - кто будет очищать мусор?

твои конс-ы пока что можно очищать деструкторами с подсчетом ссылок, т.к. циклических структур у тебя нет (хотя тут можно и привести практический контрагрумент — даже удаление через подсчет ссылок может привести к неожиданным и заранее неизвестным затратам времени на удаление; но см. ниже)

Причём очищать нужно не только функциональные объекты (это просто то же что и обычный free), но и все копии окружений которые связываются с (каждым) замыканием - заставлять пользователя помимо обычной free (для вложенных структур) заниматься освобождением функциональных окружений (для них же)? - это мало кому нужно.

type-aware free вполне справится с этим, проблемы не вижу

_________________________________________

Я понял, что ты хотел сказать. Но практически, если нам нужны Алг.ТД, то *их* и надо использовать, а не криво эмулировать структурами, построенными на замыканиях.

Меня интересует практическое применение — т.е. «вот задача, тут подойдут замыкания, и обязательно сложные циклические структуры между ними, и без GC типа никак».

ООП через замыкания, АлгТД через замыкания — это все извращения.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

сегфолт, естественно, после того, как кто-то в конце-концов попытается это разыменовать чтобы использовать

А никто и не пытается их разыменовывать, даже если и начнут пытаться - будут предупреждения от компилятора (у меня в примере их нет и сегфолт не имеет отношения к void указателям).

с подсчетом ссылок

Ну так reference counting это и есть разновидность GC, причём неэффективная в отношении слежения за замыканиями.

Но практически, если нам нужны Алг.ТД, то *их* и надо использовать, а не криво эмулировать структурами, построенными на замыканиях.

Речь не об этом, а о том что как только у нас есть «полные» замыкания мы можем эмулировать с их помощью как cons-ячейки так и объекты с состоянием. Просто такое у них свойство у замыканий - и с этим надо считаться. Вот я и спрашиваю - как без GC следить за окружениями что создают замыкания?

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

> Ну так reference counting это и есть разновидность GC

тогда, извините, получается что в с++ есть GC

причём неэффективная в отношении слежения за замыканиями.

пока что это не продемонстрировано

Речь не об этом, а о том что как только у нас есть «полные» замыкания мы можем эмулировать с их помощью как cons-ячейки так и объекты с состоянием. Просто такое у них свойство у замыканий - и с этим надо считаться.

с баранами, возомнившими себя черчем и пытающимися натуральные числа кодировать замыканиями считаться не надо :-)

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

в «скриптописательском» профайле GC можно и разрешить (хотя я пока не вижу от тебя примера его необходимости)

GC не нужен, но поддержка его нужна, т.к. я пока что не могу представить алгоритм «как всегда обходиться без GC»

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от quasimoto

> Вот я и спрашиваю - как без GC следить за окружениями что создают замыкания?

1. копирование значений и счетчик ссылок (для строк, например, он идеален, т.к. строки сами не на что не ссылаются)

2. сложно устроенные счетчики ссылок (типа счетчика на замкнутый список в целом или на строку, откуда берутся подстроки)

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

4. неглубокое копирование объектов, до момента, пока «листья» окажутся простыми объектами, например строками

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

например, идея «имеем замыкание, которое возвращает пару из нового значения и замыкание, которое тоже возвращает пару из нового значения и замыкание, которое...» похоже извращенная

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от quasimoto

вообще, нормальное использование замыканий — это что-то типа фильтра на коллекцию; фильтр например может захватить пару строк (одна как минимальная, другая как максимальная), скопировать к себе целое число (пропускать каждый 5-ый), еще чего-то... но все это должно быть константным

а на константных захваченных значениях думаю можно обойтись без полноценного GC

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

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

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

korvin_ ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

тогда, извините, получается что в с++ есть GC

(библиотечно есть, а не в самом языке) если get the facts то:

0) Конечно это вид примитивного GC (http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29, но я думаю ты там был).

1) В GObject есть GC в виде подсчёта ссылок, но это не значит что в самом си есть GC.

2) В C++ как и в C можно сделать подсчёт ссылок буквально на коленке (одна известная книга про С++ заканчивается главой как раз об этом), но опять же это не значит что в самом C++ есть GC.

3) Вообще реализация подсчёта ссылок в виде библиотеки возможна в любом языке и может использоваться для автоматического управления в foreign memory (если для внутренней памяти уже есть свой GC).

4) Другое дело языки претендующие на какую-то низкоуровневый и при этом имеющее внутренний (а не библиотечный) GC - пример Objective-C в нём есть как замыкания (в виде блоков) так и сборка мусора (опционально, как я понял).

Меня интересует практическое применение — т.е. «вот задача, тут подойдут замыкания, и обязательно сложные циклические структуры между ними, и без GC типа никак».

Хм, спроси у тех кто пишет на языках с замыканиями (python, elisp, scheme, CL, haskell, etc.) - применения замыканий крайне разнообразны ;) И я не знаю где бы они были сделаны без сборки мусора.

ООП через замыкания, АлгТД через замыкания — это все извращения.

Добавь тогда ИМХО, и ещё к этой фразе:

с баранами, возомнившими себя черчем и пытающимися натуральные числа кодировать замыканиями считаться не надо :-)

Т.е. понятно что извращения при практическом программировании, но не с точки зрения изучения (откуда ты знаешь - может через некоторое время появятся методы верификации и оптимизации программ которые применимы в формализме какого-нибудь lambda calculus, но не применимы с точки зрения классического вычисления на state machine).

причём неэффективная в отношении слежения за замыканиями.

пока что это не продемонстрировано

Кем? Это я должен доказывать? А как же мировой опыт и Generational GC ;)

вообще, нормальное использование замыканий ...

Опять таки - как же мнения всех тех людей что используют замыкания в своих лиспах-хаскелях-и-питонах?

Короче, я не знаю ни одного языка в котором бы замыкания (с возможностью их возвращения из функции) были бы сделаны без GC, если ты знаешь - назови, я с удовольствием посмотрю. Ну или сам напиши proof-of-concept - можно для начала посмотреть как там в gcc реализованы локальные замыкания.

quasimoto ★★★★
()
Ответ на: комментарий от korvin_

использование http://en.wikipedia.org/wiki/Church_encoding вместо целых чисел, предоставляемых железом тоже «ничем не противоречит определению»; вот только я посмотрю, на сколько десятичных порядков программа начнет после этого тормозить (не меньше чем на 3, думаю)

«сложный» должен тут означать не «много полей и методов», а что-то другое — например, немутабельные объекты проще мутабельных, строки проще объектов, держащих внутря себя ссылки с подсчетом; но и это не вся история

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от quasimoto

>>> причём неэффективная в отношении слежения за замыканиями.

пока что это не продемонстрировано

Кем? Это я должен доказывать? А как же мировой опыт и Generational GC ;)

да, ты, так как ты сказал

Ну так reference counting это и есть разновидность GC, причём неэффективная в отношении слежения за замыканиями.

«мировой опыт» чего? мировой опыт практического языкостроения вообще — не имеет к этому вопросу отношения

лично о Гослинге — если бы умные люди типа Одерски и остальных не заставили его ввести в яву дженереки, ява бы говном и умерла

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.