You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Don't use T.untyped (the dynamic type) because it makes type narrowing trivial. No need for is_a? checks or anything when the value is untyped.
Change filter to promise an array of integers. This makes Sorbet fail, which is too bad seems more fair.
rainfall fails unexpectedly now. I'll ask for help in a comment below.
New benchmark results:
$ racket _benchmark.rkt
(Benchmark Sorbet)
(positive O )
(negative O )
(connectives O )
(nesting_body O )
(struct_fields x )
(tuple_elements x )
(tuple_length x )
(alias O )
(nesting_condition O )
(merge_with_union O )
(predicate_2way x )
(predicate_1way x )
(predicate_checked x )
$ racket _benchmark.rkt -e
(Benchmark Sorbet)
(filter x )
(flatten O )
(tree_node x )
(rainfall x )
How would you write a function that takes anything and checks if the value is an integer? Here's pseudocode (from README.md in this repo):
# positive
define f(x: Top) -> Top:
if x is String:
return String.length(x) // type of x is refined to String
else:
return x
Right now in Sorbet, we have this code using Object:
# typed: strict
extend T::Sig
sig { params(x: T.anything).returns(Integer) }
def positive_success_f(x)
if x.is_a?(String)
x.length
else
0
end
end
I'd rather use the Sorbet top type T.anything but it seems too hard to work with. We'd have to do a case statement. By chance, do you know a better way? https://sorbet.org/docs/anything
The error message that I get from running Sorbet makes me think there's something easier, but when I try replacing x.is_a? with x.class.is_a? (which is what I think the error is telling me!), I get another error message:
$ bundle exec srb tc foo.rb
foo.rb:6: Method is_a? does not exist on T.anything https://srb.help/7003
6 | if x.is_a?(String)
^^^^^
Got T.anything originating from:
foo.rb:5:
5 |def positive_success_f(x)
^
There is a singleton class method with the same name:
https://github.com/sorbet/sorbet/tree/06f78f051811eea111f223a5487c733b29a2f890/rbi/core/kernel.rbi#L543: Defined here
543 | def is_a?(arg0); end
^^^^^^^^^^^^^^^
Either:
- use .class to call it, or
- remove self. from its definition to make it an instance method
Autocorrect: Use -a to autocorrect
foo.rb:6: Insert .class
6 | if x.is_a?(String)
^
Errors: 1
Q2
Can you figure out a way to use is_a? to turn an Object into a Hash? Here's what I tried:
# typed: strict
extend T::Sig
## Example rainfall
## success
sig { params(weather_reports: T::Array[Object]).returns(Float) }
def rainfall_success(weather_reports)
total = T.let(0.0, Float)
count = T.let(0, Integer)
weather_reports.each do |day|
if day.is_a?(T::Hash[Symbol, Object]) && !day.nil?
if day.key?(:rainfall)
val = T.let(day[:rainfall], Object)
if val.is_a?(Float) && 0.0 <= val && val <= 999.0
total += val
count += 1
end
end
end
end
count > 0 ? total / count : 0.0
end
The error message suggests that I'm way off base ... but if I change all the Object to T.untyped then the code typechecks so maybe it's not totally crazy to put T::Hash[...] inside an is_a? check? I'm so confused.
foo.rb:11: Expected T::Module[T.anything] but found Runtime object representing type: T::Hash[Symbol, Object] for argument arg0 https://srb.help/7002
11 | if day.is_a?(T::Hash[Symbol, Object]) && !day.nil?
^^^^^^^^^^^^^^^^^^^^^^^
Expected T::Module[T.anything] for argument arg0 of method Kernel#is_a?:
https://github.com/sorbet/sorbet/tree/06f78f051811eea111f223a5487c733b29a2f890/rbi/core/kernel.rbi#L539:
539 | arg0: T::Module[T.anything],
^^^^
Got Runtime object representing type: T::Hash[Symbol, Object] originating from:
foo.rb:11:
11 | if day.is_a?(T::Hash[Symbol, Object]) && !day.nil?
^^^^^^^^^^^^^^^^^^^^^^^
Detailed explanation:
It looks like you're using Sorbet type syntax in a runtime value position.
If you really mean to use types as values, use T::Utils.coerce to hide the type syntax from the type checker.
Otherwise, you're likely using the type system in a way it wasn't meant to be used.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
T.untyped(the dynamic type) because it makes type narrowing trivial. No need foris_a?checks or anything when the value is untyped.filterto promise an array of integers. This makes Sorbet fail, which is too bad seems more fair.rainfallfails unexpectedly now. I'll ask for help in a comment below.New benchmark results: