Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework spec function/expression taxonomy #6505

Merged
merged 3 commits into from
Apr 16, 2018
Merged

Rework spec function/expression taxonomy #6505

merged 3 commits into from
Apr 16, 2018

Conversation

lbud
Copy link
Contributor

@lbud lbud commented Apr 12, 2018

This PR reworks the taxonomy to describe how a property can use functions/expressions, as described in #6389 (comment) and #6389 (comment):

type ExpressionType = 'data-driven' | 'cross-faded' | 'cross-faded-data-driven' | 'color-ramp' | 'data-constant' | 'constant';

type ExpressionParameters = Array<'zoom' | 'feature' | 'heatmap-density' | 'line-progress'>;

type ExpressionSpecification = {
    interpolated: boolean,
    parameters: ExpressionParameters
}

StylePropertySpecification = {
    ...
    'property-type': ExpressionType,
    'expression': ExpressionSpecification
}

so now any property all properties include a property-type key, and for all property-types except constant also an expression property, i.e.

    "type": "number",
    "property-type": "data-driven",
    "expression": {
        "interpolated": true,
        "parameters": [
            "zoom",
            "feature"
        ]
    }

Benchmarks: http://bl.ocks.org/lbud/raw/2ac3b8869074c112802166978cea8345/ (I couldn't reproduce the Layer discrepancies on subsequent isolated bench runs).

Closes #6389
Supersedes / closes #4194
Refs #6430
Refs #6303

Launch Checklist

  • briefly describe the changes in this PR
  • write tests for all new functionality
  • post benchmark scores
  • manually test the debug page

Copy link
Contributor

@anandthakker anandthakker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels so much cleaner ☺️

type ExpressionParameters = Array<'zoom' | 'feature' | 'heatmap-density' | 'line-progress'>;

type ExpressionSpecification = {
type: ExpressionType,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like field is currently called property-type, not type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels slightly weird to me to have property-type nested under expression. Would it make sense to move it up to the layout/paint property specification, and also add constant as one of the options for properties that can't take any expression? E.g.:

"visibility": {
  "property-type": "constant",
  // no "expression" field
  "type": "enum",
   /* ... */
}
"line-cap": {
  "property-type": "data-constant",
  "expression": {
    "interpolated": false,
    "parameters": ["zoom"]
   },
  "type": "enum",
   /* ... */
}

Then we could always use propertySpec["property-type"] and never have to rely on the presence/absence of the "expression" field

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me @anandthakker!

// @flow

export function isPropertyFunction(spec: Object): boolean {
const dataDrivenTypes = new Set(['data-driven', 'cross-faded-data-driven']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can use Set / Map, since they'd require polyfills for IE 😢

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this would have showed up in the style-spec build test, but it's not getting run on CI 😬 #6433


export function isZoomFunction(spec: Object): boolean {
return spec.expression && spec.expression.parameters.indexOf('zoom') > -1;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to isPropertyExpression and isZoomExpression?

@lbud lbud requested a review from anandthakker April 12, 2018 18:32
return `ColorRampProperty`;
case 'data-constant':
default:
return `DataConstantProperty<${flowType(property)}>`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for completeness, should we also list case 'constant': here? (Alternatively, since DataConstantProperty<T> isn't really intended to represent a totally constant property, it could be case 'constant': throw new Error("Constant properties unimplemented");)

return `new ColorRampProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
case 'data-constant':
default:
return `new DataConstantProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@@ -0,0 +1,13 @@
// @flow

export function isPropertyExpression(spec: Object): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isPropertyExpressionsupportsPropertyExpressions -- or something similar that doesn't imply that the function is testing whether the input itself is a property expression. (Similarly for isZoomExpression and isInterpolated.)

Also, can spec be typed as StylePropertySpecification?

@@ -236,8 +236,8 @@ function appendStopPair(curve, input, output, isStep) {
function getFunctionType(parameters, propertySpec) {
if (parameters.type) {
return parameters.type;
} else if (propertySpec.function) {
return propertySpec.function === 'interpolated' ? 'exponential' : 'interval';
} else if (propertySpec.expression) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be asserting propertySpec.expression? We shouldn't be trying to create a function for something that doesn't support expressions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 this was a bad workaround for a flow error — will fix.

@lbud lbud merged commit 77b9821 into master Apr 16, 2018
@lbud lbud deleted the expression-spec branch April 16, 2018 21:47
lbud pushed a commit that referenced this pull request Apr 16, 2018
@lbud lbud restored the expression-spec branch April 16, 2018 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants