We use the Julia REPL quite a bit with custom data flows. When interactively toying around with them, we find the pipe operator extremely handy; especially combined with expressive Base.show() output, the sense of progression aids the learning, with minimal cursoring-and-bracketing-around.
Leaner/shorter variants than |>= might even be better, but |= and | are already taken. (Maybe this could even be tackled on a higher, not-just-pipe level, via some “rightward” assignment operator that would not have to adhere to some pipe nomenclature.)
I agree this would be nice (I really with R had this too). fwiw, Chain.jl has something kind of similar in the latest version (which doesn’t wrap in a let block)
julia> using Chain
julia> x = rand(10);
julia> @chain x begin
first
y = _
end
0.5028500583195015
julia> y
0.5028500583195015
This doesn’t solve the problem, though, since if you knew you wanted to assign a variable, you would have written it at the top.
Same response to @tbeason, sometimes you write an expression and then realize only later you want to assign it to a variable. Its a nice feature wither REPL
I don’t think that really makes much of a difference, you can return to the beginning of a long expression with 1 or 2 keystrokes (home key) and add the assignment if you want. It is more about a conceptual difference.
I concur with @pdeffebach that macros are not ideal here – when I started piping around, I of course forgot to start the line with the initial macro; I’d need the same procedure (up → home → write something).
(Of course the number of keystrokes is absurdly modest. But maybe it’s also psychological – at least my head does not want to go back to the beginning of the nice pipeline; it is now snugly entrenched at the end of it…)
I’m not sure about this. I only pipe across many lines, and left handed assignment is a lot clearer in that case. There’s no way I would confuse = and |>, but I might confuse |>= and |> at a glance and think result is the last called function. I get the use in the REPL, but we already can 1) click the home key to move to the start of the line, or 2) retrieve the value from global ans immediately after execution:
julia> 1:9 |> sum
45
julia> ans
45
julia> result = ans
45
julia> 1+1
2
julia> ans
2
julia> result
45
julia> ans
45
The following, at first sight, seems to achieve the desired “assignment-at-end-of-pipe.” I am very unsure if this does not break something else; any feedback really very welcome!
(The primary goal would be for this to work in the REPL; it would not necessarily need to have to work otherwise…)
The idea is to overwrite the function call operator for Symbol:
julia> x
ERROR: UndefVarError: x not defined
julia> function (newvarname::Symbol)(varvalue) eval(:($newvarname = $varvalue)) end
julia> 1 |> sin |> cos |> sin |> cos |> sin |> cos |> :x
0.7467069000243155
julia> x
0.7467069000243155
(I would activate it in my REPL modes for interactive usage only…)
Could there be some dangerous side-effect here in your opinion? Maybe I need to do better escaping/quoting…?
Interesting, though the use of eval feels like a code smell to me.
Alternatively, you could have a macro creating a function suitable for piping, i.e.,
macro rassign(symb)
:(x -> global $(esc(symb)) = x)
end
julia> 1 |> sin |> cos |> sin |> cos |> sin |> cos |> @rassign x
0.7467069000243155
julia> x
0.7467069000243155