Is there an equivalent of Haskell's fromMaybe?

Is there a Julia equivalent of (or well worn idiom for) Haskell’s fromMaybe, e.g., for use with Union{T, Nothing}?

something seems to be it:

help?> something
search: something @something

  something(x...)

  Return the first value in the arguments which is not equal to nothing, if any. Otherwise throw an error. Arguments of type Some are
  unwrapped.

Is it the case though that something(x, y, ...) evaluates y even if x is not nothing?

something is a function like any other; Julia is not lazy like Haskell. Arguments are evaluated first.

(types of arguments are also not part of the type of a function)

Yeah sorry that was a dumb question. I hadn’t realized that. (But ugh!)

There’s the macro @something for that.

Note that @something is an AST transform (commonly known as a macro), not a function:

julia> @macroexpand @something a b    
:(something(let val                   
          #= some.jl:143 =#           
          if (val = a) !== nothing    
              val                     
          else                        
              if (val = b) !== nothing
                  val                 
              else                    
                  nothing             
              end                     
          end                         
      end))                           

This works because all expressions return their last value (in this case a, b or nothing as a fallback).

Is Maybe.jl widely used? I’m new and don’t want to gum things up trying to make Julia something (see what I did there) that it isn’t. Better to deal with its idioms.

According to JuliaHub, Maybe.jl has 0 Dependents, so I’d say no.

Usually, nothing and missing values are handled immediately instead of deferred to a later point in time. Maybe you can tell us more about what you want to code up and we can suggest some way of achieving it?

@something was merged into Base. So it’s definitely idiomatic.

I can’t figure out how to invoke @something. I’ve tried @something(...) and Base.@something(...).

Just like in the @macroexpand call I’ve used above:

julia> a = 1                                    
1                                               
                                                
julia> b = nothing                              
                                                
julia> @something a b                           
1                                               
                                                
julia> @something b a                           
1                                               
                                                
julia> @something b b                           
ERROR: ArgumentError: No value arguments present
Stacktrace:                                     
 [1] something()                                
   @ Base ./some.jl:99                          
 [2] something(::Nothing)                       
   @ Base ./some.jl:100                         
 [3] top-level scope                            
   @ some.jl:143                                

Ah my bad! @something was a very recent addition, and is not in the LTS version (or 1.6 I think).

You are right that something(...) evaluates it’s arguments.

To emulate @something, i.e. have fromMaybe which isn’t eager, you can use the if...else pattern shown above.

Yes, the @something macro will be available from 1.7 onwards.

Use the something function in combination with the Some type.

Right now, just test driving the language. To actually do what I want to do it’s probably simpler (and clearer) to just do something like:

    if haskey(things, n)
        return things[n]
    else
       return a_new_thing
    end

rather than

    @something( get(things, n, nothing), a_new_thing )

In practice making a_new_thing has some setup so the former makes sense anyway unless I use let.

For reference the equivalent Haskell that inspired the question is something like

get_thing n = fromMaybe (Thing n part_1 part_2) (M.lookup n things)
    where
        part_1 = a_bunch_of_stuff_that_doest_fit_above
        part_2 = more_stuff_that_doest_fit_above

Sounds like you want to skip the nothing and use get! or get directly:

 get!(f::Function, collection, key)                                                                                   
                                                                                                                      
 Return the value stored for the given key, or if no mapping for the key is present, store key => f(), and return f().

Usage:

julia> d = Dict()                                         
Dict{Any, Any}()                                          
                                                          
julia> get!(() -> begin println("hello"); 1 end, d, "key")
hello                                                     
1                                                         
                                                          
julia> get!(() -> begin println("hello"); 1 end, d, "key")
1                                                         
                                                          
julia> d                                                  
Dict{Any, Any} with 1 entry:                              
  "key" => 1                                              

By the way, this kind of docstring can be easily accessed by using the REPL help mode, invoked by entering ? at the REPL prompt.

That’s good, except I don’t want to store the generated one.

You can do that with get (no exclamation mark):

julia> d = Dict()                                        
Dict{Any, Any}()                                         
                                                         
julia> get(() -> begin println("hello"); 1 end, d, "key")
hello                                                    
1                                                        
                                                         
julia> get(() -> begin println("hello"); 1 end, d, "key")
hello                                                    
1                                                        
                                                         
julia> d                                                 
Dict{Any, Any}()                                         
                                                         
julia> d["key"] = 44                                     
44                                                       
                                                         
julia> get(() -> begin println("hello"); 1 end, d, "key")
44                                                       

It’s a convention (not enforced by the compiler) that functions that modify one or more of their arguments end in a !. There’s no auto generation of such modifying functions, but most of the time when one version exists, the other does as well.