Lasso Soft Inc. > Home

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.

Lasso 9 Issues



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...

Comments

31 Mar, 2015 by Steffan Cline
This is a critical issue which has broken DS for me entirely. I can't even use it at this point. This bug has been sitting for some time now and needs to be addressed.
31 Mar, 2015 by Shao Miller
Would it be possible to clarify what the issue is, here? Reading the detail, there is code, but not expected/desired observations versus actual observations.
31 Mar, 2015 by Ke Carlton
Sure, the reason why it breaks things is that the entire point of multiple dispatch is to process different data types according. With 9.3 it's routing data types differently. Here is an example of how it breaks stuff:

// 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.
03 Apr, 2015 by Shao Miller
This is the result of a fix, in Lasso 9.3. Lasso 9.2.7 allowed for ambiguity in this situation while Lasso 9.3 does not. Please consider the following code:

<?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.
03 Apr, 2015 by smiller
I'd recommend:
define datatosave(p::trait_keyedforeach) => datatosave_dispatch(#p);
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"));
20 Apr, 2015 by Ke Carlton
I agree less ambiguity is an improvement — but it should be mentioned somewhere, for example this mentions nothing about it: http://www.lassosoft.com/Lasso-9-3-release-notes — this type of change breaks stuff.

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

20 Apr, 2015 by Ke Carlton
@smiller, that approach pretty much defeats the entire point of multiple dispatch...
20 Jul, 2015 by Kyle Jessup
I reverted the fix so that this bug can once again exist.
It seems to be back to the old broken behavior for 9.3.1
Please log in to your LassoSoft account to comment

LassoSoft Inc. > Home

 

 

©LassoSoft Inc 2015 | Web Development by Treefrog Inc | PrivacyLegal terms and Shipping | Contact LassoSoft