unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* memoization and error messages
@ 2002-11-24 10:43 Dirk Herrmann
  2002-11-24 12:57 ` tomas
  0 siblings, 1 reply; 9+ messages in thread
From: Dirk Herrmann @ 2002-11-24 10:43 UTC (permalink / raw)


Hi folks,

since yesterday I have made some progress with the memoizer, I just feel
like showing you :-)))  I will show you some transcripts of how my
modified version of guile works, with some explanations.  The focus of
this mail is on error messages for syntax errors.  Part of this mail is
for showing you things that already work (and how they work), some parts
indicate open points.  In general, the handling of syntax errors is not
perfect yet, but its a start.


1) Syntactic keywords are no longer accepted as expressions.  Formerly,
guile would have accepted the following:
  guile> define
  #<macro 4020ada0>
But now, the correct position of syntactic keywords is checked by the
memoizer:
  guile> define
  ERROR: In procedure memoization:
  ERROR: Misplaced syntactic keyword define.
  ABORT: (syntax-error)

2) Error messages are, where possible, more explicit:
  guile> (if)
  ERROR: In procedure memoization:
  ERROR: In line 1: Missing or extra expression in (if).
  ABORT: (syntax-error)
  ***
  guile> (lambda (a a) #t)
  ERROR: In procedure memoization:
  ERROR: In line 2: Duplicate formal a in expression (lambda (a a) #t).
  ABORT: (syntax-error)
  ***
  guile> (lambda (1 a) #t)
  ERROR: In procedure memoization:
  ERROR: In line 3: Bad formal 1 in expression (lambda (1 a) #t).
  ABORT: (syntax-error)
  ***
  guile> () 
  ERROR: In procedure memoization:
  ERROR: Illegal empty combination ().
  ABORT: (syntax-error)
It should be noted, that checks for the empty combination () were formerly
done during evaluation.  Now, these checks are removed from the evaluator!
The bad thing with this example is, that information about line numbers
can't be issued for expressions that are no lists.  Since () is an
immediate value, there is no linenumber information available.  Currently,
it also doesn't work for the following example:
  guile> (foo () bar)
  ERROR: In procedure memoization:
  ERROR: Illegal empty combination ().
  ABORT: (syntax-error)
although here at least the line number of the outer expression could be
printed.  This, however, requires to carry a stack of outer expressions
around while doing memoization.  This is not implemented yet, but could
certainly be done.  I will add this feature eventually.
  ***
  guile> (foo . bar)
  ERROR: In procedure memoization:
  ERROR: In line 7: Bad expression (foo . bar).
  ABORT: (syntax-error)
Expressions are always checked to be proper lists during memoization.
Please note: The example above shows that if a linenumber is available it
is printed.

3) Bad expressions are detected before evaluating the code!
  guile> (define (foo) (foo . bar))
  ERROR: In procedure memoization:
  ERROR: In line 10: Bad expression (foo . bar).
  ABORT: (syntax-error)
Formerly, this error would have remained undetected until foo was actually
executed.

4) Backtraces are somewhat strange.  Compare the following backtraces:
  guile> (eval '(foo . bar) (interaction-environment))                
  Backtrace:
  In unknown file:
     ?: 0* [eval (foo . bar) #<directory (guile-user) 8051a40>]
  <unnamed port>: In procedure memoization in expression (eval (quote #) (interaction-environment)):
  <unnamed port>: In line 0: Bad expression (foo . bar).
  ABORT: (syntax-error)
*****
  guile> (eval '(if #t (foo . bar)) (interaction-environment))
  Backtrace:
  In unknown file:
     ?: 0* [eval (if #t (foo . bar)) #<directory (guile-user) 8051a40>]
     ?: 1* [if (if #t (foo . bar)) (#<eval-closure 40271520>)]
  <unnamed port>: In procedure memoization in expression (eval (quote #) (interaction-environment)):
  <unnamed port>: In line 1: Bad expression (foo . bar).
  ABORT: (syntax-error)
*****
  guile> (eval '(if #t (if #t (if #t (foo . bar)))) (interaction-environment))
  Backtrace:
  In unknown file:
     ?: 0* [eval (if #t (if #t (if #t #))) #<directory (guile-user) 8051a40>]
     ?: 1* [if (if #t (if #t (if #t #))) (#<eval-closure 40271520>)]
     ?: 2* [if (if #t (if #t (foo . bar))) (#<eval-closure 40271520>)]
     ?: 3* [if (if #t (foo . bar)) (#<eval-closure 40271520>)]
  ERROR: In procedure memoization:
  ERROR: In line 2: Bad expression (foo . bar).
  ABORT: (syntax-error)
What surprises me is that with every additional (if #t ...) I get another
backtrace frame displayed.  But, within the memoizer I am pretty sure that
I don't add backtrace information for the debugger.  If someone knows how
backtraces are computed, I would appreciate that information.


As you see, there are still some open points with respect to reporting
syntax errors.  But I also hope that you see that a separation of
memoization and execution also brings benefits with respect to early error
detection.  And, it should be obvious that the executor benefits from the
fact that all syntax checks are done in advance.

Please let me know if you can help in any of the open points above.  And,
certainly, if you have suggestions for improvement of the above style of
error reporting.

Best regards, 
Dirk Herrmann



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 10:43 memoization and error messages Dirk Herrmann
@ 2002-11-24 12:57 ` tomas
  2002-11-24 16:49   ` Dirk Herrmann
  0 siblings, 1 reply; 9+ messages in thread
From: tomas @ 2002-11-24 12:57 UTC (permalink / raw)
  Cc: guile-devel

On Sun, Nov 24, 2002 at 11:43:15AM +0100, Dirk Herrmann wrote:
> Hi folks,
> 
> since yesterday I have made some progress with the memoizer, I just feel
> like showing you :-)))  I will show you some transcripts of how my
> modified version of guile works, with some explanations.  The focus of
> this mail is on error messages for syntax errors.  Part of this mail is
> for showing you things that already work (and how they work), some parts
> indicate open points.  In general, the handling of syntax errors is not
> perfect yet, but its a start.
> 
> 
> 1) Syntactic keywords are no longer accepted as expressions.  Formerly,
> guile would have accepted the following:
>   guile> define
>   #<macro 4020ada0>
> But now, the correct position of syntactic keywords is checked by the
> memoizer:
>   guile> define
>   ERROR: In procedure memoization:
>   ERROR: Misplaced syntactic keyword define.
>   ABORT: (syntax-error)

Hrm. Here's the usual whiner. Feel free to ignore me if I get onto
your nerves [1] ;-)

That means that macros aren't anymore `first class objects'? What
consequences does this have for meta-programming?

