LINUX.ORG.RU

Не понимаю, что такое замыкание (closure)

 ,


5

6

Если почитать SICP, то замыкания - это такое свойство функции, что, например, «мы говорим, что операция объединения данных обладает замыканием в том случае, если результаты объединения этой операции могут объединяться этой же операцией». Поэтому я думал, что суть примера с языком описания изображений в том, что это круто, когда наши процедуры обладают этим свойством - из несложных операций с изображениями мы можем получать сложные, потому что операция над изображением - это изображение.

Но если прочитать вики, то «Замыкание (англ. closure) в программировании — функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции и не в качестве её параметров (а в окружающем коде).» Ну и что? Получается просто, что процедура использует глобальные переменные, ничего примечательного тут вроде и нет.

Так что такое замыкание? Помогите разобраться.

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

Это же неэквивалентный код. Оригинал тут намного лучше.

Он эквивалентный. С той поправкой, что оригинал хуже — откуда обобщённый код знает про какого-то user, user-name (может я хочу не по name в таблицу пушить а по user-id?) и зачем он разбивает целое на этот user-name и хвост user-data? Пусть общаются через структуру, то есть

(defun receive-users-from-etc-passwd (user-receiver)
  ...
            (funcall user-receiver (make-user login uid gid name home shell)...
                                   ;; ^ это

(defun synchronize-from-etc-passwd-to-hash-db (key)
  (synchronize ...
               ;; было:
               (lambda (user-name &rest user-data)
                 (let ((new-user (make-user)))
                   (mapc (lambda (slot value) (setf (slot-value new-user slot) value))
                         '(login uid gid name home shell)
                         (cons user-name user-data))
                   (setf (gethash user-name *db*) new-user)))))
               ;; стало:
               #'(lambda (user) (setf (gethash (funcall key user) *db*) user)...

Это проще, короче, можно выбрать любой key, эффективнее — структура всё равно формируется, поэтому лучше сделать это сразу и просто передавать через funcall одну ссылку на неё вместо передачи 100500 ссылок на разные составляющие да ещё и через apply (который медленнее funcall).

А вот это:

syn f g h = f $ g <*> h

или

syn f g h = f $ flip g =<< h

в случае монады (a -> _) это

syn f g h = f (\x -> g x (h x))

то есть эквивалентно

(defun syn (f g h)
  (funcall f (lambda (x) (funcall g x (funcall h x)))))

некий фильтр g смотрит на x и решает передавать его действию h или нет. То как это решается тоже отдано клиентскому коду, это позволяет написать вещь вроде

synBinary path = syn (fromBinary path) (flip const) evaluate

чего не получится с unless. Для эквивалентности по части unless (unlessM — не макрос но ленивая функция, так что всё ок):

syn' f g h = syn f (unlessM . g) h
--         = f $ unlessM . g <*> h

то есть

(defun syn (f g h)
  (funcall f (lambda (x) (unless (funcall g x) (funcall h x)))))

(хотя тут уже макрос) и тогда

synBinaryListToHT key path ht = syn' (fromBinaryList path)
  (\x -> isJust <$> HT.lookup ht (key x)) (\x -> HT.insert ht (key x) x)

будет без unlessM.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Он эквивалентный.

Конечно же нет. Можно скзаать что делает функция

syn f g h = f $ g <*> h

?

Нельзя.

А вот в исходном коде семантика совершенно понятна.

и зачем он разбивает целое на этот user-name и хвост user-data? Пусть общаются через структуру, то есть

Ну это, конечно, понятно, что аналог исходного кода в хаскеле будет в 10 раз длиннее, в 10 раз менее понятен и с зигохистморфическими препроморфизмами, а потому приходится велосипедить структуру, но вот не надо выдавать это за плюс :)

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

некий фильтр g смотрит на x и решает передавать его действию h или нет. То как это решается тоже отдано клиентскому коду, это позволяет написать вещь вроде

Это ничего не выводится из вашего кода. Классический пример, когда абстракция выходит за пределы домена и код становится абстрактным бесполезным говном.

Вот напишите код так, чтобы было понятно - да, g - это фильтр, который смотрит на х, решает как что передавать и т.п.

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

А чтобы сделать решение более гибким придется написать еще и собственный тайпкласс (ApplicativeFunctor f) => MyYobaApplicative f a

И, конечно, все эти f, g и прочие однобуковки надо заменить на нормальные названия:

syn receiveUsers userExists userAddNew = receiveUsers $ userExists <*> userAddNew

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

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

Зависит. Одну ту же сущность можно рассматривать под разными углами.

От того как мы рассмавтриваем эту сущность ее «сущность» не зависит. Это субъективный фактор, потому его нельзя учитывать.

gobject- это ООП. winapi - это ООП. Уровень vfs/vnode в линухе - это ООП.

Конечно же, нет. Повторяю - в сишке нету ООП и нельзя никак сделать ООП. Нету там классов. Не по названию нету, а по сущности - нету в сишке объектов, которые можно было бы считать классами.

Это то, как люди ДУМАЮТ о нем.

То есть субъективный фактор.

И из этого вытекает то, как они могут это применять.

Нет.

Есть такое слово ПАРАДИГМА, вот оно как раз об этом.

Нет, не об этом.

Сишка - не ООЯ. Но в нем возможно ООП.

Нет, не возможно. Потому что классов нет.

Если в каком-то языке нет концепции АБВГД, может оказаться, что можно его закрутить так, чтобы программировать в стиле АБВГД.

Ну да, в стиле ООП программировать можно, но ООП в сишке нет, это я и сказал. Потому что классов нет. Были бы классы (или если бы можно было сделать классы) в сишке было бы ООП.

В нашем же случае процедуры _есть_ их _можно сделать_.

Есть предложение забыть про перфокарты, ибо они вообще не язык, а носитель.

Ну то, как машина работает с перфокартами, задает определенные свойства языка. В нашем случае - гарантирует наличие в языке процедур.

Более конкретные свойства, понятно, зависят от конкретной нотации перфокарт.

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

да. достаточно индексируемой памяти

В рассматриваемом случае вообще только регистры есть и все.

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

<в сторону>эээ ссылку на рассматриваемый случай(модель)?

если есть «арифметика(достаточно строкой склейки(конкатенации)) на именах» регистров то это и есть индексируемая .

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

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

если нет ничего и только некоторый набор регистров(мест хранения) с уникальными именами без возможности менять имена в коде то машинка слабее/уже тьюринговой

Любая _реальная_ машина слабее/уже тьюринговой, т.к. у нее как раз и есть всегда «некоторый набор регистров».

Он просто предполагается достаточно широким для решения определенных задач.

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

в С нет ООП(которое(с этапа попадания в мэйнстрим- при прикручивании к «статически» типизированному(с протечками -для облегчения жизни программисту) языку(без тыканья пальцами) само было по себе компромиссом )) из коробки

однако выполнение следующих «правил жития» - достаточно:

1. всё держим в структурах. 2. каждая функция(по факту метод) в себе имеет свой профилькод(хэш от типов аргументов) который сравнивает с дополнительным аргументом хитрым сравнением на включение/пересичение) - если ок то вызов разрешимый , если нет - АХТУНГ. 3. у каждой структуры есть указатель на доступный по чтению памяти структуру"класс"(то имеем классовую объектность - если разрешенно в рантайме менять - то ближе к прототипной)- если ещё и указатель можно менять - вообщем веселье ручного заката с его плюсами и минусами. 3. у каждой структуры-класса активация нужной функции через сравнение тег структуры обьекта - здесь или в родителе и так далее.

А наследование зло.

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

мы же «бесконечной» не обладаем.

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

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

что мы называем ООП?

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

ну тогда и С с классами ( которое было препроцессором) тоже не ООП - печаль печаль.

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

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

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

Самое интересное в notes, там дополнения Ады.

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

Это субъективный фактор, потому его нельзя учитывать.

Льзя. Если мы говорим о технологиях, об инструментах. Если нам дали микроскоп, а мы умеем только забивать гвозди - мы будем только забивать гвозди (и это будет ПРАВИЛЬНО с нашей точки зрения). Нам надо рассматривать его как микроскоп - тогда мы сможем через него смотреть.

Не по названию нету, а по сущности - нету в сишке объектов, которые можно было бы считать классами.

Точно так же, как вы РАССМАТРИВАЕТЕ набор перфокарт как процедуру, можно РАССМАТРИВАТЬ структуру (плюс явно управляемый vtable) и набор функций как объект. И работать в рамках этой парадигмы. Что люди и делают. Это не делает С ООЯ. Это не делает первую версию фортрана процедурным языком - возможность взять несколько перфокарт и использовать в другом месте.

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

Льзя.

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

Точно так же, как вы РАССМАТРИВАЕТЕ набор перфокарт как процедуру, можно РАССМАТРИВАТЬ структуру (плюс явно управляемый vtable) и набор функций как объект.

Проблема в том, что набор перфокарт _является__ процедурой, по определению. А структура _не является_ объектом. По определению. Это объективные факторы, они не зависят от чьего бы то ни было мнения. А как там и кто что рассматривает - нам не важно.

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

И как же ты собираешься его учитывать, если для каждого человека он свой собственный?

Очень просто. Люди общаются. И если Вася забивал гвозди микроскопом, а Петя вдруг понял, что там можно смотреть букашек - Петя может поделиться с Васей этой информацией. И тогда Вася получит возможность смотреть букашек. Даже если он не будет этой возможностью пользоваться. Но это знание у него уже есть. Парадигма эта ему уже знакома.

По определению

Определения опять же у каждого свои;) Важно, можно ли использовать НЕЧТО, как объект или как процедуру.

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

Это объективные факторы

Слыш, тупило, ты хоть определение слова «факторы» прочитай.

anonymous
()

Если почитать SICP, то там, ЕМНИП, четко и ясно написано, что в основном этот термин в отношении ЯП имеет иное значение. В SICP же это скорее алгебраический термин, который обозначает замкнутость множества относительно операции.

cdshines ★★★★★
()
Последнее исправление: cdshines (всего исправлений: 1)
Ответ на: комментарий от qulinxao

Это не мои определения, это общепринятые.

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

Очень просто. Люди общаются. И если Вася забивал гвозди микроскопом, а Петя вдруг понял, что там можно смотреть букашек - Петя может поделиться с Васей этой информацией. И тогда Вася получит возможность смотреть букашек. Даже если он не будет этой возможностью пользоваться. Но это знание у него уже есть. Парадигма эта ему уже знакома.

Еще раз, для Пети эта сущность является X, для Васи - не является, как же определить является или нет?

Определения опять же у каждого свои;)

Да нет есть общепринятые.

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

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

ну чё вперёд с такими определениями.

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

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

как же определить является или нет?

В этом вопросе нет объективного «является». Во-первых, потому что определения бывают разными. Во-вторых, мы говорим о моделях, которые существуют только в сознании. «Объективно является» всего лишь означает, что большинство людей согласились с неким определением. Плутон для одних планета, для других - не планета. И пока не договорились об определении - правы обе стороны. И даже когда придумали определение - могут быть те, кто с ним не согласны. Если для меня сущность «структура с явным vtable» позволит жить в достаточно (для меня) полноценной ОО модели в С - я буду считать возможным ООП в С.

svu ★★★★★
()
Последнее исправление: svu (всего исправлений: 1)
Ответ на: комментарий от anonymous

потому приходится велосипедить структуру, но вот не надо выдавать это за плюс :)

Так у свизарда всё равно была структура и использовалась она не лучшим образом — где лишний код (в synchronize-from-etc-passwd-to-hash-db) и лишний (в данном случае) apply я показал.

