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