LINUX.ORG.RU

расширяемая система

 , ,


1

3

http://www.gnu.org/software/emacs/emacs-paper.html#SEC17

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

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



Последнее исправление: linearisation (всего исправлений: 3)

Что важнее: обсуждать языки программирования или использовать наиболее подходящие языки программирования для решения полезных задач?

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

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

linearisation
() автор топика

Ну не расширяемый так не расширяемый. Напишем на микросервисах.

Norgat ★★★★★
()

Столлман, как обычно, ведёт себя по-идиотски.

Imagine that function A binds the variable FOO, and calls the function B, which calls the function C, and C uses the value of FOO.

Imagine that the functions A and C are part of a user extension, while B is part of the standard system.

И как тогда B вызывает С, если она про неё ничего не знает?

А, так вы говорите, она узнаёт про C от A? А передать замыкание A, типа, не в состоянии?

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

Вы просто не поняли о чем он говорит. Не может быть никакого замыкания, потому что в его примере A и С являются частью расширения, а B — частью нативной системы. Нечего замыкать, нет никакого лексического контекста на момент реализации B

linearisation
() автор топика
Ответ на: комментарий от Miguel

И как тогда B вызывает С, если она про неё ничего не знает?

Тут то как раз все просто, например, она может быть подана явным аргументом

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

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

Ещё раз. A каким-то образом сообщает B, что надо вызвать C. В ЭТОТ момент всё уже определено.

Ну, грубо: A — какая-то функция, которая хочет отсортировать массив ARRAY, B — функция сортировки (библиотечная), C — функция сравнения элементов массива. C нужен дополнительный параметр FOO. Соотвественно, A содержит не вызов B(ARRAY, C), а вызов B(ARRAY, function(x,y) {return C(x,y,FOO)}). И всё.

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

Какой толк подавать замыкание, если код вызывающий это замыкание не получает доступа к этому замыканию?

Что значит «не получает доступа»? Он получает доступ: он его ВЫЗЫВАЕТ. Больше ему ничего не требуется.

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

Ему требуется, в данном случае, значение переменной FOO

Ему — то есть, B — не может требоваться значение переменной FOO. Потому что о переменной FOO это самое B тупо НЕ ЗНАЕТ.

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

В этом и проблема, что он должен знать, но узнать возможности нет, потому что оно должно быть (в норме) получено в рантайме.

linearisation
() автор топика
Ответ на: комментарий от Miguel

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

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

В кезе, который приведен по ссылке — должен.

По ссылке НЕТ вменяемого кода. Хотя бы псевдо.

Если ты вот про это:

(defun foo1 (x) (foo2))
(defun foo2 () (+ x 5))
то он НИКАК не относится к дальнейшим разлагольствованиям, что, дескать, нельзя всё передавать в параметрах. ЗДЕСЬ — можно и нужно:
(defun foo1 (x) (foo2 x))
(defun foo2 (x) (+ x 5))

Если ты сумеешь внятно описать случай с A, B и C, который замыканиями НЕ покрывается, то пиши.

Miguel ★★★★★
()

Тупняк, шизофрения, провокация флейма

system-root ★★★★★
()
Ответ на: комментарий от Miguel

Пока что я вижу у Столмана примерно следующее:

; библиотечный код
(defun B (c) (... (c) ...))
; пользовательский код
(defun C () (... FOO ...))
(defun A () ((defvar FOO ...) ... (B C) ...))

Который отлично переписывается вот так:

; пользовательский код
(defun C (FOO) (... FOO ...))
(defun A () ((defvar FOO ...) ... (B (lambda () (C FOO))) ...))

Без всякой динамики.

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

Пока что я вижу у Столмана примерно следующее:

Не то ты видишь. Вот адекватный пример

;синтаксис scheme, имея в виду что связывание динамическое
(define (B C) (... something with C ...)); native

(define (A key-code) (B))
(define (C) (something with key-code value))

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

Ну дык РОВНО ТО ЖЕ САМОЕ, что я написал:

(define (C key-code) (something with key-code value))
(define (A key-code) (B (lambda () (C key-code))))
Miguel ★★★★★
()
Ответ на: комментарий от Miguel

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

Считай что поправил:). У меня нет прав для правки:)

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

OK. Я написал тебе, как это нормально делается.

Miguel ★★★★★
()

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

Почему переписываются? :-) Они, в лучшем случае, дописываются, в худшем - рефакторятся :-) Потом компиляются и работают раз в 1000, а то и в 10000 (как минимум) быстрее, чем системы с динамическими биндингами - привет тормознутый Emacs Lisp, даже Python быстрее, чем Elisp :-) Поэтому и ввели костыль под названием «lexical-binding: t» в Elisp - привет «расширяемым системам с динамическим экстентом» :-) Гг :-)

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

Зато к реальности имеют отношения профессионально написанные программы, которые являются действительно полезными :-) И почти все эти программы написаны на «не расширяемых» языках типа джавы и цепепе :-) Сравни хотя бы Emacs и Clion :-) В Emacs даже поддержка Common Lisp в хваленом SLIME выглядит по гиковски :-) Бесконечные баги, которым нет конца :-) Про цепепе молчу вообще, там спустя десятилетия даже парсер нормальный т.н. «хакеры со всего мира» не сделали :-) А тут раз, и за пару лет написали IDE для нормальной работы с C++ :-) И написали на Java :-) Лол :-)

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

