Passing String parameters

Hi there, I’m trying to pass a String to my function

foo (s::A, n::N=2) where {A<:Union{String,Vector{String}}, N <: Number}

I’m calling the function as so foo(“test”) and am receiving the error

MethodError: Cannot convert an object of type Char to an object of type String

I’m a little lost on how I am using a Char here? Any help would be great, cheers Jamie

You are not using it in the function signature, that is for sure. That should work:

julia> foo(s::A, n::N=2) where {A<:Union{String,Vector{String}}, N <: Number} = s
foo (generic function with 2 methods)

julia> foo("test")
"test"

Thus, the problem is somewhere else. It is better if you post a snippet of code in which the error can be reproduced (in a fresh Julia section).

ps. Use the </> icon to write code within backticks, it becomes properly formatted.

Thanks for the response. Hmm I have pasted the code below but after some more tests I have found that if I run function from in the file it works as intended. It is only once the module is imported that the error begins. Not sure how this would effect my parameters though.

module Longurl
export expand_urls

using HTTP

"""
    Urls(expanded_url, status_code)
"""
struct Urls
    expanded_url::Vector{Union{String, Nothing}}
    status_code::Vector{Union{String, Nothing}}
end

"""
Takes a list of short urls and expands them into their long form

...
# Arguments
- `urls_to_expand::Array`: the list of short urls
- `seconds::Int64`: the timeout in seconds
# Returns
- `Urls`: Struct containing properties expanded_url and status_code
...
"""
function expand_urls(urls_to_expand::A, seconds::N=2) where {A<:Union{String,Vector{String}}, N <: Number} 

    if urls_to_expand isa String
        urls_to_expand = [urls_to_expand]
    end
    
    original_stdout = stdout
    original_error = stderr

    short_urls = Vector{Union{String, Nothing}}(nothing, length(urls_to_expand))
    expanded_urls = Vector{Union{String, Nothing}}(nothing, length(urls_to_expand))
    status_codes = Vector{Union{String, Nothing}}(nothing, length(urls_to_expand))

    i = 0
    for url in urls_to_expand
        i += 1
        last_head = nothing
        last_host = nothing
        last_code = nothing
        (rd, wr) = redirect_stdout()

        try
            HTTP.head(url, readtimeout=seconds, verbose=2, retry=false)
        catch e
            print(e)
        finally
            redirect_stdout(original_stdout)
            close(wr)  
            for line in readlines(rd)
                if occursin("HEAD", line)
                    last_head = split(line, " ")[2]
                end
                if occursin("Host", line)
                    last_host = split(line, " ")[2]
                end
                if occursin("HTTP/1.1 ", line)
                    last_code = split(line, " ")[2]
                end
            end
            short_urls[i] = url
            status_codes[i] = last_code
            expanded_urls[i] = last_host * last_head
        end
    end 
    
    long_urls = Urls(expanded_urls, status_codes)

    return long_urls

end

end

I could not reproduce the error you report here. If you provided a minimal (non-)working example, it will be easier to help.

I have the module on github which includes the code I posted above.

I have attached an image that shows the error I am getting when importing this module. Cheers again I really appreciate this.

If you are getting Char, I suspect you are iterating through a String.

perhaps you want

expand_urls(["http://www.google.com"])

to iterate through an array

Aha that makes sense! However I have now added a check to make sure if it is in fact a string it gets converted to a vector containing said string but I still seem to be getting the problem.

EDIT: I have figured out this problem is more down to my misunderstanding of the Julia package system. Thanks for all the help, it seems that whenever I called Pkg.add and using it was using an old version of the package even if I activated the environment with the new package. I went through and removed the old package files from my .julia and re added them and the issue was gone.

This sort of design isn’t normally ideal. I wouldn’t write the function to accept both strings and vectors of strings. It’s cleaner and less error prone to write your function to accept strings, and then iterate outside your expand_urls function (and call it expand_url), using for example broadcasting.

And then consider defining your Urls struct to only accept scalars and create a vector of Urls, instead of holding the vectors inside a single object.

I think this would be a lot cleaner.

5 Likes

I think the easiest way to avoid that kind of problem is to go to the directory of the package and start Julia with

julia --project
1 Like