RFC: Source-relative paths & expression-level "comments"

Hi, I am not certain this is the appropriate forum for this - or if I should just be making a PR. I’m not part of the Julia dev team (don’t know the procedure).

I realized it might be nice to have two small macros added to Julia’s library:

  • Something to “expand” source-relative paths.
  • Something to quickly disable a multi-line expression

Source-relative paths:

Mostly copied from @__DIR__:

macro srelpath(filepath)
	__source__.file === nothing &&
		return throw("Cannot find source-relative path")
	_dirname = dirname(String(__source__.file))
	_dirname = isempty(_dirname) ? pwd() : abspath(_dirname)
	return joinpath(_dirname, filepath)
end

This would allow one to more easily pass a source-relative (instead of cwd-relative) path to functions in other modules, for example:

data = readdlm(@srelpath("delim_file.txt"), '\t', Int, '\n')

It is basically just a shorthand (following other *path() functions) for the following:

data = readdlm(joinpath(@__DIR__, "delim_file.txt"), '\t', Int, '\n')

It is a small change, but I think it slightly improves readability.

Quick expression-level diable:

macro X(ex); return nothing; end

Very simple, but it would allow one to quicly disable multi-line expressions such as a function definition or large data declarations (alternative to #= [...] =#):

@X function MyFun()
	println("Running...")
end

@X b = Dict(
	:a => 54,
	:b => 7,
	:c => 11,
	:d => 22,
)

Again, it is only a small change from encasing with #= [...] =#, but I think it is (sufficiently) often easier to disable/enable an expression by prepending something instead of encasing it with #= [...] =#.

3 Likes

The procedure is documented, and you can make a PR without being part of the dev team (just fork), but there is no reason why this functionality couldn’t just live in a package.

1 Like

Thanks. I forgot about that page!

Agreed, it could just live in a package - I just don’t want to create a bunch of elemental packages, each for a single macro (as an example). And if I bundle them all in a poorly themed “MyUsefulAddons” packages, I will likely be its only user.

So I might have just ventured onto a pointless exercise here. Thanks for the pointer, though. I will try to remember the CONTRIBUTING.md page in the future!

reading the above made my mind go

Water, Earth, Fire, Air. Long ago, the four nations lived together in harmony. Then, everything changed when the Fire Nation attacked. Only the Avatar, master of all four elements, could stop them, but when the world needed him most, he vanished. A hundred years passed and …

I think you meant elementary.

2 Likes

:slight_smile:

Funny. Just made me realize I don’t really know the difference between “elemental” and “elementary”.
–>https://www.merriam-webster.com/dictionary/elemental
–>https://www.merriam-webster.com/dictionary/elementary

TLDR;

Apparently you are correct if I used elemental as a noun.

But as an adjective, it appears elemental is appropriate because it refers to a package that encapsulates a single element:

1 a : of, relating to, or being an element

OTOH, “elementary” seems like it refers to something being “basic” (in its simplest form):

1 a : of, relating to, or dealing with the simplest elements or principles of something

But I did like the quote nonetheless :slight_smile:. Very visual.

2 Likes

It is imprinted in the mind of many of my generation as it was played before every episode of “Avatar: the last airbender”.

But good to know that elemental may be used this way. English is not my first language, and “elemental” probably got in my vocabulary from D&D so I never questioned myself about other uses.

1 Like

I find some packages that implement one thing and do it well very useful, eg

@Tamas_Papp: And to a certain extent, I sort of agree. I myself implemented NumericIO (which is just to provide better control over writing out floating point values using more readable formatting (ex: 2×10² for 2e2 or 50μ for 5e-6):

I was also hesitant in publishing a over simple package at that time, but it ended up being a good idea. (Though I should revisit it - I have issues with the API, etc).

But am disliking the idea of having to start all of my “scripts” with a block like:

using Unpack
using ArgCheck
using SourceRelativePaths
using ExpressionDisable
using FieldDefaults
using Parameters
using Reexport
using NumericIO

#Finally, code starts here...

It might be ok, though

I suppose I could package those up in a personal “JuliaExtensions_MA” package to create my own version of “core julia”.

I’ll have to think about that. If I find it practical, then I might just agree with you @Tamas_Papp.

Lingering concerns

I suppose this creates an artificial little mental block for myself because macros like @X seem sort of obscure if they are not part of the language, so using it increases learning time for other developers - especially if everyone implements slightly different versions.

  • So I tend to avoid using modules like Parameters.jl or even Reexport.jl.
  • I assume people avoid using NumericIO.jl for similar reasons.

But I must admit, my reasoning is not necessarily a rational one.

1 Like