Skip to content

Add in operator#520

Open
sbundaz wants to merge 9 commits into
spylang:mainfrom
sbundaz:add-in-operator
Open

Add in operator#520
sbundaz wants to merge 9 commits into
spylang:mainfrom
sbundaz:add-in-operator

Conversation

@sbundaz

@sbundaz sbundaz commented May 14, 2026

Copy link
Copy Markdown
Contributor

Issue: #407

This PR adds the in operator.

@sbundaz sbundaz force-pushed the add-in-operator branch from 87a032a to a1bb813 Compare May 22, 2026 06:57
@sbundaz sbundaz marked this pull request as ready for review May 22, 2026 07:26
@JeffersGlass

Copy link
Copy Markdown
Contributor

In general this looks good to me! A few thoughts:

  1. It would be nice to have _dict.__contains__ and _tuple.__contains__ for completeness in the stdlib
  2. A bunch of the string methods got moved to App Level (stdlib/_str.spy) earlier this week. For consistency str.__contains__ may want to move there
  3. There isn't a firm story around Iterator or Iterable yet... in CPython if there's no __contains__ method it falls back to __iter__ (SPy's __fastiter__?) and then __getitem__ if they exist. This is probably overkill for now, but maybe a good extension for later.

@JeffersGlass

Copy link
Copy Markdown
Contributor

After a little more testing, I think you'll need to add some additional traps for non-matching types of generic containers.. For instance, this is currently an error:

def main() -> None:
    x = [1,2,3]
    "1" in x
TypeError: mismatched types
  | /workspaces/spy/a.spy:4
  |     print("1" in x)
  |           |_| expected `i32`, got `str`

  | /workspaces/spy/stdlib/_list.spy:364
  |         def __contains__(self, value: T) -> bool:
  |         |______________________________________| function defined here

  | /workspaces/spy/a.spy:4
  |     print("1" in x)
  |           |______| operator::IN called here

Whereas it probably wants to just return False.

@antocuni

Copy link
Copy Markdown
Member

After a little more testing, I think you'll need to add some additional traps for non-matching types of generic containers.. For instance, this is currently an error:

def main() -> None:
    x = [1,2,3]
    "1" in x
TypeError: mismatched types
  | /workspaces/spy/a.spy:4
  |     print("1" in x)
  |           |_| expected `i32`, got `str`

  | /workspaces/spy/stdlib/_list.spy:364
  |         def __contains__(self, value: T) -> bool:
  |         |______________________________________| function defined here

  | /workspaces/spy/a.spy:4
  |     print("1" in x)
  |           |______| operator::IN called here

Whereas it probably wants to just return False.

I'm happy to be convinced otherwise, but I think this should be an error, unless it's list[object] or list[dynamic].

I made the same choice for e.g. ==: 1 == ”hello" it's a TypeError

@antocuni

Copy link
Copy Markdown
Member

@sbundaz sorry it's taking so long to review, I hope to get to it soon!

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.

3 participants