------
[1] No, I do acknowledge that *you* are doing the work and I'm just
    sitting back and complaining. I wouldn't take any offense if
    you prefer to do more real work instead of taking the time to
    answer to my ramblings.

Thanks
-- tomas


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 12:57 ` tomas
@ 2002-11-24 16:49   ` Dirk Herrmann
  2002-11-24 22:25     ` Daniel Skarda
                       ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Dirk Herrmann @ 2002-11-24 16:49 UTC (permalink / raw)
  Cc: guile-devel

On Sun, 24 Nov 2002 tomas@fabula.de wrote:

> That means that macros aren't anymore `first class objects'? What
> consequences does this have for meta-programming?

I don't know.  Can you be a little more specific about what you want to
accomplish that you can only accomplish with macros as first-class objects
(or rather said "accomplish cleanly")?  If so, please provide code
examples that show your approaches.

[rambling on]
It may make sense to point out the following:  Separate in-advance
memoization brings the possibility to speed up evaluation, it allows to
store pre-compiled code and thus speed up loading time, and it is a great
way to clean up guile's internals and achieve better R5RS conformance.

However, it does impose some restrictions:  Guile will be stricter with
respect to certain R5RS demands.  Further, macro expansion is no longer as
dynamic as it was before.  That is, the point of time when expansion is
handled is known in advance - this was not the case before.

But, for those who depend on dynamic code expansion (i. e. re-expansion of
code whenever a macro changes) there is always eval.  People say they
don't like eval.  But, they like dynamic code expansion, huh?  And, what
are their problems with eval?  Performance considerations?  Isn't it
better to improve speed and cleanliness for 99,9% of the cases, where
dynamic re-expansion is not necessary, instead of inhibiting performance
improvements in order to be able to avoid using eval?

