Is there exists a Dart dynamic type equivalent for Crystal? (Or, equivalent usage)

Let me describe my usage scenario.

When port a big (code is not familiar) Ruby gem into Crystal, a rather annoying thing is that, hundreds of empty {} and , It’s hard to figure out the real type is if just take a quick look, But no type in empty , {} is syntax error, quite annoying.

Same things happen on Dart, but, dart handle this use a special dynamic type can be used replace any type., when user user it, user is responsible for the null safety, but code is working, without error, the downside is some editor autocomplete missing.

so, is there exist a type can be used to as this role?

e.g. i can replace all occur of x = [] into x = [] of Dynamic, y = {} into y = {} of Dynamic => Dynamic to workaround the syntax error, then i will replace Dynamic into the really type smoothly.

thanks.

Hi! There’s no such thing in Crystal, and likely will never be.

Hi, @asterite any better advice for use a special type as the default placeholder?

what i means is, a type that is rarely used directly by users(rarely appears in errors backtrace), i can replace {} with: {} of RareType => RareType use port_ruby_to_crystal tool.

then, when this type show in the error message, i can know i set a wrong type as placeholder.

anyway, this is a intermediate step for avoid the syntax error of empty hash/array in Ruby, less friction.

Wouldn’t it be better for this use case to just leave the untyped hash literal? Then the compiler’s syntax error directly points you to where you need to manually give some type information.

Then the compiler’s syntax error directly points you to where you need to manually give some type information.

You are right, but, syntax error often hides many other more specific errors, e.g. the type inference never work. this is a mutually exclusive issue.

  1. I need type inference to teach me, type of those empty hash/array should be.
  2. empty hash/array syntax error, make type inference not work.

Maybe you can define a module and then you se that as a type? I don’t think I understand what you are trying to do.

I just want a builtin Type, e.g. used by compiler, almost never used directly by users, as a empty array/hash’s default type, then, once the code has no syntax errors, i can use type inference to guess the correct type, then replace it back.

I guess you can do this?

class BlackHole
  macro method_missing(call)
    raise "BUG: must implement {{call.name}}"
  end
end

array = BlackHole.new
array << 1
array << "hello"
puts array.size
array.each do |x|
  puts x
end

Such type will never make it to the standard library, though.

2 Likes

I probably still explain my thought clearly, sorry, maybe this just an unreasonable demand?

I really want to do is, when i am porting a big ruby gem, replace all ary = [], h = {} with ary = [] of SomeType, h = {} of SomeType => SomeType use a tools, after then, when i run replaced ruby code use crystal, no syntax anymore, instead of, only compiler error left, which can lead me to find the correct type of the ary and h.

So, here, when i am replaceing code, the SomeType is important, It must be a valid builtin Crystal Type, but, rarely used by the user directly, which give a sign like this when build the code, like this:

Oops, then i will know, i should replace

arry = [] of SomeType

into

arry = [] of Procodile::Instance.

If i am not add this Intermediate step instead, only give me syntax like: Error: for empty arrays use '[] of ElementType', without any additional help for figure out what arry type is.

There doesn’t exist any one for all kind of type in Crystal. For porting projects, one should first have a better understanding of code before starting the port process, in that way one will know before hand what kind of objects are going to be stored in those containers.

2nd for your use case you can always start with union types of some general types which you believe are quite normal in that gem which you are porting, and once done with migration you can restrict that type to be something more specific or concise.

alias SomeType = String | Int32 | Float64 | Nil | MyAweSomeType

arr = [] of SomeType
hsh = {} of SomeType => SomeType

.......

HIH

1 Like

Why do you think it must be a builtin?

What wouldn’t work with the BlackHole class from Is there exists a Dart dynamic type equivalent for Crystal? (Or, equivalent usage) - #8 by asterite ?

Why do you think it must be a builtin?

I want do replace use a scripts, and without have to add a new type into the code.

but i consider asterite solution are the right way now, use a Type like BlackHole much better than any other built type.