| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| Dear Cognoscenti I am starting a Number Theory project, primarily for generating examples in the classroom, using bignums and rational-numbers in CL. I'll be posting some "beginner" questions, because I've found that I've forgotten what little I knew; I am relearning CL, v*e*r*y slowly, and have been getting tangled up with `defpackage', and package-management in general. [It is also clear that I have forgotten how to ask short questions, but that too will come back with practice.] ================ I'd like to define various rings, e.g, the ring of polynomials in one variable. Or the field of polynomials modulo a particular irreducible polynomial. Concretely, let's suppose I have written these packages: RING-POLY : Implements arithmetic operations in the polynomial ring. Internally the routines are named `ROP+' (for the Ring OPeration of addition), `ROP*', `ROP-ISZERO-P' and so on. RING-MOD5 : Implements arithmetic operations in the integers-mod-5. Internally the routines are named by the same names, `ROP+' (for addition mod-5), etc. So RING-POLY::ROP+ adds two polynomials, whereas RING-MOD5::ROP+ adds two integers mod-5. There are various other packages, say MATRIX : for putting a matrix in reduced-row-echelon form. First question: In package RING-POLY, I need to define FOO (i.e, RING-POLY::FOO) that calls external routine MATRIX:RREF. This latter's code uses ROP+ and ROP* and so on. How do I set things up so that, when _loading_ package RING-POLY and consequently defining FOO, that each occurrence of ROP+ in this call to MATRIX:RREF actually _means_ RING-POLY::ROP+ ? And similarly, when loading RING-MOD5 that each of occurrence of ROP+ in a call to MATRIX:RREF actually _means_ RING-MOD5::ROP+ ? [I realize that perhaps the routines in MATRIX could all be written as macros, rather than functions. But I'd just as soon have MATRIX written as if there is only one ring in the world, and MATRIX is just a bunch of functions that use this ring's operations.] Second question: (This is a generalization of the first.) After having done > (in-package "COMMON-LISP-USER") > (use-package "RING-POLY") > (use-package "RING-MOD5") > (use-package "MATRIX") I'd like to able to write something like the following: > (compute-value-using-ring "RING-POLY" (RREF some-matrix ) ) where COMPUTE-VALUE-USING-RING sets up a temporary context where the routines in MATRIX, when referring to ROP+, are somehow actually using RING-POLY::ROP+ . ================================================== ============== Comments: 0: For the time being, I am pretending that none of the routines RING- POLY::ROP+ need to refer to arithmetic operations in other, simpler rings. This isn't actually true, but I'm already confused by the simpler situation. 1: Some time ago, I did something similar in EL [emacs lisp], using a pointer to (something like) structs whose entries were the various arithmetic operations. Firstly, I found this clumsy. Secondly, since CL has a real package system, and since the different (defstruct)s would be occurring in different RING packages, then their slot names [this is something I'm confused about] would actually be different symbols [due to the package-name component], so I'm not sure how I'd refer to them generically inside of the MATRIX code. 2: I'd like MATRIX to not know of the existence of multiple rings. So I'd just as soon _not_ have the routines in MATRIX have to have a "current-ring" parameter that is passed-in. 3: The data is not typed. I.e, my situation doesn't have the complexity that ROP+ has to look at its arguments and say "Ah --you folks are polynomials. So now I know how to add you". Rather, the _context_ that a ROP routine is called-in should determine which ring it is. As an example, suppose M is a matrix, with each entry a list, such as ( 2/3 , 9 , 4). Called in the context of RING-POLY, such an entry is interpreted as the polynomial 2/3 + 9x + 4x^2. But called in the context of RING-RATIONALS-WITH-BAGGAGE, the same list ( 2/3 , 9 , 4) is simply interpreted as the number 2/3, where the "9" and "4" are some auxiliary data that just goes along for the ride. Sincerely, -Jonathan King -- Prof. Jonathan LF King Mathematics dept, Univ. of Florida <squash[[AT]]math.ufl.edu>, <http://www.math.ufl.edu/~squash/> |
|
#2
| |||
| |||
| squash+go@math.ufl.edu wrote: > Dear Cognoscenti > > I am starting a Number Theory project, primarily for > generating examples in the classroom, using bignums and > rational-numbers in CL. > > I'll be posting some "beginner" questions, because I've found that > I've forgotten what little I knew; I am relearning CL, v*e*r*y > slowly, and have been getting tangled up with `defpackage', and > package-management in general. [It is also clear that I have > forgotten how to ask short questions, but that too will come back > with practice.] What you seem to want to do is not possible with packages. Package references are resolved at read time, but you want a change of function references at runtime. With plain Common Lisp, you could probably use generic functions that dispatch on the kind of ring operations that you want. However, this violates your requirement that the matrix operations are not aware that potentially different ring operations are used in the first. What you describe rather sounds like an excellent use case for ContextL. You may want to it check it out at http://common-lisp.net/project/closer/contextl.html Please contact me if you have any questions. If ContextL actually turns out to be useful, I would also like to hear about it... Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/ |
|
#3
| |||
| |||
| Hi, As I don't have much time right now, I'm going to quickly hack something up without actually reading all of your post, so... sorry if this turns out to be completely off-topic. ![]() > I'd like to able to write something like the following: > > > (compute-value-using-ring "RING-POLY" > (RREF some-matrix ) ) > > where COMPUTE-VALUE-USING-RING sets up a temporary context where the > routines in MATRIX, when referring to ROP+, are somehow actually using > RING-POLY::ROP+ . You could use special variables: (in-package matrix) (defvar *rop+*) (defvar *rop**) (defun rop+ (&rest args) (apply *rop+* args)) (defun rop* (&rest args) (apply *rop** args)) .... You call these functions in the MATRIX routines. Then, you define a macro WITH-RING-OPERATIONS, also in package MATRIX: (defmacro with-ring-operations ((+-op *-op) &body body) `(let ((*rop+* ,+-op) (*rop** ,*-op)) ,@body)) You would call the macro like this: (with-ring-operations (#'ring-poly::+-op #'ring-poly::*-op) (RREF some-matrix ...) ...) Maybe you could even implement your COMPUTE-VALUE-USING-RING macro (I'm calling it WITH-RING here; caution: this is completely untested! I can only hope it's not fundamentally wrong): (defmacro with-ring ((package-designator) &body body) `(with-ring-operations (,(fdefinition (find-symbol "ROP+" (package- name package-designator))) ,(fdefinition (find-symbol "ROP*" (package- name package-designator)))) ,@body)) This is an ugly hack if you ask me, though. You'd probably be better served with something like ContextL that actually has a concept of special functions, which is what I'm trying to simulate here (or so I hear -- I've never used ContextL myself, although it's on my to-do list )).Hope this helps, ~ Matthias |
|
#4
| |||
| |||
| In article <5irmcgF3qc4bnU1@mid.individual.net>, Pascal Costanza <pc@p-cos.net> wrote: > squash+go@math.ufl.edu wrote: > > Dear Cognoscenti > > > > I am starting a Number Theory project, primarily for > > generating examples in the classroom, using bignums and > > rational-numbers in CL. > > > > I'll be posting some "beginner" questions, because I've found that > > I've forgotten what little I knew; I am relearning CL, v*e*r*y > > slowly, and have been getting tangled up with `defpackage', and > > package-management in general. [It is also clear that I have > > forgotten how to ask short questions, but that too will come back > > with practice.] > > What you seem to want to do is not possible with packages. Package > references are resolved at read time, but you want a change of function > references at runtime. > > With plain Common Lisp, you could probably use generic functions that > dispatch on the kind of ring operations that you want. However, this > violates your requirement that the matrix operations are not aware that > potentially different ring operations are used in the first. While this will not answer the OP's question, it might be still interesting to look at the following two CLOS-based systems (Weyl and Kenzo) for inspiration: Kenzo. http://www-fourier.ujf-grenoble.fr/~sergerar/Kenzo/ Weyl is a part of SimLab http://www.cs.cornell.edu/Info/Proje...lease-1-0.html The release includes source and documentation. The Weyl Computer Algebra Substrate http://ecommons.library.cornell.edu/.../1/90-1077.pdf > > What you describe rather sounds like an excellent use case for ContextL. > You may want to it check it out at > http://common-lisp.net/project/closer/contextl.html > > Please contact me if you have any questions. If ContextL actually turns > out to be useful, I would also like to hear about it... > > > Pascal -- http://lispm.dyndns.org |
|
#5
| |||
| |||
| squash+go@math.ufl.edu wrote: > Dear Cognoscenti > > I am starting a Number Theory project, primarily for > generating examples in the classroom, using bignums and > rational-numbers in CL. > > I'll be posting some "beginner" questions, because I've found that > I've forgotten what little I knew; I am relearning CL, v*e*r*y > slowly, and have been getting tangled up with `defpackage', and > package-management in general. [It is also clear that I have > forgotten how to ask short questions, but that too will come back > with practice.] Your question reminds me of this thread in sci.math.symbolic. This example shows one way to organize the code in PLT Scheme: <http://2url.org/?ringexample> -- Jens Axel Søgaard |
|
#6
| |||
| |||
| Thank you, Pascal, Matthias, Rainer and Jens, for your replies. You have given me several reading assignments, which I will do as soon as I can. [The semester here begins tomorrow.] If what I'm looking for can't be done easily in CL, then this means I've mis-specified or over-specified the problem. I have an idea for a partial (but perhaps inefficient) solution using `flet' and `defmacro', which I will post in a few days. But this leads me to a question about `flet' and `defmacro'. I'll use these macros to ask the question: (defmacro me (&rest form) `(macroexpand-1 ',@form)) (defmacro mefull (&rest form) `(macroexpand ',@form)) (defmacro metoo (&rest form) `(EXT:EXPAND-FORM ',@form)) I read about `EXT:EXPAND-FORM' in this N.G.; it may be specific to CLISP. ================================================== ============== In a fresh CLISP, I execute the above macro defs. Then the following gives this [slightly edited] output: (defmacro mac (x) ` (list ,x ,x ,x)) => MAC (metoo (list (let ((z 7)) (mac z)) (flet ((mac (z) (+ z 7))) (mac 100)))) => (LIST (LET ((Z 7)) (LIST Z Z Z)) (FLET ((MAC (Z) (DECLARE (SYSTEM::SOURCE ((Z) (BLOCK MAC (+ Z 7))))) (+ Z 7))) (MAC 100))) Executing the argument to `metoo' gives (list (let ((z 7)) (mac z)) (flet ((mac (z) (+ z 7))) (mac 100))) => ((7 7 7) 107) So the call to `(mac z)' inside of `let' is macro-expanded, and the call to `(mac 100)' inside the `flet' is not macro-expanded. This makes sense to me; could someone tell me where this is said in either the book CLTL2 or at "http://www.lisp.org/HyperSpec/"? Here is a paragraph from http://www.lisp.org/HyperSpec/Body/s..._macrolet.html that says: "The names of functions defined by flet are in the lexical environment; they retain their local definitions only within the body of flet. The function definition bindings are visible only in the body of flet, not the definitions themselves. Within the function definitions, local function names that match those being defined refer to functions or macros defined outside the flet. flet can locally shadow a global function name, and the new definition can refer to the global definition." Is the sentence "flet can locally shadow a global function name, and the new definition can refer to the global definition." implying that the `(mac 100)' is not to be macro-expanded? Is the DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS link telling me this? That link leads to (among other things) http://www.lisp.org/HyperSpec/Issues...5-writeup.html which seems (in part) to be talking about destructuring. Looking at the `defmacro' page, and I did not recognize an explicit statement about how `flet' and `defmacro' interact. [That doesn't mean it isn't there; I'm just not recognizing it.] What I'm really asking is for suggestions on how to read the hyperspec efficiently [it is big, and I have a poor memory], and how to find things efficiently. [There is a lot of terminology that I haven't yet absorbed.] ================================================== ============== On a side note, when I do the expansion using `mefull' (i.e `macroexpand') rather than `metoo', it doesn't go far enough for me to see the difference between the interactions with `let' and with `flet': (mefull (list (let ((z 7)) (mac z)) (flet ((mac (z) (+ z 7))) (mac 100)))) => (LIST (LET ((Z 7)) (MAC Z)) (FLET ((MAC (Z) (+ Z 7))) (MAC 100))) I'm guessing that this is some kind of intentional granularity on the part of `macroexpand', for debugging code. Are there some general guidelines on when to use `macroexpand' rather than `EXT:EXPAND-FORM'? [I think I understand when to use `macroexpand-1'.] Sincerely, -Jonathan -- Prof. Jonathan LF King Mathematics dept, Univ. of Florida <squash[[at]]math.ufl.edu>, <http://www.math.ufl.edu/~squash/> |
|
#7
| |||
| |||
| squash+go@math.ufl.edu wrote: > So the call to `(mac z)' inside of `let' is macro-expanded, and the > call to `(mac 100)' inside the `flet' is not macro-expanded. > > This makes sense to me; could someone tell me where this is said in > either the book CLTL2 or at "http://www.lisp.org/HyperSpec/"? 3.1.1.3 and 3.1.2.1.2 in the HyperSpec. > On a side note, when I do the expansion using `mefull' (i.e > `macroexpand') > rather than `metoo', it doesn't go far enough for me to see the > difference > between the interactions with `let' and with `flet': > > (mefull (list (let ((z 7)) (mac z)) (flet ((mac (z) (+ z 7))) (mac > 100)))) > => > (LIST (LET ((Z 7)) (MAC Z)) (FLET ((MAC (Z) (+ Z 7))) (MAC 100))) > > I'm guessing that this is some kind of intentional granularity on > the part of `macroexpand', for debugging code. Are there some > general guidelines on when to use `macroexpand' rather than > `EXT:EXPAND-FORM'? [I think I understand when to use > `macroexpand-1'.] This is explained in the entry for 'macroexpand: If a form is not a macro invocation, then macroexpand just returs that form unchanged. As a sidenote, you should not do this: (defmacro me (&rest form) `(macroexpand-1 ',@form)) (defmacro mefull (&rest form) `(macroexpand ',@form)) But rather: (defmacro me (&rest form &environment env) `(macroexpand-1 ',@form env)) (defmacro mefull (&rest form &environment env) `(macroexpand ',@form env)) Otherwise, these macros may return the wrong expansions because they don't see local macro definitions. Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/ |
|
#8
| |||
| |||
| In article <5j0ghvF3qivtiU1@mid.individual.net>, Pascal Costanza <pc@p-cos.net> wrote: > squash+go@math.ufl.edu wrote: > > > So the call to `(mac z)' inside of `let' is macro-expanded, and the > > call to `(mac 100)' inside the `flet' is not macro-expanded. > > > > This makes sense to me; could someone tell me where this is said in > > either the book CLTL2 or at "http://www.lisp.org/HyperSpec/"? > > 3.1.1.3 and 3.1.2.1.2 in the HyperSpec. > > > On a side note, when I do the expansion using `mefull' (i.e > > `macroexpand') > > rather than `metoo', it doesn't go far enough for me to see the > > difference > > between the interactions with `let' and with `flet': > > > > (mefull (list (let ((z 7)) (mac z)) (flet ((mac (z) (+ z 7))) (mac > > 100)))) > > => > > (LIST (LET ((Z 7)) (MAC Z)) (FLET ((MAC (Z) (+ Z 7))) (MAC 100))) > > > > I'm guessing that this is some kind of intentional granularity on > > the part of `macroexpand', for debugging code. Are there some > > general guidelines on when to use `macroexpand' rather than > > `EXT:EXPAND-FORM'? [I think I understand when to use > > `macroexpand-1'.] > > This is explained in the entry for 'macroexpand: If a form is not a > macro invocation, then macroexpand just returs that form unchanged. > > > As a sidenote, you should not do this: > > (defmacro me (&rest form) `(macroexpand-1 ',@form)) > (defmacro mefull (&rest form) `(macroexpand ',@form)) > > But rather: > > (defmacro me (&rest form &environment env) > `(macroexpand-1 ',@form env)) > (defmacro mefull (&rest form &environment env) > `(macroexpand ',@form env)) > > Otherwise, these macros may return the wrong expansions because they > don't see local macro definitions. > > > Pascal What is the &rest for anyway? (macroexpand '(me (foo) (bar) (baz))) What would above do? The forms ME* will do nothing to help clear the issue with MACROEXPAND vs. MACROEXPAND-1. What is the purpose of writing (me (list 'foo)) vs. (macroexpand-1 (list 'foo)) ?? -- http://lispm.dyndns.org |
|
#9
| |||
| |||
| Pascal Costanza wrote > ... > As a sidenote, you should not do this: > > (defmacro me (&rest form) `(macroexpand-1 ',@form)) > (defmacro mefull (&rest form) `(macroexpand ',@form)) > > But rather: > > (defmacro me (&rest form &environment env) > `(macroexpand-1 ',@form env)) > (defmacro mefull (&rest form &environment env) > `(macroexpand ',@form env)) > > Otherwise, these macros may return the wrong expansions because they > don't see local macro definitions. Yes, thank you Pascal, I have fixed the macros in my file, and removed the "&rest", as Rainer Joswig pointed out. ================================================== ============== On Aug 21, 12:25 pm, Rainer Joswig <jos...@lisp.de> wrote: .... > > What is the purpose of writing > > (me (list 'foo)) vs. (macroexpand-1 (list 'foo)) > > ?? My poor memory. When I've been away from a programming language (in the broad sense) for a while, e.g Maple, TeX, CSS, I forget what functions/operations are named. So I alias them all to a common name, for functions/operations that are conceptually related, in the different languages. ================ As to my original question about how to make my ring-operations context dependent, I've written some code and am now experimenting with it. I'll post a more precise version of my question when I've had a chance to see what the problems are with the current approach. Sincerely, -Jonathan King -- Prof. Jonathan LF King Mathematics dept, Univ. of Florida <squash[[at]]math.ufl.edu>, <http://www.math.ufl.edu/~squash/> |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.