[
https://issues.apache.org/jira/browse/VELOCITY-704?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12675220#action_12675220
]
Nathan Bubna commented on VELOCITY-704:
---------------------------------------
The stop() function won't have any performance penalty over the directive
versions. There will be a small cost for creating the map to hold the scoped
variables, but in a few directives (localscope macros, #evaluate and #foreach),
we already create inner contexts. I really don't think we'll see any cost to
the scope.
I don't think stop() is any more confusing than having three differently named
"stop" directives that have no explicit connection to the situations for which
they are meant to be used. For instance, #break exists all the time, even when
not in a #foreach. It is obvious what $foreach.stop() does, and it can't be
used elsewhere since it will only exist within a #foreach. To easily confused
users, it may not be at all obvious why you use #break to end a #foreach early,
then use #stop(parse) to end a #parse early, and then can't leave a macro early
unless you add an undocumented directive with yet another name. The current
system is cobbled together from updates of old debugging code and
half-implemented features from other languages. In stark contrast, the stop()
approach is consistent throughout and is very VTL-centric, which means less for
users to think about.
Even if it does confuse people at first, it shouldn't confuse many of them.
#stop only became usable in v1.5 and has never been very documented, #break
only showed up a couple months ago in v1.6 and #return and #stop(parse) are
unreleased. These are not widely used features, and those most likely to use
them are more advanced users who are unlikely to be confused. And for such
advanced users, the greater power and explicitness of stop() should be a great
boon. For instance, when you have nested #foreach, #parse or #macro
situations, then you cannot get out of more than one at once. With the
control reference, they will be able to do $foreach.stopAll() or even be
specific and do things like $foreach.parent.stop().
Even if i were somehow persuaded to avoid having a method affect directive
execution (which LoopTool already does), then i would go back to pushing hard
for just one #stop() directive. I see no reason to keep three of them around
and very good reasons to have just one.
stop() provides one consistent, explicit, flexible way to do this for all
situations. It is also simple to implement and therefore easy to debug and
maintain for us developers as well.
> VTL Simplicity - "Control" objects
> ----------------------------------
>
> Key: VELOCITY-704
> URL: https://issues.apache.org/jira/browse/VELOCITY-704
> Project: Velocity
> Issue Type: New Feature
> Components: Engine
> Reporter: Nathan Bubna
> Assignee: Nathan Bubna
> Fix For: 2.0
>
>
> In the discussion for VELOCITY-680, Claude suggested the addition of what i'm
> calling "control" objects as a solution. These would have the same name as
> the block directive or macro to which they belong. At a minimum, these
> would provide get(key), set(key, value) and stop() methods to control the
> reference scoping and execution of the block to which they belong.
> Directives could extend the basic control object to provide additional
> functions, such as index() and hasNext() for #foreach. Here's some examples:
> #foreach( $user in $users )
> $user#if( $foreach.hasNext ), #end
> #if( $foreach.count > 10 ) $foreach.stop() #end
> #end
> #macro( foo $bar )
> blah blah #if( $bar == 'bar' ) $foo.stop() #end
> #set( $foo.woogie = 'woogie' )
> $foo.woogie
> #end
> #foreach( $item in $list )
> #set( $outer = $foreach )
> #foreach( $attr in $item.attributes )
> #if ( $attr == $null ) $outer.stop()#end
> #end
> #end
> ------foo.vm---------
> blah blah $template.stop() blah
> ------------------------
> #define( $foo )
> blah blah $define.stop() blah
> #end
> This could allow us to greatly simplify all sorts of things. We could remove
> the #break, #stop and #return directives. We would no longer need to have
> "local" contexts for foreach loops or macros; instead users could set and get
> local variables directly in the provided namespace. All else would be
> global. This may even cut down our internal code complexity a fair bit.
> It'll certainly obviate the need for several configuration properties and
> internal contexts. Everything becomes much more explicit, obvious and
> robust. I also don't think it looks ugly. :)
> We would, of course, have to make sure that the StopExceptions thrown by
> stop() aren't wrapped into MethodInvocationExceptions. We'd have to make the
> directives clean up their control when done rendering, and if they're nested
> in a directive of the same type, then they should save and restore the
> reference to the parent control. We'd also have to figure out a good
> default name to give the control objects for the top-level control object,
> and whether it would be different than the name of the control object used
> during a #parse call. $template? $parse? $velocity? If we wanted to use
> $template--which i think works well for both top-level and #parse--then we'd
> probably have to make it configurable, since that's likely to conflict. And
> if we make that configurable, i suppose we may as well make it configurable
> for the others too.
> I'm struggling to think of any real downside to this. Most of the replaced
> features (implicit macro localscope, #stop, #break, $velocityHasNext) are
> either not default behavior or are new features. I'd wager that most people
> would only have to change $velocityCount to $foreach.count. Even that's no
> big deal, since this would be for a major version change. , The worst i can
> think of is the fact that for a couple of these controls it would mean a few
> more keystrokes. Considering all the gains in extensibility, explicitness
> and simplification (for us and users), i think it's worth a few keystrokes.
> What do you guys think?
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]