map?get(nonStringKey) for FM 2.3.x?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

map?get(nonStringKey) for FM 2.3.x?

Daniel Dekany
FTL has this annoying problem that it has no type that corresponds to
Java's Map. It has a type called hash, but it was introduced for
variable hierarchies (like `user.name`), so the keys are limited to
stings. For some reason TemplateMapModel wasn't introduced, instead,
the bundled wrappers wrap Map-s as hashes, which of course doesn't
work for non-string keys. Except, if you call the Map.get method
directly from the template, but since FTL doesn't use separate
name-spaces for plain sub-variables and methods, if Map methods are
exposed, they mix with the actual string keys, which is a mess, so by
default Map methods are hidden. Luckily, with BeansWrapper, you can
just do `someMap(nonStringKey)`, but sadly, BeansWrapper is not used
by default for wrapping Map-s, they are wrapped into a SimpleHash
instead.

So the user asks how to get an item from this map with a non-String
key, and we don't have a simple answer. You need to use BeansWrapper
instead of the default... oh, but wait, switching wrapper might breaks
your application, and depending on the framework there's possibly no
way to set the object wrapper at all. How to fix this situation:

- Ultimately, add TemplateMapModel, and a new recommended
  ObjectWrapper that uses it too. Unfortunately, this is not an option
  for existing applications and frameworks, unless they willing to
  review their templates.

- SimpleHash should implement TemplateMethodModelEx, so
  `someMap(nonStringKey)` works for SimpleHash-wrapped templates too.
  My problem with this is that calling a map like a method is quite
  confusing for most programmers. You look at the template, and
  believe that "someMap" is primarily a function. But it's a Map.
  Also adding TemplateMethodModelEx to SimpleHash can break existing
  applications with a small chance.

- Add `get` as built-in, which will utilize its knowledge of the
  bundled wrappers to get to the Map behind. No mater how "someMap"
  was wrapped, if there's a Map behind, `someMap?get(key)` just works.
  If the wrapper is not recognized, nor AdapterTemplateModel is
  implemented, it can still call TemplateHashModel.get(String) and give
  an error for a non-String key.

--
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
FreeMarker-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-devel
Reply | Threaded
Open this post in threaded view
|

Re: map?get(nonStringKey) for FM 2.3.x?

Denis Bredelet
Hi Daniel,

> FTL has this annoying problem that it has no type that corresponds to
> Java's Map. It has a type called hash, but it was introduced for
> variable hierarchies (like `user.name`), so the keys are limited to
> stings. For some reason TemplateMapModel wasn't introduced, instead,
> the bundled wrappers wrap Map-s as hashes, which of course doesn't
> work for non-string keys. Except, if you call the Map.get method
> directly from the template, but since FTL doesn't use separate
> name-spaces for plain sub-variables and methods, if Map methods are
> exposed, they mix with the actual string keys, which is a mess, so by
> default Map methods are hidden. Luckily, with BeansWrapper, you can
> just do `someMap(nonStringKey)`, but sadly, BeansWrapper is not used
> by default for wrapping Map-s, they are wrapped into a SimpleHash
> instead.

What is wrong with Beans Wrapper approach?

>
> So the user asks how to get an item from this map with a non-String
> key, and we don't have a simple answer. You need to use BeansWrapper
> instead of the default... oh, but wait, switching wrapper might breaks
> your application, and depending on the framework there's possibly no
> way to set the object wrapper at all. How to fix this situation:
>
> - Ultimately, add TemplateMapModel, and a new recommended
>  ObjectWrapper that uses it too. Unfortunately, this is not an option
>  for existing applications and frameworks, unless they willing to
>  review their templates.
>
> - SimpleHash should implement TemplateMethodModelEx, so
>  `someMap(nonStringKey)` works for SimpleHash-wrapped templates too.
>  My problem with this is that calling a map like a method is quite
>  confusing for most programmers. You look at the template, and
>  believe that "someMap" is primarily a function. But it's a Map.
>  Also adding TemplateMethodModelEx to SimpleHash can break existing
>  applications with a small chance.

