Skip to content

Conversation

@maxg-square
Copy link
Contributor

@maxg-square maxg-square commented Jul 16, 2025

1/3 for caching changes.
Big-picture PR here: #587
Design doc: https://docs.google.com/document/d/1CLhFbzZGbEKgvZTUwLuGbFY-rfZNJVTi6f3PkoZT9qI/edit?usp=sharing

This PR adds a ContextualEquivalency protocols and conformances. This is basically like a lightweight Equatable, which adds the ability to interrogate objects with the notion of a context.

@maxg-square maxg-square marked this pull request as ready for review July 25, 2025 16:32
@maxg-square maxg-square requested a review from a team as a code owner July 25, 2025 16:32
@maxg-square maxg-square changed the title Add equivalency protocols and implementations Add equivalency protocols and implementations (1/3) Jul 25, 2025
* main:
  Bump macOS, Xcode, Swift, and Tuist versions. (#580)
  chore: release 6.1.0
  Fix AccessibilityContainer behaviour when it contains a UICollectionView or UITableView
  Ignoring slight keyboard overlaps in ScrollView (#575)
Comment on lines -43 to 46

private var values: [ObjectIdentifier: Any] = [:]
private var values: [Keybox: Any] = [:]

private var internalValues: [ObjectIdentifier: Any] = [:]

Copy link
Contributor

Choose a reason for hiding this comment

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

The spec doc does a nice job outlining that internal key/values are "hidden from consumers and not considered in equivalency checks." Do you think we could carry that into docs here, to outline the differences between these two dictionaries?

* main:
  Release 6.3.0
  Assert in debug mode when large content viewer is not placed inside an interaction container
  Expose largeContentViewerInteraction on LargeContentViewer backing view via protocol
  Stopped installing xcodes in GitHub Actions file
  chore: Release 6.2.0
  Support accessibility large content viewer
Copy link
Collaborator

@watt watt left a comment

Choose a reason for hiding this comment

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

A few minor things, left you tasks for the important bits.

case elementSizing
}

public protocol ContextuallyEquivalent {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A few minor things:

  • you've got this in Internal but it's public

  • strong preference from me to have 1:1 files to types if possible rather than Equivalency.swift. Make a folder named Equivalency if the grouping is important.

  • naming-wise ContextuallyEquivalent is pretty generic for something that's still very Blueprint specific. I'll float something like ElementContextComparable as an alternative.

  • find a new name for ContextuallyEquivalent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's slightly more broad than element-specific (includes env values too) and I think comparable has a connotation of being sortable given the stl usage of it – maybe something like CacheEquivalent? Or could just go the other way and be less concretely tied to that specific method it requires and be something more tied to purpose like CrossLayoutCacheable?

Copy link
Contributor

@soroushsq soroushsq Oct 21, 2025

Choose a reason for hiding this comment

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

Some ideas that max and I had:

MultipassLayoutEquivalent, LayoutContextuallyEquivalent.

We also considered flipping polarity of function, so it can't be easily confused with Equatable or Comparable. In that world, instead of asking if the two objects are functionally equivalent, you would ask if one object invalidates another compared to the previous version.

func invalidatesLayout(from previous: Self?, in context: LayoutCacheContext) -> Bool

For that, we had protocol name ideas of LayoutDependency and LayoutInvalidatingDependency.

Copy link
Collaborator

Choose a reason for hiding this comment

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

For me, Equivalent is out for the same reason as Comparable (connotations of more generic concepts).

I like CrossLayoutCacheable, or anything similar with the Cacheable suffix, since that really dials in on the distinct purpose here.

"Dependency" and "invalidates" both kind of muddy the waters for me. In the status quo, everything invalidates layout.

/// - rhs: The right hand side value being compared.
/// - context: The context to evaluate the equivalency.
/// - Returns: Whether or not the two values are equivalent in the specified context.
static func isEquivalent(lhs: Value, rhs: Value, in context: EquivalencyContext) -> Bool
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this is required I think there should be a default implementation returning false.

  • default impl on isEquivalent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discused offline earlier but feel pretty strongly we shouldn't have that – there's default implementations when values are equatable and also convenience implementations like this that are one-liners https://github.com/square/Blueprint/pull/568/files#diff-e664d2d763ebe3ca35c985ddc39c338eff03d90a5dd5f6d90091b7612d02ce4aR55 but IMO new environmentkeys should be forced to consider this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants