Julia protips

If your functions are long, you’re doing it wrong*.

*probably (I didn’t want to spoil the meter)

5 Likes

#=
    Good practice is a matter of practicing good approaches,
       enacting effective strategies, as you learn them
       and applying one's own insight to their application.
=#


#=
    This is a service routine; usually these go at the end of a file.
    Its here so some explaination is available before you see it used.
=#

#=
    Usually, string interpolation "this value: $value" is to be avoided:
    it is very inefficient, use string("this value: ", value) instead.
    With error messages, as the computational flow is to be abrogated,
    the extra time required of interpolation is immaterial, and using
    string interpolation makes it easier for others to see the sort
    of message you intend by scanning the program source text.

    The way this function is written, it works properly given a string
    or given small strings and other values, e.g. numeric variables.

    `domainerror("this is the message")`

    `domainerror("the argument (", value, " ) is invalid")
=#
function domainerror(xs...)
    str = string(xs...,)
    throw(DomainError(str))   # throw errors, its better long term
end


#=
    We are defining two `structs`.

    - one is our representative carrier of Ordinals
    - one is our representative carrier of Cardinals

    Our treatment of Ordinal and Cardinal numbers
       is appropriate for elementary school.

    The design principles and and select coding patterns
       are used for one just as for the other.
 =#

"""
    Ordinal

Ordinal numbers are "whole numbers" when used to sequence things.

The ordinal number corresponding to ⟨ 1⟩ is first (1st).
The ordinal number corresponding to ⟨80⟩ is eightith (80th).
"""
struct Ordinal
    value::Int

    function Ordinal(value::Int)
        value < 1 && domainerror("!( $value > 0 )")      # guard the domain
        return new(value)
    end
end

# define a quality by creating a predicate (use multidispatch)
isordinal(x) = false                    # catch every falsity
isordinal(x::Ordinal) = true            # select only for truth

"""
    Cardinal

Cardinal numbers are "whole numbers" when used to count things.

The cardinal number corresponding to ⟨ 1⟩ is one (1 thing).
The cardinal number corresponding to ⟨80⟩ is eighty (80 things).
"""
struct Cardinal
    value::Int

    function Cardinal(value::Int)
        value < 0 && domainerror( "!( $value >= 0 )" )    # guard the domain
        return new(value)
    end
end

# define a quality by creating a predicate (use multidispatch)
iscardinal(x) = false                   # catch every falsity
iscardinal(x::Cardinal) = true          # select only for truth


#=
    In this sandbox, the usual Ints (1,10, 512)
    are considered computational entities, and
    neither are they Ordinals nor Cardinals.

    The Ordinals and the Cardinals are each
    distinguished and constructed purposefully.
      <here, their purpose is to exemplify>
=#
2 Likes

Could you write it more beginner friendly?

edited

Simple benchmark and profiler - just use approprate macro and jump through the calls.

However, if you are not familiar with common packages functionality, you may waste some time searching the function needed. In OO languages you can simply look for methods in a pop-up list when you type a dot after an object. For now I don’t know how to do similar thing in Atom/Juno - there are pop-ups only for method names, not for the first argument type.

Cool. Couldn’t we use for example Val{true} instead of Gate? If it has no penalties it could be more friendly to namespace…

What is the advantage over

struct PositiveInt
    value::Int

   function PositiveInt(x::Integer)
        if x <= 0
            throw(DomainError(string( "a positive value is required, (x =  ",x,")")))
        end
        return new(x)
   end    
end
2 Likes

See methodswith and similar.

Nice idea. :slight_smile:

It could be doable if you could for example

"a" |> <press tab here>

And in popup get for example:

   Base.:^(_, n::Integer)  # Repeat a string n times

There is a problem though that methodswith could return veeeeeeery long list (especially if you use supertypes=true). Multiple dispatch has not only advantages.

What do you mean with similar to methodswith?

Or maybe you have pro tip how to find similar to something?

https://docs.julialang.org/en/stable/stdlib/InteractiveUtils/

These complement the functionality nicely.

I agree with @Liso, the methods list is quite long.
Especially when I write cumsom type inheriting some abstract type - the list is enormous.

There I see only apropos function that is probably equivalent to browser search.

Soo, how do I get methods by a type of input argument and probably a substring in method name, to shorten results?

None, I would use that myself – my overelaborate choices were just a quick attempt to include different techniques in a contrived example. I am revisiting the example.

I thought the advantage was to have a secret constructor that allows to elide the validation (e.g. for performance reasons).

1 Like

Nice one

For those using powershell on windows

simply append

function julia {$env:JULIA_PROJECT=pwd; C:\tools\Julia\julia-1.x\bin\julia.exe $args}

to Microsoft.Powershell_profile.ps1

although I think I prefer having separate shared environments for dev

1 Like

This is something very minor, but I used it again today so I thought I would mention: suppose I need to flip signs, eg maximize a function f that I have coded up using an API that is for finding minima (eg Optim.optimize).

In Julia, I can simply do

(-) ∘ f

which is so neat that I just like looking at it.

6 Likes

I always wonder why this isn’t a method of - . Does defining this break anything?

Base.:-(f::Function) = (-)∘f
1 Like

Probably no specific reason. That said, I would not include it in Base, since writing it out is barely longer and perhaps more transparent.

Hm. I think (-)∘f looks pretty cryptic, compared to -f. I think the latter would be particularly elegant in maps and so on.

Compare

maximum(x->-sin(x), r)
maximum((-)∘sin, r)
maximum(-sin, r)

For someone with a maths background, is quite familiar, but I doubt than any of my engineer colleagues know this symbol, and I’ve never seen it in any literature in my current field.

2 Likes

Then you get ambiguities about how to parse -sin(x), though. Or, at the very least it becomes difficult for people to read.