On 05/03/2010 04:48 AM, Caleb James DeLisle wrote:
> Wow, there are a lot of ways to write unmaintainable code.
> Do all of those examples work as you describe? (in the current version)
All except the first one, pass by sharing, which is the one causing us
trouble.
> Sergiu Dumitriu wrote:
>> On 05/02/2010 09:01 PM, Caleb James DeLisle wrote:
>>> I've been using that pattern everywhere. There are no return statements
>>> the only other options I see are making all variables global to the script
>>> or eliminating the use of macros entirely (spaghetti code).
>>> Is there a better way?
>>
>> This only affects things like this:
>>
>
> I have been using this:
> #set($output = '')
> #getData($input, $output)
> #if($output == '')
> ## error
> #end
>
>> #macro(m $returnParam)
>> #set($returnParam = 'result')
>> #end
>> #m($expectedOutput)
>> $expectedOutput is not 'result'
>>
>>
>> These will still work:
>
> Although I knew this worked, I have avoided this at all cost.
> Global variables are too hard for me to follow.
>
>>
>> #macro(m)
>> #set($returnParam = 'result')
>> #end
>> #m()
>> $returnParam is 'result'
>>
>> Or:
>>
>
> I have used this a few times.
>
>> #set($output = {})
>> #macro(m $output)
>> $output.put('expectedOutput1' : 'result1')
>> $output.put('expectedOutput2' : 'result2')
>> #end
>> #m($returnParam)
>> $returnParam.expectedOutput1 is 'result1'
>> $returnParam.expectedOutput2 is 'result2'
>>
>>
>> The first one is not nice since it has side effects which must be well
>> documented, the second one is nicer but also needs to be documented and
>> it needs a map or array even if only one output is expected.
>>
>>
>> The way velocity macros work is a bit unclear, it's a mix between call
>> by macro expansion, call by sharing, call by value and other behaviors.
>> See http://en.wikipedia.org/wiki/Evaluation_strategy and
>> http://www.knowledgerush.com/kr/encyclopedia/Call-by-something/ for
>> short explanations.
>>
>> Call by sharing example (in 1.7b1 only)
>> #macro(callBySharing $x $map)
>> #set($x = 'a')
>> $map.put('x', 'a')
>> #end
>> #set($y = 'y')
>> #set($map = {})
>> #callBySharing($y $map)
>> $y -> 'y' (but is 'a' in 1.6.2)
>> $map.x -> 'a'
>> Java-like behavior
>>
>>
>> Call by name/macro expansion example (and call by need counter-example)
>> #macro(callByMacro1 $p)
>> not using
>> #end
>> #macro(callByMacro2 $p)
>> using: $p
>> using again: $p
>> #end
>> #set($x = [])
>> #callByMacro1($x.add('t'))
>> $x -> [], the add call was not executed
>> #callByMacro2($x.add('t'))
>> $x -> [t,t], the add call was executed twice
>
> I did not know about this.
> Maybe some of these gotchas should be added to the scripting page.
>
>
>>
>>
>> Call by value(?) example (and call by name or expansion counter-example)
>> #macro(callByValueSwap $a $b)
>> $a $b becomes ##
>> #set($tmp = $a)
>> #set($a = $b)
>> #set($b = $tmp)
>> $a $b
>> #end
>> #callByValueSwap('a', 'b') ->
>> a b becomes b a
>> In a true call-by-name (or macro-expansion) implementation, $a would
>> always be 'a'. What actually happens is that #set($a = $b) creates the
>> global variable $a which shadows the formal parameter.
>>
>>
>> Call by macro expansion example (and call by value or sharing
>> counter-example)
>> #macro(changeMap $map)
>> Before: $map.someKey
>> #set($map.someKey = 'new value')
>> After: $map.someKey
>> #end
>> #changeMap({'someKey' : 'old value'}) -> old value, then again old value
>> If this was true call-by-sharing (or call-by-reference), then $map would
>> be a pointer to a real map which would be changed by the first set.
>>
>>
>> Call by macro expansion example (exposes name capture, call by name
>> counter-example)
>> #macro(nameCaptureSwap $a $b)
>> $a $b becomes ##
>> #set($tmp = $a)
>> #set($a = $b)
>> #set($b = $tmp)
>> $a $b
>> #end
>> #set($x = 'a')
>> #set($tmp = 'b')
>> #nameCaptureSwap($x $tmp) ->
>> a b becomes a a
>> This is the classic name capture example, which only happens with call
>> by macro expansion.
>>
>>
>>
>> In conclusion, Velocity macros work mostly as call-by-macro expansion
>> internally, with call-by-sharing external behavior, but affected by
>> automatic assignment of global variables when local variables can't be
>> assigned.
>
> Thanks for all of the info.
>
> The fact that we're having this discussion probably means it's time to
> implement a
> security manager so we can run non PR jsr223 script but I'm not sure how to
> prevent
> DoS attacks like vacuuming up the heap or stack overflowing the garbage
> collector.
>
>
> Caleb
>
>>
>>> Sergiu Dumitriu wrote:
>>>> Lots of goodies, but we can't upgrade until we fix the bad usage of
>>>> macros, see https://issues.apache.org/jira/browse/VELOCITY-681
>>>>
>>>> On 05/01/2010 06:20 PM, Vincent Massol wrote:
>>>>> fyi
>>>>>
>>>>> -Vincent
>>>>>
>>>>> Begin forwarded message:
>>>>>
>>>>>> From: Nathan Bubna<[email protected]>
>>>>>> Date: April 28, 2010 12:53:50 AM GMT+02:00
>>>>>> To: Velocity Developers List<[email protected]>, Velocity Users
>>>>>> List<[email protected]>, [email protected]
>>>>>> Subject: [ANNOUNCE] Velocity Engine 1.7-beta1 release available
>>>>>>
>>>>>> The Velocity developers are please to announce the availability of
>>>>>> Velocity Engine 1.7-beta1.
>>>>>>
>>>>>> Downloads can be found here:
>>>>>> http://velocity.apache.org/download.cgi
>>>>>>
>>>>>> A great deal of work has been done since the 1.6 branch. Here's a taste:
>>>>>>
>>>>>> - Your macros can now be called with bodies when you want:
>>>>>> #macro(foo)Here is $bodyContent#end
>>>>>> #...@foo()body content!#end
>>>>>> - Quotes can be escaped in strings by doubling them:
>>>>>> #set( $foo = "$person said, ""$comment"" " )
>>>>>> #set( $bar = 'Joe said, ''Hi!'' ' )
>>>>>> - The flawed #literal directive has been replaced with:
>>>>>> #[[ This is included but not parsed, so #if and $foo need no
>>>>>> escaping.]]#
>>>>>>
>>>>>> Also included are namespacing improvements, better #break and #stop,
>>>>>> bracketed index syntax, and more! For full details, please see the
>>>>>> change log:
>>>>>> http://velocity.apache.org/engine/devel/changes-report.html
>>>>>>
>>>>>> This should work as a drop-in replacement for Velocity 1.6.3 in the
>>>>>> vast majority of cases. However, there have been a number of
>>>>>> deprecations (should result in warnings in your log output) and a few
>>>>>> minor behavioral changes, all of which are explained in the change
>>>>>> log. :)
--
Sergiu Dumitriu
http://purl.org/net/sergiu/
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs