Jose Alberto Fernandez wrote:
> 
> > From: Geir Magnusson Jr. [mailto:[EMAIL PROTECTED]]
> >
> 
> First of all, I very much like summary and the idea of using a constant
> to represent NULL. That will make any issues with the storage used in the
> implementaion go away (i.e., Hashtable vs HashMap).
> 
> I would suggest the the constant be defined as part of the Context
> interface. It is a developer level concept and should be visible to all. So
> I would propose:
> 
> public interface Context {
>  public static final Object NULL = new Object();
>  ....
> }

That's *exactly* what I meant.

> This works fine, I use it in my failed attempt to change #macros into
> #subroutines. Remember.

Yes. :)

> 
> More inline...
> >
> > Christoph :
> >
> > > "Geir Magnusson Jr." wrote:
> > > [SNIP]
> > > > 4) We want to handle the app side putting null keys and
> > values into the
> > > > context w/o throwing our hands up and saying 'let the
> > implementation
> > decide'
> > > > or having to sprinkle try{} blocks everywhere.
> >
> > > OK (but note that null keys isn't really required but can be added
> > > analogosuly to null values). I see this is aiming at the solution
> > > proposed below.
> >
> > No, I don't mean we keep null keys, just that we handle them
> > and drop them.
> > As long as we return null from a get(null), all is well...
> >
> 
> I really see no reason for null keys. At least at the VLT level.

There could only be one, namely null, and I agree.
 
> > > >
> [snip]
> >
> > > Note that Jose also proposed a $?foo syntax.
> >
> > I think it was earlier than that, and soundle thumped down by
> > jon, I think.
> >
> 
> I saw a proposal for ?$foo but mine was $?foo ;-)

Ok, then I get to do it :  "Hell no! We aren't doing Perl here!"  ;->
 
> In any case, notice that what I was proposing was for "$?foo" to evaluate
> to a boolean value. That means that it will render "true" or "false" and
> that it will be evaluated in #if and #set as booleans.
> 
> I do not know if the other proposals are in the same spirit.

That's what I gathered.  I think the one acceptable to most people is
something on the order of 

  #if( $foo == NULL )

or somesuch which is pretty clear - doesn't take much guesswork to
figure it out...  That would be the case of a manual-free grammar - you
don't need a manual....  sorry.  couldn't resist.

> [snip]
> >
> > > Please note that sometimes returing null is desireable:
> > >  #set( $dummy = $hastable.put("KEY", "woobie") )
> > > Do I have to place a bang into $!hastable to avoid a message?
> >
> > No, you don't have to put a bang. That is only for rendering,
> > and you are
> > not rendering when you are on the RHS of a #set().
> >
> Is the reason with this issue with the $hastable.put() the fact that put()
> returns a value? What about if put() returned void? Just wondering.

Yes, actually.  For things that return stuff, you have to catch them
like above, or they render().  This is, I think, entirely acceptable.  
if put() returned void, all would be fine.
 
> Maybe we need something like #ignore( <expr> ) which causes the evaluation
> of expression but renders nothing. Well maybe ingore is not the best name
> ;-)

or maybe we provide a VM, since it's pass by name :)

#macro( ignore $foo )
  #set( $blargh = $foo )
#end

<musing>
(of course, if $blargh is in the context....  we need a reserved junk
reference name for this purpose.. or see below...) 
</musing>

[SNIP]
> > Can you give an example of functionality you wont have if the
> > inner context
> > is shielded from put()s by the 0th level context?
> >
> 
> Here I can give you a very concreate example that comes from our discussion
> on how VMs work. As you remember one of the points I was trying to make was
> that arguments to VMs were re-evaluated on every ocurrance in the macro.

Yes, that's by design.

> And the suggestion was made to use #set() if only one evaluation was
> required. Well additionally you need to do something like chaining to make
> sure the variable used for the #set is not already used outside of the
> macro.
> So far so good, chained Contexts can work.

Eh.  First, the #set is a workaround hack.  This will be fixed.  Second,
one way to deal with this via coding conventions which establish what a
local, throwaway references for VMs, such as $foo_ or $_foo (which may
not parse at the moment :)  

This isn't a great solution by any stretch of the imagination, but from
my point of view, VTL isn't meant to be a programming language either. 
There are plenty of them out there, and the niche that Velocity fills
isn't meant to be general.

Maybe we do offer block-scope references via #local() or something, or
maybe we declare and enforce the idea that you *can't* affect the
context from w/in a macro unless you set a reference you pass in as an
arg.  Or we can wrap the context w/in the macro body to protect it, and
require that alterations of context entities are done in a specific way,
such as :

  $this.set( $foo, val )

where $this refers to the current context, or some other nonesense like
this.  Lots of options.   My current favorite-of-the-femtosecond is the
can only change a ref you pass in option.

But this still doesn't really convince me about why chained contexts
should be modifiable.  I will read on!

> However, if the VM is suppose to change the state of the incomming context,
> then we cannot use chaining because it will be lost when leaving the VM. Ex:
> 
> #macro(m1 $p1)
> #local($a)
>  $set( $a = $p1 )
>  $set( $appVar = $a + $a )
> #end
> #end
>

Right.  Still reading...
 
> Now if we use inmutable chained contexts for the implementation of #local
> then things will not work as expected because there is no way to put $appVar
> in the outer context.

First, this assumes an implementation which is a simple use of a chained
context.  That's not necessary.  More on that later.

Next, I don't buy into the #local() thing.  But if someone put a gun to
my head and said implement #local(), it would take multiple args, and
only those would be localized references.  So $appVar would still be in
the context because it's not in the #local() arglist.

And if I did, the 'chained context' that #local() [sort of] is  doesn't
require strict adherance to the app-level API and conventions, because
we would be using it in a very specialized, controlled way. Rather, this
is entirely the point behind the InternalContextAdapter and decoupling
the application context API from the internal context API - so we can do
whatever freaky stuff we need to do internally.  I think that's
acceptable.  

And to repeat something I think I said earlier, context immutability is
able to be circumvented in that we let apps create Context
implementations that do whatever they want.  If an application framework
wants to make a non-immutable Context, groovy.  Should we provide it as
part of Velocity for default app use?  I think not. 

Our new Context API doesn't say *anything* about chaining.  That is a
concept from the AbstractBase class, and custom Contexts can implment as
needed for the app.  But I bet 99% of users will be able to use the
VelocityContext provided for them.

> Now, given the new arquitecture, the implementor of #local can define its
> own implementation of Context which is semi-permeable. Only things declared
> as local live in the local scope, the rest go thru. This is not difficult at
> all to do.

Yes!  Further, you don't even have to follow the Context API  very far,
as it's internal.

> Now, the challenge is, can we do the same without using an additional
> context? I think it is possible, but...

Yes, and that is my current project [ug... finally...] now that this
Context stuff is obviously sorting itself out :)

geir

-- 
Geir Magnusson Jr.                               [EMAIL PROTECTED]
Velocity : it's not just a good idea. It should be the law.
http://jakarta.apache.org/velocity

Reply via email to