Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Решить эту проблему можно многими способами, например, ввести уникальный маркер и вставлять новые команды после него. Маркер будет представлять собой невыполнимое условие, которое мы добавим после cond
(nil 'secret-marker)
Итак, начнем с функции, возвращающей лямда-функцию, которая представляет собой начальный код. Эта лямда-функция принимает, как единственный параметр, свой же исходный код и отдает в качестве результата также какой-то код…
(defun return-adder (n)
(lambda (x) (+ x n)))
(defun add3 (x)
(funcall (return-adder 3) x))
Хотя нет, при вызове ничего не экономится, компилятор же эту строчку все равно выбросит как заведомо невыполнимую.
Возвращает-то она, по сути, не лямбда-функцию, а s-выражение, являющееся лисп-кодом.
Соответственно, вы можете start-program вполне определить через defconstant или простым setf.
Все равно, ему как минимум придется рассмотреть многократно эту ситуацию во время выполнения программы, даже если фактически он не будет выполнять эту операцию. Ведь Лиспу совершенно неизвестно, что скормят ему в eval.
Quote там нужен, чтобы выводился именно код, а не что-то вроде #<FUNCTION (LAMBDA (X)) {100A741ECB}>
Так давайте попытаемся написать программу, которую проблематично будет создать на других языках.Я вам назову дюжину языков на которых это можно написать, кстати не только не «проблематично» а много проще, красивее и что главное удобочитаемо…
proc program {args} {
## save current :
set self [info body program]
## create each new code, evaluate it :
foreach code $args {
proc program {args} $code
program {*}$args
}
## restore self (if needed):
## proc program {args} $self
##TO_UNCOMMENT puts " !!!! it was a comment ..."
}
# draw code of program:
puts start------code-----[info body program]-----------\n
program {
#1st program: i=1, print somthing with i
set i 1
puts "Program No. $i\n"
} {
#2nd program: i=2, print somthing with i, modify self again - print current body, execute and modify again :
set i 2
puts "Now No. $i"
# expand previous self :
set code [string map {{##TO_UNCOMMENT } {}} [uplevel set self]]
append code {
puts " !!!! added code ..."
}
proc program {args} $code
puts ...------code-----[info body program]-----------\n
program {
#third program: i=3, print somthing with i
set i 3
puts "No. equal $i\n"
}
}
# draw last code of program:
puts \nend------code-----[info body program]-----------\n
start------code-----
## save current :
set self [info body program]
## create each new code, evaluate it :
foreach code $args {
proc program {args} $code
program {*}$args
}
## restore self (if needed):
## proc program {args} $self
##TO_UNCOMMENT puts " !!!! it was a comment ..."
-----------
Program No. 1
Now No. 2
...------code-----
## save current :
set self [info body program]
## create each new code, evaluate it :
foreach code $args {
proc program {args} $code
program {*}$args
}
## restore self (if needed):
## proc program {args} $self
puts " !!!! it was a comment ..."
puts " !!!! added code ..."
-----------
No. equal 3
!!!! it was a comment ...
!!!! added code ...
end------code-----
#third program: i=3, print somthing with i
set i 3
puts "No. equal $i\n"
-----------
save
, пользовательский ввод и загружая это через "source 1.txt
" получим тоже что и у вас.(я
(знаю
(что
(принято
(так)))))
Изменение кода программы во время ее выполнения на примере Common Lisp