IMO, instead of depending on dynamic code expansion (a, well, not-so-clean
and performance-inhibiting implementation detail of guile), the use of
eval is better, because it is standard and it makes parts of the code
obvious where you depend on dynamic re-expansion.
[rambling off]

Well, don't feel angry for my ramblings above, I was a little bit carried
away when I wrote it :-)  I actually very much appreciate all kinds of
comments with respect to separation of memoization and execution.  I have
learned a lot from your and other people's comments.

Friendly greetings
Dirk



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 16:49   ` Dirk Herrmann
@ 2002-11-24 22:25     ` Daniel Skarda
  2002-11-28 18:02       ` Dirk Herrmann
  2002-11-26 10:42     ` tomas
  2002-11-28 19:34     ` Neil Jerram
  2 siblings, 1 reply; 9+ messages in thread
From: Daniel Skarda @ 2002-11-24 22:25 UTC (permalink / raw)
  Cc: tomas, guile-devel

>> That means that macros aren't anymore `first class objects'? What
>> consequences does this have for meta-programming?
>
> I don't know.  Can you be a little more specific about what you want to
> accomplish that you can only accomplish with macros as first-class objects
> (or rather said "accomplish cleanly")?  If so, please provide code
> examples that show your approaches.

  I am sorry I have not followed all threads about mnemoization, so it is
possible that my notes are a little bit irrelevant.

  Why I think it is good for macros to be "first class objects":