Вообще, в обобщённом коде который не знает как будут общаться поставщики и приниматели может иметь смысл делать либо (thing), либо (&rest things). В первом случае между функциями будет летать просто один object — кому нужен атомарный объект сделает на него funcall и получит атомарный объект, кому нужен lambda-list — сделает funcall на список и поднимет себе нужный lambda-list явно одной строчкой с destructuring-bind, values-list — multiple-value-call и multiple-value-bind. Во втором случае ценой apply везде будут неявно подниматься lambda-list и летать списки (как бы в хаскеле тоже ничего не мешает летать кортежам и спискам и матчить их паттерн-матчингом, разве что :keys не получится сделать).

аналог исходного кода в хаскеле будет в 10 раз длиннее, в 10 раз менее понятен

Вот только он вышел короче (и про passwd в первом приближении тоже короче пишется — тупо по lines и split из ленивого IO). Что касается непонятности кем-либо кто не знает языка, я извиняюсь, — мне это не интересно :)

И, конечно, все эти f, g и прочие однобуковки надо заменить на нормальные названия

Нормальных названий нет, потому что никаких user тут нет. Просто так получилось, что этот syn (и никакой не syn вовсе) часть более общего (аппликативного) паттерна. То есть эта дуля на пять строк принимает какие-то функции и как-то их вызывает, вся конструкция не имеет отношения к задаче, суть просто f $ \x -> g x (h x) — не писать же, например, compose для каждого «домена»? Это всё понятно. И f $ \x -> g x (h x) это f $ g <*> h в случае (->) r. Непонятно? Ну и ладно.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от anonymous

Нет, не возможно. Потому что классов нет.

Во-первых, в ООП не обязательно наличие классов. Обязательным является наличие объектов. Классы - это один из способов описывать поведения множества объектов и не более того.

Во-вторых, в Си тебе никто не мешает сделать классы. Причем так, как тебе удобно. Можешь, например, завести их как сущности первого класса. А можешь сделать как в С++. Или вообще как-нибудь по-своему(скажем, сделать методы частным случаев мультиметодов). Ты зря столько внимания уделяешь макросам. Они же просто средство для добавления синтаксического сахара(в данном случае).

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

про passwd

Вот, по возможности более обфусцировано — с сигнатурами, (<|>) для IO, (<*>) и (>>=) для функций и point-free местами:

catching :: IO a -> (SomeException -> IO a) -> IO a
catching = catch

instance Alternative IO where
  empty = error "empty IO" -- throwIO (EmptyIO :: EmptyIO)
  a <|> b = catching a (const b)

unlessM :: Monad m => m Bool -> m () -> m ()
unlessM p a = p >>= (`unless` a)

synA :: Applicative f => (f b -> t) -> f (a -> b) -> f a -> t
synA from guar to = from $ guar <*> to

synM :: Monad m => ((a -> m ()) -> t) -> (a -> m Bool) -> (a -> m ()) -> t
synM from guar = synA from (unlessM . guar)

-- Binary [?] -> ?

fromBinaryList :: Binary e => FilePath -> (e -> IO a) -> IO ()
fromBinaryList path f = mapM_ f =<< decodeFile path

-- ? -> HashTable ?

synToHT :: (Eq k, Hashable k, HashTable h) =>
  ((v -> IO ()) -> t) -> (v -> k) -> IOHashTable h k v -> t
synToHT f key ht = synM f (fmap isJust . HT.lookup ht . key) $ HT.insert ht =<< key

-- User

data User = User
  { _login :: !ByteString, _uid :: !Word, _gid :: !Word
  , _name :: !ByteString, _home :: !ByteString, _shell :: !ByteString
  } deriving ( Show, Eq, Generic )

-- Binary [User]

instance Binary User where

-- HashTable User

type MyHT = BasicHashTable ByteString User

-- Binary [User] -> HashTable User