I want to see a concrete demonstration of the problems with this solution. Personally I think it would work well.

How is it confusing? What does it break?

Thanks,
-- Denis.

>
> - Add `get` as built-in, which will utilize its knowledge of the
>  bundled wrappers to get to the Map behind. No mater how "someMap"
>  was wrapped, if there's a Map behind, `someMap?get(key)` just works.
>  If the wrapper is not recognized, nor AdapterTemplateModel is
>  implemented, it can still call TemplateHashModel.get(String) and give
>  an error for a non-String key.
>
> --
> Best regards,
> Daniel Dekany


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
FreeMarker-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-devel
Reply | Threaded
Open this post in threaded view
|

Re: map?get(nonStringKey) for FM 2.3.x?

Daniel Dekany
Friday, August 10, 2012, 2:54:29 PM, Denis Bredelet wrote:

> Hi Daniel,
>
>> FTL has this annoying problem that it has no type that corresponds to
>> Java's Map. It has a type called hash, but it was introduced for
>> variable hierarchies (like `user.name`), so the keys are limited to
>> stings. For some reason TemplateMapModel wasn't introduced, instead,
>> the bundled wrappers wrap Map-s as hashes, which of course doesn't
>> work for non-string keys. Except, if you call the Map.get method
>> directly from the template, but since FTL doesn't use separate
>> name-spaces for plain sub-variables and methods, if Map methods are
>> exposed, they mix with the actual string keys, which is a mess, so by
>> default Map methods are hidden. Luckily, with BeansWrapper, you can
>> just do `someMap(nonStringKey)`, but sadly, BeansWrapper is not used
>> by default for wrapping Map-s, they are wrapped into a SimpleHash
>> instead.
>
> What is wrong with Beans Wrapper approach?

One problem is that the default object wrapper doesn't use it for
wrapping maps, so I can't just tell users (in the FAQ for example) to
write `map(key)` instead of `map[key]`.

Another problem is that if the users sees `foo(bar)` in a template, he
will not think that `foo` is a map, and that you have just get a value
from it. I won't either. It doesn't look like that. (Plus, most Java
programmers didn't even heard about first-class functions, which makes
this even stranger for them.)

>> So the user asks how to get an item from this map with a non-String
>> key, and we don't have a simple answer. You need to use BeansWrapper
>> instead of the default... oh, but wait, switching wrapper might breaks
>> your application, and depending on the framework there's possibly no
>> way to set the object wrapper at all. How to fix this situation:
>>
>> - Ultimately, add TemplateMapModel, and a new recommended
>>  ObjectWrapper that uses it too. Unfortunately, this is not an option
>>  for existing applications and frameworks, unless they willing to
>>  review their templates.
>>
>> - SimpleHash should implement TemplateMethodModelEx, so
>>  `someMap(nonStringKey)` works for SimpleHash-wrapped templates too.
>>  My problem with this is that calling a map like a method is quite
>>  confusing for most programmers. You look at the template, and
>>  believe that "someMap" is primarily a function. But it's a Map.
>>  Also adding TemplateMethodModelEx to SimpleHash can break existing
>>  applications with a small chance.
>
> I want to see a concrete demonstration of the problems with this
> solution. Personally I think it would work well.
>
> How is it confusing?

See earlier. Compare it with `foo?get(bar)`. In the second case it's
easier to see what's going on. It's almost `foo.get(bar)` after all.

> What does it break?

Previously the wrapped map didn't implement TemplateMethodModelEx. So
if something checks that before checking for TemplateHashModel, the
code will go on a different path.

> Thanks,
> -- Denis.
>
>>
>> - Add `get` as built-in, which will utilize its knowledge of the
>>  bundled wrappers to get to the Map behind. No mater how "someMap"
>>  was wrapped, if there's a Map behind, `someMap?get(key)` just works.
>>  If the wrapper is not recognized, nor AdapterTemplateModel is
>>  implemented, it can still call TemplateHashModel.get(String) and give
>>  an error for a non-String key.
>>
>> --
>> Best regards,
>> Daniel Dekany

--
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
FreeMarker-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-devel