>  guile> define
>  ERROR: In procedure memoization:
>  ERROR: Misplaced syntactic keyword define.
>  ABORT: (syntax-error)

  Does it mean that `define' is unbound? (*) I do not think so - I guess R5RS does
not allow to have macro and variable of the same name. 

  Macros should be in the same namespace as variables are. This is what I
dislike about Common Lisp - it has one namespace for functions and another for
variables. Maybe this is just a programmer's taste - but in my opinion
programming languages should not be designed with "what is easy to implement"
idea in the mind, but rather "programming should be fun". And I do not think it
is fun to add new cases users have to handle.

  These things I would like to be able to write in guile:

  (if (defined? 'my-macro)
      ....)

  (if (macro? foo)  ; not possible with your modification
      ....)

  (define old-foo foo) ; also not possible

  (defmacro foo args
    (do something clever with 'old-foo args))

  (module-ref (resolve-module '(guile-user)) 'define)
    
    ; returns the same value as simple "define" - but one line is correct
    ; another would be error. Why?

  Another important question - if macros were not first class, what consequences
this change would have on module system and its implementation?

  From my point of view macros as "first class objects" and non-dynamic code
expansion are two different things. If you clearly define when macros are
expanded, there is no need to forbid macros to be first class objects.

  My advice:

  1) Preserve macros as "first class objects". When somebody writes "define" or
    (define foo define), maybe he knows what he is doing :-)
    
  2) Clearly define the non-dynamic macro expansion.

  3) Provide macro `dynamic-expansion' - maybe something like this:

      (defmacro dynamic-expansion code
         `(local-eval '(begin ,@code) (the-environment)))
    
      so it would be easy to identify the code with dynamic macro expansion. (I
    do not know why people use dynamic macro expansion, but I guess it is handy
    during macro debugging...)

0.


(*) Quick survey:
  
  STklos - define is unbound, variable `define' is possible and it is different
           from macro (macro and variable can coexist)

  SCM - same as in guile

  RScheme - special form, can not be referenced, can be redefined

  MzScheme - same as RScheme

  elk - same as guile

  mit-scheme - same as (R|Mz)Scheme

  bigloo - same as STklos.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 16:49   ` Dirk Herrmann
  2002-11-24 22:25     ` Daniel Skarda
@ 2002-11-26 10:42     ` tomas
  2002-11-28 19:34     ` Neil Jerram
  2 siblings, 0 replies; 9+ messages in thread
From: tomas @ 2002-11-26 10:42 UTC (permalink / raw)
  Cc: tomas, guile-devel

On Sun, Nov 24, 2002 at 05:49:27PM +0100, Dirk Herrmann wrote:
> On Sun, 24 Nov 2002 tomas@fabula.de wrote:
> 
> > That means that macros aren't anymore `first class objects'? What
> > consequences does this have for meta-programming?
> 
> I don't know.  Can you be a little more specific about what you want to
> accomplish that you can only accomplish with macros as first-class objects
> (or rather said "accomplish cleanly")?  If so, please provide code
> examples that show your approaches.

Sorry to be so unspecific. One could for example imagine doing code
analysis by re-binding `interesting' symbols and then `running' the
code. Or, rendering of SXML by evalling an S-expression: different
stylesheets would correspond to different environments. In a more
general setting: the environment is the `interpretation function'
of a class of S-expressions. Consider this style of programming:

  (case keyword
        ((foo) (do-foo))
        ((bar) (do-bar))
        ((quux) (do-quux))
	...)

versus

  (let ((foo do-foo)
        (bar do-bar)
        (quux do-quux)
        ...)
    (eval keyword))

(yes, I've used eval ;-)

The nice art of the second approach is that you can carry around `canned'
environments and decide last minute what interpretation so use.

The point now is one of finer control. If the second approach means that
*everything* is open (eval as a totally opaque ``memoization barrier''),
then the second variant loses big time. The ideal (I gues a non-attainable
one) would be to let the compiler to find out. Usually I won't rebind car
or let, or define. But sometimes I might have a reason to (and then I'd
be willing to pay the high price. I'd have to anyway).

> [rambling on]
> It may make sense to point out the following:  Separate in-advance
> memoization brings the possibility to speed up evaluation, it allows to
> store pre-compiled code and thus speed up loading time, and it is a great
> way to clean up guile's internals and achieve better R5RS conformance.

Yes, you are right -- I'm just (weakly) arguing against a clear either-or,
that's why I sometimes talk about partial evaluation (although I have the
impression that the whole monster might be too fat for our purposes ;)

> However, it does impose some restrictions:  Guile will be stricter with
> respect to certain R5RS demands.  Further, macro expansion is no longer as
> dynamic as it was before.  That is, the point of time when expansion is
> handled is known in advance - this was not the case before.

The last one is one very important point, I think. Whatever the
implementation is, macro-expansion time should be clear (at least
so clear that the semantics of non-pathological programs is clear,
or rather that it is possible to decide whan a program is non-pathological).


> But, for those who depend on dynamic code expansion (i. e. re-expansion of
> code whenever a macro changes) there is always eval.  People say they
> don't like eval.  But, they like dynamic code expansion, huh?  And, what
> are their problems with eval?  Performance considerations?  Isn't it
> better to improve speed and cleanliness for 99,9% of the cases, where
> dynamic re-expansion is not necessary, instead of inhibiting performance
> improvements in order to be able to avoid using eval?

It's not to avoid it. It's just trying to give the compiler the possibility
of being `smarter' than just to rely on the user's judgement (especially
important when you face automatically generated code: the `user' might be
especially dumb in those cases ;-)

> IMO, instead of depending on dynamic code expansion (a, well, not-so-clean
> and performance-inhibiting implementation detail of guile), the use of
> eval is better, because it is standard and it makes parts of the code
> obvious where you depend on dynamic re-expansion.
> [rambling off]
> 
> Well, don't feel angry for my ramblings above, I was a little bit carried
> away when I wrote it :-)  I actually very much appreciate all kinds of
> comments with respect to separation of memoization and execution.  I have
> learned a lot from your and other people's comments.

Hey, come on. I do learn a lot from your ramblings. Please *do* ramble on.
> Friendly greetings
> Dirk


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 22:25     ` Daniel Skarda
@ 2002-11-28 18:02       ` Dirk Herrmann
  2002-12-02 20:45         ` Daniel Skarda
  0 siblings, 1 reply; 9+ messages in thread
From: Dirk Herrmann @ 2002-11-28 18:02 UTC (permalink / raw)
  Cc: tomas, guile-devel

Hello Daniel,

thanks for your comments.

On Sun, 24 Nov 2002, Daniel Skarda wrote:

>   Why I think it is good for macros to be "first class objects":
> 
> >  guile> define
> >  ERROR: In procedure memoization:
> >  ERROR: Misplaced syntactic keyword define.
> >  ABORT: (syntax-error)
> 
>   Does it mean that `define' is unbound? (*) I do not think so - I guess R5RS does
> not allow to have macro and variable of the same name. 

