Why does `strip` function return a SubString instead of a String? Can one return a String type from `strip`?

I was experiencing a strange error in my code (strange because of my fault of not reading the return type of the strip function). strip returns a SubString instead of a String type and this was throwing error when using Bcrypt.CompareHashAndPassword. Is the recommended way to strip and then use string() function to convert it back to String type.

1 Like
  1. The reason why strip returns SubString is to reduce allocations.
  2. Yes, unfortunately currently you need to cast SubString to String manually in your case.
  3. In general the issue is that the Bcrypt.jl has an overly strict method signature. It is typically not recommended to require String as function argument. Usually AbstractString should be used.
4 Likes

I’m not sure it’s recommended in general, you can do a lot without converting to a String, e.g. println(strip(" Hello "), " Palli") # there , is better then *, since the latter, for concatenation, will make an actual String which is slower, and not needed.

Note, only the third version here works:

julia> p1(str::String) = println(str)
julia> p2(str::AbstractString) = println(str)
julia> p3(str::Union{AbstractString, SubString}) = println(str)
julia> p3(strip(" Palli "))
Palli

You don’t need to add types to any function definitions, it doesn’t help with speed, though can help with documentation readability? At least if you do, then using String is almost always a mistake, since there are other type of string types (in packages), and you want to be general. I thought AbstractString was better and sufficient, but it isn’t in this base, since SubString isn’t a subtype of it. Should/could it be?

Thank you. I will open an issue in Bcrypt.jl repo. Although, in general, is it better to use AbstractString or leave the type unspecified. I believe I heard in one of the talks that use of abstract types prevent JIT compiler from optimizing the code relative to specifying concrete types. Is this true? Thank you for explaining.

Code is specialized in runtime, because it is compiled during runtime, just before a call happens, taking in consideration the concrete type of the arguments in runtime (independent of how restrictive or lax the type parameters statically defined) so I fell like this is wrong. But your question is very vague, if you are talking about structs with abstract fields, yes, it may impact performance, if you are talking about function signatures, no, probably not.

Thank you. I think it was in the context of structs with abstract fields. But, as you correctly point out, I am being kind of vague. I tried to find where I heard it, but could not do so yet. But it is good to know that in function signatures using an AbstractType does not create specific ineffciencies.

1 Like