RhinoTrac
LassoSoft Ticket Tracking System
NOTE: If you are using Lasso Server 9.3 please Log your ticket directly via the LUX admin as this will give us more information about your issue.
Ticket #7945: multiple dispatch no longer works as expected
- Reported by:
- Ke Carlton
- Date:
- 28 Jan, 2015
- Priority:
- critical
- Component:
- Lasso 9
- Version:
- 9.3
- Keywords:
- Platform:
- All Platforms
Issue reported by Ke Carlton (ke@zeroloop.com)
Company: Zeroloop Limited
Component: Lasso 9 Server
Version: 9.3
Platform: All Platforms
Source IP: 121.99.59.203
Detail
======
define dispatchtest(p::trait_keyedforeach) => 'trait_keyedforeach';
define dispatchtest(p::trait_foreach) => 'trait_foreach';
dispatchtest(map)
// 9.2.7 = trait_keyedforeach
// 9.3 = trait_foreach
This silently breaks lots of stuff as keyed data elements must be iterated differently to get each pair...
Please log in to your LassoSoft account to comment
Comments
// Maps need to be processed difference
define datatosave(p::trait_keyedforeach) => #p->eachpair->asstaticarray
define datatosave(p::trait_foreach) => #p->asstaticarray
// Call the methods
datatosave(array('column1' = 'value1', 'column2' = 'value2'))
datatosave(map('column1' = 'value1', 'column2' = 'value2'))
// Lasso 9.2.7 Results
staticarray((column1 = value1), (column2 = value2))
staticarray((column1 = value1), (column2 = value2))
// Lasso 9.3 Results
staticarray((column1 = value1), (column2 = value2))
staticarray(value1, value2) // BROKEN!
It appears as though the dispatch logic has changed from 9.2.7 to 9.3 and this is likely to break a lot of system / libraries using multiple dispatch — one of Lasso 9's core / best features.
Happy to answer any other questions.
<?LassoScript
local("foo");
local("bar");
#foo = array;
"'#foo = array;<br/>'";
"'#foo->isa("trait_keyedforeach")' --> '" + #foo->isa("trait_keyedforeach") + "'<br/>";
"'#foo->isa("trait_foreach")' --> '" + #foo->isa("trait_foreach") + "'<br/>";
#bar = map;
"'#bar = map;<br/>'";
"'#bar->isa("trait_keyedforeach")' --> '" + #bar->isa("trait_keyedforeach") + "'<br/>";
"'#bar->isa("trait_foreach")' --> '" + #bar->isa("trait_foreach") + "'<br/>";
?>
This results in the following output:
#foo = array;
'#foo->isa(trait_keyedForEach)' --> '0'
'#foo->isa(trait_foreach)' --> '2'
#bar = map;
'#bar->isa(trait_keyedForEach)' --> '2'
'#bar->isa(trait_foreach)' --> '2'
We can see that a 'map' has both traits. Given that, which of your 'datatosave' definitions should be called? In Lasso 9.3, the answer is, "Whichever was defined most recently."
The code-example you've kindly shared relies on undefined behaviour and the question of the previous paragraph applies. It's unfortunate if many systems and libraries rely on the same undefined behaviour, but LassoSoft's current perspective is that such reliance is a mistake and the language itself ought not to be adjusted to support that mistake. In fact, this particular change in behaviour between 9.2.7 and 9.3 actually provides an improvement by allowing Lasso developers to identify these instances of undefined behaviour in their code.
define datatosave(p::trait_foreach) => datatosave_dispatch(#p);
define datatosave_dispatch(p) => {
/* You choose the order */
#p->isa("trait_keyedforeach") ? return datatosave_keyedforeach(#p);
#p->isa("trait_foreach") ? return datatosave_foreach(#p);
}
define datatosave_keyedforeach(p::trait_keyedforeach) => #p->eachpair->asstaticarray;
define datatosave_foreach(p::trait_foreach) => #p->asstaticarray;
datatosave(array("column1" = "value1", "column2" = "value2"));
datatosave(map("column1" = "value1", "column2" = "value2"));
So is it locked down that when there are multiple matches Lasso will consistently use the most recent definition?
In case any one else is affective by this I worked round it by using the following signatures:
define datatosave(p::trait_keyedforeach) => #p->eachpair->asstaticarray
define datatosave(p::trait_positionallykeyed) => #p->asstaticarray
This approach yields consistent behaviour in both 9.2 and 9.3
It seems to be back to the old broken behavior for 9.3.1