R5RS does allow macro and variable of the same name - in a sense.  For
example:

(defmacro foo <...>)  ;; after this line, foo is a syntactic keyword
(foo some-args ...)   ;; foo will be expanded.
(define foo <some-value>)  ;; after this line, foo is bound to a location
(foo some-args ...)   ;; foo will not be expanded.
(define (bar) foo)    ;; bar will refer to foo's binding
(defmacro foo <...>)  ;; after this line, foo is a syntactic keyword, but:
                      ;; bar will still refer to foo's _variable_ binding
(bar)   ;; will return the value at the location of foo's variable binding
(foo some-args ...)   ;; foo will be expanded
(define foo <some-value>)  ;; after this line, foo is not a syntactic
                           ;; keyword anymore.  I guess that this define
                           ;; should actually become a set! and should
                           ;; change the content of the location to which
                           ;; foo was bound formerly.
(bar)                      ;; If my above guess is right, this function
                           ;; should now return the value of the latest
                           ;; define.

>   Macros should be in the same namespace as variables are. This is what I
> dislike about Common Lisp - it has one namespace for functions and another for
> variables. Maybe this is just a programmer's taste - but in my opinion
> programming languages should not be designed with "what is easy to implement"
> idea in the mind, but rather "programming should be fun". And I do not think it
> is fun to add new cases users have to handle.
> 
>   These things I would like to be able to write in guile:
> 
>   (if (defined? 'my-macro)
>       ....)

Well, this could still be done.  The question, however, is, whether one
should distinguish between defined? and syntactic-keyword?.

>   (if (macro? foo)  ; not possible with your modification
>       ....)

True, but if you would quote foo, this could still be checked.

>   (define old-foo foo) ; also not possible

But
    (defmacro old-foo args `(foo ,@args))
does the trick.  The only problem that we currently have, is that defmacro
is not able to keep track of the module the definition of foo came from.  
For a temporary workaround, see my email about preparation for hygienic
macro expansion.

>   (defmacro foo args
>     (do something clever with 'old-foo args))

As long as you don't mix up definitions of foo from different modules,
this would also work with my example above.  And, with the workaround
presented in my email about preparation for hygienic macro expansion, it
should be possible to cover all cases even while we don't have a real
hygienic macro expander.

>   (module-ref (resolve-module '(guile-user)) 'define)
>     
>     ; returns the same value as simple "define" - but one line is correct
>     ; another would be error. Why?

Who says that one line is correct and one is an error?  sure:
   guile> define
_would_be_ an error if my local version of eval became official.  Today's
guile still accepts such a line, as it also accepts the module-ref code.
If my changes became official, the behaviour of module-ref with respect to
syntactic keywords might also change.

That is, it is simply not sure that module-ref will work the same way.
However, I recommend again to look into the email cited above.

>   3) Provide macro `dynamic-expansion' - maybe something like this:
> 
>       (defmacro dynamic-expansion code
>          `(local-eval '(begin ,@code) (the-environment)))
>     
>       so it would be easy to identify the code with dynamic macro expansion. (I
>     do not know why people use dynamic macro expansion, but I guess it is handy
>     during macro debugging...)

Yes, this could be done, although I recommend that we get rid of
local-eval.  The goals above can also be accomplished the following way:
Use 'eval to create a closure, with an argument for every element of the
local environment that is needed within the closure.  (Note:  This does
not allow to set! elements of the local environment.  You have to modifiy 
this approach a little to emulate a set! behaviour.  It's more effort, I
agree.)

Maybe we are just discussing the wrong examples here:  The major issue
about first class macros is that you can define them at run-time.  That
is, you could at run time change the set of syntactic keywords and have
the same code code expanded in different ways depending on the set of
macro definitions defined at run-time.  Do you have any situations like
this in mind?

Best regards
Dirk Herrmann



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-24 16:49   ` Dirk Herrmann
  2002-11-24 22:25     ` Daniel Skarda
  2002-11-26 10:42     ` tomas
@ 2002-11-28 19:34     ` Neil Jerram
  2 siblings, 0 replies; 9+ messages in thread
From: Neil Jerram @ 2002-11-28 19:34 UTC (permalink / raw)
  Cc: tomas, guile-devel

>>>>> "Dirk" == Dirk Herrmann <dirk@sallust.ida.ing.tu-bs.de> writes:

    Dirk> On Sun, 24 Nov 2002 tomas@fabula.de wrote:
    >> That means that macros aren't anymore `first class objects'? What
    >> consequences does this have for meta-programming?

    Dirk> I don't know.  Can you be a little more specific about what you want to
    Dirk> accomplish that you can only accomplish with macros as first-class objects
    Dirk> (or rather said "accomplish cleanly")?  If so, please provide code
    Dirk> examples that show your approaches.

What about the uses of `macro?' in `fset' in
lang/elisp/internals/fset.scm - how does this code look with your
changes?  (My understanding is that it is no longer possible to pass
around a macro value in a variable - please correct me if that's wrong.)

    Dirk> [rambling on]
    Dirk> It may make sense to point out the following:  Separate in-advance
    Dirk> memoization brings the possibility to speed up evaluation, it allows to
    Dirk> store pre-compiled code and thus speed up loading time, and it is a great
    Dirk> way to clean up guile's internals and achieve better R5RS conformance.

Agreed, and it paves the way for various kinds of fuller compilation.

    Dirk> But, for those who depend on dynamic code expansion (i. e. re-expansion of
    Dirk> code whenever a macro changes) there is always eval.

I think you are probably right that eval is the way forward, so I'll
try to learn to like it :-)  However, I wonder if dynamic expansion
usages actually need local-eval rather than R5RS eval - which is
tricky because local-eval is in a grey area at the moment.
(i.e. Marius called it a `weird critter' :-)

To test this, I offer a challenge (to anyone, not just Dirk): given
define-macro (or defmacro) behaving as Dirk proposes, write a
define-non-memoizing-macro macro that can be used to define a macro
that is expanded every time its containing expression is evaluated.

        Neil



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-11-28 18:02       ` Dirk Herrmann
@ 2002-12-02 20:45         ` Daniel Skarda
  2002-12-03  0:09           ` Lynn Winebarger
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Skarda @ 2002-12-02 20:45 UTC (permalink / raw)
  Cc: tomas, guile-devel


> R5RS does allow macro and variable of the same name - in a sense.  For
> example:

  First I must say I have to add "read R5RS more carefully" to my TODO list :)

  As my quick survey revealed, this macro part of R5RS is not consistently
implemented in most scheme implementations - in my opinion it shows that there
is something bad in R5RS.

> (defmacro foo <...>)  ;; after this line, foo is a syntactic keyword
> (foo some-args ...)   ;; foo will be expanded.
> (define foo <some-value>)  ;; after this line, foo is bound to a location
> (foo some-args ...)   ;; foo will not be expanded.
> (define (bar) foo)    ;; bar will refer to foo's binding
> (defmacro foo <...>)  ;; after this line, foo is a syntactic keyword, but:
>                       ;; bar will still refer to foo's _variable_ binding

  And what would do

(define (bar) foo)

  here (after second defmacro foo)? Return variable binding <some-value> or
macro? I rather would vote for simplicity, than for adhering to obscure feature
we find in standard (feature that most people do not care to implement in
"standard" way).

>>   (if (macro? foo)  ; not possible with your modification
>>       ....)
>
> True, but if you would quote foo, this could still be checked.

  No! If you quote foo, it is symbol.

  Current Guile:

   (cond
    ((symbol? x) ...)
    ((procedure? x) ...)
    ((macro? x) ....)

  this code after your proposal would be:

   (cond
    ((procedure? x) ...)
    ((and (symbol? x) (macro? x module))
      ...
    ((symbol? x) ...) ; now users has to remember that this line must be written 
                      ; after macro? line..... What an obscure feature...

  do you feel that you simplified programming in Guile?


>>   (define old-foo foo) ; also not possible
>
> But
>     (defmacro old-foo args `(foo ,@args))
> does the trick.  The only problem that we currently have, is that defmacro
> is not able to keep track of the module the definition of foo came from.  
> For a temporary workaround, see my email about preparation for hygienic
> macro expansion.
>
>>   (defmacro foo args
>>     (do something clever with 'old-foo args))
>
> As long as you don't mix up definitions of foo from different modules,
> this would also work with my example above.  

  No, it would not. 

(defmacro foo args blah blah ,,,)

(defmacro old-foo args `(foo ,@args))
(defmacro foo args (blah blah `(old-foo ,@args)))

  ... would cause infinite expansion.

>>   (module-ref (resolve-module '(guile-user)) 'define)
>>     
>>     ; returns the same value as simple "define" - but one line is correct
>>     ; another would be error. Why?
>
> Who says that one line is correct and one is an error?  sure:
>    guile> define
> _would_be_ an error if my local version of eval became official.  Today's
> guile still accepts such a line, as it also accepts the module-ref code.
> If my changes became official, the behaviour of module-ref with respect to
> syntactic keywords might also change.

  Well, IMHO (module-ref foo bar) should NOT be an error because "bar" is
defined in "foo" module (no matter if it is macro or not....). 

  I like about Guile (or scheme) that it lets you to touch everything in one
simple way.

  The "simple way" I understand as the way without many rule exceptions
one has to handle. I think something like: less exceptions in code => shorter
code => few bugs => shorter debugging time => faster development.

  "One way" - in guile all values can be "stored in variables" and all variables
are "equal" - why macros should be different? Why do you want to invent new way
for storing values?

>>       (defmacro dynamic-expansion code
>>          `(local-eval '(begin ,@code) (the-environment)))
>>     
>>       so it would be easy to identify the code with dynamic macro expansion. (I
>>     do not know why people use dynamic macro expansion, but I guess it is handy
>>     during macro debugging...)
>
> Yes, this could be done, although I recommend that we get rid of
> local-eval.  
  
  I do not care about how "dynamic-expansion" would be implemented.
My implementation with "local-eval" was just an example - such "dynamic-expansion"
works even with current guile eval and it clearly marks "odd" code.

> Maybe we are just discussing the wrong examples here:  The major issue
> about first class macros is that you can define them at run-time.  That
> is, you could at run time change the set of syntactic keywords and have
> the same code code expanded in different ways depending on the set of
> macro definitions defined at run-time.  Do you have any situations like
> this in mind?

  No. I do not defend dynamic macro expansion, rather I was speaking for 
"the right to touch everything" (including macros - that's what I understand 
as "macro is first class"). 

  I understand that non-dynamical macro evaluation is vital for Guile speed.
But I can not understand why it is impossible to achieve non-dynamical macro
expansion without loosing "first class macros". How "(is-a? define <macro>)"
or "(class-of let)" lowers the performance and why you want to prohibit it?
  
  Is there any other advantage than

     guile> define
 
  signals an error? In my oppinion it is easy to catch such errors - but what
would our tax? We would complicate other code and make it less immune to
possible bugs.

0.

ps: My small wish for Guile: macrolet (or let-macro - something like
let-syntax). How hard it would be to write macrolet with your eval?


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: memoization and error messages
  2002-12-02 20:45         ` Daniel Skarda
@ 2002-12-03  0:09           ` Lynn Winebarger
  0 siblings, 0 replies; 9+ messages in thread
From: Lynn Winebarger @ 2002-12-03  0:09 UTC (permalink / raw)
  Cc: tomas, guile-devel

On Monday 02 December 2002 15:45, Daniel Skarda wrote:
> > R5RS does allow macro and variable of the same name - in a sense.  For
> > example:
> 
>   First I must say I have to add "read R5RS more carefully" to my TODO list :)
> 
>   As my quick survey revealed, this macro part of R5RS is not consistently
> implemented in most scheme implementations - in my opinion it shows that there
> is something bad in R5RS.

    Or maybe it's just that hygienic macros are more difficult to implement
than non-hygienic macro systems.

Lynn



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2002-12-03  0:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-24 10:43 memoization and error messages Dirk Herrmann
2002-11-24 12:57 ` tomas
2002-11-24 16:49   ` Dirk Herrmann
2002-11-24 22:25     ` Daniel Skarda
2002-11-28 18:02       ` Dirk Herrmann
2002-12-02 20:45         ` Daniel Skarda
2002-12-03  0:09           ` Lynn Winebarger
2002-11-26 10:42     ` tomas
2002-11-28 19:34     ` Neil Jerram

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).