synBinaryUsersToHT :: FilePath -> MyHT -> IO ()
synBinaryUsersToHT = (`synToHT` _name) . fromBinaryList

-- Passwd -> ? User

fromPasswd :: (User -> IO a) -> IO ()
fromPasswd f = (mapM_ (f . readUser) . BS8.lines =<< BS.readFile "/etc/passwd")
               <|> error "while reading /etc/passwd" where
  readUser bs = case BS8.split ':' bs of
    [login, _, uid, gid, name, home, shell] ->
      User login (read $ BS8.unpack uid) (read $ BS8.unpack gid) name home shell
      -- read :: Read a => ByteString -> a ?

-- Passwd -> HashTable User

synPasswdToHT :: MyHT -> IO ()
synPasswdToHT = synToHT fromPasswd _name

test :: IO ()
test = do
  
  let root = User "root" 0 0 "root" "/root" "sh"
      user = User "user" 1 1 "user" "/user" "sh"

  encodeFile "/tmp/test" [root, user]
  ht <- HT.new
  synBinaryUsersToHT "/tmp/test" ht
  root' <- HT.lookup ht "root"
  user' <- HT.lookup ht "user"
  assert (isJust root' && isJust user' && root == fromJust root' && user == fromJust user') $! return ()

  ht <- HT.new
  synPasswdToHT ht
  mapM_ print =<< HT.toList ht
quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Вот только он вышел короче

Где? Аналога исходного кода на хаскеле ты не предоставил :)

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

Что касается непонятности кем-либо кто не знает языка

При чем тут незнание языка? Ты просто используешь зачем-то в коде кучу сущностей, которые оттуда можно смело убрать. А код с меньшим количеством сущностей определенно проще.

Нормальных названий нет, потому что никаких user тут нет.

Да нет, они там есть. Такая семнатика у задачи.

Просто так получилось, что этот syn (и никакой не syn вовсе) часть более общего (аппликативного) паттерна.

Нет, нету там никакого более общего паттерна.

То есть эта дуля на пять строк принимает какие-то функции и как-то их вызывает,

То есть _ничего_ не делает. А нам надо, чтобы она делала вполне конкретную вещь - обходила определенную коллекцию записей _определенного вида_, и делала что-то с теми записями, у которых определенное поле удовлетворяло некоторому предикату.

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

суть просто f $ \x -> g x (h x) — не писать же, например, compose для каждого «домена»?

Что значит, не писать? КОНЕЧНО, писать. И все, кто пишет качественный код, их тоже пишут. Иначе никак. Вроде, это очевидные совершенно истины.

Это всё понятно. И f $ \x -> g x (h x) это f $ g <*> h в случае (->) r.

А какой смысл вместо f $ \x -> g x (h x) писать f $ g <*> h, если из второго все равно придется _в уме_ получать первое (сперва вспомнить приоритет операций, потом определить какой конкретный инстанс <*> требуется, узнать как он для требуемого случая определен, по пути еще посмотреть тип функции syn...) и потом с первым работать? Любишь выполнять лишнюю работу? я понимаю, если бы первый вариант был длиннее. Но он ведь такой же. Только задействует меньшее количество сущностей, быстрее в восприятии и написании, проще. А второй вариант - банальная обфускация.

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

unlessM :: Monad m => m Bool -> m () -> m ()

Протекающая абстракция. unless должно принимать обычный Bool, а не m Bool.

synA :: Applicative f => (f b -> t) -> f (a -> b) -> f a -> t
synM :: Monad m => ((a -> m ()) -> t) -> (a -> m Bool) -> (a -> m ()) -> t

Нарушение ТЗ. syn должна работать не на любом аппликативном функторе, а на _конкретном_ предназначенном для этой формы. Требуется реализовать новый тайпкласс (обертку для аппликатива) и инстанс для него. Ну и очевидная ошибка с unless, см. выше.

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

Как минимум, исправь это.

Напоминаю, что в результате, посмотрев на syn, я должен знать о семантике все то же самое, что я знаю о ее семантике, посмотрев на syncronize из оригинала.

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