(B (lambda () (C key-code))))

Допустим B это

(define (B C) (set! something (C)))
эффект будет совершенно иной, в моем случае присваивание произойдет в месте исполнения кода, а в твоем — где-то в лексическом пространстве имен B.

linearisation
() автор топика

Про пользу динамического биндинга всё ясно, но реальная проблема в через чур интимной связи этих 3 функции (A B C). Или делаешь буилдер и контекст C зависит от контекста буилдера, или расширенные функции B,C работает с таблицей - проблема решена. В общем, не понимаю, нафиг нужен такой жуткий посредник B, а если он таки нужен, зачем тогда такая ярая связь между A,C? У кого нибудь есть реальный пример такой нужды? В статье описанные решается по проще.

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

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

Что за чушь? Во всех случаях присваивание произойдёт в один и тот же момент. Сразу после того, как C закончит исполняться.

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

То есть, что-то вроде

(defun A ()
  (defvar something)
  (B C)
  ...use "something" in some way...
)
Ты это имеешь в виду?

Это такой говнокод, что даже стыдно. Если Столлман такое пишет — он полный у-о. Потому что должно быть тогда так:

; library code
(defun B (c) ((c)))

;user code
(defun A ()
  (defvar something (B C))
  ...use "something" in some way...
)
Всё!

Miguel ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Начались новогодние школьные каникулы ;-).

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

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



(define (setA) (set 'a (+ a 1)))
(define (showA) (println a))
(define (target a) (showA) (setA) (showA))

(target 100)


;>>>> 100
;>>>> 101



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

Они, в лучшем случае, дописываются, в худшем - рефакторятся

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

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

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

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

Я окончательно перестал что-либо понимать.

Практически в любом языке есть подобные кунштюки. От C до Haskell. Ни одному из них не требуется dynamic binding.

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

А зачем использовать ту же функцию и для нового, и для старого функционала

Затем, что эта функция уже используется во многих местах.

linearisation
() автор топика
Ответ на: комментарий от Miguel

Вы имеете в виду на уровне синтаксических конструкций, сахара? Что значит есть? Если речь идет просто осахаре, предоставляемом средой исполнения, то это отношения к делу не имеет.

От C до Haskell. Ни одному из них не требуется dynamic binding

Кстати, статически компилируемые языки, в этом смысле, имеют еще одну проблему, помимо перечисленных. В них, насколько я знаю, даже исключения а-ля continuations, с нелокальным выходом и динамическим перехватом исключений не возможен. Это, правдf не относится к JIT-компиляции

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

относился к чему то такому

Так делать плохо. Потом в документации приходится вместо нормального API типа B (C : (function () : any)) : null дополнительно писать «читает переменные ..., изменяет переменные ..., бросает исключения ...». А уж тестирование такого комбайна — просто ужас.

Для

(define (B C) (set! something (C)))
something всегда берётся по месту определения B (и является частью его API, как errno в Си). Но так можно делать только если точно знаешь, что something всегда в системе ровно один. В Scheme принято делать что-то вроде
(define (B C setter) (setter (C)))
...
(define (A)
  (define something 1)
  (define something2 2)
  (B C (lambda (x) (set! something x))
  (B C2 (lambda (x) (set! something2 x))))
В этом случае мы по месту выполнения определяем, в какой контекст писать.

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

Затем, что эта функция уже используется во многих местах.

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

monk ★★★★★
()

http://www.gnu.org/software/emacs/emacs-paper.html#SEC17

Оспадетыбожемой!

«У нас всё всегда в одном скопе, поэтому это круто», — говорится по ссылке. Это ж ад. Никакого разделения, все могут править всё. Если у двух функций локальные переменные окажутся названы одинаково, программиста ждёт сюрприз.

i-rinat ★★★★★
()
Ответ на: комментарий от linearisation

В них, насколько я знаю, даже исключения а-ля continuations, с нелокальным выходом и динамическим перехватом исключений не возможен.

setjmp, longjmp, signal — всё работает.

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

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

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

Но если хочешь расширить её функционал, можешь создать и использовать другую функцию (которая уже внутри себя, если надо, использует старую), не так ли? Тогда и овцы целы, и волк сыт - старый код работает как и раньше, а новый код, где надо, использует новую функцию с дополнительными наворотами. Можешь дать реальный пример (не эту очень странную абстракцию с функциями A, B и C, как в статье), когда такое не прокатит?

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

Ну, для си работает, допустим, благодаря longjmp, но в общем случае то — нет, правильно? Не в каждом статически-компилируемом ЯП есть такие возможности?

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

Не в каждом статически-компилируемом ЯП есть такие возможности?

В каждом, который компилируется в бинарник и использует системные стек, а не делает свою виртуальную машину. То есть, для Си++, Паскаля, Фортрана, Ады всё работает.

И не в каждом динамическом. В Elisp нету, в Common Lisp нету, в Python нету. Динамические проще перечислить где есть: Scheme и Ruby.

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

Если речь идет просто осахаре, предоставляемом средой исполнения, то это отношения к делу не имеет.

У тебя полная каша в голове. Сахар предоставляется компилятором, а не средой исполнения.

статически компилируемые языки

Это ещё что?

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