Write a macro that, given a term of code, transforms all the calls to the function FOO in that term, and only those calls, into calls to function BAR with the same arguments. Language: Common Lisp or Scheme.
One of the very first lessons of the wizard book is that data is a type of abstract being that inhabits the computer (programs are another). Indeed programs are a kind of data which is executable by some other program. An executing program is called a process.
A Lisp program is a collection of Lisp objects, which are data. Sometimes a Lisp program is called "Lisp code".
The syntax (or structure) of a Lisp program is defined in terms of Lisp objects.
Text can be read by some program (possibly a Lisp program) which generates Lisp objects during the time it is reading that text. Conventionally, a program that reads text and generates Lisp objects is called a Lisp reader.
Lisp objects that are read in by a Lisp reader may also be Lisp programs.
One family of textual syntaxes Lisp readers usually understand are called "S-expressions". However there are others e.g. "M-expressions", "Sweet expressions" etc.
I hope this answers your questions.
Name:
Anonymous2014-07-17 9:23
>>16 As a lisp weenie, I never had to think of any of that abstract bullshit.
Name:
Anonymous2014-07-17 12:13
To lisp weenies, lisp is just a language with a hackable syntax.
You need to macroexpand, then replace, ignoring branches in which the variable becomes bound (via lambda or let). Where did all the good posters from 2005-2008 go? :(
Name:
Anonymous2014-07-17 19:41
>>24 sexper is fine for code walking. But what you want is a proof that *anus is never changed from its constant value, which entails much more than just code walking alone.
Name:
Anonymous2014-07-17 19:43
>>25 That is not a solution, because it not only replaces calls to FOO in the original term, but also in the expansions of other macros. E.g. if there exists the macro
(defmacro zoo (k) (foo k))
and our code term contains the s-exp
(zoo k)
then your erroneous solution will modify what (zoo k) will expand into, which is a malign side effect. Anything that is not a call to FOO must be untouched.
Name:
Anonymous2014-07-17 19:49
>>26 Alright, s-exps are unsuitable for even the simplest intelligent codewalking. Which is a necessary condition for writing useful code transforms.
Transforming untagged nodes and hoping that the result will be correct runnable code is like putting grenades in your barbecue and hoping that no one gets hurt.
>>34 I've given it some thought and I don't believe that a macro is the correct tool to "replace" all function calls of foo to bar. It's not even clear what that means, unless you talk about function pointers. Even though >>32's example can be modified to handle the FUNCALL case, there's more things one can come up with to screw with the macro:
; to demonstrate: (defun myfuncall ...) (myfuncall #'foo ...)
Therefore, if anything, the solution used by >>32 is just fine. What >>9 wrote is also fine, only that it has to be used on the macroexpanded AST. Seriously, >>1 trolled us all by posting an ill-imposed problem.
>>36 Perhaps the lisp reader must be modified for this problem to be solved. Or whatever mechanism is that looks for the function tag in a symbol. However, I think this solution can not be applied locally. All in all, if >>1 can restate the problem considering the objections raised thusfar, I'll solve it.
As it is, my program would not produce correct output on all fully macroexpanded expressions, because I am not handling all relevant special forms (do, let, tagbody etc.).
Of course, a program which does the requested replacement correctly for all of Common Lisp's 25 special operators as enumerated in section 3.1.2.1.2.1 of the Hyperspec could be written.
Interestingly, and enlighteningly, that program would be a new Lisp evaluator, and would define a new Lisp language.
Name:
Anonymous2014-07-18 10:45
>>36 I don't think your demonstrated case counts. It doesn't matter that, after transformation, the form calls a function that calls foo, just as long as foo isn't called directly.
Name:
Anonymous2014-07-18 10:51
>>39 and what does it mean for foo to be called directly? I think you haven't explained this one.
>>30 He is not correct. A call to macro zoo is not a call to function foo. The challenge is to transform just the direct calls to a function, without interfering with the inner workings of any functions or macros (it's called "information hiding"). Besides, once you can target exclusively the direct calls, it would be trivial to call macroexpand first and then to call our macro.
Name:
Anonymous2014-07-18 19:37
>>36 I can only hope that function calls are better defined in Scheme. Common Lisp, it seems, is totally unsuitable for writing code transforms.
Name:
Anonymous2014-07-18 19:46
Oops, sorry, Scheme has
((eval (string->symbol "foo")) arg1 arg2 ...)
Therefore, my challenge has no solutions in either CL or Scheme.
Not at all. I was just trying to find out if s-exp languages have any actual advantages for writing macros. Lispers talk much about how cool "code is data" is, and how much easier writing macros is with s-exps. Yet it seemed to me that most of their macros are generative, which the s-exps are not particularly advantageous for (it can be done in any "blub" language, just look at Nemerle or Rust or Metalua, for example). So I wondered if homoiconicity is good for transformative macros. And it turns out that you can't even write a reliable function-swapping macro with it. At least with the s-exp kind of homoiconicity.
If >>9 handled all special forms (and also replaced all calls to eval to itself) you'd get what you want.
Name:
Anonymous2014-07-18 23:20
>>44 It's arbitrary if you want the replacement to work on expanded inner macros or not. You can either call macro expand before doing the deep substitution or not call macro expand. I don't know what your use case is in using this macro, but if you want to preserve referential transparency the inner macros must be expanded first.
>>47 You can. But I wont. Do your own research you cock sucking faggot.
>>49 Macros take unevaluated lisp forms as input, which are s-expressions.
Name:
Anonymous2014-07-18 23:32
>>51 Unevaluated Lisp forms are not s-expressions!
S-expressions are text, made up of characters. Lisp forms are Lisp objects.
s-expression → Lisp reader that understands s-expressions → Lisp form
Name:
Anonymous2014-07-18 23:32
>>44 Furthermore, you cock sucking faggot, unevaluated lisp with no expanded macros may consist of forms outside the lisp spec. Lisp macros allow you to define entirely different languages and a macro that attempts to locate all function calls will not be able to do the traversal without being extended for each macro written. Thus the only way the macro can work as intended is to expand the inner macros, thereby translating all nested DSLs to lisp, and then performing the code transformation on code containing nothing other than lisp forms defined in the spec.
Name:
Anonymous2014-07-19 3:14
No seriously, I don't think you people even understand this. I need a formal definition before I present a solution. Consider: (funcall (function (intern (read)))) Do we want BAR to be called when FOO is entered by the user?
Name:
Anonymous2014-07-19 18:20
>>53 What if you need to locate all calls to a particular macro? They won't even exist after macroexpansion.
Basically OP, try doing your request using your language of choice. You will see the problem is not the language, but the request itself. Symbolic expressions are just that, expressions notated in a tree like fashion: https://en.wikipedia.org/wiki/Symbolic_expressions
It has nothing to do with the ability to of the programmers here to rewrite a new interpreter. You are welcome to prove Lisp users otherwise.
Name:
Anonymous2014-07-20 7:21
>>55 Search the tree and as you search expand macros. Keep going down the tree until you find the macro you are looking for or you hit the bottom. The call to the macro could occur within an expanded macro at some arbitrary level.
>>67 Thanks for clarifying that. I just couldn't remember the term 'function slot', and what the difference between (foo) and (funcall 'foo) is, if any. The solution posted above then is complete and correct.
>>68 It's a term of code that contains a call to function foo. You're a fucking retard who cannot read. >>69 You're a fucking retard who has never used Lisp macros, obviously.
>>73 (list 'foo 7) >'(foo 7) It's only a function call when you tell lisp to evaluate it. Since that hasn't happened, it's just a list.
Is '(7 7) a function call to the number 7?
Name:
Anonymous2014-07-27 16:30
>>75 A term of code. A term of code. How many times do I have to repeat it till it sinks? There is a difference between a term of code and the process of its evaluation. Macros work specifically on terms of code.
Name:
Anonymous2014-07-27 16:36
>>76 Macros are passed unevaluated forms yes. But the unevaluated form of '(foo 7) is doubly unevaluated so it still doesn't make sense.
Name:
Anonymous2014-07-27 16:37
>>76 What makes '(7 7) different from '(foo 7) ? And please define 'term of code'. I'm not sure what you mean.