anonymous
()

помедитируй над этим кодом

def addClosure(val1):
    def closure(val2):
        return val1 + val2
    return closure
 
class AddFunctor(object):
    def __init__(self,val1):
        self.val1 = val1
    def __call__(self,val2):
        return self.val1 + val2
 
cl = addClosure(2)
fn = AddFunctor(2)
 
print cl(1), fn(1)  # напечатает "3 3"

функция которую предварительно инициализируют аналог из ООП обьект с одним методом

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

Кстати, надо бы наверное сделать специальный обфускатор для хаскеля. Работать он будет так:

1. сперва пишем обычный, нормальный код.

2. автоматически заменяем все имена на бессмысленные f, g, x etc.

3. у нас получается некоторое дерево вызовов, проводим замену его поддеревьев по определенным rewriting rules, например дерево (f x) на f $ x, f (g x) на (f . g) x, то что сделал ты с f $ g <*> h и т.п., потом проводит «депоинтизацию», убирая где можно аргументы.

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

ЗЫ: обрати внимание на первый пункт - получить обфусцированный код можно только тогда, когда нормальный код _уже_ есть. Это к слову о любителях ненужной работы.

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

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

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

Оно может быть сколь угодно необъективным - как только мне предъявят доказательства осознания другими людьми ПП до 1950х. Мы говорим об исторических фактах, которые вполне объективны. Было или не было (зафиксировано).

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

Было или не было (зафиксировано).

Нут так объективен факт фиксации события, а ты споришь не о событии, а его трактовке.

вопрос в том был ли зафиксирован до 1850 года факт наличия идея использования перфокарт в качестве процедур или не был. Понятно, что это зависти от того, что именно мы понимаем под процедурой. Я под процедурой понимаю любой объект, удовлетворяющий впонле конкретному определению процедуры. А ты объект, который кто-то называет процедурой.

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

Давай по-другому - то, что императивное программирование появилось за век до декларативного (функционального) ты согласен?

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

Насчет императивного мне будет сложнее спорить - пожалуй, соглашусь. Императивщина у нас в мозгах прошита практически на аппаратном уровне.

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

Но следуя твоей логике, например, планет не было до тех пор, пока люди не придумали понятие «планета». А вселенной до появления у человека разума и вовсе не существовало.

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

алсо, в результате мы выяснили, что вопрос таки субъективен. Так что я еще раз спрошу - чего ж ты встрял и полез чегото доказывать, если считаешь, что он субъективен?

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

Планеты как объекты - сущности, естественным образом появившиеся во вселенной. Процедуры - сущности технологические, обязанные своим появлением человеческому сознанию. И зависящие от него.

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

Ну так императивное программирование под процедурным понимают в том числе.

Тут важен момент, что понимание операции, как процесса, меняющего стейт, у Ады как раз уже было: «by the word operation, we mean any process which alters the mutual relation of two or more things, be this relation of what kind it may. This is the most general definition, and would include all subjects in the universe.»

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

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

Процедуры - сущности технологические, обязанные своим появлением человеческому сознанию. И зависящие от него.

Ну это же не правда. Не путай понятие процедуры и объект, который называют этим понятием. Понятие, да, существует лишь в человеческом сознании (как и понятие планеты), а вот сам объект существует независимо от этого сознания (как и планеты).

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

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

даже если вдруг все в мире резко возьмут и забудут язык Х.

Я не говорю про конкретное сознание. Я говорю про какое-нибудь сознание. Чтобы процедура на языке Х появилась - нужно, чтобы хоть один человек знал про этот язык. Нужно хоть одно сознание. В отличие от планеты.

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

Чтобы процедура на языке Х появилась - нужно, чтобы хоть один человек знал про этот язык.

Зачем? Еще раз, я написал процедуру, потом все забыли Х (я в том числе), процедура что, ВНЕЗАПНО перестанет быть процедурой?

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